diff --git a/.ci/.drone.yml b/.ci/.drone.yml index ac75e5b6a2..4dab7ad31a 100644 --- a/.ci/.drone.yml +++ b/.ci/.drone.yml @@ -81,5 +81,5 @@ trigger: - refs/heads/main - refs/heads/develop - refs/heads/helics2 - - 'refs/pull/**' - - 'refs/tags/**' + - "refs/pull/**" + - "refs/tags/**" diff --git a/.ci/azure-pipelines-daily.yml b/.ci/azure-pipelines-daily.yml index bfd1993bfa..8ef8847545 100644 --- a/.ci/azure-pipelines-daily.yml +++ b/.ci/azure-pipelines-daily.yml @@ -1,7 +1,7 @@ trigger: none pr: none schedules: - - cron: '0 10 * * *' + - cron: "0 10 * * *" displayName: Daily late night PST (GMT-8) branches: include: @@ -12,14 +12,14 @@ jobs: strategy: matrix: all-tests: - containerImage: 'helics/buildenv:ubuntu20.04-default-builder' - test_config: 'daily' + containerImage: "helics/buildenv:ubuntu20.04-default-builder" + test_config: "daily" zmq-subproject: - containerImage: 'helics/buildenv:ubuntu20.04-default-builder' - test_config: 'ci' + containerImage: "helics/buildenv:ubuntu20.04-default-builder" + test_config: "ci" zmq_subproject: true pool: - vmImage: 'ubuntu-latest' + vmImage: "ubuntu-latest" container: $[ variables['containerImage'] ] timeoutInMinutes: 90 @@ -30,27 +30,27 @@ jobs: mkdir -p build && cd build ../scripts/ci-build.sh env: - MAKEFLAGS: '-j 4' - CMAKE_GENERATOR: 'Unix Makefiles' - USE_SWIG: 'true' + MAKEFLAGS: "-j 4" + CMAKE_GENERATOR: "Unix Makefiles" + USE_SWIG: "true" ZMQ_SUBPROJECT: $[variables['zmq_subproject']] ZMQ_FORCE_SUBPROJECT: $[variables['zmq_subproject']] - displayName: 'Build HELICS' + displayName: "Build HELICS" - bash: ../scripts/run-ci-tests.sh "$TEST_CONFIG" env: TEST_CONFIG: $[variables['test_config']] - workingDirectory: 'build' - displayName: 'Test HELICS' + workingDirectory: "build" + displayName: "Test HELICS" - job: Windows strategy: matrix: VS2022-64bit: - imageName: 'windows-2022' - langArch: 'x64' - vsArch: 'x64' - extraFlags: '' + imageName: "windows-2022" + langArch: "x64" + vsArch: "x64" + extraFlags: "" pool: vmImage: $(imageName) variables: @@ -89,7 +89,7 @@ jobs: - task: CMake@1 inputs: cmakeArgs: -A $(vsArch) -DHELICS_ENABLE_SWIG=ON -DHELICS_BUILD_CXX_SHARED_LIB=ON -DHELICS_ENABLE_PACKAGE_BUILD=ON -DHELICS_BUILD_TESTS=ON -DHELICS_BUILD_EXAMPLES=ON -DHELICS_DISABLE_VCPKG=ON $(extraFlags) .. - displayName: 'Configure HELICS' + displayName: "Configure HELICS" condition: eq( variables['Agent.OS'], 'Windows_NT' ) # - task: CMake@1 @@ -102,7 +102,7 @@ jobs: # Build HELICS # ----------------------- - bash: cmake --build . --config Release - displayName: 'Build HELICS' + displayName: "Build HELICS" workingDirectory: build # ----------------------- @@ -112,29 +112,29 @@ jobs: cpack_dir="$(which cmake)" cpack_dir="${cpack_dir%/cmake}" "${cpack_dir}/cpack" -G "ZIP" -C Release -B "$PWD/installer-output" - displayName: 'Package HELICS' + displayName: "Package HELICS" workingDirectory: build - task: CopyFiles@2 inputs: - sourceFolder: '$(Build.SourcesDirectory)/build/installer-output' - contents: '*.exe' - TargetFolder: '$(Build.ArtifactStagingDirectory)' + sourceFolder: "$(Build.SourcesDirectory)/build/installer-output" + contents: "*.exe" + TargetFolder: "$(Build.ArtifactStagingDirectory)" - task: PublishBuildArtifacts@1 inputs: - pathtoPublish: '$(Build.ArtifactStagingDirectory)' + pathtoPublish: "$(Build.ArtifactStagingDirectory)" artifactName: installer # ----------------------- # Test HELICS # ----------------------- - bash: ctest --output-on-failure --timeout 480 -C Release -L "Continuous" - displayName: 'Test HELICS' + displayName: "Test HELICS" workingDirectory: build # Packaging tests - bash: ctest --output-on-failure --timeout 200 -C Release -L "PackagingFast" - displayName: 'Test HELICS packaging' + displayName: "Test HELICS packaging" workingDirectory: build # For debugging, can get build folder contents by adding PublishBuildArtifacts task and set pathtoPublish: '$(Build.SourcesDirectory)/build' diff --git a/.ci/azure-pipelines.yml b/.ci/azure-pipelines.yml index e08357c185..53eda311aa 100644 --- a/.ci/azure-pipelines.yml +++ b/.ci/azure-pipelines.yml @@ -12,28 +12,28 @@ jobs: strategy: matrix: ubuntuDefault: - containerImage: 'helics/buildenv:ubuntu20.04-default-builder' - test_config: 'ci' - use_mpi: 'true' - encrypted: 'true' + containerImage: "helics/buildenv:ubuntu20.04-default-builder" + test_config: "ci" + use_mpi: "true" + encrypted: "true" gcc8: - containerImage: 'helics/buildenv:gcc8-builder' - test_config: 'ci' - use_mpi: 'true' - encrypted: 'true' + containerImage: "helics/buildenv:gcc8-builder" + test_config: "ci" + use_mpi: "true" + encrypted: "true" clang13: - containerImage: 'helics/buildenv:clang13-builder' - test_config: 'ci' - use_mpi: '' - encrypted: '' + containerImage: "helics/buildenv:clang13-builder" + test_config: "ci" + use_mpi: "" + encrypted: "" clang7: - containerImage: 'helics/buildenv:clang7-builder' - test_config: 'ci' - use_mpi: '' - encrypted: '' + containerImage: "helics/buildenv:clang7-builder" + test_config: "ci" + use_mpi: "" + encrypted: "" pool: - vmImage: 'ubuntu-latest' + vmImage: "ubuntu-latest" container: $[ variables['containerImage'] ] timeoutInMinutes: 60 @@ -44,31 +44,31 @@ jobs: mkdir -p build && cd build ../scripts/ci-build.sh env: - MAKEFLAGS: '-j 4' - CMAKE_GENERATOR: 'Unix Makefiles' - USE_SWIG: 'true' + MAKEFLAGS: "-j 4" + CMAKE_GENERATOR: "Unix Makefiles" + USE_SWIG: "true" USE_MPI: $[variables['use_mpi']] ENCRYPTED: $[variables['encrypted']] ZMQ_SUBPROJECT: $[variables['zmq_subproject']] ZMQ_FORCE_SUBPROJECT: $[variables['zmq_subproject']] - displayName: 'Build HELICS' + displayName: "Build HELICS" - bash: ../scripts/run-ci-tests.sh "$TEST_CONFIG" env: TEST_CONFIG: $[variables['test_config']] - workingDirectory: 'build' - displayName: 'Test HELICS' + workingDirectory: "build" + displayName: "Test HELICS" - job: macOS strategy: matrix: XCode-latest: - test_config: 'ci' - vmImage: 'macOS-12' + test_config: "ci" + vmImage: "macOS-13" XCode-oldest: - test_config: 'ci' - vmImage: 'macOS-11' - xcode_path: '/Applications/Xcode_11.7.app' + test_config: "ci" + vmImage: "macOS-12" + xcode_path: "/Applications/Xcode_13.2.1.app" pool: vmImage: $[ variables['vmImage'] ] timeoutInMinutes: 60 @@ -77,46 +77,46 @@ jobs: - bash: sudo xcode-select --switch "${XCODE_PATH}/Contents/Developer" env: XCODE_PATH: $[variables['xcode_path']] - displayName: 'Set XCode Path' + displayName: "Set XCode Path" condition: ne(variables['xcode_path'],'') - bash: | brew install swig zeromq boost - displayName: 'Install dependencies' + displayName: "Install dependencies" - bash: | unset VCPKG_ROOT source scripts/setup-helics-ci-options.sh mkdir -p build && cd build ../scripts/ci-build.sh env: - MAKEFLAGS: '-j 4' - CMAKE_GENERATOR: 'Unix Makefiles' - USE_SWIG: 'true' - displayName: 'Build HELICS' + MAKEFLAGS: "-j 4" + CMAKE_GENERATOR: "Unix Makefiles" + USE_SWIG: "true" + displayName: "Build HELICS" - bash: ../scripts/run-ci-tests.sh "$TEST_CONFIG" env: TEST_CONFIG: $[variables['test_config']] - workingDirectory: 'build' - displayName: 'Test HELICS' + workingDirectory: "build" + displayName: "Test HELICS" - job: Windows strategy: matrix: VS2019-32bit: - imageName: 'windows-2019' - langArch: 'x86' - vsArch: 'Win32' - extraFlags: '-DHELICS_DISABLE_WEBSERVER=ON' + imageName: "windows-2019" + langArch: "x86" + vsArch: "Win32" + extraFlags: "-DHELICS_DISABLE_WEBSERVER=ON" VS2019-64bit: - imageName: 'windows-2019' - langArch: 'x64' - vsArch: 'x64' - extraFlags: '' + imageName: "windows-2019" + langArch: "x64" + vsArch: "x64" + extraFlags: "" VS2022-64bit: - imageName: 'windows-2022' - langArch: 'x64' - vsArch: 'x64' - extraFlags: '-DCMAKE_CXX_STANDARD=20' + imageName: "windows-2022" + langArch: "x64" + vsArch: "x64" + extraFlags: "-DCMAKE_CXX_STANDARD=20" pool: vmImage: $(imageName) @@ -157,7 +157,7 @@ jobs: - task: CMake@1 inputs: cmakeArgs: -A $(vsArch) -DHELICS_ENABLE_SWIG=ON -DHELICS_BUILD_CXX_SHARED_LIB=ON -DHELICS_ENABLE_PACKAGE_BUILD=ON -DHELICS_BUILD_TESTS=ON -DHELICS_BUILD_EXAMPLES=ON -DHELICS_DISABLE_VCPKG=ON $(extraFlags) .. - displayName: 'Configure HELICS' + displayName: "Configure HELICS" condition: eq( variables['Agent.OS'], 'Windows_NT' ) # - task: CMake@1 @@ -170,7 +170,7 @@ jobs: # Build HELICS # ----------------------- - bash: cmake --build . --config Release - displayName: 'Build HELICS' + displayName: "Build HELICS" workingDirectory: build # ----------------------- @@ -180,30 +180,30 @@ jobs: cpack_dir="$(which cmake)" cpack_dir="${cpack_dir%/cmake}" "${cpack_dir}/cpack" -G "NSIS" -C Release -B "$PWD/installer-output" - displayName: 'Package HELICS' + displayName: "Package HELICS" workingDirectory: build - task: CopyFiles@2 inputs: - sourceFolder: '$(Build.SourcesDirectory)/build/installer-output' - contents: '*.exe' - TargetFolder: '$(Build.ArtifactStagingDirectory)' + sourceFolder: "$(Build.SourcesDirectory)/build/installer-output" + contents: "*.exe" + TargetFolder: "$(Build.ArtifactStagingDirectory)" - task: PublishBuildArtifacts@1 inputs: - pathtoPublish: '$(Build.ArtifactStagingDirectory)' + pathtoPublish: "$(Build.ArtifactStagingDirectory)" artifactName: installer # ----------------------- # Test HELICS # ----------------------- - bash: ctest --output-on-failure --timeout 440 -C Release -L "Continuous" - displayName: 'Test HELICS' + displayName: "Test HELICS" workingDirectory: build # Packaging tests - bash: ctest --output-on-failure --timeout 200 -C Release -L "PackagingFast" - displayName: 'Test HELICS packaging' + displayName: "Test HELICS packaging" workingDirectory: build # For debugging, can get build folder contents by adding PublishBuildArtifacts task and set pathtoPublish: '$(Build.SourcesDirectory)/build' diff --git a/.circleci/config.yml b/.circleci/config.yml index ef2e216def..dd9c3a9799 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -68,8 +68,8 @@ jobs: docker: - image: helics/buildenv:octave environment: - OCTAVETEST: '/root/project/tests/octave' - CMAKE_FLAGS: '-DHELICS_BUILD_OCTAVE_INTERFACE=ON -DHELICS_BUILD_TESTS=ON' + OCTAVETEST: "/root/project/tests/octave" + CMAKE_FLAGS: "-DHELICS_BUILD_OCTAVE_INTERFACE=ON -DHELICS_BUILD_TESTS=ON" steps: - checkout - run: *setup_helics @@ -77,10 +77,10 @@ jobs: helicsgccTSan: docker: - - image: helics/buildenv:gcc12-builder + - image: helics/buildenv:gcc13-builder environment: - CMAKE_FLAGS: '-DCMAKE_CXX_FLAGS="-fsanitize=thread -g -O1 " -DHELICS_BUILD_TESTS=ON -DHELICS_ZMQ_SUBPROJECT=ON -DHELICS_ZMQ_FORCE_SUBPROJECT=ON -DHELICS_DISABLE_SYSTEM_CALL_TESTS=ON' - TSAN_OPTIONS: 'second_deadlock_stack=1 suppressions=/root/project/.circleci/tsan_suppression.txt history_size=4' + CMAKE_FLAGS: '-DCMAKE_CXX_FLAGS="-fsanitize=thread -g -O1 " -DHELICS_BUILD_TESTS=ON -DHELICS_ZMQ_SUBPROJECT=ON -DHELICS_ZMQ_FORCE_SUBPROJECT=ON -DHELICS_DISABLE_SYSTEM_CALL_TESTS=ON -DCMAKE_CXX_STANDARD=20' + TSAN_OPTIONS: "second_deadlock_stack=1 suppressions=/root/project/.circleci/tsan_suppression.txt history_size=4" steps: - checkout @@ -89,11 +89,11 @@ jobs: helicsgccASan: docker: - - image: helics/buildenv:gcc12-builder + - image: helics/buildenv:gcc13-builder environment: - CMAKE_FLAGS: '-DCMAKE_CXX_FLAGS="-ggdb -fsanitize=address -fno-omit-frame-pointer -static-libstdc++ -static-libasan -lrt -g -O1 " -DHELICS_BUILD_TESTS=ON -DHELICS_ZMQ_SUBPROJECT=ON -DHELICS_ZMQ_FORCE_SUBPROJECT=ON -DHELICS_DISABLE_SYSTEM_CALL_TESTS=ON' - ASAN_OPTIONS: 'alloc_dealloc_mismatch=0' - LSAN_OPTIONS: 'suppressions=/root/project/.circleci/leak_suppression_gcc.txt' + CMAKE_FLAGS: '-DCMAKE_CXX_FLAGS="-ggdb -fsanitize=address -fno-omit-frame-pointer -static-libstdc++ -static-libasan -lrt -g -O1 " -DHELICS_BUILD_TESTS=ON -DHELICS_ZMQ_SUBPROJECT=ON -DHELICS_ZMQ_FORCE_SUBPROJECT=ON -DHELICS_DISABLE_SYSTEM_CALL_TESTS=ON -DCMAKE_CXX_STANDARD=20' + ASAN_OPTIONS: "alloc_dealloc_mismatch=0" + LSAN_OPTIONS: "suppressions=/root/project/.circleci/leak_suppression_gcc.txt" steps: - checkout - run: *setup_helics @@ -104,9 +104,9 @@ jobs: - image: helics/buildenv:sanitizers-14 environment: CMAKE_FLAGS: '-DCMAKE_CXX_COMPILER=clang++ -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_FLAGS="-fsanitize=undefined,address -lc++ -lc++abi -fsanitize-address-use-after-scope -fsanitize-ignorelist=/root/project/.circleci/asan_suppression.txt -Wno-unused-command-line-argument -fno-omit-frame-pointer -g -O1 -fsanitize-blacklist=/root/project/.circleci/asan_blacklist.txt" -DHELICS_BUILD_TESTS=ON -DHELICS_ZMQ_SUBPROJECT=ON -DHELICS_ZMQ_FORCE_SUBPROJECT=ON' - LSAN_OPTIONS: 'suppressions=/root/project/.circleci/leak_suppression.txt' - UBSAN_OPTIONS: 'print_stacktrace=1 suppressions=/root/project/.circleci/ubsan_suppression.txt' - ASAN_OPTIONS: 'alloc_dealloc_mismatch=0' + LSAN_OPTIONS: "suppressions=/root/project/.circleci/leak_suppression.txt" + UBSAN_OPTIONS: "print_stacktrace=1 suppressions=/root/project/.circleci/ubsan_suppression.txt" + ASAN_OPTIONS: "alloc_dealloc_mismatch=0" steps: - checkout - run: *setup_helics @@ -128,7 +128,7 @@ jobs: - image: helics/buildenv:sanitizers-14 environment: CMAKE_FLAGS: '-DCMAKE_CXX_COMPILER=clang++ -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_FLAGS="-fsanitize=thread -nostdinc++ -nostdlib++ -L/root/develop/libcxx_tsan/lib -lc++ -lc++abi -I/root/develop/libcxx_tsan/include -I/root/develop/libcxx_tsan/include/c++/v1 -Wno-unused-command-line-argument -fno-omit-frame-pointer -g -O2 -Wl,-rpath,/root/develop/libcxx_tsan/lib" -DHELICS_BUILD_TESTS=ON -DHELICS_ZMQ_SUBPROJECT=ON -DHELICS_ZMQ_FORCE_SUBPROJECT=ON' - TSAN_OPTIONS: 'suppressions=/root/project/.circleci/tsan_suppression.txt' + TSAN_OPTIONS: "suppressions=/root/project/.circleci/tsan_suppression.txt" steps: - checkout - run: *setup_helics @@ -138,7 +138,7 @@ jobs: docker: - image: helics/buildenv:builder environment: - CMAKE_FLAGS: '-DHELICS_BUILD_CXX_SHARED_LIB=ON -DHELICS_BUILD_TESTS=ON -DHELICS_BUILD_BENCHMARKS=ON -DHELICS_INSTALL_PACKAGE_TESTS=ON' + CMAKE_FLAGS: "-DHELICS_BUILD_CXX_SHARED_LIB=ON -DHELICS_BUILD_TESTS=ON -DHELICS_BUILD_BENCHMARKS=ON -DHELICS_INSTALL_PACKAGE_TESTS=ON" steps: - checkout - run: *setup_helics @@ -148,7 +148,7 @@ jobs: docker: - image: helics/buildenv:gcc10-builder environment: - CMAKE_FLAGS: '-DHELICS_BUILD_CXX_SHARED_LIB=ON -DHELICS_ENABLE_ZMQ_CORE=OFF -DHELICS_ENABLE_IPC_CORE=OFF -DHELICS_BUILD_TESTS=ON -DCMAKE_CXX_STANDARD=17' + CMAKE_FLAGS: "-DHELICS_BUILD_CXX_SHARED_LIB=ON -DHELICS_ENABLE_ZMQ_CORE=OFF -DHELICS_ENABLE_IPC_CORE=OFF -DHELICS_BUILD_TESTS=ON -DCMAKE_CXX_STANDARD=17" steps: - checkout - run: *setup_helics @@ -158,7 +158,7 @@ jobs: docker: - image: helics/buildenv:tumbleweed-builder environment: - CMAKE_FLAGS: '-DHELICS_BUILD_CXX_SHARED_LIB=ON -DHELICS_ENABLE_ZMQ_CORE=OFF -DHELICS_ENABLE_IPC_CORE=OFF -DHELICS_ENABLE_UDP_CORE=OFF -DHELICS_BUILD_TESTS=ON -DCMAKE_CXX_STANDARD=20' + CMAKE_FLAGS: "-DHELICS_BUILD_CXX_SHARED_LIB=ON -DHELICS_ENABLE_ZMQ_CORE=OFF -DHELICS_ENABLE_IPC_CORE=OFF -DHELICS_ENABLE_UDP_CORE=OFF -DHELICS_BUILD_TESTS=ON -DCMAKE_CXX_STANDARD=20" steps: - checkout - run: *setup_helics @@ -167,17 +167,17 @@ jobs: docker: - image: helics/buildenv:builder environment: - CMAKE_FLAGS: '-DHELICS_BUILD_TESTS=ON -DHELICS_INSTALL_PACKAGE_TESTS=ON' + CMAKE_FLAGS: "-DHELICS_BUILD_TESTS=ON -DHELICS_INSTALL_PACKAGE_TESTS=ON" steps: - checkout - run: *setup_helics - run: *run_installer_tests - gcc12: + gcc13: docker: - - image: helics/buildenv:gcc12-builder + - image: helics/buildenv:gcc13-builder environment: - CMAKE_FLAGS: '-DHELICS_EXTRA_COMPILE_FLAGS=-Wredundant-tags -DHELICS_BUILD_CXX_SHARED_LIB=ON -DHELICS_BUILD_TESTS=ON' + CMAKE_FLAGS: '-DHELICS_EXTRA_COMPILE_FLAGS=-Wredundant-tags -DCMAKE_CXX_FLAGS="-pedantic-errors" -DHELICS_BUILD_CXX_SHARED_LIB=ON -DHELICS_BUILD_TESTS=ON -DCMAKE_CXX_STANDARD=20' steps: - checkout - run: *setup_helics @@ -187,7 +187,7 @@ jobs: docker: - image: helics/buildenv:clang14-builder environment: - CMAKE_FLAGS: '-DHELICS_BUILD_CXX_SHARED_LIB=ON -DHELICS_BUILD_TESTS=ON -DCMAKE_CXX_STANDARD=20' + CMAKE_FLAGS: '-DCMAKE_CXX_FLAGS="-pedantic-errors" -DHELICS_BUILD_CXX_SHARED_LIB=ON -DHELICS_BUILD_TESTS=ON -DCMAKE_CXX_STANDARD=20' steps: - checkout - run: *setup_helics @@ -197,7 +197,7 @@ jobs: docker: - image: helics/buildenv:clang14-builder environment: - CMAKE_FLAGS: '-DHELICS_BUILD_CXX_SHARED_LIB=ON -DHELICS_BUILD_TESTS=ON -DHELICS_BUILD_EXAMPLES=ON -DCMAKE_CXX_STANDARD=23' + CMAKE_FLAGS: "-DHELICS_BUILD_CXX_SHARED_LIB=ON -DHELICS_BUILD_TESTS=ON -DHELICS_BUILD_EXAMPLES=ON -DCMAKE_CXX_STANDARD=23" steps: - checkout - run: *setup_helics @@ -206,7 +206,7 @@ jobs: docker: - image: helics/buildenv:builder environment: - CMAKE_FLAGS: '-DHELICS_BUILD_BENCHMARKS=ON -DBM_RESULT_DIR=/tmp/bm_results/ -DHELICS_DISABLE_C_SHARED_LIB=ON' + CMAKE_FLAGS: "-DHELICS_BUILD_BENCHMARKS=ON -DBM_RESULT_DIR=/tmp/bm_results/ -DHELICS_DISABLE_C_SHARED_LIB=ON" steps: - checkout - run: *setup_helics @@ -220,7 +220,7 @@ jobs: image: ubuntu-2004:current resource_class: arm.medium environment: - CMAKE_FLAGS: '-DHELICS_BUILD_CXX_SHARED_LIB=OFF -DHELICS_BUILD_TESTS=ON -DHELICS_ZMQ_SUBPROJECT=ON -DHELICS_ZMQ_FORCE_SUBPROJECT=ON -DHELICS_DISABLE_BOOST=ON' + CMAKE_FLAGS: "-DHELICS_BUILD_CXX_SHARED_LIB=OFF -DHELICS_BUILD_TESTS=ON -DHELICS_ZMQ_SUBPROJECT=ON -DHELICS_ZMQ_FORCE_SUBPROJECT=ON -DHELICS_DISABLE_BOOST=ON" steps: - checkout - run: *setup_helics @@ -241,7 +241,7 @@ workflows: filters: branches: ignore: /pre-commit\/.*/ - - gcc12: + - gcc13: filters: branches: ignore: /pre-commit\/.*/ @@ -300,7 +300,7 @@ workflows: nightly: triggers: - schedule: - cron: '0 8 * * *' + cron: "0 8 * * *" filters: branches: only: @@ -318,7 +318,7 @@ workflows: benchmark: triggers: - schedule: - cron: '17 9 * * 0,2,5' + cron: "17 9 * * 0,2,5" filters: branches: only: diff --git a/.circleci/config_old.yml b/.circleci/config_old.yml index 5872bc4d81..9fd0734da8 100644 --- a/.circleci/config_old.yml +++ b/.circleci/config_old.yml @@ -52,8 +52,8 @@ jobs: docker: - image: helics/buildenv:octave environment: - OCTAVETEST: '/root/project/tests/octave' - CMAKE_FLAGS: '-DHELICS_BUILD_OCTAVE_INTERFACE=ON -DHELICS_BUILD_TESTS=ON' + OCTAVETEST: "/root/project/tests/octave" + CMAKE_FLAGS: "-DHELICS_BUILD_OCTAVE_INTERFACE=ON -DHELICS_BUILD_TESTS=ON" steps: - checkout - run: *setup_helics @@ -64,7 +64,7 @@ jobs: - image: helics/buildenv:gcc12-builder environment: CMAKE_FLAGS: '-DCMAKE_CXX_FLAGS="-fsanitize=thread -g -O1 " -DHELICS_BUILD_TESTS=ON -DHELICS_ZMQ_SUBPROJECT=ON -DHELICS_ZMQ_FORCE_SUBPROJECT=ON -DHELICS_DISABLE_SYSTEM_CALL_TESTS=ON' - TSAN_OPTIONS: 'second_deadlock_stack=1 suppressions=/root/project/.circleci/tsan_suppression.txt history_size=4' + TSAN_OPTIONS: "second_deadlock_stack=1 suppressions=/root/project/.circleci/tsan_suppression.txt history_size=4" steps: - checkout @@ -87,8 +87,8 @@ jobs: - image: helics/buildenv:sanitizers-14 environment: CMAKE_FLAGS: '-DCMAKE_CXX_COMPILER=clang++ -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_FLAGS="-fsanitize=undefined,address -fsanitize-address-use-after-scope -fsanitize-ignorelist=/root/project/.circleci/asan_suppression.txt -nostdinc++ -nostdlib++ -L/root/develop/libcxx_asan/lib -lc++ -lc++abi -isystem /root/develop/libcxx_asan/include/c++/v1 -Wno-unused-command-line-argument -fno-omit-frame-pointer -g -O1 -Wl,-rpath,/root/develop/libcxx_asan/lib -fsanitize-blacklist=/root/project/.circleci/asan_blacklist.txt" -DHELICS_BUILD_TESTS=ON -DHELICS_ZMQ_SUBPROJECT=ON -DHELICS_ZMQ_FORCE_SUBPROJECT=ON' - LSAN_OPTIONS: 'suppressions=/root/project/.circleci/leak_suppression.txt' - UBSAN_OPTIONS: 'print_stacktrace=1 suppressions=/root/project/.circleci/ubsan_suppression.txt' + LSAN_OPTIONS: "suppressions=/root/project/.circleci/leak_suppression.txt" + UBSAN_OPTIONS: "print_stacktrace=1 suppressions=/root/project/.circleci/ubsan_suppression.txt" steps: - checkout - run: *setup_helics @@ -109,7 +109,7 @@ jobs: docker: - image: helics/buildenv:builder environment: - CMAKE_FLAGS: '-DHELICS_BUILD_CXX_SHARED_LIB=ON -DHELICS_BUILD_TESTS=ON -DHELICS_BUILD_BENCHMARKS=ON -DHELICS_INSTALL_PACKAGE_TESTS=ON' + CMAKE_FLAGS: "-DHELICS_BUILD_CXX_SHARED_LIB=ON -DHELICS_BUILD_TESTS=ON -DHELICS_BUILD_BENCHMARKS=ON -DHELICS_INSTALL_PACKAGE_TESTS=ON" steps: - checkout - run: *setup_helics @@ -119,7 +119,7 @@ jobs: docker: - image: helics/buildenv:gcc8-builder environment: - CMAKE_FLAGS: '-DHELICS_BUILD_CXX_SHARED_LIB=ON -DHELICS_ENABLE_ZMQ_CORE=OFF -DHELICS_ENABLE_IPC_CORE=OFF -DHELICS_BUILD_TESTS=ON -DCMAKE_CXX_STANDARD=17' + CMAKE_FLAGS: "-DHELICS_BUILD_CXX_SHARED_LIB=ON -DHELICS_ENABLE_ZMQ_CORE=OFF -DHELICS_ENABLE_IPC_CORE=OFF -DHELICS_BUILD_TESTS=ON -DCMAKE_CXX_STANDARD=17" steps: - checkout - run: *setup_helics @@ -129,7 +129,7 @@ jobs: docker: - image: helics/buildenv:tumbleweed-builder environment: - CMAKE_FLAGS: '-DHELICS_BUILD_CXX_SHARED_LIB=ON -DHELICS_ENABLE_ZMQ_CORE=OFF -DHELICS_ENABLE_IPC_CORE=OFF -DHELICS_ENABLE_UDP_CORE=OFF -DHELICS_BUILD_TESTS=ON -DCMAKE_CXX_STANDARD=17' + CMAKE_FLAGS: "-DHELICS_BUILD_CXX_SHARED_LIB=ON -DHELICS_ENABLE_ZMQ_CORE=OFF -DHELICS_ENABLE_IPC_CORE=OFF -DHELICS_ENABLE_UDP_CORE=OFF -DHELICS_BUILD_TESTS=ON -DCMAKE_CXX_STANDARD=17" steps: - checkout - run: *setup_helics @@ -138,7 +138,7 @@ jobs: docker: - image: helics/buildenv:builder environment: - CMAKE_FLAGS: '-DHELICS_BUILD_TESTS=ON -DHELICS_INSTALL_PACKAGE_TESTS=ON' + CMAKE_FLAGS: "-DHELICS_BUILD_TESTS=ON -DHELICS_INSTALL_PACKAGE_TESTS=ON" steps: - checkout - run: *setup_helics @@ -148,7 +148,7 @@ jobs: docker: - image: helics/buildenv:gcc12-builder environment: - CMAKE_FLAGS: '-DHELICS_EXTRA_COMPILE_FLAGS=-Wredundant-tags' + CMAKE_FLAGS: "-DHELICS_EXTRA_COMPILE_FLAGS=-Wredundant-tags" steps: - checkout - run: *setup_helics @@ -157,7 +157,7 @@ jobs: docker: - image: helics/buildenv:builder environment: - CMAKE_FLAGS: '-DHELICS_BUILD_BENCHMARKS=ON -DBM_RESULT_DIR=/tmp/bm_results/ -DHELICS_DISABLE_C_SHARED_LIB=ON' + CMAKE_FLAGS: "-DHELICS_BUILD_BENCHMARKS=ON -DBM_RESULT_DIR=/tmp/bm_results/ -DHELICS_DISABLE_C_SHARED_LIB=ON" steps: - checkout - run: *setup_helics @@ -202,7 +202,7 @@ workflows: nightly: triggers: - schedule: - cron: '0 8 * * *' + cron: "0 8 * * *" filters: branches: only: @@ -214,7 +214,7 @@ workflows: benchmark: triggers: - schedule: - cron: '17 9 * * 0,2,5' + cron: "17 9 * * 0,2,5" filters: branches: only: diff --git a/.circleci/tsan_suppression.txt b/.circleci/tsan_suppression.txt index 01e74af092..af982f39f9 100644 --- a/.circleci/tsan_suppression.txt +++ b/.circleci/tsan_suppression.txt @@ -1,6 +1,10 @@ # This is a known purposeful leak and possible resulting race condition detection on closing of shared libraries - # potential race condition from race:cxa_at_exit_wrapper race:zmq::session_base_t race:zmq::pipe_t + +mutex:DelayedDestructor::destroyObjects + +# false positive https://github.com/google/sanitizers/issues/1620 +mutex:timed_mutex::unlock diff --git a/.cirrus.yml b/.cirrus.yml index e053f9e7a9..ba1d4682db 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -1,5 +1,5 @@ freebsd_instance: - image_family: freebsd-12-2 + image_family: freebsd-14-0 task: skip: $CIRRUS_BRANCH == 'pre-commit/.*' diff --git a/.clang-tidy b/.clang-tidy index 7bfaa35323..2543eeec4c 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -24,8 +24,10 @@ Checks: " clang-analyzer-*, bugprone-*, -bugprone-narrowing-conversions, + -bugprone-easily-swappable-parameters, misc-*, -misc-non-private-member-variables-in-classes, + -misc-no-recursion, cert-*, -cert-err58-cpp, portability-*, @@ -60,14 +62,18 @@ WarningsAsErrors: " -clang-analyzer-optin.cplusplus.VirtualCall, bugprone-*, -bugprone-narrowing-conversions, + -bugprone-easily-swappable-parameters, + -bugprone-exception-escape, misc-*, -misc-non-private-member-variables-in-classes, + -misc-no-recursion, cert-*, -cert-err58-cpp, portability-*, readability-*, -readability-magic-numbers, -readability-identifier-naming, + -readability-identifier-length, performance-* -performance-unnecessary-value-param " @@ -315,7 +321,7 @@ CheckOptions: - key: readability-identifier-naming.MethodSuffix value: "" - key: readability-identifier-naming.NamespaceCase - value: lowercase + value: lower_case - key: readability-identifier-naming.NamespacePrefix value: "" - key: readability-identifier-naming.NamespaceSuffix @@ -434,6 +440,8 @@ CheckOptions: value: "" - key: readability-identifier-naming.VirtualMethodSuffix value: "" + - key: readability-function-cognitive-complexity.Threshold + value: 100 - key: readability-simplify-boolean-expr.ChainedConditionalAssignment value: "0" - key: readability-simplify-boolean-expr.ChainedConditionalReturn diff --git a/.github/actions/linux-release-builder/action.yml b/.github/actions/linux-release-builder/action.yml index 6c9978e96c..21a1f18b32 100644 --- a/.github/actions/linux-release-builder/action.yml +++ b/.github/actions/linux-release-builder/action.yml @@ -1,13 +1,13 @@ -name: 'Linux Release Builder' -description: 'Runs a build using a container image with an old glibc to get a binary that works on more Linux systems' +name: "Linux Release Builder" +description: "Runs a build using a container image with an old glibc to get a binary that works on more Linux systems" inputs: script: - description: 'Bash script to run in the container' + description: "Bash script to run in the container" required: true cpack_gen: - description: 'CPack Generator(s) to use' + description: "CPack Generator(s) to use" required: false - default: 'TGZ' + default: "TGZ" runs: - using: 'docker' - image: 'Dockerfile' + using: "docker" + image: "Dockerfile" diff --git a/.github/actions/run-clang-tidy-pr.sh b/.github/actions/run-clang-tidy-pr.sh index 83adef298c..bcd6b31a53 100755 --- a/.github/actions/run-clang-tidy-pr.sh +++ b/.github/actions/run-clang-tidy-pr.sh @@ -14,7 +14,7 @@ if ((filecount > 0 && filecount <= 20)); then echo "====Run clang-tidy====" while read -r line; do if echo "$line" | grep -E '\.(cpp|hpp|c|h)$'; then - python3 /usr/share/clang/run-clang-tidy.py "$line" -p build -quiet + /usr/bin/run-clang-tidy "$line" -p build -quiet rc=$? echo "clang-tidy exit code: $rc" if [[ "$rc" != "0" ]]; then diff --git a/.github/dependabot.yml b/.github/dependabot.yml index c7cfe907a7..ee7422bacd 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,8 +1,8 @@ version: 2 updates: - - package-ecosystem: 'github-actions' - directory: '/' + - package-ecosystem: "github-actions" + directory: "/" schedule: - interval: 'weekly' - target-branch: 'develop' + interval: "weekly" + target-branch: "develop" open-pull-requests-limit: 10 diff --git a/.github/workflows/benchmark-package.yml b/.github/workflows/benchmark-package.yml index 513eb70433..1ebd9c3767 100644 --- a/.github/workflows/benchmark-package.yml +++ b/.github/workflows/benchmark-package.yml @@ -38,11 +38,11 @@ jobs: steps: - name: Checkout event ref - uses: actions/checkout@v2 + uses: actions/checkout@v4 if: github.event_name != 'schedule' - name: Checkout develop branch - uses: actions/checkout@v2 + uses: actions/checkout@v4 with: ref: develop if: github.event_name == 'schedule' @@ -75,9 +75,9 @@ jobs: # GitHub Actions combines artifacts uploaded with the same name - name: Upload artifact - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v4 with: - name: ${{ runner.os }}-benchmarks + name: ${{ matrix.id }}-benchmarks path: artifact diff --git a/.github/workflows/compress-images.yml b/.github/workflows/compress-images.yml index e086963a6f..c66cc76fc8 100644 --- a/.github/workflows/compress-images.yml +++ b/.github/workflows/compress-images.yml @@ -23,7 +23,7 @@ jobs: name: calibreapp/image-actions runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Compress Images id: calibre uses: calibreapp/image-actions@main diff --git a/.github/workflows/create-release-checklist.yml b/.github/workflows/create-release-checklist.yml index 1f5eaf2477..13e3673805 100644 --- a/.github/workflows/create-release-checklist.yml +++ b/.github/workflows/create-release-checklist.yml @@ -23,7 +23,7 @@ jobs: steps: # Needed to get the checklist template - name: Checkout release checklist template - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Create issue env: GH_TOKEN: ${{ github.token }} diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 0a4aa9df11..1727cadfdc 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -36,10 +36,10 @@ jobs: packages: write steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Docker meta data id: meta - uses: docker/metadata-action@v4 + uses: docker/metadata-action@v5 with: images: | helics/helics @@ -56,13 +56,13 @@ jobs: type=semver,pattern={{version}} - name: Login to Docker Hub if: github.event_name != 'workflow_dispatch' || !github.event.inputs.build_only - uses: docker/login-action@v2 + uses: docker/login-action@v3 with: username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_PASSWORD }} - name: Login to GitHub Container Registry if: github.event_name != 'workflow_dispatch' || !github.event.inputs.build_only - uses: docker/login-action@v2 + uses: docker/login-action@v3 with: registry: ghcr.io username: ${{ github.actor }} diff --git a/.github/workflows/msys2.yml b/.github/workflows/msys2.yml index c8d64e1f86..dbaff62454 100644 --- a/.github/workflows/msys2.yml +++ b/.github/workflows/msys2.yml @@ -42,13 +42,13 @@ jobs: mingw-w64-${{matrix.env}}-zeromq mingw-w64-${{matrix.env}}-boost - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: submodules: true if: github.event_name != 'schedule' - name: Checkout develop branch - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: submodules: true ref: develop @@ -59,6 +59,7 @@ jobs: CMAKE_GENERATOR: ${{matrix.gen}} DISABLE_INTERFACES: "Java" DISABLE_EXAMPLES: "true" + CXX_STANDARD: 20 #ZMQ_SUBPROJECT: "true" #ZMQ_FORCE_SUBPROJECT: "true" run: | diff --git a/.github/workflows/release-build.yml b/.github/workflows/release-build.yml index e8131df872..429f927389 100644 --- a/.github/workflows/release-build.yml +++ b/.github/workflows/release-build.yml @@ -5,9 +5,16 @@ on: workflow_dispatch: inputs: packages: - description: 'List of packages to build (everything, archive, msvc, installer, sharedlib)' + description: 'List of packages to build' required: true default: 'everything' + type: choice + options: + - everything + - archive + - msvc + - installer + - sharedlib commit: description: 'Commit-ish (tag, branchname, sha) for code to build (uses scripts from the same branch as the workflow)' default: '' @@ -31,10 +38,10 @@ jobs: run: | unset DEPTH if [ -n '${{ github.event.inputs.commit }}' ]; then DEPTH='0'; else DEPTH='1'; fi - echo "::set-output name=DEPTH::${DEPTH}" + echo "DEPTH=${DEPTH}" >> $GITHUB_OUTPUT - name: Checkout code - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: fetch-depth: ${{ steps.determine_fd.outputs.DEPTH }} if: github.event.action == 'published' || github.event_name == 'workflow_dispatch' @@ -65,7 +72,7 @@ jobs: run: ./.github/actions/upload-release-asset.sh "artifact/Helics-$(git rev-parse --abbrev-ref "${GITHUB_REF}")-source.tar.gz" - name: Upload artifact - uses: actions/upload-artifact@v1 + uses: actions/upload-artifact@v4 with: name: all-submodules-archive path: artifact @@ -94,16 +101,16 @@ jobs: run: | unset DEPTH if [ -n '${{ github.event.inputs.commit }}' ]; then DEPTH='0'; else DEPTH='1'; fi - echo "::set-output name=DEPTH::${DEPTH}" + echo "DEPTH=${DEPTH}" >> $GITHUB_OUTPUT - name: Checkout code - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: fetch-depth: ${{ steps.determine_fd.outputs.DEPTH }} if: github.event_name != 'schedule' - name: Checkout develop branch - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: ref: develop if: github.event_name == 'schedule' @@ -136,9 +143,9 @@ jobs: # GitHub Actions combines artifacts uploaded with the same name - name: Upload artifact - uses: actions/upload-artifact@v1 + uses: actions/upload-artifact@v4 with: - name: ${{ runner.os }}-installers + name: ${{ matrix.os }}-msvc-installers path: artifact ##################################### @@ -181,16 +188,16 @@ jobs: run: | unset DEPTH if [ -n '${{ github.event.inputs.commit }}' ]; then DEPTH='0'; else DEPTH='1'; fi - echo "::set-output name=DEPTH::${DEPTH}" + echo "DEPTH=${DEPTH}" >> $GITHUB_OUTPUT - name: Checkout code - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: fetch-depth: ${{ steps.determine_fd.outputs.DEPTH }} if: github.event_name != 'schedule' - name: Checkout develop branch - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: ref: develop if: github.event_name == 'schedule' @@ -239,9 +246,9 @@ jobs: # GitHub Actions combines artifacts uploaded with the same name - name: Upload artifact - uses: actions/upload-artifact@v1 + uses: actions/upload-artifact@v4 with: - name: ${{ runner.os }}-installers + name: ${{ matrix.id }}-installers path: artifact ##################################### @@ -280,16 +287,16 @@ jobs: run: | unset DEPTH if [ -n '${{ github.event.inputs.commit }}' ]; then DEPTH='0'; else DEPTH='1'; fi - echo "::set-output name=DEPTH::${DEPTH}" + echo "DEPTH=${DEPTH}" >> $GITHUB_OUTPUT - name: Checkout code - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: fetch-depth: ${{ steps.determine_fd.outputs.DEPTH }} if: github.event_name != 'schedule' - name: Checkout develop branch - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: ref: develop if: github.event_name == 'schedule' @@ -337,9 +344,9 @@ jobs: # GitHub Actions combines artifacts uploaded with the same name - name: Upload artifact - uses: actions/upload-artifact@v1 + uses: actions/upload-artifact@v4 with: - name: ${{ runner.os }}-installers + name: ${{ matrix.id }}-sharedlib-installers path: artifact ##################################### @@ -351,31 +358,13 @@ jobs: runs-on: ubuntu-latest if: github.event.action == 'published' steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - - name: Get all submodules archive - uses: actions/download-artifact@v1 + - name: Get all artifacts + uses: actions/download-artifact@v4 with: - name: all-submodules-archive - path: artifacts - - - name: Get Windows installers - uses: actions/download-artifact@v1 - with: - name: Windows-installers - path: artifacts - - - name: Get macOS installers - uses: actions/download-artifact@v1 - with: - name: macOS-installers - path: artifacts - - - name: Get Linux installers - uses: actions/download-artifact@v1 - with: - name: Linux-installers path: artifacts + merge-multiple: true - name: Create SHA-256 file run: cd artifacts && sha256sum * > "Helics-$(git rev-parse --abbrev-ref "${GITHUB_REF}")-SHA-256.txt" @@ -387,19 +376,17 @@ jobs: run: ./.github/actions/upload-release-asset.sh "artifacts/Helics-$(git rev-parse --abbrev-ref "${GITHUB_REF}")-SHA-256.txt" ##################################### -# Send helics-version-update event(s) +# Trigger helics-packaging workflows ##################################### send-version-update-event: - name: Send helics-version-update event(s) + name: Trigger helics-packaging workflows needs: [generate-sha256] runs-on: ubuntu-latest if: github.event.action == 'published' steps: - - name: Send event to helics-packaging + - name: Run helics_version_update workflow in helics-packaging + env: + GH_TOKEN: ${{ secrets.HELICS_PACKAGING_TOKEN }} run: | - HELICS_REPO="${{ github.repository }}" HELICS_VERSION="${{ github.event.release.tag_name }}" - curl -X POST --header 'authorization: Bearer ${{ secrets.HELICS_BOT_TOKEN }}' \ - --url https://api.github.com/repos/GMLC-TDC/helics-packaging/dispatches \ - --header 'content-type: application/json' \ - --data "{\"event_type\":\"helics-version-update\",\"client_payload\":{\"repository\":\"${HELICS_REPO}\",\"tag_name\":\"${HELICS_VERSION}\",\"version\":\"${HELICS_VERSION#v}\"}}" + gh workflow run --repo GMLC-TDC/helics-packaging helics_version_update.yml -f version="${HELICS_VERSION#v}" diff --git a/.github/workflows/static-analyzers.yml b/.github/workflows/static-analyzers.yml index 5d69d00fc8..6db896862d 100644 --- a/.github/workflows/static-analyzers.yml +++ b/.github/workflows/static-analyzers.yml @@ -6,12 +6,10 @@ on: branches: - develop - main - - helics2 pull_request: branches: - develop - main - - helics2 jobs: cpplint: @@ -19,7 +17,7 @@ jobs: container: helics/buildenv:cpplint steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Run cpplint run: cpplint --counting=detailed --recursive examples benchmarks src tests @@ -29,7 +27,9 @@ jobs: container: helics/buildenv:clang-extra-tools steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Run clang-tidy on changed files shell: bash - run: ./.github/actions/run-clang-tidy-pr.sh + run: | + git config --global --add safe.directory ${GITHUB_WORKSPACE} + ./.github/actions/run-clang-tidy-pr.sh diff --git a/.github/workflows/swig-interface-gen.yml b/.github/workflows/swig-interface-gen.yml index a2192522c4..7176e6bd09 100644 --- a/.github/workflows/swig-interface-gen.yml +++ b/.github/workflows/swig-interface-gen.yml @@ -6,14 +6,13 @@ on: branches: - main - develop - - helics2 jobs: build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: fetch-depth: 0 @@ -25,24 +24,26 @@ jobs: - uses: gmlc-tdc/helics-action/update-swig-interfaces@main # Run pre-commit docker-clang-format hook - - uses: actions/setup-python@v2 + - uses: actions/setup-python@v5 + with: + python-version: '3.10' - name: set PY run: echo "PY=$(python --version --version | sha256sum | cut -d' ' -f1)" >> $GITHUB_ENV - - uses: actions/cache@v1 + - uses: actions/cache@v4 with: path: ~/.cache/pre-commit key: pre-commit|${{ env.PY }}|${{ hashFiles('.pre-commit-config.yaml') }} # Run clang-format on helics.h and helics_api.h - name: clang-format - uses: pre-commit/action@v2.0.3 + uses: pre-commit/action@v3.0.0 # Failure is expected, since we know it will be fixing up the generated helics header files continue-on-error: true with: extra_args: clang-format --files src/helics/shared_api_library/backup/helics/helics.h src/helics/shared_api_library/backup/helics/helics_api.h - name: Create Pull Request - uses: peter-evans/create-pull-request@v4 + uses: peter-evans/create-pull-request@v6 with: commit-message: Automated update to generated interface files author: GitHub diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 30ddd8c077..adefeb257c 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -8,21 +8,21 @@ repos: - id: dockerfile_lint args: [--rulefile, ./config/Docker/docker_rules.yml, --dockerfile] - repo: https://github.com/psf/black - rev: 22.12.0 + rev: 24.1.1 hooks: - id: black args: ["--line-length=100"] - repo: https://github.com/asottile/blacken-docs - rev: 1.13.0 + rev: 1.16.0 hooks: - id: blacken-docs additional_dependencies: [black==22.12] - repo: https://github.com/Lucas-C/pre-commit-hooks - rev: v1.3.1 + rev: v1.5.4 hooks: - id: remove-tabs - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.4.0 + rev: v4.5.0 hooks: - id: check-added-large-files - id: mixed-line-ending @@ -40,7 +40,7 @@ repos: - id: detect-private-key exclude: ^(tests/helics/test_files/encryption_config/openssl_certs/) - repo: https://github.com/pre-commit/mirrors-prettier - rev: v3.0.0-alpha.4 + rev: v4.0.0-alpha.8 hooks: - id: prettier exclude: ^(docs/user-guide/examples/user_guide_examples) @@ -52,7 +52,7 @@ repos: exclude: "mac.md" - id: script-must-have-extension - repo: https://github.com/shellcheck-py/shellcheck-py - rev: v0.9.0.2 + rev: v0.9.0.6 hooks: - id: shellcheck args: [-x] @@ -62,7 +62,7 @@ repos: - id: cmake-format exclude: "cmake_+" - repo: https://github.com/codespell-project/codespell - rev: v2.2.2 + rev: v2.2.6 hooks: - id: codespell exclude: ^(docs/user-guide/examples/user_guide_examples) @@ -74,7 +74,7 @@ repos: "--exclude-file=./config/spelling_ignorelines.txt", ] - repo: https://github.com/pre-commit/mirrors-clang-format - rev: v15.0.6 + rev: v17.0.6 hooks: - id: clang-format types: diff --git a/.readthedocs.yaml b/.readthedocs.yaml index 9be8b63c62..416a32994a 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -3,9 +3,9 @@ version: 2 formats: all build: - os: ubuntu-20.04 + os: ubuntu-22.04 tools: - python: "3.9" + python: "3.10" sphinx: configuration: docs/conf.py diff --git a/CHANGELOG.md b/CHANGELOG.md index c3a79df93f..b78f6e11cc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,40 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm A note on future revisions. Everything within a major version number should be code compatible (with the exception of experimental interfaces). The most notable example of an experimental interface is the support for multiple source inputs. The APIs to deal with this will change in future minor releases. Everything within a single minor release should be network compatible with other federates on the same minor release number. Compatibility across minor release numbers may be possible in some situations but we are not going to guarantee this as those components are subject to performance improvements and may need to be modified at some point. Patch releases will be limited to bug fixes and other improvements not impacting the public API or network compatibility. Check the [Public API](./docs/Public_API.md) for details on what is included and excluded from the public API and version stability. +## [3.5.0][] - 2024-02-05 + +Major release including connector app capability, a refresh of the of the dataBuffer interface, and other bug fixes + +### Fixed + +- Fixed some issues regarding config files in the apps, where the config file was not being handled consistently +- Fixed a few more sporadically failing testing cases and a rare bug in the use of `wait_for_current_time` flag when entering executing mode +- Fixed a memory growth issue related to find operations in the C interface +- Resolved some issues with the threadSanitizer and other sporadic failures in the test cases + +### Changed + +- Test with Boost 1.84 and CMake 3.28 +- Large refactor of the dataBufferAPI, this is now considered stable, all dataBuffer related methods now start with helicsDataBuffer for consistency with other API methods and the XXXToBytes methods are changed to FillFromXXXX to be more consistent with other API's +- Update 3rd party libraries +- Update copyright to 2024 +- Autobuild ZMQ now set to 4.3.5 + +### Added + +- Added Connector app to enable automated connections of the federates via a set of matching rules, and allow optional interface generation via a query/command +- Added helics::systemInfo() to the C++ shared library +- Added ability to generate translators from config files +- Added API's to get and send dataBuffers from publications/inputs/endpoints + +### Deprecated + +- Nearly all methods that use `Subscription` in the name have been deprecated in favor of an equivalent version for `Input` to reduce confusion of use of subscription objects (which are just Input objects); these are all 1:1 mappings + - `getSubscription(string target)` -> `getInputByTarget(string target)` + - `getSubscription(int index)` -> `getInput(int index)` + - `helicsSubscriptionGetTarget(inp)` -> `helicsInputGetTarget(inp)` + - `helicsFederateGetSubscription(fed, string target)`->`helicsFederateGetInputByTarget(fed,string target)` + ## [3.4.0][] - 2023-01-19 Major release including full dynamic federation capability and wildcard based matching for interface connections. diff --git a/CMakeLists.txt b/CMakeLists.txt index 700dfb471b..d48f3d5569 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ # ~~~ -# Copyright (c) 2017-2023, Battelle Memorial Institute; Lawrence Livermore +# Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore # National Security, LLC; Alliance for Sustainable Energy, LLC. # See the top-level NOTICE for additional details. # All rights reserved. @@ -7,7 +7,7 @@ # SPDX-License-Identifier: BSD-3-Clause # ~~~ -cmake_minimum_required(VERSION 3.11...3.25) +cmake_minimum_required(VERSION 3.11...3.28) # Install dependencies using vcpkg if VCPKG_ROOT is set and no CMake Toolchain file is given vcpkg # installation on a system doesn't set VCPKG_ROOT, so setting it should be like an opt-in for users @@ -17,14 +17,14 @@ if(DEFINED ENV{VCPKG_ROOT} AND NOT DEFINED CMAKE_TOOLCHAIN_FILE AND NOT HELICS_D set(CMAKE_TOOLCHAIN_FILE "$ENV{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake" CACHE STRING "") endif() -project(HELICS VERSION 3.4.0) +project(HELICS VERSION 3.5.0) # ----------------------------------------------------------------------------- # HELICS Version number # ----------------------------------------------------------------------------- set(HELICS_VERSION_BUILD) # use ISO date YYYY-MM-DD -set(HELICS_DATE "2023-01-19") +set(HELICS_DATE "2024-02-06") set(HELICS_VERSION_UNDERSCORE "${HELICS_VERSION_MAJOR}_${HELICS_VERSION_MINOR}_${HELICS_VERSION_PATCH}" @@ -309,7 +309,7 @@ if(NOT TARGET toml11::toml11) set(toml11_TEST_WITH_UBSAN OFF CACHE INTERNAL "") set(toml11_INSTALL OFF CACHE INTERNAL "") add_subdirectory(ThirdParty/toml EXCLUDE_FROM_ALL) - + hide_variable(TOML11_USE_UNRELEASED_TOML_FEATURES) endif() # ------------------------------------------------------------- @@ -408,7 +408,12 @@ if(MSYS OR CYGWIN) if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang") set(ENABLE_IPC_CORE FALSE) endif() - target_compile_definitions(helics_base INTERFACE -D_WIN32_WINNT=0x0601) + # setting to windows 10 for all compilation + if(WIN32_WINNT) + add_compile_definitions("_WIN32_WINNT=${WIN32_WINNT}") + else() + add_compile_definitions(_WIN32_WINNT=0x0A00) + endif() endif() if(MINGW AND NOT UNIX_LIKE) @@ -706,7 +711,7 @@ if(HELICS_BUILD_BENCHMARKS) endif() if(EXISTS ${PROJECT_BINARY_DIR}/_deps/libzmq-src AND HELICS_ENABLE_ZMQ_CORE) - list(APPEND LICENSE_LIST "ZeroMQ" "${PROJECT_BINARY_DIR}/_deps/libzmq-src/COPYING") + list(APPEND LICENSE_LIST "ZeroMQ" "${PROJECT_BINARY_DIR}/_deps/libzmq-src/LICENSE") endif() if(NOT HELICS_DISABLE_ASIO) diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index c4df0f249f..4e129ad354 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -32,7 +32,6 @@ If you would like to contribute to the HELICS project see [CONTRIBUTING](CONTRIB - [Ai Enkoji](https://github.com/aenkoji1) - [Nan Duan](https://github.com/nan-duan) - [Nathan Yee](https://github.com/yee29) (Now Accenture) -- [Ai Enkoji](https://github.com/aenkoji1) ### National Renewable Energy Lab @@ -76,7 +75,7 @@ CLI11 is a command line parser used throughout HELICS. Several modification used ### [toml11](https://github.com/ToruNiina/toml11) -toml11 is a C\++11 header-only TOML parser/encoder depending only on the C++ standard library. Compatible with the latest version of TOML v0.5.0. toml11 is licensed under the [MIT](https://github.com/ToruNiina/toml11/blob/master/LICENSE) license. HELICS includes it through a submodule of a library [fork](https://github.com/GMLC-TDC/toml11) until the changes can be merged upstream. +toml11 is a C\++11 header-only TOML parser/encoder depending only on the C++ standard library. Compatible with the latest version of TOML v1.0.0. toml11 is licensed under the [MIT](https://github.com/ToruNiina/toml11/blob/master/LICENSE) license. HELICS includes it through a submodule of a library [fork](https://github.com/GMLC-TDC/toml11) until the changes can be merged upstream. ### [GridDyn](https://github.com/LLNL/GridDyn) @@ -139,7 +138,8 @@ Boost is used in a few places in the code. The IPC core uses the Boost.Interproc #### [zmq](http://www.zeromq.org) -ZeroMQ is one of many backends that can be used by HELICS for message passing (ZMQ core networking). The automatic download currently uses version 4.3.1. No ZMQ library code is included in the HELICS source. HELICS installers include ZeroMQ binary libraries. ZeroMQ is licensed under [LGPL](https://github.com/zeromq/libzmq/blob/master/COPYING.LESSER) with a modification to allow for linking and in various forms and distribution of the binary under different terms if the library was not modified. Clarification on static linking being okay can be found in [this github issue](https://github.com/zeromq/libzmq/issues/3787). No modification of the ZMQ library or any of the ZeroMQ source files is included in the HELICS source code. Currently the Windows installers and shared library builds static link ZeroMQ. When building from source it is an optional component and can be excluded by setting `HELICS_ENABLE_ZMQ_CORE` to `OFF` +ZeroMQ is one of many backends that can be used by HELICS for message passing (ZMQ core networking). The automatic download currently uses version 4.3.5. No ZMQ library code is included in the HELICS source. HELICS installers include ZeroMQ binary libraries. ZeroMQ is licensed under [MPL](https://github.com/zeromq/libzmq/blob/master/LICENSE) +Previous versions(prior to 4.3.5) were under LGPL with a modification to allow for linking and in various forms and distribution of the binary under different terms if the library was not modified. Clarification on static linking being okay can be found in [this github issue](https://github.com/zeromq/libzmq/issues/3787). No modification of the ZMQ library or any of the ZeroMQ source files is included in the HELICS source code. Currently the Windows installers and shared library builds static link ZeroMQ. When building from source it is an optional component and can be excluded by setting `HELICS_ENABLE_ZMQ_CORE` to `OFF` ### [Google Test](https://github.com/google/googletest) diff --git a/LICENSE b/LICENSE index 52a1844e41..110819a212 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ BSD 3-Clause License -Copyright (c) 2017-2023, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: diff --git a/ThirdParty/asio b/ThirdParty/asio index 147f7225a9..1f8d154829 160000 --- a/ThirdParty/asio +++ b/ThirdParty/asio @@ -1 +1 @@ -Subproject commit 147f7225a96d45a2807a64e443177f621844e51c +Subproject commit 1f8d154829b902dbc45a651587c6c6df948358e8 diff --git a/ThirdParty/cmake/ucm.cmake b/ThirdParty/cmake/ucm.cmake index 4f9b982a33..4b17d5112d 100644 --- a/ThirdParty/cmake/ucm.cmake +++ b/ThirdParty/cmake/ucm.cmake @@ -10,7 +10,7 @@ # The documentation can be found at the library's page: # https://github.com/onqtam/ucm -cmake_minimum_required(VERSION 2.8.12) +cmake_minimum_required(VERSION 3.11) include(CMakeParseArguments) @@ -21,12 +21,13 @@ endif() if(COMMAND cotire AND "1.7.9" VERSION_LESS "${COTIRE_CMAKE_MODULE_VERSION}") set(ucm_with_cotire 1) - option(UCM_UNITY_BUILD "Enable unity build for targets registered with the ucm_add_target() macro" OFF) - option(UCM_NO_COTIRE_FOLDER "Do not use a cotire folder in the solution explorer for all unity and cotire related targets" ON) else() set(ucm_with_cotire 0) endif() +option(UCM_UNITY_BUILD "Enable unity build for targets registered with the ucm_add_target() macro" OFF) +option(UCM_NO_COTIRE_FOLDER "Do not use a cotire folder in the solution explorer for all unity and cotire related targets" ON) + # ucm_add_flags # Adds compiler flags to CMAKE__FLAGS or to a specific config macro(ucm_add_flags) @@ -76,6 +77,38 @@ macro(ucm_set_flags) ucm_add_flags(CLEAR_OLD ${ARGN}) endmacro() +# ucm_remove_flags +# Removes compiler flags from CMAKE__FLAGS or from a specific config +macro(ucm_remove_flags) + cmake_parse_arguments(ARG "C;CXX" "" "CONFIG" ${ARGN}) + + if(NOT ARG_CONFIG) + set(ARG_CONFIG " ") + endif() + + foreach(CONFIG ${ARG_CONFIG}) + # determine from which flags to remove + if(NOT ${CONFIG} STREQUAL " ") + string(TOUPPER ${CONFIG} CONFIG) + set(CXX_FLAGS CMAKE_CXX_FLAGS_${CONFIG}) + set(C_FLAGS CMAKE_C_FLAGS_${CONFIG}) + else() + set(CXX_FLAGS CMAKE_CXX_FLAGS) + set(C_FLAGS CMAKE_C_FLAGS) + endif() + + # remove all the passed flags + foreach(flag ${ARG_UNPARSED_ARGUMENTS}) + if("${ARG_CXX}" OR NOT "${ARG_C}") + string(REGEX REPLACE "${flag}" "" ${CXX_FLAGS} "${${CXX_FLAGS}}") + endif() + if("${ARG_C}" OR NOT "${ARG_CXX}") + string(REGEX REPLACE "${flag}" "" ${C_FLAGS} "${${C_FLAGS}}") + endif() + endforeach() + endforeach() +endmacro() + # ucm_add_linker_flags # Adds linker flags to CMAKE__LINKER_FLAGS or to a specific config macro(ucm_add_linker_flags) diff --git a/ThirdParty/concurrency b/ThirdParty/concurrency index 1bed77b9a9..3a06173deb 160000 --- a/ThirdParty/concurrency +++ b/ThirdParty/concurrency @@ -1 +1 @@ -Subproject commit 1bed77b9a976f46df964b27f589cc965600ee3cc +Subproject commit 3a06173debc18c6712245eb7b6e779d1837f179d diff --git a/ThirdParty/fmtlib b/ThirdParty/fmtlib index a33701196a..f5e54359df 160000 --- a/ThirdParty/fmtlib +++ b/ThirdParty/fmtlib @@ -1 +1 @@ -Subproject commit a33701196adfad74917046096bf5a2aa0ab0bb50 +Subproject commit f5e54359df4c26b6230fc61d38aa294581393084 diff --git a/ThirdParty/json_cpp b/ThirdParty/json_cpp index 42e892d96e..69098a18b9 160000 --- a/ThirdParty/json_cpp +++ b/ThirdParty/json_cpp @@ -1 +1 @@ -Subproject commit 42e892d96e47b1f6e29844cc705e148ec4856448 +Subproject commit 69098a18b9af0c47549d9a271c054d13ca92b006 diff --git a/ThirdParty/spdlog b/ThirdParty/spdlog index ad0e89cbfb..7e635fca68 160000 --- a/ThirdParty/spdlog +++ b/ThirdParty/spdlog @@ -1 +1 @@ -Subproject commit ad0e89cbfb4d0c1ce4d097e134eb7be67baebb36 +Subproject commit 7e635fca68d014934b4af8a1cf874f63989352b7 diff --git a/ThirdParty/toml b/ThirdParty/toml index dcfe39a783..087408a8fb 160000 --- a/ThirdParty/toml +++ b/ThirdParty/toml @@ -1 +1 @@ -Subproject commit dcfe39a783a94e8d52c885e5883a6fbb21529019 +Subproject commit 087408a8fbc8983d8c590eee9d3541400dfa34d9 diff --git a/ThirdParty/units b/ThirdParty/units index 5399c41d15..7917f5f2cf 160000 --- a/ThirdParty/units +++ b/ThirdParty/units @@ -1 +1 @@ -Subproject commit 5399c41d152758a45fcd3246a94742660c1f5cbb +Subproject commit 7917f5f2cfefdcc90b5085ade91761d06df74e59 diff --git a/ThirdParty/utilities b/ThirdParty/utilities index 952aed2d4c..0a82fa18d9 160000 --- a/ThirdParty/utilities +++ b/ThirdParty/utilities @@ -1 +1 @@ -Subproject commit 952aed2d4c99da871b125f420f6362519c5c9b9d +Subproject commit 0a82fa18d9cecbecaa96d1b29f09bf3c75ee27aa diff --git a/appveyor.yml b/appveyor.yml index 01c297b963..fec6e917fc 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -5,7 +5,7 @@ branches: - main - develop -version: 3.4.0.{build} +version: 3.5.0.{build} image: Visual Studio 2019 diff --git a/benchmarks/CMakeLists.txt b/benchmarks/CMakeLists.txt index bbe352970b..0cf4575ac3 100644 --- a/benchmarks/CMakeLists.txt +++ b/benchmarks/CMakeLists.txt @@ -1,5 +1,5 @@ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Copyright (c) 2017-2023, Battelle Memorial Institute; Lawrence Livermore +# Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore # National Security, LLC; Alliance for Sustainable Energy, LLC. # See the top-level NOTICE for additional details. # All rights reserved. diff --git a/benchmarks/helics/ActionMessageBenchmarks.cpp b/benchmarks/helics/ActionMessageBenchmarks.cpp index 3bb01686d8..4562ed1904 100644 --- a/benchmarks/helics/ActionMessageBenchmarks.cpp +++ b/benchmarks/helics/ActionMessageBenchmarks.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/benchmarks/helics/BarabasiAlbertFederate.hpp b/benchmarks/helics/BarabasiAlbertFederate.hpp index d3a4f71681..fa46fcd067 100644 --- a/benchmarks/helics/BarabasiAlbertFederate.hpp +++ b/benchmarks/helics/BarabasiAlbertFederate.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/benchmarks/helics/BenchmarkFederate.hpp b/benchmarks/helics/BenchmarkFederate.hpp index 386421cf9e..6ea3a8484d 100644 --- a/benchmarks/helics/BenchmarkFederate.hpp +++ b/benchmarks/helics/BenchmarkFederate.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/benchmarks/helics/BenchmarkMain.cpp b/benchmarks/helics/BenchmarkMain.cpp index 16c05d67fe..4a1aeefc2b 100644 --- a/benchmarks/helics/BenchmarkMain.cpp +++ b/benchmarks/helics/BenchmarkMain.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/benchmarks/helics/CMakeLists.txt b/benchmarks/helics/CMakeLists.txt index 3afccdb10f..f10fb479dd 100644 --- a/benchmarks/helics/CMakeLists.txt +++ b/benchmarks/helics/CMakeLists.txt @@ -1,5 +1,5 @@ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Copyright (c) 2017-2023, Battelle Memorial Institute; Lawrence Livermore +# Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore # National Security, LLC; Alliance for Sustainable Energy, LLC. # See the top-level NOTICE for additional details. # All rights reserved. diff --git a/benchmarks/helics/EchoHubFederate.hpp b/benchmarks/helics/EchoHubFederate.hpp index b806b0b01c..eab46a64c5 100644 --- a/benchmarks/helics/EchoHubFederate.hpp +++ b/benchmarks/helics/EchoHubFederate.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/benchmarks/helics/EchoLeafFederate.hpp b/benchmarks/helics/EchoLeafFederate.hpp index 8f0a0bbf22..5a5f8a2f80 100644 --- a/benchmarks/helics/EchoLeafFederate.hpp +++ b/benchmarks/helics/EchoLeafFederate.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/benchmarks/helics/EchoMessageHubFederate.hpp b/benchmarks/helics/EchoMessageHubFederate.hpp index b4f8b4d617..3ccf4e9062 100644 --- a/benchmarks/helics/EchoMessageHubFederate.hpp +++ b/benchmarks/helics/EchoMessageHubFederate.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/benchmarks/helics/EchoMessageLeafFederate.hpp b/benchmarks/helics/EchoMessageLeafFederate.hpp index 7b0ca86aed..6d8c88d9c7 100644 --- a/benchmarks/helics/EchoMessageLeafFederate.hpp +++ b/benchmarks/helics/EchoMessageLeafFederate.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/benchmarks/helics/MessageExchangeFederate.hpp b/benchmarks/helics/MessageExchangeFederate.hpp index 245824d479..b7d839ed03 100644 --- a/benchmarks/helics/MessageExchangeFederate.hpp +++ b/benchmarks/helics/MessageExchangeFederate.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/benchmarks/helics/PholdFederate.hpp b/benchmarks/helics/PholdFederate.hpp index 60926e740a..08cb2933fc 100644 --- a/benchmarks/helics/PholdFederate.hpp +++ b/benchmarks/helics/PholdFederate.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/benchmarks/helics/RingTransmitFederate.hpp b/benchmarks/helics/RingTransmitFederate.hpp index 381f1dbcca..2023ced0a5 100644 --- a/benchmarks/helics/RingTransmitFederate.hpp +++ b/benchmarks/helics/RingTransmitFederate.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/benchmarks/helics/RingTransmitMessageFederate.hpp b/benchmarks/helics/RingTransmitMessageFederate.hpp index 1e26905f28..e4ebe9cb86 100644 --- a/benchmarks/helics/RingTransmitMessageFederate.hpp +++ b/benchmarks/helics/RingTransmitMessageFederate.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/benchmarks/helics/TcpFederate.cpp b/benchmarks/helics/TcpFederate.cpp index 2657520450..3d396a0301 100644 --- a/benchmarks/helics/TcpFederate.cpp +++ b/benchmarks/helics/TcpFederate.cpp @@ -1,12 +1,10 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause */ -#pragma once - #include "gmlc/networking/AsioContextManager.h" #include "gmlc/networking/TcpHelperClasses.h" #include "helics/network/networkDefaults.hpp" diff --git a/benchmarks/helics/TimingHubFederate.hpp b/benchmarks/helics/TimingHubFederate.hpp index 6f8e564149..4a24526223 100644 --- a/benchmarks/helics/TimingHubFederate.hpp +++ b/benchmarks/helics/TimingHubFederate.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/benchmarks/helics/TimingLeafFederate.hpp b/benchmarks/helics/TimingLeafFederate.hpp index 57fa255726..11e1e88b04 100644 --- a/benchmarks/helics/TimingLeafFederate.hpp +++ b/benchmarks/helics/TimingLeafFederate.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/benchmarks/helics/WattsStrogatzFederate.hpp b/benchmarks/helics/WattsStrogatzFederate.hpp index f1640e97c7..40a1f574c9 100644 --- a/benchmarks/helics/WattsStrogatzFederate.hpp +++ b/benchmarks/helics/WattsStrogatzFederate.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/benchmarks/helics/barabasiAlbertBenchmarks.cpp b/benchmarks/helics/barabasiAlbertBenchmarks.cpp index aa81c00012..b8a083a4ea 100644 --- a/benchmarks/helics/barabasiAlbertBenchmarks.cpp +++ b/benchmarks/helics/barabasiAlbertBenchmarks.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/benchmarks/helics/conversionBenchmarks.cpp b/benchmarks/helics/conversionBenchmarks.cpp index 34286f93ce..c958f5d1a6 100644 --- a/benchmarks/helics/conversionBenchmarks.cpp +++ b/benchmarks/helics/conversionBenchmarks.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/benchmarks/helics/echoBenchmarks.cpp b/benchmarks/helics/echoBenchmarks.cpp index a94c03251f..d6e6419e49 100644 --- a/benchmarks/helics/echoBenchmarks.cpp +++ b/benchmarks/helics/echoBenchmarks.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/benchmarks/helics/echoBenchmarks_c.cpp b/benchmarks/helics/echoBenchmarks_c.cpp index b6782ed5b2..99ed79fd6e 100644 --- a/benchmarks/helics/echoBenchmarks_c.cpp +++ b/benchmarks/helics/echoBenchmarks_c.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/benchmarks/helics/echoMessageBenchmarks.cpp b/benchmarks/helics/echoMessageBenchmarks.cpp index 96b22c03af..08dcdcaac6 100644 --- a/benchmarks/helics/echoMessageBenchmarks.cpp +++ b/benchmarks/helics/echoMessageBenchmarks.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/benchmarks/helics/filterBenchmarks.cpp b/benchmarks/helics/filterBenchmarks.cpp index a22b8bf71e..4b747979c7 100644 --- a/benchmarks/helics/filterBenchmarks.cpp +++ b/benchmarks/helics/filterBenchmarks.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/benchmarks/helics/helics_benchmark_main.h b/benchmarks/helics/helics_benchmark_main.h index 78beb0d0e9..96d164bd58 100644 --- a/benchmarks/helics/helics_benchmark_main.h +++ b/benchmarks/helics/helics_benchmark_main.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/benchmarks/helics/helics_benchmark_util.h b/benchmarks/helics/helics_benchmark_util.h index 0a30114eaa..afb9a5a5b5 100644 --- a/benchmarks/helics/helics_benchmark_util.h +++ b/benchmarks/helics/helics_benchmark_util.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/benchmarks/helics/messageLookupBenchmarks.cpp b/benchmarks/helics/messageLookupBenchmarks.cpp index b411ee36e1..b49ed0f1cb 100644 --- a/benchmarks/helics/messageLookupBenchmarks.cpp +++ b/benchmarks/helics/messageLookupBenchmarks.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/benchmarks/helics/messageSendBenchmarks.cpp b/benchmarks/helics/messageSendBenchmarks.cpp index a198f9c4ad..40a4644371 100644 --- a/benchmarks/helics/messageSendBenchmarks.cpp +++ b/benchmarks/helics/messageSendBenchmarks.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/benchmarks/helics/pholdBenchmarks.cpp b/benchmarks/helics/pholdBenchmarks.cpp index c6ececf551..26caac3f60 100644 --- a/benchmarks/helics/pholdBenchmarks.cpp +++ b/benchmarks/helics/pholdBenchmarks.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/benchmarks/helics/ringBenchmarks.cpp b/benchmarks/helics/ringBenchmarks.cpp index 039dbeb581..37855bfe0a 100644 --- a/benchmarks/helics/ringBenchmarks.cpp +++ b/benchmarks/helics/ringBenchmarks.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/benchmarks/helics/ringMessageBenchmarks.cpp b/benchmarks/helics/ringMessageBenchmarks.cpp index b8318caea2..7cd006ae90 100644 --- a/benchmarks/helics/ringMessageBenchmarks.cpp +++ b/benchmarks/helics/ringMessageBenchmarks.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/benchmarks/helics/timingBenchmarks.cpp b/benchmarks/helics/timingBenchmarks.cpp index b2b81bc89d..d0f9c17680 100644 --- a/benchmarks/helics/timingBenchmarks.cpp +++ b/benchmarks/helics/timingBenchmarks.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/benchmarks/helics/wattsStrogatzBenchmarks.cpp b/benchmarks/helics/wattsStrogatzBenchmarks.cpp index 707705683f..39014d9ac4 100644 --- a/benchmarks/helics/wattsStrogatzBenchmarks.cpp +++ b/benchmarks/helics/wattsStrogatzBenchmarks.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/config/Docker/Dockerfile-HELICS b/config/Docker/Dockerfile-HELICS index 292390f613..ada558c78d 100644 --- a/config/Docker/Dockerfile-HELICS +++ b/config/Docker/Dockerfile-HELICS @@ -47,8 +47,8 @@ LABEL name="helics.helics" LABEL org.helics.description="HELICS basic docker image" LABEL org.helics.vcs-ref=$GIT_COMMIT LABEL org.helics.vcs-url="https://github.com/GMLC-TDC/helics" -LABEL version="3.4.0" -LABEL date="2023-01-19" +LABEL version="3.5.0" +LABEL date="2024-02-05" # Copy the HELICS install from the builder image stage above to a location in the PATH env var COPY --from=builder /root/develop/helics-install /usr diff --git a/config/Docker/Dockerfile-HELICS-apps b/config/Docker/Dockerfile-HELICS-apps index 2e379b8702..0e6cd945a1 100644 --- a/config/Docker/Dockerfile-HELICS-apps +++ b/config/Docker/Dockerfile-HELICS-apps @@ -48,8 +48,8 @@ LABEL name="helics.apps" LABEL org.helics.description="HELICS applications" LABEL org.helics.vcs-ref=$GIT_COMMIT LABEL org.helics.vcs-url="https://github.com/GMLC-TDC/helics" -LABEL version="3.4.0" -LABEL date="2023-01-19" +LABEL version="3.5.0" +LABEL date="2024-02-05" # Copy the HELICS install from the builder image stage above to a location in the PATH env var COPY --from=builder /root/develop/helics-install /usr diff --git a/config/Docker/Dockerfile-HELICS-builder b/config/Docker/Dockerfile-HELICS-builder index 05c34699f2..2f8c617e5c 100644 --- a/config/Docker/Dockerfile-HELICS-builder +++ b/config/Docker/Dockerfile-HELICS-builder @@ -44,8 +44,8 @@ LABEL name="helics.builder" LABEL org.helics.description="HELICS builder base image" LABEL org.helics.vcs-ref=$GIT_COMMIT LABEL org.helics.vcs-url="https://github.com/GMLC-TDC/helics" -LABEL version="3.4.0" -LABEL date="2023-01-19" +LABEL version="3.5.0" +LABEL date="2024-02-05" # Copy the HELICS install from the builder image stage above to a location in the PATH env var COPY --from=builder /root/develop/helics-install /usr diff --git a/config/Docker/docker_rules.yml b/config/Docker/docker_rules.yml index e56a3d5559..dd867482f9 100644 --- a/config/Docker/docker_rules.yml +++ b/config/Docker/docker_rules.yml @@ -1,7 +1,7 @@ --- profile: - name: 'helics docker images' - description: 'HELICS Profile. Checks basic syntax and required labels' + name: "helics docker images" + description: "HELICS Profile. Checks basic syntax and required labels" includes: #- recommended_label_rules.yaml line_rules: @@ -18,147 +18,147 @@ line_rules: Name: valueRegex: /[\w]+/ message: "Label 'Name' is missing or has invalid format" - level: 'warn' + level: "warn" required: true reference_url: - - 'http://docs.projectatomic.io/container-best-practices/#' - - '_recommended_labels_for_your_project' + - "http://docs.projectatomic.io/container-best-practices/#" + - "_recommended_labels_for_your_project" Version: valueRegex: /[\w.${}()"'\\\/~<>\-?\%:]+/ message: "Label 'Version' is missing or has invalid format" - level: 'warn' + level: "warn" required: true reference_url: - - 'http://docs.projectatomic.io/container-best-practices/#' - - '_recommended_labels_for_your_project' + - "http://docs.projectatomic.io/container-best-practices/#" + - "_recommended_labels_for_your_project" Release: valueRegex: /[\w.${}()"'\\\/~<>\-?\%:]+/ message: "Label 'Release' is missing or has invalid format" - level: 'warn' + level: "warn" required: false reference_url: - - 'http://docs.projectatomic.io/container-best-practices/#' - - '_recommended_labels_for_your_project' + - "http://docs.projectatomic.io/container-best-practices/#" + - "_recommended_labels_for_your_project" Architecture: valueRegex: /[\w]*[6,8][4,6]|[.]*86[.]*64/ message: "Label 'Architecture' is missing or has invalid format: x86, i386, x86_64" - level: 'info' + level: "info" required: false reference_url: - - 'http://docs.projectatomic.io/container-best-practices/#' - - '_recommended_labels_for_your_project' + - "http://docs.projectatomic.io/container-best-practices/#" + - "_recommended_labels_for_your_project" Vendor: valueRegex: /([\w]+).+/ message: "Label 'Vendor' is missing or has invalid format" - level: 'warn' + level: "warn" required: false reference_url: - - 'http://docs.projectatomic.io/container-best-practices/#' - - '_recommended_labels_for_your_project' + - "http://docs.projectatomic.io/container-best-practices/#" + - "_recommended_labels_for_your_project" Url: valueRegex: /([\w]+).+/ message: "Label 'Url' is missing or has invalid format" - level: 'warn' + level: "warn" required: false reference_url: - - 'http://docs.projectatomic.io/container-best-practices/#' - - '_recommended_labels_for_your_project' + - "http://docs.projectatomic.io/container-best-practices/#" + - "_recommended_labels_for_your_project" Help: valueRegex: /([\w]+).+/ message: "Label 'Help' is missing or has invalid format" - level: 'warn' + level: "warn" required: false reference_url: - - 'http://docs.projectatomic.io/container-best-practices/#' - - '_recommended_labels_for_your_project' + - "http://docs.projectatomic.io/container-best-practices/#" + - "_recommended_labels_for_your_project" FROM: paramSyntaxRegex: /^[\w./\-:]+(:[${}\w.]+)?(-[${}\w.]+)?( as \w+)?$/i rules: - - label: 'no_tag' + - label: "no_tag" regex: /^[:]/ - level: 'error' - message: 'No tag is used' - description: 'lorem ipsum tar' + level: "error" + message: "No tag is used" + description: "lorem ipsum tar" reference_url: - - 'https://docs.docker.com/engine/reference/builder/' - - '#from' + - "https://docs.docker.com/engine/reference/builder/" + - "#from" MAINTAINER: paramSyntaxRegex: /.+/ rules: [] RUN: paramSyntaxRegex: /.+/ rules: - - label: 'no_yum_clean_all' + - label: "no_yum_clean_all" regex: /yum(?!.+clean all|.+\.repo|-config|\.conf)/ - level: 'warn' - message: 'yum clean all is not used' - description: 'the yum cache will remain in this layer making the layer unnecessarily large' + level: "warn" + message: "yum clean all is not used" + description: "the yum cache will remain in this layer making the layer unnecessarily large" reference_url: - - 'http://docs.projectatomic.io/container-best-practices/#' - - '_clear_packaging_caches_and_temporary_package_downloads' - - label: 'yum_update_all' + - "http://docs.projectatomic.io/container-best-practices/#" + - "_clear_packaging_caches_and_temporary_package_downloads" + - label: "yum_update_all" regex: /yum(.+update all|.+upgrade|.+update)/ - level: 'info' - message: 'updating the entire base image may add unnecessary size to the container' - description: 'update the entire base image may add unnecessary size to the container' + level: "info" + message: "updating the entire base image may add unnecessary size to the container" + description: "update the entire base image may add unnecessary size to the container" reference_url: - - 'http://docs.projectatomic.io/container-best-practices/#' - - '_clear_packaging_caches_and_temporary_package_downloads' - - label: 'no_dnf_clean_all' + - "http://docs.projectatomic.io/container-best-practices/#" + - "_clear_packaging_caches_and_temporary_package_downloads" + - label: "no_dnf_clean_all" regex: /dnf(?!.+clean all|.+\.repo)/g - level: 'warn' - message: 'dnf clean all is not used' - description: 'the dnf cache will remain in this layer making the layer unnecessarily large' + level: "warn" + message: "dnf clean all is not used" + description: "the dnf cache will remain in this layer making the layer unnecessarily large" reference_url: - - 'http://docs.projectatomic.io/container-best-practices/#' - - '_clear_packaging_caches_and_temporary_package_downloads' - - label: 'no_rvm_cleanup_all' + - "http://docs.projectatomic.io/container-best-practices/#" + - "_clear_packaging_caches_and_temporary_package_downloads" + - label: "no_rvm_cleanup_all" regex: /rvm install(?!.+cleanup all)/g - level: 'warn' - message: 'rvm cleanup is not used' - description: 'the rvm cache will remain in this layer making the layer unnecessarily large' + level: "warn" + message: "rvm cleanup is not used" + description: "the rvm cache will remain in this layer making the layer unnecessarily large" reference_url: - - 'http://docs.projectatomic.io/container-best-practices/#' - - '_clear_packaging_caches_and_temporary_package_downloads' - - label: 'no_gem_clean_all' + - "http://docs.projectatomic.io/container-best-practices/#" + - "_clear_packaging_caches_and_temporary_package_downloads" + - label: "no_gem_clean_all" regex: /gem install(?!.+cleanup|.+\rvm cleanup all)/g - level: 'warn' - message: 'gem cleanup all is not used' - description: 'the gem cache will remain in this layer making the layer unnecessarily large' + level: "warn" + message: "gem cleanup all is not used" + description: "the gem cache will remain in this layer making the layer unnecessarily large" reference_url: - - 'http://docs.projectatomic.io/container-best-practices/#' - - '_clear_packaging_caches_and_temporary_package_downloads' - - label: 'no_apt-get_clean' + - "http://docs.projectatomic.io/container-best-practices/#" + - "_clear_packaging_caches_and_temporary_package_downloads" + - label: "no_apt-get_clean" regex: /apt-get install(?!.+clean)/g - level: 'info' - message: 'apt-get clean is not used' - description: 'the apt-get cache will remain in this layer making the layer unnecessarily large' + level: "info" + message: "apt-get clean is not used" + description: "the apt-get cache will remain in this layer making the layer unnecessarily large" reference_url: - - 'http://docs.projectatomic.io/container-best-practices/#' - - '_clear_packaging_caches_and_temporary_package_downloads' - - label: 'privileged_run_container' + - "http://docs.projectatomic.io/container-best-practices/#" + - "_clear_packaging_caches_and_temporary_package_downloads" + - label: "privileged_run_container" regex: /privileged/ - level: 'warn' - message: 'a privileged run container is allowed access to host devices' - description: 'Does this run need to be privileged?' + level: "warn" + message: "a privileged run container is allowed access to host devices" + description: "Does this run need to be privileged?" reference_url: - - 'http://docs.docker.com/engine/reference/run/#' - - 'runtime-privilege-and-linux-capabilities' - - label: 'installing_ssh' + - "http://docs.docker.com/engine/reference/run/#" + - "runtime-privilege-and-linux-capabilities" + - label: "installing_ssh" regex: /openssh-server/ - level: 'warn' - message: 'installing SSH in a container is not recommended' - description: 'Do you really need SSH in this image?' - reference_url: 'https://github.com/jpetazzo/nsenter' - - label: 'no_ampersand_usage' + level: "warn" + message: "installing SSH in a container is not recommended" + description: "Do you really need SSH in this image?" + reference_url: "https://github.com/jpetazzo/nsenter" + - label: "no_ampersand_usage" regex: / ; / - level: 'info' - message: 'using ; instead of &&' - description: 'RUN do_1 && do_2: The ampersands change the resulting evaluation into do_1 and then do_2 only if do_1 was successful.' + level: "info" + message: "using ; instead of &&" + description: "RUN do_1 && do_2: The ampersands change the resulting evaluation into do_1 and then do_2 only if do_1 was successful." reference_url: - - 'http://docs.projectatomic.io/container-best-practices/#' - - '#_using_semi_colons_vs_double_ampersands' + - "http://docs.projectatomic.io/container-best-practices/#" + - "#_using_semi_colons_vs_double_ampersands" EXPOSE: paramSyntaxRegex: /^[\d-\s\w/\\]+$/ rules: [] @@ -187,10 +187,10 @@ line_rules: rules: [] required_instructions: - count: 1 - description: 'Labels are needed to identify information about the docker image' + description: "Labels are needed to identify information about the docker image" instruction: LABEL level: error - message: 'No LABELs are defined' + message: "No LABELs are defined" reference_url: - - 'https://docs.docker.com/engine/reference/builder/' - - '#label' + - "https://docs.docker.com/engine/reference/builder/" + - "#label" diff --git a/config/cmake/AddGooglebenchmark.cmake b/config/cmake/AddGooglebenchmark.cmake index ac11e9c092..469f2476cc 100644 --- a/config/cmake/AddGooglebenchmark.cmake +++ b/config/cmake/AddGooglebenchmark.cmake @@ -1,5 +1,5 @@ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Copyright (c) 2017-2020, Battelle Memorial Institute; Lawrence Livermore +# Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore # National Security, LLC; Alliance for Sustainable Energy, LLC. # See the top-level NOTICE for additional details. # All rights reserved. @@ -7,7 +7,7 @@ # SPDX-License-Identifier: BSD-3-Clause # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -set(gbenchmark_version v1.5.0) +set(gbenchmark_version v1.8.3) string(TOLOWER "gbenchmark" gbName) @@ -87,6 +87,11 @@ hide_variable(BENCHMARK_ENABLE_ASSEMBLY_TESTS) hide_variable(BENCHMARK_ENABLE_EXCEPTIONS) hide_variable(BENCHMARK_ENABLE_LTO) hide_variable(BENCHMARK_USE_LIBCXX) +hide_variable(BENCHMARK_ENABLE_DOXYGEN) +hide_variable(BENCHMARK_ENABLE_LIBPFM) +hide_variable(BENCHMARK_ENABLE_WERROR) +hide_variable(BENCHMARK_FORCE_WERROR) +hide_variable(BENCHMARK_USE_BUNDLED_GTEST) hide_variable(LIBRT) set_target_properties(benchmark benchmark_main PROPERTIES FOLDER "Extern") diff --git a/config/cmake/AddGoogletest.cmake b/config/cmake/AddGoogletest.cmake index df2c7ad726..0b4129f7e8 100644 --- a/config/cmake/AddGoogletest.cmake +++ b/config/cmake/AddGoogletest.cmake @@ -1,5 +1,5 @@ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Copyright (c) 2017-2023, Battelle Memorial Institute; Lawrence Livermore +# Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore # National Security, LLC; Alliance for Sustainable Energy, LLC. # See the top-level NOTICE for additional details. # All rights reserved. @@ -12,7 +12,7 @@ # output on failed tests without having to set an environment variable. # -set(gtest_version release-1.12.1) +set(gtest_version v1.14.0) string(TOLOWER "googletest" gtName) @@ -80,6 +80,7 @@ hide_variable(gtest_hide_internal_symbols) hide_variable(BUILD_GMOCK) hide_variable(BUILD_GTEST) hide_variable(INSTALL_GTEST) +hide_variable(GTEST_HAS_ABSL) set_target_properties(gtest gtest_main gmock gmock_main PROPERTIES FOLDER "Extern") diff --git a/config/cmake/BuildType.cmake b/config/cmake/BuildType.cmake index 80d2421eed..1397ad0682 100644 --- a/config/cmake/BuildType.cmake +++ b/config/cmake/BuildType.cmake @@ -1,5 +1,5 @@ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Copyright (c) 2017-2023, Battelle Memorial Institute; Lawrence Livermore +# Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore # National Security, LLC; Alliance for Sustainable Energy, LLC. # See the top-level NOTICE for additional details. # All rights reserved. diff --git a/config/cmake/CheckLatestCXXStandardOption.cmake b/config/cmake/CheckLatestCXXStandardOption.cmake index de9738b5be..8484aca690 100644 --- a/config/cmake/CheckLatestCXXStandardOption.cmake +++ b/config/cmake/CheckLatestCXXStandardOption.cmake @@ -1,5 +1,5 @@ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Copyright (c) 2017-2023, Battelle Memorial Institute; Lawrence Livermore +# Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore # National Security, LLC; Alliance for Sustainable Energy, LLC. # See the top-level NOTICE for additional details. # All rights reserved. @@ -21,6 +21,15 @@ if(CMAKE_CXX_STANDARD LESS 17) message(FATAL_ERROR "{$PROJECT_NAME} requires C++17 or greater") endif() +if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 13.0) + if(CMAKE_CXX_STANDARD LESS 20) + message( + FATAL_ERROR + " using gcc>=13.0 {$PROJECT_NAME} requires setting C++ standard to C++20 or greater" + ) + endif() +endif() + if(MSVC) if(CMAKE_CXX_STANDARD EQUAL 17) check_cxx_compiler_flag(/std:c++17 has_std_17_flag) diff --git a/config/cmake/FindZeroMQ.cmake b/config/cmake/FindZeroMQ.cmake index a0d339e3d7..07b92dc507 100644 --- a/config/cmake/FindZeroMQ.cmake +++ b/config/cmake/FindZeroMQ.cmake @@ -1,5 +1,5 @@ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Copyright (c) 2017-2020, Battelle Memorial Institute; Lawrence Livermore +# Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore # National Security, LLC; Alliance for Sustainable Energy, LLC. # See the top-level NOTICE for additional details. # All rights reserved. @@ -60,6 +60,7 @@ if(MSVC) if(${ZeroMQ_NAME} MATCHES "registry") # if key was not found, the string "registry" is returned set(_ZeroMQ_VERSIONS + "4_3_5" "4_3_4" "4_3_3" "4_3_2" @@ -71,13 +72,6 @@ if(MSVC) "4_2_2" "4_2_1" "4_2_0" - "4_1_5" - "4_1_4" - "4_0_4" - "4_0_3" - "4_0_2" - "4_0_1" - "4_0_0" ) set(ZeroMQ_LIBRARY_NAME) foreach(ver ${_ZeroMQ_VERSIONS}) diff --git a/config/cmake/addBoost.cmake b/config/cmake/addBoost.cmake index bbaa77feb4..aeacd0a426 100644 --- a/config/cmake/addBoost.cmake +++ b/config/cmake/addBoost.cmake @@ -1,5 +1,5 @@ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Copyright (c) 2017-2023, Battelle Memorial Institute; Lawrence Livermore +# Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore # National Security, LLC; Alliance for Sustainable Energy, LLC. # See the top-level NOTICE for additional details. # All rights reserved. @@ -14,6 +14,9 @@ mark_as_advanced(BOOST_INSTALL_PATH) if(WIN32 AND NOT UNIX_LIKE) set(boost_versions + boost_1_84_0 + boost_1_83_0 + boost_1_82_0 boost_1_81_0 boost_1_80_0 boost_1_79_0 @@ -67,16 +70,16 @@ if(WIN32 AND NOT UNIX_LIKE) ) if(BOOST_TEST_PATH) - set(BOOST_ROOT ${BOOST_TEST_PATH}) + set(Boost_ROOT ${BOOST_TEST_PATH}) endif(BOOST_TEST_PATH) else() - if(NOT BOOST_ROOT) + if(NOT Boost_ROOT) if(BOOST_INSTALL_PATH) - set(BOOST_ROOT "${BOOST_INSTALL_PATH}") + set(Boost_ROOT "${BOOST_INSTALL_PATH}") elseif($ENV{BOOST_INSTALL_PATH}) - set(BOOST_ROOT "$ENV{BOOST_INSTALL_PATH}") + set(Boost_ROOT "$ENV{BOOST_INSTALL_PATH}") else() - set(BOOST_ROOT "$ENV{BOOST_ROOT}") + set(Boost_ROOT "$ENV{BOOST_ROOT}") endif() endif() endif() diff --git a/config/cmake/addGitHooks.cmake b/config/cmake/addGitHooks.cmake index 3bc5883f15..a1db6220b0 100644 --- a/config/cmake/addGitHooks.cmake +++ b/config/cmake/addGitHooks.cmake @@ -1,5 +1,5 @@ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Copyright (c) 2017-2021, Battelle Memorial Institute; Lawrence Livermore +# Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore # National Security, LLC; Alliance for Sustainable Energy, LLC. # See the top-level NOTICE for additional details. # All rights reserved. @@ -7,7 +7,7 @@ # SPDX-License-Identifier: BSD-3-Clause # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -cmake_minimum_required(VERSION 3.4...3.20) +cmake_minimum_required(VERSION 3.4...3.28) set(CLANG_FORMAT_MIN_VERSION "7.0") function(set_git_hooks_enabled) diff --git a/config/cmake/addJsoncpp.cmake b/config/cmake/addJsoncpp.cmake index d22a1bc976..6304690c55 100644 --- a/config/cmake/addJsoncpp.cmake +++ b/config/cmake/addJsoncpp.cmake @@ -1,5 +1,5 @@ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Copyright (c) 2017-2023, Battelle Memorial Institute; Lawrence Livermore +# Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore # National Security, LLC; Alliance for Sustainable Energy, LLC. # See the top-level NOTICE for additional details. # All rights reserved. diff --git a/config/cmake/addMPI.cmake b/config/cmake/addMPI.cmake index 82fe9f6bf4..82d604dbdc 100644 --- a/config/cmake/addMPI.cmake +++ b/config/cmake/addMPI.cmake @@ -11,7 +11,7 @@ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # ~~~ -# Copyright (c) 2017-2019, Battelle Memorial Institute; Lawrence Livermore +# Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore # National Security, LLC; Alliance for Sustainable Energy, LLC. # See the top-level NOTICE for additional details. # All rights reserved. diff --git a/config/cmake/addNetworking.cmake b/config/cmake/addNetworking.cmake index c14568fcdb..5a511e08ae 100644 --- a/config/cmake/addNetworking.cmake +++ b/config/cmake/addNetworking.cmake @@ -1,5 +1,5 @@ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Copyright (c) 2017-2023, Battelle Memorial Institute; Lawrence Livermore +# Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore # National Security, LLC; Alliance for Sustainable Energy, LLC. # See the top-level NOTICE for additional details. # All rights reserved. diff --git a/config/cmake/addSpdlog.cmake b/config/cmake/addSpdlog.cmake index 8ff49ce11a..8b2e91eabf 100644 --- a/config/cmake/addSpdlog.cmake +++ b/config/cmake/addSpdlog.cmake @@ -1,5 +1,5 @@ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Copyright (c) 2017-2021, Battelle Memorial Institute; Lawrence Livermore +# Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore # National Security, LLC; Alliance for Sustainable Energy, LLC. # See the top-level NOTICE for additional details. # All rights reserved. @@ -52,5 +52,7 @@ if(NOT TARGET spdlog::spdlog) hide_variable(SPDLOG_INSTALL) hide_variable(SPDLOG_CLOCK_COARSE) hide_variable(SPDLOG_USE_STD_FORMAT) + hide_variable(SPDLOG_SYSTEM_INCLUDES) + hide_variable(SPDLOG_BUID_PIC) endif() endif() diff --git a/config/cmake/addUnits.cmake b/config/cmake/addUnits.cmake index d9f9f33173..3e96a24819 100644 --- a/config/cmake/addUnits.cmake +++ b/config/cmake/addUnits.cmake @@ -1,5 +1,5 @@ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Copyright (c) 2017-2023, Battelle Memorial Institute; Lawrence Livermore +# Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore # National Security, LLC; Alliance for Sustainable Energy, LLC. # See the top-level NOTICE for additional details. # All rights reserved. diff --git a/config/cmake/addUtilities.cmake b/config/cmake/addUtilities.cmake index f1c1c7efd0..2aabf68c25 100644 --- a/config/cmake/addUtilities.cmake +++ b/config/cmake/addUtilities.cmake @@ -1,5 +1,5 @@ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Copyright (c) 2017-2023, Battelle Memorial Institute; Lawrence Livermore +# Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore # National Security, LLC; Alliance for Sustainable Energy, LLC. # See the top-level NOTICE for additional details. # All rights reserved. diff --git a/config/cmake/addZeroMQ.cmake b/config/cmake/addZeroMQ.cmake index 64a90d88ad..1c17ac4ef0 100644 --- a/config/cmake/addZeroMQ.cmake +++ b/config/cmake/addZeroMQ.cmake @@ -1,5 +1,5 @@ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Copyright (c) 2017-2020, Battelle Memorial Institute; Lawrence Livermore +# Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore # National Security, LLC; Alliance for Sustainable Energy, LLC. # See the top-level NOTICE for additional details. # All rights reserved. diff --git a/config/cmake/addfmt.cmake b/config/cmake/addfmt.cmake index b109d0af8f..fa0e945904 100644 --- a/config/cmake/addfmt.cmake +++ b/config/cmake/addfmt.cmake @@ -1,5 +1,5 @@ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Copyright (c) 2017-2021, Battelle Memorial Institute; Lawrence Livermore +# Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore # National Security, LLC; Alliance for Sustainable Energy, LLC. # See the top-level NOTICE for additional details. # All rights reserved. @@ -38,6 +38,7 @@ if(NOT TARGET fmt::fmt) add_subdirectory(ThirdParty/fmtlib) set_target_properties(fmt PROPERTIES FOLDER Extern) + hide_variable(FMT_DOC) hide_variable(FMT_INSTALL) hide_variable(FMT_PEDANTIC) @@ -49,5 +50,8 @@ if(NOT TARGET fmt::fmt) hide_variable(FMT_INC_DIR) hide_variable(FMT_MODULE) hide_variable(FMT_SYSTEM_HEADERS) + hide_variable(FMT_PKGCONFIG_DIR) + hide_variable(FMT_CMAKE_DIR) + hide_variable(FMT_LIB_DIR) endif() endif() diff --git a/config/cmake/addlibzmq.cmake b/config/cmake/addlibzmq.cmake index 888448ec33..d6187b5bbd 100644 --- a/config/cmake/addlibzmq.cmake +++ b/config/cmake/addlibzmq.cmake @@ -1,5 +1,5 @@ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Copyright (c) 2019-2023, Battelle Memorial Institute; Lawrence Livermore +# Copyright (c) 2019-2024, Battelle Memorial Institute; Lawrence Livermore # National Security, LLC; Alliance for Sustainable Energy, LLC. # See the top-level NOTICE for additional details. # All rights reserved. @@ -19,7 +19,7 @@ else() set(zmq_shared_build ON) endif() -set(${PROJECT_NAME}_LIBZMQ_VERSION v4.3.4) +set(${PROJECT_NAME}_LIBZMQ_VERSION v4.3.5) string(TOLOWER "libzmq" lcName) @@ -120,6 +120,8 @@ hide_variable(ENABLE_ANALYSIS) hide_variable(ENABLE_ASAN) hide_variable(ENABLE_RADIX_TREE) hide_variable(ENABLE_EVENTFD) +hide_variable(ENABLE_LIBSODIUM_RANDOMBYTES_CLOSE) +hide_variable(ENABLE_NO_EXPORT) hide_variable(ZMQ_CV_IMPL) hide_variable(BUILD_TESTS) hide_variable(ENABLE_INTRINSICS) diff --git a/config/cmake/combineLicenses.cmake b/config/cmake/combineLicenses.cmake index 4dcb4fb691..377c16becc 100644 --- a/config/cmake/combineLicenses.cmake +++ b/config/cmake/combineLicenses.cmake @@ -1,5 +1,5 @@ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Copyright (c) 2017-2021, Battelle Memorial Institute; Lawrence Livermore +# Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore # National Security, LLC; Alliance for Sustainable Energy, LLC. # See the top-level NOTICE for additional details. # All rights reserved. diff --git a/config/cmake/commonBuildFlags.cmake b/config/cmake/commonBuildFlags.cmake index 007c83699c..a6fa78240d 100644 --- a/config/cmake/commonBuildFlags.cmake +++ b/config/cmake/commonBuildFlags.cmake @@ -1,5 +1,5 @@ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Copyright (c) 2017-2023, Battelle Memorial Institute; Lawrence Livermore +# Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore # National Security, LLC; Alliance for Sustainable Energy, LLC. # See the top-level NOTICE for additional details. # All rights reserved. diff --git a/config/cmake/commonBuildPaths.cmake b/config/cmake/commonBuildPaths.cmake index 06ff6efb91..0c5b72b52e 100644 --- a/config/cmake/commonBuildPaths.cmake +++ b/config/cmake/commonBuildPaths.cmake @@ -1,5 +1,5 @@ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Copyright (c) 2017-2023, Battelle Memorial Institute; Lawrence Livermore +# Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore # National Security, LLC; Alliance for Sustainable Energy, LLC. # See the top-level NOTICE for additional details. # All rights reserved. diff --git a/config/cmake/commonRPath.cmake b/config/cmake/commonRPath.cmake index 5e6e85b21c..e6e45bcf79 100644 --- a/config/cmake/commonRPath.cmake +++ b/config/cmake/commonRPath.cmake @@ -1,5 +1,5 @@ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Copyright (c) 2017-2023, Battelle Memorial Institute; Lawrence Livermore +# Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore # National Security, LLC; Alliance for Sustainable Energy, LLC. # See the top-level NOTICE for additional details. # All rights reserved. diff --git a/config/cmake/compiler_flags.cmake b/config/cmake/compiler_flags.cmake index e2196d10bf..c33b4020a9 100644 --- a/config/cmake/compiler_flags.cmake +++ b/config/cmake/compiler_flags.cmake @@ -1,5 +1,5 @@ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Copyright (c) 2017-2023, Battelle Memorial Institute; Lawrence Livermore +# Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore # National Security, LLC; Alliance for Sustainable Energy, LLC. # See the top-level NOTICE for additional details. # All rights reserved. @@ -72,9 +72,12 @@ target_compile_options(compile_flags_target INTERFACE ${${PROJECT_NAME}_EXTRA_CO target_compile_options(build_flags_target INTERFACE ${${PROJECT_NAME}_EXTRA_BUILD_FLAGS}) if(${PROJECT_NAME}_ENABLE_EXTRA_COMPILER_WARNINGS) - target_compile_options( - compile_flags_target INTERFACE $<$>:-Wall -pedantic> - ) + target_compile_options(compile_flags_target INTERFACE $<$>:-Wall>) + if(NOT WIN32) + # to support clang-cl which doesn't support these options + target_compile_options(compile_flags_target INTERFACE -pedantic) + + endif() target_compile_options( compile_flags_target INTERFACE $<$:$<$>:-Wextra @@ -116,22 +119,31 @@ if(${PROJECT_NAME}_ENABLE_EXTRA_COMPILER_WARNINGS) target_link_libraries(build_flags_target INTERFACE "stdc++fs") endif() + if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 13.0) + target_compile_options( + compile_flags_target INTERFACE $<$:-Wparentheses> + ) + endif() endif() if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang") target_compile_options(compile_flags_target INTERFACE $<$:-Wshadow>) target_compile_options( compile_flags_target INTERFACE -Wdocumentation -Wno-documentation-deprecated-sync ) - if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 13.0) - message(STATUS "clang>13") + if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 13.0) + message(STATUS "clang>=13") target_compile_options( compile_flags_target INTERFACE -Wreserved-identifier -Wunused-but-set-parameter -Wunused-but-set-variable ) endif() + endif() endif(${PROJECT_NAME}_ENABLE_EXTRA_COMPILER_WARNINGS) +if(WIN32 AND CMAKE_CXX_COMPILER_ID STREQUAL "Clang") + target_compile_options(compile_flags_target INTERFACE -Wno-reserved-identifier) +endif() # ------------------------------------------------------------- # Extra definitions for visual studio # ------------------------------------------------------------- diff --git a/config/cmake/copy_key_files.cmake b/config/cmake/copy_key_files.cmake index 3bd5d7fb5d..d7f4647a36 100644 --- a/config/cmake/copy_key_files.cmake +++ b/config/cmake/copy_key_files.cmake @@ -1,5 +1,5 @@ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Copyright (c) 2017-2020, Battelle Memorial Institute; Lawrence Livermore +# Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore # National Security, LLC; Alliance for Sustainable Energy, LLC. # See the top-level NOTICE for additional details. # All rights reserved. diff --git a/config/cmake/escape_string.cmake b/config/cmake/escape_string.cmake index 9a8773c462..2c7bd8fc6c 100644 --- a/config/cmake/escape_string.cmake +++ b/config/cmake/escape_string.cmake @@ -1,5 +1,5 @@ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Copyright (c) 2017-2020, Battelle Memorial Institute; Lawrence Livermore +# Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore # National Security, LLC; Alliance for Sustainable Energy, LLC. # See the top-level NOTICE for additional details. # All rights reserved. diff --git a/config/cmake/extraMacros.cmake b/config/cmake/extraMacros.cmake index ed51a2558d..9b4ad12c69 100644 --- a/config/cmake/extraMacros.cmake +++ b/config/cmake/extraMacros.cmake @@ -1,5 +1,5 @@ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Copyright (c) 2017-2023, Battelle Memorial Institute; Lawrence Livermore +# Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore # National Security, LLC; Alliance for Sustainable Energy, LLC. # See the top-level NOTICE for additional details. # All rights reserved. diff --git a/config/cmake/updateGitSubmodules.cmake b/config/cmake/updateGitSubmodules.cmake index 3d82712665..19e2602491 100644 --- a/config/cmake/updateGitSubmodules.cmake +++ b/config/cmake/updateGitSubmodules.cmake @@ -1,5 +1,5 @@ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Copyright (c) 2017-2023, Battelle Memorial Institute; Lawrence Livermore +# Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore # National Security, LLC; Alliance for Sustainable Energy, LLC. # See the top-level NOTICE for additional details. # All rights reserved. diff --git a/config/cmake/version_describe.cmake b/config/cmake/version_describe.cmake index f81ccee6da..283fd9ebc7 100644 --- a/config/cmake/version_describe.cmake +++ b/config/cmake/version_describe.cmake @@ -1,5 +1,5 @@ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Copyright (c) 2017-2023, Battelle Memorial Institute; Lawrence Livermore +# Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore # National Security, LLC; Alliance for Sustainable Energy, LLC. # See the top-level NOTICE for additional details. # All rights reserved. diff --git a/config/helics-config.h.in b/config/helics-config.h.in index f74e8c48da..71d0795dbc 100644 --- a/config/helics-config.h.in +++ b/config/helics-config.h.in @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/docs/CMakeLists.txt b/docs/CMakeLists.txt index b25fbe301d..f4db8b4c1d 100644 --- a/docs/CMakeLists.txt +++ b/docs/CMakeLists.txt @@ -1,5 +1,5 @@ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Copyright (c) 2017-2023, Battelle Memorial Institute; Lawrence Livermore +# Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore # National Security, LLC; Alliance for Sustainable Energy, LLC. # See the top-level NOTICE for additional details. # All rights reserved. @@ -37,7 +37,6 @@ if(MSVC) ${PROJECT_SOURCE_DIR}/CONTRIBUTORS.md ${PROJECT_SOURCE_DIR}/CONTRIBUTING.md ${PROJECT_SOURCE_DIR}/docs/Public_API.md - ${PROJECT_SOURCE_DIR}/docs/docker.md ${PROJECT_SOURCE_DIR}/docs/ROADMAP.md ) diff --git a/docs/Public_API.md b/docs/Public_API.md index 6599b13020..e7c1dfaa8e 100644 --- a/docs/Public_API.md +++ b/docs/Public_API.md @@ -30,7 +30,7 @@ The public API includes the following - CoreApp.hpp - timeOperations.hpp - typeOperations.hpp - - Exceptions: Translators and the global time coordinator option are in Beta and subject to finalization in the 3.4 release (they are mostly final and any changes will be highlighted). Vector subscriptions, and vector inputs are subject to change. The queries to retrieve JSON may update the format of the returned JSON in the future. A general note on queries: the data returned via queries is subject to change, though in general queries will not be removed. As determined by the need of HELICS users and applications, the data structure may change at minor revision numbers. We hope to fully document the queries structure in HELICS v3.4 at which point they will be stable for at least minor releases and changes will be noted. The callback federate API is considered in Beta and may change. + - Exceptions: Translators and the global time coordinator option are in Beta and subject to finalization in a later release (they are mostly final and any changes will be highlighted). Vector subscriptions, and vector inputs are subject to change. The queries to retrieve JSON may update the format of the returned JSON in the future. A general note on queries: the data returned via queries is subject to change, though in general queries will not be removed. As determined by the need of HELICS users and applications, the data structure may change at minor revision numbers. We hope to fully document the queries structure at which point they will be stable for at least minor releases and changes will be noted. The callback federate API is considered in Beta and may change. - Core library headers @@ -48,7 +48,6 @@ The public API includes the following - All C library operations are merged into a single header `helics.h` - A `helics_api.h` header is available for generating interfaces which strips out import declarations and comments. The C shared library API is the primary driver of versioning and changes to that will be considered in all versioning decisions. - - Translator and helicsData API's and methods are in Beta and subject to revision until the HELICS 3.3 release; comments or bugs are welcome, the 3.2.1 release includes updates to the API's and is mostly considered feature complete though still subject to revisions. - App Library @@ -59,6 +58,7 @@ The public API includes the following - Tracer.hpp - Probe.hpp - Clone.hpp + - Connector.hpp (considered in Beta and subject to change) - helicsApp.hpp - BrokerApp.hpp (aliased to application_api version) - CoreApp.hpp (aliased to application_api version) diff --git a/docs/ROADMAP.md b/docs/ROADMAP.md index a12fcc9720..5ca307557f 100644 --- a/docs/ROADMAP.md +++ b/docs/ROADMAP.md @@ -2,14 +2,20 @@ This document contains tentative plans for changes and improvements of note in upcoming versions of the HELICS library. All dates are approximate and subject to change, but this is a snapshot of the current planning thoughts. See the [projects](https://github.com/GMLC-TDC/HELICS/projects) for additional details -## \[3.5\] ~ Summer 2023 +## \[3.6\] ~ Summer 2024 - Single thread cores +- Update IPC core - Some of the other features listed below +- This release will likely update HELICS to use C++20 and update minimum Compilers, CMake, boost, and other dependencies. + - GCC 11 + - clang 14 + - CMake 3.22 + - MSVC 16.10 + - XCode 14 ## Nearer term features -- Update IPC core - Full xSDK compatibility - Separate Java Interface - Observer App diff --git a/docs/conf.py b/docs/conf.py index 034ae45013..29680fc38c 100755 --- a/docs/conf.py +++ b/docs/conf.py @@ -126,6 +126,8 @@ def ext_candidates(fpath): ] myst_dmath_double_inline = True +myst_heading_anchors = 5 + breathe_projects = { "helics": os.path.abspath(os.path.join(current_directory, "./../build-doxygen/docs/xml")), } @@ -141,7 +143,7 @@ def ext_candidates(fpath): # General information about the project. project = "HELICS" -copyright = "2017-2021 Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause. Documentation source in https://github.com/GMLC-TDC/HELICS" +copyright = "2017-2024 Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause. Documentation source in https://github.com/GMLC-TDC/HELICS" author = "Philip Top, Trevor Hardy, Ryan Mast, Dheepak Krishnamurthy, Andrew Fisher, Bryan Palmintier, Jason Fuller" # The version info for the project you're documenting, acts as replacement for @@ -158,12 +160,20 @@ def ext_candidates(fpath): # # This is also used if you do content translation via gettext catalogs. # Usually you set "language" from the command line for these cases. -language = None +language = "en" # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. # This patterns also effect to html_static_path and html_extra_path -exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"] +exclude_patterns = [ + "_build", + "Thumbs.db", + ".DS_Store", + "deprecated", + "404.md", + "swagger/docs/HELICS-api.md", + "user-guide/deprecated", +] # The name of the Pygments (syntax highlighting) style to use. pygments_style = "sphinx" diff --git a/docs/HELICS2_CHANGELOG.md b/docs/deprecated/HELICS2_CHANGELOG.md similarity index 100% rename from docs/HELICS2_CHANGELOG.md rename to docs/deprecated/HELICS2_CHANGELOG.md diff --git a/docs/developer-guide/Notes.md b/docs/deprecated/Notes.md similarity index 100% rename from docs/developer-guide/Notes.md rename to docs/deprecated/Notes.md diff --git a/docs/docker.md b/docs/deprecated/docker.md similarity index 100% rename from docs/docker.md rename to docs/deprecated/docker.md diff --git a/docs/doxygen/index.md b/docs/deprecated/doxygen/index.md similarity index 100% rename from docs/doxygen/index.md rename to docs/deprecated/doxygen/index.md diff --git a/docs/deprecated/running_interaction.md b/docs/deprecated/running_interaction.md new file mode 100644 index 0000000000..1974c2716f --- /dev/null +++ b/docs/deprecated/running_interaction.md @@ -0,0 +1 @@ +# Webserver diff --git a/docs/user-guide/troubleshooting.md b/docs/deprecated/troubleshooting.md similarity index 100% rename from docs/user-guide/troubleshooting.md rename to docs/deprecated/troubleshooting.md diff --git a/docs/developer-guide/typeConversions.md b/docs/developer-guide/typeConversions.md index cceb12a132..9c1c096b0e 100644 --- a/docs/developer-guide/typeConversions.md +++ b/docs/developer-guide/typeConversions.md @@ -145,32 +145,32 @@ Similar to getDoubleFromString in conversion of vectors. It will convert most re ### Conversion from vector double -- INT -> trunc(vectorNorm(val)) [^1] +- INT -> trunc(vectorNorm(val)) [^3] - DOUBLE -> vectorNorm(val) - COMPLEX -> val[0]+val[1]j - VECTOR -> val - COMPLEX_VECTOR -> [val[0],val[1],...,val[N]] -- STRING -> vectorString(val) [^2] -- NAMED_POINT -> {vectorString(val), NaN} [^3] +- STRING -> vectorString(val) [^4] +- NAMED_POINT -> {vectorString(val), NaN} [^5] - BOOL -> (vectorNorm(val)!=0)?"1":"0" -[^1]: vectorNorm is the sqrt of the inner product of the vector. -[^2]: vectorString is comma-separated string of the numerical values enclosed in `[]`, for example `[45.7,22.7,17.8]`. This is a JSON compatible string format. -[^3]: if the vector is a single element the NAMED_POINT translation is equivalent to a double translation. +[^3]: vectorNorm is the sqrt of the inner product of the vector. +[^4]: vectorString is comma-separated string of the numerical values enclosed in `[]`, for example `[45.7,22.7,17.8]`. This is a JSON compatible string format. +[^5]: if the vector is a single element the NAMED_POINT translation is equivalent to a double translation. ### Conversion from Complex Vector - INT -> trunc(vectorNorm(val)) - DOUBLE -> vectorNorm(val) - COMPLEX -> val[0] -- VECTOR -> [abs(val[0]),abs(val[1]),...abs(val[N])][^1] +- VECTOR -> [abs(val[0]),abs(val[1]),...abs(val[N])][^6] - COMPLEX_VECTOR -> val - NAMED_POINT -> {vectorString(val), NaN} - STRING -> complexVectorString(val) - BOOL -> (vectorNorm(val)!=0)?"1":"0" See [Conversion from vector double](#conversion-from-vector-double) for definitions of vectorNorm. -[^1]: if the imaginary part of these values is 0, then the real part is used; otherwise it uses the absolute value. +[^6]: if the imaginary part of these values is 0, then the real part is used; otherwise it uses the absolute value. ### Conversion from Complex diff --git a/docs/index.md b/docs/index.md index 353e771bea..e755bedd69 100644 --- a/docs/index.md +++ b/docs/index.md @@ -21,7 +21,7 @@ Motivation: Energy systems and their associated information and communication te .. toctree:: :maxdepth: 2 - + quick_start/quick_start_index user-guide/index developer-guide/index references/index diff --git a/docs/quick_start/quick_start_index.md b/docs/quick_start/quick_start_index.md new file mode 100644 index 0000000000..89f9f8a2df --- /dev/null +++ b/docs/quick_start/quick_start_index.md @@ -0,0 +1,47 @@ +# HELICS Quick Start + +If you just want to get a HELICS co-simulation running on your local machine and to see how it works for yourself, this is the place to start. This Quick Start Guide will get HELICS installed along with the Python interface along with the first fundamental example. You'll then be able to run it, see your results, and take a look at the code. And, of course, at the end of all of that you're puzzled as to what you actually did, we have a [whole Users's Guide](../user-guide/index.md) to get you up to speed. + +The commands below are are terminal/command-line tools available on Windows, Linux, and macOS. + +## Install HELICS and the Python Language Binding + +`pip install 'helics[cli]'` + +The HELICS User Guide predominantly uses Python as, in our experience, Python is the _lingua franca_ of the application-oriented (vs. computer science) computing world. The above command installs the Python language bindings for HELICS (allowing you to add `import helics` to any Python script) as well as a HELICS library. + +## Confirm installation + +`helics --version` should return something reasonable-looking, namely a version number followed by unique identifier for the release. + +## Clone in the HELICS Examples Repository + +`git clone https://github.com/GMLC-TDC/HELICS-Examples.git` + +OR + +[Download a copy of the repository](https://github.com/GMLC-TDC/HELICS-Examples/archive/refs/heads/main.zip) (if you're not familiar with Git.) + +The HELICS Examples repository contains all the examples for the User Guide (and other example content as well). Cloning or downloading this repository will give you a local copy of all those examples. + +## Navigate to the "Fundamental Default" example + +We'll be running the first example in the User Guide. From the top level of the HELICS Examples repository follow this path: + +`user_guide_examples/fundamental/fundamental_default` + +## Run the Fundamental Default Example + +`helics run --path=fundamental_default_runner.json` + +The `helics run` command provides an easy way to launch a co-simulation based on the contents of the runner file ("fundamental_default_runner.json" in this case). In this case, the runner launches two Python federates created for this example, "Battery.py" (which models five EV batteries) and "Charger.py" (which models five EV chargers). You should a few graphs that look like this: + +![](https://github.com/GMLC-TDC/helics_doc_resources/raw/main/user_guide/fundamental_default_resultbattery.png) +![](https://github.com/GMLC-TDC/helics_doc_resources/raw/main/user_guide/fundamental_default_resultcharger.png) + +## Next Steps + +- Look through the code of ["Battery.py"](https://github.com/GMLC-TDC/HELICS-Examples/blob/main/user_guide_examples/fundamental/fundamental_default/Battery.py) and/or ["Charger.py"](https://github.com/GMLC-TDC/HELICS-Examples/blob/main/user_guide_examples/fundamental/fundamental_default/Charger.py) to see how they work. +- If you're a little confused, look at the [documentation on the Fundamental Default example](../user-guide/examples/fundamental/fundamental_default.md) +- If you're still a little confused, start from [the beginning of the User Guide](../user-guide/index.md) to better understand HELICS principles and concepts. +- If this is all making sense now, [try running another example](../user-guide/examples/supported_language_examples_index.md) to better understand some of the other features of HELICS. diff --git a/docs/references/api-reference/CPP.md b/docs/references/api-reference/CPP.md new file mode 100644 index 0000000000..7dc6a05a02 --- /dev/null +++ b/docs/references/api-reference/CPP.md @@ -0,0 +1,3 @@ +# C++ API Reference (Doxygen) + +The latest Doxygen generated docs for the C++ API can be found at [https://docs.helics.org/en/latest/doxygen/index.html](https://docs.helics.org/en/latest/doxygen/index.html) diff --git a/docs/references/api-reference/index.md b/docs/references/api-reference/index.md index eaf7a0777d..1efb7d57fa 100644 --- a/docs/references/api-reference/index.md +++ b/docs/references/api-reference/index.md @@ -2,23 +2,24 @@ ```{eval-rst} .. toctree:: - :hidden: :maxdepth: 1 C_API + CPP + rest_queries_api ``` -## [C++ API (doxygen)](../../doxygen/index.md) - -## [C API](./C_API.md) +## [C API](./C_API) ## [Python API](https://python.helics.org/api/) -## [matHELICS API](./C_API.md) +## [matHELICS API](./C_API) + +There's no dedicated documentation for the matHELICS API at this time as the API is virtually identical to the other higher level languages such as [Python](https://python.helics.org/api/) and [Julia](https://julia.helics.org/stable/). Of particular note, as in those two languages, matHELICS supports the use of complex as a native data type. So `helicsInputGetComplex()` returns a complex value not a list of two floats, one for the real and one for the imaginary. -There's no dedicated documentation for the matHELICS API at this time. Refer to the [documentation on the C API](./C_API.md) (on which it is based) for function names. The [Python API and its documentation](https://python.helics.org/api/) is also based on the C API and can be a useful reference as well. +There is also inline documentation in the [source code files](https://github.com/GMLC-TDC/matHELICS/tree/main/matlabBindings/%2Bhelics) that may be helpful in providing insight. ## [Julia API](https://gmlc-tdc.github.io/HELICS.jl/latest/api/) -## [REST Queries API](./rest_queries_api.md) +## [REST Queries API](https://docs.helics.org/en/latest/references/api-reference/rest_queries_api.html) diff --git a/docs/references/apps/Connector.md b/docs/references/apps/Connector.md new file mode 100644 index 0000000000..9d6c3a48b1 --- /dev/null +++ b/docs/references/apps/Connector.md @@ -0,0 +1,248 @@ +# Connector + +The Connector app can automatically connect interfaces together. It does this using the query mechanisms inside HELICS to detect all the unconnected interfaces in a cosimulation. Then using given configuration rules it will establish connections between those interfaces. + +It can also run in a two-phase mode to have the federates create then connect interfaces. In the first phase, the connector app will query the federates for their potential interfaces and then go through those interfaces to see if there is a potential connection to be made using the same rules. If a potential interface has a connection available, it will send a command to the appropriate federate to create the interface. Once the interfaces exist, the Connector enters the second phase and makes the requested connections from the new and existing unconnected interfaces. + +## Connector configuration + +The main mechanism to load connection information is through configuration files called "match-files", typically a plain text file. The format is: + +` <*direction> <*tags...>` + +"origin" is the interface that is currently unconnected and "target" is the interface to connect it to. "direction" is optional and is assumed to be bidirectional matching ("bi"); in this case the direction of the match does not indicate the flow of the data but rather which interface is unmatched (the "from"). For example, if the match string looked like "V_out, V_in from_to" the Connector treats "V_out" as unconnected and will match it with "V_in" even if "V_in" is already connected. Bidrectional matching allows either interface to be unconnected to create a match. + +"tags" are optional and allow for filtering the candidate connections; see below for further details on their use. Comments lines are supported and begin with `#`. Currently only publications, inputs, and endpoints are supported for matching by Connector. + +Here's a simple example of a plain text match-file. + +```text +#comment line for simple file test +inp1 pub1 from_to +``` + +The following example uses a cascaded matching definition. + +```text +# comment line for cascade file test +# second comment line +inp1 intermediate1 +intermediate1 intermediate1 bi +intermediate1 intermediate2 from_to +intermediate2 intermediate3 from_to +# comment line in the middle +intermediate3 pub1 bi +inp2 intermediate2 from_to +publication3 input3 to_from +``` + +The following example uses tags in the matching process, see more on tags below. + +```text +#comment line for simple file test +inp1 pub1 from_to tag1 +inp2 pub1 tag2 tag3 +``` + +The match-file can also be JSON formatted. + +```json +{ + "connections": [ + ["inp1", "pub1", "FROM_TO", "tag1"], + ["inp2", "pub2", "tag2", "tag3"] + ] +} +``` + +## Notes on Tags + +- Connections specified with no tags or "default" tag will match with everything as if the tag were not there. If a connection specified by a match in the match-file uses a tag, a connection will only be made if the specified tag is used by a federate, core, or broker. +- A tag can be specified by a "global_value". The tag used for the connector is the name of the global or tag and the value can be anything other than a "false" value; if the tag is specified with a "false" value it is not used in the matching. Tags used in the match-file can also be specified in the value of the "tags" global or local tag. In this case they are specified with a comma separated list. The complete list of "false" valued strings is as follows: + +```txt + "0", "", "false", + "False", "FALSE", "off", + "Off", "OFF", "disabled", + "Disabled", "DISABLED", "disable", + "Disable", "DISABLE", "f", + "F", "0", std::string_view(reinterpret_cast(&nullstringRep), 1), + " ", "no", "NO", + "No", "-" +``` + +## Regular Expression (regex) Matching + +In addition to directly defining the connections to be made between interfaces, one-by-one, it is also possible to use regular expressions to define the connections. Regular expressions allow a large number of similarly-name interfaces to be matched with a single statement. The file is formatted as follows: + +```text +REGEX:pub_num_(?\d*)_(?[A-Za-z]*), REGEX:input_num_(?\d*)_(?[A-Za-z]*) +``` + +In this example, "interface_num" and "alpha_index" are user-defined strings that gives a name to the portion of the regex that needs to match. The funny stuff immediately after it ("\d*", "[A-Za-z]*") is the regular expression proper that the regular expression will use to determine how to make matches. Using the above example, the following matches would be made: + +```text +pub_num_1_a input_num_1_a +pub_num_204_voltage input_num_204_voltage +``` + +Writing regular expressions quickly and accurately is a learned skill and depending the names of the interfaces, it can be difficult to craft one that does exactly what you need. The use of tags may be helpful in preventing matches between federates when they are not needed. Additionally, it may be easier to write a regular expression that makes most of the matches you need and then use direct matches for the remainder. + +## Interface Creation and Matching + +As mentioned in the introduction, it is also possible for the Connector app to interact with federates that are created with no exposed interfaces and jointly work through a process where those interfaces are created and then connected. A [Python example](https://github.com/GMLC-TDC/HELICS-Examples/tree/53bece298f9be952002e2f9201f24922fabc73b4/user_guide_examples/advanced/advanced_connector/interface_creation) of this process in action can be found in the [HELICS Examples repository](https://github.com/GMLC-TDC/HELICS-Examples) but a conceptual overivew of the process is as follows: + +### Federate creation + +On launch of the federation, the federates are created with no exposed interfaces BUT with an understanding of what interfaces it can create. These interfaces may, for example, be hard-coded or based on the system model it reads on start-up. + +### Interface Query + +The Connector queries the federates to determine which interfaces each one can create. The query is made after the federate enter initializing mode and the federate must enter initializing mode iteratively (`helicsFederateEnterInitializingModeIterative()`) to synchronize the query responses across the federation. Every federate that is going to create interfaces needs to register a callback function to handle this custom query by the Connector and respond appropriately. The Connector will query the federate with "potential_interfaces" and the federate must respond with a properly formatted JSON: + +```json +{ + "publications": [] + "inputs": [] + "endpoints": [] +} +``` + +As this is a query operation, which are executed asynchronously with the simulation time, it is undefined when the query will be made and thus a callback function must be used to respond to the query. + +### Connector Interface Creation Command + +After receiving the query responses from all the federates, the connector performs its standard matching operation using a match-file. Once the matches are made, it determines which connections need to be made and sends a command to each federate telling it which interfaces to create. As with the query, the commands are received asynchronously but are guaranteed to be present after calling `helicsFederateEnterInitializingModeIterative()` twice. At that point, the federate can get the command and parse the returned JSON to determine which interfaces to create. The format is the same as the query response: + +```json +{ + "publications": [] + "inputs": [] + "endpoints": [] +} +``` + +### Interface Creation and Co-Simulation Execution + +The federate takes the JSON command and, using its own internal knowledge of the interface (global or not, data type, units) and creates the interfaces. After that, the federate doesn't need to do anything else for the interface connections to be connected and can call `helicsFederateEnterExecutingMode()` (assuming it has nothing else to do as a part of initializing). The Connector will make the connections between the interfaces as they are created and when complete, exit the federation. + +## Use of the Connector + +To use the Connector to create the interface connections, simply call it as part of your federation, adding the matchfile as a command-line argument. The connector app will start up when the federation is launched and, using the match-file, create the connections between interfaces behind the scenes. Once the work it complete (by the "execution" mode of the federation), it exits the federation and allows now connected federates to proceed. A sample call looks like: + +```sh +helics_connector matchfile.txt +``` + +## Command line arguments + +Options specific to the connector are as follows: + +```text +Options: + --version Display program version information and exit + --connection [INTERFACE1,INTERFACE2,DIRECTIONALITY,TXT...] ... + specify connections to make in the cosimulation + --match_target_endpoints set to true to enable connection of unconnected target endpoints + --match_multiple set to true to enable matching of multiple connections (default false) + --always_check_regex set to true to enable regex matching even if other matches are defined +``` + +The full CLI list is shown below including helics connection options and general options. + +```text +Common options for all Helics Apps +Usage: [HELICS_APP] [OPTIONS] [input] + +Positionals: + input TEXT:FILE The primary input file + +Options: + -h,-?,--help Print this help message and exit + --config-file,--config [helics_config.toml] + specify base configuration file + --version Display program version information and exit + --local Specify otherwise unspecified endpoints and publications as local (i.e. the names will be prepended with the player name) + --stop TIME The time to stop the app + --input TEXT:FILE The primary input file +[Option Group: quiet] + Options: + --quiet silence most print output +[Option Group: Subcommands] + Federate Info Parsing + Positionals: + config [helicsConfig.ini] specify a configuration file + Options: + --version Display program version information and exit + --config-file,--config [helicsConfig.ini] + specify a configuration file + --config_section TEXT specify the section of the config file to use + --config_index INT specify the section index of the config file to use for configuration arrays + -n,--name TEXT name of the federate + --corename TEXT the name of the core to create or find + -i,--coreinitstring TEXT (Env:HELICS_CORE_INIT_STRING) + The initialization arguments for the core + --brokerinitstring TEXT The initialization arguments for the broker if autogenerated + --broker,--brokeraddress TEXT + address or name of the broker to connect + --brokerport INT:POSITIVE Port number of the Broker + --port INT:POSITIVE Specify the port number to use + --localport TEXT Port number to use for connections to this federate + --autobroker tell the core to automatically generate a broker if needed + --debugging tell the core to allow user debugging in a nicer fashion + --observer tell the federate/core that this federate is an observer + --allow_remote_control,--disable_remote_control{false} + enable the federate to respond to certain remote operations such as disconnect + --json tell the core and federate to use JSON based serialization for all messages, to ensure compatibility + --profiler TEXT [log] Enable profiling and specify a file name (NOTE: use --profiler_append= in the core init string to append to an existing file) + --broker_key,--brokerkey,--brokerKey TEXT + specify a key to use to match a broker should match the broker key + --offset TIME the offset of the time steps (default in ms) + --period TIME the execution cycle of the federate (default in ms) + --stoptime TIME the maximum simulation time of a federate (default in ms) + --timedelta TIME The minimum time between time grants for a Federate (default in ms) + --inputdelay TIME the INPUT delay on incoming communication of the federate (default in ms) + --outputdelay TIME the output delay for outgoing communication of the federate (default in ms) + --grant_timeout TIME timeout to trigger diagnostic action when a federate time grant is not available within the timeout period (default in ms) + --maxiterations INT:POSITIVE + the maximum number of iterations a federate is allowed to take + --loglevel INT:{summary,none,connections,no_print,profiling,interfaces,error,timing,warning,data,debug,trace}:value in {summary->6,none->-4,connections->9,no_print->-4,profiling->2,interfaces->12,error->0,timing->15,warning->3,data->18,debug->21,trace->24} OR {6,-4,9,-4,2,12,0,15,3,18,21,24} (Env:HELICS_LOG_LEVEL) + the logging level of a federate + --separator CHAR [/] separator character for local federates + -f,--flags,--flag ... named flag for the federate + [Option Group: quiet] + Options: + --quiet silence most print output + [Option Group: network type] + Options: + --core TEXT [()] type or name of the core to connect to + --force_new_core if set to true will force the federate to generate a new core + -t,--coretype TEXT [()] (Env:HELICS_CORE_TYPE) + type of the core to connect to + [Option Group: encryption] + options related to encryption + Options: + --encrypted (Env:HELICS_ENCRYPTION) + enable encryption on the network + --encryption_config TEXT (Env:HELICS_ENCRYPTION_CONFIG) + set the configuration file for encryption options + [Option Group: realtime] + Options: + --rtlag TIME the amount of the time the federate is allowed to lag realtime before corrective action is taken (default in ms) + --rtlead TIME the amount of the time the federate is allowed to lead realtime before corrective action is taken (default in ms) + --rttolerance TIME the time tolerance of the real time mode (default in ms) +Command line options for the Connector App +Usage: [OPTIONS] + +Options: + --version Display program version information and exit + --connection [INTERFACE1,INTERFACE2,DIRECTIONALITY,TXT...] ... + specify connections to make in the cosimulation + --match_target_endpoints set to true to enable connection of unconnected target endpoints + --match_multiple set to true to enable matching of multiple connections (default false) + --always_check_regex set to true to enable regex matching even if other matches are defined +``` + +also permissible are all arguments allowed for federates and any specific broker specified: + +[Command line reference](cmdArgs.md) diff --git a/docs/references/apps/index.md b/docs/references/apps/index.md index 1a9d8e4ec6..126856db76 100644 --- a/docs/references/apps/index.md +++ b/docs/references/apps/index.md @@ -16,4 +16,5 @@ Included with HELICS are a number of apps that provide useful utilities and test Broker BrokerServer Clone + Connector ``` diff --git a/docs/references/configuration_options_reference.md b/docs/references/configuration_options_reference.md index 8d2b5eb6d2..6f72173179 100644 --- a/docs/references/configuration_options_reference.md +++ b/docs/references/configuration_options_reference.md @@ -27,17 +27,17 @@ Which method you use to configure your federate and co-simulation significantly - `helicsCreateValueFederateFromConfig` [C++](https://docs.helics.org/en/latest/doxygen/helics_8h.html#ad5dc3f4a7034ae800c67946faf2ce839) | [C](api-reference/C_API.md#creation) - | [Python](https://python.helics.org/api/capi-py.html#helicsCreateValueFederateFromConfig) + | [Python](https://python.helics.org/api/capi-py/#helicsCreateValueFederateFromConfig) | [Julia](https://julia.helics.org/latest/api/#HELICS.helicsCreateValueFederateFromConfig-Tuple{String}) - `helicsCreateMessageFederateFromConfig` [C++](https://docs.helics.org/en/latest/doxygen/helics_8h.html#a8d992360400e996c083c0b3a1d75b8f0) | [C](api-reference/C_API.md#creation) - | [Python](https://python.helics.org/api/capi-py.html#helicsCreateMessageFederateFromConfig) + | [Python](https://python.helics.org/api/capi-py/#helicsCreateMessageFederateFromConfig) | [Julia](https://julia.helics.org/latest/api/#HELICS.helicsCreateMessageFederateFromConfig-Tuple{String}) - `helicsCreateCombinationFederateFromConfig` [C++](https://docs.helics.org/en/latest/doxygen/helics_8h.html#a758381aad8bd5f9d0925a8b13ee04a1d) | [C](api-reference/C_API.md#creation) - | [Python](https://python.helics.org/api/capi-py.html#helicsCreateCombinationFederateFromConfig) + | [Python](https://python.helics.org/api/capi-py/#helicsCreateCombinationFederateFromConfig) | [Julia](https://julia.helics.org/latest/api/#HELICS.helicsCreateCombinationFederateFromConfig-Tuple{String}) - **JSON configuration produces a natural artifact that defines the co-simulation** - Another advantage of the external configuration in the JSON file is that it is a human-readable artifact that can be distributed separately from the source code that provides a lot of information about how the co-simulation was run. In fact, its possible to just look at the configuration files of a federation and do some high-level debugging (checking to see that the subscriptions and publications are aligned, for example). - **New federates in ill-defined use cases may benefit from API configuration** - The modularity that the JSON config provides may not offer many benefits if the federate is newly integrated into HELICS and/or is part of an evolving analysis. During these times the person(s) doing the integration may just want to make direct API calls instead of having to mess with writing the federate code and a configuration file. There will likely be a point in the future when the software is more codified and switching to a JSON configuration makes more sense. @@ -71,13 +71,14 @@ An example of one publication, subscription, named input, endpoint, and filter i "core_init_string" : "", "autobroker": false, "connection_required": false, - "connection_optional": false, + "connection_optional": true, "strict_input_type_checking": false, "terminate_on_error": false, "source_only": false, "observer": false, "only_update_on_change": false, "only_transmit_on_change": false, + "broker_key": "", //Logging "logfile": "output.log" @@ -144,6 +145,7 @@ An example of one publication, subscription, named input, endpoint, and filter i "connection_optional": true, "connection_required": false, "tolerance": -1, + // for targets can be singular or plural, if an array must use plural form "targets": "", "buffer_data": false, indication the publication should buffer data "strict_input_type_checking": false, @@ -171,6 +173,7 @@ An example of one publication, subscription, named input, endpoint, and filter i "single_connection_only": false, "multiple_connections_allowed": false "multi_input_handling_method": "average", + // for targets can be singular or plural, if an array must use plural form "targets": ["pub1", "pub2"] "default": 5.5, } @@ -200,6 +203,16 @@ An example of one publication, subscription, named input, endpoint, and filter i } } ] + "translators": [ + { + "name": "translator name", + // can use singular form if only a single target + "source_target": "publication name", + "destination_targets": "endpoint name", + "info": "", + "type": "JSON", + } + ] } ``` @@ -212,44 +225,50 @@ There are a number of flags which control how a federate acts with respect to ti _API:_ `helicsFederateInfoSetCoreName` [C++](https://docs.helics.org/en/latest/doxygen/helics_8h.html#a1fc4b4563bd06ac54d9569d1df5f8d0c) | [C](api-reference/C_API.md#federateinfo) -| [Python](https://python.helics.org/api/capi-py.html#helicsFederateInfoSetCoreName) -| [Julia](https://julia.helics.org/latest/api/#HELICS.helicsFederateInfoSetCoreName-Tuple{HELICS.FederateInfo,String}) +| [Python](https://python.helics.org/api/capi-py/#helicsFederateInfoSetCoreName) +| [Julia](https://julia.helics.org/latest/api/#HELICS.helicsFederateInfoSetCoreName-Tuple{HELICS.FederateInfo,%20String}) Every federate must have a unique name across the entire federation; this is functionally the address of the federate and is used to determine where HELICS messages are sent. An error will be generated if the federate name is not unique. --- -### `core_type` | `coretype` | `coreType` | `-t` ["zmq"] +### `core_type` | `-t` ["zmq"] + +_Alternative names:_ `coretype` | `coreType` _API:_ `helicsFederateInfoSetCoreTypeFromString` -[C++](https://docs.helics.org/en/latest/doxygen/classhelicscpp_1_1FederateInfo.html#a94654cba67de8d4aaf47cd99bbbd5d60) +[C++](https://docs.helics.org/en/latest/doxygen/classhelics_1_1BasicFedInfo.html#a1597a91e6783094a6cf29bd4d0493785) | [C](api-reference/C_API.md#federateinfo) -| [Python](https://python.helics.org/api/capi-py.html#helicsFederateInfoSetCoreTypeFromString) -| [Julia](https://julia.helics.org/latest/api/#HELICS.helicsFederateInfoSetCoreType-Tuple{HELICS.FederateInfo,Union{Int64,%20HELICS.Lib.helics_core_type}}) +| [Python](https://python.helics.org/api/capi-py/#helicsFederateInfoSetCoreTypeFromString) +| [Julia](https://julia.helics.org/latest/api/#HELICS.helicsFederateInfoSetCoreType-Tuple{HELICS.FederateInfo,%20Union{Int64,%20HELICS.Lib.HelicsCoreTypes}}) There are a number of technologies or message buses that can be used to send HELICS messages among federates. Every HELICS enabled simulator has code in it that creates a core which connects to a HELICS broker using one of these messaging technologies. ZeroMQ (zmq) is the default core type and most commonly used but there are also cores that use TCP and UDP networking protocols directly (forgoing ZMQ's guarantee of delivery and reconnection functions), IPC (uses Boost's interprocess communication for fast in-memory message-passing but only works if all federates are running on the same physical computer), and MPI (for use on HPC clusters where MPI is installed). See the [User Guide page on core types](../user-guide/advanced_topics/CoreTypes.md) for more details. --- -### `core_name` | `corename` | `coreName` [] +### `core_name` [HELICS-generated] + +_Alternative names:_ `corename` | `coreName` _API:_ helicsFederateInfoSetCoreName -[C++](https://docs.helics.org/en/latest/doxygen/helics_8h.html#a1fc4b4563bd06ac54d9569d1df5f8d0c) +[C++](https://docs.helics.org/en/latest/doxygen/classhelics_1_1FederateInfo.html#abb18967525d94a2a98c1d30be12fcedc) | [C](api-reference/C_API.md#federateinfo) -| [Python](https://python.helics.org/api/capi-py.html#helicsFederateInfoSetCoreName) -| [Julia](https://julia.helics.org/latest/api/#HELICS.helicsFederateInfoSetCoreName-Tuple{HELICS.FederateInfo,String}) +| [Python](https://python.helics.org/api/capi-py/#helicsFederateInfoSetCoreName) +| [Julia](https://julia.helics.org/latest/api/#HELICS.helicsFederateInfoSetCoreName-Tuple{HELICS.FederateInfo,%20String}) Only applicable for `ipc` and `test` core types; otherwise can be left undefined. --- -### `core_init_string` | `coreinitstring` | `coreInitString` | `-i` [] +### `core_init_string` | `-i` [null] + +_Alternative names:_ `coreinitstring` | `coreInitString` _API:_ `helicsFederateInfoSetCoreInitString` -[C++](https://docs.helics.org/en/latest/doxygen/helics_8h.html#a472ea0a8ff1a57d91bfa01b04137e2a8) +[C++](https://docs.helics.org/en/latest/doxygen/classhelics_1_1FederateInfo.html#ac466e079d28d9bf2fabb065ba0372b70) | [C](api-reference/C_API.md#federateinfo) -| [Python](https://python.helics.org/api/capi-py.html#helicsFederateInfoSetCoreInitString) -| [Julia](https://julia.helics.org/latest/api/#HELICS.helicsFederateInfoSetCoreInitString-Tuple{HELICS.FederateInfo,String}) +| [Python](https://python.helics.org/api/capi-py/#helicsFederateInfoSetCoreInitString) +| [Julia](https://julia.helics.org/latest/api/#HELICS.helicsFederateInfoSetCoreInitString-Tuple{HELICS.FederateInfo,%20String}) A command-line-like string that specifies options for the core as it connects to the federation. These options are: @@ -275,13 +294,15 @@ Automatically generate a broker if one cannot be connected to. For federations w --- -### `broker_init_string` | `brokerinitstring` | `brokerInitString` [""] +### `broker_init_string` [null] + +_Alternative names:_ `brokerinitstring`, `brokerInitString` _API:_ `helicsFederateInfoSetBrokerInitString` -[C++](https://docs.helics.org/en/latest/doxygen/helics_8h.html#a1f145624be99cd3261d4ad1314785e2c) +[C++](https://docs.helics.org/en/latest/doxygen/classhelics_1_1FederateInfo.html#a167ad88f2315f46d6edcf920325b8ad0) | [C](api-reference/C_API.md#federateinfo) -| [Python](https://python.helics.org/api/capi-py.html#helicsFederateInfoSetBrokerInitString) -| [Julia](https://julia.helics.org/latest/api/#HELICS.helicsFederateInfoSetBrokerInitString-Tuple{HELICS.FederateInfo,String}) +| [Python](https://python.helics.org/api/capi-py/#helicsFederateInfoSetBrokerInitString) +| [Julia](https://julia.helics.org/latest/api/#HELICS.helicsFederateInfoSetBrokerInitString-Tuple{HELICS.FederateInfo,%20String}) String used to define the configuration of the broker if one is autogenerated. Such configuration typically includes things like broker IP addresses and port numbers. Again, if this is a co-simulation running on a single computer (and is the only HELICS co-simulation running on said computer) the default option is likely to be sufficient. The following options are available for this string: @@ -302,7 +323,10 @@ String used to define the configuration of the broker if one is autogenerated. S - `--dumplog` - Captures a record of all logging messages and writes them out to file or console when the broker terminates. - `--globaltime` - Specify that the broker should use a globalTime coordinator to coordinate a master clock time with all federates. - `--asynctime` - Specify that the federation should use the asynchronous time coordinator (only minimal time management is handled in HELICS and federates are allowed to operate independently). -- `--timing = ("async"|"global"|"default"|"distributed")` - specify the timing mode to use for time coordination +- `--timing = ("async"|"global"|"default"|"distributed")` - specify the timing mode to use for time coordination. + - `distributed` - Time management is distributed and managed by each federates. This is the default + - `global` - HELICS centrally manages the time coordination; for larger federations this is likely to be slower + - `async` - federates manage their own time with minimal coordination from HELICS (such as when using real-time simulators) - `--tick=` - Heartbeat period in ms. When brokers fail to respond after 2 ticks secondary actions are taking to confirm the broker is still connected to the federation. Times can also be entered as strings such as "15s" or "75ms". - `--timeout=` milliseconds to wait for all the federates to connect to the broker (can also be entered as a time like '10s' or '45ms') - `--network_timeout=` - Time to establish a socket connection in ms. Times can also be entered as strings such as "15s" or "75ms". @@ -315,17 +339,24 @@ String used to define the configuration of the broker if one is autogenerated. S - `--brokerkey=` - A broker key to use for connections to ensure federates are connecting with a specific broker and only appropriate federates connect with the broker. See [simultaneous co-simulations](../user-guide/advanced_topics/simultaneous_cosimulations.md) for more information. - `--profiler=log` - Send the profiling messages to the default logging file. `log` can be replaced with a path to an alternative file where only the profiling messages will be sent. See the [User Guide page on profiling](../user-guide/advanced_topics/profiling.md) for further details. If a file is specified it is cleared. - `--profiler_append=somefile.txt` - Send the profiling messages to file and leave the existing contents appending new data. See the [User Guide page on profiling](../user-guide/advanced_topics/profiling.md) for further details. -- `--timemonitor=` - Specify the name of the federate to monitor the time from and generate periodic log messages in the broker as the federate updates its time. -- `--timemonitorperiod=` - can only be used with `--timemonitor`, set the minimum time period which must elapse in simulation before another log message from the time monitor is generated +- `--time_monitor=` - Specify the name of the federate to monitor the time from and generate periodic log messages in the broker as the federate updates its time. +- `--time_monitor_period=` - can only be used with `--time_monitor`, set the minimum time period which must elapse in simulation before another log message from the time monitor is generated +- `--disable_timer` - Disables all timeout in broker operation +- `--debugging` - Equivalent to `--slow_responding --disable_timer` - `--logbuffer` - Enable buffering recent log messages for retrieval with the "logs" query. Optionally specify the size of the circular log buffer; defaults to 10 messages if no size is supplied. +- `--allow_remote_control` - Enables the broker to respond to certain remote commands such as "disconnect" +- `--dynamic` - Allow for dynamic federations where federates can join after the co-simulation has begun. This capability is disabled by default. +- `--disable_dynamic_sources` - Prevents data sources from registering after the federation has entered initializing mode. This capability is **enabled** by default + +### `terminate_on_error` [false] -### `terminate_on_error` | `terminateonerror` | `terminateOnError` [false] +_Alternative names:_ `terminateonerror`, `terminateOnError` _API:_ `helicsFederateInfoSetFlagOption` [C++](https://docs.helics.org/en/latest/doxygen/classhelics_1_1CoreFederateInfo.html#a63efa7762fdc8a9d9869bbed6939448e) | [C](api-reference/C_API.md#federateinfo) -| [Python](https://python.helics.org/api/capi-py.html#helicsFederateInfoSetFlagOption) -| [Julia](https://julia.helics.org/latest/api/#HELICS.helicsFederateInfoSetFlagOption-Tuple{HELICS.FederateInfo,Union{Int64,%20HELICS.Lib.helics_federate_flags},Bool}) +| [Python](https://python.helics.org/api/capi-py/#helicsFederateInfoSetFlagOption) +| [Julia](https://julia.helics.org/latest/api/#HELICS.helicsFederateInfoSetFlagOption-Tuple{HELICS.FederateInfo,%20Union{Int64,%20HELICS.Lib.HelicsFederateFlags},%20Bool}) _Property's enumerated name:_ `HELICS_FLAG_TERMINATE_ON_ERROR` [72] @@ -333,13 +364,15 @@ If the `terminate_on_error` flag is set then a federate encountering an internal --- -### `source_only` | `sourceonly` | `sourceOnly` [false] +### `source_only` | [false] + +_Alternative names:_ `sourceonly`, `sourceOnly` _API:_ `helicsFederateInfoSetFlagOption` [C++](https://docs.helics.org/en/latest/doxygen/classhelics_1_1CoreFederateInfo.html#a63efa7762fdc8a9d9869bbed6939448e) | [C](api-reference/C_API.md#federateinfo) -| [Python](https://python.helics.org/api/capi-py.html#helicsFederateInfoSetFlagOption) -| [Julia](https://julia.helics.org/latest/api/#HELICS.helicsFederateInfoSetFlagOption-Tuple{HELICS.FederateInfo,Union{Int64,%20HELICS.Lib.helics_federate_flags},Bool}) +| [Python](https://python.helics.org/api/capi-py/#helicsFederateInfoSetFlagOption) +| [Julia](https://julia.helics.org/latest/api/#HELICS.helicsFederateInfoSetFlagOption-Tuple{HELICS.FederateInfo,%20Union{Int64,%20HELICS.Lib.HelicsFederateFlags},%20Bool}) _Property's enumerated name:_ `HELICS_FLAG_SOURCE_ONLY` [4] @@ -352,34 +385,50 @@ Used to indicate to the federation that this federate is only producing data and _API:_ `helicsFederateInfoSetFlagOption` [C++](https://docs.helics.org/en/latest/doxygen/classhelics_1_1CoreFederateInfo.html#a63efa7762fdc8a9d9869bbed6939448e) | [C](api-reference/C_API.md#federateinfo) -| [Python](https://python.helics.org/api/capi-py.html#helicsFederateInfoSetFlagOption) -| [Julia](https://julia.helics.org/latest/api/#HELICS.helicsFederateInfoSetFlagOption-Tuple{HELICS.FederateInfo,Union{Int64,%20HELICS.Lib.helics_federate_flags},Bool}) +| [Python](https://python.helics.org/api/capi-py/#helicsFederateInfoSetFlagOption) +| [Julia](https://julia.helics.org/latest/api/#HELICS.helicsFederateInfoSetFlagOption-Tuple{HELICS.FederateInfo,%20Union{Int64,%20HELICS.Lib.HelicsFederateFlags},%20Bool}) _Property's enumerated name:_ `HELICS_FLAG_OBSERVER` [0] Used to indicate to the federation that this federate produces no data and only has inputs/subscriptions. Specifying this when appropriate allows HELICS to more efficiently grant times to the federation. +--- + +### `broker_key` [null] + +_API:_ `helicsFederateSetBrokerKey` +[C++](https://docs.helics.org/en/latest/doxygen/classhelics_1_1BrokerBase.html#a45c3f109160b1054f46a6734da6f1557) +| [C](api-reference/C_API.md#federateinfo) +| [Python](https://python.helics.org/api/capi-py/#helicsFederateInfoSetBrokerKey) +| [Julia](https://julia.helics.org/latest/api/#HELICS.helicsFederateInfoSetBrokerKey-Tuple{HELICS.FederateInfo,%20String}) + +Setting a broker key only allows federates that have the same broker key to be part of the federation. + ## Logging Options -### `log_file` | `logfile` | `logFile` [] +### `log_file` [null] +_Alternative names:_ `logfile`, `logFile` _API:_ `helicsFederateSetLogFile` -[C++](https://docs.helics.org/en/latest/doxygen/helics_8h.html#abde89169985b8a18c2d1b8fa803e5169) + +[C++](https://docs.helics.org/en/latest/doxygen/classhelics_1_1Logger.html) | [C](api-reference/C_API.md#federate) -| [Python](https://python.helics.org/api/capi-py.html#helicsFederateSetLogFile) -| [Julia](https://julia.helics.org/latest/api/#HELICS.helicsBrokerSetLogFile-Tuple{HELICS.Broker,String}) +| [Python](https://python.helics.org/api/capi-py/#helicsFederateSetLogFile) +| [Julia](https://julia.helics.org/latest/api/#HELICS.helicsBrokerSetLogFile-Tuple{HELICS.Broker,%20String}) Specifies the name of the log file where logging messages will be written. --- -### `log_level` | `loglevel` | `logLevel` [0] +### `log_level` [0] + +_Alternative names:_ `loglevel`, `logLevel` _API:_ `helicsFederateInfoSetIntegerProperty` -[C++](https://docs.helics.org/en/latest/doxygen/classhelics_1_1CommonCore.html#ad6a898deb8df83ee31d62eccbb202aef) +[C++](https://docs.helics.org/en/latest/doxygen/classhelics_1_1CommonCore.html#a01dddbf428e5d1f0ad8ead05491dabff) | [C](api-reference/C_API.md#federateinfo) -| [Python](https://python.helics.org/api/capi-py.html#helicsFederateInfoSetIntegerProperty) -| [Julia](https://julia.helics.org/latest/api/#HELICS.helicsFederateInfoSetIntegerProperty-Tuple{HELICS.FederateInfo,Union{Int64,%20HELICS.Lib.helics_properties},Int64}) +| [Python](https://python.helics.org/api/capi-py/#helicsFederateInfoSetIntegerProperty) +| [Julia](https://julia.helics.org/latest/api/#HELICS.helicsFederateInfoSetIntegerProperty-Tuple{HELICS.FederateInfo,%20Union{Int64,%20HELICS.Lib.HelicsProperties},%20Int64}) _Property's enumerated name:_ `HELICS_PROPERTY_INT_LOG_LEVEL` [271] @@ -402,13 +451,15 @@ Determines the level of detail for log messages. In the list above, the keywords --- -### `file_log_level` | `fileloglevel` | `fileLogLevel` [null] +### `file_log_level` [null] + +_Alternative names:_ `fileloglevel`, `fileLogLevel` _API:_ `helicsFederateInfoSetIntegerProperty` -[C++](https://docs.helics.org/en/latest/doxygen/classhelics_1_1CommonCore.html#ad6a898deb8df83ee31d62eccbb202aef) +[C++](https://docs.helics.org/en/latest/doxygen/classhelics_1_1CommonCore.html#a01dddbf428e5d1f0ad8ead05491dabff) | [C](api-reference/C_API.md#federateinfo) -| [Python](https://python.helics.org/api/capi-py.html#helicsFederateInfoSetIntegerProperty) -| [Julia](https://julia.helics.org/latest/api/#HELICS.helicsFederateInfoSetIntegerProperty-Tuple{HELICS.FederateInfo,Union{Int64,%20HELICS.Lib.helics_properties},Int64}) +| [Python](https://python.helics.org/api/capi-py/#helicsFederateInfoSetIntegerProperty) +| [Julia](https://julia.helics.org/latest/api/#HELICS.helicsFederateInfoSetIntegerProperty-Tuple{HELICS.FederateInfo,%20Union{Int64,%20HELICS.Lib.HelicsProperties},%20Int64}) _Property's enumerated name:_ `HELICS_PROPERTY_INT_FILE_LOG_LEVEL` [272] @@ -418,13 +469,15 @@ Allows a distinct log level for the written log file to be specified. By default --- -### `console_log_level` | `consoleloglevel` | `consoleLogLevel` [null] +### `console_log_level` [null] + +_Alternative names:_ `consoleloglevel`, `consoleLogLevel` _API:_ `helicsFederateInfoSetIntegerProperty` -[C++](https://docs.helics.org/en/latest/doxygen/classhelics_1_1CommonCore.html#ad6a898deb8df83ee31d62eccbb202aef) +[C++](https://docs.helics.org/en/latest/doxygen/classhelics_1_1CommonCore.html#a01dddbf428e5d1f0ad8ead05491dabff) | [C](api-reference/C_API.md#federateinfo) -| [Python](https://python.helics.org/api/capi-py.html#helicsFederateInfoSetIntegerProperty) -| [Julia](https://julia.helics.org/latest/api/#HELICS.helicsFederateInfoSetIntegerProperty-Tuple{HELICS.FederateInfo,Union{Int64,%20HELICS.Lib.helics_properties},Int64}) +| [Python](https://python.helics.org/api/capi-py/#helicsFederateInfoSetIntegerProperty) +| [Julia](https://julia.helics.org/latest/api/#HELICS.helicsFederateInfoSetIntegerProperty-Tuple{HELICS.FederateInfo,%20Union{Int64,%20HELICS.Lib.HelicsProperties},%20Int64}) _Property's enumerated name:_ `HELICS_PROPERTY_INT_CONSOLE_LOG_LEVEL` [274] @@ -434,13 +487,15 @@ Allows a distinct log level for the written log file to be specified. By default --- -### `force_logging_flush` | `forceloggingflush` | `forceLoggingFlush` [false] +### `force_logging_flush` [false] + +_Alternative names:_ `forceloggingflush`, `forceLoggingFlush` _API:_ `helicsFederateInfoSetFlagOption` [C++](https://docs.helics.org/en/latest/doxygen/classhelics_1_1CoreFederateInfo.html#a63efa7762fdc8a9d9869bbed6939448e) | [C](api-reference/C_API.md#federateinfo) -| [Python](https://python.helics.org/api/capi-py.html#helicsFederateInfoSetFlagOption) -| [Julia](https://julia.helics.org/latest/api/#HELICS.helicsFederateInfoSetFlagOption-Tuple{HELICS.FederateInfo,Union{Int64,%20HELICS.Lib.helics_federate_flags},Bool}) +| [Python](https://python.helics.org/api/capi-py/#helicsFederateInfoSetFlagOption) +| [Julia](https://julia.helics.org/latest/api/#HELICS.helicsFederateInfoSetFlagOption-Tuple{HELICS.FederateInfo,%20Union{Int64,%20HELICS.Lib.HelicsFederateFlags},%20Bool}) _Property's enumerated name:_ `HELICS_FLAG_FORCE_LOGGING_FLUSH` [88] @@ -448,13 +503,15 @@ Setting this option forces HELICS logging messages to be flushed to file after e --- -### `dump_log` | `dumplog` | `dumpLog` [false] +### `dump_log` [false] + +_Alternative names:_ `dumplog`, `dumpLog` _API:_ `helicsFederateInfoSetFlagOption` [C++](https://docs.helics.org/en/latest/doxygen/classhelics_1_1CoreFederateInfo.html#a63efa7762fdc8a9d9869bbed6939448e) | [C](api-reference/C_API.md#federateinfo) -| [Python](https://python.helics.org/api/capi-py.html#helicsFederateInfoSetFlagOption) -| [Julia](https://julia.helics.org/latest/api/#HELICS.helicsFederateInfoSetFlagOption-Tuple{HELICS.FederateInfo,Union{Int64,%20HELICS.Lib.helics_federate_flags},Bool}) +| [Python](https://python.helics.org/api/capi-py/#helicsFederateInfoSetFlagOption) +| [Julia](https://julia.helics.org/latest/api/#HELICS.helicsFederateInfoSetFlagOption-Tuple{HELICS.FederateInfo,%20Union{Int64,%20HELICS.Lib.HelicsFederateFlags},%20Bool}) _Property's enumerated name:_ `HELICS_FLAG_DUMPLOG` [89] @@ -462,13 +519,15 @@ When set, a record of all messages is captured and written out to the log file a --- -### `logbuffer` | `log_buffer` | `logBuffer` [10] +### `logbuffer` [10] + +_Alternative names:_ `log_buffer`, `logBuffer` _API:_ `helicsFederateInfoSetIntegerProperty` -[C++](https://docs.helics.org/en/latest/doxygen/classhelics_1_1CommonCore.html#ad6a898deb8df83ee31d62eccbb202aef) +[C++](https://docs.helics.org/en/latest/doxygen/classhelics_1_1CommonCore.html#a01dddbf428e5d1f0ad8ead05491dabff) | [C](api-reference/C_API.md#federateinfo) -| [Python](https://python.helics.org/api/capi-py.html#helicsFederateInfoSetIntegerProperty) -| [Julia](https://julia.helics.org/latest/api/#HELICS.helicsFederateInfoSetIntegerProperty-Tuple{HELICS.FederateInfo,Union{Int64,%20HELICS.Lib.helics_properties},Int64}) +| [Python](https://python.helics.org/api/capi-py/#helicsFederateInfoSetIntegerProperty) +| [Julia](https://julia.helics.org/latest/api/#HELICS.helicsFederateInfoSetIntegerProperty-Tuple{HELICS.FederateInfo,%20Union{Int64,%20HELICS.Lib.HelicsProperties},%20Int64}) _Property's enumerated name:_ `HELICS_PROPERTY_INT_LOG_BUFFER` [276] @@ -476,13 +535,15 @@ When set to a number greater than 0 will enable the most recent X log messages o ## Other Options -## `indexgroup` | `index_group` | `indexGroup` [0] +### `indexgroup` [0] + +_Alternative names:_ `index_group`, `indexGroup` _API:_ `helicsFederateInfoSetIntegerProperty` [C++](https://docs.helics.org/en/latest/doxygen/classhelics_1_1CommonCore.html#a01dddbf428e5d1f0ad8ead05491dabff) | [C](api-reference/C_API.md#federateinfo) | [Python](https://python.helics.org/api/capi-py/#helicsFederateInfoSetIntegerProperty) -| [Julia](https://julia.helics.org/latest/api/#HELICS.helicsFederateInfoSetIntegerProperty-Tuple{HELICS.FederateInfo,Union{Int64,%20HELICS.Lib.helics_properties},Int64}) +| [Julia](https://julia.helics.org/latest/api/#HELICS.helicsFederateInfoSetIntegerProperty-Tuple{HELICS.FederateInfo,%20Union{Int64,%20HELICS.Lib.HelicsProperties},%20Int64}) _Property's enumerated name:_ `HELICS_PROPERTY_INT_INDEX_GROUP` [282] @@ -490,13 +551,15 @@ When set to a number greater than 0 will modify the internal federateId codes. V ## Timing Options -### `ignore_time_mismatch` | `ignoretimemismatch` | `ignoreTimeMismatch` [false] +### `ignore_time_mismatch` [false] + +_Alternative names:_ `ignoretimemismatch`, `ignoreTimeMismatch` _API:_ `helicsFederateInfoSetFlagOption` [C++](https://docs.helics.org/en/latest/doxygen/classhelics_1_1CoreFederateInfo.html#a63efa7762fdc8a9d9869bbed6939448e) | [C](api-reference/C_API.md#federateinfo) -| [Python](https://python.helics.org/api/capi-py.html#helicsFederateInfoSetFlagOption) -| [Julia](https://julia.helics.org/latest/api/#HELICS.helicsFederateInfoSetFlagOption-Tuple{HELICS.FederateInfo,Union{Int64,%20HELICS.Lib.helics_federate_flags},Bool}) +| [Python](https://python.helics.org/api/capi-py/#helicsFederateInfoSetFlagOption) +| [Julia](https://julia.helics.org/latest/api/#HELICS.helicsFederateInfoSetFlagOption-Tuple{HELICS.FederateInfo,%20Union{Int64,%20HELICS.Lib.HelicsFederateFlags},%20Bool}) _Property's enumerated name:_ `HELICS_FLAG_IGNORE_TIME_MISMATCH_WARNINGS` [67] @@ -509,8 +572,8 @@ If certain timing options (_i.e._ `period`, or `minTimeDelta`) are used it is po _API:_ `helicsFederateInfoSetFlagOption` [C++](https://docs.helics.org/en/latest/doxygen/classhelics_1_1CoreFederateInfo.html#a63efa7762fdc8a9d9869bbed6939448e) | [C](api-reference/C_API.md#federateinfo) -| [Python](https://python.helics.org/api/capi-py.html#helicsFederateInfoSetFlagOption) -| [Julia](https://julia.helics.org/latest/api/#HELICS.helicsFederateInfoSetFlagOption-Tuple{HELICS.FederateInfo,Union{Int64,%20HELICS.Lib.helics_federate_flags},Bool}) +| [Python](https://python.helics.org/api/capi-py/#helicsFederateInfoSetFlagOption) +| [Julia](https://julia.helics.org/latest/api/#HELICS.helicsFederateInfoSetFlagOption-Tuple{HELICS.FederateInfo,%20Union{Int64,%20HELICS.Lib.HelicsFederateFlags},%20Bool}) _Property's enumerated name:_ `HELICS_FLAG_UNINTERRUPTIBLE` [1] @@ -518,13 +581,13 @@ Normally, a federate will be granted a time earlier than it requested when it re --- -### `period` [0] +### `period` [1ns] _API:_ `helicsFederateInfoSetTimeProperty` -[C++](https://docs.helics.org/en/latest/doxygen/classhelics_1_1Core.html#aef32f6cb11188baf60cc8826914a4b6f) +[C++](https://docs.helics.org/en/latest/doxygen/classhelics_1_1Core.html#a877611c1cfb0d30d1acb86b00f76eba3) | [C](api-reference/C_API.md#federateinfo) -| [Python](https://python.helics.org/api/capi-py.html#helicsFederateInfoSetTimeProperty) -| [Julia](https://julia.helics.org/latest/api/#HELICS.helicsFederateInfoSetTimeProperty-Tuple{HELICS.FederateInfo,Union{Int64,%20HELICS.Lib.helics_properties},Union{Float64,%20Int64}}) +| [Python](https://python.helics.org/api/capi-py/#helicsFederateInfoSetTimeProperty) +| [Julia](https://julia.helics.org/latest/api/#HELICS.helicsFederateInfoSetTimeProperty-Tuple{HELICS.FederateInfo,%20Union{Int64,%20HELICS.Lib.HelicsProperties},%20Union{Float64,%20Int64}}) _Property's enumerated name:_ `HELICS_PROPERTY_TIME_PERIOD` [140] @@ -535,10 +598,10 @@ Many time-based simulators have a minimum time-resolution or a user-configurable ### `offset` [0] _API:_ `helicsFederateInfoSetTimeProperty` -[C++](https://docs.helics.org/en/latest/doxygen/classhelics_1_1Core.html#aef32f6cb11188baf60cc8826914a4b6f) +[C++](https://docs.helics.org/en/latest/doxygen/classhelics_1_1Core.html#a877611c1cfb0d30d1acb86b00f76eba3) | [C](api-reference/C_API.md#federateinfo) -| [Python](https://python.helics.org/api/capi-py.html#helicsFederateInfoSetTimeProperty) -| [Julia](https://julia.helics.org/latest/api/#HELICS.helicsFederateInfoSetTimeProperty-Tuple{HELICS.FederateInfo,Union{Int64,%20HELICS.Lib.helics_properties},Union{Float64,%20Int64}}) +| [Python](https://python.helics.org/api/capi-py/#helicsFederateInfoSetTimeProperty) +| [Julia](https://julia.helics.org/latest/api/#HELICS.helicsFederateInfoSetTimeProperty-Tuple{HELICS.FederateInfo,%20Union{Int64,%20HELICS.Lib.HelicsProperties},%20Union{Float64,%20Int64}}) _Property's enumerated name:_ `HELICS_PROPERTY_TIME_OFFSET` [141] @@ -546,13 +609,15 @@ There may be cases where it is preferable to have a simulator receive time grant --- -### `time_delta` | `timeDelta` | `timedelta` [1ns] +### `time_delta` [1ns] + +_Alternative names:_ `timeDelta`, `timedelta` _API:_ `helicsFederateInfoSetTimeProperty` -[C++](https://docs.helics.org/en/latest/doxygen/classhelics_1_1Core.html#aef32f6cb11188baf60cc8826914a4b6f) +[C++](https://docs.helics.org/en/latest/doxygen/classhelics_1_1Core.html#a877611c1cfb0d30d1acb86b00f76eba3) | [C](api-reference/C_API.md#federateinfo) -| [Python](https://python.helics.org/api/capi-py.html#helicsFederateInfoSetTimeProperty) -| [Julia](https://julia.helics.org/latest/api/#HELICS.helicsFederateInfoSetTimeProperty-Tuple{HELICS.FederateInfo,Union{Int64,%20HELICS.Lib.helics_properties},Union{Float64,%20Int64}}) +| [Python](https://python.helics.org/api/capi-py/#helicsFederateInfoSetTimeProperty) +| [Julia](https://julia.helics.org/latest/api/#HELICS.helicsFederateInfoSetTimeProperty-Tuple{HELICS.FederateInfo,%20Union{Int64,%20HELICS.Lib.HelicsProperties},%20Union{Float64,%20Int64}}) _Property's enumerated name:_ `HELICS_PROPERTY_TIME_DELTA` [137] @@ -560,13 +625,15 @@ timeDelta has some similarities to `period`; where `period` constrained the gran --- -### `input_delay` | `inputdelay` | `inputDelay` [0] +### `input_delay` [0] + +_Alternative names:_ `inputdelay`, `inputDelay` _API:_ `helicsFederateInfoSetTimeProperty` -[C++](https://docs.helics.org/en/latest/doxygen/classhelics_1_1Core.html#aef32f6cb11188baf60cc8826914a4b6f) +[C++](https://docs.helics.org/en/latest/doxygen/classhelics_1_1Core.html#a877611c1cfb0d30d1acb86b00f76eba3) | [C](api-reference/C_API.md#federateinfo) -| [Python](https://python.helics.org/api/capi-py.html#helicsFederateInfoSetTimeProperty) -| [Julia](https://julia.helics.org/latest/api/#HELICS.helicsFederateInfoSetTimeProperty-Tuple{HELICS.FederateInfo,Union{Int64,%20HELICS.Lib.helics_properties},Union{Float64,%20Int64}}) +| [Python](https://python.helics.org/api/capi-py/#helicsFederateInfoSetTimeProperty) +| [Julia](https://julia.helics.org/latest/api/#HELICS.helicsFederateInfoSetTimeProperty-Tuple{HELICS.FederateInfo,%20Union{Int64,%20HELICS.Lib.HelicsProperties},%20Union{Float64,%20Int64}}) _Property's enumerated name:_ `HELICS_PROPERTY_INPUT_TIME_DELAY` [148] @@ -574,13 +641,15 @@ _Property's enumerated name:_ `HELICS_PROPERTY_INPUT_TIME_DELAY` [148] --- -### `output_delay` | `outputdelay` | `outputDelay` [0] +### `output_delay` [0] + +_Alternative names:_ `outputdelay`, `outputDelay` _API:_ `helicsFederateInfoSetTimeProperty` -[C++](https://docs.helics.org/en/latest/doxygen/classhelics_1_1Core.html#aef32f6cb11188baf60cc8826914a4b6f) +[C++](https://docs.helics.org/en/latest/doxygen/classhelics_1_1Core.html#a877611c1cfb0d30d1acb86b00f76eba3) | [C](api-reference/C_API.md#federateinfo) -| [Python](https://python.helics.org/api/capi-py.html#helicsFederateInfoSetTimeProperty) -| [Julia](https://julia.helics.org/latest/api/#HELICS.helicsFederateInfoSetTimeProperty-Tuple{HELICS.FederateInfo,Union{Int64,%20HELICS.Lib.helics_properties},Union{Float64,%20Int64}}) +| [Python](https://python.helics.org/api/capi-py/#helicsFederateInfoSetTimeProperty) +| [Julia](https://julia.helics.org/latest/api/#HELICS.helicsFederateInfoSetTimeProperty-Tuple{HELICS.FederateInfo,%20Union{Int64,%20HELICS.Lib.HelicsProperties},%20Union{Float64,%20Int64}}) _Property's enumerated name:_ `HELICS_TIME_PROPERTY_OUTPUT_TIME_DELAY` [150] @@ -588,12 +657,14 @@ _Property's enumerated name:_ `HELICS_TIME_PROPERTY_OUTPUT_TIME_DELAY` [150] --- -### `real_time` | `realtime` | `realTime` [false] +### `real_time` [false] + +_Alternative names:_ `realtime`, `realTime` _API:_ `helicsFederateInfoSetFlagOption` [C++](https://docs.helics.org/en/latest/doxygen/classhelics_1_1CoreFederateInfo.html#a63efa7762fdc8a9d9869bbed6939448e) | [C](api-reference/C_API.md#federateinfo) -| [Python](https://python.helics.org/api/capi-py.html#helicsFederateInfoSetFlagOption) +| [Python](https://python.helics.org/api/capi-py/#helicsFederateInfoSetFlagOption) | [Julia](https://julia.helics.org/latest/api/#HELICS.helicsFederateInfoSetFlagOption-Tuple{HELICS.FederateInfo,Union{Int64,%20HELICS.Lib.helics_federate_flags},Bool}) _Property's enumerated name:_ `HELICS_FLAG_REALTIME` [16] @@ -603,13 +674,15 @@ If the federate is running faster than real time this will insert additional del --- -### `rt_lag`| `rtlag` | `rtLag` [0.2] and `rt_lead` | `rtlead` | `rtLead` [0.2] +### `rt_lag and `rt_lead`[0.2] + +_Alternative names:_ `rtlag`, `rtLag`; `rtlead`, `rtLead` _API:_ `helicsFederateInfoSetTimeProperty` -[C++](https://docs.helics.org/en/latest/doxygen/classhelics_1_1Core.html#aef32f6cb11188baf60cc8826914a4b6f) +[C++](https://docs.helics.org/en/latest/doxygen/classhelics_1_1Core.html#a877611c1cfb0d30d1acb86b00f76eba3) | [C](api-reference/C_API.md#federateinfo) -| [Python](https://python.helics.org/api/capi-py.html#helicsFederateInfoSetTimeProperty) -| [Julia](https://julia.helics.org/latest/api/#HELICS.helicsFederateInfoSetTimeProperty-Tuple{HELICS.FederateInfo,Union{Int64,%20HELICS.Lib.helics_properties},Union{Float64,%20Int64}}) +| [Python](https://python.helics.org/api/capi-py/#helicsFederateInfoSetTimeProperty) +| [Julia](https://julia.helics.org/latest/api/#HELICS.helicsFederateInfoSetTimeProperty-Tuple{HELICS.FederateInfo,%20Union{Int64,%20HELICS.Lib.HelicsProperties},%20Union{Float64,%20Int64}}) _Property's enumerated name:_ `HELICS_PROPERTY_TIME_RT_LAG` [143] and `HELICS_PROPERTY_TIME_RT_LEAD` [144] @@ -617,13 +690,15 @@ Defines "real-time" for HELICS by setting tolerances for HELICS to use when runn --- -### `rt_tolerance` | `rttolerance` | `rtTolerance` [0.2] +### `rt_tolerance` [0.2] + +_Alternative names:_ `rttolerance`, `rtTolerance` _API:_ `helicsFederateInfoSetTimeProperty` -[C++](https://docs.helics.org/en/latest/doxygen/classhelics_1_1Core.html#aef32f6cb11188baf60cc8826914a4b6f) +[C++](https://docs.helics.org/en/latest/doxygen/classhelics_1_1Core.html#a877611c1cfb0d30d1acb86b00f76eba3) | [C](api-reference/C_API.md#federateinfo) -| [Python](https://python.helics.org/api/capi-py.html#helicsFederateInfoSetTimeProperty) -| [Julia](https://julia.helics.org/latest/api/#HELICS.helicsFederateInfoSetTimeProperty-Tuple{HELICS.FederateInfo,Union{Int64,%20HELICS.Lib.helics_properties},Union{Float64,%20Int64}}) +| [Python](https://python.helics.org/api/capi-py/#helicsFederateInfoSetTimeProperty) +| [Julia](https://julia.helics.org/latest/api/#HELICS.helicsFederateInfoSetTimeProperty-Tuple{HELICS.FederateInfo,%20Union{Int64,%20HELICS.Lib.HelicsProperties},%20Union{Float64,%20Int64}}) _Property's enumerated name:_ `HELICS_PROPERTY_TIME_RT_TOLERANCE` [145] @@ -631,13 +706,15 @@ Implements the same functionality of `rt_lag` and `rt_lead` but does so by using --- -### `wait_for_current_time_update` |`waitforcurrenttimeupdate` | `waitForCurrentTimeUpdate` [false] +### `wait_for_current_time_update` [false] + +_Alternative names:_ `waitforcurrenttimeupdate`, `waitForCurrentTimeUpdate` _API:_ `helicsFederateInfoSetFlagOption` [C++](https://docs.helics.org/en/latest/doxygen/classhelics_1_1CoreFederateInfo.html#a63efa7762fdc8a9d9869bbed6939448e) | [C](api-reference/C_API.md#federateinfo) -| [Python](https://python.helics.org/api/capi-py.html#helicsFederateInfoSetFlagOption) -| [Julia](https://julia.helics.org/latest/api/#HELICS.helicsFederateInfoSetFlagOption-Tuple{HELICS.FederateInfo,Union{Int64,%20HELICS.Lib.helics_federate_flags},Bool}) +| [Python](https://python.helics.org/api/capi-py/#helicsFederateInfoSetFlagOption) +| [Julia](https://julia.helics.org/latest/api/#HELICS.helicsFederateInfoSetFlagOption-Tuple{HELICS.FederateInfo,%20Union{Int64,%20HELICS.Lib.HelicsFederateFlags},%20Bool}) _Property's enumerated name:_ `HELICS_FLAG_WAIT_FOR_CURRENT_TIME_UPDATE` [10] @@ -645,13 +722,15 @@ If set to true, a federate will not be granted the requested time until all othe --- -### `restrictive_time_policy` | `restrictivetimepolicy` | `restrictiveTimePolicy` [false] +### `restrictive_time_policy` [false] + +_Alternative names:_ `restrictivetimepolicy` | `restrictiveTimePolicy` _API:_ `helicsFederateInfoSetFlagOption` [C++](https://docs.helics.org/en/latest/doxygen/classhelics_1_1CoreFederateInfo.html#a63efa7762fdc8a9d9869bbed6939448e) | [C](api-reference/C_API.md#federateinfo) -| [Python](https://python.helics.org/api/capi-py.html#helicsFederateInfoSetFlagOption) -| [Julia](https://julia.helics.org/latest/api/#HELICS.helicsFederateInfoSetFlagOption-Tuple{HELICS.FederateInfo,Union{Int64,%20HELICS.Lib.helics_federate_flags},Bool}) +| [Python](https://python.helics.org/api/capi-py/#helicsFederateInfoSetFlagOption) +| [Julia](https://julia.helics.org/latest/api/#HELICS.helicsFederateInfoSetFlagOption-Tuple{HELICS.FederateInfo,%20Union{Int64,%20HELICS.Lib.HelicsFederateFlags},%20Bool}) _Property's enumerated name:_ `HELICS_FLAG_RESTRICTIVE_TIME_POLICY` [11] @@ -663,13 +742,15 @@ Only applicable to Named Input interfaces ([see section on value federate interf --- -### `slow_responding` | `slowresponsing` | `slowResponding` [false] +### `slow_responding` [false] + +_Alternative names:_ `slowresponsing`, `slowResponding` _API:_ `helicsFederateInfoSetFlagOption` [C++](https://docs.helics.org/en/latest/doxygen/classhelics_1_1CoreFederateInfo.html#a63efa7762fdc8a9d9869bbed6939448e) | [C](api-reference/C_API.md#federateinfo) -| [Python](https://python.helics.org/api/capi-py.html#helicsFederateInfoSetFlagOption) -| [Julia](https://julia.helics.org/latest/api/#HELICS.helicsFederateInfoSetFlagOption-Tuple{HELICS.FederateInfo,Union{Int64,%20HELICS.Lib.helics_federate_flags},Bool}) +| [Python](https://python.helics.org/api/capi-py/#helicsFederateInfoSetFlagOption) +| [Julia](https://julia.helics.org/latest/api/#HELICS.helicsFederateInfoSetFlagOption-Tuple{HELICS.FederateInfo,%20Union{Int64,%20HELICS.Lib.HelicsFederateFlags},%20Bool}) _Property's enumerated name:_ `HELICS_FLAG_SLOW_RESPONDING` [29] @@ -682,10 +763,10 @@ If applied to a core or broker (`--slow_responding` in the `core_init_string` or ### `event_triggered` [false] _API:_ `helicsFederateInfoSetTimeProperty` -[C++](https://docs.helics.org/en/latest/doxygen/classhelics_1_1Core.html#aef32f6cb11188baf60cc8826914a4b6f) +[C++](https://docs.helics.org/en/latest/doxygen/classhelics_1_1Core.html#a877611c1cfb0d30d1acb86b00f76eba3) | [C](api-reference/C_API.md#federateinfo) -| [Python](https://python.helics.org/api/capi-py.html#helicsFederateInfoSetTimeProperty) -| [Julia](https://julia.helics.org/latest/api/#HELICS.helicsFederateInfoSetTimeProperty-Tuple{HELICS.FederateInfo,Union{Int64,%20HELICS.Lib.helics_properties},Union{Float64,%20Int64}}) +| [Python](https://python.helics.org/api/capi-py/#helicsFederateInfoSetTimeProperty) +| [Julia](https://julia.helics.org/latest/api/#HELICS.helicsFederateInfoSetTimeProperty-Tuple{HELICS.FederateInfo,%20Union{Int64,%20HELICS.Lib.HelicsProperties},%20Union{Float64,%20Int64}}) _Property's enumerated name:_ `HELICS_FLAG_EVENT_TRIGGERED` [81] @@ -693,13 +774,15 @@ For federates that are event-driven rather than timing driven, this flag must be ## Iteration -### `forward_compute` | `forwardcompute` | `forwardCompute` [false] +### `forward_compute` [false] + +_Alternative names:_ `forwardcompute` | `forwardCompute` _API:_ `helicsFederateInfoSetFlagOption` [C++](https://docs.helics.org/en/latest/doxygen/classhelics_1_1CoreFederateInfo.html#a63efa7762fdc8a9d9869bbed6939448e) | [C](api-reference/C_API.md#federateinfo) -| [Python](https://python.helics.org/api/capi-py.html#helicsFederateInfoSetFlagOption) -| [Julia](https://julia.helics.org/latest/api/#HELICS.helicsFederateInfoSetFlagOption-Tuple{HELICS.FederateInfo,Union{Int64,%20HELICS.Lib.helics_federate_flags},Bool}) +| [Python](https://python.helics.org/api/capi-py/#helicsFederateInfoSetFlagOption) +| [Julia](https://julia.helics.org/latest/api/#HELICS.helicsFederateInfoSetFlagOption-Tuple{HELICS.FederateInfo,%20Union{Int64,%20HELICS.Lib.HelicsFederateFlags},%20Bool}) _Property's enumerated name:_ `HELICS_FLAG_FORWARD_COMPUTE` [14] @@ -712,8 +795,8 @@ Indicates to the broker and the rest of the federation that this federate comput _API:_ `helicsFederateInfoSetFlagOption` [C++](https://docs.helics.org/en/latest/doxygen/classhelics_1_1CoreFederateInfo.html#a63efa7762fdc8a9d9869bbed6939448e) | [C](api-reference/C_API.md#federateinfo) -| [Python](https://python.helics.org/api/capi-py.html#helicsFederateInfoSetFlagOption) -| [Julia](https://julia.helics.org/latest/api/#HELICS.helicsFederateInfoSetFlagOption-Tuple{HELICS.FederateInfo,Union{Int64,%20HELICS.Lib.helics_federate_flags},Bool}) +| [Python](https://python.helics.org/api/capi-py/#helicsFederateInfoSetFlagOption) +| [Julia](https://julia.helics.org/latest/api/#HELICS.helicsFederateInfoSetFlagOption-Tuple{HELICS.FederateInfo,%20Union{Int64,%20HELICS.Lib.HelicsFederateFlags},%20Bool}) _Property's enumerated name:_ `HELICS_FLAG_ROLLBACK` [12] @@ -721,13 +804,15 @@ Indicates to the broker and the rest of the federation that this federate can/do --- -### `max_iterations` | `maxiterations` | `maxIteration` [50] +### `max_iterations` [50] + +_Alternative names:_ `maxiterations`, `maxIteration` _API:_ `helicsFederateInfoSetIntegerProperty` -[C++](https://docs.helics.org/en/latest/doxygen/classhelics_1_1CommonCore.html#ad6a898deb8df83ee31d62eccbb202aef) +[C++](https://docs.helics.org/en/latest/doxygen/classhelics_1_1CommonCore.html#a01dddbf428e5d1f0ad8ead05491dabff) | [C](api-reference/C_API.md#federateinfo) -| [Python](https://python.helics.org/api/capi-py.html#helicsFederateInfoSetIntegerProperty) -| [Julia](https://julia.helics.org/latest/api/#HELICS.helicsFederateInfoSetIntegerProperty-Tuple{HELICS.FederateInfo,Union{Int64,%20HELICS.Lib.helics_properties},Int64}) +| [Python](https://python.helics.org/api/capi-py/#helicsFederateInfoSetIntegerProperty) +| [Julia](https://julia.helics.org/latest/api/#HELICS.helicsFederateInfoSetIntegerProperty-Tuple{HELICS.FederateInfo,%20Union{Int64,%20HELICS.Lib.HelicsProperties},%20Int64}) _Property's enumerated name:_ `HELICS_PROPERTY_INT_MAX_ITERATIONS` [259] @@ -737,13 +822,15 @@ For federates engaged in iteration (recomputing values based on updated inputs a These options can be set globally for all subscriptions, inputs and publications for a given federate. Even after setting them globally, they can be included in the configuration for an individual subscription, input, or publication, over-riding the global setting. -### `only_update_on_change` | `onlyupdateonchange` | `onlyUpdateOnChange` [false] and `only_transmit_on_change` | `onlytransmitonchange` | `onlyTransmitOnChange` [false] +### `only_update_on_change` and `only_transmit_on_change` [false] + +_Alternative names:_ `onlyupdateonchange`, `onlyUpdateOnChange`;`onlytransmitonchange`, `onlyTransmitOnChange` _API:_ `helicsFederateInfoSetFlagOption` [C++](https://docs.helics.org/en/latest/doxygen/classhelics_1_1CoreFederateInfo.html#a63efa7762fdc8a9d9869bbed6939448e) | [C](api-reference/C_API.md#federateinfo) -| [Python](https://python.helics.org/api/capi-py.html#helicsFederateInfoSetFlagOption) -| [Julia](https://julia.helics.org/latest/api/#HELICS.helicsFederateInfoSetFlagOption-Tuple{HELICS.FederateInfo,Union{Int64,%20HELICS.Lib.helics_federate_flags},Bool}) +| [Python](https://python.helics.org/api/capi-py/#helicsFederateInfoSetFlagOption) +| [Julia](https://julia.helics.org/latest/api/#HELICS.helicsFederateInfoSetFlagOption-Tuple{HELICS.FederateInfo,%20Union{Int64,%20HELICS.Lib.HelicsFederateFlags},%20Bool}) _Property's enumerated name:_ `HELICS_FLAG_ONLY_UPDATE_ON_CHANGE` [454] and `HELICS_FLAG_ONLY_TRANSMIT_ON_CHANGE` [452] @@ -751,25 +838,26 @@ Setting these flags prevents new value signals with the same value from being re --- -### `tolerance` +### `tolerance` [0] _API:_ `helicsPublicationSetMinimumChange` and `helicsInputSetMinimumChange` + [C++ input](https://docs.helics.org/en/latest/doxygen/classhelics_1_1Input.html#a55056ac9dd2895270f575827dd9951c7) and [C++ publication](https://docs.helics.org/en/latest/doxygen/classhelics_1_1Publication.html#ab66f5680bb4a5e062314f6f8e5dea846) | [C input](api-reference/C_API.md#input) and [C publication](api-reference/C_API.md#publication) -| [Python input](https://python.helics.org/api/capi-py.html#helicsInputSetMinimumChange) and [Python publication](https://python.helics.org/api/capi-py.html#helicsPublicationSetMinimumChange) -| [Julia input](https://julia.helics.org/latest/api/#HELICS.helicsInputSetMinimumChange-Tuple{HELICS.Subscription,Float64}) and [Julia publication](https://julia.helics.org/latest/api/#HELICS.helicsPublicationSetMinimumChange-Tuple{HELICS.Publication,Float64}) +| [Python input](https://python.helics.org/api/capi-py/#helicsInputSetMinimumChange) and [Python publication](https://python.helics.org/api/capi-py/#helicsPublicationSetMinimumChange) +| [Julia input](https://julia.helics.org/latest/api/#HELICS.helicsPublicationSetMinimumChange-Tuple{HELICS.Publication,%20Float64}) and [Julia publication](https://julia.helics.org/latest/api/#HELICS.helicsInputSetMinimumChange-Tuple{HELICS.Input,%20Float64}) This option allows the specific numerical definition of "change" when using the `only_update_on_change` and `only_transmit_on_change` options. --- -### `default` +### `default` [0] _API:_ `helicsInputSetDefaultX` [C++ input](https://docs.helics.org/en/latest/doxygen/classhelics_1_1Input.html#a55056ac9dd2895270f575827dd9951c7) | [C input](api-reference/C_API.md#input) -| [Python input](https://python.helics.org/api/capi-py.html#helicsInputSetDefault) -| [Julia input](https://julia.helics.org/latest/api/#HELICS.helicsInputSetDefulat-Tuple{HELICS.Input,XXX}) +| [Python input](https://python.helics.org/api/capi-py/#helicsInputSetDefault) +| [Julia input](https://julia.helics.org/latest/api/#HELICS.helicsInputSetDefaultBoolean-Tuple{HELICS.Input,%20Bool}) This option allows specifying the default value used when no publication has been received. Each datatype has its own API call such as: @@ -791,13 +879,15 @@ Though they are not as obviously named, the following two APIs do provide a mean --- -### `connection_required` | `connectionrequired` | `connectionRequired` [false] +### `connection_required` [false] + +_Alternative names:_ `connectionrequired` | `connectionRequired` _API:_ `helicsFederateInfoSetFlagOption` [C++](https://docs.helics.org/en/latest/doxygen/classhelics_1_1CoreFederateInfo.html#a63efa7762fdc8a9d9869bbed6939448e) | [C](api-reference/C_API.md#federateinfo) -| [Python](https://python.helics.org/api/capi-py.html#helicsFederateInfoSetFlagOption) -| [Julia](https://julia.helics.org/latest/api/#HELICS.helicsFederateInfoSetFlagOption-Tuple{HELICS.FederateInfo,Union{Int64,%20HELICS.Lib.helics_federate_flags},Bool}) +| [Python](https://python.helics.org/api/capi-py/#helicsFederateInfoSetFlagOption) +| [Julia](https://julia.helics.org/latest/api/#HELICS.helicsFederateInfoSetFlagOption-Tuple{HELICS.FederateInfo,%20Union{Int64,%20HELICS.Lib.HelicsFederateFlags},%20Bool}) _Property's enumerated name:_ `HELICS_HANDLE_OPTION_CONNECTION_REQUIRED` [397] @@ -808,13 +898,15 @@ When a federate is initialized, one of its tasks is to make sure the recipients --- -### `connection_optional` | `connectionoptional` | `connectionOptional` [false] +### `connection_optional` [true] + +_Alternative names:_ `connectionoptional`, `connectionOptional` _API:_ `helicsFederateInfoSetFlagOption` [C++](https://docs.helics.org/en/latest/doxygen/classhelics_1_1CoreFederateInfo.html#a63efa7762fdc8a9d9869bbed6939448e) | [C](api-reference/C_API.md#federateinfo) -| [Python](https://python.helics.org/api/capi-py.html#helicsFederateInfoSetFlagOption) -| [Julia](https://julia.helics.org/latest/api/#HELICS.helicsFederateInfoSetFlagOption-Tuple{HELICS.FederateInfo,Union{Int64,%20HELICS.Lib.helics_federate_flags},Bool}) +| [Python](https://python.helics.org/api/capi-py/#helicsFederateInfoSetFlagOption) +| [Julia](https://julia.helics.org/latest/api/#HELICS.helicsFederateInfoSetFlagOption-Tuple{HELICS.FederateInfo,%20Union{Int64,%20HELICS.Lib.HelicsFederateFlags},%20Bool}) _Property's enumerated name:_ `HELICS_HANDLE_OPTION_CONNECITON_OPTIONAL` [402] @@ -827,19 +919,19 @@ These options are valid for subscriptions, inputs, and/or publications (generica `helicsFederateRegisterPublication` [C++](https://docs.helics.org/en/latest/doxygen/ValueFederate_8h.html#ac00c4e17aeb9e20fdf0f42fb8bc63d29) | [C](api-reference/C_API.md#federate) -| [Python](https://python.helics.org/api/capi-py.html#helicsFederateRegisterPublication) +| [Python](https://python.helics.org/api/capi-py/#helicsFederateRegisterPublication) | [Julia](https://julia.helics.org/latest/api/#HELICS.helicsFederateRegisterPublication) `helicsFederateRegisterSubscription` [C++](https://docs.helics.org/en/latest/doxygen/ValueFederate_8h.html#ab30020ca06ad37548691f313df42e15f) | [C](api-reference/C_API.md#federate) -| [Python](https://python.helics.org/api/capi-py.html#helicsFederateRegisterSubscription) +| [Python](https://python.helics.org/api/capi-py/#helicsFederateRegisterSubscription) | [Julia](https://julia.helics.org/latest/api/#HELICS.helicsFederateRegisterSubscription) `helicsFederateRegisterInput` [C++](https://docs.helics.org/en/latest/doxygen/ValueFederate_8h.html#aa41b313f5e527055444bf915c8da3258) | [C](api-reference/C_API.md#federate) -| [Python](https://python.helics.org/api/capi-py.html#helicsFederateRegisterInput) +| [Python](https://python.helics.org/api/capi-py/#helicsFederateRegisterInput) | [Julia](https://julia.helics.org/latest/api/#HELICS.helicsFederateRegisterInput) ### `key` (required) @@ -868,13 +960,15 @@ HELICS is able to do some levels of unit conversion, currently only on double ty --- -### `buffer_data` | `bufferdata` | `bufferData` [false] +### `buffer_data` [false] + +_Alternative names:_ `bufferdata` | `bufferData` _API:_ `helicsInputSetOption` [C++](https://docs.helics.org/en/latest/doxygen/classhelics_1_1CoreFederateInfo.html#a63efa7762fdc8a9d9869bbed6939448e) | [C](api-reference/C_API.md#input) -| [Python](https://python.helics.org/api/capi-py.html#helicsInputSetOption) -| [Julia](https://julia.helics.org/latest/api/#HELICS.helicsInputSetOption-Tuple{HELICS.Subscription,Union{Int64,%20HELICS.Lib.helics_handle_options},Bool}) +| [Python](https://python.helics.org/api/capi-py/#helicsInputSetOption) +| [Julia](https://julia.helics.org/latest/api/#HELICS.helicsInputSetOption-Tuple{HELICS.Input,%20Union{Int64,%20HELICS.Lib.HelicsHandleOptions},%20Bool}) _Property's enumerated name:_ `HELICS_HANDLE_OPTION_BUFFER_DATA` [411] @@ -882,9 +976,11 @@ _Property's enumerated name:_ `HELICS_HANDLE_OPTION_BUFFER_DATA` [411] --- -### `ignore_units_mismatch | ignoreunitmismatch | ignoreUnitMismatch` [null] +### `ignore_units_mismatch` [null] -_API:_ +_Alternative names:_ `ignoreunitmismatch`, `ignoreUnitMismatch` + +_API:_ TODO Under normal operation, handles that are connected (value signals flowing between them) are required to have units that either match or can be directly converted between. If mismatching units are connected, an error is thrown; when this flag is set that error is suppressed. --- @@ -892,21 +988,23 @@ Under normal operation, handles that are connected (value signals flowing betwee ### `info` [""] _API:_ `helicsInputSetInfo` -[C++](https://docs.helics.org/en/latest/doxygen/group__Information.html#ga8117e8d7c987b3fb27e065b6693116e6) +[C++](https://docs.helics.org/en/latest/doxygen/group__Information.html#ga207530cdd10afb89581baea6977e60b8) | [C](api-reference/C_API.md#input) -| [Python](https://python.helics.org/api/capi-py.html#helicsInputSetInfo) -| [Julia](https://julia.helics.org/latest/api/#HELICS.helicsInputSetInfo-Tuple{HELICS.Subscription,String}) +| [Python](https://python.helics.org/api/capi-py/#helicsInputSetInfo) +| [Julia](https://julia.helics.org/latest/api/#HELICS.helicsInputSetInfo-Tuple{HELICS.Input,%20String}) The `info` field is entirely ignored by HELICS and is used as a mechanism to pass configuration information to the federate so that it can properly integrate into the federation. Thus, there is no standard content or format for this field; it is entirely up to the individual simulators to decide how the data in this field (if any) should be used. Often it is used by simulators to map the HELICS names into internal variable names as shown in the above example. --- -### `strict_input_type_checking` | `strictinputtypechecking` | `strictInputTypeChecking` [false] +### `strict_input_type_checking` [false] + +_Alternative names:_ `strictinputtypechecking`, `strictInputTypeChecking` _API:_ `helicsFederateInfoSetFlagOption` [C++](https://docs.helics.org/en/latest/doxygen/classhelics_1_1CoreFederateInfo.html#a63efa7762fdc8a9d9869bbed6939448e) | [C](api-reference/C_API.md#federateinfo) -| [Python](https://python.helics.org/api/capi-py.html#helicsFederateInfoSetFlagOption) -| [Julia](https://julia.helics.org/latest/api/#HELICS.helicsFederateInfoSetFlagOption-Tuple{HELICS.FederateInfo,Union{Int64,%20HELICS.Lib.helics_federate_flags},Bool}) +| [Python](https://python.helics.org/api/capi-py/#helicsFederateInfoSetFlagOption) +| [Julia](https://julia.helics.org/latest/api/#HELICS.helicsFederateInfoSetFlagOption-Tuple{HELICS.FederateInfo,%20Union{Int64,%20HELICS.Lib.HelicsFederateFlags},%20Bool}) _Property's enumerated name:_ `HELICS_HANDLE_OPTION_STRICT_TYPE_CHECKING` [414] @@ -916,12 +1014,13 @@ Generally, HELICS does [data type conversions where supported](../developer-guid ## Publication-only Options -### `targets` +### `targets` [null] [C++](https://docs.helics.org/en/latest/doxygen/classhelics_1_1Publication.html#abb36f297be67589f7a73c4c1fc39240b) | [C](api-reference/C_API.md#publication) -| [Python](https://python.helics.org/api/capi-py.html#helicsPublicationAddTarget) +| [Python](https://python.helics.org/api/capi-py/#helicsPublicationAddTarget) | [Julia](https://julia.helics.org/latest/api/#Publication) + Used to specify which inputs should receive the values from this output. This can be a list of output keys/names. ## Input-only Options @@ -932,19 +1031,20 @@ Inputs can receive values from multiple sending handles and the means by which t [C++](https://docs.helics.org/en/latest/doxygen/classhelics_1_1Input.html#a017ad953343ac7758fbf1f45ea54d1eb) | [C](api-reference/C_API.md#input) -| [Python](https://python.helics.org/api/capi-py.html#helicsInputAddTarget) +| [Python](https://python.helics.org/api/capi-py/#helicsInputAddTarget) | [Julia](https://julia.helics.org/latest/api/#Input) + Inputs can specify which outputs (typically publications) they should be pulling from. This is similar to subscriptions but inputs can allow multiple outputs to feed to the same input. This can be a list of output keys/names. --- -### `connections` [] +### `connections` [null] _API:_ `helicsInputSetOption` -[C++](https://docs.helics.org/en/latest/doxygen/classhelics_1_1CoreFederateInfo.html#a63efa7762fdc8a9d9869bbed6939448e) +[C++](https://docs.helics.org/en/latest/doxygen/group__Information.html#ga7eb9a9058a92cb27b6b370fbff5a5ceb) | [C](api-reference/C_API.md#input) -| [Python](https://python.helics.org/api/capi-py.html#helicsInputSetOption) -| [Julia](https://julia.helics.org/latest/api/#HELICS.helicsInputSetOption-Tuple{HELICS.Subscription,Union{Int64,%20HELICS.Lib.helics_handle_options},Bool}) +| [Python](https://python.helics.org/api/capi-py/#helicsInputSetOption) +| [Julia](https://julia.helics.org/latest/api/#HELICS.helicsInputSetOption-Tuple{HELICS.Input,%20Union{Int64,%20HELICS.Lib.HelicsHandleOptions},%20Bool}) _Property's enumerated name:_ `HELICS_HANDLE_OPTION_CONNECTIONS` [522] @@ -952,13 +1052,15 @@ Allows an integer number of connections to be considered value for this input ha --- -### `input_priority_location` | `inputprioritylocation` | `inputPriorityLocation` [] +### `input_priority_location` [null] + +_Alternative names:_ `inputprioritylocation`, `inputPriorityLocation` _API:_ `helicsInputSetOption` -[C++](https://docs.helics.org/en/latest/doxygen/group__Information.html#ga5cb76ace18e1fa7cedd1d5ed8a56f3d1) +[C++](https://docs.helics.org/en/latest/doxygen/group__Information.html#ga7eb9a9058a92cb27b6b370fbff5a5ceb) | [C](api-reference/C_API.md#input) -| [Python](https://python.helics.org/api/capi-py.html#helicsInputSetOption) -| [Julia](https://julia.helics.org/latest/api/#HELICS.helicsInputSetOption-Tuple{HELICS.Subscription,Union{Int64,%20HELICS.Lib.helics_handle_options},Bool}) +| [Python](https://python.helics.org/api/capi-py/#helicsInputSetOption) +| [Julia](https://julia.helics.org/latest/api/#HELICS.helicsInputSetOption-Tuple{HELICS.Input,%20Union{Int64,%20HELICS.Lib.HelicsHandleOptions},%20Bool}) _Property's enumerated name:_ `HELICS_HANDLE_OPTION_INPUT_PRIORITY_LOCATION` [510] @@ -966,13 +1068,15 @@ When receiving values from multiple sending handles, when the values are receive --- -### `clear_priority_list` | `clearprioritylist` | `clearPriorityList` [false] +### `clear_priority_list` [false] + +_Alternative names:_ `clearprioritylist`, `clearPriorityList` _API:_ `helicsInputSetOption` -[C++](https://docs.helics.org/en/latest/doxygen/group__Information.html#ga5cb76ace18e1fa7cedd1d5ed8a56f3d1) +[C++](https://docs.helics.org/en/latest/doxygen/group__Information.html#ga7eb9a9058a92cb27b6b370fbff5a5ceb) | [C](api-reference/C_API.md#input) -| [Python](https://python.helics.org/api/capi-py.html#helicsInputSetOption) -| [Julia](https://julia.helics.org/latest/api/#HELICS.helicsInputSetOption-Tuple{HELICS.Subscription,Union{Int64,%20HELICS.Lib.helics_handle_options},Bool}) +| [Python](https://python.helics.org/api/capi-py/#helicsInputSetOption) +| [Julia](https://julia.helics.org/latest/api/#HELICS.helicsInputSetOption-Tuple{HELICS.Input,%20Union{Int64,%20HELICS.Lib.HelicsHandleOptions},%20Bool}) _Property's enumerated name:_ `HELICS_HANDLE_OPTION_CLEAR_PRIORITY_LIST` [512] @@ -980,26 +1084,30 @@ When receiving values from multiple sending handles, when the values are receive --- -### `single_connection_only` | `singleconnectiononly` |`singleConnectionOnly` [false] +### `single_connection_only` [false] + +_Alternative names:_ `singleconnectiononly`, `singleConnectionOnly` _API:_ `helicsInputSetOption` -[C++](https://docs.helics.org/en/latest/doxygen/group__Information.html#ga5cb76ace18e1fa7cedd1d5ed8a56f3d1) +[C++](https://docs.helics.org/en/latest/doxygen/group__Information.html#ga7eb9a9058a92cb27b6b370fbff5a5ceb) | [C](api-reference/C_API.md#input) -| [Python](https://python.helics.org/api/capi-py.html#helicsInputSetOption) -| [Julia](https://julia.helics.org/latest/api/#HELICS.helicsInputSetOption-Tuple{HELICS.Subscription,Union{Int64,%20HELICS.Lib.helics_handle_options},Bool}) +| [Python](https://python.helics.org/api/capi-py/#helicsInputSetOption) +| [Julia](https://julia.helics.org/latest/api/#HELICS.helicsInputSetOption-Tuple{HELICS.Input,%20Union{Int64,%20HELICS.Lib.HelicsHandleOptions},%20Bool}) _Property's enumerated name:_ `HELICS_HANDLE_OPTION_SINGLE_CONNECTION_ONLY` [407] When set, this forces the input handle to have only one sending handle it will receive from. Setting this flag serves as a sort of double-check to ensure that only one other handle is sending to this input handle and that the federation has been configured as expected. --- -### `multiple_connections_allowed` | `multipleconnectionsallowed` | `multipleConnectionsAllowed` [true] +### `multiple_connections_allowed` [true] + +_Alternative names:_ `multipleconnectionsallowed`, `multipleConnectionsAllowed` _API:_ `helicsInputSetOption` -[C++](https://docs.helics.org/en/latest/doxygen/group__Information.html#ga5cb76ace18e1fa7cedd1d5ed8a56f3d1) +[C++](https://docs.helics.org/en/latest/doxygen/group__Information.html#ga7eb9a9058a92cb27b6b370fbff5a5ceb) | [C](api-reference/C_API.md#input) -| [Python](https://python.helics.org/api/capi-py.html#helicsInputSetOption) -| [Julia](https://julia.helics.org/latest/api/#HELICS.helicsInputSetOption-Tuple{HELICS.Subscription,Union{Int64,%20HELICS.Lib.helics_handle_options},Bool}) +| [Python](https://python.helics.org/api/capi-py/#helicsInputSetOption) +| [Julia](https://julia.helics.org/latest/api/#HELICS.helicsInputSetOption-Tuple{HELICS.Input,%20Union{Int64,%20HELICS.Lib.HelicsHandleOptions},%20Bool}) _Property's enumerated name:_ `HELICS_HANDLE_OPTION_MULTIPLE_CONNECTIONS_ALLOWED` [409] @@ -1007,13 +1115,15 @@ When set, this flag allows the input handle to receive valuesfrom multiple other --- -### `multi_input_handling_method` | `multiinputhandlingmethod` | `multiInputHandlingMethod` [`none`] +### `multi_input_handling_method` [`none`] + +_Alternative names:_ `multiinputhandlingmethod`, `multiInputHandlingMethod` _API:_ `helicsInputSetOption` -[C++](https://docs.helics.org/en/latest/doxygen/group__Information.html#ga5cb76ace18e1fa7cedd1d5ed8a56f3d1) +[C++](https://docs.helics.org/en/latest/doxygen/group__Information.html#ga7eb9a9058a92cb27b6b370fbff5a5ceb) | [C](api-reference/C_API.md#input) -| [Python](https://python.helics.org/api/capi-py.html#helicsInputSetOption) -| [Julia](https://julia.helics.org/latest/api/#HELICS.helicsInputSetOption-Tuple{HELICS.Subscription,Union{Int64,%20HELICS.Lib.helics_handle_options},Bool}) +| [Python](https://python.helics.org/api/capi-py/#helicsInputSetOption) +| [Julia](https://julia.helics.org/latest/api/#HELICS.helicsInputSetOption-Tuple{HELICS.Input,%20Union{Int64,%20HELICS.Lib.HelicsHandleOptions},%20Bool}) _Property's enumerated name:_ `HELICS_HANDLE_OPTION_MULTI_INPUT_HANDLING_METHOD` [507] _Property values:_ @@ -1039,8 +1149,8 @@ As in the value handles, the registration of endpoints is done through a single _API:_ `helicsFederateRegisterEndpoint` [C++](https://docs.helics.org/en/latest/doxygen/MessageFederate_8h.html#a2eb3f4680791a817b7654f0b6ca97d4d) | [C](api-reference/C_API.md#federate) -| [Python](https://python.helics.org/api/capi-py.html#helicsFederateRegisterEndpoint) -| [Julia](https://julia.helics.org/latest/api/#HELICS.helicsFederateRegisterEndpoint-Tuple{HELICS.Federate,String,String}) +| [Python](https://python.helics.org/api/capi-py/#helicsFederateRegisterEndpoint) +| [Julia](https://julia.helics.org/latest/api/#HELICS.helicsFederateRegisterEndpoint-Tuple{HELICS.Federate,%20String,%20String}) ### `name` (required) @@ -1048,7 +1158,7 @@ The name of the endpoint as it will be known to the rest of the federation. --- -### `type` [] +### `type` [null] _API:_ (none) @@ -1056,19 +1166,21 @@ HELICS supports data types and data type conversion ([as best it can](https://ww --- -### `destination` | `target` [] +### `destination` [null] + +_Alternative names:_ `target` _API:_ `helicsEndpointSetDefaultDestination` -[C++](https://docs.helics.org/en/latest/doxygen/MessageFederate_8h.html#a4d32466958d0b47ded8825380275d787) +[C++](https://docs.helics.org/en/latest/doxygen/MessageFederate_8h.html#a14821937c957403bb1392c7df6790529) | [C](api-reference/C_API.md#endpoint) -| [Python](https://python.helics.org/api/capi-py.html#helicsEndpointSetDefaultDestination) -| [Julia](https://julia.helics.org/latest/api/#HELICS.helicsEndpointSetDefaultDestination-Tuple{HELICS.Endpoint,String}) +| [Python](https://python.helics.org/api/capi-py/#helicsEndpointSetDefaultDestination) +| [Julia](https://julia.helics.org/latest/api/#HELICS.helicsEndpointSetDefaultDestination-Tuple{HELICS.Endpoint,%20String}) Defines the default destination for a message sent from this endpoint. --- -### `alias` [] +### `alias` [null] _API:_ (none) @@ -1076,13 +1188,13 @@ Creates a local alias for a handle that may have a long name. --- -### `subscriptions` [] +### `subscriptions` [null] _API:_ `helicsEndpointSubscribe` -[C++](https://docs.helics.org/en/latest/doxygen/MessageFederate_8h.html#ae7ab88b9e49dc6c3ef5f2042b1890a45) +[C++](https://docs.helics.org/en/latest/doxygen/MessageFederate_8h.html#a4a46f16a60b4d4c539b7f8d7113d7b54) | [C](api-reference/C_API.md#endpoint) -| [Python](https://python.helics.org/api/capi-py.html#helicsEndpointSubscribe) -| [Julia](https://julia.helics.org/latest/api/#HELICS.helicsEndpointSubscribe-Tuple{HELICS.Endpoint,String}) +| [Python](https://python.helics.org/api/capi-py/#helicsEndpointSubscribe) +| [Julia](https://julia.helics.org/latest/api/#HELICS.helicsEndpointSubscribe-Tuple{HELICS.Endpoint,%20String}) --- @@ -1095,10 +1207,10 @@ See section on Filter Options. ### `info` [""] _API:_ `helicsEndpointSetInfo` -[C++](https://docs.helics.org/en/latest/doxygen/MessageFederate_8h.html#acb58eb5e9fca5c05451592d4a76de524) +[C++](https://docs.helics.org/en/latest/doxygen/MessageFederate_8h.html#af935c7f5ba547a19d1164c6d62f4f79a) | [C](api-reference/C_API.md#endpoint) -| [Python](https://python.helics.org/api/capi-py.html#helicsEndpointSetInfo) -| [Julia](https://julia.helics.org/latest/api/#HELICS.helicsEndpointSetInfo-Tuple{HELICS.Endpoint,String}) +| [Python](https://python.helics.org/api/capi-py/#helicsEndpointSetInfo) +| [Julia](https://julia.helics.org/latest/api/#HELICS.helicsEndpointSetInfo-Tuple{HELICS.Endpoint,%20String}) The `info` field is entirely ignored by HELICS and is used as a mechanism to pass configuration information to the federate so that it can properly integrate into the federation. Thus, there is no standard content or format for this field; it is entirely up to the individual simulators to decide how the data in this field (if any) should be used. Often it is used by simulators to map the HELICS names into internal variable names as shown in the above example. ## Filter Options @@ -1113,24 +1225,28 @@ Custom filters may have input and output types associated with them. This is used for chaining and automatic ordering of filters. Filters do not have to be defined on the same core as the endpoint, and in fact can be anywhere in the federation, any messages will be automatically routed appropriately. -_API:_ `helicsFederateRegisterFilter` -([C++](https://docs.helics.org/en/latest/doxygen/MessageFilters_8h.html#ae51e3c5dc5a974b3f1ec4c37e4901580) +_API:_ + +`helicsFederateRegisterFilter` +([C++](https://docs.helics.org/en/latest/doxygen/MessageFilters_8h.html#ad73223d527cfb6ff9179b7beb3a092cb) | [C](api-reference/C_API.md#federate) -| [Python](https://python.helics.org/api/capi-py.html#helicsFederateRegisterFilter) -| [Julia](https://julia.helics.org/latest/api/#HELICS.helicsFederateRegisterFilter-Tuple{HELICS.Federate,Union{Int64,%20HELICS.Lib.helics_filter_type},String})) -to create/register the filter and then `helicsFilterAddSourceTarget` -([C++](https://docs.helics.org/en/latest/doxygen/MessageFilters_8h.html#ae3c07304f81645db5f92fd4a3b9e53ce) +| [Python](https://julia.helics.org/latest/api/#HELICS.helicsFederateRegisterFilter-Tuple{HELICS.Federate,%20Union{Int64,%20HELICS.Lib.HelicsFilterTypes},%20String}) +| [Julia](https://julia.helics.org/latest/api/#HELICS.helicsFederateRegisterFilter-Tuple{HELICS.Federate,%20Union{Int64,%20HELICS.Lib.HelicsFilterTypes},%20String})) +to create/register the filter and then + +`helicsFilterAddSourceTarget` +([C++](https://docs.helics.org/en/latest/doxygen/MessageFilters_8h.html#a40d2017f51dca63c1b034df70c35c655) | [C](api-reference/C_API.md#filter) -| [Python](https://python.helics.org/api/capi-py.html#helicsFilterAddSourceTarget) -| [Julia](https://julia.helics.org/latest/api/#HELICS.helicsFilterAddSourceTarget-Tuple{HELICS.Filter,String})) +| [Python](https://python.helics.org/api/capi-py/#helicsFilterAddSourceTarget) +| [Julia](https://julia.helics.org/latest/api/#HELICS.helicsFilterAddSourceTarget-Tuple{HELICS.Filter,%20String})) or `helicsFilterAddDestinationTarget` -([C++](https://docs.helics.org/en/latest/doxygen/MessageFilters_8h.html#a664e4b45227a9e1070951376836eb8d6) +([C++](https://docs.helics.org/en/latest/doxygen/MessageFilters_8h.html#aa197abc9f9c07f9d8fbe39aef588965f) | [C](api-reference/C_API.md#filter) -| [Python](https://python.helics.org/api/capi-py.html#helicsFilterAddDestinationTarget) -| [Julia](https://julia.helics.org/latest/api/#HELICS.helicsFilterAddDestinationTarget-Tuple{HELICS.Filter,String})) +| [Python](https://python.helics.org/api/capi-py/#helicsFilterAddDestinationTarget) +| [Julia](https://julia.helics.org/latest/api/#HELICS.helicsFilterAddDestinationTarget-Tuple{HELICS.Filter,%20String})) to associate it with a specific endpoint -### `name` [] +### `name` [null] _API:_ (none) @@ -1138,48 +1254,52 @@ Name of the filter; must be unique to a federate. --- -### `source_targets`, `sourcetargets`, `sourceTargets` [] +### `source_targets` [null] + +_Alternative names:_ `sourcetargets`, `sourceTargets` _API:_ `helicsFilterAddSourceTarget` [C++](https://docs.helics.org/en/latest/doxygen/MessageFilters_8h.html#a40d2017f51dca63c1b034df70c35c655) | [C](https://docs.helics.org/en/latest/references/api-reference/C_API.html#filter) -| [Python](https://python.helics.org/api/capi-py.html#helicsFilterAddSourceTarget) +| [Python](https://python.helics.org/api/capi-py/#helicsFilterAddSourceTarget) | [Julia](https://julia.helics.org/latest/api/#HELICS.helicsFilterAddSourceTarget-Tuple{HELICS.Filter,%20String}) Acts on previously registered filter and associated with a specific endpoint of the federate. --- -### `destination_targets`, `destinationtargets`, `destinationtargets` [] +### `destination_targets` [null] + +_Alternative names:_ `destinationtargets`, `destinationtargets` _API:_ `helicsFilterAddDestinationTarget` [C++](https://docs.helics.org/en/latest/doxygen/MessageFilters_8h.html#aa197abc9f9c07f9d8fbe39aef588965f) | [C](https://docs.helics.org/en/latest/references/api-reference/C_API.html#filter) -| [Python](https://python.helics.org/api/capi-py.html#helicsFilterAddDestinationTarget) +| [Python](https://python.helics.org/api/capi-py/#helicsFilterAddDestinationTarget) | [Julia](https://julia.helics.org/latest/api/#HELICS.helicsFilterAddDestinationTarget-Tuple{HELICS.Filter,%20String}) Acts on previously registered filter and associated with a specific endpoint of the federate. --- -### `info` [""] +### `info` [null] _API:_ `helicsFilterSetInfo` -[C++](https://docs.helics.org/en/latest/doxygen/group__Clone.html#gaf8d846ddb206fdbc7c22769f4a2b2f9b) +[C++](https://docs.helics.org/en/latest/doxygen/group__Clone.html#gaea3f69061b5ee71dac977fad59f62083) | [C](api-reference/C_API.md#filter) -| [Python](https://python.helics.org/api/capi-py.html#helicsFilterSetInfo) -| [Julia](https://julia.helics.org/latest/api/#HELICS.helicsFilterSetInfo-Tuple{HELICS.Filter,String}}) +| [Python](https://python.helics.org/api/capi-py/#helicsFilterSetInfo) +| [Julia](https://julia.helics.org/latest/api/#HELICS.helicsFilterSetInfo-Tuple{HELICS.Filter,%20String}) The `info` field is entirely ignored by HELICS and is used as a mechanism to pass configuration information to the federate so that it can properly integrate into the federation. Thus, there is no standard content or format for this field; it is entirely up to the individual simulators to decide how the data in this field (if any) should be used. Often it is used by simulators to map the HELICS names into internal variable names as shown in the above example. --- -### `operation` [] +### `operation` [null] _API:_ `helicsFederateRegisterFilter` -[C++](https://docs.helics.org/en/latest/doxygen/MessageFilters_8h.html#ae51e3c5dc5a974b3f1ec4c37e4901580) +[C++](https://docs.helics.org/en/latest/doxygen/MessageFilters_8h.html#ad73223d527cfb6ff9179b7beb3a092cb) | [C](api-reference/C_API.md#federate) -| [Python](https://python.helics.org/api/capi-py.html#helicsFederateRegisterFilter) -| [Julia](https://julia.helics.org/latest/api/#HELICS.helicsFederateRegisterFilter-Tuple{HELICS.Federate,Union{Int64,%20HELICS.Lib.helics_filter_type},String}) +| [Python](https://python.helics.org/api/capi-py/#helicsFederateRegisterFilter) +| [Julia](https://julia.helics.org/latest/api/#HELICS.helicsFederateRegisterFilter-Tuple{HELICS.Federate,%20Union{Int64,%20HELICS.Lib.HelicsFilterTypes},%20String}) Filters have a predefined set of operations they can perform. The following list defines the valid operations for filters. Most filters require additional specifications in properties data structure, an example of which is shown for each filter type. @@ -1217,8 +1337,9 @@ Example `property` object: }, ``` -#### `random_delay` | `randomdelay` | `randomDelay` +#### `random_delay` [null] +_Alternative names:_ `randomdelay`, `randomDelay` This filter will randomly delay a message according to specified random distribution available options include distribution selection, and 2 parameters for the distribution some distributions only take one parameter in which case the second is ignored. The distributions available are based on those available in the C++ [random](http://www.cplusplus.com/reference/random/) library. @@ -1308,17 +1429,97 @@ This filter will copy a message and send it to the original destination plus a n }, ``` +## Translator Options + +Translators are used to bridge the gap between the value and message interfaces allowing publications to be sent to endpoints and endpoint messages to be sent to inputs as values. A translator functions as publication, input, and endpoint that other interfaces including filters can connect to. Further details can be found on the [documentation page covering translators](../user-guide/advanced_topics/translators). + +_API:_ `helicsCoreRegisterTranslator` +[C++](https://docs.helics.org/en/latest/doxygen/classhelics_1_1Translator.html#a34a960d2259756912ad1dd6e70609416) +| [C]() +| [Python](https://python.helics.org/api/capi-py/#helicsCoreRegisterTranslator) +| [Julia](https://julia.helics.org/latest/api/#HELICS.helicsCoreRegisterTranslator-Tuple{HELICS.Core,%20Int64,%20String}) + +or + +_API:_ `helicsFederateRegisterGlobalTranslator` +[C++](https://docs.helics.org/en/latest/doxygen/classhelics_1_1Translator.html#a16f2ce4896c3f5e72d353b10584102a5) +| [C]() +| [Python](https://python.helics.org/api/capi-py/#helicsFederateRegisterGlobalTranslator) +| [Julia](https://julia.helics.org/latest/api/#HELICS.helicsFederateRegisterGlobalTranslator-Tuple{HELICS.Federate,%20Int64,%20String}) + +--- + +### `name` [null] + +_API:_ (none, done as part of registering the translator) + +Name of the filter; must be unique to a federate. + +--- + +### `type` [null] + +_API:_ (none, done as part of registering the translator) + +Type of translator; determines the format of the data on the endpoint side of the translator. Must be one of the following: `HELICS_TRANSLATOR_TYPE_CUSTOM`, `HELICS_TRANSLATOR_TYPE_JSON`, or `HELICS_TRANSLATOR_TYPE_BINARY`. + +--- + +### `source_targets` [null] + +_Alternative names:_ `sourcetargets`, `sourceTargets` + +_API:_ `helicsTranslatorAddPublicationTarget` +[C++](https://docs.helics.org/en/latest/doxygen/classhelics_1_1Translator.html) +| [C]() +| [Python](https://python.helics.org/api/capi-py/#helicsTranslatorAddPublicationTarget) +| [Julia](https://julia.helics.org/latest/api/#HELICS.helicsTranslatorAddPublicationTarget-Tuple{HELICS.Translator,%20String}) + +or + +_API:_ `helicsTranslatorAddSourceEndpoint` +[C++](https://docs.helics.org/en/latest/doxygen/classhelics_1_1Translator.html) +| [C]() +| [Python](https://python.helics.org/api/capi-py/#helicsTranslatorAddSourceEndpoint) +| [Julia](https://julia.helics.org/latest/api/#HELICS.helicsTranslatorAddSourceEndpoint-Tuple{HELICS.Translator,%20String}) + +Connects the specified publication to the translator's input or adds the translator's endpoint as a destination for all messages coming from the specified endpoint. + +--- + +### `destination_targets` [null] + +_Alternative names:_ `destinationtargets`, `destinationTargets` + +_API:_ `helicsTranslatorAddInputTarget` +[C++](https://docs.helics.org/en/latest/doxygen/classhelics_1_1Translator.html) +| [C]() +| [Python](https://python.helics.org/api/capi-py/#helicsTranslatorAddInputTarget) +| [Julia](https://julia.helics.org/latest/api/#HELICS.helicsTranslatorAddInputTarget-Tuple{HELICS.Translator,%20String}) + +or + +_API:_ `helicsTranslatorAddDestinationEndpoint` +[C++](https://docs.helics.org/en/latest/doxygen/classhelics_1_1Translator.html) +| [C]() +| [Python](https://python.helics.org/api/capi-py/#helicsTranslatorAddDestinationEndpoint) +| [Julia](https://julia.helics.org/latest/api/#HELICS.helicsTranslatorAddDestinationEndpoint-Tuple{HELICS.Translator,%20String}) + +Connects the specified input to the translator's publication (output) or adds the specified endpoint as a destination for all messages coming from the translator's endpoint. + +--- + ## Profiling -HELICS 2.8 and v3.0.1 have a profiling capability that allows users to measure the time spent waiting for HELICS to grant it time and how much time is spent executing native code. These measurements are the foundation to understanding how to improve computation performance in a federation. Further details are provided in the [Profiling page in the User Guide.](../user-guide/advanced_topics/profiling.md) When enabling profiling at the federate level there are a few APIs that can be utilized. +HELICS has a profiling capability that allows users to measure the time spent waiting for HELICS to grant it time and how much time is spent executing native code. These measurements are the foundation to understanding how to improve computation performance in a federation. Further details are provided in the [Profiling page in the User Guide.](../user-guide/advanced_topics/profiling.md) When enabling profiling at the federate level there are a few APIs that can be utilized. ### `profiling` [false] _API:_ `helicsFederateInfoSetFlagOption` [C++](https://docs.helics.org/en/latest/doxygen/classhelics_1_1CoreFederateInfo.html#a63efa7762fdc8a9d9869bbed6939448e) | [C](api-reference/C_API.md#federateinfo) -| [Python](https://python.helics.org/api/capi-py.html#helicsFederateInfoSetFlagOption) -| [Julia](https://julia.helics.org/latest/api/#HELICS.helicsFederateInfoSetFlagOption-Tuple{HELICS.FederateInfo,Union{Int64,%20HELICS.Lib.helics_federate_flags},Bool}) +| [Python](https://python.helics.org/api/capi-py/#helicsFederateInfoSetFlagOption) +| [Julia](https://julia.helics.org/latest/api/#HELICS.helicsFederateInfoSetFlagOption-Tuple{HELICS.FederateInfo,%20Union{Int64,%20HELICS.Lib.HelicsFederateFlags},%20Bool}) _Property's enumerated name:_ `HELICS_FLAG_PROFILING` [93] @@ -1326,7 +1527,7 @@ Setting this flag enables profiling for the federate. --- -### `profiler` [""] +### `profiler` [null] Turns on profiling for the federate and allows the specification of the log file where profiling messages will be written. No API is possible with this option as it must be specified prior to the creation of the federates. @@ -1337,8 +1538,8 @@ Turns on profiling for the federate and allows the specification of the log file _API:_ `helicsFederateInfoSetFlagOption` [C++](https://docs.helics.org/en/latest/doxygen/classhelics_1_1CoreFederateInfo.html#a63efa7762fdc8a9d9869bbed6939448e) | [C](api-reference/C_API.md#federateinfo) -| [Python](https://python.helics.org/api/capi-py.html#helicsFederateInfoSetFlagOption) -| [Julia](https://julia.helics.org/latest/api/#HELICS.helicsFederateInfoSetFlagOption-Tuple{HELICS.FederateInfo,Union{Int64,%20HELICS.Lib.helics_federate_flags},Bool}) +| [Python](https://python.helics.org/api/capi-py/#helicsFederateInfoSetFlagOption) +| [Julia](https://julia.helics.org/latest/api/#HELICS.helicsFederateInfoSetFlagOption-Tuple{HELICS.FederateInfo,%20Union{Int64,%20HELICS.Lib.HelicsFederateFlags},%20Bool}) _Property's enumerated name:_ `HELICS_FLAG_LOCAL_PROFILING_CAPTURE` [96] @@ -1351,8 +1552,8 @@ Setting this flag sends the profiling messages to the local federate log rather _API:_ `helicsFederateInfoSetFlagOption` [C++](https://docs.helics.org/en/latest/doxygen/classhelics_1_1CoreFederateInfo.html#a63efa7762fdc8a9d9869bbed6939448e) | [C](api-reference/C_API.md#federateinfo) -| [Python](https://python.helics.org/api/capi-py.html#helicsFederateInfoSetFlagOption) -| [Julia](https://julia.helics.org/latest/api/#HELICS.helicsFederateInfoSetFlagOption-Tuple{HELICS.FederateInfo,Union{Int64,%20HELICS.Lib.helics_federate_flags},Bool}) +| [Python](https://python.helics.org/api/capi-py/#helicsFederateInfoSetFlagOption) +| [Julia](https://julia.helics.org/latest/api/#HELICS.helicsFederateInfoSetFlagOption-Tuple{HELICS.FederateInfo,%20Union{Int64,%20HELICS.Lib.HelicsFederateFlags},%20Bool}) _Property's enumerated name:_ `HELICS_FLAG_PROFILING_MARKER` [95] @@ -1370,7 +1571,9 @@ See multiple options for --local, --ipv4, --ipv6, --all --- -### `reuse_address` | `reuseaddress` | `reuseAddress` [false] +### `reuse_address` [false] + +_Alternative names:_ `reuseaddress`, `reuseAddress` _API:_ (none) @@ -1378,13 +1581,16 @@ Allows the server to reuse a bound address, mostly useful for tcp cores. --- -### `noack_connect` | `noackconnect` | `noackConnect` [false] +### `noack_connect` [false] +_Alternative names:_ `noackconnect`, `noackConnect` Specify that a connection_ack message is not required to be connected with a broker. --- -### `max_size` | `maxsize` | `maxSize`[4096] +### `max_size` [4096] + +_Alternative names:_ `maxsize`, `maxSize` _API:_ (none) @@ -1392,7 +1598,9 @@ Message buffer size. Can be increased for large messages to limit the number of --- -### `max_count` | `maxcount` | `maxCount` [256] +### `max_count` [256] + +_Alternative names:_ `maxcount`, `maxCount` _API:_ (none) @@ -1400,7 +1608,9 @@ Maximum number of messages in queue. Can be increased for large volumes of messa --- -### `network_retries` | `networkretries` | `networkRetries` [5] +### `network_retries` [5] + +_Alternative names:_ `networkretries`, `networkRetries` _API:_ (none) Maximum number of network retry attempts. @@ -1416,12 +1626,16 @@ set to true to enable encryption on network types that support encryption ### `encryption_config` +_Alternative names:_ `encryptionconfig`, `encryptionConfig` + _API:_ (none) specify json or a file containing the configuration options for defining the encrypted interface --- -### `use_os_port` | `useosport` | `useOsPort` [false] +### `use_os_port` [false] + +_Alternative names:_ `useosport`, `useOsPort` _API:_ (none) Setting this flag specifies that the OS should set the port for the HELICS message bus. HELICS will ask the operating system which port to use and will use the indicated port. @@ -1435,14 +1649,18 @@ specify that the network connection should be a server or client. By default nei --- -### `local_interface` | `localinterface` | `localInterface` [local address] +### `local_interface` [local IP address] + +_Alternative names:_ `localinterface`, `localInterface` _API:_ (none) Specifies the IP address (and optionally port) the rest of the federation should use when contacting this federate. --- -### `broker_address` | `brokeraddress` | `brokerAddress` [] +### `broker_address` [local IP address] + +_Alternative names:_ `brokeraddress`, `brokerAddress` _API:_ (none) @@ -1450,7 +1668,9 @@ Specifies the IP address (and optionally port) a federate or sub-broker should u --- -### `broker_port` | `brokerport` | `brokerPort` [] +### `broker_port` [] + +_Alternative names:_ `brokerport`, `brokerPort` _API:_ (none) @@ -1458,27 +1678,33 @@ Specifies the port a federate or sub-broker should use when contacting its paren --- -### `broker_name` | `brokername` | `brokerName` [] +### `broker_name` [null] + +_Alternative names:_ `brokername`, `brokerName` _API:_ (none) --- -### `local_port` | `localport` | `localPort` [] +### `local_port` [] +_Alternative names:_ `localport`, `localPort` _API:_ (none) + Specifies the port the rest of the federation should use when contacting this federate. --- -### `port_start` | `portstart` | `portStart` [] +### `port_start` [] + +_Alternative names:_ `portstart`, `portStart` _API:_ (none) starting port for automatic port definitions. --- -### `force` [] +### `force` [false] _API:_ (none) Flag specifying that the broker network connection should attempt to override and terminate any existing broker using the specified port. diff --git a/docs/references/index.md b/docs/references/index.md index 3cbd190561..90e17d8d6d 100644 --- a/docs/references/index.md +++ b/docs/references/index.md @@ -1,14 +1,16 @@ # References +This section is most useful for those that are acting as integrators, getting a new simulation tool or custom code working as a HELICS federate. It provides references to the existing functionality HELICS provides as well as links to tools that are currently integrated with HELICS, both external simulation tools and internal support tools. + ```{eval-rst} .. toctree:: - :hidden: :maxdepth: 1 + api-reference/index + configuration_options_reference Tools_using_HELICS apps/index - configuration_options_reference - api-reference/index + ``` diff --git a/docs/requirements.txt b/docs/requirements.txt index 13f42400d2..ef02e81ff9 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -1,10 +1,10 @@ -sphinx==4.2.0 -sphinx_rtd_theme==1.0.0 -myst-parser==0.15.2 -ipython==7.31.1 -ipykernel==6.4.2 -breathe==4.31.0 -sphinxcontrib-svg2pdfconverter==1.1.1 +sphinx==7.2.6 +sphinx_rtd_theme==2.0.0 +myst-parser==2.0.0 +ipython==8.20.0 +ipykernel==6.29.0 +breathe==4.35.0 +sphinxcontrib-svg2pdfconverter==1.2.2 requests==2.31.0 gmlc-tdc-sphinxcontrib-redoc==1.6.1a1 -sphinxcontrib-mermaid==0.8.1 +sphinxcontrib-mermaid==0.9.2 diff --git a/docs/swagger/reference/queries.yaml b/docs/swagger/reference/queries.yaml index d2f9e4db2f..dc877ac82e 100644 --- a/docs/swagger/reference/queries.yaml +++ b/docs/swagger/reference/queries.yaml @@ -5,7 +5,7 @@ info: contact: name: Philip Top url: helics.org - email: helicsteam@helics.org + email: support@helics.org license: name: BSD-3 url: "https://github.com/GMLC-TDC/HELICS/blob/main/LICENSE" diff --git a/docs/swagger/reference/web-server.json b/docs/swagger/reference/web-server.json index 2c8b03fc41..99b36d1977 100644 --- a/docs/swagger/reference/web-server.json +++ b/docs/swagger/reference/web-server.json @@ -315,7 +315,7 @@ } } }, - "description": "This is supplying 2 parameters in the address, the parameters can also be supplied as a qeury parameter or in the body" + "description": "This is supplying 2 parameters in the address, the parameters can also be supplied as a query parameter or in the body" }, "parameters": [ { diff --git a/docs/user-guide/advanced_topics/CoreTypes.md b/docs/user-guide/advanced_topics/CoreTypes.md index 5d5376fd78..0701e36730 100644 --- a/docs/user-guide/advanced_topics/CoreTypes.md +++ b/docs/user-guide/advanced_topics/CoreTypes.md @@ -30,7 +30,7 @@ The ZMQ_SS core also uses ZMQ for the underlying messaging technology but was de ## UDP -UDP cores sends IP messages and caries with it the traditional limitation of UDP messging: no guaranteed delivery or order of received messages. It may be faster in cases with highly reliable networking. It's primary use is for performance testing and the UDP core uses [asio](https://think-async.com/Asio/) for networking. +UDP cores sends IP messages and caries with it the traditional limitation of UDP messaging: no guaranteed delivery or order of received messages. It may be faster in cases with highly reliable networking. It's primary use is for performance testing and the UDP core uses [asio](https://think-async.com/Asio/) for networking. ## TCP diff --git a/docs/user-guide/advanced_topics/advanced_topics_index.md b/docs/user-guide/advanced_topics/advanced_topics_index.md index e600277d80..fc746a7061 100644 --- a/docs/user-guide/advanced_topics/advanced_topics_index.md +++ b/docs/user-guide/advanced_topics/advanced_topics_index.md @@ -5,21 +5,27 @@ :maxdepth: 1 :hidden: - multiSourceInputs + aliases architectures - queries - webserver - CoreTypes - multibroker broker_hierarchies + callbacks + CallbackFederate + commandInterface + CoreTypes + dynamic_federations + encrypted_communication environment_variables - simultaneous_cosimulations + iteration + multibroker broker_multicomputer + multiSourceInputs + networking orchestration program_termination profiling + queries + simultaneous_cosimulations targeted_endpoints - dynamic_federations timeouts commandInterface iteration @@ -42,21 +48,27 @@ The Advanced Topics section will dig into specific features of HELICS that are l The Advanced Topics will cover: -- [**Multi-Source Inputs**](./multiSourceInputs.md) - Using inputs (rather than subscriptions), it is possible to accept value signals from multiple sources. This section discusses the various tools HELICS provides for managing how to handle/resolve what can be conflicting or inconsistent signal data. +- [**Aliases**](./aliases.md) - HELICS 3.3 introduced the notion of aliases. Aliases allow a mapping of an interface key to a different string. - [**Architectures**](./architectures.md) - Introduction to different ways to connect federates, cores, and brokers to manage efficient passing of signals in a co-simulation. -- [**Queries**](./queries.md) - How queries can be used to get information on HELICS brokers, federates, and cores. -- [**API Webserver**](./webserver.md) - How to interact with a running co-simulation using queries. +- [**Broker Hierarchies**](./broker_hierarchies.md) - Purpose of broker hierarchies and how to configure a HELICS co-simulation to implement one. +- [**Callbacks**](./callbacks.md) - Over time a number of callbacks have been added for various operations and stages of the life cycle of a federate. This document describes the different callbacks available. +- [**Callback Federates**](./CallbackFederate.md) - HELICS 3.3 introduced a beta test for callback federates which allow a federate to operate purely inline with a core based solely on callbacks. This can allow a much higher number of federates on a given system than was previously possible. +- [**Command Interface**](./commandInterface.md) - HELICS v3 introduced the command interface as a method of asynchronously communicating between federates. - [**Cores**](./CoreTypes.md) - Discussion of the different types of message-passing buses and their implementation as HELICS cores. -- **Multiple Brokers** - - [**Connecting Multiple Core Types (Multi-Protocol Broker)**](./multibroker.md) What to do when one type of communication isn't sufficient. - - [**Broker Hierarchies**](./broker_hierarchies.md) - Purpose of broker hierarchies and how to configure a HELICS co-simulation to implement one. +- [**Dynamic Federations**](./dynamic_federations.md) - Sometimes it is useful to have a federate that is not ready at the beginning of co-simulation. This is a dynamic federation. There are various levels of this (not all are available yet) and this document discusses some aspects of dynamic co-simulation. +- [**Encrypted Communication**](./encrypted_communication.md) - How to encrypt communication between HELICS brokers/federates. - [**Environment Variables**](./environment_variables.md) - HELICS supports some environment variables for configuration of a federate or broker. -- [**Simultaneous co-simulations**](./simultaneous_cosimulations.md) - Options for running multiple independent co-simulations on a single system. +- [**Iteration**](./iteration.md) - Setting up federates so that they can iterate without advancing simulation time to achieve a more consistent state. +- [**Multi-compute-node Co-simulation**](./broker_multicomputer.md) - Executing a co-simulation across multiple compute nodes. +- [**Multi-Protocol Brokers (Multi-broker) for Multiple Core Types)**](./multibroker.md) What to do when one type of communication isn't sufficient. +- [**Multi-Source Inputs**](./multiSourceInputs.md) - Using inputs (rather than subscriptions), it is possible to accept value signals from multiple sources. This section discusses the various tools HELICS provides for managing how to handle/resolve what can be conflicting or inconsistent signal data. +- [**Networking**](networking.md) - How to configure HELICS to run in more challenging networking environments. - [**Orchestration Tool (Merlin)**](./orchestration.md) - Brief guide on using [Merlin](https://github.com/LLNL/merlin) to handle situations where a HELICS co-simulation is just one step in an automated analysis process (_e.g._ uncertainty quantification) or where assistance is needed deploying a large co-simulation in an HPC environment. - [**Program termination**](./program_termination.md) - Some additional features in HELICS related to program shutdown and co-simulation termination. - [**Profiling**](./profiling.md) - Some profiling capability for co-simulations. +- [**Queries**](./queries.md) - How queries can be used to get information on HELICS brokers, federates, and cores. +- [**Simultaneous co-simulations**](./simultaneous_cosimulations.md) - Options for running multiple independent co-simulations on a single system. - [**Targeted Endpoints**](./targeted_endpoints.md) - details on the new targeted endpoints in HELICS 3. -- [**Dynamic Federations**](./dynamic_federations.md) - Sometimes it is useful to have a federate that is not ready at the beginning of co-simulation. This is a dynamic federation. There are various levels of this (not all are available yet) and this document discusses some aspects of dynamic co-simulation. - [**Timeouts**](./timeouts.md) - HELICS includes a number of timeouts to prevent failed operations from continuing indefinitely, the various timeout options are discussed in this document. - [**Command Interface**](./commandInterface.md) - HELICS v3 introduced the command interface as a method of asynchronously communicating between federates. - [**Aliases**](./aliases.md) - HELICS 3.3 introduced the notion of aliases. Aliases allow a mapping of an interface key to a different string. @@ -64,3 +76,6 @@ The Advanced Topics will cover: - [**Callback Federates**](./CallbackFederate.md) - HELICS 3.3 introduced a beta test for callback federates which allow a federate to operate purely inline with a core based solely on callbacks. This can allow a much higher number of federates on a given system than was previously possible. - [**Networking**](./CallbackFederate.md) - HELICS provides several ways of working in more restrictive networking environments. - [**Encrypted Communication**](./encrypted_communication.md) - How to encrypt communication between HELICS brokers/federates. +- [**Timing Optimization**](./timingOptimization.md) - Guidance and recommendation on how to configure and set-up timing to optimize federation performance. +- [**Translators**](./translators.md) - Translators provide a means of HELICS message interfaces to communicate with HELICS value interfaces and vice versa. +- [**Webserver API**](./webserver.md) - How to interact with a running co-simulation using a REST-based web API. diff --git a/docs/user-guide/advanced_topics/broker_multicomputer.md b/docs/user-guide/advanced_topics/broker_multicomputer.md index 2ac70c5105..ba73f72bf2 100644 --- a/docs/user-guide/advanced_topics/broker_multicomputer.md +++ b/docs/user-guide/advanced_topics/broker_multicomputer.md @@ -10,9 +10,9 @@ Generally, there are a few changes that will be necessary for running a multi-co - Define `broker_address` for each of the federates that are running on another computer. This will look something like `"broker_address": "tcp://10.211.55.23"` if using a JSON configuration file. - The default port for the HELICS broker is 23405 and if that works in your networking environment then you don't need to do anything. To use another port, each federate must change the value for `broker_port` (_e.g._ `"broker_port": "23500"`)and the broker must set its own `local_port` option to the same value (_e.g._ `helics_broker -f 3 --loglevel=warning --ipv4 --port=23500`). -Which is not to say there can't be other networking complications. Once running on multiple computers the network configuration and configuration can create new challenges. Handling these is beyond the scope of this document but take a look at the some of the other examples to get an idea of how you might be able to handle this. There's also the [Configuration Options Reference](../../references/configuration_options_reference.md) that has a more comprehensive list of the [network configurations available](./../references/configuration_options_reference.md#Network). +Which is not to say there can't be other networking complications. Once running on multiple computers the network configuration and configuration can create new challenges. Handling these is beyond the scope of this document but take a look at the some of the other examples to get an idea of how you might be able to handle this. There's also the [Configuration Options Reference](../../references/configuration_options_reference.md) that has a more comprehensive list of the [network configurations available](../../references/configuration_options_reference.md#network). -For those that are doing configuration via APIs, the "broker_address" and "broker_port" options can be included as part of the ["core_init_string"](../../references/configuration_options_reference.md#core-init-string-coreinitstring-coreinitstring-i) for the federates and the ["broker_init_string"](../../references/configuration_options_reference.md#broker-init-string-brokerinitstring-brokerinitstring) if instantiating the broker via APIs. +For those that are doing configuration via APIs, the "broker_address" and "broker_port" options can be included as part of the ["core_init_string"](../../references/configuration_options_reference.md#core_init_string---i-null) for the federates and the ["broker_init_string"](../../references/configuration_options_reference.md#broker_init_string--null) if instantiating the broker via APIs. ## Example diff --git a/docs/user-guide/advanced_topics/dynamic_federations.md b/docs/user-guide/advanced_topics/dynamic_federations.md index 665a4f76e1..4798eb5bde 100644 --- a/docs/user-guide/advanced_topics/dynamic_federations.md +++ b/docs/user-guide/advanced_topics/dynamic_federations.md @@ -1,46 +1,70 @@ # Dynamic Federations -In general a dynamic federation is one in which the federates or simulators are not all available at the start of the co-simulation. Instead some components attach to the running co-simulation part-way through the simulation. The longer term goal of HELICS is to fully support dynamic federations but there are many complicated issues to handle timing and data communication that need to be resolved before full general dynamic federations are supported. As of HELICS 3.1 a limited though quite useful form is available through observer federates. +In general, a dynamic federation is one in which one or more federates joins the co-simulation after the co-simulation begins. Instead, some federates join the running co-simulation part-way through its execution. For example, a co-simulation with EV federates being charged by a power system federate may have EV federates joining the co-simulation to charge and leave it when charging is done. Alternatively, real-time or hardware-in-the-loop co-simulations may have federates (components) that are only needed for part of the co-simulation and join late. Dynamic federations provide greater flexibility in constructing and running co-simulations. ## Levels of Dynamic Federations -Dynamic Federations come in various flavors of complexity. The first is simply allowing additional subscriptions to existing federates. The next is allowing additional "observer" federates to join a running co-simulation. The third is allowing new publications, endpoints, or filters on existing federates. And the fourth is a full dynamic federation. +Dynamic federations can be thought of as being composed of features in increasing levels of complexity: -The first of these has been unofficially available for some time and will be supported in HELICS 3.1. Dynamic observer federates will also be allowed in HELICS 3.1, and will be detailed further in a subsequent section. The last two levels are currently a work in progress and are currently planned to be supported in HELICS 3.2 (Early 2022). +1. Allowing the additional of subscriptions to an existing federate publication by existing members of the federation. +2. Allowing federates that only receive information ("observers") to join the federation after execution has begun. As a part of joining the co-simulation the observer would need the functionality in level one to successfully subscribe to the necessary publications of other federates. +3. Allowing the creation of new publications, endpoints, or filters by existing federates which other members of the federation could then connect to as targets. +4. Allowing federates to join the co-simulation after execution has begun and create arbitrary interfaces (publications, subscriptions, endpoints, etc). This relies on all previous levels of complexity being implemented. -### Dynamic Subscriptions +HELICS v3.1 supported levels 1 and 2. HELICS v3.4 supports full dynamic federations (level 4). -In the normal case, the `registerInput`, `registerSubscription`, or `registerTargetedEndpoint` are done in the creation phase of co-simulation so all the checks and connections can be made and everything set up before `timeZero` (start of co-simulation). If these calls are made after the `enterInitializingMode` call, then the time guarantees are different. Ordinarily data published in the initialization phase would be available to all subscriptions of a publication, but with dynamic subscriptions the data is not going to be sent to the new subscription until new publications after a time request or `enterExecutingMode` call has been made. (A `bufferData` flag is in the works to allow data to be sent for dynamic subscriptions at the time of connection if set on the publisher). +## Dynamic Subscriptions -Apart from time considerations there are no additional requirements. The checks on the subscription are done immediately as opposed to waiting for the `enterInitializingMode` call. +In the normal case, the `helicsFederateRegisterInput()`, `helicsFederateRegisterSubscription()`, or `helicsFederateregisterTargetedEndpoint()` methods are called in the creation phase of co-simulation to allow for the creation of the data exchanges between federates prior to the start of co-simulation. If these calls are made after the `helicsFederateEnterInitializingMode()` call, the topology of the data exchanges between federates is altered and with it the timing dependencies. In non-dynamic federations, data published in the initialization phase is available to all subscribers of that publication as soon as as any other federate enters executing mode or makes a time request. In a dynamic federation, subscription data by default is not sent to the new (dynamically added) subscriber (or subscription) until a new publication is made after a time request or `helicsFederateEnterExecutingMode()` call has been made by the subscriber. For example, let's say Federate A publishes a value at simulation time zero and never after that point. If Federate B joins the co-simulation late and enters executing mode at simulation time five, it will not see the value published by Federate A. -### Dynamic Observer Federates +In many use cases, this lack of visibility to previously published values is a problem. For example, if the published value is a voltage, it would make sense that this value would be available to all federates even if they join late; the voltage always exists and thus should conceptually always be accessible for use by the model inside the federate. To provide persistence in this data for dynamic co-simulations, each publication can set a `bufferData` flag that retains the last value published so that any late-joining federates can access it, and this value will be sent immediately when the connection is made. This buffer is disabled by default as it does slightly increase the memory footprint of each federates using it. It is anticipated that for dynamic federations, many use cases will want to employ this flag to preserve the "always available" concept of published values. The flag can be set at the federate level so all created publications have the flag set automatically. -A federate may declare itself to be an observer in the FederateInfo structure when a federate is declared. This can be done via the command line (`--observer`) or through a flag. +## Dynamic Observer Federates -In the C++ API +A federate may declare itself to be an observer in the FederateInfo structure when a federate is declared. This can be done via the command line (`--observer`) or through a HELICS federate flag as shown below. This declares that the federate will only be receiving data, not sending any so there is no time dependency of any other federate to this one. + +C++: ```c++ FederateInfo fi; fi.observer=true; ``` -and in the C or other language API's +C: ```c helicsFederateInfoSetFlagOption(fi, HELICS_FLAG_OBSERVER,HELICS_TRUE,&err); ``` -The observer flag triggers some flags in the created core and federate to notify the broker that it can be dynamically added. Otherwise it will get an error notification that the federate is not accepting new federates. If a core is created before the new federate it must also be created with the observer flag enabled. Otherwise, it will not be allowed to join the federation. +Python: + +```python +import helics as h + +fi = h.helicsCreateFederateInfo() +h.helicsFederateInfoSetFlagOption(fi, h.HELICS_FLAG_OBSERVER, True) +``` + +The observer flag triggers functionality in the corresponding HELICS core and federate to notify the broker that it can be dynamically added. If this flag is not set an error message will be produced indicating that the federation is not accepting new federates. If a HELICS core is created before the new federate it must also be created with the observer flag enabled. -Once joined, subscriptions can be added with the same timing rules as described in the previous section. One key thing to be aware of is that for dynamic federates the time returned after enterExecutingMode is not necessarily 0, but will depend on the time of federates containing the publications or endpoints that are being linked. If there are no data pathways zero will still be returned. +Once joined, subscriptions can be added with the timing limitations as described in the previous section. Be aware that dynamic federates, after calling `helicsFederateEnterExecutingMode()`, the time returned is not necessarily zero, but will depend on the time of federates containing the publications or endpoints that are being linked. The late-joining observer federate can get current simulation time by calling `helicFederateGetCurrentTime()`, as necessary. -The utility of this capability is primarily for debugging/observation purposes. It is possible to join, get the latest data and make some queries about the current co-simulation status for monitoring purposes and disconnect. At present a new name is required each time an observer connects. This may be relaxed in the future. +Observer federates are useful for co-simulation debugging and monitoring purposes. Using an observer, it is possible to join the federation, get the latest data and make some queries about the current state of the co-simulation and then disconnect. At present, a new name is required each time an observer connects. -### Dynamic Publications +## Dynamic Publications -Dynamic publications and endpoints will be allowed in the near future. These would include just creating a publication or endpoint on an already executing federate. It would then be available for others to connect to and receive data. It would typically take at least two timesteps of the publisher to actually receive any data from the new publication. The first to ensure registration is completed and the second to publish the data. It would be possible to send the data immediately after the register call but it would be impossible (unless on the same core) for any other federate to connect until after the second request time call. +Dynamic publications and endpoints are implemented as of HELICS v3.4. For any late-joining federate, the process by which the federate joins can introduce delays in subscribers seeing the values that are published. Just as in a static co-simulation, after calling `helicsFederateEnterExecutingMode()` a federate can publish values and these values will be available to any subscribing federates the next time they make a time request. This time request is also the point at which a federate could add a subscription to the late-joining federate's publication; that is, the simulation time at which the publications of the late-joining federate become visible to the rest of the federation. No values published by the late-joining federate will be visible to the federate adding this new subscription until a subsequent time request is granted. -### Full Dynamic Federations +## Full Dynamic Federations + +Given the above limitations, as of HELICS v3.4 fully dynamic federations are supported. By setting the `--dynamic` flag on the root broker of a federation and any intermediate brokers or cores to which dynamic federates may be added, federates may join the federation late. (HELICS have always been able to leave a federation early.) And as with observer federates, after calling `helicsFederateEnterExecutingMode()` + +## Example + +An example of dynamic federation operation is under development though HELICS makes it very easy to support a dynamic federation. Simply add `--dynamic` to the broker initialization string for the root broker (if you are employing a [broker hierarchy](./broker_hierarchies.md)). For example, in a federation with four federates (one of which will be joining late), the call to start the broker is + +```shell +$ helics_broker -f3 --dynamic +``` -Allowing full dynamic federations will require activating a flag on the root broker to explicitly allow dynamic federations. It is not intended to be a normal use case, and will not be enabled by default. This functionality is not operational as of HELICS 3.1 and significantly more testing is needed before the feature becomes generally available and more details will be added at that time. +In this example, three federates must be in the federation in order to enter initialization and then executing mode and the broker is ready if more join later. diff --git a/docs/user-guide/advanced_topics/environment_variables.md b/docs/user-guide/advanced_topics/environment_variables.md index 4471847bc8..45aef00d48 100644 --- a/docs/user-guide/advanced_topics/environment_variables.md +++ b/docs/user-guide/advanced_topics/environment_variables.md @@ -14,7 +14,7 @@ For setting up a federate a few environment variables are used ## Core and Broker environment variables - `HELICS_BROKER_LOG_LEVEL`: the log level for the broker to use. Equivalent to `--loglevel=X` -- `HELICS_BROKER_KEY`: the key to use for connecting a core to a broker. See [broker key](../../references/configuration_options_reference.md#core-init-string-coreinitstring-coreinitstring-i) +- `HELICS_BROKER_KEY`: the key to use for connecting a core to a broker. See [broker key](../../references/configuration_options_reference.md#core_init_string---i-null) - `HELICS_BROKER_ADDRESS`: the interface address of the broker. Equivalent to `--brokeraddress=X` - `HELICS_BROKER_PORT`: the port number of the broker. Equivalent to `--brokerport=X` - `HELICS_CONNECTION_PORT`: the port number to use for connecting. This has different behavior for cores and brokers. For cores this is the broker port and for brokers this is the local port diff --git a/docs/user-guide/advanced_topics/iteration.md b/docs/user-guide/advanced_topics/iteration.md index 1bf7115cdc..97b8ca54ab 100644 --- a/docs/user-guide/advanced_topics/iteration.md +++ b/docs/user-guide/advanced_topics/iteration.md @@ -61,7 +61,7 @@ The big and important exception to this is if a given federate has reached a sta ### `only_update_on_change` -Since iteration is highly dependent on received inputs, an implicit convergence criterion is implemented through the [`only_update_on_change`](../../references/configuration_options_reference) flag. When set this flag will only show new inputs to federates if they have changed since the last time they have been published. This can be helpful in that if there is a slightly mis-behaving federate that published every time, regardless of whether it thinks it has converged, those republications can be screened out. Additionally, `only_update_on_change` has a related parameter called [`tolerance`](../../references/configuration_options_reference#tolerance) that allows values within a certain numerical range from the previously published value to be considered "unchanged" and will not be presented to the federate. This can effecively be used to define the convergence criterion as it limits the changes in inputs to a federate. +Since iteration is highly dependent on received inputs, an implicit convergence criterion is implemented through the [`only_update_on_change`](../../references/configuration_options_reference) flag. When set this flag will only show new inputs to federates if they have changed since the last time they have been published. This can be helpful in that if there is a slightly mis-behaving federate that published every time, regardless of whether it thinks it has converged, those republications can be screened out. Additionally, `only_update_on_change` has a related parameter called [`tolerance`](../../references/configuration_options_reference.md#tolerance-0) that allows values within a certain numerical range from the previously published value to be considered "unchanged" and will not be presented to the federate. This can effectively be used to define the convergence criterion as it limits the changes in inputs to a federate. ## Example Iterative Federate Psuedo-code diff --git a/docs/user-guide/advanced_topics/queries.md b/docs/user-guide/advanced_topics/queries.md index cbd6d1ce0e..b048aeb65b 100644 --- a/docs/user-guide/advanced_topics/queries.md +++ b/docs/user-guide/advanced_topics/queries.md @@ -185,7 +185,7 @@ The following queries will be answered by a core: | ``data_flow_graph`` | a representation of the data connections from all interfaces in a core [structure] | +--------------------------+-------------------------------------------------------------------------------------+ |``filtered_endpoints`` | data structure containing the filters on endpoints for the core[structure] | -+-------------------------+--------------------------------------------------------------------------------------+ ++--------------------------+-------------------------------------------------------------------------------------+ | ``barriers`` | a data structure with current time barriers [structure] | +--------------------------+-------------------------------------------------------------------------------------+ | ``queries`` | list of dependent objects [sv] | @@ -253,10 +253,10 @@ The following queries will be answered by a broker: | ``dependencies`` | structure containing dependency information for the broker [structure] | +--------------------------+---------------------------------------------------------------------------------------------------+ | ``dependents`` | list of dependent objects [sv] | -+-------------------------+----------------------------------------------------------------------------------------------------+ ++--------------------------+---------------------------------------------------------------------------------------------------+ | ``barriers`` | a data structure with current time barriers [structure] | +--------------------------+---------------------------------------------------------------------------------------------------+ -| ``counts`` | a simple count of the number of brokers, federates, and handles [structure] | +| ``counts`` | a simple count of the number of brokers, federates, and interfaces [structure] | +--------------------------+---------------------------------------------------------------------------------------------------+ | ``current_state`` | a structure with the current known status of the brokers and federates [structure] | +--------------------------+---------------------------------------------------------------------------------------------------+ @@ -338,7 +338,7 @@ In the header [``](https://docs.helics.org/en/latest/ ### C API and interface API's -Queries in the [C API](../../api-reference/C_API.md#query) have the same valid targets and properties that can be queried but the construction of the query is slightly different. The basic operation is to create a query using `helicsQueryCreate(target,query)`. Once created, the target or query string can be changed with `helicsQuerySetTarget()` and `helicsQuerySetQueryString()`, respectively. +Queries in the [C API](../../references/api-reference/C_API.md#query) have the same valid targets and properties that can be queried but the construction of the query is slightly different. The basic operation is to create a query using `helicsQueryCreate(target,query)`. Once created, the target or query string can be changed with `helicsQuerySetTarget()` and `helicsQuerySetQueryString()`, respectively. This function returns a query object that can be used in one of the execute functions (`helicsQueryExecute()`, `helicsQueryExecuteAsync()`, `helicsQueryBrokerExecute()`, `helicsQueryCoreExecute()`, to perform the query and receive back results. The query can be called asynchronously on a federate. The target field may be empty if the query is intended to be used on a local federate, in which case the target is assumed to be the federate itself. A query must be freed after use `helicsQueryFree()`. diff --git a/docs/user-guide/advanced_topics/timingOptimization.md b/docs/user-guide/advanced_topics/timingOptimization.md new file mode 100644 index 0000000000..c9052cad3e --- /dev/null +++ b/docs/user-guide/advanced_topics/timingOptimization.md @@ -0,0 +1,105 @@ +# Introduction + +Generally, most federates have both inputs they depend on and outputs on which other federates depend and configuring federates so that each one updates its own model under the correct circumstances is challenging. HELICS largely handles this through its own timing algorithm and also provides many configuration flags and settings to allow the user to optimize the timing and sequencing of federates to produce the most optimal performance. This document provides a few hints that, based on experience, we have found helpful in getting the most out of a HELICS-based co-simulation. + +## `uninterruptible` + +By default, a federate in HELICS is granted time when either of two conditions are met: + +1. HELICS has determined it is safe for the federate to simulate its requested time based on the simulated times of all the federates from which it has inputs. +2. The federate has received an update on one of its value or message interfaces. + +The latter logic is implemented under the philosophical assumption that a federate MAY want to produce a new output if one of its inputs has changed. By granting a federate an earlier time it gives the federate the ability to evaluate its new input and decide what, if any, actions it needs to take. There is some computational cost, though, to granting an earlier time as the federate must perform some kind of minimal computation to evaluate the new input. For a federate with a large number of inputs or inputs that receive changes frequently, these early time grants can add up to a relatively large amount of unnecessary computation. + +To prevent this, HELICS provides for federates a flag called "uninterruptible" which removes this second option for determining the time to grant and only allows a federate to be granted the time it requests. + +The `uninterruptible` flag had a significant effect on the total number of calls into the `federateRequestTime` method, the most significant source of time delay found in our testing. By reducing the number of times this method is called, especially where it may not be necessary, moderate performance gains were observed in communication-heavy federates. + +Setting the `uninterruptible` via the JSON configuration is trivial: + +```json +{ + "name": "sub_7", + "period": 15, + "logging": "warning", + "uninterruptible": true, + "publications": [ + { + "global": false, + "key": "unresponsive_mw", + "type": "double" + }, + ] + "subscriptions": [ + { + "key": "pypower/LMP_7", + "type": "double" + }, + { + "key": "gld_7/distribution_load", + "type": "complex" + }, + ] +} +``` + +## Input `isUpdated` + +HELICS provides a method which allows the federate to check if a specific endpoint or subscription has been updated since it was last read. In this context, "update" simply means the input has received a value since the last time it was checked. This new input may be identical in value to the last time the interface was updated and the flag simply indicates the publisher has sent another value to the subscriber's input. + +If a value change is not guaranteed every time the simulator is granted time, or if multiple values are being updated in lockstep with a change on one indicating many have changed, a call to the `isUpdated` method prior to asking for the latest value can significantly reduce total computation time, and net substantial performance benefits. + +```python +... +hFed = helics.helicsCreateValueFederateFromConfig(helicsConfig) +subLMP = helics.helicsFederateGetInputByTarget(hFed, tso_federate + "/LMP_" + bus) +... + +# ==================== Time step looping under HELICS =========================== +helics.helicsFederateEnterExecutingMode(hFed) + +while time_granted < time_stop: + ... + time_granted = int(helics.helicsFederateRequestTime(hFed, nextHELICSTime)) + # Faster to check than to always grab the input every time the federate + # is granted time + if helics.helicsInputIsUpdated(subLMP): + LMP = helics.helicsInputGetDouble(subLMP) + aucObj.set_lmp(LMP) + ... +``` + +## `onlyUpdateOnChange` + +Similar to what the `isUpdated()` API call achieves, there is also a configuration flag that can be set to force HELICS to prevent signals from being sent (if set on the publication) or from being received (if set on the subscription) if the value of the signal has not changed. This adds a slight burden to HELICS as it now compares each published or subscribed value to the previous one to decide whether the signal will appear on the receivers interface. In cases where the computational cost of federate is large, though, this can end up being a net increase in performance. + +Furthermore, a `tolerance` value can be set for each interface to define a degree of change that can be considered no-change. This allows very small changes in the published value to be ignored and treated as no change to the signal. + +Configuring this in the JSON is not difficult: + +```json +{ + "name": "sub_7", + "period": 15, + "logging": "warning", + "publications": [ + { + "global": false, + "key": "unresponsive_mw", + "type": "double", + "onlyUpdateOnChange": true, + "tolerance": 0.01 + }, + ] + "subscriptions": [ + { + "key": "pypower/LMP_7", + "type": "double" + }, + { + "key": "gld_7/distribution_load", + "type": "complex" + }, + ] +} +``` diff --git a/docs/user-guide/advanced_topics/translators.md b/docs/user-guide/advanced_topics/translators.md new file mode 100644 index 0000000000..fe00433c42 --- /dev/null +++ b/docs/user-guide/advanced_topics/translators.md @@ -0,0 +1,60 @@ +# Translators + +Translators are HELICS objects that can be used to bridge the gap between values (publications, subscriptions, inputs) and messages (endpoints). These two types of signals come from the need to model different data: physical data (_e.g._ voltage, speed, energy) use value interfaces and abstract data (_e.g._ control signals, measurements) use message interfaces. Each type of interface has unique properties with advantages and disadvantages so it pays to think through which type of interface best suits a particular piece of data being exchanged. + +But the world is messy and not ideal. Maybe you are working with a federation you wrote before you were a HELICS Master. Maybe you're inheriting somebody else's messy federation. Maybe the tools you have to work with only implemented value interfaces but you really need to use a message interface. Translators exist to bridge these two interface types and allow data exchanges that would not otherwise be possible. + +## Translator Basics + +To HELICS, a translator is a specialized federate with one input, one publication (output) and one endpoint. A value sent to the input will result in a message sent to any targets of the translator's endpoint and any messages sent to the endpoint will result in a publication to any subscribing federates. As a federate, there will always be a one simulated nanosecond delay between when the data arrives at the input or endpoint and is sent out on the endpoint or publication, respectively. That is, the work of the translator takes a non-zero amount of simulated time. + +Translators come in three types that determine how the data is translated between values and messages: JSON, custom, and binary. The binary option is unlikely to be useful in virtually all cases and won't be discussed. The custom option utilizes the `helicsTranslatorSetCustomCallback()` function to allow a user to define a translation process directly via a custom function that gets called anytime the translator needs to do it's work. Using a custom translator may be required for special translation needs but is not expected to be needed for the typical use cases. + +That leaves the JSON translator type, where the message coming out of or going into the endpoint being structured as a simple JSON formatted as: + +```text +{ + "type": , + "value": +} +``` + +for example: + +```json +{ + "type": "double", + "value": 56.78943 +} +``` + +In this example, if the translator's value input received a data from a publication that was formatted as a double of 56.78943, it would produce the above JSON on the endpoint output. Similarly, if the translator's endpoint received the above JSON, it would publish out a double value of 56.78943. + +## Translator Configuration + +Translators can be defined by any federate and either linked into the federation via a core or a federate, with the later creating a global translator which simplifies the addressing of the input, publication, and endpoint of the translator. + +Translators can add their own sources and destinations for their interfaces but can also be targeted by configuration of other federates. That is, both the translator itself but also the federates that want to use the translator have the ability to connect to its inputs, publications and outputs. Because all federates connected to the output and endpoint will receive the translated data, when designing the data-passing topology of the federation. To keep certain data from going to certain federates, multiple translators may be required. + +Just like inputs, publications, endpoints, and filter, translators can be defined via JSON configuration by any federate as follows: + +```text + "translators": [ + { + "name": "test translator", + "type": "JSON", + "global": true, + "info": "", + "source_target": + "destination_target: + } + ] +``` + +APIs exist for setting all of these parameters and are further defined in the [Configuration Options Reference](../../references/configuration_options_reference). + +## DIY Translator + +If for some reason the HELICS provided translators are not able to meet your needs, you can always implement a similar but more highly customized functionality through a custom federate. Though this is the use case intended to be supported via setting a custom callback for a translator, there may be other limitations that don't allow the use of a custom callback function. With such a federate, it would be possible to, for example, translate values on the same interface differently based on who sent them, allow message interfaces to conform to a non-JSON format, and implement data type translation. The same APIs you would use for writing any other federates, so in this regard it is just another federate. In this case, though, this custom translator federate doesn't model any system and just acts as a data translator. + +## Example diff --git a/docs/user-guide/deprecated/troubleshooting.md b/docs/user-guide/deprecated/troubleshooting.md new file mode 100644 index 0000000000..cc1a6148fd --- /dev/null +++ b/docs/user-guide/deprecated/troubleshooting.md @@ -0,0 +1,3 @@ +# Troubleshooting HELICS co-simulations + +This section will describe techniques for trouble-shooting HELICS-base co-simulations including the use of the web interface, native debuggers, and writing custom queries. diff --git a/docs/user-guide/examples/advanced_examples/advanced_FMU.md b/docs/user-guide/examples/advanced_examples/advanced_FMU.md new file mode 100644 index 0000000000..2cb8994e6f --- /dev/null +++ b/docs/user-guide/examples/advanced_examples/advanced_FMU.md @@ -0,0 +1,71 @@ +# FMUs with HELICS + +```{eval-rst} +.. toctree:: + :maxdepth: 1 + + +``` + +This demonstrates the use of HELICS-FMI to integrate an FMU into a HELICS-based co-simulation. [Functional Mock-Up Interface (FMI)](https://fmi-standard.org/) is an existing method of integrating models that is similar to HELICS is some ways. FMI provides a way to specify a model and with the help of a supporting tool, compile into a binary and provide a companion specification of the interface to that model. In some cases, a solver for the model is also distributed along with the model, effectively making it a highly specialized simulation tool. These elements can be bundled up into a distributable unit called a "functional mock-up unit" (FMU) that can be distributed without revealing the inner workings of a model. HELICS provides a way to allow one or more FMUs to participate in a HELICS co-simulation using the HELICS-FMI application. + +- [Where is the code?](#where-is-the-code) +- [What is this Co-simulation doing?](#what-is-this-co-simulation-doing) +- [HELICS components](#helics-components) +- [Building the FMU](#building-the-fmu) +- [Configuring the co-simulation](#configuring-the-co-simulation) +- [Execution and Results](#execution-and-results) + +## Where is the code? + +The code for the [Advanced examples](https://github.com/GMLC-TDC/HELICS-Examples/tree/main/user_guide_examples/advanced) can be found in the HELICS-Examples repository on GitHub. This example on [using an FMU in a HELICS-based co-simulation](https://github.com/GMLC-TDC/HELICS-Examples/tree/main/user_guide_examples/advanced/advanced_fmu). If you have issues navigating the examples, visit the HELICS [Gitter page](https://gitter.im/GMLC-TDC/HELICS) or the [user forum on GitHub](https://github.com/GMLC-TDC/HELICS/discussions). + +Note that this code contains a component (the FMU) that has been compiled for Windows and thus will only function on Windows. The FMU source code has been included and can be compiled into an FMU for other platforms with the appropriate tools. + +## What is this co-simulation doing? + +This example shows you how to take an existing FMU and incorporate it into a HELICS-based co-simulation. This effectively allows FMUs to act as HELICS federates. + +The [Functional Mock-up Interface (FMI)](https://fmi-standard.org/) is a modeling language popularly implemented by the commercial tool [Modelon](https://modelon.com/) (_nee_ Modelica) but also has an open-source implementation [OpenModelica](https://openmodelica.org/). The modeling language allows for a black-box description of a model's interfaces to support co-simulation of various modeled entities through the creation of an FMU. The FMU, when used for co-simulation, consists of two main components: 1. An XML file describing the data exchange interfaces 2. Binary version of the model with callable FMI-defined functions that simulate the model. + +FMI effectively defines another means of performing a co-simulation using FMUs and the HELICS team has created a means by which these FMUs can join a HELICS-based co-simulation. To integrate the FMU into the example, HELICS-FMI acts as a bridge that is able to execute the "SimpleBattery.fmu" FMU. HELICS-FMI takes care of executing the FMU using the inputs from the rest of the co-simulation and providing the outputs on its behalf. + +## HELICS components + +To enable an FMU to act as a HELICS federate, the "helics_fmi" application as been developed. This application has the ability to read an FMU, set-up the defined data-exchange interfaces as HELICS value interfaces, and call the necessary simulation functions for the FMU to push it forward in simulated time. This puts the HELICS in the role of "master algorithm" (to use the FMI parlance). + +As a more specialty item, helics_fmi is not included as a part of the standard HELICS distribution and must be built from source. The source code can be found in the ["helics_fmi"](https://github.com/GMLC-TDC/HELICS-FMI) repository and uses a CMake build process like the main HELICS library. You can follow [the instructions here on building the main HELICS library](https://docs.helics.org/en/latest/user-guide/installation/build_from_source.html) but work from the helics_fmi repo. + +## Building the FMU + +Distributed with the example is the [source code for the FMU battery model](https://github.com/GMLC-TDC/HELICS-Examples/blob/main/user_guide_examples/advanced/advanced_fmu/SimpleBattery.mo). This source code needs to be compiled into an FMU for use in this example. Provided with this example is the [FMU for Windows](https://github.com/GMLC-TDC/HELICS-Examples/blob/main/user_guide_examples/advanced/advanced_fmu/SimpleBattery.fmu); if running this example on another platform the FMU will have to be compiled on that platform to produce a valid binary. + +## Configuring the Co-Simulation + +With helics_fmi and FMU built, all that remains is providing command line options for helics_fmi. Looking at the [runner JSON for this example](https://github.com/GMLC-TDC/HELICS-Examples/blob/main/user_guide_examples/advanced/advanced_fmu/runner.json), the following options are used: + +- `stoptime` - The simulated time in seconds for ending the FMU simulation +- `step` - Simulation step size, equivalent to `period` in HELICS configuration +- `name` - Federate name +- `flags` - Special runtime flags to address particular FMU needs +- `set` - Allow for interaction with the interface values defined by the FMU. In this case it is used to define initialization values. + +## Execution and Results + +To execute this example, use the provided runner file: + +```shell +helics run --path=runner.json +``` + +The FMU has been designed to replicate the model used in this example suite and the results should be identical to those provided in the fundamental default example: + +![](https://github.com/GMLC-TDC/helics_doc_resources/raw/main/user_guide/fundamental_default_resultcharger.png) + +## [Questions and Help](../../support.md) + +Do you have questions about HELICS or need help? + +1. Come to [office hours](https://helics.org/HELICSOfficeHours.ics)! +2. Post on the [gitter](https://gitter.im/GMLC-TDC/HELICS)! +3. Place your question on the [github forum](https://github.com/GMLC-TDC/HELICS/discussions)! diff --git a/docs/user-guide/examples/advanced_examples/advanced_brokers_hierarchies.md b/docs/user-guide/examples/advanced_examples/advanced_brokers_hierarchies.md index c008a8615f..df74bf429a 100644 --- a/docs/user-guide/examples/advanced_examples/advanced_brokers_hierarchies.md +++ b/docs/user-guide/examples/advanced_examples/advanced_brokers_hierarchies.md @@ -11,7 +11,7 @@ This example shows how to configure a HELICS co-simulation to allow the use of m - [Where is the code?](#where-is-the-code) - [What is this Co-simulation doing?](#what-is-this-co-simulation-doing) - - [Differences Compared to the Advanced Default Example](#differences-compared-to-the-advanced-default-example) + - [Differences Compared to the Advanced Default Example](#differences-compared-to-advanced-default-example) - [HELICS Differences](#helics-differences) - [HELICS Components](#helics-components) - [Execution and Results](#execution-and-results) @@ -88,6 +88,6 @@ These results are identical to those in the base [Advanced Default example](./ad Do you have questions about HELICS or need help? -1. Come to [office hours](mailto:helicsteam@helics.org)! +1. Come to [office hours](https://helics.org/HELICSOfficeHours.ics)! 2. Post on the [gitter](https://gitter.im/GMLC-TDC/HELICS)! 3. Place your question on the [github forum](https://github.com/GMLC-TDC/HELICS/discussions)! diff --git a/docs/user-guide/examples/advanced_examples/advanced_brokers_multibroker.md b/docs/user-guide/examples/advanced_examples/advanced_brokers_multibroker.md index c7130b1d05..3adc067f0f 100644 --- a/docs/user-guide/examples/advanced_examples/advanced_brokers_multibroker.md +++ b/docs/user-guide/examples/advanced_examples/advanced_brokers_multibroker.md @@ -110,6 +110,6 @@ As has been mentioned, since this is just a change to the co-simulation architec Do you have questions about HELICS or need help? -1. Come to [office hours](mailto:helicsteam@helics.org)! +1. Come to [office hours](https://helics.org/HELICSOfficeHours.ics)! 2. Post on the [gitter](https://gitter.im/GMLC-TDC/HELICS)! 3. Place your question on the [github forum](https://github.com/GMLC-TDC/HELICS/discussions)! diff --git a/docs/user-guide/examples/advanced_examples/advanced_brokers_multicomputer.md b/docs/user-guide/examples/advanced_examples/advanced_brokers_multicomputer.md index 3843d4413a..ebd2a9b630 100644 --- a/docs/user-guide/examples/advanced_examples/advanced_brokers_multicomputer.md +++ b/docs/user-guide/examples/advanced_examples/advanced_brokers_multicomputer.md @@ -11,7 +11,7 @@ This example shows how to configure a HELICS co-simulation to run across multipl - [Where is the code?](#where-is-the-code) - [What is this Co-simulation doing?](#what-is-this-co-simulation-doing) - - [Differences Compared to the Advanced Default Example](#differences-compared-to-the-advanced-default-example) + - [Differences Compared to the Advanced Default Example](#differences-compared-to-advanced-default-example) - [HELICS Differences](#helics-differences) - [HELICS Components](#helics-components) - [Execution and Results](#execution-and-results) @@ -94,6 +94,6 @@ The peak charging results are shown below and are identical to the results from Do you have questions about HELICS or need help? -1. Come to [office hours](mailto:helicsteam@helics.org)! +1. Come to [office hours](https://helics.org/HELICSOfficeHours.ics)! 2. Post on the [gitter](https://gitter.im/GMLC-TDC/HELICS)! 3. Place your question on the [github forum](https://github.com/GMLC-TDC/HELICS/discussions)! diff --git a/docs/user-guide/examples/advanced_examples/advanced_brokers_simultaneous.md b/docs/user-guide/examples/advanced_examples/advanced_brokers_simultaneous.md index 91da0fc718..033b6f678e 100644 --- a/docs/user-guide/examples/advanced_examples/advanced_brokers_simultaneous.md +++ b/docs/user-guide/examples/advanced_examples/advanced_brokers_simultaneous.md @@ -110,6 +110,6 @@ To do a more legitimate sensitivity analysis to the population of EVs that are b Do you have questions about HELICS or need help? -1. Come to [office hours](mailto:helicsteam@helics.org)! +1. Come to [office hours](https://helics.org/HELICSOfficeHours.ics)! 2. Post on the [gitter](https://gitter.im/GMLC-TDC/HELICS)! 3. Place your question on the [github forum](https://github.com/GMLC-TDC/HELICS/discussions)! diff --git a/docs/user-guide/examples/advanced_examples/advanced_default.md b/docs/user-guide/examples/advanced_examples/advanced_default.md index c4a2c723d3..87cb98721d 100644 --- a/docs/user-guide/examples/advanced_examples/advanced_default.md +++ b/docs/user-guide/examples/advanced_examples/advanced_default.md @@ -6,7 +6,7 @@ The Advanced Base Example tutorial is organized as follows: - [Example files](#example-files) - [Co-simulation Setup](#co-simulation-setup) - - [Messages + Values](#messages-values) + - [Messages + Values](#messages-and-values) - [Co-simulation Execution and Results](#co-simulation-execution-and-results) - [Questions and Help](#questions-and-help) @@ -25,9 +25,9 @@ The files include: ## Co-simulation Setup -### Messages + Values +### Messages and Values -As you may or may not have read in the [User Guide](../../fundamental_topics/message_federates.md), one of the key differences between value exchange and the message exchange is that value exchange paths are defined once the federation has been initialized but message exchanges are dynamic and can travel from any endpoint to any endpoint throughout the co-simulation. The diagram below shows the three federates used in this example with the representative handles for both the value and message exchanges. +As you may or may not have read in the [User Guide](../../fundamental_topics/message_federates.md), one of the key differences between value exchange and the message exchange is that value exchange paths are defined once the federation has been initialized but message exchanges are dynamic and can travel from any endpoint to any endpoint throughout the co-simulation. The diagram below shows the three federates used in this example with the representative interfaces for both the value and message exchanges. ![](https://github.com/GMLC-TDC/helics_doc_resources/raw/main/user_guide/advanced_default_signal_topology.png) @@ -63,6 +63,6 @@ The data shown in the power graph is arguably the point of the analysis. It show Do you have questions about HELICS or need help? -1. Come to [office hours](mailto:helicsteam@helics.org)! +1. Come to [office hours](https://helics.org/HELICSOfficeHours.ics)! 2. Post on the [gitter](https://gitter.im/GMLC-TDC/HELICS)! 3. Place your question on the [github forum](https://github.com/GMLC-TDC/HELICS/discussions)! diff --git a/docs/user-guide/examples/advanced_examples/advanced_examples_index.md b/docs/user-guide/examples/advanced_examples/advanced_examples_index.md index df2cd80709..e2f1c84945 100644 --- a/docs/user-guide/examples/advanced_examples/advanced_examples_index.md +++ b/docs/user-guide/examples/advanced_examples/advanced_examples_index.md @@ -14,6 +14,7 @@ advanced_multi_input advanced_orchestration advanced_iteration + advanced_FMU ``` @@ -21,14 +22,14 @@ The Advanced Examples are modular, each building upon the [base example](./advan This page describes the model for the Advanced Examples. This model is topically the same as the Fundamental Examples, but more complex in its execution. This allows the research question to become more nuanced and for the user to define new components to a HELICS co-simulation. -- [Where is the code?](#where-is-the-code) -- [What is this Co-simulation doing?](#what-is-this-co-simulation-doing) - - [Differences Compared to the Fundamental Examples](#differences-compared-to-the-fundamental-examples) - - [HELICS Differences](#helics-differences) - - [Research Question Complexity Differences](#research-question-complexity-differences) -- [HELICS Components](#helics-components) - - [Federates with infinite time](#federates-with-infinite-time) - - [Initial time requests and model initialization](#initial-time-requests-and-model-initialization) +- Where is the Code? +- What is this Co-simulation Doing? + - Differences Compared to the Fundamental Examples + - HELICS Differences + - Research Question Complexity Differences +- HELICS Components + - Federates with infinite time + - Initial time requests and model initialization @@ -40,8 +41,6 @@ Where is the code? The code for the [Advanced examples](https://github.com/GMLC-TDC/HELICS-Examples/tree/main/user_guide_examples/advanced) can be found in the HELICS-Examples repository on github. If you have issues navigating the examples, visit the HELICS [Gitter page](https://gitter.im/GMLC-TDC/HELICS) or the [user forum on GitHub](https://github.com/GMLC-TDC/HELICS/discussions). -**TODO: UPDATE IMAGE** - [![](https://github.com/GMLC-TDC/helics_doc_resources/raw/main/user_guide/advanced_examples_github.png)](https://github.com/GMLC-TDC/HELICS-Examples/tree/main/user_guide_examples/advanced) @@ -79,7 +78,7 @@ HELICS differences 1. **Communication:** Both physical value exchanges and abstract information exchanges are modeled. The exchange of physical values takes place between the Battery and Charger federates (this was also introduced in a slimmed-down fashion in the [Fundamental Communication Example](../fundamental_examples/fundamental_communication.md)). The message exchange (control signals, in this case) takes place between the Charger and Controller federates. For a further look at the difference between these two messaging mechanisms see our User Guide page on [value federates](../../fundamental_topics/value_federates.md) and [message federates.](../../fundamental_topics/message_federates.md) -2. **Timing:** The Controller federate has no regular update interval. The Controller works in pure abstract information and has no regular time steps to simulate. As such, it requests a maximum simulated time supported by HELICS (`HELICS_TIME_MAXTIME`) and makes sure it can be interrupted by setting `uninterruptable` to `false` in its configuration file. Any time a message comes in for the Controller, HELICS grants it a time, the Controller performs the required calculation, sends out a new control signal, and requests `HELICS_TIME_MAXTIME` again. +2. **Timing:** The Controller federate has no regular update interval. The Controller works in pure abstract information and has no regular time steps to simulate. As such, it requests a maximum simulated time supported by HELICS (`HELICS_TIME_MAXTIME`) and makes sure it can be interrupted by setting `uninterruptible` to `false` in its configuration file. Any time a message comes in for the Controller, HELICS grants it a time, the Controller performs the required calculation, sends out a new control signal, and requests `HELICS_TIME_MAXTIME` again. @@ -135,18 +134,11 @@ Federates with infinite time Federates which are abstractions of reality (e.g., controllers) do not need regular time interval updates. These types of federates can be set up to request `HELICS_TIME_MAXTIME` (effectively infinite time) and only update when a new message arrives for it to process. This component is placed prior to the main time loop. -**TODO: Get rid of fake_max_time** - -**why do we divide helics_time_maxtime by 1000?** - -**shouldn't we also show how this federate is configured? where is best for that?** - ```python hours = 24 * 7 # one week total_interval = int(60 * 60 * hours) grantedtime = 0 -fake_max_time = int(h.HELICS_TIME_MAXTIME / 1000) -starttime = fake_max_time +starttime = int(h.HELICS_TIME_MAXTIME) logger.debug(f"Requesting initial time {starttime}") grantedtime = h.helicsFederateRequestTime(fed, starttime) logger.debug(f"Granted time {grantedtime}") @@ -162,9 +154,7 @@ Initial time requests and model initialization As in the [Base Example](../fundamental_examples/fundamental_default.md), the EV batteries are assumed connected to the chargers at the beginning of the simulation and information exchange is initiated by the Charger federate sending the charging voltage to the Battery federate. In the Advanced Examples, this is a convenient choice as the charging voltage is constant and thus is never a function of the charging current. In a more realistic model, it's easy to imagine that the charger has an algorithm that adjusts the charging voltage based on the charging current to, say, ensure the battery is charged at a particular power level. In that case, **the dependency of the models is circular**; this is common component that needs to be addressed. -If the early time steps of the simulation are not as important (a model warm up period), then ensuring each federate has a default value it will provide when the input is null (and assuming the controller dynamics are not overly aggressive) will allow the models to bootstrap and through several iterations reach a consistent state. If this is not the case then HELICS does have a provision for getting models into a consistent state prior to the start of execution: initialization mode. **TODO: link to documentation or example on initialization mode.** This mode allows for this same iteration between models with no simulated time passing. It is the responsibility of the modeler to make sure there is a method to reach and detect convergence of the models and when such conditions are met, enter execution mode as would normally be done. - -**todo: add examples for where this is inserted in the code** +If the early time steps of the simulation are not as important (a model warm up period), then ensuring each federate has a default value it will provide when the input is null (and assuming the controller dynamics are not overly aggressive) will allow the models to bootstrap and through several iterations reach a consistent state. If this is not the case then HELICS does have a provision for getting models into a consistent state prior to the start of execution: initialization mode (see an example in Battery.py of the [query example](./advanced_query.md) to see the use of the initialization mode API). This mode allows for this same iteration between models with no simulated time passing. It is the responsibility of the modeler to make sure there is a method to reach and detect convergence of the models and when such conditions are met, enter execution mode as would normally be done. We've put together an [example on iteration](advanced_iteration.md) to demonstrate one way of managing convergence. @@ -176,10 +166,14 @@ Examples Covered in Advanced Examples Using the [Advanced Default Example](./advanced_default.md) as the starting point, the following examples have also been constructed: -- [**Multi-Source Inputs**](./advanced_multi_input.md) - Demonstration of use and configuration of a a multi-sourced input value handle. -- [**Queries**](./advanced_query.md) - Demonstration of the use of queries for dynamic federate configuration. +- [**Iteration**](./advanced_iteration) - Setting up federates so that they can iterate without advancing simulation time to achieve a more consistent state. +- [**Orchestration Tool (Merlin)**](./advanced_orchestration.md) Demonstration of using [Merlin](https://github.com/LLNL/merlin) to handle situations where a HELICS co-simulation is just one step in an automated analysis process (_e.g._ uncertainty quantification) or where assistance is needed deploying a large co-simulation in an HPC environment. - **Multiple Brokers** - [**Connecting Multiple Core Types (Multi-Protocol Broker)**](./advanced_brokers_multibroker.md) - Demonstration of how to configure a multi-protocol broker - [**Broker Hierarchies**](./advanced_brokers_hierarchies.md) - Purpose of broker hierarchies and how to configure a HELICS co-simulation to implement one. - [**Simultaneous co-simulations**](./advanced_brokers_simultaneous.md) - Demonstration of how to run multiple independent federations simultaneously on a single compute node. + - [**Multi-Protocol Brokers (Multi-broker) for Multiple Core Types)**](advanced_brokers_multibroker) What to do when one type of communication isn't sufficient. + - [**Multi-compute-node Co-simulation**](advanced_brokers_multicomputer) - Executing a co-simulation across multiple compute nodes. +- [**Queries**](./advanced_query.md) - Demonstration of the use of queries for dynamic federate configuration. +- [**Multi-Source Inputs**](./advanced_multi_input.md) - Demonstration of use and configuration of a a multi-sourced input value interface. - [**Orchestration Tool (Merlin)**](./advanced_orchestration.md) Demonstration of using [Merlin](https://github.com/LLNL/merlin) to handle situations where a HELICS co-simulation is just one step in an automated analysis process (_e.g._ uncertainty quantification) or where assistance is needed deploying a large co-simulation in an HPC environment. diff --git a/docs/user-guide/examples/advanced_examples/advanced_iteration.md b/docs/user-guide/examples/advanced_examples/advanced_iteration.md index 78a42c98cd..9dd5715564 100644 --- a/docs/user-guide/examples/advanced_examples/advanced_iteration.md +++ b/docs/user-guide/examples/advanced_examples/advanced_iteration.md @@ -19,7 +19,7 @@ This example on [Iteration](https://github.com/GMLC-TDC/HELICS-Examples/tree/mai This example shows how to use set up the iteration calls that support state convergence across federates. This is discussed in more detail in the [User Guide](../../advanced_topics/iteration.md). -### Differences compared to the Default example +### Differences Compared to the Advanced Default Example This example changes the model of the default example so that the charger voltage is a function of the battery current: $V_{ch}(I_{b})$. Conversely, battery current is a function of charger voltage: $I_{b}(V_{ch})$. As a result, each time step requires some iteration to find the converged fixed-point, where both models are in a consistent state. @@ -413,6 +413,6 @@ The point is, that the specific charger control architecture is not of interest Do you have questions about HELICS or need help? -1. Come to [office hours](mailto:helicsteam@helics.org)! +1. Come to [office hours](https://helics.org/HELICSOfficeHours.ics)! 2. Post on the [gitter](https://gitter.im/GMLC-TDC/HELICS)! 3. Place your question on the [github forum](https://github.com/GMLC-TDC/HELICS/discussions)! diff --git a/docs/user-guide/examples/advanced_examples/advanced_multi_input.md b/docs/user-guide/examples/advanced_examples/advanced_multi_input.md index 76ddf9a0b0..d638bba81a 100644 --- a/docs/user-guide/examples/advanced_examples/advanced_multi_input.md +++ b/docs/user-guide/examples/advanced_examples/advanced_multi_input.md @@ -17,9 +17,9 @@ This example on [multi-inputs can be found here](https://github.com/GMLC-TDC/HEL ## What is this co-simulation doing? -This example shows how to use inputs, allowing multiple publications to arrive at the same input handle (similar to a subscription, as you'll see) and a demonstration on one method of managing data conflicts that can arise. +This example shows how to use inputs, allowing multiple publications to arrive at the same input interface (similar to a subscription, as you'll see) and a demonstration on one method of managing data conflicts that can arise. -### Difference compared to the Advanced Default example +### Differences compared to the Advanced Default example This example deviates fairly significantly from the [Advanced Default example](./advanced_default.md) in that it only has a Battery and Charger federate. The Charger federate was modeled with one charging terminal that branches out to the five Battery terminals. That is, from the Charger federates perspective, there is only one charging voltage and one charging current even though the federation is still constructed to charge five batteries. @@ -69,7 +69,7 @@ With a single charger being used to charge five batteries, each battery still pu } ``` -The Charger federate configuration is also altered, using an `input` rather than a `subscription` handle to allow all publications from the Battery federates to be received on one handle. The input has been configured to allow multiple inputs and lists the publications that should be targeted toward it and to handle these multiple inputs by summing them. +The Charger federate configuration is also altered, using an `input` rather than a `subscription` interface to allow all publications from the Battery federates to be received on one interface. The input has been configured to allow multiple inputs and lists the publications that should be targeted toward it and to handle these multiple inputs by summing them. ```json { @@ -127,6 +127,6 @@ As the batteries are not replaced during charging, the initial charging power wi Do you have questions about HELICS or need help? -1. Come to [office hours](mailto:helicsteam@helics.org)! +1. Come to [office hours](https://helics.org/HELICSOfficeHours.ics)! 2. Post on the [gitter](https://gitter.im/GMLC-TDC/HELICS)! 3. Place your question on the [github forum](https://github.com/GMLC-TDC/HELICS/discussions)! diff --git a/docs/user-guide/examples/advanced_examples/advanced_orchestration.md b/docs/user-guide/examples/advanced_examples/advanced_orchestration.md index d2b2ec091f..16155d6175 100644 --- a/docs/user-guide/examples/advanced_examples/advanced_orchestration.md +++ b/docs/user-guide/examples/advanced_examples/advanced_orchestration.md @@ -190,7 +190,7 @@ The final result of the default Monte Carlo co-simulation is shown below. ![](https://github.com/GMLC-TDC/helics_doc_resources/raw/main/user_guide/MonteCarlo_Manual_small.png) -This is a time series density plot. Each simulation is a green line, and the blue solid line is the median of all simulations. From this plot, we can see that (after the system [initializes](../../fundamental_topics/stages.html#initialization), after a few hours) the maximum demand from EVs in the garage will be roughly 125 kW. We could improve the analysis by conducting an initialization step and by running the simulation for a longer time period. This type of analysis provides the engineer with information about the probability that demand for power from N EVs will be X kW. The most commonly demanded power is less than 50 kW -- does the engineer want to size the power conduit to provide median power, or maximum power? +This is a time series density plot. Each simulation is a green line, and the blue solid line is the median of all simulations. From this plot, we can see that (after the system [initializes](../../fundamental_topics/stages.md#initialization), after a few hours) the maximum demand from EVs in the garage will be roughly 125 kW. We could improve the analysis by conducting an initialization step and by running the simulation for a longer time period. This type of analysis provides the engineer with information about the probability that demand for power from N EVs will be X kW. The most commonly demanded power is less than 50 kW -- does the engineer want to size the power conduit to provide median power, or maximum power? ### Merlin Orchestration Execution @@ -342,6 +342,6 @@ output that each co-sim runs. Do you have questions about HELICS or need help? -1. Come to [office hours](mailto:helicsteam@helics.org)! +1. Come to [office hours](https://helics.org/HELICSOfficeHours.ics)! 2. Post on the [gitter](https://gitter.im/GMLC-TDC/HELICS)! 3. Place your question on the [github forum](https://github.com/GMLC-TDC/HELICS/discussions)! diff --git a/docs/user-guide/examples/advanced_examples/advanced_query.md b/docs/user-guide/examples/advanced_examples/advanced_query.md index 11065b65e7..b92d117a9a 100644 --- a/docs/user-guide/examples/advanced_examples/advanced_query.md +++ b/docs/user-guide/examples/advanced_examples/advanced_query.md @@ -19,7 +19,7 @@ This example on [queries can be found here](https://github.com/GMLC-TDC/HELICS-E This example shows how to run queries on a federation and to use the output of the queries to configure a federate. Rather than a static configuration that is defined prior to runtime, this dynamic configuration can be useful for federations that change composition frequently. -### Difference compared to the Advanced Default example +### Differences compared to the Advanced Default example This example has the same federates interacting in the same ways as in the [Advanced Default example](./advanced_default.md). The only difference is the use of queries for dynamic configuration rather than static configuration. @@ -125,6 +125,6 @@ Federate Charger (with id 131072) has the following subscriptions: Do you have questions about HELICS or need help? -1. Come to [office hours](mailto:helicsteam@helics.org)! +1. Come to [office hours](https://helics.org/HELICSOfficeHours.ics)! 2. Post on the [gitter](https://gitter.im/GMLC-TDC/HELICS)! 3. Place your question on the [github forum](https://github.com/GMLC-TDC/HELICS/discussions)! diff --git a/docs/user-guide/examples/examples_index.md b/docs/user-guide/examples/examples_index.md index e1d94a88ba..178bb5a314 100644 --- a/docs/user-guide/examples/examples_index.md +++ b/docs/user-guide/examples/examples_index.md @@ -14,6 +14,14 @@ There are two learning tracks available to those hoping to improve their HELICS These two learning tracks each start with a "base" model, which should also be considered the recommended default settings. Examples beyond the base model within a track are modular, not sequential, allowing the user to self-guide towards concepts in which they want to gain skill. +**A Word on HELICS CLI** + +All (or almost all) of the HELICS User Guide examples utilize a common tool and command for launching the co-simulation: + +`helics run --path=runner.json` + +This utilizes a tool we call `helics_cli` that is (optionally) [installed with the Python language binding](../installation/index). Not only does HELICS CLI take care of launching the co-simulation, it also manages the logging and error/warning messages that are often printed to console when running code in a stand-alone manner. Generally, using HELICS CLI is the recommended way to run a federation but if there are particular needs you have that HELICS CLI can't meet, all federations can simply be run by launching each individual federate sequentially. The contents of the HELICS CLI runner.json shows the commands it uses to launch each federate and those can simply be copied and pasted into a set of command-line prompts manually launch the co-simulation. + ```{eval-rst} .. toctree:: :maxdepth: 1 @@ -21,4 +29,5 @@ These two learning tracks each start with a "base" model, which should also be c fundamental_examples/fundamental_examples_index advanced_examples/advanced_examples_index supported_languages_examples/supported_languages_examples_index + misc_examples/misc_examples_index ``` diff --git a/docs/user-guide/examples/fundamental_examples/fundamental_combo.md b/docs/user-guide/examples/fundamental_examples/fundamental_combo.md index 834c4ec4cc..91cf397635 100644 --- a/docs/user-guide/examples/fundamental_examples/fundamental_combo.md +++ b/docs/user-guide/examples/fundamental_examples/fundamental_combo.md @@ -6,8 +6,6 @@ This tutorial is organized as follows: - [Example files](#example-files) - [Combination Federates](#combination-federates) - - [When to use pub/subs vs endpoints](#when-to-use-pub-subs-vs-endpoints) - - [Translation from pub/sub to endpoints](#translation-from-pub-sub-to-endpoints) - [Co-simulation Execution](#co-simulation-execution) - [Questions and Help](#questions-and-help) @@ -228,6 +226,6 @@ How would you model an unknown demand for vehicle charging? How would you model Do you have questions about HELICS or need help? -1. Come to [office hours](mailto:helicsteam@helics.org)! +1. Come to [office hours](https://helics.org/HELICSOfficeHours.ics)! 2. Post on the [gitter](https://gitter.im/GMLC-TDC/HELICS)! 3. Place your question on the [github forum](https://github.com/GMLC-TDC/HELICS/discussions)! diff --git a/docs/user-guide/examples/fundamental_examples/fundamental_default.md b/docs/user-guide/examples/fundamental_examples/fundamental_default.md index 5e90aa2025..9207f62d2f 100644 --- a/docs/user-guide/examples/fundamental_examples/fundamental_default.md +++ b/docs/user-guide/examples/fundamental_examples/fundamental_default.md @@ -6,9 +6,9 @@ The Base Example tutorial is organized as follows: - [Example files](#example-files) - [Default Setup](#default-setup) - - [Messages + Communication: pub sub](#messages-communication-pub-sub) + - [Messages + Communication: pub sub](#messages-and-communication-pubsub) - [Simulator Integration: External JSON](#simulator-integration-external-json) - - [Co-simulation Execution:](#co-simulation-execution-helics-cli) + - [Co-simulation Execution:](#co-simulation-execution) - [Questions and Help](#questions-and-help) ## Example files @@ -27,27 +27,27 @@ The files include: The default setup, used in the Base Example, integrates the federate configurations with external JSON files. The message and communication configurations are publications and subscriptions. This section introduces federate configuration of publications (pubs) and subscriptions (subs) with JSON files and how to launch the co-simulation with the HELICS runner. -### Messages + Communication: pub/sub +### Messages and Communication: pub/sub In the Base Example, the information being passed between the `Battery.py` federate and the `Charger.py` federate is the **voltage** applied to the battery, and the **current** measured across the battery and fed back to the charger. Voltage and current are both physical quantities, meaning that unless we act on these quantities to change them, they will retain their values. For this reason, in HELICS, physical quantities are called **values**. Values are sent via publication and subscription -- a federate can publish its value(s), and another federate can subscribe this value(s). -When configuring the communication passage between federates, it is important to connect the federate to the correct **handle**. In the image below, we have a Battery federate and a Charger federate. Each federate has a **publication** handle (red) and a **subscription** handle (yellow). The publication handle is also called the **output**, and the subscription handle the **input**. How are values passed between federates with pubs and subs? +When configuring the communication passage between federates, it is important to connect the federate to the correct **interface**. In the image below, we have a Battery federate and a Charger federate. Each federate has a **publication** interface (red) and a **subscription** interface (yellow). The publication interface is also called the **output**, and the subscription interface the **input**. How are values passed between federates with pubs and subs? ![](https://github.com/GMLC-TDC/helics_doc_resources/raw/main/user_guide/handles.png) -We have **named** the publication handle for the `Battery` federate `EV_current` to indicate the information being broadcast -- we can also call the pub handle the **named output**. This is what the publication is doing -- we are telling the Battery federate that we want to publish the EV_current. The full handle for the current is `Battery/EV_current` (within the JSON, this is also called the `key`). +We have **named** the publication interface for the `Battery` federate `EV_current` to indicate the information being broadcast -- we can also call the publication interface the **named output**. This is what the publication is doing -- we are telling the Battery federate that we want to publish the EV_current. The full interface designation for the current is `Battery/EV_current` (within the JSON, this is also called the `key`). ![](https://github.com/GMLC-TDC/helics_doc_resources/raw/main/user_guide/battery_pub.png) -How does the current value get from the Battery federate's publication to the Charger federate? The Charger must subscribe to this publication handle -- the Charger will subscribe to `Battery/EV_current`. The Charger subscription handle has not been given a name (e.g., `Charger/EV_current`), but it will receive **input** -- the Charger subscription is a defined unnamed input with a targeted publication. In this example, we configure the target of the Charger subscription in the JSON to the publication handle name `Battery/EV_current`. +How does the current value get from the Battery federate's publication to the Charger federate? The Charger must subscribe to this publication interface -- the Charger will subscribe to `Battery/EV_current`. The Charger subscription interface has not been given a name (e.g., `Charger/EV_current`), but it will receive **input** -- the Charger subscription is a defined unnamed input with a targeted publication. In this example, we configure the target of the Charger subscription in the JSON to the publication interface name `Battery/EV_current`. ![](https://github.com/GMLC-TDC/helics_doc_resources/raw/main/user_guide/charger_sub.png) -Thus far we have established that the Battery is publishing its current from the named handle `Battery/EV_current` and the Charger is subscribing to this named handle. The Charger is also sending information about values. The Charger federate will be publishing the voltage value from the `Charger/EV_voltage` handle (a named output). +Thus far we have established that the Battery is publishing its current from the named interface `Battery/EV_current` and the Charger is subscribing to this named interface. The Charger is also sending information about values. The Charger federate will be publishing the voltage value from the `Charger/EV_voltage` interface (a named output). ![](https://github.com/GMLC-TDC/helics_doc_resources/raw/main/user_guide/charger_pub.png) -In order to guarantee that the Battery federate receives the voltage value from the Charger federate, the Battery will have an unnamed input subscription which targets the `Charger/EV_voltage` handle. +In order to guarantee that the Battery federate receives the voltage value from the Charger federate, the Battery will have an unnamed input subscription which targets the `Charger/EV_voltage` interface. ![](https://github.com/GMLC-TDC/helics_doc_resources/raw/main/user_guide/battery_sub.png) @@ -96,9 +96,9 @@ This federate is configured with pubs and subs, so it will need an option to ind ] ``` -This pub and sub configuration is telling us that the `Battery.py` federate is publishing in units of amps (`A`) for current from the named handle (`key`) `Battery/EV1_current`. This federate is also subscribing to information from the `Charger.py` federate. It has subscribed to a value in units of volts (`V`) at the named handle (`key`) `Charger/EV1_voltage`. +This pub and sub configuration is telling us that the `Battery.py` federate is publishing in units of amps (`A`) for current from the named interface (`key`) `Battery/EV1_current`. This federate is also subscribing to information from the `Charger.py` federate. It has subscribed to a value in units of volts (`V`) at the named interface (`key`) `Charger/EV1_voltage`. -As discussed in [Register and Configure Federates](#register-and-configure-federates), the federate registration and configuration with JSON files in the python federate is done with one line of code: +As discussed in ["Simulator Integration: External JSON""](#simulator-integration-external-json), the federate registration and configuration with JSON files in the python federate is done with one line of code: ```python fed = h.helicsCreateValueFederateFromConfig("BatteryConfig.json") @@ -119,13 +119,9 @@ The runner JSON for the Base Example is called `fundamental_default_runner.json` ```json { + "name": "fundamental_default", + "broker": true, "federates": [ - { - "directory": ".", - "exec": "helics_broker -f 2 --loglevel=7", - "host": "localhost", - "name": "broker" - }, { "directory": ".", "exec": "python -u Charger.py 1", @@ -138,8 +134,7 @@ The runner JSON for the Base Example is called `fundamental_default_runner.json` "host": "localhost", "name": "Battery" } - ], - "name": "fundamental_default" + ] } ``` @@ -149,7 +144,7 @@ This runner tells `helics_broker` that there are three federates and to take a s 2. Launch the `Charger.py` federate in the current directory: `python -u Charger.py 1` 3. Launch the `Battery.py` federate in the current directory: `python -u Battery.py 1` -The final step is to launch our Base Example with the HELICS runner from the command line: +The final step is to launch our Base Example with the HELICS runner from the command line (making sure you've [installed the HELICS cli extension](../../installation/index.md)): ```shell helics run --path=fundamental_default_runner.json @@ -166,6 +161,6 @@ We can see the state of charge of each battery over the duration of the co-simul Do you have questions about HELICS or need help? -1. Come to [office hours](mailto:helicsteam@helics.org)! +1. Come to [office hours](https://helics.org/HELICSOfficeHours.ics)! 2. Post on the [gitter](https://gitter.im/GMLC-TDC/HELICS)! 3. Place your question on the [github forum](https://github.com/GMLC-TDC/HELICS/discussions)! diff --git a/docs/user-guide/examples/fundamental_examples/fundamental_endpoints.md b/docs/user-guide/examples/fundamental_examples/fundamental_endpoints.md index aafcd783fc..29ec00f720 100644 --- a/docs/user-guide/examples/fundamental_examples/fundamental_endpoints.md +++ b/docs/user-guide/examples/fundamental_examples/fundamental_endpoints.md @@ -6,8 +6,8 @@ This tutorial is organized as follows: - [Example files](#example-files) - [Federate Communication with Endpoints](#federate-communication-with-endpoints) - - [When to use pub/subs vs endpoints](#when-to-use-pub-subs-vs-endpoints) - - [Translation from pub/sub to endpoints](#translation-from-pub-sub-to-endpoints) + - [When to use pub/subs vs endpoints](#when-to-use-pubsubs-vs-endpoints) + - [Translation from pub/sub to endpoints](#translation-from-pubsub-to-endpoints) - [Config Files](#config-files) - [Simulators](#simulators) - [Co-simulation Execution](#co-simulation-execution) @@ -143,7 +143,7 @@ As with the Base Example, configuration can be done with JSON files. The first c ] ``` -If you have run the Base Example, you will have seen that the information passed between the federates occurs at the same HELICS time; both federates have `"period": 60` in their config files. Recall from the [Configuration Options Reference](../../../references/configuration_options_reference.md#period-0) that the `period` controls the minimum time resolution for a federate. +If you have run the Base Example, you will have seen that the information passed between the federates occurs at the same HELICS time; both federates have `"period": 60` in their config files. Recall from the [Configuration Options Reference](../../../references/configuration_options_reference.md#period-1ns) that the `period` controls the minimum time resolution for a federate. We have a federation sending messages at the same time (`"period": 60`), and HELICS doesn't know which message arrives first. We need to introduce an `offset` to the config file of one of the federates to force it to wait until the message has been received. We also need to keep `"uninterruptible": false`, so that the federate will be granted the time at which it has received a message (which will be `"period": 60`). @@ -323,6 +323,6 @@ Armed now with the knowledge of endpoints and messages, how could you change the Do you have questions about HELICS or need help? -1. Come to [office hours](mailto:helicsteam@helics.org)! +1. Come to [office hours](https://helics.org/HELICSOfficeHours.ics)! 2. Post on the [gitter](https://gitter.im/GMLC-TDC/HELICS)! 3. Place your question on the [github forum](https://github.com/GMLC-TDC/HELICS/discussions)! diff --git a/docs/user-guide/examples/fundamental_examples/fundamental_examples_index.md b/docs/user-guide/examples/fundamental_examples/fundamental_examples_index.md index 9bdc7e02ee..4faeeae6d1 100644 --- a/docs/user-guide/examples/fundamental_examples/fundamental_examples_index.md +++ b/docs/user-guide/examples/fundamental_examples/fundamental_examples_index.md @@ -16,15 +16,15 @@ The Fundamental examples are meant to build in complexity -- if you are new to H This page describes the model -- what is the research question addressed, and what are the components to a simple HELICS co-simulation: -- [Where is the code?](#where-is-the-code) -- [What is this Co-simulation doing?](#what-is-this-co-simulation-doing) -- [HELICS Components](#helics-components) - - [Register and Configure Federates](#register-and-configure-federates) - - [Enter Execution Mode](#enter-execution-mode) - - [Define Time Variables](#define-time-variables) - - [Initiate Time Steps for the Time Loop](#initiate-time-steps-for-the-time-loop) - - [Send/Receive Communication between Federates](#send-receive-communication-between-federates) - - [Finalize Co-simulation](#finalize-co-simulation) +- Where is the Code? +- What is this Co-simulation Doing? +- HELICS Components + - Register and Configure Federates + - Enter Execution Mode + - Define Time Variables + - Initiate Time Steps for the Time Loop + - Send/Receive Communication between Federates + - Finalize Co-simulation @@ -224,9 +224,9 @@ Send/Receive Communication between Federates -Once inside the time loop, information is requested and sent between federates at each time step. In the Base Example, the federates first request information from the handles to which they have subscribed, and then send information from the handles from which they publish. +Once inside the time loop, information is requested and sent between federates at each time step. In the Base Example, the federates first request information from the interfaces to which they have subscribed, and then send information from the interfaces from which they publish. -The `Battery.py` federate first asks for voltage information from the handles to which it subscribes: +The `Battery.py` federate first asks for voltage information from the interfaces to which it subscribes: ```python # Get the applied charging voltage from the EV @@ -237,7 +237,7 @@ logger.debug( ) ``` -And then (after doing some internal calculations) publishes the charging current of the battery at its publication handle: +And then (after doing some internal calculations) publishes the charging current of the battery at its publication interface: ```python # Publish out charging current @@ -245,7 +245,7 @@ h.helicsPublicationPublishDouble(pubid[j], charging_current) logger.debug(f"\tPublished {pub_name[j]} with value " f"{charging_current:.2f}") ``` -Meanwhile, the `Charger.py` federate asks for charging current from the handles to which it subscribes: +Meanwhile, the `Charger.py` federate asks for charging current from the interfaces to which it subscribes: ```python charging_current[j] = h.helicsInputGetDouble((subid[j])) @@ -255,7 +255,7 @@ logger.debug( ) ``` -And publishes the charging voltage at its publication handle: +And publishes the charging voltage at its publication interface: ```python # Publish updated charging voltage diff --git a/docs/user-guide/examples/fundamental_examples/fundamental_fedintegration.md b/docs/user-guide/examples/fundamental_examples/fundamental_fedintegration.md index d1c350256d..001ccefcbe 100644 --- a/docs/user-guide/examples/fundamental_examples/fundamental_fedintegration.md +++ b/docs/user-guide/examples/fundamental_examples/fundamental_fedintegration.md @@ -5,9 +5,9 @@ The Federate Integration Example extends the Base Example to demonstrate how to - [Computing Environment](#computing-environment) - [Example files](#example-files) - [Federate Integration using the PyHELICS API](#federate-integration-using-the-pyhelics-api) - - [Translation from JSON to PyHELICS API methods](#translation-from-json-to-pyhelics-api) + - [Translation from JSON to PyHELICS API methods](#translation-from-json-to-pyhelics-api-methods) - [Federate Integration with API calls](#federate-integration-with-api-calls) - - [Dynamic Pub/Subs with API calls](#dynamic-pub-subs-with-api-calls) + - [Dynamic Pub/Subs with API calls](#dynamic-pubsubs-with-api-calls) - [Co-simulation Execution](#co-simulation-execution) - [Questions and Help](#questions-and-help) @@ -187,7 +187,7 @@ Notice that we pass to this API the `fedinfo` set by all preceding API calls. ### Dynamic Pub/Subs with API calls -In the Base Example, we configured the pubs and subs with an external JSON file, where _each_ publication and subscription between federate handles needed to be explicitly defined for a predetermined number of connections: +In the Base Example, we configured the pubs and subs with an external JSON file, where _each_ publication and subscription between federate interfaces needed to be explicitly defined for a predetermined number of connections: ```json "publications":[ @@ -286,6 +286,6 @@ If your output is not the same as with the Base Example, it can be helpful to pi Do you have questions about HELICS or need help? -1. Come to [office hours](mailto:helicsteam@helics.org)! +1. Come to [office hours](https://helics.org/HELICSOfficeHours.ics)! 2. Post on the [gitter](https://gitter.im/GMLC-TDC/HELICS)! 3. Place your question on the [github forum](https://github.com/GMLC-TDC/HELICS/discussions)! diff --git a/docs/user-guide/examples/fundamental_examples/fundamental_filter_federate.md b/docs/user-guide/examples/fundamental_examples/fundamental_filter_federate.md index f8fd5f5ddf..6935e48cb4 100644 --- a/docs/user-guide/examples/fundamental_examples/fundamental_filter_federate.md +++ b/docs/user-guide/examples/fundamental_examples/fundamental_filter_federate.md @@ -24,9 +24,9 @@ All files necessary to run the Federate Integration Example can be found in the - (Bonus Python program where the Filter Federate does no filtering and forwards on all received messages) - HELICS runner JSON to enable execution of the co-simulation -## Filter Federate +## Filter Federates -For situations that require filtering beyond what native HELICS filters can provide, it is possible to create a custom filter federate that acts in specific ways on the messages that receives and forwards on. Not only is it possible to re-create the native helix filter functions such as delay or dropped message but it is also possible act on the payloads of the messages themselves. Some of these functionalities (such as dropped or delayed messages) can be achieved through existing simulation tools such as an [ns-3](https://www.nsnam.org). Even in an ns-3, though custom functionality that would modify message payloads would require writing custom applications in at the industry codebase. Though this example custom filter federate example doesn't implement many of the detailed networking models in an ns-3 such as TCP and IP addressing, it's simplicity is a virtue in that it demonstrates how to implement a custom filter federate to act on HELICS messages an arbitrary manner. +For situations that require filtering beyond what native HELICS filters can provide, it is possible to create a custom filter federate that acts in specific, user-define ways. Not only is it possible to re-create the native HELICS filter functions (_e.g._ delaying or randomly dropping messages) but it is also possible act on the payloads of the messages themselves. Some of these functionalities (such as dropped or delayed messages) can be achieved through existing simulation tools such as an [ns-3](https://www.nsnam.org). Even in an ns-3, though custom functionality that would modify message payloads would require writing custom applications and compiling them into ns-3. Though this example custom filter federate doesn't implement many of the detailed networking models in an ns-3 such as TCP and IP addressing, it's simplicity is a virtue in that it demonstrates how to implement a custom filter federate to act on HELICS messages an arbitrary manner. Here is our new federation using a custom filter federate: @@ -109,6 +109,6 @@ When comparing to the results from the [previous example without any filters](./ Do you have questions about HELICS or need help? -1. Come to [office hours](mailto:helicsteam@helics.org)! +1. Come to [office hours](https://helics.org/HELICSOfficeHours.ics)! 2. Post on the [gitter](https://gitter.im/GMLC-TDC/HELICS)! 3. Place your question on the [github forum](https://github.com/GMLC-TDC/HELICS/discussions)! diff --git a/docs/user-guide/examples/fundamental_examples/fundamental_native_filter.md b/docs/user-guide/examples/fundamental_examples/fundamental_native_filter.md index 7f8c5ccabe..4f3ee7819c 100644 --- a/docs/user-guide/examples/fundamental_examples/fundamental_native_filter.md +++ b/docs/user-guide/examples/fundamental_examples/fundamental_native_filter.md @@ -5,7 +5,7 @@ This custom filter federate example expands the [combination federation example] This tutorial is organized as follows: - [Example files](#example-files) -- [HELICS Filters](#HELICS-filters) +- [HELICS Filters](#helics-filters) - [Co-simulation Execution](#co-simulation-execution) - [Questions and Help](#questions-and-help) @@ -77,6 +77,6 @@ Below are pairs of output graphs with the first from each pair being from the or Do you have questions about HELICS or need help? -1. Come to [office hours](mailto:helicsteam@helics.org)! +1. Come to [office hours](https://helics.org/HELICSOfficeHours.ics)! 2. Post on the [gitter](https://gitter.im/GMLC-TDC/HELICS)! 3. Place your question on the [github forum](https://github.com/GMLC-TDC/HELICS/discussions)! diff --git a/docs/user-guide/examples/misc_examples/gridlabd_example_1/gridlabd_example_1_index.md b/docs/user-guide/examples/misc_examples/gridlabd_example_1/gridlabd_example_1_index.md new file mode 100644 index 0000000000..d11a0a4085 --- /dev/null +++ b/docs/user-guide/examples/misc_examples/gridlabd_example_1/gridlabd_example_1_index.md @@ -0,0 +1,15 @@ +# GridLAB-D Example 1 + +This example is from an old version of the User Guide and shows how GridLAB-D can be used with HELICS to implement functionality that would otherwise not be possible without editing GridLAB-D source code. The example repeats some of the material in the [Fundamentals section of the User Guide](../../../fundamental_topics/fundamental_topics_index.md) but, by including GridLAB-D, provides a more concrete example of how to use HELICS to answer power system problems. + +```{eval-rst} +.. toctree:: + :maxdepth: 1 + + gridlabd_example_1a_value_federate + gridlabd_example_1b_message_federate + gridlabd_example_1c_filter_federate + + + +``` diff --git a/docs/user-guide/examples/misc_examples/gridlabd_example_1/gridlabd_example_1a_value_federate.md b/docs/user-guide/examples/misc_examples/gridlabd_example_1/gridlabd_example_1a_value_federate.md new file mode 100644 index 0000000000..b10c3f6ae3 --- /dev/null +++ b/docs/user-guide/examples/misc_examples/gridlabd_example_1/gridlabd_example_1a_value_federate.md @@ -0,0 +1,97 @@ +# Example 1a: GridLAB-D as a Value Federate + +HELICS messages that are value-oriented are the most common type of messages. As mentioned in the [federate introduction](../../../fundamental_topics/federates.md), value messages are intended to be used to represent the physics of a system, linking federates at their mutual boundaries and allowing a larger and more complex system to be represented than would be the case if only one simulator was used. + +## Value Federate Interface Types + +There are four interface types for value federates that allow the interactions between the federates (a large part of co-simulation/federation configuration) to be flexibly defined. The difference between the four types revolve around whether the interface is for sending or receiving HELICS messages and whether the sender/receiver is defined by the federate (technically, the core associated with the federate): + +- **Publications** - Sending interface where the federate core does not specify the intended recipient of the HELICS message +- **Named Inputs** - Receiving interface where the federate core does not specify the source federate of the HELICS message +- **Directed Outputs** - Sending interface where the federate core specifies the recipient of HELICS message +- **Subscriptions** - Receiving interface where the federate core specifies the sender of HELICS message + +In all cases the configuration of the federate core declares the existence of the interface to use for communicating with other federates. The difference between "publication"/"named inputs" and "directed outputs"/"subscriptions" is where that federate core itself knows the specific names of the interfaces on the receiving/sending federate core. + +The message type used for a given federation configuration is often an expression of the preference of the user setting up the federation. There are a few important differences that may guide which interfaces to use: + +- **Which interfaces does the simulator support?** - Though it is the preference of the HELICS development team that all integrated simulators support all four types, that may not be the case. Limitations of the simulator may limit your options as a user of that simulator. +- **Is portability of the federate and its configuration important?** - Because "publications" and "named inputs" don't require the federate to know who it is sending HELICS messages to and receiving HELICS messages from as part of the federate configuration, it affords a slightly higher degree of portability between different federations. The mapping of HELICS messages still needs to be done to configure a federation, its just done separately from the federate configuration file via a broker or core configuration file. The difference in location of this mapping may offer some configuration efficiencies in some circumstances. + +Though all four message types are supported, the remainder of this guide will focus on publications and subscriptions as they are conceptually easily understood and can be comprehensively configured through the individual federate configuration files. + +## Federate Configuration Options via JSON + +For any simulator that you didn't write for yourself, the most common way of configuring that simulator for use in a HELICS co-simulation will be through the use of an external JSON configuration file. TOML files are also supported but we will concentrate on JSON for this discussion. This file is read when a federate is being created and initialized and it will provide all the necessary information to incorporate that federate into the co-simulation. + +As the fundamental role of the co-simulation platform is to manage the synchronization and data exchange between the federates, you may or may not be surprised to learn that there are generic configuration options available to all HELICS federates that deal precisely with these. In this section, we'll focus on the options related to data exchange as pertaining to value federates, those options and in [Timing section](../../../fundamental_topics/timing_configuration.md) we'll look at the timing parameters. + +Let's look at a generic JSON configuration file as an example with the more common parameters shown; the default values are shown in "[ ]". (Further parameters and explanations can be found in the [federate configuration](../../../../references/configuration_options_reference.md) guide. + +## Example 1a - Basic transmission and distribution powerflow + +To demonstrate how a to build a co-simulation, an example of a simple integrated transmission system and distribution system powerflow can be built; all the necessary files are found [HERE](https://github.com/GMLC-TDC/HELICS-Examples/tree/160409d079d5a95bc08d37e7eef76d4748f8e9a8/user_guide_examples/misc/gridlabd_example_1) but to use them you'll need to get some specific software installed; here are the instructions: + +1. [HELICS](../../../installation/index.md) +2. [GridLAB-D](https://github.com/gridlab-d/gridlab-d/tree/develop) - Enable HELICS, see instructions [here](http://gridlab-d.shoutwiki.com/wiki/Connection:helics_msg) +3. [Python](https://www.anaconda.com/download/) - Anaconda installation, if you don't already have Python installed. You may need to also install the following Python packages (`conda install` ...) + - matplotlib + - time + - logging +4. [PyPower](https://pypi.org/project/PYPOWER/) - `pip install pypower` + +This example has a very simple message topology (with only one message being sent by either federate at each time step) and uses only a single broker. Diagrams of the message and broker topology can be found below: + +![Ex. 1a message topology](https://github.com/GMLC-TDC/helics_doc_resources/raw/main/user_guide/Ex1a_Message_topology.png) + +![Ex. 1a broker topology](https://github.com/GMLC-TDC/helics_doc_resources/raw/main/user_guide/Ex1a_Broker_topology.png) + +- **Transmission system** - The transmission system model used is the IEEE-118 bus model. To a single bus in this model the GridLAB-D distribution system is attached. All other load buses in the model use a static load shape scaled proportionately so the peak of the load shape matches meet the model-defined load value. The generators are re-dispatched every fifteen minutes by running an optimal power flow (the so-called "ACOPF" which places constraints on the voltage at the nodes in the system) and every five minutes a powerflow is run the update the state of the system. To allow for the relatively modest size of the single distribution system attached to the transmission system, the distribution system load is amplified by a factor of fifteen before being applied to the transmission system. + +- **Distribution system** - A GridLAB-D model of the IEEE-123 node distribution system has been used. The model includes voltage regulators along the primary side of the system and includes secondary (or distribution) transformers with loads attached to the secondary of these transformers. The loads themselves are ZIP loads with a high impedance traction that are randomly scaled versions of the same time-varying load-shapes. + +In this particular case, the Python script executing the transmission model also creates the broker; this is a choice of convenience and could have been created by any other federates. This simulation is run for 24 hours. + +### Running co-simulations via `helics run ...` + +To run this simulation, the HELICS team has also developed a standardized means of launching co-simulations. Discussion of how to configure a JSON for use in launching a HELICS-based co-simulation is discussed in the [over here](../../../fundamental_topics/helics_run.md) but for all these examples, the configuration has already been done. In this case, that configuration is in the examples folder as "cosim_runner_1a.json" and looks like this: + +```json +{ + "broker": true, + "federates": [ + { + "directory": ".", + "exec": "python 1abc_Transmission_simulator.py -c 1a", + "host": "localhost", + "name": "1a_Transmission" + }, + { + "directory": ".", + "exec": "gridlabd 1a_IEEE_123_feeder.glm", + "host": "localhost", + "name": "1a_GridLABD" + } + ], + "name": "1a-T-D-Cosimulation-HELICSRunner" +} +``` + +Briefly, it's easy to guess what a few of these parameters do: + +- "directory" is the location of the model to be run +- "exec" is the command line call (with all necessary options) to launch the co-simulation + +With a properly written configuration file, launching the co-simulation becomes very straightforward: + +`helics run --path=` + +### Experiment and Results + +To show the difference between running these two simulators in a stand-alone analysis and as a co-simulation, modify the federate JSON configurations and use `helics run ...` in both cases to run the analysis. To run the two as a co-simulation, leave publication and subscription entries in the federate JSON configuration. To run them as stand-alone federates with no interaction, delete the publications and subscriptions from both JSON configuration files. By removing the information transfer between the two they become disconnected but are still able to be executed as if they were participating in the federation. + +The figure below shows the total load on the transmission node to which the distribution system model is attached and the transmission system voltage at the same node over the course of the simulated day. + +![Ex. 1a transmission bus voltage](https://github.com/GMLC-TDC/helics_doc_resources/blob/db4e8a9edeb5602c6463ff147b8bc72e6119532e/user_guide/1a_transmission_plot.png?raw=true) + +As can be seen, the load and voltage are correlated as expected but the correlation is relatively weak; big changes in load have minimal impacts on the transmission voltage. This is what we would expect for a simple transmission and distribution co-simulation. diff --git a/docs/user-guide/examples/misc_examples/gridlabd_example_1/gridlabd_example_1b_message_federate.md b/docs/user-guide/examples/misc_examples/gridlabd_example_1/gridlabd_example_1b_message_federate.md new file mode 100644 index 0000000000..b8199c46f4 --- /dev/null +++ b/docs/user-guide/examples/misc_examples/gridlabd_example_1/gridlabd_example_1b_message_federate.md @@ -0,0 +1,144 @@ +# Example 1b: GridLAB-D as a Message Federates + +As previously discussed in the [federate introduction](../../../fundamental_topics/federates.md), message federates are used to create HELICS messages that model information transfers (versus physical values) moving between federates. Measurement and control signals are typical applications for these types of federates. + +Unlike HELICS values which are persistent (meaning they are continuously available throughout the co-simulation), HELICS messages are only readable once when collected from an endpoint. Once that collection is made the message only exists within the memory of the collecting message federate. If another message federate needs the information, a new message must be created and sent to the appropriate endpoint. Filters can be created to clone messages as well if that behavior is desired. + +## Message Federate Endpoints + +As previously discussed, message federates interact with the federation by defining an "endpoint" that acts as their address to send and receive messages. Message federates are typically sending and receiving measurements, control signals, commands, and other signal data with HELICS acting as a perfect communication system (infinite bandwidth, virtually no latency, guaranteed delivery). + +In fact, as you'll see in [a later section](../../../fundamental_topics/filters.md), it is possible to create more realistic communication-system effects natively in HELICS (as well as use a full-blown communication simulator like [ns-3](https://www.nsnam.org) to do the same). This is relevant now, though, because it influences how the endpoints are created and, as a consequence, how the simulator handles messages. You could, for example, have a system with three federates communicating with each other: a remote voltage sensor, a voltage controller, and a voltage regulation actuator (we'll pretend for the case of this example that the last two are physically separated though they often aren't). In this case, you could imagine that the voltage sensor only sends messages to the voltage controller and the voltage controller only sends messages to the voltage regulation actuator. That is, those two paths between the three entities are distinct, have no interaction, and have unique properties (though they may not be modeled). Given this, referring to the figure below, the voltage sensor could have one endpoint ("Endpoint 1") to send the voltage signal, the voltage regulator could receive the measurement at one endpoint ("Endpoint 2") and send the control signal on another ("Endpoint 3"), and the voltage regulation actuator would receive the control signal on its own endpoint ("Endpoint 4"). + +![Voltage regulation message federates](https://github.com/GMLC-TDC/helics_doc_resources/raw/main/user_guide/voltage_reg_message_federate.png) + +The federate code handling these messages can be relatively simple because the data coming in or going out of each endpoint is unique. The voltage controller always receives (and only receives) the voltage measurement at one endpoint and similarly only sends the control signal on another. + +Consider a counter-example: automated meter-reading (AMI) using a wireless network that connects all meters in a distribution system to a data-aggregator in the substation (where, presumably, the data travels over a dedicated wired connection to a control room). All meters will have a single endpoint over which they will send their data but what about the receiver? The co-simulation could be designed with the data-aggregator having a unique endpoint for each meter but this implies come kind of dedicated communication channel for each meter; this is not the case with wireless communication. Instead, it is probably better to create a single endpoint representing the wireless connection the data aggregator has with the AMI network. In this case, messages from any of the meters in the system will be flowing through the same endpoint and to differentiate the messages from each other, the federate will have to be written to examine the metadata with the message to determine its original source. + +![Signal topology for AMI message federates](https://github.com/GMLC-TDC/helics_doc_resources/raw/main/user_guide/ami_message_federate.png) + +## Interactions Between Messages and Values + +Though it is not possible to have a HELICS message show up at a value interface, the converse is possible; message_federates can subscribe to HELICS values. Every time a value federate publishes a new value to the federation, if a message federate has subscribed to that message HELICS will generate a new HELICS message and send it directly to the destination endpoint. These messages are queued and not overwritten (unlike in HELICS values) which means when a message federate is synchronized it may have multiple messages from the same source to manage. + +This feature offers the convenience of allowing a message federate to receive messages from pure value federates that have no endpoints defined. This is particularly useful for simulators that do not support endpoints but are required to provide measurement signals controllers. Implemented in this way, though, it is not possible to later implement a full-blown communication simulator that these values-turned-messages can traverse. Such co-simulation architectures in HELICS require the existence of both a sending and receiving endpoint; this feature very explicitly by-passes the need for a sending endpoint. + +## Example 1b - Distribution system EV charge controller + +To demonstrate how a message federate interacts with the federation, let's take the previous example and add two things to it: add electric vehicle (EV) loads in the distribution system, and a centralized EV charge control manager. [Models files for this example can be found here](https://github.com/GMLC-TDC/HELICS-Examples/tree/160409d079d5a95bc08d37e7eef76d4748f8e9a8/user_guide_examples/misc/gridlabd_example_1). + +Keeping in mind that this a model for demonstration purposes (which is to say, don't take this too seriously), let's make the following assumptions and definitions to simplify the behavior of the EV charge controller: + +- All EVs are very large (200kW; level 2 charging is rated up to 20kW so these are effective HVDC chargers) +- All EVs have infinite battery capacity +- All EVs will be at home all day, desiring to charge all day if they can. +- All EVs charge at the same power level. +- The EV charge controller has direct control over the charging of all EVs in the distribution system. It can tell them when to turn off and on at will. +- The EV charge controller has the responsibility to limit the total load of the distribution system to a specified level to prevent overloading on the substation transformer. +- The EV will turn off some EV charging when the total distribution load exceeds the transformer limit by a certain percentage and will turn some EVs back on when below the limit by a certain percentage. +- Nothing is fair about how the charge controller chooses which EVs to charge and which to disconnect. + +The message topology (including the endpoints) and the not very interesting broker topology are shown below. + +![Ex. 1b signal topology](https://github.com/GMLC-TDC/helics_doc_resources/raw/main/user_guide/Ex1b_Message_topology.png) + +![Ex. 1b broker topology](https://github.com/GMLC-TDC/helics_doc_resources/raw/main/user_guide/Ex1b_Broker_topology.png) + +Taking these assumptions and specifications, it is not too difficult to write a simple charge controller as a Python script. And just by opening the [JSON configuration file](https://github.com/GMLC-TDC/HELICS-Examples/blob/160409d079d5a95bc08d37e7eef76d4748f8e9a8/user_guide_examples/misc/gridlabd_example_1/1b_cosim_runner.json) we can learn important details about how the controller works. + +```json +{ + "broker": true, + "federates": [ + { + "directory": ".", + "exec": "python 1abc_Transmission_simulator.py -c 1b", + "host": "localhost", + "name": "1b_Transmission" + }, + { + "directory": ".", + "exec": "python 1bc_EV_Controller.py -c 1b", + "host": "localhost", + "name": "1b_Controller" + }, + { + "directory": ".", + "exec": "gridlabd.sh 1b_IEEE_123_feeder.glm", + "host": "localhost", + "name": "1b_GridLABD" + } + ], + "name": "1b-T-D-Cosimulation-HELICSRunner" +} +``` + +The first thing to note is the the EV controller has been written as a combination federate, having both endpoints for receiving/sending messages and subscriptions to HELICS values. The HELICS values that the controller has subscribed to give the controller access to both the total load of the feeder (`totalLoad`, presumably) as well as the charging power for each of the individual EVs being controlled (six in total). + +Looking at the [GridLAB-D JSON configuration file](https://github.com/GMLC-TDC/HELICS/tree/319de2b125fe5e36818f0434ac3d0a82ccc46534/examples/user_guide_examples/Example_1b/Distribution/IEEE_123_feeder_0.json) confirms this: + +```json +{ + "coreInit": "--federates=1", + "coreName": "Distribution Federate", + "coreType": "zmq", + "name": "DistributionSim", + "offset": 0.0, + "period": 60, + "timeDelta": 1.0, + "logfile": "output.log", + "log_level": "warning", + "publications": [ + { + "global": true, + "key": "IEEE_123_feeder_0/totalLoad", + "type": "complex", + "unit": "VA", + "info": { + "object": "network_node", + "property": "distribution_load" + } + } + ], + "subscriptions": [ + { + "required": true, + "key": "TransmissionSim/transmission_voltage", + "type": "complex", + "unit": "V", + "info": { + "object": "network_node", + "property": "positive_sequence_voltage" + } + } + ], + "endpoints": [ + { + "global": true, + "key": "IEEE_123_feeder_0/EV6", + "destination": "EV_Controller/EV6", + "info": { + "publication_info": { + "object": "EV6", + "property": "constant_power_A" + }, + "subscription_info": { + "object": "EV6", + "property": "constant_power_A" + } + } + } + ] +} +``` + +GridLAB-D is publishing out the total load on the feeder as well as the individual EV charging loads. It also has endpoints set up for each of the EV chargers to receive messages from the controller. Based on the strings in the `info` field it appears that the received messages are used to define the EV charge power. + +Running [the example](https://github.com/GMLC-TDC/HELICS-Examples/blob/160409d079d5a95bc08d37e7eef76d4748f8e9a8/user_guide_examples/misc/gridlabd_example_1/1b_cosim_runner.json) and looking at the results, as the total load on the feeder exceeded the pre-defined maximum loading of the feeder (red line in the graph), the EV controller disconnected an additional EV load. Conversely, as the load dipped to the lower limit (green line), the controller reconnected the EV load. Looking at a graph of the EV charge power for each EV shows the timing of the EV charging for each load. + +![Ex. 1b EV charge pattern](https://github.com/GMLC-TDC/helics_doc_resources/blob/db4e8a9edeb5602c6463ff147b8bc72e6119532e/user_guide/1b_EV_plot.png?raw=true) + +Given the relatively dramatic changes in load, you might expect the voltage on the transmission system to be impacted. + +![Ex. 1b transmission system voltage and load magnitude](https://github.com/GMLC-TDC/helics_doc_resources/blob/db4e8a9edeb5602c6463ff147b8bc72e6119532e/user_guide/1b_transmission_plot.png?raw=true) diff --git a/docs/user-guide/examples/misc_examples/gridlabd_example_1/gridlabd_example_1c_filter_federate.md b/docs/user-guide/examples/misc_examples/gridlabd_example_1/gridlabd_example_1c_filter_federate.md new file mode 100644 index 0000000000..727cda4f4a --- /dev/null +++ b/docs/user-guide/examples/misc_examples/gridlabd_example_1/gridlabd_example_1c_filter_federate.md @@ -0,0 +1,35 @@ +# Example 1c: Filters and their Impacts on HELICS Messages + +As was introduced in the [introductory section on federates](../../../fundamental_topics/federates.md), message federates (and combo federates) are used to send messages (control signals, measurements, anything traveling over some kind of communication network) via HELICS to other federates. Though they seem very similar, the way messages and values are handled by HELICS is very different and is motivated by the underlying reality they are being used to model. + +1. **Messages are directed and unique, values are persistent.** - Because HELICS values are used to represent physical reality, they are available to any subscribing federate at any time. If the publishing federate only updates the value, say, once every minute, any subscribing federates that are granted a time during that minute window will all receive the same value regardless of when they requested it. + + HELICS messages, though, are much more like other kinds of real-world messages in that they are directed and unique. Messages are sent by a federate from one endpoint to another endpoint in the federation (presumably the receiving endpoint is owned by another federate but this doesn't have to be the case). Internal to HELICS, each message has a unique identifier and can be thought to travel between a generic communication system between the source and destination endpoints. + +2. **Messages can be filtered, values cannot.** - By creating a generic communication system between two endpoints, HELICS has the ability to model simple communication system effects on messages traveling through said network. These effects are called "filters" and are associated with the HELICS core (which in turn manages the federate's endpoints) embedded with the federate in question. Typical filtering actions might be delaying the transmission of the message or randomly dropping a certain percentage of the received messages. Filters can also be defined to operate on messages being sent ("source filters") and/or messages being received ("destination filters"). + + Because HELICS values do not pass through this generic network, they cannot be operated on by filters. Since HELICS values are used to represent physics of the system not the control and coordination of it, it is appropriate that filters not be available to modify them. It is entirely possible to use HELICS value federates to send control signals to other federates; co-simulations can and have been made to work in such ways. Doing so, though, cuts out the possibility of using filters and, as we'll see, the easy integration of communication system simulators. + +The figure below is an example of a representation of the message topology of a generic co-simulation federation composed entirely of message federates. Source and destination filters have been implemented (indicated by the blue endpoints), each showing a different built-in HELICS filter function. + +- As a reminder, a single endpoint can be used to both send and receive messages (as shown by Federate 4). Both a source filter and a destination filter can be set up on a single endpoint. In fact multiple source filters can be used on the same endpoint. +- The source filter on Federate 3 delays the messages to both Federate 2 and Federate 4 by the same 0.5 seconds. Without establishing a separate endpoint devoted to each federate, there is no way to produce different delays in the messages sent along these two paths. +- Because the filter on Federate 4 is a destination filter, the message it receives from Federate 3 is affected by the filter but the message it sends to Federate 2 is not affected. +- As constructed, the source filter on Federate 2 has no impact on this co-simulation as there are no messages sent from that endpoint. +- Individual filters can be targeted to act on multiple endpoints and act as both source and destination filters. + +![Signal topology using built-in HELICS filters](https://github.com/GMLC-TDC/helics_doc_resources/raw/main/user_guide/messages_and_filters_example.png) + +## Example 1c - EV charge controller with HELICS filters + +To demonstrate the effects of filters, let's take the same model we were working with in the [previous example](../../../fundamental_topics/message_federates.md), and add a filter to the controller. Specifically, let's assume a very, very poor communication system and add a 3600 second delay to the control messages sent from the EV charge controller to each of the EVs. ([Model files for this example can be found here](https://github.com/GMLC-TDC/HELICS-Examples/tree/160409d079d5a95bc08d37e7eef76d4748f8e9a8/user_guide_examples/misc/gridlabd_example_1).) + +![Ex. 1c signal topology](https://github.com/GMLC-TDC/helics_doc_resources/raw/main/user_guide/Ex1c_Message_topology.png) + +Let's run [this co-simulation](https://github.com/GMLC-TDC/HELICS-Examples/blob/160409d079d5a95bc08d37e7eef76d4748f8e9a8/user_guide_examples/misc/gridlabd_example_1/1c_cosim_runner.json) and capture the same data as last time for direct comparison: total substation load and EV charging behavior, both as a function of time. + +![Ex. 1c total feeder load and voltage](https://github.com/GMLC-TDC/helics_doc_resources/blob/db4e8a9edeb5602c6463ff147b8bc72e6119532e/user_guide/1c_transmission_plot.png?raw=true) + +![Ex. 1c EV charge pattern](https://github.com/GMLC-TDC/helics_doc_resources/blob/db4e8a9edeb5602c6463ff147b8bc72e6119532e/user_guide/1c_EV_plot.png?raw=true) + +Granted that the charge controller communication system is ridiculously poor, this example does show that communication system effects can have a significant impact on system operation. For more realistic example, the HELICS Use Case repository has [an example](https://github.com/GMLC-TDC/HELICS-Use-Cases/tree/main/PNNL-Wide-Area-Control) of frequency control using real-time PMU measurements that shows the impact of imperfect communication systems. diff --git a/docs/user-guide/examples/misc_examples/misc_examples_index.md b/docs/user-guide/examples/misc_examples/misc_examples_index.md new file mode 100644 index 0000000000..13db55f276 --- /dev/null +++ b/docs/user-guide/examples/misc_examples/misc_examples_index.md @@ -0,0 +1,12 @@ +# Miscellaneous Examples + +This section provides a collection of miscellaneous examples that we hope will help users + +```{eval-rst} +.. toctree:: + :maxdepth: 1 + + gridlabd_example_1/gridlabd_example_1_index + + +``` diff --git a/docs/user-guide/examples/supported_languages_examples/supported_languages_examples_index.md b/docs/user-guide/examples/supported_languages_examples/supported_languages_examples_index.md index e5d7061515..8a7148f263 100644 --- a/docs/user-guide/examples/supported_languages_examples/supported_languages_examples_index.md +++ b/docs/user-guide/examples/supported_languages_examples/supported_languages_examples_index.md @@ -5,7 +5,7 @@ The User Guide Examples are primarily written in Python due to its popularity but HELICS provides language bindings for many other languages. To demonstrate this, [one of the examples](../advanced_examples/advanced_default) has been written in each of the supporting languages to show how the APIs look in each of those languages but achieve similar functionality. - [Python (C-API)](https://github.com/GMLC-TDC/HELICS-Examples/tree/main/user_guide_examples/advanced/advanced_default) -- [Python (Pythonic API) - forthcoming](https://github.com/GMLC-TDC/HELICS-Examples/issues/76) +- [Python (Pythonic API) - forthcoming](https://github.com/GMLC-TDC/HELICS-Examples/tree/main/user_guide_examples/advanced/advanced_default_pythonic) - [MATLAB](https://github.com/GMLC-TDC/HELICS-Examples/tree/main/user_guide_examples/advanced/advanced_default_matlab) - [C - forthcoming](https://github.com/GMLC-TDC/HELICS-Examples/issues/77) - [C++ - forthcoming](https://github.com/GMLC-TDC/HELICS-Examples/issues/78) diff --git a/docs/user-guide/fundamental_topics/federates.md b/docs/user-guide/fundamental_topics/federates.md index 89d8477c26..19a7e2e9af 100644 --- a/docs/user-guide/fundamental_topics/federates.md +++ b/docs/user-guide/fundamental_topics/federates.md @@ -7,7 +7,6 @@ value_federates message_federates - value_types filters ``` @@ -55,16 +54,16 @@ Value federates have direct fixed connections through interfaces to other federa - Publications - Sending interface - - Handle named with `"key"` in configuration - - Recipient handle of value is not necessary, however it can be specified with `"targets"` in configuration + - Interface named with `"key"` in configuration + - Recipient interface value is not necessary, however it can be specified with `"targets"` in configuration - Subscriptions (Unnamed Inputs) - Receiving interface - Not "named" (no identifier to the rest of the federation) - - Source of value handle is specified with `"key"` in configuration + - Source of value interface is specified with `"key"` in configuration - Named Inputs - Receiving interface - - Handle named with `"key"` in configuration - - Source handle of value is not necessary, however it can be specified with `"targets"` -- Named Inputs can receive values from multiple `"targets"` + - Interface named with `"key"` in configuration + - Source interface of value is not necessary, however it can be specified with `"targets"` -- Named Inputs can receive values from multiple `"targets"` The most commonly used of these fixed interfaces are publications and subscriptions. In the [Fundamental Example](../examples/fundamental_examples/fundamental_examples_index.md), the Battery federate and the Charger federate have fixed pub/sub connections. In the figure below, publishing interfaces are in **red** and the subscription interfaces are in **yellow**. The Battery federate **publishes** the current flowing into the battery from the publication interface named `EV_Battery/EV_current` and does not specify the intended recipient. The Charger federate **subscribes** to the amps from the Battery with the subscription interface named `EV_Battery/EV_current` -- the receiving interface only specifies the sender. @@ -95,11 +94,11 @@ Message federates interact with the federation through endpoints interfaces. Mes Endpoints are interfaces used to pass packetized data blocks (messages) to another federate. Message federates interact with the federation by defining an endpoint that acts as their address to send and receive messages. Message federates are typically sending and receiving measurements, control signals, commands, and other signal data with HELICS acting as a perfect communication system (infinite bandwidth, no latency, guaranteed delivery). -In the figure below, Federate A and B are message federates with endpoints epA and epB. They do not have a fixed communication pathway; they have unique addresses (endpoints) to which messages can be sent. An endpoint can send data to any other endpoint in the system -- it just needs the "address" (endpoint handle). +In the figure below, Federate A and B are message federates with endpoints epA and epB. They do not have a fixed communication pathway; they have unique addresses (endpoints) to which messages can be sent. An endpoint can send data to any other endpoint in the system -- it just needs the "address" (endpoint interface). ![](https://github.com/GMLC-TDC/helics_doc_resources/raw/main/user_guide/ep_connection.png) -Endpoints can have a `"type"` which is a user defined string. HELICS currently does not recognize any predefined types. The data consists of raw binary data and optionally a send time. Messages are delivered first by time order, then federate id number, then handle id, then by order of arrival. +Endpoints can have a `"type"` which is a user defined string. HELICS currently does not recognize any predefined types. The data consists of raw binary data and optionally a send time. Messages are delivered first by time order, then federate ID number, then interface ID, then by order of arrival. Unlike HELICS values which are persistent (meaning they are continuously available throughout the co-simulation), HELICS messages are only readable once when collected from an endpoint. Once that collection is made, the message only exists within the memory of the collecting message federate. If another message federate needs the information, a new message must be created and sent to the appropriate endpoint. diff --git a/docs/user-guide/fundamental_topics/filters.md b/docs/user-guide/fundamental_topics/filters.md index f45f4153c9..9ba34206c9 100644 --- a/docs/user-guide/fundamental_topics/filters.md +++ b/docs/user-guide/fundamental_topics/filters.md @@ -19,89 +19,3 @@ The figure below is an example of a representation of the message topology of a - Individual filters can be targeted to act on multiple endpoints and act as both source and destination filters. ![Signal topology using built-in HELICS filters](https://github.com/GMLC-TDC/helics_doc_resources/raw/main/user_guide/messages_and_filters_example.png) - -## Example 1c - EV charge controller with HELICS filters - -To demonstrate the effects of filters, let's take the same model we were working with in the [previous example](./message_federates.md), and add a filter to the controller. Specifically, let's assume a very, very poor communication system and add a 600 second delay to the control messages sent from the EV charge controller to each of the EVs. - -![Ex. 1c signal topology](https://github.com/GMLC-TDC/helics_doc_resources/raw/main/user_guide/Ex1c_Message_topology.png) - -[The JSON configuration file](https://github.com/GMLC-TDC/HELICS/tree/319de2b125fe5e36818f0434ac3d0a82ccc46534/examples/user_guide_examples/Example_1c/EV_Controller/Control.json) adds a new `filter` section that implements the filtering: - -```json -"filters": - [ - { - "name":"filterEV6", - "sourcetarget":"EV_Controller/EV6", - "operation":"delay", - "properties": - { - "name":"delay", - "value":600 - } - }, - { - "name":"filterEV5", - "sourcetarget":"EV_Controller/EV5", - "operation":"delay", - "properties": - { - "name":"delay", - "value":600 - } - }, - ] -``` - -- **`name`** (optional) - Name of the endpoint filter -- **`sourcetarget(s)`** - Name(s) of the endpoints to which this source filter will be applied -- **`desttarget(s)`** - Name(s) of the endpoints to which this destination filter will be applied -- **`operation`** - Defines the type of filtering operation that will be applied to messages. As of v2.0, the supported types are: `delay`, `timedelay`, `randomdelay`, `randomdrop`, `reroute`, `redirect`, `clone`, `cloning`, and `custom`. [Further details on filter types can be found on the configuration reference page](../../references/configuration_options_reference.md). -- **`properties`** - Each filter type has specific parameters that define how it operates. In this case, one of those parameters is the amount each message will be delayed, in seconds. - -Let's run [this co-simulation](https://github.com/GMLC-TDC/HELICS/tree/319de2b125fe5e36818f0434ac3d0a82ccc46534/examples/user_guide_examples/Example_1c/) and capture the same data as last time for direct comparison: total substation load and EV charging behavior, both as a function of time. - -![Ex. 1c total feeder load](https://github.com/GMLC-TDC/helics_doc_resources/raw/main/user_guide/Ex1c_Feeder_consumption.png) - -![Ex. 1c EV charge pattern](https://github.com/GMLC-TDC/helics_doc_resources/raw/main/user_guide/Ex1c_EV_outputs.png) - -Granted that the charge controller communication system is ridiculously poor, this example does show that communication system effects can have a significant impact on system operation. For more realistic example, the HELICS Use Case repository has [an example](https://github.com/GMLC-TDC/HELICS-Use-Cases/tree/main/PNNL-Wide-Area-Control) of frequency control using real-time PMU measurements that shows the impact of imperfect communication systems. - -## Explicit Communication System Modeling - -HELICS filters are a simple, easy step to add a touch of realism to messages in the HELICS co-simulation. The simplicity of filters, though, may be inadequate at times. Real-world communication networks have dynamic delays and data loss rates, protocol effects, and more complex topologies. Sometimes, these effects are important (or may even be the point of the co-simulation) and an explicit communication system model is required to capture these effects. - -The wonderful thing about the software architecture of HELICS is that simulators that have been properly modified to allow HELICS integration will seamlessly slide into the role of filters without having to reconfigure the sending and receiving federates. The move from native HELICS filters to full-blown communication system models is invisible. This is achieved by allowing user-defined nodes in a communication system model to be designated the filter for a given endpoint. All HELICS messages coming from that endpoint enter the communication system federate at that node and message being sent to that endpoint exit the communication system federate at that node. Conceptually, the change looks something like the figure below: - -![Replacing native HELICS filters with explicit communication network simulator](https://github.com/GMLC-TDC/helics_doc_resources/raw/main/user_guide/filter_federate_example.png) - -### Example 1d - EV charge controller with an ns-3 model - -For this co-simulation, we're going to use [ns-3](https://www.nsnam.org) as our communication system model. Like many other detailed simulators, ns-3 is a complicated simulator, more complicated than can easily be explained in any detail here. If you're so interested, the [ns-3 tutorial](https://www.nsnam.org/docs/release/3.29/tutorial/html/index.html) is excellent and is the best place to start to understand how it is used to model and simulate communication systems. For those not wanting to dig into that, here's the three sentence version: ns-3 models the communication system topology as a collection of nodes and communication channels connecting them. Depending on the type of channel used, various properties (e.g. delay) can be assigned to them. On top of this network, various protocols can be assigned to build up the protocol stack with applications at the top of the stack. - -When using HELICS and ns-3 together, the application that is installed is the bridge between the communication network and the rest of the HELICS federation. For each endpoint that is modeled in the communication network, a HELICS filter ns-3 application is installed at a corresponding node in the ns-3 model. - -The specific ns-3 model built for this example uses the CSMA model built into ns-3 as a stand-in for a power-line carrier (PLC) communication system. Both CSMA and PLC use a bus topology with all transmitters attached to a common, shared communication channel. Each EV in the electrical network will be represented by a corresponding communication node. Older PLC implementations were known to be quite slow and we'll abuse and stretch this fact to force the average of the communication delays through the network to match that of the previous example. We'll also set the receiver at the substation to have a corresponding receive error rate. - -First, you'll need to install [ns-3](https://www.nsnam.org/docs/release/3.29/tutorial/html/getting-started.html#downloading-ns-3-using-git) and add the [HELICS module](https://github.com/GMLC-TDC/helics-ns3). As the README indicates, HELICS for ns-3 is an extension that is simply plopped into the standard ns-3 distribution `contrib` folder and the configured with a few extra switches and compiled. - -**EXAMPLE USING NS-3 AND HELICS IS UNDER DEVELOPMENT** - - diff --git a/docs/user-guide/fundamental_topics/fundamental_topics_index.md b/docs/user-guide/fundamental_topics/fundamental_topics_index.md index aa97952256..ad201a4ddb 100644 --- a/docs/user-guide/fundamental_topics/fundamental_topics_index.md +++ b/docs/user-guide/fundamental_topics/fundamental_topics_index.md @@ -12,7 +12,6 @@ stages logging helics_run - web_interface simulator_integration @@ -27,7 +26,6 @@ The topics considered "fundamental" to building a co-simualtion with HELICS are: - [Value Federates](./value_federates.md) - [Message Federates](./message_federates.md) - [Filters](./filters.md) - - [Value Types](./value_types.md) - [**Federate Interface Configuration**](./interface_configuration.md) - How to connect an existing simulator with HELICS - [**With JSON config file**](./interface_configuration.md#json-configuration) - [**With HELICS APIs**](./interface_configuration.md#api-configuration) @@ -37,5 +35,4 @@ The topics considered "fundamental" to building a co-simualtion with HELICS are: - [**Stages of the Co-simulation**](./stages.md) - [**Logging**](./logging.md) - Discussion of logging within HELICS and how to control it. - [**Execution with `helics run ...`**](./helics_run.md) - The HELICS team has developed a standardized means of running HELICS co-simulations. -- [**Simulation Management**](./web_interface.md) - Using the webserver, HELICS also has a built-in web interface for running, monitoring, and diagnosing co-simulations. - [**Simulator Integration**](./simulator_integration.md) - A guide for integrating HELICS into simulators. diff --git a/docs/user-guide/fundamental_topics/helics_terminology.md b/docs/user-guide/fundamental_topics/helics_terminology.md index 493d7af822..098933eafd 100644 --- a/docs/user-guide/fundamental_topics/helics_terminology.md +++ b/docs/user-guide/fundamental_topics/helics_terminology.md @@ -2,16 +2,46 @@ Before digging into the specifics of how a HELICS co-simulation runs, there are a number of key terms and concepts that need to be clarified first. -- **Simulator** - A simulator is the executable that is able to perform some analysis function, often but not always, by solving specific problems to generate a time series of values. Simulators are abstract in the sense that it largely refers to the software in a non-executing state, outside of the co-simulation. We might say things like, "That simulator doesn't model xyz appropriately for this analysis." or "This simulator has been parallelized and runs incredibly quickly on many-core computers." Any time we are talking about a specific instance of a simulator running a specific model you are really talking about a... +![Relational diagram for key HELICS concepts](https://github.com/GMLC-TDC/helics_doc_resources/raw/main/user_guide/HELICS_terminology.png) -- **Federate** - Federates are the running instances of simulators that have been assigned specific models and/or have specific values they are providing to and receiving from other federates. For example, we can have ten distribution circuit models that we are connecting for a co-simulation. Each could be run by the simulator GridLAB-D, and when they are running, they become ten unique federates providing unique values to each other. A collection of federates working together in a co-simulation is called a "federation." +**Simulator** - A simulator is the executable that is able to perform some analysis function, often but not always, by solving specific problems to generate a time series of values. -- **Model** - A model is synonymous with an agent in the co-simulation. A simulator contains the calculations for the model. Depending on the needs of the co-simulation, a federate can be configured to contain one or many models. For example, if we want to create a co-simulation of electric vehicles, we may write a simulator (executable program) to model the physics of the electric vehicle battery. We can then designate any number of agents/models of this battery by configuring the transfer of signals between the "Battery Federate" (which has _N_ batteries modeled) and another federate. +- Simulators are abstract in the sense that it largely refers to the software in a non-executing state, outside of the co-simulation. We might say things like, "That simulator doesn't have feature xyz." or "This simulator has been parallelized and runs incredibly quickly on many-core computers." +- Any time we are talking about a specific instance of a simulator running a specific model you are really talking about a federate. + - Simulators, on their own, do not have the ability to join a HELICS co-simulation but can still have a model associated them. -- **Signals** - Signals are the the information passed between federates during the execution of the co-simulation. Fundamentally, co-simulation is about message-passing via these signals. HELICS divides these messages into two types: value signals and message signal. The former is used when coupling two federates that share physics (_e.g._ batteries providing power to wheel motors on an electric car) and the later is used to couple two federates with information (_e.g._ a battery charge controller and a charge relay on a battery). There are various techniques and implementations of the message-passing infrastructure that have been implemented in the core. There are also a variety of mechanisms within a co-simulation to define the nature of the data being exchanged (data type, for example) and how the data is distributed around the federation. +**Federate** - Federates are the running instances of simulators that have been assigned specific models and/or have specific values they are providing to and receiving from other federates. -- **Interface** - A structure by which a federate can communicate with other federates. Includes Endpoints, Publications, and Inputs. +- For example, we can have ten distribution circuit models that we are connecting for a co-simulation. Each could be run by the simulator GridLAB-D, and when they are running, they become ten unique federates providing unique values to each other. +- A collection of federates working together in a co-simulation is called a "federation." + - Additional documentation can be found in [this tutorial's page on federates](./federates.md). -- **Core** - The core is the software that has been embedded inside a simulator to allow it to join a HELICS federation. In general, each federate has a single core, making the two synonymous (core <=> federate). The two most common configurations are: (1) one core, one federate, one model; (2) one core, one federate, multiple models. There are sometimes cases where a single executable is used to represent multiple federates and all of those federates use a single core (one core, multiple federates, multiple models). Cores are built around specific message buses with HELICS supporting a number of different bus types. Selection of the message bus is part of the configuration process required to form the federation. Additional information about cores can be found in the [Advanced Topics](../advanced_topics/CoreTypes.md). +**Model** - A model is the representation of some portion of reality being managed by a federate. -- **Broker** - The broker is a special executable distributed with HELICS; it is responsible for performing the two key tasks of a co-simulation: (1) maintaining synchronization in the federation and (2) facilitating message exchange. Each core (federate) must connect to a broker to be part of the federation. Brokers receive and distribute messages from any federates that are connected to it, routing them to the appropriate location. HELICS also supports a hierarchy of brokers, allowing brokers to pass messages between each other to connect federates associated with different brokers and thus maintain the integrity of the federation. The broker at the top of the hierarchy is called the "root broker" and it is the message router of last resort. +- A simulator contains the calculations for the model. +- Depending on the needs of the co-simulation, a federate can be configured to contain one or many models. +- For example, if we want to create a co-simulation of electric vehicles, we may write a simulator (executable program) to model the physics of the electric vehicle battery. We can then designate any number of agents/models of this battery by configuring the transfer of signals between the "Battery Federate" (which has _N_ batteries modeled) and another federate. + +**Signals** - Signals are the the information passed between federates during the execution of the co-simulation. Fundamentally, co-simulation is about message-passing via these signals. + +- We can notionally think of federates talking directly to each other by passing signals back and forth. Under the hood, the path the data takes is through the core and then broker. +- HELICS divides these messages into two types: value signals and message signal. The former is used when coupling two federates that share physics (_e.g._ batteries providing power to wheel motors on an electric car) and the later is used to couple two federates with information (_e.g._ a battery charge controller and a charge relay on a battery). +- There are also a variety of mechanisms within a co-simulation to define the nature of the data being exchanged (data type, for example) and how the data is distributed around the federation. + +**Interface** - An object by which a federate pass signals to each other. + +- Includes Endpoints, Publications, and Inputs. +- Additional documentation on interfaces can be found in [this tutorial's page on federates](./federates.md). + +**Core** - The core is the software that has been embedded inside a simulator to allow it to join a HELICS federation. Simulators without a core are not HELICS federates. + +- In general, each federate has a single core, making the two synonymous (core <=> federate). +- The two most common configurations are: (1) one core, one federate, one model; (2) one core, one federate, multiple models. +- There are sometimes cases where a single executable is used to represent multiple federates and all of those federates use a single core (one core, multiple federates, multiple models). +- Cores are built around specific messaging protocols with HELICS supporting a number of different protocols (_e.g._ ZMQ, TCP, MPI). Selection of the messaging protocol is part of the configuration process required to form the federation. Additional information about cores can be found in the [Advanced Topics](../advanced_topics/CoreTypes.md). + +**Broker** - The broker is a special executable distributed with HELICS; it is responsible for facilitating signal passing between federates. + +- Each core (federate) must connect to a broker to be part of the federation. +- Brokers receive and distribute messages from any federates that are connected to it, routing them to the appropriate location. +- HELICS also supports a hierarchy of brokers, allowing brokers to pass messages between each other to connect federates associated with different brokers and thus maintain the integrity of the federation. The broker at the top of the hierarchy is called the "root broker" and it is the message router of last resort. [Additional information about broker hierarchies can be found here](../advanced_topics/broker_hierarchies.md). diff --git a/docs/user-guide/fundamental_topics/interface_configuration.md b/docs/user-guide/fundamental_topics/interface_configuration.md index 93a87f6903..a674bab881 100644 --- a/docs/user-guide/fundamental_topics/interface_configuration.md +++ b/docs/user-guide/fundamental_topics/interface_configuration.md @@ -6,7 +6,7 @@ As soon as one particular instance of a simulator begins running in a co-simulat **Core type** - The core manages interfaces between the federation and the federate; there are several messaging technologies supported by HELICS. -**Publications and Inputs** - Publication configuration contains a listing of source handle, data types, and units being sent by the federate; input configuration does the same for values being received by the federate. If supported by the simulator (e.g., [a Python simulator](../examples/fundamental_examples/fundamental_default.md)), these values can be mapped to internal variables of the simulator from the configuration file. +**Publications and Inputs** - Publication configuration contains a listing of source interface, data types, and units being sent by the federate; input configuration does the same for values being received by the federate. If supported by the simulator (e.g., [a Python simulator](../examples/fundamental_examples/fundamental_default.md)), these values can be mapped to internal variables of the simulator from the configuration file. **Endpoints** - Endpoints are sending and receiving points for HELICS messages to and from message federates. They are declared and defined for each federate. @@ -97,13 +97,13 @@ Below is a sample JSON configuration file with some of the more common options. - **`uninterruptible`** - Setting `uninterruptible` to `false` allows the federate to be interrupted if there is a signal available for it to receive. This is a [timing configuration](./timing_configuration.md) option. - **`terminate_on_error`** - By default, HELICS will not terminate execution of every participating federate if an error occurs in one. However, in most cases, if such an error occurs, the cosimulation is no longer valid. Setting `terminate_on_error` frees the federate from the broker if there is an error in execution, which simplifies debugging. This will prevent your federate from hanging in the event that another federate fails. - **`wait_for_current_time_update`** - There are times when HELICS will grant the same simulated time to a number of federates simultaneously. There is a possibility of this leading to unexpected co-simulation results if federates are unexpectedly operating on old data. Using this flag, HELICS uses this option to provide the ability for one federate to always be granted this time last, after all other federates that have been granted this time have requested a later time. This ensures that the federate with this flag set will have all the latest information from all other federates before it begins execution at the granted time. -- **`federate_init_string`** - This option provides a way of passing in a large number of configuration options that a federate needs during initialization. You can consult the [Configuration Options Reference](../../references/configuration_options_reference.md#broker-init-string-brokerinitstring-brokerinitstring) page for a more complete list but there are a few worth bringing up specifically. `--broker_address=` and `--port=`- Allows you to specify the IP address and port number of the broker to which you want this federate to connect. You can consult the [Advanced Topics section of the User Guide](../advanced_topics/advanced_topics_index.md) to see further explanation of how to handle more complex broker configuration. +- **`federate_init_string`** - This option provides a way of passing in a large number of configuration options that a federate needs during initialization. You can consult the [Configuration Options Reference](../../references/configuration_options_reference.md#broker_init_string--null) page for a more complete list but there are a few worth bringing up specifically. `--broker_address=` and `--port=`- Allows you to specify the IP address and port number of the broker to which you want this federate to connect. You can consult the [Advanced Topics section of the User Guide](../advanced_topics/advanced_topics_index.md) to see further explanation of how to handle more complex broker configuration. - **`endpoints`** - - `name` - The string in this field is the unique identifier/handle for the endpoint interface. + - `name` - The string in this field is the unique identifier for the endpoint interface. - `destination` - This option can be used to set a default destination for the messages sent from this endpoint. The default destination is allowed to be rerouted or changed during run time. - `global` - Just as in value federates, `global` allows for the identifier of the endpoint to be declared unique for the entire federation. - **`publications`** - - `key` - The string in this field is the unique identifier/handle (at the federate level) for the value that will be published to the federation. In the example above, `global` is set to `true`, meaning the `key` must be unique to the entire federation. + - `key` - The string in this field is the unique identifier (at the federate level) for the value that will be published to the federation. In the example above, `global` is set to `true`, meaning the `key` must be unique to the entire federation. - `global` - Indicates that the value in `key` will be used as a global name when other federates are subscribing to the message. This requires that the user ensure that the name is used only once across all federates. Setting `global` to `true` is handy for federations with a small number of federates and a small number of message exchanges as it allows the `key` string to be short and simple. For larger federations, it is likely to be easier to set the flag to `false`. - `required` - At least one federate must subscribe to the publications. - `type` - Data type, such as integer, double, complex. @@ -134,7 +134,7 @@ Below is a sample JSON configuration file with some of the more common options. ## API Configuration -Configuring the federate interface with the API is done internal to a user-written simulator. The specific API used will depend on the language the simulator is written in. Native APIs for HELICS are available in [C++](../../doxygen/index.md) and [C](../../references/api-reference/C_API.md). MATLAB, Java, Julia, Nim, and Python all support the C API calls (ex: `helicsFederateEnterExecutionMode()`). Python and Julia also have native APIs (see: [Python (PyHELICS)](https://python.helics.org/api/), [Julia](https://gmlc-tdc.github.io/HELICS.jl/latest/api/)) that wrap the C APIs to better support the conventions of their languages. The [API References](../../references/api-reference/index.md) page contains links to the APIs. +Configuring the federate interface with the API is done internal to a user-written simulator. The specific API used will depend on the language the simulator is written in. Native APIs for HELICS are available in [C++](../../references/api-reference/CPP.md) and [C](../../references/api-reference/C_API.md). MATLAB, Java, Julia, Nim, and Python all support the C API calls (ex: `helicsFederateEnterExecutionMode()`). Python and Julia also have native APIs (see: [Python (PyHELICS)](https://python.helics.org/api/), [Julia](https://gmlc-tdc.github.io/HELICS.jl/latest/api/)) that wrap the C APIs to better support the conventions of their languages. The [API References](../../references/api-reference/index.md) page contains links to the APIs. The [Examples](../examples/examples_index.md) in this User Guide are written in Python -- the following federate interface configuration guidance will use the [PyHELICS](https://python.helics.org/api/) API, but can easily be adapted to other C-based HELICS APIs. diff --git a/docs/user-guide/fundamental_topics/logging.md b/docs/user-guide/fundamental_topics/logging.md index ae27ad006a..0bfe76658a 100644 --- a/docs/user-guide/fundamental_topics/logging.md +++ b/docs/user-guide/fundamental_topics/logging.md @@ -5,7 +5,7 @@ Logging in HELICS provides a way to understand the operation of a federate and i - [Log Levels](#log-levels) - [Setting up the Simulator for Logging](#setting-up-the-simulator-for-logging) - [Setting up the Federate for Logging](#setting-up-the-federate-for-logging) -- [Setting up the Core/Broker for Logging](#setting-up-the-core-broker-for-logging) +- [Setting up the Core/Broker for Logging](#setting-up-the-core-or-broker-for-logging) ## Log Levels @@ -120,7 +120,7 @@ Or with the API interface functions for each federate: h.helicsFederateInfoSetIntegerProperty(fed, h.HELICS_PROPERTY_INT_LOG_LEVEL, 1) ``` -## Setting up the Core/Broker for Logging +## Setting up the Core or Broker for Logging It is possible to specify a log file to use on a core. This can be specified through the coreinit string `--logfile logfile.txt` diff --git a/docs/user-guide/fundamental_topics/message_federates.md b/docs/user-guide/fundamental_topics/message_federates.md index 57add71646..706d5107cb 100644 --- a/docs/user-guide/fundamental_topics/message_federates.md +++ b/docs/user-guide/fundamental_topics/message_federates.md @@ -23,184 +23,3 @@ Consider a counter-example: automated meter-reading (AMI) using a wireless netwo Though it is not possible to have a HELICS message show up at a value interface, the converse is possible; message_federates can subscribe to HELICS values. Every time a value federate publishes a new value to the federation, if a message federate has subscribed to that message HELICS will generate a new HELICS message and send it directly to the destination endpoint. These messages are queued and not overwritten (unlike in HELICS values) which means when a message federate is synchronized it may have multiple messages from the same source to manage. This feature offers the convenience of allowing a message federate to receive messages from pure value federates that have no endpoints defined. This is particularly useful for simulators that do not support endpoints but are required to provide measurement signals controllers. Implemented in this way, though, it is not possible to later implement a full-blown communication simulator that these values-turned-messages can traverse. Such co-simulation architectures in HELICS require the existence of both a sending and receiving endpoint; this feature very explicitly by-passes the need for a sending endpoint. - -## Message Federate Configuration in JSON - -Once the message topology considering endpoints has been determined, the definitions of these endpoints in the JSON file is straight-forward. Here's what it could look like for the voltage regulator example from above. - -```json -{ - "endpoints": [ - { - "name": "voltage_sensor", - "global": true, - "destination": "voltage_controller", - "info": "" - }, - { - "name": "voltage_controller_1", - "global": true, - "info": "" - }, - { - "name": "voltage_controller_2", - "global": true, - "destination": "voltage_actuator", - "info": "" - }, - { - "name": "voltage_actuator", - "global": true, - "info": "" - } - ] -} -``` - -- **`name`** - Analogous to `key` in value federates, this is the unique identifier of the endpoint in the federation and has the same interaction with `global` as the value federates do. -- **`global`** - Just as in value federates, `global` allows for the identifier of the endpoint to be declared unique for the entire federation. -- **`destination`** - For endpoints that send all outgoing messages to only a single endpoint, `destination` allows the endpoint to be specified in the JSON configuration. This allows for a more modular implementation of the federate since this parameter is externally defined rather than being hardcoded in the federate itself. -- **`info`** - Just as in the value federate, the string in this field is ignored by HELICS and can be used by the federate for internal configuration purposes. - -## Example 1b - Distribution system EV charge controller - -To demonstrate how a message federate interacts with the federation, let's take the previous example and add two things to it: electric vehicle (EV) loads in the distribution system, and a centralized EV charge control manager. - -Keeping in mind that this a model for demonstration purposes (which is to say, don't take this too seriously), let's make the following assumptions and definitions to simplify the behavior of the EV charge controller: - -- All EVs are very large (200kW; level 2 charging is rated up to 20kW) -- All EVs have infinite battery capacity -- All EVs will be at home all day, desiring to charge all day if they can. -- All EVs charge at the same power level. -- The EV charge controller has direct control over the charging of all EVs in the distribution system. It can tell them when to turn off and on at will. -- The EV charge controller has the responsibility to limit the total load of the distribution system to a specified level to prevent overloading on the substation transformer. -- The EV will turn off some EV charging when the total distribution load exceeds the transformer limit by a certain percentage and will turn some EVs back on when below the limit by a certain percentage. -- Nothing is fair about how the charge controller chooses which EVs to charge and which to disconnect. - -The message topology (including the endpoints) and the not very interesting broker topology are shown below. - -![Ex. 1b signal topology](https://github.com/GMLC-TDC/helics_doc_resources/raw/main/user_guide/Ex1b_Message_topology.png) - -![Ex. 1b broker topology](https://github.com/GMLC-TDC/helics_doc_resources/raw/main/user_guide/Ex1b_Broker_topology.png) - -Taking these assumptions and specifications, it is not too difficult to write a simple charge controller as a Python script. And just by opening the [JSON configuration file](https://github.com/GMLC-TDC/HELICS/tree/319de2b125fe5e36818f0434ac3d0a82ccc46534/examples/user_guide_examples/Example_1b/EV_Controller/Control.json) we can learn important details about how the controller works. - -```json -{ - "name": "EV_Controller", - "loglevel": 5, - "coreType": "zmq", - "timeDelta": 1.0, - "uninterruptible": true, - - "endpoints": [ - { - "name": "EV_Controller/EV6", - "destination": "IEEE_123_feeder_0/EV6", - "type": "genmessage", - "global": true - }, - { - "name": "EV_Controller/EV5", - "destination": "IEEE_123_feeder_0/EV5", - "type": "genmessage", - "global": true - } - ], - "subscriptions": [ - { - "key": "IEEE_123_feeder_0/totalLoad", - "type": "complex", - "required": true - }, - { - "key": "IEEE_123_feeder_0/charge_EV6", - "type": "complex", - "required": true - }, - { - "key": "IEEE_123_feeder_0/charge_EV5", - "type": "complex", - "required": true - } - ] -} -``` - -The first thing to note is the the EV controller has been written as a combination federate, having both endpoints for receiving/sending messages and subscriptions to HELICS values. The HELICS values that the controller has subscribed to give the controller access to both the total load of the feeder (`totalLoad`, presumably) as well as the charging power for each of the individual EVs being controlled (six in total). - -Looking at the [GridLAB-D JSON configuration file](https://github.com/GMLC-TDC/HELICS/tree/319de2b125fe5e36818f0434ac3d0a82ccc46534/examples/user_guide_examples/Example_1b/Distribution/IEEE_123_feeder_0.json) confirms this: - -```json -{ - "name" : "DistributionSim", - "loglevel": 5, - "coreType": "zmq", - "period" : 1.0, - "publications" : [ - { - "global" : true, - "key" : "IEEE_123_feeder_0/totalLoad", - "type" : "complex", - "unit" : "VA", - "info" : "{ - \"object\" : \"network_node\", - \"property\" : \"distribution_load\" - }" - }, - { - "global" : true, - "key" : "IEEE_123_feeder_0/charge_EV6", - "type" : "complex", - "unit" : "VA", - "info" : "{ - \"object\" : \"EV6\", - \"property\" : \"constant_power_A\" - }" - }, - { - "global" : true, - "key" : "IEEE_123_feeder_0/charge_EV5", - "type" : "complex", - "unit" : "VA", - "info" : "{ - \"object\" : \"EV5\", - \"property\" : \"constant_power_B\" - }" - } - ], - "endpoints" : [ - { - "global" : true, - "name" : "IEEE_123_feeder_0/EV6", - "type" : "complex", - "info" : "{ - \"object\" : \"EV6\", - \"property\" : \"constant_power_A\" - }" - }, - { - "global" : true, - "name" : "IEEE_123_feeder_0/EV5", - "type" : "complex", - "info" : "{ - \"object\" : \"EV5\", - \"property\" : \"constant_power_B\" - }" - } - ] -} - -``` - -GridLAB-D is publishing out the total load on the feeder as well as the individual EV charging loads. It also has endpoints set up for each of the EV chargers to receive messages from the controller. Based on the strings in the `info` field it appears that the received messages are used to define the EV charge power. - -Running [the example](https://github.com/GMLC-TDC/HELICS/tree/319de2b125fe5e36818f0434ac3d0a82ccc46534/examples/user_guide_examples/Example_1b/) and looking at the results, as the total load on the feeder exceeded the pre-defined maximum loading of the feeder (red line in the graph), the EV controller disconnected an additional EV load. Conversely, as the load dipped to the lower limit (green line), the controller reconnected the EV load. Looking at a graph of the EV charge power for each EV shows the timing of the EV charging for each load. - -![Ex. 1b total feeder load](https://github.com/GMLC-TDC/helics_doc_resources/raw/main/user_guide/Ex1b_Feeder_consumption.png) - -![Ex. 1b EV charge pattern](https://github.com/GMLC-TDC/helics_doc_resources/raw/main/user_guide/Ex1b_EV_outputs.png) - -Given the relatively dramatic changes in load, you might expect the voltage on the transmission system to be impacted. You would be right: - -![Ex. 1b transmission system voltage magnitude](https://github.com/GMLC-TDC/helics_doc_resources/raw/main/user_guide/Ex1b_Bus_voltage_118.png) diff --git a/docs/user-guide/fundamental_topics/simulator_integration.md b/docs/user-guide/fundamental_topics/simulator_integration.md index 265eb06d7d..16bbf0c79d 100644 --- a/docs/user-guide/fundamental_topics/simulator_integration.md +++ b/docs/user-guide/fundamental_topics/simulator_integration.md @@ -1,16 +1,18 @@ +# Simulator Integration + A "simulator" is the executable program. As soon as one particular instance of that simulator begins running in a co-simulation it is considered a "federate". Every federate (instance of a simulator) will require configuration of the way it will communicate (send signals) to other federates in the federation. For simulators that already have HELICS support, the configuration takes the form of a JSON (or TOML) file; bespoke simulators can be configured with the HELICS APIs in the code or via a JSON file. The essential information that HELICS configuration defines is: **Federate name** - The unique name this federate will be known as throughout the federation. It is essential this name is unique so that HELICS messages can route properly. **Core type** - The core manages interfaces between the federation and the federate; there are several messaging technologies supported by HELICS. -**Publications and Inputs** - Publication configuration contains a listing of source handle, data types, and units being sent by the federate; input configuration does the same for values being received by the federate. If supported by the simulator (e.g., [a Python simulator](../examples/fundamental_examples/fundamental_default.md)), these values can be mapped to internal variables of the simulator from the configuration file. +**Publications and Inputs** - Publication configuration contains a listing of source interface name, data types, and units being sent by the federate; input configuration does the same for values being received by the federate. If supported by the simulator (e.g., [a Python simulator](../examples/fundamental_examples/fundamental_default.md)), these values can be mapped to internal variables of the simulator from the configuration file. **Endpoints** - Endpoints are sending and receiving points for HELICS messages to and from message federates. They are declared and defined for each federate. **Time step size** - This value defines the resolution of the simulator to prevent HELICS from telling the simulator to step to a time of which it has no concept (e.g. trying to simulate the time of 1.5 seconds when the simulator has a resolution of one second). -# Integration of Federates +## Integration of Federates A co-simulation is, in some sense, a simulation of simulations. There will be two types of configuration required: @@ -39,7 +41,7 @@ The figure below shows the most common architecture for HELICS co-simulation. Ea ## Configuring the federate -Let's look at a generic JSON configuration file as an example with the more common parameters shown. As we'll see [later in this section](#Using-a-config-file), this file is loaded by the federate using a specific API, allowing the same simulator to be used to create many federates that are all unique without having the modify the source code of the simulator. There are many, many more configuration parameters that this file could include; a relatively comprehensive list along with explanations of the functionality they provide can be found in the [federate configuration](../../references/configuration_options_reference.md) guide. +Let's look at a generic JSON configuration file as an example with the more common parameters shown. As we'll see [later in this section](#using-a-config-file), this file is loaded by the federate using a specific API, allowing the same simulator to be used to create many federates that are all unique without having the modify the source code of the simulator. There are many, many more configuration parameters that this file could include; a relatively comprehensive list along with explanations of the functionality they provide can be found in the [federate configuration](../../references/configuration_options_reference.md) guide. ### Sample federate JSON configuration file @@ -207,7 +209,7 @@ pub = h.helicsFederateGetPublicationByIndex(fed, index) pub_key = h.helicsPublicationGetKey(pub) ``` -The object returned when the helicsFederateGetPublicationByIndex() method is invoked is the handle used for retrieving other publication metadata (as in the helicsPublicationGetKey() method) and when publishing data to HELICS (as described in the execution section below). +The object returned when the helicsFederateGetPublicationByIndex() method is invoked is the interface object used for retrieving other publication metadata (as in the helicsPublicationGetKey() method) and when publishing data to HELICS (as described in the execution section below). ### Federate Execution diff --git a/docs/user-guide/fundamental_topics/stages.md b/docs/user-guide/fundamental_topics/stages.md index 5917b3f94f..799c822f54 100644 --- a/docs/user-guide/fundamental_topics/stages.md +++ b/docs/user-guide/fundamental_topics/stages.md @@ -112,7 +112,7 @@ pub = h.helicsFederateGetPublicationByIndex(fed, index) pub_key = h.helicsPublicationGetKey(pub) ``` -The object returned when the helicsFederateGetPublicationByIndex() method is invoked is the handle used for retrieving other publication metadata (as in the helicsPublicationGetKey() method) and when publishing data to HELICS (as described in the execution section below). +The object returned when the helicsFederateGetPublicationByIndex() method is invoked is the interface object used for retrieving other publication metadata (as in the helicsPublicationGetKey() method) and when publishing data to HELICS (as described in the execution section below). ## Initialization diff --git a/docs/user-guide/fundamental_topics/value_federates.md b/docs/user-guide/fundamental_topics/value_federates.md index 704bae841a..aedcb14cfb 100644 --- a/docs/user-guide/fundamental_topics/value_federates.md +++ b/docs/user-guide/fundamental_topics/value_federates.md @@ -19,142 +19,3 @@ The message type used for a given federation configuration is often an expressio - **Is portability of the federate and its configuration important?** - Because "publications" and "named inputs" don't require the federate to know who it is sending HELICS messages to and receiving HELICS messages from as part of the federate configuration, it affords a slightly higher degree of portability between different federations. The mapping of HELICS messages still needs to be done to configure a federation, its just done separately from the federate configuration file via a broker or core configuration file. The difference in location of this mapping may offer some configuration efficiencies in some circumstances. Though all four message types are supported, the remainder of this guide will focus on publications and subscriptions as they are conceptually easily understood and can be comprehensively configured through the individual federate configuration files. - -## Federate Configuration Options via JSON - -For any simulator that you didn't write for yourself, the most common way of configuring that simulator for use in a HELICS co-simulation will be through the use of an external JSON configuration file. TOML files are also supported but we will concentrate on JSON for this discussion. This file is read when a federate is being created and initialized and it will provide all the necessary information to incorporate that federate into the co-simulation. - -As the fundamental role of the co-simulation platform is to manage the synchronization and data exchange between the federates, you may or may not be surprised to learn that there are generic configuration options available to all HELICS federates that deal precisely with these. In this section, we'll focus on the options related to data exchange as pertaining to value federates, those options and in [Timing section](timing_configuration.md) we'll look at the timing parameters. - -Let's look at a generic JSON configuration file as an example with the more common parameters shown; the default values are shown in "[ ]". (Further parameters and explanations can be found in the [federate configuration](../../references/configuration_options_reference.md) guide. - -### General Configuration Parameter - -(xxxxxxx figure out what needs to be in here now that we have the Configuration Options Reference page) - -Though contained here in this section on value federates, the options below are applicable to both value and message federates. As value federates are the more common type, we've put them here. - -```json -{ - "name": "generic_federate", - "coreType": "zmq" -} -``` - -- **`name`** - Every federate must have a unique name across the entire federation; this is functionally the address of the federate and is used to determine where HELICS messages are sent. An error will be generated if the federate name is not unique. -- **`coreType` [zmq]** - There are a number of technologies or message buses that can be used to send HELICS messages among federates. Every HELICS enabled simulator has code in it that creates a core which connects to a HELICS broker using one of these messaging technologies. ZeroMQ (zmq) is the default core type and most commonly used but there are also cores that use TCP and UDP networking protocols directly (forgoing ZMQ's guarantee of delivery and reconnection functions), IPC (uses Boost's interprocess communication for fast in-memory message-passing but only works if all federates are running on the same physical computer), and MPI (for use on HPC clusters where MPI is installed). - -### Value Federate Interface Configuration - -```json -{ - "publications" : [ - { - "key" : "IEEE_123_feeder_0/totalLoad", - "global" : true, - "type" : "complex", - "unit" : "VA", - "info" : "{ - \"object\" : \"network_node\", - \"property\" : \"distribution_load\" - }" - } - ], - "subscriptions" : [ - { - "required": true, - "key" : "TransmissionSim/transmission_voltage", - "type" : "complex", - "unit" : "V", - "info" : "{ - \"object\" : \"network_node\", - \"property\" : \"positive_sequence_voltage\" - }" - } - ] -} -``` - -- **`publications` and/or `subscriptions`** - These are lists of the values being sent to and from the given federate. -- **`key`** - - - `publications` - The string in this field is the unique identifier (at the federate level) for the value that will be published to the federation. If `global` is set (see below) it must be unique to the entire federation. - - `subscriptions` - This string identifies the federation-unique value that this federate wishes to receive. Unless `global` has been set to `true` in the publishings JSON configuration file, the name of the value is formatted as `/`. Both of these strings can be found in the publishing federate's JSON configuration file as the `name` and `key` strings, respectively. If `global` is `true` the string is just the `key` value. -- **`global` [false]** - (publications only) `global` is used to indicate that the value in `key` will be used as a global name when other federates are subscribing to the message. This requires that the user ensure that the name is used only once across all federates. Setting `global` to `true` is handy for federations with a small number of federates and a small number of message exchanges as it allows the `key` string to be short and simple. For larger federations, it is likely to be easier to set the flag to `false` and accept the extra naming -- **`required` [false]** - - - `publications` - At least one federate must subscribe to the publications. - - `subscriptions` - The message being subscribed to must be provided by some other publisher in the federation. -- **`type`** - HELICS supports data types and data type conversion ([as best it can](https://www.youtube.com/watch?v=mZOAn-3aATY)). -- **`units`** - HELICS is able to do some levels of unit conversion, currently only on double type publications but more may be added in the future. The units can be any sort of unit string, a wide assortment is supported and can be compound units such as m/s^2 and the conversion will convert as long as things are convertible. The unit match is also checked for other types and an error if mismatching units are detected. A warning is also generated if the units are not understood and not matching. The unit checking and conversion is only active if both the publication and subscription specify units. -- **`info`** - The `info` field is entirely ignored by HELICS and is used as a mechanism to pass configuration information to the federate so that it can properly integrate into the federation. Thus, there is no standard content or format for this field; it is entirely up to the individual simulators to decide how the data in this field (if any) should be used. Often it is used by simulators to map the HELICS names into internal variable names as shown in the above example. In this case, the object `network_node` has a property called `positive_sequence_voltage` that will be updated with the value from the subscription `TransmissionSim/transmission_voltage`. - -## Example 1a - Basic transmission and distribution powerflow - -To demonstrate how a to build a co-simulation, an example of a simple integrated transmission system and distribution system powerflow can be built; all the necessary files are found [HERE](https://github.com/GMLC-TDC/HELICS/tree/helics3/examples/user_guide_examples/Example_1a) but to use them you'll need to get some specific software installed; here are the instructions: - -1. [HELICS](../installation/index.md) -2. [GridLAB-D](https://github.com/gridlab-d/gridlab-d/tree/develop) - Enable HELICS, see instructions [here](http://gridlab-d.shoutwiki.com/wiki/Connection:helics_msg) -3. [Python](https://www.anaconda.com/download/) - Anaconda installation, if you don't already have Python installed. You may need to also install the following Python packages (`conda install` ...) - - matplotlib - - time - - logging -4. [PyPower](https://pypi.org/project/PYPOWER/) - `pip install pypower` - -This example has a very simple message topology (with only one message being sent by either federate at each time step) and uses only a single broker. Diagrams of the message and broker topology can be found below: - -![Ex. 1a message topology](https://github.com/GMLC-TDC/helics_doc_resources/raw/main/user_guide/Ex1a_Message_topology.png) - -![Ex. 1a broker topology](https://github.com/GMLC-TDC/helics_doc_resources/raw/main/user_guide/Ex1a_Broker_topology.png) - -- **Transmission system** - The transmission system model used is the IEEE-118 bus model. To a single bus in this model the GridLAB-D distribution system is attached. All other load buses in the model use a static load shape scaled proportionately so the peak of the load shape matches meet the model-defined load value. The generators are re-dispatched every fifteen minutes by running an optimal power flow (the so-called "ACOPF" which places constraints on the voltage at the nodes in the system) and every five minutes a powerflow is run the update the state of the system. To allow for the relatively modest size of the single distribution system attached to the transmission system, the distribution system load is amplified by a factor of fifteen before being applied to the transmission system. - -- **Distribution system** - A GridLAB-D model of the IEEE-123 node distribution system has been used. The model includes voltage regulators along the primary side of the system and includes secondary (or distribution) transformers with loads attached to the secondary of these transformers. The loads themselves are ZIP loads with a high impedance traction that are randomly scaled versions of the same time-varying load-shapes. - -In this particular case, the Python script executing the transmission model also creates the broker; this is a choice of convenience and could have been created by any other federates. This simulation is run for 24 hours. - -### Running co-simulations via `helics run ...` - -To run this simulation, the HELICS team has also developed a standardized means of launching co-simulations. Discussion of how to configure a JSON for use in launching a HELICS-based co-simulation is discussed in the [over here](./helics_run.md) but for all these examples, the configuration has already been done. In this case, that configuration is in the examples folder as "cosim_runner_1a.json" and looks like this: - -```json -{ - "broker": false, - "federates": [ - { - "directory": "./Transmission/", - "exec": "python Transmission_simulator.py", - "host": "localhost", - "name": "PythonCombinationFederate" - }, - { - "directory": "./Distribution/", - "exec": "gridlabd IEEE_123_feeder_0.glm", - "host": "localhost", - "name": "GridLABDFederate" - } - ], - "name": "Example-1a-T-D-Cosimulation-HELICSRunner" -} -``` - -Briefly, it's easy to guess what a few of these parameters do: - -- "directory" is the location of the model to be run -- "exec" is the command line call (with all necessary options) to launch the co-simulation - -With a properly written configuration file, launching the co-simulation becomes very straightforward: - -`helics run --path ` - -### Experiment and Results - -To show the difference between running these two simulators in a stand-alone analysis and as a co-simulation, modify the federate JSON configurations and use `helics run ...` in both cases to run the analysis. To run the two as a co-simulation, leave publication and subscription entries in the federate JSON configuration. To run them as stand-alone federates with no interaction, delete the publications and subscriptions from both JSON configuration files. By removing the information transfer between the two they become disconnected but are still able to be executed as if they were participating in the federation. - -The figure below shows the total load on the transmission node to which the distribution system model is attached over the course of the simulated day, both when operating stand-alone and when running in a co-simulation with the distribution system. - -![Ex. 1a transmission bus voltage](https://github.com/GMLC-TDC/helics_doc_resources/raw/main/user_guide/Ex1a_Bus_voltage_118.png) - -As can be seen, the impacts of co-simulation are relatively modest in this case. Even when the transmission system provides a dynamic high-side substation voltage (rather than just assuming a fixed value) and even with loads that have been created to be very voltage sensitive, the changing substation voltage doesn't impact the load substantially and change the voltage profiles significantly. (If you're curious to see an even bigger impact, you can disable the voltage regulators in GridLAB-D by editing the `regulator_configuration` objects so that the `Control` parameter is set to `MANUAL`. This will lock the regulators into place and allow the substation voltage to propagate through the circuit unregulated.) (xxxxxxx - double-check this.) - -The load of the distribution circuit as seen by the transmission model with and without co-simulation is similarly muted. - -![Ex. 1a distribution system load](https://github.com/GMLC-TDC/helics_doc_resources/raw/main/user_guide/Ex1a_Feeder_consumption.png) diff --git a/docs/user-guide/fundamental_topics/value_types.md b/docs/user-guide/fundamental_topics/value_types.md deleted file mode 100644 index c096459420..0000000000 --- a/docs/user-guide/fundamental_topics/value_types.md +++ /dev/null @@ -1,3 +0,0 @@ -# HELICS Value Message Types - -This section will describe in more detail the four types of HELICS messages and provide further guidance to help users determine which ones to use to maximize co-simulation performance or ease of configuration. diff --git a/docs/user-guide/fundamental_topics/web_interface.md b/docs/user-guide/fundamental_topics/web_interface.md index 0c0441394f..9b24ee4eef 100644 --- a/docs/user-guide/fundamental_topics/web_interface.md +++ b/docs/user-guide/fundamental_topics/web_interface.md @@ -39,19 +39,13 @@ When you have a co-simulation that you've vetted and feel comfortable will run w 1. (optional) Load in a configuration file - If you just want to look at a few federates and/or publications to track the progress of the co-simulation, make a web interface configuration file that does so and load it up. 2. Press the "Run" button (number 2 in the screenshot above). -The helics_cli will launch the co-simulation and the web interface will update every xxxxxxx seconds (or as specified in the configuration file). This periodically updating view is helpful if only to see where the co-simulation is at (simulation time-wise) but also helps confirm that message values are as expected. When the co-simulation is done, xxxxxxx (as message will appear? How are we indicating this?). All messages from the co-simulation (or a subset as specified in the helic_cli configuration) have been stored in an SQLite database; the database can be directly queried or the data can be exported to file in a number of formats (CSV, JSON) and post-process by a tool of your choice. +The helics_cli will launch the co-simulation and the web interface will update every five seconds (or as specified in the configuration file). This periodically updating view is helpful if only to see where the co-simulation is at (simulation time-wise) but also helps confirm that message values are as expected. When the co-simulation is done, xxxxxxx (as message will appear? How are we indicating this?). All messages from the co-simulation (or a subset as specified in the helic_cli configuration) have been stored in an SQLite database; the database can be directly queried or the data can be exported to file in a number of formats (CSV, JSON) and post-process by a tool of your choice. ### Debugging runs -Just like writing code, it is not unusual for a co-simulation to not quite work write the first time it's constructed and the web interface provides tooling to help verify and trouble-shoot the construction co-simulation. [There's a whole section on trouble-shooting techniques](../troubleshooting.md) and we won't re-iterate the guidance here but here's how the web interface can be used try to get a diagnostic view of the federation's operation. +Just like writing code, it is not unusual for a co-simulation to not quite work write the first time it's constructed and the web interface provides tooling to help verify and trouble-shoot the construction co-simulation. Here's how the web interface can be used try to get a diagnostic view of the federation's operation. 1. (optional but highly recommended) Load in a configuration file - Limit the federates and publications to those of interest and most revealing of the state of the simulation. 2. Enter a simulated time of interest and press the "Run to next grant" button (number 4 in the above diagram) 3. Check the state of the federation - When the co-simulation stops at the indicated time, check that all federates of interest have been granted and are requesting expected times. Check the message table and verify that all messages of interest have published with reasonable/expected values. 4. As necessary, proceed to subsequent or later time steps to hunt down the particular problem of interest. - -## Web interface demonstration - -Below is a demonstration of how the web interface is used to run Example xxxxxxx. - - diff --git a/docs/user-guide/installation/build_from_source.md b/docs/user-guide/installation/build_from_source.md index 733ad40ebc..3c80621cfe 100644 --- a/docs/user-guide/installation/build_from_source.md +++ b/docs/user-guide/installation/build_from_source.md @@ -29,7 +29,7 @@ git checkout develop To switch to a tagged release, you can type the following: ```bash -git checkout v3.0.1 +git checkout v3.3.1 ``` You will not need a full understanding of how `git` works for installing HELICS, but if you are interested you can find a good `git` resource in [this page](https://git-scm.com/book/en/v2). diff --git a/docs/user-guide/installation/helics_cmake_options.md b/docs/user-guide/installation/helics_cmake_options.md index ad7e3cd6d9..5eb4d89dc8 100644 --- a/docs/user-guide/installation/helics_cmake_options.md +++ b/docs/user-guide/installation/helics_cmake_options.md @@ -99,3 +99,4 @@ There are a few options in the CMake system that are not visible in the GUI they - `HELICS_SKIP_ZMQ_INSTALL`: This is only relevant if ZMQ is built as part of the compilation process, but it skips the installation of zmq as part of HELICS install in that case. - `HELICS_BENCHMARK_SHIFT_FACTOR`: For running the benchmarks this shift factor can be used to scale the number of federates used for the benchmark tests. If used it is required to be a number and is power of 2 shift from nominal values. For example for a small system a shift factor of -1 or -2 might be appropriate for the benchmarks not to take too long. The default for systems with 4 or fewer cores is `-1` and 0 for larger compute systems. For small 2 core systems a value of -2 might be appropriate. For some very large systems a bigger value might be able to be used. - `HELICS_HIDE_CMAKE_VARIABLES`: When using HELICS as a subproject in a CMake build this option can be enabled to hide all HELICS related variables in CMake so they won't show up in the CMake GUI. +- `WIN32_WINNT`: On some systems like msys or cygwin some libraries need to know the version of windows and it is not automatically detected so this variable can override the default which is set up for windows 10. diff --git a/docs/user-guide/installation/index.md b/docs/user-guide/installation/index.md index 7ea60a0112..280dd6d70c 100644 --- a/docs/user-guide/installation/index.md +++ b/docs/user-guide/installation/index.md @@ -41,7 +41,7 @@ graph LR end subgraph Package Manager/Precompiled languageChoice(What language are
you using?) - languageChoice -->|Python| python[Use pip:

pip install helics] + languageChoice -->|Python| python["Use pip:

pip install 'helics[cli]'"] languageChoice -->|MATLAB| matlab[Follow instructions in
the matHELICS repository] languageChoice -->|julia| julia[Use pkg:

pck> add helics] languageChoice -->|Java| java[Build from source with the
Java CMAKE option set

HELICS_BUILD_JAVA_INTERFACE=ON] @@ -81,6 +81,10 @@ Installation instructions are available in the [matHELICS repository README](htt [`pkg> add HELICS`](https://github.com/GMLC-TDC/HELICS.jl/blob/master/README.md) +### pip install + +[`pip install 'helics[cli]'`](https://python.helics.org/) (Includes the optional but recommended helics_cli tool.) + ### jHELICS [Build from source](./build_from_source.md) with the [CMAKE option](./helics_cmake_options.md) `HELICS_BUILD_JAVA_INTERFACE=ON` @@ -101,6 +105,10 @@ Installation instructions are available in the [matHELICS repository README](htt [`spack install helics`](./spack.md) +## Running an Example + +The [Quick Start guide](../../quick_start/quick_start_index.md) walks through the steps of running the first Python-based User Guide example and serves as a good way to test your (Python) installation. + ## HELICS runner Previously a separate executable, `helics_cli` was used to provide functionality to launch a HELICS-based co-simulation by calling a JSON configuration such as @@ -109,4 +117,4 @@ Previously a separate executable, `helics_cli` was used to provide functionality helics run --path= ``` -This functionality still exists but has been moved to the [PyHELICS code base](https://python.helics.org/) and the `helics_cli` repository has been deprecated. Thus, it is recommended that all users install PyHELICS (via `pip install helics` as described above) to gain the runner and web interface functionality. +This functionality still exists but has been moved to the [PyHELICS code base](https://python.helics.org/) and the `helics_cli` repository has been deprecated. Thus, it is recommended that all users install PyHELICS (via `pip install 'helics[cli]'` as described above) to gain the runner and web interface functionality. diff --git a/docs/user-guide/needs_updating/hello_world.md b/docs/user-guide/needs_updating/hello_world.md deleted file mode 100644 index bec0657d8c..0000000000 --- a/docs/user-guide/needs_updating/hello_world.md +++ /dev/null @@ -1,169 +0,0 @@ -# Hello World - -Now that you have HELICS installed, you are ready to create your first -HELICS federation. Let's create a simple `Hello, World` example with 2 -federates. - -
- -Note: This tutorial assumes basic familiarity with the command line. The -HELICS co-simulation framework itself makes no specific demands about -your editing, tooling, or where your code lives. Feel free to use -whatever editor or IDE you are comfortable with. - -
- -**Create a federations directory** - -Linux and Mac: - -```bash -$ mkdir -p ~/federations/hello_world -$ cd ~/federations/hello_world -``` - -Windows CMD: - -```bash -> mkdir %USERPROFILE%\federations -> cd %USERPROFILE%\federations -> mkdir hello_world -> cd hello_world -``` - -**Writing your first federation** - -Next, make a new source file and call it `hello_world_sender.c`. Copy -the contents from -[hello_world_sender.c](https://github.com/GMLC-TDC/HELICS-Examples/blob/72c9d38e/c/hello_world/hello_world_sender.c) -and paste it into the file. - -Next, create a new source file and call it `hello_world_receiver.c`. -Copy the contents from -[hello_world_receiver.c](https://github.com/GMLC-TDC/HELICS-Examples/blob/72c9d38e/c/hello_world/hello_world_receiver.c) -and paste it into the file. - -We will go through in more detail the contents of these files. For now, -save the files and open two terminals. - -**Compiling the federates** - -To compile the federates, you can use the following commands. - -Linux and Mac: - -```bash -$ cc hello_world_sender.c -o ./hello_world_sender -lhelicsSharedLib -$ cc hello_world_receiver.c -o ./hello_world_receiver -lhelicsSharedLib -``` - -You may need to include additional include paths and library paths in -the above command. - -**Running a federation** - -Linux and Mac: - -Next, open three terminals. In the first terminal, run the following -command. - -```bash -$ ./helics_broker -f2 -``` - -In the second terminal, run the following command. - -```bash -$ ./hello_world_sender -``` - -In a third terminal, run the following command. - -```bash -$ ./hello_world_receiver -``` - -You should see `Hello, World` printed out in the terminal where you ran -the `hello_world_receiver`. - -_For a guide to run this example in Visual Studio go to this link: -[hello-world-VS](./hello-world-VS.md)._ - -**Anatomy of a HELICS federation** - -Now, let’s go over what just happened in the `hello_world_sender.c` part -of the “Hello, World” program in detail. - -The following block creates a ValueFederate. We will discuss what -`FederateInfo` is and what a `ValueFederate` is, along with other types -of Federates in more detail in other documents. - -```c -fedinfo = helicsCreateFederateInfo (); -helicsFederateInfoSetCoreTypeFromString (fedinfo,"zmq",&err); -helicsFederateInfoSetCoreInitString (fedinfo,fedinitstring,&err); -helicsFederateInfoSetTimeProperty (fedinfo,helicsGetPropertyIndex("period"), 1.0,&err); -vfed = helicsCreateValueFederate ("hello_world_sender",fedinfo,&err); -``` - -The following registers a global publication. - -```c -pub = helicsFederateRegisterGlobalPublication (vfed, "hello", helics_data_type_string, "",&err); -``` - -The following ensures that the federation has entered execution mode. -If `helicsFederateEnterInitializingMode` is not included the call to -`helicsFederateEnterExecutingMode` will automatically make the call in the background. - -```c -helicsFederateEnterInitializingMode (vfed,&err); -helicsFederateEnterExecutingMode (vfed,&err); -``` - -These functions publish a String and make a RequestTime function call to -advance time in the simulation. - -```c -helicsPublicationPublishString(pub, "Hello, World",&err); -currenttime=helicsFederateRequestTime(vfed, 1.0, &err); -``` - -And finally, these functions free the Federate and close the HELICS library. - -```c -helicsFederateFinalize (vfed,&err); -helicsFederateFree (vfed); -helicsCloseLibrary (); -``` - -You can see that the `hello_world_receiver.c` is also very similar, but -uses a Subscription instead. A snippet of the code is shown below. - -```c -fedinfo = helicsCreateFederateInfo (); -helicsFederateInfoSetCoreTypeFromString (fedinfo, "zmq",&err); -helicsFederateInfoSetCoreInitString (fedinfo, fedinitstring,&err); -helicsFederateInfoSetTimeProperty (fedinfo,helics_property_time_period, 1.0,&err); - -vfed = helicsCreateValueFederate ("hello_world_receiver",fedinfo,&err); -sub = helicsFederateRegisterSubscription (vfed, "hello",NULL,&err); - -helicsFederateEnterInitializingMode (vfed,&err); -helicsFederateEnterExecutingMode (vfed,&err); - -/** request that helics grant the federate a time of 1.0 - the new time will be returned in currentime*/ -currenttime=helicsFederateRequestTime (vfed, 1.0,&err); - -isUpdated = helicsInputIsUpdated (sub); -helicsInputGetString (sub, value, 128,&actualLen,&err) -printf("%s\n", value); - -helicsFederateFinalize (vfed,&err); -helicsFederateFree (vfed); -helicsCloseLibrary (); -``` - -**_A note on the `&err` term_** -Many functions in the C API take a pointer to a helics_error structure. This can be created by a call to `helicsErrorInitialize` and can be reset by `helicsErrorClear(helics_error *err)`. If an error occurs during the execution of a function or some inputs were invalid an error code in the helics_error structure will be set and a message included. For all functions if an error structure that already has an error in place is passed as an argument the function short circuits and does nothing. So checks can be done after a sequence of calls if desired with no worry about side effects. In the C++98 API an error triggers an exception, and in the base C++ API these originate as exceptions. diff --git a/docs/user-guide/needs_updating/hello_world_VS.md b/docs/user-guide/needs_updating/hello_world_VS.md deleted file mode 100644 index 89ce4533cc..0000000000 --- a/docs/user-guide/needs_updating/hello_world_VS.md +++ /dev/null @@ -1,226 +0,0 @@ -# Running hello_world example using HELICS windows installer + Visual Studio 2019 - -**1. Make sure that you have downloaded HELICS through the installer** - -- To get to the installer you can access it through either of the following links: - - - [https://github.com/GMLC-TDC/HELICS/releases](https://github.com/GMLC-TDC/HELICS/releases) - - [https://docs.helics.org/en/latest/installation/index.html](https://docs.helics.org/en/latest/installation/index.html) - where you will see this: - - ![](./visuals/releases.JPG) - -- Once you have gotten to the list of releases, you will see something like this: - - ![](./visuals/installerEXE.jpg) - - There is a file with the .exe suffix like the highlighted file above. That will be your Windows Installer. Download it. - -- After downloading the executable, run it. - - ** Windows may give you a warning but you may run it anyway. ** - - Once you allow it to make changes, you will have the set up guide appear: - - ![](./visuals/SetUpScreen.JPG) - -- Click through: - -Next > I agree > Choose to add system variables if you would like > Next > Choose Destination folder for your install > Next > Choose Start Up Folder > Next > Keep all install components > Install - -- This should install HELICS onto Windows and your folder directory should look somewhat like this: - - ![](./visuals/folderview.JPG) - - Inside the following folders (bin, lib, and include) you find this: - - - bin: - - ![](./visuals/bin.JPG) - - - lib: - - ![](./visuals/lib.JPG) - - - include: - -![](./visuals/include.JPG) - -** Keep track where the dynamic and static libraries are. We will need to know these locations to link it in Visual Studios! ** - -**2. Pull the HELICS example folder down from github** - -```shell-session -git clone https://github.com/GMLC-TDC/HELICS-Examples.git -``` - -- To navigate to the C hello_world example: -folder-HELICS-examples-downloaded-to-/c/hello_world. - -It should look like this: - -![](./visuals/helloworlddir.JPG) - -**3. Load the examples into Visual Studio** - -Open up Visual Studio. We will do this twice since helics_world_sender.c and helics_world_receiver.c will need to be ran as two different executables. - -We will first do this for helics_world_sender.c . - -a. When you open up Visual Studio, there will be a welcome/get started pop up. You will see panel like this: - -![](./visuals/vsStartMenu.JPG) - -You will choose "Create a new project." - -b. Choose "Empty Project" - -![](./visuals/emptyProject.JPG) - -Even though it says it is C++, we will be using this option and simply changing the suffix/extension. - -c. Enter name the project with the file name without it's suffix (we will first do hello_world_sender): - -![](./visuals/configureSender.jpg) - -d. Choose "Create". - -e. Repeat steps a-d except this time use the name hello_world_receiver. - -Your "Configure your new project" screen should look like this: - -![](./visuals/configureReceiver.jpg) - -f. Once both projects have been created, we will add their respective source files. - -i. In Solution Explorer, - -```text -Right click hello_world_sender > Add > Existing item ... -``` - -![](./visuals/addExistingSender.jpg) - -ii. Go to the location of where you pulled down the HELICS example: - -![](./visuals/locationSender.jpg) - -Click Add. You should see the hello-world_sender.c file appear in the Solutions Explorer under the Source Files. - -Now do the same thing with hello_world_receiver.c in the hello_world_receiver Visual Studio project. - -**4. Link HELICS in visual studios to run example** - -a. Since we are using the HELICS installer, only the release version is attached. We need to make sure we're running on "Release" and "x64" settings. check that these are set in each tool bar of the projects: - -![](./visuals/releaseSender.JPG) - -![](./visuals/releaseReceiver.JPG) - -b. Go to Project > Properties > C/C++ > All Options > Additional Include Directories > Down Arrow > Edit - -This is where you will add the Include Directory of your HELICS installation. Check Step One (your path should end with include instead of helics, i.e. from the example it should be C:/Users/arbitraryfolder/HELICS/helics_2_6_0/include: - -![](./visuals/settingsInclude.jpg) - -Click Ok > Apply. ** Do not exit out of Properties yet ** - -c. Go to Linker > All Options > scroll all the way up - -i. Additional Dependencies > Down Arrow > Edit - -This is where you will add the HELICS static library name: helicsSharedLib.lib - -![](./visuals/settingLib.jpg) - -Click Ok > Apply. ** Do not exit out of Properties yet. Stay in Linker** - -ii. Additional Library Directories > Down Arrow > Edit - -This is where you will add the directories that hold the HELICS static and dynamic libraries, helicsSharedLib.lib and helicsSharedLib.dll, i.e. from example: - -C:/Users/arbitraryfolder/HELICS/helics_2_6_0/bin - -C:/Users/arbitraryfolder/HELICS/helics_2_6_0/lib - -![](./visuals/settingLibDir.jpg) - -Click Ok > Apply > Ok (This will exit you out of Properties) - -d. Go to ToolBar > Build > Build Solution - -e. Once the solution is built, go to the Solution Explorer. You will go to the ToolBar and click on the folder/window icon next to the Home Icon. Once clicked the down arrow, you will either see - -Folder View - -- if you see this, you can just simply click Folder View and it'll switch you over to the Folder View - -or - -Two Options: .sln and project name with path - -- if you see this, you will click the project name with the path - -![](./visuals/switchingViews.jpg) - -Here you see that there are two options. - -Once you switch to Folder View or the option with the name + path, you will go to the Folder x64 > Release. You should be able to find the helics_world_sender.exe or the helics_world.receiver.exe file depending on which project you're looking at right now. - -Here you will add the dynamic library. This is crucial part and cannot be missed or else we will have an error when we try to run the simulation. - -i. Right Click on Release > Click Open Folder in File Explorer - -![](./visuals/OpenFolder.jpg) - -ii. In another File Explorer, open up to your HELICS bin folder. You will find the helicsSharedLib.dll file. This will then be COPIED to the Release Folder that was just opened. - -Before .dll file is copied over: - -![](./visuals/twofolders.jpg) - -Copy the file over simply by - -Click on the helicsSharedLib.dll in bin folder > Ctrl + c > Go over to Release folder > Ctrl + v - -After .dll file is copied over: - -![](./visuals/twofoldersAfter.jpg) - -iii. Go back to Solutions View in order to run the solution (executable). - -To do this, go back to Solution Explorer toolbar and click on folder/window icon next tot the Home Icon. Click the down arrow and choose option with .sln extension. - -f. Once Solution is built, do steps a-e for other project (if you just did helics_world_sender, do helics_world_receiver, vice versa). - -**5. Run the example** - -To run the example we must have the broker running and also two of the solutions built into executables and ran. - -The broker should be located in your HELICS bin folder. - -a. Open a command prompt on windows, and go to the folder & run: - -`helics_broker -f2` - -This will tell the broker to expect two federates (helics_world_sender & helics_world_receiver). - -- If there is a commError regarding zmq reply socket, it is because you are waiting too long to run the federates and the broker timed out. - -b. Run helics_world_sender - -`Click Green Play button 'Local Windows Debugger'` - -** Microsoft Visual Studio Debug console should pop up ** - -c. Run helics_world_receiver - -`Click Green Play button 'Local Windows Debugger'` - -** Microsoft visual Studio Debug console should pop up ** - -This is how each prompt/console should look like after - -broker, helics_world_sender, helics_world_receiver, respectively : - -![](./visuals/results.jpg) - -## Congratulations you ran your first HELICS simulation through Visual Studio! diff --git a/docs/user-guide/support.md b/docs/user-guide/support.md index e31dc52589..55752db222 100644 --- a/docs/user-guide/support.md +++ b/docs/user-guide/support.md @@ -23,4 +23,4 @@ If you're having trouble with understanding what HELICS does, how to use HELICS, - **[Gitter](https://gitter.im/GMLC-TDC/HELICS)** - Live chat with developers (when they're logged in) for quick fix support. -- **Virtual Office Hours** - HELICS developers have periodic open office hours where anybody can come and get hands-on help with understanding HELICS better or getting a particular feature to work. Contact helicsteam@helics.org for an invitation. +- **Virtual Office Hours** - HELICS developers have periodic [open office hours](https://helics.org/HELICSOfficeHours.ics) where anybody can come and get hands-on help with understanding HELICS better or getting a particular feature to work. diff --git a/examples/BrokerServerTestCase/CMakeLists.txt b/examples/BrokerServerTestCase/CMakeLists.txt index e7b012336d..a1074a1456 100644 --- a/examples/BrokerServerTestCase/CMakeLists.txt +++ b/examples/BrokerServerTestCase/CMakeLists.txt @@ -1,5 +1,5 @@ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Copyright (c) 2017-2023, Battelle Memorial Institute; Lawrence Livermore +# Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore # National Security, LLC; Alliance for Sustainable Energy, LLC. # See the top-level NOTICE for additional details. # All rights reserved. diff --git a/examples/BrokerServerTestCase/brokerServerTest.cpp b/examples/BrokerServerTestCase/brokerServerTest.cpp index 1cc5bfb0be..d95dee6329 100644 --- a/examples/BrokerServerTestCase/brokerServerTest.cpp +++ b/examples/BrokerServerTestCase/brokerServerTest.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 2ec5ccd510..64de2c8d56 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -1,5 +1,5 @@ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Copyright (c) 2017-2023, Battelle Memorial Institute; Lawrence Livermore +# Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore # National Security, LLC; Alliance for Sustainable Energy, LLC. # See the top-level NOTICE for additional details. # All rights reserved. diff --git a/examples/CppInterface/CMakeLists.txt b/examples/CppInterface/CMakeLists.txt index 155ad356ef..dff0dfb4e0 100644 --- a/examples/CppInterface/CMakeLists.txt +++ b/examples/CppInterface/CMakeLists.txt @@ -1,5 +1,5 @@ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Copyright (c) 2017-2023, Battelle Memorial Institute; Lawrence Livermore +# Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore # National Security, LLC; Alliance for Sustainable Energy, LLC. # See the top-level NOTICE for additional details. # All rights reserved. diff --git a/examples/CppInterface/nonlings_fed1.cpp b/examples/CppInterface/nonlings_fed1.cpp index 7b7f8793ac..55e8122125 100644 --- a/examples/CppInterface/nonlings_fed1.cpp +++ b/examples/CppInterface/nonlings_fed1.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/examples/CppInterface/nonlings_fed2.cpp b/examples/CppInterface/nonlings_fed2.cpp index 647740fd49..3c0270ca74 100644 --- a/examples/CppInterface/nonlings_fed2.cpp +++ b/examples/CppInterface/nonlings_fed2.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/examples/InteropExample/CMakeLists.txt b/examples/InteropExample/CMakeLists.txt index a0f88a71d3..f26f0baa5e 100644 --- a/examples/InteropExample/CMakeLists.txt +++ b/examples/InteropExample/CMakeLists.txt @@ -1,5 +1,5 @@ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Copyright (c) 2017-2023, Battelle Memorial Institute; Lawrence Livermore +# Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore # National Security, LLC; Alliance for Sustainable Energy, LLC. # See the top-level NOTICE for additional details. # All rights reserved. diff --git a/examples/InteropExample/InterOpFed1.cpp b/examples/InteropExample/InterOpFed1.cpp index cca7da56e1..3a26aff0b7 100644 --- a/examples/InteropExample/InterOpFed1.cpp +++ b/examples/InteropExample/InterOpFed1.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/examples/InteropExample/InterOpFed2.cpp b/examples/InteropExample/InterOpFed2.cpp index 0b856c87c2..54021e9e62 100644 --- a/examples/InteropExample/InterOpFed2.cpp +++ b/examples/InteropExample/InterOpFed2.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/examples/comboFederates1/CMakeLists.txt b/examples/comboFederates1/CMakeLists.txt index 79ce3d0cca..9558e5d459 100644 --- a/examples/comboFederates1/CMakeLists.txt +++ b/examples/comboFederates1/CMakeLists.txt @@ -1,5 +1,5 @@ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Copyright (c) 2017-2023, Battelle Memorial Institute; Lawrence Livermore +# Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore # National Security, LLC; Alliance for Sustainable Energy, LLC. # See the top-level NOTICE for additional details. # All rights reserved. diff --git a/examples/comboFederates1/comboFed.cpp b/examples/comboFederates1/comboFed.cpp index e33a1a07bc..621106697a 100644 --- a/examples/comboFederates1/comboFed.cpp +++ b/examples/comboFederates1/comboFed.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/examples/comboFederates_cpp_shared/CMakeLists.txt b/examples/comboFederates_cpp_shared/CMakeLists.txt index 854d5c3c2c..97a8859ecd 100644 --- a/examples/comboFederates_cpp_shared/CMakeLists.txt +++ b/examples/comboFederates_cpp_shared/CMakeLists.txt @@ -1,5 +1,5 @@ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Copyright (c) 2017-2023, Battelle Memorial Institute; Lawrence Livermore +# Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore # National Security, LLC; Alliance for Sustainable Energy, LLC. # See the top-level NOTICE for additional details. # All rights reserved. diff --git a/examples/comboFederates_cpp_shared/comboFed.cpp b/examples/comboFederates_cpp_shared/comboFed.cpp index 2ed550e800..ad6075a9ea 100644 --- a/examples/comboFederates_cpp_shared/comboFed.cpp +++ b/examples/comboFederates_cpp_shared/comboFed.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/interfaces/CMakeLists.txt b/interfaces/CMakeLists.txt index 2bcd1e0184..8d89eaafad 100644 --- a/interfaces/CMakeLists.txt +++ b/interfaces/CMakeLists.txt @@ -1,5 +1,5 @@ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Copyright (c) 2017-2023, Battelle Memorial Institute; Lawrence Livermore +# Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore # National Security, LLC; Alliance for Sustainable Energy, LLC. # See the top-level NOTICE for additional details. # All rights reserved. diff --git a/interfaces/csharp/CMakeLists.txt b/interfaces/csharp/CMakeLists.txt index 6064e6c198..04af4f9ddd 100644 --- a/interfaces/csharp/CMakeLists.txt +++ b/interfaces/csharp/CMakeLists.txt @@ -1,5 +1,5 @@ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Copyright (c) 2017-2023, Battelle Memorial Institute; Lawrence Livermore +# Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore # National Security, LLC; Alliance for Sustainable Energy, LLC. # See the top-level NOTICE for additional details. # All rights reserved. diff --git a/interfaces/java/CMakeLists.txt b/interfaces/java/CMakeLists.txt index b27a55d5cc..2573d34a53 100644 --- a/interfaces/java/CMakeLists.txt +++ b/interfaces/java/CMakeLists.txt @@ -1,5 +1,5 @@ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Copyright (c) 2017-2023, Battelle Memorial Institute; Lawrence Livermore +# Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore # National Security, LLC; Alliance for Sustainable Energy, LLC. # See the top-level NOTICE for additional details. # All rights reserved. diff --git a/interfaces/java/interface/helics.java b/interfaces/java/interface/helics.java index 9254d9cc06..1b384b7f32 100644 --- a/interfaces/java/interface/helics.java +++ b/interfaces/java/interface/helics.java @@ -128,7 +128,8 @@ public static int helicsDataBufferReserve(SWIGTYPE_p_void data, SWIGTYPE_p_int32 } /** - * create a new data buffer and copy an existing buffer + * create a new data buffer and copy an existing buffer
+ * @return a data buffer object with a copy of the data */ public static SWIGTYPE_p_void helicsDataBufferClone(SWIGTYPE_p_void data) { long cPtr = helicsJNI.helicsDataBufferClone(SWIGTYPE_p_void.getCPtr(data)); @@ -136,87 +137,121 @@ public static SWIGTYPE_p_void helicsDataBufferClone(SWIGTYPE_p_void data) { } /** - * convert an integer to serialized bytes + * convert an integer to serialized bytes in a buffer
+ * @param data the HelicsDataBuffer to fill
+ * @param value the value to serialize into the dataBuffer
+ * @return the buffer size after filling */ - public static SWIGTYPE_p_int32_t helicsIntegerToBytes(long value, SWIGTYPE_p_void data) { - return new SWIGTYPE_p_int32_t(helicsJNI.helicsIntegerToBytes(value, SWIGTYPE_p_void.getCPtr(data)), true); + public static SWIGTYPE_p_int32_t helicsDataBufferFillFromInteger(SWIGTYPE_p_void data, long value) { + return new SWIGTYPE_p_int32_t(helicsJNI.helicsDataBufferFillFromInteger(SWIGTYPE_p_void.getCPtr(data), value), true); } /** - * convert a double to serialized bytes + * convert a double to serialized bytesin a buffer
+ * @param data the HelicsDataBuffer to fill
+ * @param value the value to serialize into the dataBuffer
+ * @return the buffer size after filling */ - public static SWIGTYPE_p_int32_t helicsDoubleToBytes(double value, SWIGTYPE_p_void data) { - return new SWIGTYPE_p_int32_t(helicsJNI.helicsDoubleToBytes(value, SWIGTYPE_p_void.getCPtr(data)), true); + public static SWIGTYPE_p_int32_t helicsDataBufferFillFromDouble(SWIGTYPE_p_void data, double value) { + return new SWIGTYPE_p_int32_t(helicsJNI.helicsDataBufferFillFromDouble(SWIGTYPE_p_void.getCPtr(data), value), true); } /** - * convert a string to serialized bytes + * convert a string to serialized bytesin a buffer
+ * @param data the HelicsDataBuffer to fill
+ * @param value the value to serialize into the dataBuffer
+ * @return the buffer size after filling */ - public static SWIGTYPE_p_int32_t helicsStringToBytes(String value, SWIGTYPE_p_void data) { - return new SWIGTYPE_p_int32_t(helicsJNI.helicsStringToBytes(value, SWIGTYPE_p_void.getCPtr(data)), true); + public static SWIGTYPE_p_int32_t helicsDataBufferFillFromString(SWIGTYPE_p_void data, String value) { + return new SWIGTYPE_p_int32_t(helicsJNI.helicsDataBufferFillFromString(SWIGTYPE_p_void.getCPtr(data), value), true); } /** - * convert a raw string (may contain nulls) to serialized bytes + * convert a raw string (may contain nulls) to serialized bytesin a buffer
+ * @param data the HelicsDataBuffer to fill
+ * @return the buffer size after filling */ - public static SWIGTYPE_p_int32_t helicsRawStringToBytes(String str, int stringSize, SWIGTYPE_p_void data) { - return new SWIGTYPE_p_int32_t(helicsJNI.helicsRawStringToBytes(str, stringSize, SWIGTYPE_p_void.getCPtr(data)), true); + public static SWIGTYPE_p_int32_t helicsDataBufferFillFromRawString(SWIGTYPE_p_void data, String str, int stringSize) { + return new SWIGTYPE_p_int32_t(helicsJNI.helicsDataBufferFillFromRawString(SWIGTYPE_p_void.getCPtr(data), str, stringSize), true); } /** - * convert a bool to serialized bytes + * convert a bool to serialized bytesin a buffer
+ * @param data the HelicsDataBuffer to fill
+ * @param value the value to serialize into the dataBuffer
+ * @return the buffer size after filling */ - public static SWIGTYPE_p_int32_t helicsBooleanToBytes(int value, SWIGTYPE_p_void data) { - return new SWIGTYPE_p_int32_t(helicsJNI.helicsBooleanToBytes(value, SWIGTYPE_p_void.getCPtr(data)), true); + public static SWIGTYPE_p_int32_t helicsDataBufferFillFromBoolean(SWIGTYPE_p_void data, int value) { + return new SWIGTYPE_p_int32_t(helicsJNI.helicsDataBufferFillFromBoolean(SWIGTYPE_p_void.getCPtr(data), value), true); } /** - * convert a char to serialized bytes + * convert a char to serialized bytesin a buffer
+ * @param data the HelicsDataBuffer to fill
+ * @param value the value to serialize into the dataBuffer
+ * @return the buffer size after filling */ - public static SWIGTYPE_p_int32_t helicsCharToBytes(char value, SWIGTYPE_p_void data) { - return new SWIGTYPE_p_int32_t(helicsJNI.helicsCharToBytes(value, SWIGTYPE_p_void.getCPtr(data)), true); + public static SWIGTYPE_p_int32_t helicsDataBufferFillFromChar(SWIGTYPE_p_void data, char value) { + return new SWIGTYPE_p_int32_t(helicsJNI.helicsDataBufferFillFromChar(SWIGTYPE_p_void.getCPtr(data), value), true); } /** - * convert a time to serialized bytes + * convert a time to serialized bytesin a buffer
+ * @param data the HelicsDataBuffer to fill
+ * @param value the value to serialize into the dataBuffer
+ * @return the buffer size after filling */ - public static SWIGTYPE_p_int32_t helicsTimeToBytes(double value, SWIGTYPE_p_void data) { - return new SWIGTYPE_p_int32_t(helicsJNI.helicsTimeToBytes(value, SWIGTYPE_p_void.getCPtr(data)), true); + public static SWIGTYPE_p_int32_t helicsDataBufferFillFromTime(SWIGTYPE_p_void data, double value) { + return new SWIGTYPE_p_int32_t(helicsJNI.helicsDataBufferFillFromTime(SWIGTYPE_p_void.getCPtr(data), value), true); } /** - * convert a complex pair to serialized bytes + * convert a complex pair to serialized bytesin a buffer
+ * @param data the HelicsDataBuffer to fill
+ * @return the buffer size after filling */ - public static SWIGTYPE_p_int32_t helicsComplexToBytes(double real, double imag, SWIGTYPE_p_void data) { - return new SWIGTYPE_p_int32_t(helicsJNI.helicsComplexToBytes(real, imag, SWIGTYPE_p_void.getCPtr(data)), true); + public static SWIGTYPE_p_int32_t helicsDataBufferFillFromComplex(SWIGTYPE_p_void data, double real, double imag) { + return new SWIGTYPE_p_int32_t(helicsJNI.helicsDataBufferFillFromComplex(SWIGTYPE_p_void.getCPtr(data), real, imag), true); } /** - * convert a complex object to serialized bytes + * convert a complex object to serialized bytesin a buffer
+ * @param data the HelicsDataBuffer to fill
+ * @param value the value to serialize into the dataBuffer
+ * @return the buffer size after filling */ - public static SWIGTYPE_p_int32_t helicsComplexObjectToBytes(HelicsComplex value, SWIGTYPE_p_void data) { - return new SWIGTYPE_p_int32_t(helicsJNI.helicsComplexObjectToBytes(HelicsComplex.getCPtr(value), value, SWIGTYPE_p_void.getCPtr(data)), true); + public static SWIGTYPE_p_int32_t helicsDataBufferFillFromComplexObject(SWIGTYPE_p_void data, HelicsComplex value) { + return new SWIGTYPE_p_int32_t(helicsJNI.helicsDataBufferFillFromComplexObject(SWIGTYPE_p_void.getCPtr(data), HelicsComplex.getCPtr(value), value), true); } /** - * convert a real vector to serialized bytes + * convert a real vector to serialized bytesin a buffer
+ * @param data the HelicsDataBuffer to fill
+ * @param value the value to serialize into the dataBuffer
+ * @return the buffer size after filling */ - public static SWIGTYPE_p_int32_t helicsVectorToBytes(double[] value, int dataSize, SWIGTYPE_p_void data) { - return new SWIGTYPE_p_int32_t(helicsJNI.helicsVectorToBytes(value, dataSize, SWIGTYPE_p_void.getCPtr(data)), true); + public static SWIGTYPE_p_int32_t helicsDataBufferFillFromVector(SWIGTYPE_p_void data, double[] value, int dataSize) { + return new SWIGTYPE_p_int32_t(helicsJNI.helicsDataBufferFillFromVector(SWIGTYPE_p_void.getCPtr(data), value, dataSize), true); } /** - * convert a named point to serialized bytes + * convert a named point to serialized bytesin a buffer
+ * @param data the HelicsDataBuffer to fill
+ * @param value the value to serialize into the dataBuffer
+ * @return the buffer size after filling */ - public static SWIGTYPE_p_int32_t helicsNamedPointToBytes(String name, double value, SWIGTYPE_p_void data) { - return new SWIGTYPE_p_int32_t(helicsJNI.helicsNamedPointToBytes(name, value, SWIGTYPE_p_void.getCPtr(data)), true); + public static SWIGTYPE_p_int32_t helicsDataBufferFillFromNamedPoint(SWIGTYPE_p_void data, String name, double value) { + return new SWIGTYPE_p_int32_t(helicsJNI.helicsDataBufferFillFromNamedPoint(SWIGTYPE_p_void.getCPtr(data), name, value), true); } /** - * convert a complex vector to serialized bytes + * convert a complex vector to serialized bytesin a buffer
+ * @param data the HelicsDataBuffer to fill
+ * @param value the value to serialize into the dataBuffer
+ * @return the buffer size after filling */ - public static SWIGTYPE_p_int32_t helicsComplexVectorToBytes(double[] value, int dataSize, SWIGTYPE_p_void data) { - return new SWIGTYPE_p_int32_t(helicsJNI.helicsComplexVectorToBytes(value, dataSize, SWIGTYPE_p_void.getCPtr(data)), true); + public static SWIGTYPE_p_int32_t helicsDataBufferFillFromComplexVector(SWIGTYPE_p_void data, double[] value, int dataSize) { + return new SWIGTYPE_p_int32_t(helicsJNI.helicsDataBufferFillFromComplexVector(SWIGTYPE_p_void.getCPtr(data), value, dataSize), true); } /** @@ -852,16 +887,16 @@ public static void helicsBrokerFree(SWIGTYPE_p_void broker) { *
* HelicsFederate objects can be used in all functions that take a HelicsFederate or HelicsFederate object as an argument.
*
- * @param fedName The name of the federate to create, can NULL or an empty string to use the default name from fi or an assigned name.
- * @param fi The federate info object that contains details on the federate.
+ * @param fedName The name of the federate to create, can NULL or an empty string to use the default name from fedInfo or an assigned name.
+ * @param fedInfo The federate info object that contains details on the federate.
*
* ,out] err An error object that will contain an error code and string if any error occurred during the execution of the function.
*
*
* @return An opaque value federate object. */ - public static SWIGTYPE_p_void helicsCreateValueFederate(String fedName, SWIGTYPE_p_void fi) { - long cPtr = helicsJNI.helicsCreateValueFederate(fedName, SWIGTYPE_p_void.getCPtr(fi)); + public static SWIGTYPE_p_void helicsCreateValueFederate(String fedName, SWIGTYPE_p_void fedInfo) { + long cPtr = helicsJNI.helicsCreateValueFederate(fedName, SWIGTYPE_p_void.getCPtr(fedInfo)); return (cPtr == 0) ? null : new SWIGTYPE_p_void(cPtr, false); } @@ -889,15 +924,15 @@ public static SWIGTYPE_p_void helicsCreateValueFederateFromConfig(String configF * argument.
*
* @param fedName The name of the federate to create.
- * @param fi The federate info object that contains details on the federate.
+ * @param fedInfo The federate info object that contains details on the federate.
*
* ,out] err An error object that will contain an error code and string if any error occurred during the execution of the function.
*
*
* @return An opaque message federate object. */ - public static SWIGTYPE_p_void helicsCreateMessageFederate(String fedName, SWIGTYPE_p_void fi) { - long cPtr = helicsJNI.helicsCreateMessageFederate(fedName, SWIGTYPE_p_void.getCPtr(fi)); + public static SWIGTYPE_p_void helicsCreateMessageFederate(String fedName, SWIGTYPE_p_void fedInfo) { + long cPtr = helicsJNI.helicsCreateMessageFederate(fedName, SWIGTYPE_p_void.getCPtr(fedInfo)); return (cPtr == 0) ? null : new SWIGTYPE_p_void(cPtr, false); } @@ -925,16 +960,16 @@ public static SWIGTYPE_p_void helicsCreateMessageFederateFromConfig(String confi * Combination federates are both value federates and message federates, objects can be used in all functions
* that take a HelicsFederate, helics_message_federate or HelicsFederate object as an argument
*
- * @param fedName A string with the name of the federate, can be NULL or an empty string to pull the default name from fi.
- * @param fi The federate info object that contains details on the federate.
+ * @param fedName A string with the name of the federate, can be NULL or an empty string to pull the default name from fedInfo.
+ * @param fedInfo The federate info object that contains details on the federate.
*
* ,out] err An error object that will contain an error code and string if any error occurred during the execution of the function.
*
*
* @return An opaque value federate object nullptr if the object creation failed. */ - public static SWIGTYPE_p_void helicsCreateCombinationFederate(String fedName, SWIGTYPE_p_void fi) { - long cPtr = helicsJNI.helicsCreateCombinationFederate(fedName, SWIGTYPE_p_void.getCPtr(fi)); + public static SWIGTYPE_p_void helicsCreateCombinationFederate(String fedName, SWIGTYPE_p_void fedInfo) { + long cPtr = helicsJNI.helicsCreateCombinationFederate(fedName, SWIGTYPE_p_void.getCPtr(fedInfo)); return (cPtr == 0) ? null : new SWIGTYPE_p_void(cPtr, false); } @@ -961,16 +996,16 @@ public static SWIGTYPE_p_void helicsCreateCombinationFederateFromConfig(String c *
* Callback federates are combination federates that run a series of callback for execution in a completely automated fashion.
*
- * @param fedName A string with the name of the federate, can be NULL or an empty string to pull the default name from fi.
- * @param fi The federate info object that contains details on the federate.
+ * @param fedName A string with the name of the federate, can be NULL or an empty string to pull the default name from fedInfo.
+ * @param fedInfo The federate info object that contains details on the federate.
*
* ,out] err An error object that will contain an error code and string if any error occurred during the execution of the function.
*
*
* @return An opaque value federate object; nullptr if the object creation failed. */ - public static SWIGTYPE_p_void helicsCreateCallbackFederate(String fedName, SWIGTYPE_p_void fi) { - long cPtr = helicsJNI.helicsCreateCallbackFederate(fedName, SWIGTYPE_p_void.getCPtr(fi)); + public static SWIGTYPE_p_void helicsCreateCallbackFederate(String fedName, SWIGTYPE_p_void fedInfo) { + long cPtr = helicsJNI.helicsCreateCallbackFederate(fedName, SWIGTYPE_p_void.getCPtr(fedInfo)); return (cPtr == 0) ? null : new SWIGTYPE_p_void(cPtr, false); } @@ -1064,48 +1099,48 @@ public static SWIGTYPE_p_void helicsCreateFederateInfo() { /** * Create a federate info object from an existing one and clone the information.
*
- * @param fi A federateInfo object to duplicate.
+ * @param fedInfo A federateInfo object to duplicate.
*
* ,out] err An error object that will contain an error code and string if any error occurred during the execution of the function.
*
*
* @return A HelicsFederateInfo object which is a reference to the created object. */ - public static SWIGTYPE_p_void helicsFederateInfoClone(SWIGTYPE_p_void fi) { - long cPtr = helicsJNI.helicsFederateInfoClone(SWIGTYPE_p_void.getCPtr(fi)); + public static SWIGTYPE_p_void helicsFederateInfoClone(SWIGTYPE_p_void fedInfo) { + long cPtr = helicsJNI.helicsFederateInfoClone(SWIGTYPE_p_void.getCPtr(fedInfo)); return (cPtr == 0) ? null : new SWIGTYPE_p_void(cPtr, false); } /** * Load federate info from command line arguments.
*
- * @param fi A federateInfo object.
+ * @param fedInfo A federateInfo object.
* @param argc The number of command line arguments.
* @param argv An array of strings from the command line.
*
* ,out] err An error object that will contain an error code and string if any error occurred during the execution of the function. */ - public static void helicsFederateInfoLoadFromArgs(SWIGTYPE_p_void fi, String[] argc) { - helicsJNI.helicsFederateInfoLoadFromArgs(SWIGTYPE_p_void.getCPtr(fi), argc); + public static void helicsFederateInfoLoadFromArgs(SWIGTYPE_p_void fedInfo, String[] argc) { + helicsJNI.helicsFederateInfoLoadFromArgs(SWIGTYPE_p_void.getCPtr(fedInfo), argc); } /** * Load federate info from command line arguments contained in a string.
*
- * @param fi A federateInfo object.
+ * @param fedInfo A federateInfo object.
* @param args Command line arguments specified in a string.
*
* ,out] err An error object that will contain an error code and string if any error occurred during the execution of the function. */ - public static void helicsFederateInfoLoadFromString(SWIGTYPE_p_void fi, String args) { - helicsJNI.helicsFederateInfoLoadFromString(SWIGTYPE_p_void.getCPtr(fi), args); + public static void helicsFederateInfoLoadFromString(SWIGTYPE_p_void fedInfo, String args) { + helicsJNI.helicsFederateInfoLoadFromString(SWIGTYPE_p_void.getCPtr(fedInfo), args); } /** * Delete the memory associated with a federate info object. */ - public static void helicsFederateInfoFree(SWIGTYPE_p_void fi) { - helicsJNI.helicsFederateInfoFree(SWIGTYPE_p_void.getCPtr(fi)); + public static void helicsFederateInfoFree(SWIGTYPE_p_void fedInfo) { + helicsJNI.helicsFederateInfoFree(SWIGTYPE_p_void.getCPtr(fedInfo)); } /** @@ -1120,88 +1155,88 @@ public static int helicsFederateIsValid(SWIGTYPE_p_void fed) { /** * Set the name of the core to link to for a federate.
*
- * @param fi The federate info object to alter.
+ * @param fedInfo The federate info object to alter.
* @param corename The identifier for a core to link to.
*
* ,out] err An error object that will contain an error code and string if any error occurred during the execution of the function. */ - public static void helicsFederateInfoSetCoreName(SWIGTYPE_p_void fi, String corename) { - helicsJNI.helicsFederateInfoSetCoreName(SWIGTYPE_p_void.getCPtr(fi), corename); + public static void helicsFederateInfoSetCoreName(SWIGTYPE_p_void fedInfo, String corename) { + helicsJNI.helicsFederateInfoSetCoreName(SWIGTYPE_p_void.getCPtr(fedInfo), corename); } /** * Set the initialization string for the core usually in the form of command line arguments.
*
- * @param fi The federate info object to alter.
+ * @param fedInfo The federate info object to alter.
* @param coreInit A string containing command line arguments to be passed to the core.
*
* ,out] err An error object that will contain an error code and string if any error occurred during the execution of the function. */ - public static void helicsFederateInfoSetCoreInitString(SWIGTYPE_p_void fi, String coreInit) { - helicsJNI.helicsFederateInfoSetCoreInitString(SWIGTYPE_p_void.getCPtr(fi), coreInit); + public static void helicsFederateInfoSetCoreInitString(SWIGTYPE_p_void fedInfo, String coreInit) { + helicsJNI.helicsFederateInfoSetCoreInitString(SWIGTYPE_p_void.getCPtr(fedInfo), coreInit); } /** * Set the initialization string that a core will pass to a generated broker usually in the form of command line arguments.
*
- * @param fi The federate info object to alter.
+ * @param fedInfo The federate info object to alter.
* @param brokerInit A string with command line arguments for a generated broker.
*
* ,out] err An error object that will contain an error code and string if any error occurred during the execution of the function. */ - public static void helicsFederateInfoSetBrokerInitString(SWIGTYPE_p_void fi, String brokerInit) { - helicsJNI.helicsFederateInfoSetBrokerInitString(SWIGTYPE_p_void.getCPtr(fi), brokerInit); + public static void helicsFederateInfoSetBrokerInitString(SWIGTYPE_p_void fedInfo, String brokerInit) { + helicsJNI.helicsFederateInfoSetBrokerInitString(SWIGTYPE_p_void.getCPtr(fedInfo), brokerInit); } /** * Set the core type by integer code.
*
* Valid values available by definitions in api-data.h.
- * @param fi The federate info object to alter.
+ * @param fedInfo The federate info object to alter.
* @param coretype An numerical code for a core type see /ref helics_CoreType.
*
* ,out] err An error object that will contain an error code and string if any error occurred during the execution of the function. */ - public static void helicsFederateInfoSetCoreType(SWIGTYPE_p_void fi, int coretype) { - helicsJNI.helicsFederateInfoSetCoreType(SWIGTYPE_p_void.getCPtr(fi), coretype); + public static void helicsFederateInfoSetCoreType(SWIGTYPE_p_void fedInfo, int coretype) { + helicsJNI.helicsFederateInfoSetCoreType(SWIGTYPE_p_void.getCPtr(fedInfo), coretype); } /** * Set the core type from a string.
*
- * @param fi The federate info object to alter.
+ * @param fedInfo The federate info object to alter.
* @param coretype A string naming a core type.
*
* ,out] err An error object that will contain an error code and string if any error occurred during the execution of the function. */ - public static void helicsFederateInfoSetCoreTypeFromString(SWIGTYPE_p_void fi, String coretype) { - helicsJNI.helicsFederateInfoSetCoreTypeFromString(SWIGTYPE_p_void.getCPtr(fi), coretype); + public static void helicsFederateInfoSetCoreTypeFromString(SWIGTYPE_p_void fedInfo, String coretype) { + helicsJNI.helicsFederateInfoSetCoreTypeFromString(SWIGTYPE_p_void.getCPtr(fedInfo), coretype); } /** * Set the name or connection information for a broker.
*
* This is only used if the core is automatically created, the broker information will be transferred to the core for connection.
- * @param fi The federate info object to alter.
+ * @param fedInfo The federate info object to alter.
* @param broker A string which defines the connection information for a broker either a name or an address.
*
* ,out] err An error object that will contain an error code and string if any error occurred during the execution of the function. */ - public static void helicsFederateInfoSetBroker(SWIGTYPE_p_void fi, String broker) { - helicsJNI.helicsFederateInfoSetBroker(SWIGTYPE_p_void.getCPtr(fi), broker); + public static void helicsFederateInfoSetBroker(SWIGTYPE_p_void fedInfo, String broker) { + helicsJNI.helicsFederateInfoSetBroker(SWIGTYPE_p_void.getCPtr(fedInfo), broker); } /** * Set the key for a broker connection.
*
* This is only used if the core is automatically created, the broker information will be transferred to the core for connection.
- * @param fi The federate info object to alter.
+ * @param fedInfo The federate info object to alter.
* @param brokerkey A string containing a key for the broker to connect.
*
* ,out] err An error object that will contain an error code and string if any error occurred during the execution of the function. */ - public static void helicsFederateInfoSetBrokerKey(SWIGTYPE_p_void fi, String brokerkey) { - helicsJNI.helicsFederateInfoSetBrokerKey(SWIGTYPE_p_void.getCPtr(fi), brokerkey); + public static void helicsFederateInfoSetBrokerKey(SWIGTYPE_p_void fedInfo, String brokerkey) { + helicsJNI.helicsFederateInfoSetBrokerKey(SWIGTYPE_p_void.getCPtr(fedInfo), brokerkey); } /** @@ -1209,26 +1244,26 @@ public static void helicsFederateInfoSetBrokerKey(SWIGTYPE_p_void fi, String bro *
* This is only used if the core is automatically created, the broker information will be transferred to the core for connection.
* This will only be useful for network broker connections.
- * @param fi The federate info object to alter.
+ * @param fedInfo The federate info object to alter.
* @param brokerPort The integer port number to use for connection with a broker.
*
* ,out] err An error object that will contain an error code and string if any error occurred during the execution of the function. */ - public static void helicsFederateInfoSetBrokerPort(SWIGTYPE_p_void fi, int brokerPort) { - helicsJNI.helicsFederateInfoSetBrokerPort(SWIGTYPE_p_void.getCPtr(fi), brokerPort); + public static void helicsFederateInfoSetBrokerPort(SWIGTYPE_p_void fedInfo, int brokerPort) { + helicsJNI.helicsFederateInfoSetBrokerPort(SWIGTYPE_p_void.getCPtr(fedInfo), brokerPort); } /** * Set the local port to use.
*
* This is only used if the core is automatically created, the port information will be transferred to the core for connection.
- * @param fi The federate info object to alter.
+ * @param fedInfo The federate info object to alter.
* @param localPort A string with the port information to use as the local server port can be a number or "auto" or "os_local".
*
* ,out] err An error object that will contain an error code and string if any error occurred during the execution of the function. */ - public static void helicsFederateInfoSetLocalPort(SWIGTYPE_p_void fi, String localPort) { - helicsJNI.helicsFederateInfoSetLocalPort(SWIGTYPE_p_void.getCPtr(fi), localPort); + public static void helicsFederateInfoSetLocalPort(SWIGTYPE_p_void fedInfo, String localPort) { + helicsJNI.helicsFederateInfoSetLocalPort(SWIGTYPE_p_void.getCPtr(fedInfo), localPort); } /** @@ -1290,14 +1325,14 @@ public static int helicsGetDataType(String val) { * Set a flag in the info structure.
*
* Valid flags are available /ref helics_federate_flags.
- * @param fi The federate info object to alter.
+ * @param fedInfo The federate info object to alter.
* @param flag A numerical index for a flag.
* @param value The desired value of the flag HELICS_TRUE or HELICS_FALSE.
*
* ,out] err An error object that will contain an error code and string if any error occurred during the execution of the function. */ - public static void helicsFederateInfoSetFlagOption(SWIGTYPE_p_void fi, int flag, int value) { - helicsJNI.helicsFederateInfoSetFlagOption(SWIGTYPE_p_void.getCPtr(fi), flag, value); + public static void helicsFederateInfoSetFlagOption(SWIGTYPE_p_void fedInfo, int flag, int value) { + helicsJNI.helicsFederateInfoSetFlagOption(SWIGTYPE_p_void.getCPtr(fedInfo), flag, value); } /** @@ -1305,26 +1340,26 @@ public static void helicsFederateInfoSetFlagOption(SWIGTYPE_p_void fi, int flag, *
* The separator character is the separation character for local publications/endpoints in creating their global name.
* For example if the separator character is '/' then a local endpoint would have a globally reachable name of fedName/localName.
- * @param fi The federate info object to alter.
+ * @param fedInfo The federate info object to alter.
* @param separator The character to use as a separator.
*
* ,out] err An error object that will contain an error code and string if any error occurred during the execution of the function. */ - public static void helicsFederateInfoSetSeparator(SWIGTYPE_p_void fi, char separator) { - helicsJNI.helicsFederateInfoSetSeparator(SWIGTYPE_p_void.getCPtr(fi), separator); + public static void helicsFederateInfoSetSeparator(SWIGTYPE_p_void fedInfo, char separator) { + helicsJNI.helicsFederateInfoSetSeparator(SWIGTYPE_p_void.getCPtr(fedInfo), separator); } /** * Set the output delay for a federate.
*
- * @param fi The federate info object to alter.
+ * @param fedInfo The federate info object to alter.
* @param timeProperty An integer representation of the time based property to set see /ref helics_properties.
* @param propertyValue The value of the property to set the timeProperty to.
*
* ,out] err An error object that will contain an error code and string if any error occurred during the execution of the function. */ - public static void helicsFederateInfoSetTimeProperty(SWIGTYPE_p_void fi, int timeProperty, double propertyValue) { - helicsJNI.helicsFederateInfoSetTimeProperty(SWIGTYPE_p_void.getCPtr(fi), timeProperty, propertyValue); + public static void helicsFederateInfoSetTimeProperty(SWIGTYPE_p_void fedInfo, int timeProperty, double propertyValue) { + helicsJNI.helicsFederateInfoSetTimeProperty(SWIGTYPE_p_void.getCPtr(fedInfo), timeProperty, propertyValue); } /** @@ -1332,14 +1367,14 @@ public static void helicsFederateInfoSetTimeProperty(SWIGTYPE_p_void fi, int tim *
* Set known properties.
*
- * @param fi The federateInfo object to alter.
+ * @param fedInfo The federateInfo object to alter.
* @param intProperty An int identifying the property.
* @param propertyValue The value to set the property to.
*
* ,out] err An error object that will contain an error code and string if any error occurred during the execution of the function. */ - public static void helicsFederateInfoSetIntegerProperty(SWIGTYPE_p_void fi, int intProperty, int propertyValue) { - helicsJNI.helicsFederateInfoSetIntegerProperty(SWIGTYPE_p_void.getCPtr(fi), intProperty, propertyValue); + public static void helicsFederateInfoSetIntegerProperty(SWIGTYPE_p_void fedInfo, int intProperty, int propertyValue) { + helicsJNI.helicsFederateInfoSetIntegerProperty(SWIGTYPE_p_void.getCPtr(fedInfo), intProperty, propertyValue); } /** @@ -2902,6 +2937,18 @@ public static void helicsPublicationPublishNamedPoint(SWIGTYPE_p_void pub, Strin helicsJNI.helicsPublicationPublishNamedPoint(SWIGTYPE_p_void.getCPtr(pub), field, val); } + /** + * Publish the contents of a helicsDataBuffer.
+ *
+ * @param pub The publication to publish for.
+ * @param buffer a HelicsDataBuffer object containing the data to publish
+ *
+ * ,out] err A pointer to an error object for catching errors. + */ + public static void helicsPublicationPublishDataBuffer(SWIGTYPE_p_void pub, SWIGTYPE_p_void buffer) { + helicsJNI.helicsPublicationPublishDataBuffer(SWIGTYPE_p_void.getCPtr(pub), SWIGTYPE_p_void.getCPtr(buffer)); + } + /** * Add a named input to the list of targets a publication publishes to.
*
@@ -2961,6 +3008,19 @@ public static void helicsInputGetBytes(SWIGTYPE_p_void ipt, SWIGTYPE_p_void data helicsJNI.helicsInputGetBytes(SWIGTYPE_p_void.getCPtr(ipt), SWIGTYPE_p_void.getCPtr(data), maxDataLength, actualSize); } + /** + * Get a copy of the raw data in a HelicsDataBuffer
+ *
+ * @param inp The input to get the data for.
+ *
+ * ,out] err A pointer to an error object for catching errors.
+ * @return A HelicsDataBuffer object containing the data + */ + public static SWIGTYPE_p_void helicsInputGetDataBuffer(SWIGTYPE_p_void inp) { + long cPtr = helicsJNI.helicsInputGetDataBuffer(SWIGTYPE_p_void.getCPtr(inp)); + return (cPtr == 0) ? null : new SWIGTYPE_p_void(cPtr, false); + } + /** * Get the size of a value for an input assuming return as a string.
*
@@ -4277,6 +4337,18 @@ public static SWIGTYPE_p_void helicsMessageGetBytesPointer(SWIGTYPE_p_void messa return (cPtr == 0) ? null : new SWIGTYPE_p_void(cPtr, false); } + /** + * Get a data buffer to the message object
+ *
+ * @param message A message object to get the dataBuffer for
+ *
+ * @return A HelicsDataBuffer object to the data in a message. Modifying the buffer will directly modify the message contents. + */ + public static SWIGTYPE_p_void helicsMessageDataBuffer(SWIGTYPE_p_void message) { + long cPtr = helicsJNI.helicsMessageDataBuffer(SWIGTYPE_p_void.getCPtr(message)); + return (cPtr == 0) ? null : new SWIGTYPE_p_void(cPtr, false); + } + /** * A check if the message contains a valid payload.
*
@@ -4423,6 +4495,18 @@ public static void helicsMessageSetData(SWIGTYPE_p_void message, SWIGTYPE_p_void helicsJNI.helicsMessageSetData(SWIGTYPE_p_void.getCPtr(message), SWIGTYPE_p_void.getCPtr(data), inputDataLength); } + /** + * Set the data payload of a message from a HelicsDataBuffer Object
+ *
+ * @param message The message object in question.
+ * @param data the dataBuffer containing the appropriate data, if null will clear the message payload
+ *
+ * ,out] err An error object to fill out in case of an error. + */ + public static void helicsMessageSetDataBuffer(SWIGTYPE_p_void message, SWIGTYPE_p_void data) { + helicsJNI.helicsMessageSetDataBuffer(SWIGTYPE_p_void.getCPtr(message), SWIGTYPE_p_void.getCPtr(data)); + } + /** * Append data to the payload.
*
diff --git a/interfaces/java/interface/helicsJNI.java b/interfaces/java/interface/helicsJNI.java index c58b6192c7..fd8e023e2b 100644 --- a/interfaces/java/interface/helicsJNI.java +++ b/interfaces/java/interface/helicsJNI.java @@ -205,18 +205,18 @@ public class helicsJNI { public final static native long helicsDataBufferData(long jarg1); public final static native int helicsDataBufferReserve(long jarg1, long jarg2); public final static native long helicsDataBufferClone(long jarg1); - public final static native long helicsIntegerToBytes(long jarg1, long jarg2); - public final static native long helicsDoubleToBytes(double jarg1, long jarg2); - public final static native long helicsStringToBytes(String jarg1, long jarg2); - public final static native long helicsRawStringToBytes(String jarg1, int jarg2, long jarg3); - public final static native long helicsBooleanToBytes(int jarg1, long jarg2); - public final static native long helicsCharToBytes(char jarg1, long jarg2); - public final static native long helicsTimeToBytes(double jarg1, long jarg2); - public final static native long helicsComplexToBytes(double jarg1, double jarg2, long jarg3); - public final static native long helicsComplexObjectToBytes(long jarg1, HelicsComplex jarg1_, long jarg2); - public final static native long helicsVectorToBytes(double[] jarg1, int jarg2, long jarg3); - public final static native long helicsNamedPointToBytes(String jarg1, double jarg2, long jarg3); - public final static native long helicsComplexVectorToBytes(double[] jarg1, int jarg2, long jarg3); + public final static native long helicsDataBufferFillFromInteger(long jarg1, long jarg2); + public final static native long helicsDataBufferFillFromDouble(long jarg1, double jarg2); + public final static native long helicsDataBufferFillFromString(long jarg1, String jarg2); + public final static native long helicsDataBufferFillFromRawString(long jarg1, String jarg2, int jarg3); + public final static native long helicsDataBufferFillFromBoolean(long jarg1, int jarg2); + public final static native long helicsDataBufferFillFromChar(long jarg1, char jarg2); + public final static native long helicsDataBufferFillFromTime(long jarg1, double jarg2); + public final static native long helicsDataBufferFillFromComplex(long jarg1, double jarg2, double jarg3); + public final static native long helicsDataBufferFillFromComplexObject(long jarg1, long jarg2, HelicsComplex jarg2_); + public final static native long helicsDataBufferFillFromVector(long jarg1, double[] jarg2, int jarg3); + public final static native long helicsDataBufferFillFromNamedPoint(long jarg1, String jarg2, double jarg3); + public final static native long helicsDataBufferFillFromComplexVector(long jarg1, double[] jarg2, int jarg3); public final static native int helicsDataBufferType(long jarg1); public final static native long helicsDataBufferToInteger(long jarg1); public final static native double helicsDataBufferToDouble(long jarg1); @@ -428,11 +428,13 @@ public class helicsJNI { public final static native void helicsPublicationPublishVector(long jarg1, double[] jarg2, int jarg3); public final static native void helicsPublicationPublishComplexVector(long jarg1, double[] jarg2, int jarg3); public final static native void helicsPublicationPublishNamedPoint(long jarg1, String jarg2, double jarg3); + public final static native void helicsPublicationPublishDataBuffer(long jarg1, long jarg2); public final static native void helicsPublicationAddTarget(long jarg1, String jarg2); public final static native int helicsInputIsValid(long jarg1); public final static native void helicsInputAddTarget(long jarg1, String jarg2); public final static native int helicsInputGetByteCount(long jarg1); public final static native void helicsInputGetBytes(long jarg1, long jarg2, int jarg3, int[] jarg4); + public final static native long helicsInputGetDataBuffer(long jarg1); public final static native int helicsInputGetStringSize(long jarg1); public final static native void helicsInputGetString(long jarg1, byte[] jarg2, int[] jarg4); public final static native long helicsInputGetInteger(long jarg1); @@ -539,6 +541,7 @@ public class helicsJNI { public final static native int helicsMessageGetByteCount(long jarg1); public final static native void helicsMessageGetBytes(long jarg1, long jarg2, int jarg3, int[] jarg4); public final static native long helicsMessageGetBytesPointer(long jarg1); + public final static native long helicsMessageDataBuffer(long jarg1); public final static native int helicsMessageIsValid(long jarg1); public final static native void helicsMessageSetSource(long jarg1, String jarg2); public final static native void helicsMessageSetDestination(long jarg1, String jarg2); @@ -551,6 +554,7 @@ public class helicsJNI { public final static native void helicsMessageSetFlagOption(long jarg1, int jarg2, int jarg3); public final static native void helicsMessageSetString(long jarg1, String jarg2); public final static native void helicsMessageSetData(long jarg1, long jarg2, int jarg3); + public final static native void helicsMessageSetDataBuffer(long jarg1, long jarg2); public final static native void helicsMessageAppendData(long jarg1, long jarg2, int jarg3); public final static native void helicsMessageCopy(long jarg1, long jarg2); public final static native long helicsMessageClone(long jarg1); diff --git a/interfaces/java/interface/helicsJava.c b/interfaces/java/interface/helicsJava.c index 5581c7832a..c1de5b36b9 100644 --- a/interfaces/java/interface/helicsJava.c +++ b/interfaces/java/interface/helicsJava.c @@ -2617,17 +2617,17 @@ SWIGEXPORT jlong JNICALL Java_com_java_helics_helicsJNI_helicsDataBufferClone(JN } -SWIGEXPORT jlong JNICALL Java_com_java_helics_helicsJNI_helicsIntegerToBytes(JNIEnv *jenv, jclass jcls, jlong jarg1, jlong jarg2) { +SWIGEXPORT jlong JNICALL Java_com_java_helics_helicsJNI_helicsDataBufferFillFromInteger(JNIEnv *jenv, jclass jcls, jlong jarg1, jlong jarg2) { jlong jresult = 0 ; - int64_t arg1 ; - HelicsDataBuffer arg2 = (HelicsDataBuffer) 0 ; + HelicsDataBuffer arg1 = (HelicsDataBuffer) 0 ; + int64_t arg2 ; int32_t result; (void)jenv; (void)jcls; - arg1 = (int64_t)jarg1; - arg2 = *(HelicsDataBuffer *)&jarg2; - result = helicsIntegerToBytes(arg1,arg2); + arg1 = *(HelicsDataBuffer *)&jarg1; + arg2 = (int64_t)jarg2; + result = helicsDataBufferFillFromInteger(arg1,arg2); { int32_t * resultptr = (int32_t *) malloc(sizeof(int32_t)); memmove(resultptr, &result, sizeof(int32_t)); @@ -2637,17 +2637,17 @@ SWIGEXPORT jlong JNICALL Java_com_java_helics_helicsJNI_helicsIntegerToBytes(JNI } -SWIGEXPORT jlong JNICALL Java_com_java_helics_helicsJNI_helicsDoubleToBytes(JNIEnv *jenv, jclass jcls, jdouble jarg1, jlong jarg2) { +SWIGEXPORT jlong JNICALL Java_com_java_helics_helicsJNI_helicsDataBufferFillFromDouble(JNIEnv *jenv, jclass jcls, jlong jarg1, jdouble jarg2) { jlong jresult = 0 ; - double arg1 ; - HelicsDataBuffer arg2 = (HelicsDataBuffer) 0 ; + HelicsDataBuffer arg1 = (HelicsDataBuffer) 0 ; + double arg2 ; int32_t result; (void)jenv; (void)jcls; - arg1 = (double)jarg1; - arg2 = *(HelicsDataBuffer *)&jarg2; - result = helicsDoubleToBytes(arg1,arg2); + arg1 = *(HelicsDataBuffer *)&jarg1; + arg2 = (double)jarg2; + result = helicsDataBufferFillFromDouble(arg1,arg2); { int32_t * resultptr = (int32_t *) malloc(sizeof(int32_t)); memmove(resultptr, &result, sizeof(int32_t)); @@ -2657,69 +2657,69 @@ SWIGEXPORT jlong JNICALL Java_com_java_helics_helicsJNI_helicsDoubleToBytes(JNIE } -SWIGEXPORT jlong JNICALL Java_com_java_helics_helicsJNI_helicsStringToBytes(JNIEnv *jenv, jclass jcls, jstring jarg1, jlong jarg2) { +SWIGEXPORT jlong JNICALL Java_com_java_helics_helicsJNI_helicsDataBufferFillFromString(JNIEnv *jenv, jclass jcls, jlong jarg1, jstring jarg2) { jlong jresult = 0 ; - char *arg1 = (char *) 0 ; - HelicsDataBuffer arg2 = (HelicsDataBuffer) 0 ; + HelicsDataBuffer arg1 = (HelicsDataBuffer) 0 ; + char *arg2 = (char *) 0 ; int32_t result; (void)jenv; (void)jcls; - arg1 = 0; - if (jarg1) { - arg1 = (char *)(*jenv)->GetStringUTFChars(jenv, jarg1, 0); - if (!arg1) return 0; + arg1 = *(HelicsDataBuffer *)&jarg1; + arg2 = 0; + if (jarg2) { + arg2 = (char *)(*jenv)->GetStringUTFChars(jenv, jarg2, 0); + if (!arg2) return 0; } - arg2 = *(HelicsDataBuffer *)&jarg2; - result = helicsStringToBytes((char const *)arg1,arg2); + result = helicsDataBufferFillFromString(arg1,(char const *)arg2); { int32_t * resultptr = (int32_t *) malloc(sizeof(int32_t)); memmove(resultptr, &result, sizeof(int32_t)); *(int32_t **)&jresult = resultptr; } - if (arg1) (*jenv)->ReleaseStringUTFChars(jenv, jarg1, (const char *)arg1); + if (arg2) (*jenv)->ReleaseStringUTFChars(jenv, jarg2, (const char *)arg2); return jresult; } -SWIGEXPORT jlong JNICALL Java_com_java_helics_helicsJNI_helicsRawStringToBytes(JNIEnv *jenv, jclass jcls, jstring jarg1, jint jarg2, jlong jarg3) { +SWIGEXPORT jlong JNICALL Java_com_java_helics_helicsJNI_helicsDataBufferFillFromRawString(JNIEnv *jenv, jclass jcls, jlong jarg1, jstring jarg2, jint jarg3) { jlong jresult = 0 ; - char *arg1 = (char *) 0 ; - int arg2 ; - HelicsDataBuffer arg3 = (HelicsDataBuffer) 0 ; + HelicsDataBuffer arg1 = (HelicsDataBuffer) 0 ; + char *arg2 = (char *) 0 ; + int arg3 ; int32_t result; (void)jenv; (void)jcls; - arg1 = 0; - if (jarg1) { - arg1 = (char *)(*jenv)->GetStringUTFChars(jenv, jarg1, 0); - if (!arg1) return 0; + arg1 = *(HelicsDataBuffer *)&jarg1; + arg2 = 0; + if (jarg2) { + arg2 = (char *)(*jenv)->GetStringUTFChars(jenv, jarg2, 0); + if (!arg2) return 0; } - arg2 = (int)jarg2; - arg3 = *(HelicsDataBuffer *)&jarg3; - result = helicsRawStringToBytes((char const *)arg1,arg2,arg3); + arg3 = (int)jarg3; + result = helicsDataBufferFillFromRawString(arg1,(char const *)arg2,arg3); { int32_t * resultptr = (int32_t *) malloc(sizeof(int32_t)); memmove(resultptr, &result, sizeof(int32_t)); *(int32_t **)&jresult = resultptr; } - if (arg1) (*jenv)->ReleaseStringUTFChars(jenv, jarg1, (const char *)arg1); + if (arg2) (*jenv)->ReleaseStringUTFChars(jenv, jarg2, (const char *)arg2); return jresult; } -SWIGEXPORT jlong JNICALL Java_com_java_helics_helicsJNI_helicsBooleanToBytes(JNIEnv *jenv, jclass jcls, jint jarg1, jlong jarg2) { +SWIGEXPORT jlong JNICALL Java_com_java_helics_helicsJNI_helicsDataBufferFillFromBoolean(JNIEnv *jenv, jclass jcls, jlong jarg1, jint jarg2) { jlong jresult = 0 ; - HelicsBool arg1 ; - HelicsDataBuffer arg2 = (HelicsDataBuffer) 0 ; + HelicsDataBuffer arg1 = (HelicsDataBuffer) 0 ; + HelicsBool arg2 ; int32_t result; (void)jenv; (void)jcls; - arg1 = (HelicsBool)jarg1; - arg2 = *(HelicsDataBuffer *)&jarg2; - result = helicsBooleanToBytes(arg1,arg2); + arg1 = *(HelicsDataBuffer *)&jarg1; + arg2 = (HelicsBool)jarg2; + result = helicsDataBufferFillFromBoolean(arg1,arg2); { int32_t * resultptr = (int32_t *) malloc(sizeof(int32_t)); memmove(resultptr, &result, sizeof(int32_t)); @@ -2729,17 +2729,17 @@ SWIGEXPORT jlong JNICALL Java_com_java_helics_helicsJNI_helicsBooleanToBytes(JNI } -SWIGEXPORT jlong JNICALL Java_com_java_helics_helicsJNI_helicsCharToBytes(JNIEnv *jenv, jclass jcls, jchar jarg1, jlong jarg2) { +SWIGEXPORT jlong JNICALL Java_com_java_helics_helicsJNI_helicsDataBufferFillFromChar(JNIEnv *jenv, jclass jcls, jlong jarg1, jchar jarg2) { jlong jresult = 0 ; - char arg1 ; - HelicsDataBuffer arg2 = (HelicsDataBuffer) 0 ; + HelicsDataBuffer arg1 = (HelicsDataBuffer) 0 ; + char arg2 ; int32_t result; (void)jenv; (void)jcls; - arg1 = (char)jarg1; - arg2 = *(HelicsDataBuffer *)&jarg2; - result = helicsCharToBytes(arg1,arg2); + arg1 = *(HelicsDataBuffer *)&jarg1; + arg2 = (char)jarg2; + result = helicsDataBufferFillFromChar(arg1,arg2); { int32_t * resultptr = (int32_t *) malloc(sizeof(int32_t)); memmove(resultptr, &result, sizeof(int32_t)); @@ -2749,17 +2749,17 @@ SWIGEXPORT jlong JNICALL Java_com_java_helics_helicsJNI_helicsCharToBytes(JNIEnv } -SWIGEXPORT jlong JNICALL Java_com_java_helics_helicsJNI_helicsTimeToBytes(JNIEnv *jenv, jclass jcls, jdouble jarg1, jlong jarg2) { +SWIGEXPORT jlong JNICALL Java_com_java_helics_helicsJNI_helicsDataBufferFillFromTime(JNIEnv *jenv, jclass jcls, jlong jarg1, jdouble jarg2) { jlong jresult = 0 ; - HelicsTime arg1 ; - HelicsDataBuffer arg2 = (HelicsDataBuffer) 0 ; + HelicsDataBuffer arg1 = (HelicsDataBuffer) 0 ; + HelicsTime arg2 ; int32_t result; (void)jenv; (void)jcls; - arg1 = (HelicsTime)jarg1; - arg2 = *(HelicsDataBuffer *)&jarg2; - result = helicsTimeToBytes(arg1,arg2); + arg1 = *(HelicsDataBuffer *)&jarg1; + arg2 = (HelicsTime)jarg2; + result = helicsDataBufferFillFromTime(arg1,arg2); { int32_t * resultptr = (int32_t *) malloc(sizeof(int32_t)); memmove(resultptr, &result, sizeof(int32_t)); @@ -2769,19 +2769,19 @@ SWIGEXPORT jlong JNICALL Java_com_java_helics_helicsJNI_helicsTimeToBytes(JNIEnv } -SWIGEXPORT jlong JNICALL Java_com_java_helics_helicsJNI_helicsComplexToBytes(JNIEnv *jenv, jclass jcls, jdouble jarg1, jdouble jarg2, jlong jarg3) { +SWIGEXPORT jlong JNICALL Java_com_java_helics_helicsJNI_helicsDataBufferFillFromComplex(JNIEnv *jenv, jclass jcls, jlong jarg1, jdouble jarg2, jdouble jarg3) { jlong jresult = 0 ; - double arg1 ; + HelicsDataBuffer arg1 = (HelicsDataBuffer) 0 ; double arg2 ; - HelicsDataBuffer arg3 = (HelicsDataBuffer) 0 ; + double arg3 ; int32_t result; (void)jenv; (void)jcls; - arg1 = (double)jarg1; + arg1 = *(HelicsDataBuffer *)&jarg1; arg2 = (double)jarg2; - arg3 = *(HelicsDataBuffer *)&jarg3; - result = helicsComplexToBytes(arg1,arg2,arg3); + arg3 = (double)jarg3; + result = helicsDataBufferFillFromComplex(arg1,arg2,arg3); { int32_t * resultptr = (int32_t *) malloc(sizeof(int32_t)); memmove(resultptr, &result, sizeof(int32_t)); @@ -2791,24 +2791,24 @@ SWIGEXPORT jlong JNICALL Java_com_java_helics_helicsJNI_helicsComplexToBytes(JNI } -SWIGEXPORT jlong JNICALL Java_com_java_helics_helicsJNI_helicsComplexObjectToBytes(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jlong jarg2) { +SWIGEXPORT jlong JNICALL Java_com_java_helics_helicsJNI_helicsDataBufferFillFromComplexObject(JNIEnv *jenv, jclass jcls, jlong jarg1, jlong jarg2, jobject jarg2_) { jlong jresult = 0 ; - HelicsComplex arg1 ; - HelicsDataBuffer arg2 = (HelicsDataBuffer) 0 ; - HelicsComplex *argp1 ; + HelicsDataBuffer arg1 = (HelicsDataBuffer) 0 ; + HelicsComplex arg2 ; + HelicsComplex *argp2 ; int32_t result; (void)jenv; (void)jcls; - (void)jarg1_; - argp1 = *(HelicsComplex **)&jarg1; - if (!argp1) { + (void)jarg2_; + arg1 = *(HelicsDataBuffer *)&jarg1; + argp2 = *(HelicsComplex **)&jarg2; + if (!argp2) { SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "Attempt to dereference null HelicsComplex"); return 0; } - arg1 = *argp1; - arg2 = *(HelicsDataBuffer *)&jarg2; - result = helicsComplexObjectToBytes(arg1,arg2); + arg2 = *argp2; + result = helicsDataBufferFillFromComplexObject(arg1,arg2); { int32_t * resultptr = (int32_t *) malloc(sizeof(int32_t)); memmove(resultptr, &result, sizeof(int32_t)); @@ -2818,105 +2818,105 @@ SWIGEXPORT jlong JNICALL Java_com_java_helics_helicsJNI_helicsComplexObjectToByt } -SWIGEXPORT jlong JNICALL Java_com_java_helics_helicsJNI_helicsVectorToBytes(JNIEnv *jenv, jclass jcls, jdoubleArray jarg1, jint jarg2, jlong jarg3) { +SWIGEXPORT jlong JNICALL Java_com_java_helics_helicsJNI_helicsDataBufferFillFromVector(JNIEnv *jenv, jclass jcls, jlong jarg1, jdoubleArray jarg2, jint jarg3) { jlong jresult = 0 ; - double *arg1 = (double *) 0 ; - int arg2 ; - HelicsDataBuffer arg3 = (HelicsDataBuffer) 0 ; - double temp1 ; + HelicsDataBuffer arg1 = (HelicsDataBuffer) 0 ; + double *arg2 = (double *) 0 ; + int arg3 ; + double temp2 ; int32_t result; (void)jenv; (void)jcls; + arg1 = *(HelicsDataBuffer *)&jarg1; { - if (!jarg1) { + if (!jarg2) { SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "array null"); return 0; } - if ((*jenv)->GetArrayLength(jenv, jarg1) == 0) { + if ((*jenv)->GetArrayLength(jenv, jarg2) == 0) { SWIG_JavaThrowException(jenv, SWIG_JavaIndexOutOfBoundsException, "Array must contain at least 1 element"); return 0; } - temp1 = (double)0; - arg1 = &temp1; + temp2 = (double)0; + arg2 = &temp2; } - arg2 = (int)jarg2; - arg3 = *(HelicsDataBuffer *)&jarg3; - result = helicsVectorToBytes((double const *)arg1,arg2,arg3); + arg3 = (int)jarg3; + result = helicsDataBufferFillFromVector(arg1,(double const *)arg2,arg3); { int32_t * resultptr = (int32_t *) malloc(sizeof(int32_t)); memmove(resultptr, &result, sizeof(int32_t)); *(int32_t **)&jresult = resultptr; } { - jdouble jvalue = (jdouble)temp1; - (*jenv)->SetDoubleArrayRegion(jenv, jarg1, 0, 1, &jvalue); + jdouble jvalue = (jdouble)temp2; + (*jenv)->SetDoubleArrayRegion(jenv, jarg2, 0, 1, &jvalue); } return jresult; } -SWIGEXPORT jlong JNICALL Java_com_java_helics_helicsJNI_helicsNamedPointToBytes(JNIEnv *jenv, jclass jcls, jstring jarg1, jdouble jarg2, jlong jarg3) { +SWIGEXPORT jlong JNICALL Java_com_java_helics_helicsJNI_helicsDataBufferFillFromNamedPoint(JNIEnv *jenv, jclass jcls, jlong jarg1, jstring jarg2, jdouble jarg3) { jlong jresult = 0 ; - char *arg1 = (char *) 0 ; - double arg2 ; - HelicsDataBuffer arg3 = (HelicsDataBuffer) 0 ; + HelicsDataBuffer arg1 = (HelicsDataBuffer) 0 ; + char *arg2 = (char *) 0 ; + double arg3 ; int32_t result; (void)jenv; (void)jcls; - arg1 = 0; - if (jarg1) { - arg1 = (char *)(*jenv)->GetStringUTFChars(jenv, jarg1, 0); - if (!arg1) return 0; + arg1 = *(HelicsDataBuffer *)&jarg1; + arg2 = 0; + if (jarg2) { + arg2 = (char *)(*jenv)->GetStringUTFChars(jenv, jarg2, 0); + if (!arg2) return 0; } - arg2 = (double)jarg2; - arg3 = *(HelicsDataBuffer *)&jarg3; - result = helicsNamedPointToBytes((char const *)arg1,arg2,arg3); + arg3 = (double)jarg3; + result = helicsDataBufferFillFromNamedPoint(arg1,(char const *)arg2,arg3); { int32_t * resultptr = (int32_t *) malloc(sizeof(int32_t)); memmove(resultptr, &result, sizeof(int32_t)); *(int32_t **)&jresult = resultptr; } - if (arg1) (*jenv)->ReleaseStringUTFChars(jenv, jarg1, (const char *)arg1); + if (arg2) (*jenv)->ReleaseStringUTFChars(jenv, jarg2, (const char *)arg2); return jresult; } -SWIGEXPORT jlong JNICALL Java_com_java_helics_helicsJNI_helicsComplexVectorToBytes(JNIEnv *jenv, jclass jcls, jdoubleArray jarg1, jint jarg2, jlong jarg3) { +SWIGEXPORT jlong JNICALL Java_com_java_helics_helicsJNI_helicsDataBufferFillFromComplexVector(JNIEnv *jenv, jclass jcls, jlong jarg1, jdoubleArray jarg2, jint jarg3) { jlong jresult = 0 ; - double *arg1 = (double *) 0 ; - int arg2 ; - HelicsDataBuffer arg3 = (HelicsDataBuffer) 0 ; - double temp1 ; + HelicsDataBuffer arg1 = (HelicsDataBuffer) 0 ; + double *arg2 = (double *) 0 ; + int arg3 ; + double temp2 ; int32_t result; (void)jenv; (void)jcls; + arg1 = *(HelicsDataBuffer *)&jarg1; { - if (!jarg1) { + if (!jarg2) { SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "array null"); return 0; } - if ((*jenv)->GetArrayLength(jenv, jarg1) == 0) { + if ((*jenv)->GetArrayLength(jenv, jarg2) == 0) { SWIG_JavaThrowException(jenv, SWIG_JavaIndexOutOfBoundsException, "Array must contain at least 1 element"); return 0; } - temp1 = (double)0; - arg1 = &temp1; + temp2 = (double)0; + arg2 = &temp2; } - arg2 = (int)jarg2; - arg3 = *(HelicsDataBuffer *)&jarg3; - result = helicsComplexVectorToBytes((double const *)arg1,arg2,arg3); + arg3 = (int)jarg3; + result = helicsDataBufferFillFromComplexVector(arg1,(double const *)arg2,arg3); { int32_t * resultptr = (int32_t *) malloc(sizeof(int32_t)); memmove(resultptr, &result, sizeof(int32_t)); *(int32_t **)&jresult = resultptr; } { - jdouble jvalue = (jdouble)temp1; - (*jenv)->SetDoubleArrayRegion(jenv, jarg1, 0, 1, &jvalue); + jdouble jvalue = (jdouble)temp2; + (*jenv)->SetDoubleArrayRegion(jenv, jarg2, 0, 1, &jvalue); } return jresult; @@ -8680,6 +8680,31 @@ SWIGEXPORT void JNICALL Java_com_java_helics_helicsJNI_helicsPublicationPublishN } +SWIGEXPORT void JNICALL Java_com_java_helics_helicsJNI_helicsPublicationPublishDataBuffer(JNIEnv *jenv, jclass jcls, jlong jarg1, jlong jarg2) { + HelicsPublication arg1 = (HelicsPublication) 0 ; + HelicsDataBuffer arg2 = (HelicsDataBuffer) 0 ; + HelicsError *arg3 = (HelicsError *) 0 ; + HelicsError etemp3 ; + + (void)jenv; + (void)jcls; + { + etemp3=helicsErrorInitialize(); + arg3=&etemp3; + } + arg1 = *(HelicsPublication *)&jarg1; + arg2 = *(HelicsDataBuffer *)&jarg2; + helicsPublicationPublishDataBuffer(arg1,arg2,arg3); + { + if (arg3->error_code!=HELICS_OK) + { + jclass clazz = (*jenv)->FindClass(jenv, "java/lang/Exception"); + (*jenv)->ThrowNew(jenv, clazz, arg3->message); + } + } +} + + SWIGEXPORT void JNICALL Java_com_java_helics_helicsJNI_helicsPublicationAddTarget(JNIEnv *jenv, jclass jcls, jlong jarg1, jstring jarg2) { HelicsPublication arg1 = (HelicsPublication) 0 ; char *arg2 = (char *) 0 ; @@ -8814,6 +8839,33 @@ SWIGEXPORT void JNICALL Java_com_java_helics_helicsJNI_helicsInputGetBytes(JNIEn } +SWIGEXPORT jlong JNICALL Java_com_java_helics_helicsJNI_helicsInputGetDataBuffer(JNIEnv *jenv, jclass jcls, jlong jarg1) { + jlong jresult = 0 ; + HelicsInput arg1 = (HelicsInput) 0 ; + HelicsError *arg2 = (HelicsError *) 0 ; + HelicsError etemp2 ; + HelicsDataBuffer result; + + (void)jenv; + (void)jcls; + { + etemp2=helicsErrorInitialize(); + arg2=&etemp2; + } + arg1 = *(HelicsInput *)&jarg1; + result = (HelicsDataBuffer)helicsInputGetDataBuffer(arg1,arg2); + *(HelicsDataBuffer *)&jresult = result; + { + if (arg2->error_code!=HELICS_OK) + { + jclass clazz = (*jenv)->FindClass(jenv, "java/lang/Exception"); + (*jenv)->ThrowNew(jenv, clazz, arg2->message); + } + } + return jresult; +} + + SWIGEXPORT jint JNICALL Java_com_java_helics_helicsJNI_helicsInputGetStringSize(JNIEnv *jenv, jclass jcls, jlong jarg1) { jint jresult = 0 ; HelicsInput arg1 = (HelicsInput) 0 ; @@ -11361,6 +11413,33 @@ SWIGEXPORT jlong JNICALL Java_com_java_helics_helicsJNI_helicsMessageGetBytesPoi } +SWIGEXPORT jlong JNICALL Java_com_java_helics_helicsJNI_helicsMessageDataBuffer(JNIEnv *jenv, jclass jcls, jlong jarg1) { + jlong jresult = 0 ; + HelicsMessage arg1 = (HelicsMessage) 0 ; + HelicsError *arg2 = (HelicsError *) 0 ; + HelicsError etemp2 ; + HelicsDataBuffer result; + + (void)jenv; + (void)jcls; + { + etemp2=helicsErrorInitialize(); + arg2=&etemp2; + } + arg1 = *(HelicsMessage *)&jarg1; + result = (HelicsDataBuffer)helicsMessageDataBuffer(arg1,arg2); + *(HelicsDataBuffer *)&jresult = result; + { + if (arg2->error_code!=HELICS_OK) + { + jclass clazz = (*jenv)->FindClass(jenv, "java/lang/Exception"); + (*jenv)->ThrowNew(jenv, clazz, arg2->message); + } + } + return jresult; +} + + SWIGEXPORT jint JNICALL Java_com_java_helics_helicsJNI_helicsMessageIsValid(JNIEnv *jenv, jclass jcls, jlong jarg1) { jint jresult = 0 ; HelicsMessage arg1 = (HelicsMessage) 0 ; @@ -11670,6 +11749,31 @@ SWIGEXPORT void JNICALL Java_com_java_helics_helicsJNI_helicsMessageSetData(JNIE } +SWIGEXPORT void JNICALL Java_com_java_helics_helicsJNI_helicsMessageSetDataBuffer(JNIEnv *jenv, jclass jcls, jlong jarg1, jlong jarg2) { + HelicsMessage arg1 = (HelicsMessage) 0 ; + HelicsDataBuffer arg2 = (HelicsDataBuffer) 0 ; + HelicsError *arg3 = (HelicsError *) 0 ; + HelicsError etemp3 ; + + (void)jenv; + (void)jcls; + { + etemp3=helicsErrorInitialize(); + arg3=&etemp3; + } + arg1 = *(HelicsMessage *)&jarg1; + arg2 = *(HelicsDataBuffer *)&jarg2; + helicsMessageSetDataBuffer(arg1,arg2,arg3); + { + if (arg3->error_code!=HELICS_OK) + { + jclass clazz = (*jenv)->FindClass(jenv, "java/lang/Exception"); + (*jenv)->ThrowNew(jenv, clazz, arg3->message); + } + } +} + + SWIGEXPORT void JNICALL Java_com_java_helics_helicsJNI_helicsMessageAppendData(JNIEnv *jenv, jclass jcls, jlong jarg1, jlong jarg2, jint jarg3) { HelicsMessage arg1 = (HelicsMessage) 0 ; void *arg2 = (void *) 0 ; diff --git a/interfaces/octave/CMakeLists.txt b/interfaces/octave/CMakeLists.txt index bccb76df71..76452a2b84 100644 --- a/interfaces/octave/CMakeLists.txt +++ b/interfaces/octave/CMakeLists.txt @@ -1,5 +1,5 @@ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Copyright (c) 2017-2023, Battelle Memorial Institute; Lawrence Livermore +# Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore # National Security, LLC; Alliance for Sustainable Energy, LLC. # See the top-level NOTICE for additional details. # All rights reserved. diff --git a/scripts/cmake-format-helper.py b/scripts/cmake-format-helper.py index 915d514e29..a310d19f13 100755 --- a/scripts/cmake-format-helper.py +++ b/scripts/cmake-format-helper.py @@ -34,5 +34,4 @@ def main(): if __name__ == "__main__": - main() diff --git a/scripts/fix_install_names.py b/scripts/fix_install_names.py index 0c9f21611a..60d07751a2 100755 --- a/scripts/fix_install_names.py +++ b/scripts/fix_install_names.py @@ -10,7 +10,6 @@ def get_libraries(executable, substring): - output = subprocess.check_output(shlex.split("otool -L {}".format(executable))).decode("utf-8") print(output) @@ -28,7 +27,6 @@ def get_libraries(executable, substring): def fix_install_name(executable, with_rpath=True): - BOOST_LIBRARIES = get_libraries(executable, "boost") for library in BOOST_LIBRARIES: @@ -46,7 +44,6 @@ def fix_install_name(executable, with_rpath=True): subprocess.call(shlex.split(cmd)) if with_rpath is True: - rpaths = [] for d in ["zmq", "boost"]: rpaths.append("{}".format(os.path.abspath(os.path.join(DEPENDENCIES, d, "lib")))) @@ -57,7 +54,6 @@ def fix_install_name(executable, with_rpath=True): def main(executable_directory=None): - print("Fixing install names ...") if executable_directory is None: @@ -70,13 +66,11 @@ def main(executable_directory=None): if filename.startswith("helics_") and os.access( os.path.abspath(os.path.join(APPS, filename)), os.X_OK ): - print("Fixing for {}".format(filename)) fix_install_name(os.path.abspath(os.path.join(APPS, filename))) if __name__ == "__main__": - import sys try: diff --git a/scripts/generateHelicsH.py b/scripts/generateHelicsH.py index 1a1887dd37..0b24f6ced1 100755 --- a/scripts/generateHelicsH.py +++ b/scripts/generateHelicsH.py @@ -24,7 +24,7 @@ outfile = open(os.path.join(outpath, "helics.h"), "w") outfile.write("/*\n") -outfile.write("Copyright (c) 2017-2023,\n") +outfile.write("Copyright (c) 2017-2024,\n") outfile.write( "Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for\n" ) @@ -111,7 +111,7 @@ outfile2 = open(os.path.join(outpath, "helics_api.h"), "w") outfile2.write("/*\n") -outfile2.write("Copyright (c) 2017-2023,\n") +outfile2.write("Copyright (c) 2017-2024,\n") outfile2.write( "Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for\n" ) diff --git a/scripts/git-all-archive.py b/scripts/git-all-archive.py index 705f057df3..5815bf0436 100755 --- a/scripts/git-all-archive.py +++ b/scripts/git-all-archive.py @@ -106,7 +106,6 @@ def SendFile(FILENAME, CLONE, RELEASE, TOKEN, CLIENTID, CLIENTSECRET): # main program ## def main(): - # Setup arguments DESCRIPTION = """ Store an extraneous binary file code in the github release page. @@ -173,7 +172,6 @@ def main(): # Clone repository into ./HELICS by default # if CLONE is not None: - if TOPATH is None: TOPATH = "./HELICS" if os.path.exists(TOPATH): diff --git a/scripts/render-doxyfile.py b/scripts/render-doxyfile.py index b79625858b..b564c698c0 100644 --- a/scripts/render-doxyfile.py +++ b/scripts/render-doxyfile.py @@ -4,7 +4,6 @@ def get_version(): - with open(os.path.join(dirname, "../CMakeLists.txt")) as f: data = f.read() @@ -16,7 +15,6 @@ def get_version(): def main(): - helics_version = get_version() current_source_dir = os.path.abspath(os.path.join(dirname, "../")) output_dir = os.path.abspath(os.path.join(dirname, "../build-doxygen/docs")) @@ -38,5 +36,4 @@ def main(): if __name__ == "__main__": - main() diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 31dac6c8cd..a764772357 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,5 +1,5 @@ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Copyright (c) 2017-2023, Battelle Memorial Institute; Lawrence Livermore +# Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore # National Security, LLC; Alliance for Sustainable Energy, LLC. # See the top-level NOTICE for additional details. # All rights reserved. diff --git a/src/empty.cpp b/src/empty.cpp index 5d149e67bc..57dc1f5816 100644 --- a/src/empty.cpp +++ b/src/empty.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/CMakeLists.txt b/src/helics/CMakeLists.txt index 4d66fdb6b0..9bfb8bac57 100644 --- a/src/helics/CMakeLists.txt +++ b/src/helics/CMakeLists.txt @@ -1,5 +1,5 @@ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Copyright (c) 2017-2023, Battelle Memorial Institute; Lawrence Livermore +# Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore # National Security, LLC; Alliance for Sustainable Energy, LLC. # See the top-level NOTICE for additional details. # All rights reserved. @@ -72,6 +72,9 @@ if(NOT HELICS_DISABLE_C_SHARED_LIB) add_subdirectory(cpp98) if(NOT CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME) - set_target_properties(helics helicsCpp98_ide PROPERTIES FOLDER helics) + set_target_properties(helics PROPERTIES FOLDER helics) + if(TARGET helicsCpp98_ide) + set_target_properties(helicsCpp98_ide PROPERTIES FOLDER helics) + endif() endif() endif() diff --git a/src/helics/MessageFederates.hpp b/src/helics/MessageFederates.hpp index f8bc6eae08..324a043f97 100644 --- a/src/helics/MessageFederates.hpp +++ b/src/helics/MessageFederates.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/ValueFederates.hpp b/src/helics/ValueFederates.hpp index 61bc8bd7cf..9595e0a25e 100644 --- a/src/helics/ValueFederates.hpp +++ b/src/helics/ValueFederates.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/application_api.hpp b/src/helics/application_api.hpp index bcee18e215..e91033f4ff 100644 --- a/src/helics/application_api.hpp +++ b/src/helics/application_api.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/application_api/AsyncFedCallInfo.hpp b/src/helics/application_api/AsyncFedCallInfo.hpp index 3a5eee17c5..e8f9f76a7b 100644 --- a/src/helics/application_api/AsyncFedCallInfo.hpp +++ b/src/helics/application_api/AsyncFedCallInfo.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/application_api/BrokerApp.cpp b/src/helics/application_api/BrokerApp.cpp index f68f95b0c9..a1acc3425f 100644 --- a/src/helics/application_api/BrokerApp.cpp +++ b/src/helics/application_api/BrokerApp.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/application_api/BrokerApp.hpp b/src/helics/application_api/BrokerApp.hpp index a245c5a105..2752597ad5 100644 --- a/src/helics/application_api/BrokerApp.hpp +++ b/src/helics/application_api/BrokerApp.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -87,7 +87,7 @@ class HELICS_CXX_EXPORT BrokerApp { */ bool isOpenToNewFederates() const; - /** forceably disconnect the broker*/ + /** forcibly disconnect the broker*/ void forceTerminate(); /** wait for the broker to normally disconnect for a certain amount of time*/ bool waitForDisconnect(std::chrono::milliseconds waitTime = std::chrono::milliseconds(0)); diff --git a/src/helics/application_api/CMakeLists.txt b/src/helics/application_api/CMakeLists.txt index 1b158ba4a7..b67887c902 100644 --- a/src/helics/application_api/CMakeLists.txt +++ b/src/helics/application_api/CMakeLists.txt @@ -1,5 +1,5 @@ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Copyright (c) 2017-2023, Battelle Memorial Institute; Lawrence Livermore +# Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore # National Security, LLC; Alliance for Sustainable Energy, LLC. # See the top-level NOTICE for additional details. # All rights reserved. diff --git a/src/helics/application_api/CallbackFederate.cpp b/src/helics/application_api/CallbackFederate.cpp index 7785ebdf2c..187d2dc555 100644 --- a/src/helics/application_api/CallbackFederate.cpp +++ b/src/helics/application_api/CallbackFederate.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/application_api/CallbackFederate.hpp b/src/helics/application_api/CallbackFederate.hpp index 4abdd51353..fa6722f0b7 100644 --- a/src/helics/application_api/CallbackFederate.hpp +++ b/src/helics/application_api/CallbackFederate.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/application_api/CombinationFederate.cpp b/src/helics/application_api/CombinationFederate.cpp index 1f4bde66a6..1d171fc402 100644 --- a/src/helics/application_api/CombinationFederate.cpp +++ b/src/helics/application_api/CombinationFederate.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -17,16 +17,16 @@ CombinationFederate::CombinationFederate(std::string_view fedName, const Federat } CombinationFederate::CombinationFederate(std::string_view fedName, const std::shared_ptr& core, - const FederateInfo& fi): - Federate(fedName, core, fi), + const FederateInfo& fedInfo): + Federate(fedName, core, fedInfo), ValueFederate(true), MessageFederate(true) { } CombinationFederate::CombinationFederate(std::string_view fedName, CoreApp& core, - const FederateInfo& fi): - Federate(fedName, core, fi), + const FederateInfo& fedInfo): + Federate(fedName, core, fedInfo), ValueFederate(true), MessageFederate(true) { } @@ -35,13 +35,11 @@ CombinationFederate::CombinationFederate(const std::string& configString): Federate(std::string_view{}, loadFederateInfo(configString)), ValueFederate(true), MessageFederate(true) { - CombinationFederate::registerInterfaces(configString); } CombinationFederate::CombinationFederate(std::string_view fedName, const std::string& configString): Federate(fedName, loadFederateInfo(configString)), ValueFederate(true), MessageFederate(true) { - CombinationFederate::registerInterfaces(configString); } CombinationFederate::CombinationFederate(CombinationFederate&&) noexcept = default; diff --git a/src/helics/application_api/CombinationFederate.hpp b/src/helics/application_api/CombinationFederate.hpp index a1e451696a..7c83e7cd89 100644 --- a/src/helics/application_api/CombinationFederate.hpp +++ b/src/helics/application_api/CombinationFederate.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -21,28 +21,31 @@ class HELICS_CXX_EXPORT CombinationFederate: public ValueFederate, public Messag CombinationFederate(); /**constructor taking a federate information structure and using the default core - @param fedName the name of the federate, may be left empty to use a default or one found in fi - @param fi a federate information structure + @param fedName the name of the federate, may be left empty to use a default or one found in + fedInfo + @param fedInfo a federate information structure */ - explicit CombinationFederate(std::string_view fedName, const FederateInfo& fi); + explicit CombinationFederate(std::string_view fedName, const FederateInfo& fedInfo); /**constructor taking a federate information structure and using the given core - @param fedName the name of the federate, may be left empty to use a default or one found in fi + @param fedName the name of the federate, may be left empty to use a default or one found in + fedInfo @param core a pointer to core object which the federate can join - @param fi a federate information structure + @param fedInfo a federate information structure */ CombinationFederate(std::string_view fedName, const std::shared_ptr& core, - const FederateInfo& fi = FederateInfo{}); + const FederateInfo& fedInfo = FederateInfo{}); /**constructor taking a federate information structure and using the given CoreApp - @param fedName the name of the federate, may be left empty to use a default or one found in fi + @param fedName the name of the federate, may be left empty to use a default or one found in + fedInfo @param core a CoreApp object representing the core to connect to - @param fi a federate information structure + @param fedInfo a federate information structure */ CombinationFederate(std::string_view fedName, CoreApp& core, - const FederateInfo& fi = FederateInfo{}); + const FederateInfo& fedInfo = FederateInfo{}); /**constructor taking a federate name and a file with the required information @param fedName the name of the federate, can be empty to use the name from the configString diff --git a/src/helics/application_api/ConnectorFederateManager.cpp b/src/helics/application_api/ConnectorFederateManager.cpp index 3cb2a42eed..7d74edae9d 100644 --- a/src/helics/application_api/ConnectorFederateManager.cpp +++ b/src/helics/application_api/ConnectorFederateManager.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/application_api/ConnectorFederateManager.hpp b/src/helics/application_api/ConnectorFederateManager.hpp index 6487310498..e885d96929 100644 --- a/src/helics/application_api/ConnectorFederateManager.hpp +++ b/src/helics/application_api/ConnectorFederateManager.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/application_api/CoreApp.cpp b/src/helics/application_api/CoreApp.cpp index 82e37583d9..118c84c648 100644 --- a/src/helics/application_api/CoreApp.cpp +++ b/src/helics/application_api/CoreApp.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/application_api/CoreApp.hpp b/src/helics/application_api/CoreApp.hpp index 4293bb36e7..3adeedd05e 100644 --- a/src/helics/application_api/CoreApp.hpp +++ b/src/helics/application_api/CoreApp.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -87,7 +87,7 @@ class HELICS_CXX_EXPORT CoreApp { /** check if the broker is ready to accept new federates or cores */ bool isOpenToNewFederates() const; - /** forceably disconnect the core*/ + /** forcibly disconnect the core*/ void forceTerminate(); /** wait for the core to normally disconnect for a certain amount of time*/ bool waitForDisconnect(std::chrono::milliseconds waitTime = std::chrono::milliseconds(0)); @@ -125,7 +125,7 @@ class HELICS_CXX_EXPORT CoreApp { queryable through a "tags" query or "tag/" @param tag the name of the tag to set the value for @param value the value for the given tag*/ - void setTag(std::string_view tag, std::string_view value); + void setTag(std::string_view tag, std::string_view value = "true"); /** get the value of a specific tag (key-value pair) for a core @details the tag is an arbitrary user defined string and value; the tags for a core are queryable @@ -141,7 +141,7 @@ class HELICS_CXX_EXPORT CoreApp { @param valueName the name of the global to set @param value the value of the global */ - void setGlobal(std::string_view valueName, std::string_view value); + void setGlobal(std::string_view valueName, std::string_view value = "true"); /** send a command to a specific target @details the format is somewhat unspecified; target is the name of an object, typically one of diff --git a/src/helics/application_api/Endpoints.cpp b/src/helics/application_api/Endpoints.cpp index 256dd5db6b..b78cb50c1d 100644 --- a/src/helics/application_api/Endpoints.cpp +++ b/src/helics/application_api/Endpoints.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -13,8 +13,8 @@ SPDX-License-Identifier: BSD-3-Clause namespace helics { -Endpoint::Endpoint(MessageFederate* mFed, std::string_view name, InterfaceHandle id): - Interface(mFed, id, name), fed(mFed) +Endpoint::Endpoint(MessageFederate* mFed, std::string_view name, InterfaceHandle hid): + Interface(mFed, hid, name), fed(mFed) { } @@ -39,7 +39,7 @@ void Endpoint::send(const char* data, size_t data_size) const { if ((fed->getCurrentMode() == Federate::Modes::EXECUTING) || (fed->getCurrentMode() == Federate::Modes::INITIALIZING)) { - cr->send(handle, data, data_size); + mCore->send(handle, data, data_size); } else { throw(InvalidFunctionCall( "messages not allowed outside of execution and initialization mode")); @@ -53,7 +53,7 @@ void Endpoint::sendTo(const char* data, size_t data_size, std::string_view dest) if (dest.empty()) { dest = defDest; } - cr->sendTo(handle, data, data_size, dest); + mCore->sendTo(handle, data, data_size, dest); } else { throw(InvalidFunctionCall( "messages not allowed outside of execution and initialization mode")); @@ -64,7 +64,7 @@ void Endpoint::sendAt(const char* data, size_t data_size, Time sendTime) const { if ((fed->getCurrentMode() == Federate::Modes::EXECUTING) || (fed->getCurrentMode() == Federate::Modes::INITIALIZING)) { - cr->sendAt(handle, data, data_size, sendTime); + mCore->sendAt(handle, data, data_size, sendTime); } else { throw(InvalidFunctionCall( "messages not allowed outside of execution and initialization mode")); @@ -81,7 +81,7 @@ void Endpoint::sendToAt(const char* data, if (dest.empty()) { dest = defDest; } - cr->sendToAt(handle, data, data_size, dest, sendTime); + mCore->sendToAt(handle, data, data_size, dest, sendTime); } else { throw(InvalidFunctionCall( "messages not allowed outside of execution and initialization mode")); @@ -95,7 +95,7 @@ void Endpoint::send(const void* data, size_t data_size) const { if ((fed->getCurrentMode() == Federate::Modes::EXECUTING) || (fed->getCurrentMode() == Federate::Modes::INITIALIZING)) { - cr->send(handle, data, data_size); + mCore->send(handle, data, data_size); } else { throw(InvalidFunctionCall( "messages not allowed outside of execution and initialization mode")); @@ -110,7 +110,7 @@ void Endpoint::send(std::unique_ptr mess) const if (mess->dest.empty()) { mess->dest = defDest; } - cr->sendMessage(handle, std::move(mess)); + mCore->sendMessage(handle, std::move(mess)); } else { throw(InvalidFunctionCall( "messages not allowed outside of execution and initialization mode")); @@ -127,12 +127,12 @@ void Endpoint::setDefaultDestination(std::string_view target) const std::string& Endpoint::getDefaultDestination() const { - return (!defDest.empty()) ? defDest : cr->getDestinationTargets(handle); + return (!defDest.empty()) ? defDest : mCore->getDestinationTargets(handle); } void Endpoint::subscribe(std::string_view key) { - cr->addSourceTarget(handle, key, helics::InterfaceType::PUBLICATION); + mCore->addSourceTarget(handle, key, helics::InterfaceType::PUBLICATION); } std::unique_ptr Endpoint::getMessage() const @@ -162,20 +162,20 @@ void Endpoint::setCallback(const std::function& cal /** add a named filter to an endpoint for all messages coming from the endpoint*/ void Endpoint::addSourceFilter(std::string_view filterName) { - cr->addSourceTarget(handle, filterName, InterfaceType::FILTER); + mCore->addSourceTarget(handle, filterName, InterfaceType::FILTER); } /** add a named filter to an endpoint for all messages going to the endpoint*/ void Endpoint::addDestinationFilter(std::string_view filterName) { - cr->addDestinationTarget(handle, filterName, InterfaceType::FILTER); + mCore->addDestinationTarget(handle, filterName, InterfaceType::FILTER); } void Endpoint::addSourceEndpoint(std::string_view endpointName) { - cr->addSourceTarget(handle, endpointName, InterfaceType::ENDPOINT); + mCore->addSourceTarget(handle, endpointName, InterfaceType::ENDPOINT); } void Endpoint::addDestinationEndpoint(std::string_view endpointName) { - cr->addDestinationTarget(handle, endpointName, InterfaceType::ENDPOINT); + mCore->addDestinationTarget(handle, endpointName, InterfaceType::ENDPOINT); } } // namespace helics diff --git a/src/helics/application_api/Endpoints.hpp b/src/helics/application_api/Endpoints.hpp index e1f1ea99a0..dd29c493ca 100644 --- a/src/helics/application_api/Endpoints.hpp +++ b/src/helics/application_api/Endpoints.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -31,7 +31,7 @@ class HELICS_CXX_EXPORT Endpoint: public Interface { Endpoint() = default; /**/ // constructor used by messageFederateManager - Endpoint(MessageFederate* mFed, std::string_view name, InterfaceHandle id); + Endpoint(MessageFederate* mFed, std::string_view name, InterfaceHandle hid); Endpoint(MessageFederate* mFed, std::string_view name, diff --git a/src/helics/application_api/Federate.cpp b/src/helics/application_api/Federate.cpp index 96ec87a65f..d0d29696ce 100644 --- a/src/helics/application_api/Federate.cpp +++ b/src/helics/application_api/Federate.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -10,7 +10,6 @@ SPDX-License-Identifier: BSD-3-Clause #include "../common/JsonGeneration.hpp" #include "../common/addTargets.hpp" #include "../common/configFileHelpers.hpp" -#include "../common/fmt_format.h" #include "../core/BrokerFactory.hpp" #include "../core/Core.hpp" #include "../core/CoreFactory.hpp" @@ -26,6 +25,7 @@ SPDX-License-Identifier: BSD-3-Clause #include "helics/helics-config.h" #include +#include #include #include #include @@ -42,141 +42,42 @@ void cleanupHelicsLibrary() BrokerFactory::cleanUpBrokers(100ms); } -Federate::Federate(std::string_view fedName, const FederateInfo& fi): mName(fedName) +Federate::Federate(std::string_view fedName, const FederateInfo& fedInfo): mName(fedName) { if (mName.empty()) { - mName = fi.defName; + mName = fedInfo.defName; } - singleThreadFederate = fi.checkFlagProperty(defs::Flags::SINGLE_THREAD_FEDERATE, false); + getCore(fedInfo); - if (fi.coreName.empty()) { - if (!fi.forceNewCore) { - coreObject = CoreFactory::findJoinableCoreOfType(fi.coreType); - } - if (!coreObject) { - if (!mName.empty()) { - std::string cname = - fmt::format("{}_core_{}", fedName, gmlc::utilities::randomString(6)); - - try { - coreObject = - CoreFactory::create(fi.coreType, cname, generateFullCoreInitString(fi)); - } - catch (const helics::RegistrationFailure&) { - // there is a possibility of race condition here in the naming resulting a - // failure this catches and reverts to previous naming which is fully randomly - // generated - coreObject = CoreFactory::create(fi.coreType, generateFullCoreInitString(fi)); - } - } else { - coreObject = CoreFactory::create(fi.coreType, generateFullCoreInitString(fi)); - } - } - } else { - if (!fi.forceNewCore) { - coreObject = - CoreFactory::FindOrCreate(fi.coreType, fi.coreName, generateFullCoreInitString(fi)); - if (!coreObject->isOpenToNewFederates()) { - coreObject = nullptr; - logWarningMessage("found core object is not open"); - CoreFactory::cleanUpCores(200ms); - coreObject = CoreFactory::FindOrCreate(fi.coreType, - fi.coreName, - generateFullCoreInitString(fi)); - if (!coreObject->isOpenToNewFederates()) { - throw(RegistrationFailure( - "Unable to connect to specified core: core is not open to new Federates")); - } - } - } else { - coreObject = - CoreFactory::create(fi.coreType, fi.coreName, generateFullCoreInitString(fi)); - } - } - /** make sure the core is connected */ - if (!coreObject->isConnected()) { - coreObject->connect(); - if (!coreObject->isConnected()) { - if (coreObject->hasError()) { - auto message = coreObject->getErrorMessage(); - coreObject->disconnect(); - throw(RegistrationFailure(message)); - } - coreObject->disconnect(); - throw(RegistrationFailure("Unable to connect to broker->unable to register federate")); - } - } - - // this call will throw an error on failure - fedID = coreObject->registerFederate(mName, fi); - if (mName.find("${") != std::string::npos) { - mName = coreObject->getFederateName(fedID); - } - nameSegmentSeparator = fi.separator; - strictConfigChecking = fi.checkFlagProperty(defs::Flags::STRICT_CONFIG_CHECKING, true); + verifyCore(); - useJsonSerialization = fi.useJsonSerialization; - observerMode = fi.observer; - mCurrentTime = coreObject->getCurrentTime(fedID); - asyncCallInfo = std::make_unique>(); - cManager = std::make_unique(coreObject.get(), - this, - fedID, - singleThreadFederate); + registerFederate(fedInfo); } -Federate::Federate(std::string_view fedname, CoreApp& core, const FederateInfo& fi): - Federate(fedname, core.getCopyofCorePointer(), fi) +Federate::Federate(std::string_view fedname, CoreApp& core, const FederateInfo& fedInfo): + Federate(fedname, core.getCopyofCorePointer(), fedInfo) { } Federate::Federate(std::string_view fedName, const std::shared_ptr& core, - const FederateInfo& fi): + const FederateInfo& fedInfo): coreObject(core), mName(fedName) { - if (!coreObject) { - if (fi.coreName.empty()) { - coreObject = CoreFactory::findJoinableCoreOfType(fi.coreType); - if (!coreObject) { - coreObject = CoreFactory::create(fi.coreType, generateFullCoreInitString(fi)); - } - } else { - coreObject = - CoreFactory::FindOrCreate(fi.coreType, fi.coreName, generateFullCoreInitString(fi)); - } - } - - /** make sure the core is connected */ - if (!coreObject->isConnected()) { - coreObject->connect(); - } if (mName.empty()) { - mName = fi.defName; + mName = fedInfo.defName; } - fedID = coreObject->registerFederate(mName, fi); - nameSegmentSeparator = fi.separator; - observerMode = fi.observer; - strictConfigChecking = fi.checkFlagProperty(defs::Flags::STRICT_CONFIG_CHECKING, true); - singleThreadFederate = fi.checkFlagProperty(defs::Flags::SINGLE_THREAD_FEDERATE, false); - mCurrentTime = coreObject->getCurrentTime(fedID); - if (!singleThreadFederate) { - asyncCallInfo = std::make_unique>(); - } - cManager = std::make_unique(coreObject.get(), - this, - fedID, - singleThreadFederate); + getCore(fedInfo); + verifyCore(); + + registerFederate(fedInfo); } Federate::Federate(std::string_view fedName, const std::string& configString): Federate(fedName, loadFederateInfo(configString)) { - if (looksLikeFile(configString)) { - registerFilterInterfaces(configString); - } } Federate::Federate(const std::string& configString): Federate(std::string_view{}, configString) {} @@ -236,10 +137,117 @@ Federate::~Federate() } } +void Federate::getCore(const FederateInfo& fedInfo) +{ + singleThreadFederate = fedInfo.checkFlagProperty(defs::Flags::SINGLE_THREAD_FEDERATE, false); + if (coreObject) { + return; + } + + if (fedInfo.coreName.empty()) { + if (!fedInfo.forceNewCore) { + coreObject = CoreFactory::findJoinableCoreOfType(fedInfo.coreType); + } + if (!coreObject) { + if (!mName.empty()) { + std::string cname = + fmt::format("{}_core_{}", mName, gmlc::utilities::randomString(6)); + auto loc = mName.find("${"); + if (loc != std::string::npos) { + cname = fmt::format("{}_core_{}", + mName.substr(0, loc), + gmlc::utilities::randomString(8)); + } + try { + coreObject = CoreFactory::create(fedInfo.coreType, + cname, + generateFullCoreInitString(fedInfo)); + } + catch (const helics::RegistrationFailure&) { + // there is a possibility of race condition here in the naming resulting a + // failure this catches and reverts to previous naming which is fully randomly + // generated + coreObject = + CoreFactory::create(fedInfo.coreType, generateFullCoreInitString(fedInfo)); + } + } else { + coreObject = + CoreFactory::create(fedInfo.coreType, generateFullCoreInitString(fedInfo)); + } + } + } else { + if (!fedInfo.forceNewCore) { + coreObject = CoreFactory::FindOrCreate(fedInfo.coreType, + fedInfo.coreName, + generateFullCoreInitString(fedInfo)); + if (!coreObject->isOpenToNewFederates()) { + coreObject = nullptr; + logWarningMessage("found core object is not open"); + CoreFactory::cleanUpCores(200ms); + coreObject = CoreFactory::FindOrCreate(fedInfo.coreType, + fedInfo.coreName, + generateFullCoreInitString(fedInfo)); + if (!coreObject->isOpenToNewFederates()) { + throw(RegistrationFailure( + "Unable to connect to specified core: core is not open to new Federates")); + } + } + } else { + coreObject = CoreFactory::create(fedInfo.coreType, + fedInfo.coreName, + generateFullCoreInitString(fedInfo)); + } + } +} + +void Federate::verifyCore() +{ + /** make sure the core is connected */ + if (!coreObject->isConnected()) { + coreObject->connect(); + if (!coreObject->isConnected()) { + if (coreObject->hasError()) { + auto message = coreObject->getErrorMessage(); + coreObject->disconnect(); + throw(RegistrationFailure(message)); + } + coreObject->disconnect(); + throw(RegistrationFailure("Unable to connect to broker->unable to register federate")); + } + } +} +/** function to register the federate with the core*/ +void Federate::registerFederate(const FederateInfo& fedInfo) +{ + // this call will throw an error on failure + fedID = coreObject->registerFederate(mName, fedInfo); + if (mName.find("${") != std::string::npos) { + mName = coreObject->getFederateName(fedID); + } + + nameSegmentSeparator = fedInfo.separator; + strictConfigChecking = fedInfo.checkFlagProperty(defs::Flags::STRICT_CONFIG_CHECKING, true); + + useJsonSerialization = fedInfo.useJsonSerialization; + observerMode = fedInfo.observer; + configFile = fedInfo.fileInUse; + mCurrentTime = coreObject->getCurrentTime(fedID); + if (!singleThreadFederate) { + asyncCallInfo = std::make_unique>(); + } + cManager = std::make_unique(coreObject.get(), + this, + fedID, + singleThreadFederate); + if (!configFile.empty()) { + registerConnectorInterfaces(configFile); + } +} + void Federate::enterInitializingMode() { - auto cm = currentMode.load(); - switch (cm) { + auto cmode = currentMode.load(); + switch (cmode) { case Modes::STARTUP: try { if (coreObject->enterInitializingMode(fedID)) { @@ -279,17 +287,17 @@ void Federate::enterInitializingModeAsync() throw(InvalidFunctionCall( "Async function calls and methods are not allowed for single thread federates")); } - auto cm = currentMode.load(); - if (cm == Modes::STARTUP) { + auto cmode = currentMode.load(); + if (cmode == Modes::STARTUP) { auto asyncInfo = asyncCallInfo->lock(); - if (currentMode.compare_exchange_strong(cm, Modes::PENDING_INIT)) { + if (currentMode.compare_exchange_strong(cmode, Modes::PENDING_INIT)) { asyncInfo->initFuture = std::async(std::launch::async, [this]() { return coreObject->enterInitializingMode(fedID); }); } - } else if (cm == Modes::PENDING_INIT) { + } else if (cmode == Modes::PENDING_INIT) { return; - } else if (cm != Modes::INITIALIZING) { + } else if (cmode != Modes::INITIALIZING) { // if we are already in initialization do nothing throw(InvalidFunctionCall("cannot transition from current mode to initializing mode")); } @@ -331,8 +339,7 @@ void Federate::enterInitializingModeComplete() case Modes::PENDING_INIT: { auto asyncInfo = asyncCallInfo->lock(); try { - bool res = asyncInfo->initFuture.get(); - if (res) { + if (asyncInfo->initFuture.get()) { enteringInitializingMode(IterationResult::NEXT_STEP); } } @@ -355,8 +362,8 @@ void Federate::enterInitializingModeComplete() void Federate::enterInitializingModeIterative() { - auto cm = currentMode.load(); - switch (cm) { + auto cmode = currentMode.load(); + switch (cmode) { case Modes::STARTUP: try { coreObject->enterInitializingMode(fedID, IterationRequest::FORCE_ITERATION); @@ -376,15 +383,15 @@ void Federate::enterInitializingModeIterative() void Federate::enterInitializingModeIterativeAsync() { - auto cm = currentMode.load(); - if (cm == Modes::STARTUP) { + auto cmode = currentMode.load(); + if (cmode == Modes::STARTUP) { auto asyncInfo = asyncCallInfo->lock(); - if (currentMode.compare_exchange_strong(cm, Modes::PENDING_ITERATIVE_INIT)) { + if (currentMode.compare_exchange_strong(cmode, Modes::PENDING_ITERATIVE_INIT)) { asyncInfo->initIterativeFuture = std::async(std::launch::async, [this]() { coreObject->enterInitializingMode(fedID, IterationRequest::FORCE_ITERATION); }); } - } else if (cm == Modes::PENDING_ITERATIVE_INIT) { + } else if (cmode == Modes::PENDING_ITERATIVE_INIT) { return; } else { // everything else is an error @@ -853,13 +860,15 @@ void Federate::completeOperation() void Federate::localError(int errorcode) { - std::string errorString = "local error " + std::to_string(errorcode) + " in federate " + mName; + const std::string errorString = + "local error " + std::to_string(errorcode) + " in federate " + mName; localError(errorcode, errorString); } void Federate::globalError(int errorcode) { - std::string errorString = "global error " + std::to_string(errorcode) + " in federate " + mName; + const std::string errorString = + "global error " + std::to_string(errorcode) + " in federate " + mName; globalError(errorcode, errorString); } @@ -1040,7 +1049,7 @@ iteration_time Federate::requestTimeIterativeComplete() void Federate::updateFederateMode(Modes newMode) { - Modes oldMode = currentMode.load(); + const Modes oldMode = currentMode.load(); currentMode.store(newMode); if (newMode == oldMode) { return; @@ -1129,10 +1138,11 @@ void Federate::disconnectTransition() void Federate::registerInterfaces(const std::string& configString) { - registerFilterInterfaces(configString); + // this will be deprecated at some point in the future + registerConnectorInterfaces(configString); } -void Federate::registerFilterInterfaces(const std::string& configString) +void Federate::registerConnectorInterfaces(const std::string& configString) { if (fileops::hasTomlExtension(configString)) { registerConnectorInterfacesToml(configString); @@ -1146,15 +1156,30 @@ void Federate::registerFilterInterfaces(const std::string& configString) } } +static Translator& generateTranslator(Federate* fed, + bool global, + std::string_view name, + TranslatorTypes ttype, + std::string_view endpointType, + std::string_view units) +{ + Translator& trans = (global) ? fed->registerGlobalTranslator(name, endpointType, units) : + fed->registerTranslator(name, endpointType, units); + if (ttype != TranslatorTypes::CUSTOM) { + trans.setTranslatorType(static_cast(ttype)); + } + return trans; +} + static Filter& generateFilter(Federate* fed, bool global, bool cloning, - const std::string& name, + std::string_view name, FilterTypes operation, - const std::string& inputType, - const std::string& outputType) + std::string_view inputType, + std::string_view outputType) { - bool useTypes = !((inputType.empty()) && (outputType.empty())); + const bool useTypes = !((inputType.empty()) && (outputType.empty())); if (useTypes) { if (cloning) { return (global) ? fed->registerGlobalCloningFilter(name, inputType, outputType) : @@ -1164,48 +1189,148 @@ static Filter& generateFilter(Federate* fed, fed->registerFilter(name, inputType, outputType); } if (cloning) { - return (global) ? make_cloning_filter(InterfaceVisibility::GLOBAL, operation, fed, name) : - make_cloning_filter(operation, fed, name); + Filter& filt = + (global) ? fed->registerGlobalCloningFilter(name) : fed->registerCloningFilter(name); + if (operation != FilterTypes::CUSTOM) { + filt.setFilterType(static_cast(operation)); + } + return filt; } - return (global) ? make_filter(InterfaceVisibility::GLOBAL, operation, fed, name) : - make_filter(operation, fed, name); + Filter& filt = (global) ? fed->registerCloningFilter(name) : fed->registerFilter(name); + if (operation != FilterTypes::CUSTOM) { + filt.setFilterType(static_cast(operation)); + } + return filt; } static constexpr std::string_view emptyStr; -template -static void loadOptions(Federate* fed, const Inp& data, Filter& filt) +template +static void loadOptions(Federate* fed, const Inp& data, INTERFACE& iface) { - addTargets(data, "flags", [&filt, fed](const std::string& target) { + addTargets(data, "flags", [&iface, fed](const std::string& target) { auto oindex = getOptionIndex((target.front() != '-') ? target : target.substr(1)); - int val = (target.front() != '-') ? 1 : 0; + const int val = (target.front() != '-') ? 1 : 0; if (oindex == HELICS_INVALID_OPTION_INDEX) { fed->logWarningMessage(target + " is not a recognized flag"); return; } - filt.setOption(oindex, val); + iface.setOption(oindex, val); }); processOptions( data, [](const std::string& option) { return getOptionIndex(option); }, [](const std::string& value) { return getOptionValue(value); }, - [&filt](int32_t option, int32_t value) { filt.setOption(option, value); }); + [&iface](int32_t option, int32_t value) { iface.setOption(option, value); }); auto info = fileops::getOrDefault(data, "info", emptyStr); if (!info.empty()) { - filt.setInfo(info); + iface.setInfo(info); } - loadTags(data, [&filt](std::string_view tagname, std::string_view tagvalue) { - filt.setTag(tagname, tagvalue); + loadTags(data, [&iface](std::string_view tagname, std::string_view tagvalue) { + iface.setTag(tagname, tagvalue); + }); + + addTargetVariations(data, "source", "targets", [&iface](const std::string& target) { + iface.addSourceTarget(target); + }); + addTargetVariations(data, "destination", "targets", [&iface](const std::string& target) { + iface.addDestinationTarget(target); }); - auto asrc = [&filt](const std::string& target) { filt.addSourceTarget(target); }; - auto adest = [&filt](const std::string& target) { filt.addDestinationTarget(target); }; - addTargets(data, "sourcetargets", asrc); - addTargets(data, "sourceTargets", asrc); - addTargets(data, "source_targets", asrc); - addTargets(data, "destinationTargets", adest); - addTargets(data, "destinationtargets", adest); - addTargets(data, "destination_targets", adest); +} + +static void arrayPairProcess(Json::Value doc, + const std::string& key, + const std::function& pairOp) +{ + if (doc.isMember(key)) { + if (doc[key].isArray()) { + for (auto& val : doc[key]) { + pairOp(val[0].asString(), val[1].asString()); + } + } else { + auto members = doc[key].getMemberNames(); + for (auto& val : members) { + pairOp(val, doc[key][val].asString()); + } + } + } +} + +bool Federate::checkValidFilterType(bool useTypes, + FilterTypes opType, + const std::string& operation) const +{ + if ((useTypes) && (operation != "custom")) { + if (strictConfigChecking) { + logMessage(HELICS_LOG_LEVEL_ERROR, + "input and output types may only be specified for custom filters"); + throw(InvalidParameter( + "input and output types may only be specified for custom filters")); + } + logMessage(HELICS_LOG_LEVEL_WARNING, + "input and output types may only be specified for custom filters"); + return false; + } + if (!useTypes) { + if (opType == FilterTypes::UNRECOGNIZED) { + if (strictConfigChecking) { + const std::string emessage = + fmt::format("unrecognized filter operation:{}", operation); + logMessage(HELICS_LOG_LEVEL_ERROR, emessage); + + throw(InvalidParameter(emessage)); + } + logMessage(HELICS_LOG_LEVEL_WARNING, + fmt::format("unrecognized filter operation:{}", operation)); + return false; + } + } + return true; +} + +template +static void + loadPropertiesJson(Federate* fed, INTERFACE& iface, const Json::Value& json, bool strict) +{ + static constexpr std::string_view errorMessage = + R"(interface properties require "name" and "value" fields)"; + if (json.isMember("properties")) { + auto& props = json["properties"]; + if (props.isArray()) { + for (const auto& prop : props) { + if ((!prop.isMember("name")) || (!prop.isMember("value"))) { + if (strict) { + fed->logMessage(HELICS_LOG_LEVEL_ERROR, errorMessage); + + throw(InvalidParameter(errorMessage)); + } + fed->logMessage(HELICS_LOG_LEVEL_WARNING, errorMessage); + continue; + } + if (prop["value"].isDouble()) { + iface.set(prop["name"].asString(), prop["value"].asDouble()); + } else { + iface.setString(prop["name"].asString(), prop["value"].asString()); + } + } + } else { + if ((!props.isMember("name")) || (!props.isMember("value"))) { + if (strict) { + fed->logMessage(HELICS_LOG_LEVEL_ERROR, errorMessage); + + throw(InvalidParameter(errorMessage)); + } + fed->logMessage(HELICS_LOG_LEVEL_WARNING, errorMessage); + } else { + if (props["value"].isDouble()) { + iface.set(props["name"].asString(), props["value"].asDouble()); + } else { + iface.setString(props["name"].asString(), props["value"].asString()); + } + } + } + } } void Federate::registerConnectorInterfacesJson(const std::string& jsonString) @@ -1213,131 +1338,203 @@ void Federate::registerConnectorInterfacesJson(const std::string& jsonString) using fileops::getOrDefault; auto doc = fileops::loadJson(jsonString); + bool defaultGlobal = false; + fileops::replaceIfMember(doc, "defaultglobal", defaultGlobal); + if (doc.isMember("filters")) { for (const auto& filt : doc["filters"]) { - std::string key = getOrDefault(filt, "name", emptyStr); - std::string inputType = getOrDefault(filt, "inputType", emptyStr); - std::string outputType = getOrDefault(filt, "outputType", emptyStr); - bool cloningflag = getOrDefault(filt, "cloning", false); - bool useTypes = !((inputType.empty()) && (outputType.empty())); - - std::string operation = getOrDefault(filt, "operation", std::string("custom")); + const std::string key = getOrDefault(filt, "name", emptyStr); + const std::string inputType = getOrDefault(filt, "inputType", emptyStr); + const std::string outputType = getOrDefault(filt, "outputType", emptyStr); + const bool cloningflag = getOrDefault(filt, "cloning", false); + const bool useTypes = !((inputType.empty()) && (outputType.empty())); + const bool global = fileops::getOrDefault(filt, "global", defaultGlobal); + const std::string operation = getOrDefault(filt, "operation", std::string("custom")); auto opType = filterTypeFromString(operation); - if ((useTypes) && (operation != "custom")) { - if (strictConfigChecking) { - logMessage(HELICS_LOG_LEVEL_ERROR, - "input and output types may only be specified for custom filters"); - throw(InvalidParameter( - "input and output types may only be specified for custom filters")); - } - logMessage(HELICS_LOG_LEVEL_WARNING, - "input and output types may only be specified for custom filters"); + if (!checkValidFilterType(useTypes, opType, operation)) { continue; } - if (!useTypes) { - if (opType == FilterTypes::UNRECOGNIZED) { - if (strictConfigChecking) { - std::string emessage = - fmt::format("unrecognized filter operation:{}", operation); - logMessage(HELICS_LOG_LEVEL_ERROR, emessage); - - throw(InvalidParameter(emessage)); - } - logMessage(HELICS_LOG_LEVEL_WARNING, - fmt::format("unrecognized filter operation:{}", operation)); - continue; - } - } auto& filter = - generateFilter(this, false, cloningflag, key, opType, inputType, outputType); + generateFilter(this, global, cloningflag, key, opType, inputType, outputType); loadOptions(this, filt, filter); + + addTargetVariations(filt, "source", "endpoints", [&filter](const std::string& target) { + filter.addSourceTarget(target); + }); + addTargetVariations(filt, + "destination", + "endpoints", + [&filter](const std::string& target) { + filter.addDestinationTarget(target); + }); + if (cloningflag) { addTargets(filt, "delivery", [&filter](const std::string& target) { static_cast(filter).addDeliveryEndpoint(target); }); } - if (filt.isMember("properties")) { - auto props = filt["properties"]; - if (props.isArray()) { - for (const auto& prop : props) { - if ((!prop.isMember("name")) || (!prop.isMember("value"))) { - if (strictConfigChecking) { - logMessage( - HELICS_LOG_LEVEL_ERROR, - R"(filter properties require "name" and "value" fields)"); - - throw(InvalidParameter( - R"(filter properties require "name" and "value" fields)")); - } - logMessage(HELICS_LOG_LEVEL_WARNING, - R"(filter properties require "name" and "value" fields)"); - continue; - } - if (prop["value"].isDouble()) { - filter.set(prop["name"].asString(), prop["value"].asDouble()); - } else { - filter.setString(prop["name"].asString(), prop["value"].asString()); - } - } - } else { - if ((!props.isMember("name")) || (!props.isMember("value"))) { - if (strictConfigChecking) { - logMessage(HELICS_LOG_LEVEL_ERROR, - R"(filter properties require "name" and "value" fields)"); - - throw(InvalidParameter( - R"(filter properties require "name" and "value" fields)")); - } - logMessage(HELICS_LOG_LEVEL_WARNING, - R"(filter properties require "name" and "value" fields)"); - continue; - } - if (props["value"].isDouble()) { - filter.set(props["name"].asString(), props["value"].asDouble()); - } else { - filter.setString(props["name"].asString(), props["value"].asString()); - } + loadPropertiesJson(this, filter, filt, strictConfigChecking); + } + } + if (doc.isMember("translators")) { + for (const auto& trans : doc["translators"]) { + const std::string key = getOrDefault(trans, "name", emptyStr); + + std::string ttype = getOrDefault(trans, "type", std::string("custom")); + auto opType = translatorTypeFromString(ttype); + auto etype = fileops::getOrDefault(trans, "endpointtype", emptyStr); + auto units = fileops::getOrDefault(trans, "unit", emptyStr); + fileops::replaceIfMember(trans, "units", units); + const bool global = fileops::getOrDefault(trans, "global", defaultGlobal); + + if (opType == TranslatorTypes::UNRECOGNIZED) { + if (strictConfigChecking) { + const std::string emessage = + fmt::format("unrecognized translator type:{}", ttype); + logMessage(HELICS_LOG_LEVEL_ERROR, emessage); + + throw(InvalidParameter(emessage)); } + logMessage(HELICS_LOG_LEVEL_WARNING, + fmt::format("unrecognized translator operation:{}", ttype)); + continue; } + auto& translator = generateTranslator(this, global, key, opType, etype, units); + loadOptions(this, trans, translator); + + addTargetVariations(trans, + "source", + "endpoints", + [&translator](const std::string& target) { + translator.addSourceEndpoint(target); + }); + addTargetVariations(trans, + "destination", + "endpoints", + [&translator](const std::string& target) { + translator.addDestinationEndpoint(target); + }); + addTargetVariations(trans, + "source", + "publications", + [&translator](const std::string& target) { + translator.addPublication(target); + }); + addTargetVariations(trans, + "destination", + "inputs", + [&translator](const std::string& target) { + translator.addInputTarget(target); + }); + addTargetVariations(trans, + "source", + "filters", + [&translator](const std::string& target) { + translator.addSourceFilter(target); + }); + addTargetVariations(trans, + "destination", + "filters", + [&translator](const std::string& target) { + translator.addDestinationFilter(target); + }); + loadPropertiesJson(this, translator, trans, strictConfigChecking); } } - if (doc.isMember("globals")) { - if (doc["globals"].isArray()) { - for (auto& val : doc["globals"]) { - setGlobal(val[0].asString(), val[1].asString()); + arrayPairProcess(doc, "globals", [this](std::string_view key, std::string_view val) { + setGlobal(key, val); + }); + arrayPairProcess(doc, "aliases", [this](std::string_view key, std::string_view val) { + addAlias(key, val); + }); + + loadTags(doc, [this](std::string_view tagname, std::string_view tagvalue) { + this->setTag(tagname, tagvalue); + }); +} + +static void arrayPairProcess(toml::value doc, + const std::string& key, + const std::function& pairOp) +{ + using fileops::isMember; + if (isMember(doc, key)) { + auto& info = toml::find(doc, key); + if (info.is_array()) { + for (auto& val : info.as_array()) { + pairOp(static_cast(val.as_array()[0].as_string()), + static_cast(val.as_array()[1].as_string())); } } else { - auto members = doc["globals"].getMemberNames(); - for (auto& val : members) { - setGlobal(val, doc["globals"][val].asString()); + for (const auto& val : info.as_table()) { + pairOp(val.first, static_cast(val.second.as_string())); } } } +} - if (doc.isMember("aliases")) { - if (doc["aliases"].isArray()) { - for (auto& val : doc["aliases"]) { - addAlias(val[0].asString(), val[1].asString()); +template +static void + loadPropertiesToml(Federate* fed, INTERFACE& iface, const toml::value& data, bool strict) +{ + static constexpr std::string_view errorMessage = + R"(interface properties require "name" and "value" fields)"; + if (fileops::isMember(data, "properties")) { + auto& props = toml::find(data, "properties"); + if (props.is_array()) { + auto& propArray = props.as_array(); + for (const auto& prop : propArray) { + std::string propname; + propname = toml::find_or(prop, "name", propname); + const toml::value uVal; + auto& propval = toml::find_or(prop, "value", uVal); + + if ((propname.empty()) || (propval.is_uninitialized())) { + if (strict) { + fed->logMessage(HELICS_LOG_LEVEL_ERROR, errorMessage); + + throw(InvalidParameter(errorMessage)); + } + fed->logMessage(HELICS_LOG_LEVEL_WARNING, errorMessage); + continue; + } + if (propval.is_floating()) { + iface.set(propname, propval.as_floating()); + } else { + iface.setString(propname, static_cast(propval.as_string())); + } } } else { - auto members = doc["aliases"].getMemberNames(); - for (auto& val : members) { - addAlias(val, doc["aliases"][val].asString()); + std::string propname; + propname = toml::find_or(props, "name", propname); + toml::value uVal; + auto propval = toml::find_or(props, "value", uVal); + + if ((propname.empty()) || (propval.is_uninitialized())) { + if (strict) { + fed->logMessage(HELICS_LOG_LEVEL_ERROR, errorMessage); + + throw(InvalidParameter(errorMessage)); + } + fed->logMessage(HELICS_LOG_LEVEL_WARNING, errorMessage); + } else { + if (propval.is_floating()) { + iface.set(propname, propval.as_floating()); + } else { + iface.setString(propname, static_cast(propval.as_string())); + } } } } - - loadTags(doc, [this](std::string_view tagname, std::string_view tagvalue) { - this->setTag(tagname, tagvalue); - }); } void Federate::registerConnectorInterfacesToml(const std::string& tomlString) { using fileops::getOrDefault; using fileops::isMember; + using fileops::replaceIfMember; toml::value doc; try { @@ -1346,116 +1543,121 @@ void Federate::registerConnectorInterfacesToml(const std::string& tomlString) catch (const std::invalid_argument& ia) { throw(helics::InvalidParameter(ia.what())); } + bool defaultGlobal = false; + replaceIfMember(doc, "defaultglobal", defaultGlobal); if (isMember(doc, "filters")) { - auto filts = toml::find(doc, "filters"); + auto& filts = toml::find(doc, "filters"); if (!filts.is_array()) { throw(helics::InvalidParameter("filters section in toml file must be an array")); } auto& filtArray = filts.as_array(); for (const auto& filt : filtArray) { - std::string key = getOrDefault(filt, "name", emptyStr); - bool cloningflag = getOrDefault(filt, "cloning", false); - std::string inputType = getOrDefault(filt, "inputType", emptyStr); - std::string outputType = getOrDefault(filt, "outputType", emptyStr); - bool useTypes = !((inputType.empty()) && (outputType.empty())); - - std::string operation = getOrDefault(filt, "operation", std::string("custom")); + const std::string key = getOrDefault(filt, "name", emptyStr); + const bool cloningflag = getOrDefault(filt, "cloning", false); + const std::string inputType = getOrDefault(filt, "inputType", emptyStr); + const std::string outputType = getOrDefault(filt, "outputType", emptyStr); + const bool useTypes = !((inputType.empty()) && (outputType.empty())); + const bool global = getOrDefault(filt, "global", defaultGlobal); + const std::string operation = getOrDefault(filt, "operation", std::string("custom")); auto opType = filterTypeFromString(operation); - if ((useTypes) && (operation != "custom")) { - if (strictConfigChecking) { - logMessage(HELICS_LOG_LEVEL_ERROR, - "input and output types may only be specified for custom filters"); - throw(InvalidParameter( - "input and output types may only be specified for custom filters")); - } - logMessage(HELICS_LOG_LEVEL_WARNING, - "input and output types may only be specified for custom filters"); + if (!checkValidFilterType(useTypes, opType, operation)) { continue; } - if (!useTypes) { - if (opType == FilterTypes::UNRECOGNIZED) { - auto emessage = fmt::format("unrecognized filter operation:{}", operation); - if (strictConfigChecking) { - logMessage(HELICS_LOG_LEVEL_ERROR, emessage); - - throw(InvalidParameter(emessage)); - } - logMessage(HELICS_LOG_LEVEL_WARNING, emessage); - continue; - } - } auto& filter = - generateFilter(this, false, cloningflag, key, opType, inputType, outputType); + generateFilter(this, global, cloningflag, key, opType, inputType, outputType); loadOptions(this, filt, filter); - + addTargetVariations(filt, "source", "endpoints", [&filter](const std::string& target) { + filter.addSourceTarget(target); + }); + addTargetVariations(filt, + "destination", + "endpoints", + [&filter](const std::string& target) { + filter.addDestinationTarget(target); + }); if (cloningflag) { addTargets(filt, "delivery", [&filter](const std::string& target) { static_cast(filter).addDeliveryEndpoint(target); }); } - if (isMember(filt, "properties")) { - auto props = toml::find(filt, "properties"); - if (props.is_array()) { - auto& propArray = props.as_array(); - for (const auto& prop : propArray) { - std::string propname; - propname = toml::find_or(prop, "name", propname); - toml::value uVal; - auto propval = toml::find_or(prop, "value", uVal); - - if ((propname.empty()) || (propval.is_uninitialized())) { - if (strictConfigChecking) { - logMessage( - HELICS_LOG_LEVEL_ERROR, - R"(filter properties require "name" and "value" fields)"); - - throw(InvalidParameter( - R"(filter properties require "name" and "value" fields)")); - } - logMessage(HELICS_LOG_LEVEL_WARNING, - R"(filter properties require "name" and "value" fields)"); - continue; - } - if (propval.is_floating()) { - filter.set(propname, propval.as_floating()); - } else { - filter.setString(propname, - static_cast(propval.as_string())); - } - } - } else { - std::string propname; - propname = toml::find_or(props, "name", propname); - toml::value uVal; - auto propval = toml::find_or(props, "value", uVal); - - if ((propname.empty()) || (propval.is_uninitialized())) { - if (strictConfigChecking) { - logMessage(HELICS_LOG_LEVEL_ERROR, - R"(filter properties require "name" and "value" fields)"); - - throw(InvalidParameter( - R"(filter properties require "name" and "value" fields)")); - } - logMessage(HELICS_LOG_LEVEL_WARNING, - R"(filter properties require "name" and "value" fields)"); - continue; - } - if (propval.is_floating()) { - filter.set(propname, propval.as_floating()); - } else { - filter.setString(propname, - static_cast(propval.as_string())); - } + loadPropertiesToml(this, filter, filt, strictConfigChecking); + } + } + if (isMember(doc, "translators")) { + auto& transs = toml::find(doc, "translators"); + if (!transs.is_array()) { + throw(helics::InvalidParameter("translators section in toml file must be an array")); + } + auto& transArray = transs.as_array(); + for (const auto& trans : transArray) { + const std::string key = getOrDefault(trans, "name", emptyStr); + + std::string ttype = getOrDefault(trans, "type", std::string("custom")); + auto opType = translatorTypeFromString(ttype); + auto etype = fileops::getOrDefault(trans, "endpointtype", emptyStr); + auto units = fileops::getOrDefault(trans, "unit", emptyStr); + fileops::replaceIfMember(trans, "units", units); + const bool global = fileops::getOrDefault(trans, "global", defaultGlobal); + + if (opType == TranslatorTypes::UNRECOGNIZED) { + if (strictConfigChecking) { + const std::string emessage = + fmt::format("unrecognized translator type:{}", ttype); + logMessage(HELICS_LOG_LEVEL_ERROR, emessage); + + throw(InvalidParameter(emessage)); } + logMessage(HELICS_LOG_LEVEL_WARNING, + fmt::format("unrecognized filter operation:{}", ttype)); + continue; } + auto& translator = generateTranslator(this, global, key, opType, etype, units); + loadOptions(this, trans, translator); + + addTargetVariations(trans, + "source", + "endpoints", + [&translator](const std::string& target) { + translator.addSourceEndpoint(target); + }); + addTargetVariations(trans, + "destination", + "endpoints", + [&translator](const std::string& target) { + translator.addDestinationEndpoint(target); + }); + addTargetVariations(trans, + "source", + "publications", + [&translator](const std::string& target) { + translator.addPublication(target); + }); + addTargetVariations(trans, + "destination", + "inputs", + [&translator](const std::string& target) { + translator.addInputTarget(target); + }); + addTargetVariations(trans, + "source", + "filters", + [&translator](const std::string& target) { + translator.addSourceFilter(target); + }); + addTargetVariations(trans, + "destination", + "filters", + [&translator](const std::string& target) { + translator.addDestinationFilter(target); + }); + loadPropertiesToml(this, translator, trans, strictConfigChecking); } } if (isMember(doc, "globals")) { - auto globals = toml::find(doc, "globals"); + auto& globals = toml::find(doc, "globals"); if (globals.is_array()) { for (auto& val : globals.as_array()) { setGlobal(static_cast(val.as_array()[0].as_string()), @@ -1468,19 +1670,13 @@ void Federate::registerConnectorInterfacesToml(const std::string& tomlString) } } - if (isMember(doc, "aliases")) { - auto globals = toml::find(doc, "aliases"); - if (globals.is_array()) { - for (auto& val : globals.as_array()) { - addAlias(static_cast(val.as_array()[0].as_string()), - static_cast(val.as_array()[1].as_string())); - } - } else { - for (const auto& val : globals.as_table()) { - addAlias(val.first, static_cast(val.second.as_string())); - } - } - } + arrayPairProcess(doc, "globals", [this](std::string_view key, std::string_view val) { + setGlobal(key, val); + }); + arrayPairProcess(doc, "aliases", [this](std::string_view key, std::string_view val) { + addAlias(key, val); + }); + loadTags(doc, [this](std::string_view tagname, std::string_view tagvalue) { this->setTag(tagname, tagvalue); }); @@ -1719,9 +1915,9 @@ int Federate::getFilterCount() const return cManager->getFilterCount(); } -void Federate::setFilterOperator(const Filter& filt, std::shared_ptr op) +void Federate::setFilterOperator(const Filter& filt, std::shared_ptr filtOp) { - coreObject->setFilterOperator(filt.getHandle(), std::move(op)); + coreObject->setFilterOperator(filt.getHandle(), std::move(filtOp)); } const Translator& Federate::getTranslator(std::string_view translatorName) const @@ -1743,9 +1939,9 @@ Translator& Federate::getTranslator(std::string_view translatorName) } void Federate::setTranslatorOperator(const Translator& trans, - std::shared_ptr op) + std::shared_ptr transOps) { - coreObject->setTranslatorOperator(trans.getHandle(), std::move(op)); + coreObject->setTranslatorOperator(trans.getHandle(), std::move(transOps)); } int Federate::getTranslatorCount() const @@ -1764,105 +1960,105 @@ void Federate::logMessage(int level, std::string_view message) const } } -Interface::Interface(Federate* federate, InterfaceHandle id, std::string_view actName): - handle(id), mName(actName) +Interface::Interface(Federate* federate, InterfaceHandle hid, std::string_view actName): + handle(hid), mName(actName) { if (federate != nullptr) { const auto& crp = federate->getCorePointer(); if (crp) { - cr = crp.get(); + mCore = crp.get(); } } } const std::string& Interface::getName() const { - return cr->getHandleName(handle); + return mCore->getHandleName(handle); } const std::string& Interface::getTarget() const { - return cr->getSourceTargets(handle); + return mCore->getSourceTargets(handle); } void Interface::addSourceTarget(std::string_view newTarget, InterfaceType hint) { - cr->addSourceTarget(handle, newTarget, hint); + mCore->addSourceTarget(handle, newTarget, hint); } void Interface::addDestinationTarget(std::string_view newTarget, InterfaceType hint) { - cr->addDestinationTarget(handle, newTarget, hint); + mCore->addDestinationTarget(handle, newTarget, hint); } void Interface::removeTarget(std::string_view targetToRemove) { - cr->removeTarget(handle, targetToRemove); + mCore->removeTarget(handle, targetToRemove); } void Interface::addAlias(std::string_view alias) { - cr->addAlias(getName(), alias); + mCore->addAlias(getName(), alias); } const std::string& Interface::getInfo() const { - return cr->getInterfaceInfo(handle); + return mCore->getInterfaceInfo(handle); } void Interface::setInfo(std::string_view info) { - cr->setInterfaceInfo(handle, info); + mCore->setInterfaceInfo(handle, info); } const std::string& Interface::getTag(std::string_view tag) const { - return cr->getInterfaceTag(handle, tag); + return mCore->getInterfaceTag(handle, tag); } void Interface::setTag(std::string_view tag, std::string_view value) { - cr->setInterfaceTag(handle, tag, value); + mCore->setInterfaceTag(handle, tag, value); } void Interface::setOption(int32_t option, int32_t value) { - cr->setHandleOption(handle, option, value); + mCore->setHandleOption(handle, option, value); } int32_t Interface::getOption(int32_t option) const { - return cr->getHandleOption(handle, option); + return mCore->getHandleOption(handle, option); } const std::string& Interface::getInjectionType() const { - return cr->getInjectionType(handle); + return mCore->getInjectionType(handle); } const std::string& Interface::getExtractionType() const { - return cr->getExtractionType(handle); + return mCore->getExtractionType(handle); } const std::string& Interface::getInjectionUnits() const { - return cr->getInjectionUnits(handle); + return mCore->getInjectionUnits(handle); } const std::string& Interface::getExtractionUnits() const { - return cr->getExtractionUnits(handle); + return mCore->getExtractionUnits(handle); } const std::string& Interface::getSourceTargets() const { - return cr->getSourceTargets(handle); + return mCore->getSourceTargets(handle); } const std::string& Interface::getDestinationTargets() const { - return cr->getDestinationTargets(handle); + return mCore->getDestinationTargets(handle); } const std::string& Interface::getDisplayName() const @@ -1872,13 +2068,13 @@ const std::string& Interface::getDisplayName() const void Interface::close() { - cr->closeHandle(handle); - cr = CoreFactory::getEmptyCorePtr(); + mCore->closeHandle(handle); + mCore = CoreFactory::getEmptyCorePtr(); } void Interface::disconnectFromCore() { - cr = CoreFactory::getEmptyCorePtr(); + mCore = CoreFactory::getEmptyCorePtr(); } } // namespace helics diff --git a/src/helics/application_api/Federate.hpp b/src/helics/application_api/Federate.hpp index 0217a8dd9e..a3ec0ebc1d 100644 --- a/src/helics/application_api/Federate.hpp +++ b/src/helics/application_api/Federate.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -40,6 +40,7 @@ class Filter; class Translator; class CloningFilter; class Federate; +enum class FilterTypes; /** base class for a federate in the application API */ @@ -95,6 +96,7 @@ class HELICS_CXX_EXPORT Federate { std::shared_ptr coreObject; //!< reference to the core simulation API Time mCurrentTime = Time::minVal(); //!< the current simulation time Time mStopTime = Time::maxVal(); //!< the stopping time for the federate + std::string configFile; //!< any config file used private: /// pointer to a class defining the async call information std::unique_ptr> asyncCallInfo; @@ -112,24 +114,24 @@ class HELICS_CXX_EXPORT Federate { public: /**constructor taking a federate information structure @param fedname the name of the federate can be empty to use a name from the federateInfo - @param fi a federate information structure + @param fedInfo a federate information structure */ - Federate(std::string_view fedname, const FederateInfo& fi); + Federate(std::string_view fedname, const FederateInfo& fedInfo); /**constructor taking a core and a federate information structure @param fedname the name of the federate can be empty to use a name from the federateInfo @param core a shared pointer to a core object, the pointer will be copied - @param fi a federate information structure + @param fedInfo a federate information structure */ Federate(std::string_view fedname, const std::shared_ptr& core, - const FederateInfo& fi = FederateInfo{}); + const FederateInfo& fedInfo = FederateInfo{}); /**constructor taking a CoreApp and a federate information structure @param fedname the name of the federate can be empty to use a name from the federateInfo @param core a CoreApp with the core core connect to. - @param fi a federate information structure + @param fedInfo a federate information structure */ - Federate(std::string_view fedname, CoreApp& core, const FederateInfo& fi = FederateInfo{}); + Federate(std::string_view fedname, CoreApp& core, const FederateInfo& fedInfo = FederateInfo{}); /**constructor taking a file with the required information @param configString can be either a JSON file or a string containing JSON code or a TOML file */ @@ -685,9 +687,9 @@ received The FilterOperator gets called when there is a message to filter, There is no order or state to this messages can come in any order. @param filt the filter object to set the operation on - @param op a shared_ptr to a \ref FilterOperator + @param filtOp a shared_ptr to a \ref FilterOperator */ - void setFilterOperator(const Filter& filt, std::shared_ptr op); + void setFilterOperator(const Filter& filt, std::shared_ptr filtOp); /** get the number of filters registered through this federate*/ int getFilterCount() const; @@ -722,12 +724,15 @@ received The TranslatorOperator gets called when there is a message or value to translate, there is no order or state to this as messages can come in any order. @param trans the translator object to set the operation on - @param op a shared_ptr to a \ref TranslatorOperator + @param transOp a shared_ptr to a \ref TranslatorOperator */ - void setTranslatorOperator(const Translator& trans, std::shared_ptr op); + void setTranslatorOperator(const Translator& trans, + std::shared_ptr transOp); /** get the number of translators registered through this federate*/ int getTranslatorCount() const; + /** get the primary config file actually used by the federate for setup*/ + const std::string& getConfigFile() const { return configFile; } protected: /** function to run required operations for entering initializingMode*/ @@ -771,8 +776,16 @@ received @param configString the location of the file or config String to load to generate the interfaces */ - void registerFilterInterfaces(const std::string& configString); - + void registerConnectorInterfaces(const std::string& configString); + /** register filter/translator interfaces defined in a file or string + @details call is only valid in startup mode will be deprecated + @param configString the location of the file or config String to load to generate the + interfaces + */ + void registerFilterInterfaces(const std::string& configString) + { + registerConnectorInterfaces(configString); + } /** get the underlying federateID for the core*/ auto getID() const noexcept { return fedID; } /** get the current state of the federate*/ @@ -823,6 +836,12 @@ received void completeOperation(); private: + void getCore(const FederateInfo& fedInfo); + /** function to get the core into a valid state*/ + void verifyCore(); + /** function to register the federate with the core*/ + void registerFederate(const FederateInfo& fedInfo); + /** function to deal with any operations that occur on a mode switch*/ void updateFederateMode(Modes newMode); /** function to deal with any operations that need to occur on a time update*/ @@ -837,19 +856,23 @@ received @param tomlString the location of the file or config String to load to generate the interfaces */ void registerConnectorInterfacesToml(const std::string& tomlString); + /** check if a filter type and operation is valid + */ + bool + checkValidFilterType(bool useTypes, FilterTypes opType, const std::string& operation) const; }; /** base class for the interface objects*/ class HELICS_CXX_EXPORT Interface { protected: - Core* cr{nullptr}; //!< pointer to the core object + Core* mCore{nullptr}; //!< pointer to the core object InterfaceHandle handle{}; //!< the id as generated by the Federate std::string mName; //!< the name or key of the interface public: Interface() = default; - Interface(Federate* federate, InterfaceHandle id, std::string_view actName); - Interface(Core* core, InterfaceHandle id, std::string_view actName): - cr(core), handle(id), mName(actName) + Interface(Federate* federate, InterfaceHandle hid, std::string_view actName); + Interface(Core* core, InterfaceHandle hid, std::string_view actName): + mCore(core), handle(hid), mName(actName) { } virtual ~Interface() = default; diff --git a/src/helics/application_api/FederateInfo.cpp b/src/helics/application_api/FederateInfo.cpp index a138df6c38..d96e30debf 100644 --- a/src/helics/application_api/FederateInfo.cpp +++ b/src/helics/application_api/FederateInfo.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -326,28 +326,28 @@ static const std::unordered_map log_level_map{ /** all internal messages*/ {"trace", HELICS_LOG_LEVEL_TRACE}}; -static void loadFlags(FederateInfo& fi, const std::string& flags) +static void loadFlags(FederateInfo& fedInfo, const std::string& flags) { auto sflgs = gmlc::utilities::stringOps::splitline(flags); for (auto& flg : sflgs) { if (flg == "autobroker") { - fi.autobroker = true; + fedInfo.autobroker = true; continue; } if (flg == "debugging") { - fi.debugging = true; + fedInfo.debugging = true; continue; } if (flg == "json") { - fi.useJsonSerialization = true; + fedInfo.useJsonSerialization = true; // purposely not continuing here so the setFlagOption gets called } if (flg == "profiling") { - fi.profilerFileName = "log"; + fedInfo.profilerFileName = "log"; // purposely not continuing here so the setFlagOption gets called } if (flg == "observer") { - fi.observer = true; + fedInfo.observer = true; // purposely not continuing here so the setFlagOption gets called } if (flg.empty()) { @@ -355,12 +355,12 @@ static void loadFlags(FederateInfo& fi, const std::string& flags) } const auto* loc = flagStringsTranslations.find(flg); if (loc != flagStringsTranslations.end()) { - fi.setFlagOption(loc->second, true); + fedInfo.setFlagOption(loc->second, true); } else { if (flg.front() == '-') { loc = flagStringsTranslations.find(flg.substr(1)); if (loc != flagStringsTranslations.end()) { - fi.setFlagOption(loc->second, false); + fedInfo.setFlagOption(loc->second, false); } continue; } @@ -369,7 +369,7 @@ static void loadFlags(FederateInfo& fi, const std::string& flags) auto [ptr, ec] = std::from_chars(flg.data(), flg.data() + flg.size(), val); if (ec == std::errc()) { - fi.setFlagOption(std::abs(val), (val > 0)); + fedInfo.setFlagOption(std::abs(val), (val > 0)); } else if (ec == std::errc::invalid_argument) { std::cerr << "unrecognized flag " << std::quoted(flg) << std::endl; } else if (ec == std::errc::result_out_of_range) { @@ -486,29 +486,31 @@ std::unique_ptr FederateInfo::makeCLIApp() auto* fmtr = addJsonConfig(app.get()); fmtr->maxLayers(0); app->add_option("--name,-n", defName, "name of the federate"); - auto* og = app->add_option_group("network type")->immediate_callback(); - og->add_option_function( - "--core", - [this](const std::string& val) { - coreType = coreTypeFromString(val); - if (coreType == CoreType::UNRECOGNIZED) { - coreName = val; - } - }, - "type or name of the core to connect to") + auto* networking = app->add_option_group("network type")->immediate_callback(); + networking + ->add_option_function( + "--core", + [this](const std::string& val) { + coreType = coreTypeFromString(val); + if (coreType == CoreType::UNRECOGNIZED) { + coreName = val; + } + }, + "type or name of the core to connect to") ->default_str("(" + to_string(coreType) + ")"); - og->add_flag("--force_new_core", - forceNewCore, - "if set to true will force the federate to generate a new core"); - og->add_option_function( - "--coretype,-t", - [this](const std::string& val) { - coreType = coreTypeFromString(val); - if (coreType == CoreType::UNRECOGNIZED) { - throw CLI::ValidationError(val + " is NOT a recognized core type"); - } - }, - "type of the core to connect to") + networking->add_flag("--force_new_core", + forceNewCore, + "if set to true will force the federate to generate a new core"); + networking + ->add_option_function( + "--coretype,-t", + [this](const std::string& val) { + coreType = coreTypeFromString(val); + if (coreType == CoreType::UNRECOGNIZED) { + throw CLI::ValidationError(val + " is NOT a recognized core type"); + } + }, + "type of the core to connect to") ->default_str("(" + to_string(coreType) + ")") ->envname("HELICS_CORE_TYPE"); app->add_option("--corename", coreName, "the name of the core to create or find"); @@ -727,12 +729,14 @@ void FederateInfo::config_additional(helicsCLI11App* app) auto* opt = app->get_option("--config"); if (opt->count() > 0) { auto configString = opt->as(); - if (fileops::hasTomlExtension(configString)) { - loadInfoFromToml(configString, false); - fileInUse = configString; - } else if (fileops::hasJsonExtension(configString)) { - loadInfoFromJson(configString, false); - fileInUse = configString; + if (CLI::ExistingFile(configString).empty()) { + if (fileops::hasTomlExtension(configString)) { + loadInfoFromToml(configString, false); + fileInUse = configString; + } else if (fileops::hasJsonExtension(configString)) { + loadInfoFromJson(configString, false); + fileInUse = configString; + } } } } @@ -740,8 +744,9 @@ void FederateInfo::config_additional(helicsCLI11App* app) FederateInfo loadFederateInfo(const std::string& configString) { FederateInfo ret; - - if (fileops::hasTomlExtension(configString)) { + if (fileops::looksLikeCommandLine(configString)) { + ret.loadInfoFromArgsIgnoreOutput(configString); + } else if (fileops::hasTomlExtension(configString)) { ret.loadInfoFromToml(configString); ret.fileInUse = configString; } else if (fileops::hasJsonExtension(configString)) { @@ -749,8 +754,6 @@ FederateInfo loadFederateInfo(const std::string& configString) ret.fileInUse = configString; } else if (configString.find_first_of('{') != std::string::npos) { ret.loadInfoFromJson(configString); - } else if (configString.find("--") != std::string::npos) { - ret.loadInfoFromArgsIgnoreOutput(configString); } else if (configString.find('=') != std::string::npos) { ret.loadInfoFromToml(configString); } else { @@ -761,9 +764,9 @@ FederateInfo loadFederateInfo(const std::string& configString) Time FederateInfo::checkTimeProperty(int propId, Time defVal) const { - for (const auto& tp : timeProps) { - if (tp.first == propId) { - return tp.second; + for (const auto& prop : timeProps) { + if (prop.first == propId) { + return prop.second; } } return defVal; @@ -771,9 +774,9 @@ Time FederateInfo::checkTimeProperty(int propId, Time defVal) const bool FederateInfo::checkFlagProperty(int propId, bool defVal) const { - for (const auto& tp : flagProps) { - if (tp.first == propId) { - return tp.second; + for (const auto& prop : flagProps) { + if (prop.first == propId) { + return prop.second; } } return defVal; @@ -781,9 +784,9 @@ bool FederateInfo::checkFlagProperty(int propId, bool defVal) const int FederateInfo::checkIntProperty(int propId, int defVal) const { - for (const auto& tp : intProps) { - if (tp.first == propId) { - return tp.second; + for (const auto& prop : intProps) { + if (prop.first == propId) { + return prop.second; } } return defVal; @@ -795,12 +798,12 @@ void FederateInfo::loadInfoFromJson(const std::string& jsonString, bool runArgPa try { doc = fileops::loadJson(jsonString); } - catch (const std::invalid_argument& ia) { - throw(helics::InvalidParameter(ia.what())); + catch (const std::invalid_argument& iarg) { + throw(helics::InvalidParameter(iarg.what())); } - std::function timeCall = [this](const std::string& fname, - Time arg) { + const std::function timeCall = [this](const std::string& fname, + Time arg) { setProperty(propStringsTranslations.at(fname), arg); }; @@ -829,8 +832,8 @@ void FederateInfo::loadInfoFromJson(const std::string& jsonString, bool runArgPa app->parse_from_stream(file); } } - catch (const CLI::Error& e) { - throw(InvalidIdentifier(e.what())); + catch (const CLI::Error& clierror) { + throw(InvalidIdentifier(clierror.what())); } } } @@ -841,12 +844,12 @@ void FederateInfo::loadInfoFromToml(const std::string& tomlString, bool runArgPa try { doc = fileops::loadToml(tomlString); } - catch (const std::invalid_argument& ia) { - throw(helics::InvalidParameter(ia.what())); + catch (const std::invalid_argument& iarg) { + throw(helics::InvalidParameter(iarg.what())); } - std::function timeCall = [this](const std::string& fname, - Time arg) { + const std::function timeCall = [this](const std::string& fname, + Time arg) { setProperty(propStringsTranslations.at(fname), arg); }; @@ -885,58 +888,59 @@ void FederateInfo::loadInfoFromToml(const std::string& tomlString, bool runArgPa } } -std::string generateFullCoreInitString(const FederateInfo& fi) +std::string generateFullCoreInitString(const FederateInfo& fedInfo) { - auto res = fi.coreInitString; - if (!fi.broker.empty()) { + auto res = fedInfo.coreInitString; + if (!fedInfo.broker.empty()) { res.append(" --broker="); - res.append(fi.broker); + res.append(fedInfo.broker); } - if (fi.brokerPort >= 0) { + if (fedInfo.brokerPort >= 0) { res.append(" --brokerport="); - res.append(std::to_string(fi.brokerPort)); + res.append(std::to_string(fedInfo.brokerPort)); } - if (!fi.localport.empty()) { + if (!fedInfo.localport.empty()) { res.append(" --localport="); - res.append(fi.localport); + res.append(fedInfo.localport); } - if (fi.autobroker) { + if (fedInfo.autobroker) { res.append(" --autobroker"); } - if (fi.debugging) { + if (fedInfo.debugging) { res.append(" --debugging"); } - if (fi.observer) { + if (fedInfo.observer) { res.append(" --observer"); } - if (fi.useJsonSerialization) { + if (fedInfo.useJsonSerialization) { res.append(" --json"); } - if (fi.encrypted) { + if (fedInfo.encrypted) { res.append(" --encrypted"); } - if (!fi.encryptionConfig.empty()) { + if (!fedInfo.encryptionConfig.empty()) { res.append(" --encryption_config \""); - res.append(fi.encryptionConfig); + res.append(fedInfo.encryptionConfig); res.append("\""); } - if (!fi.profilerFileName.empty()) { + if (!fedInfo.profilerFileName.empty()) { res.append(" --profiler \""); - res.append(fi.profilerFileName); + res.append(fedInfo.profilerFileName); res.append("\""); } - if (!fi.brokerInitString.empty()) { + if (!fedInfo.brokerInitString.empty()) { res.append(" --broker_init_string \""); - res.append(fi.brokerInitString); + res.append(fedInfo.brokerInitString); res.append("\""); } - if (!fi.key.empty()) { + if (!fedInfo.key.empty()) { res += " --broker_key="; - res.append(fi.key); + res.append(fedInfo.key); } - if (!fi.fileInUse.empty()) { // we used the file, specify a core section - res += " --config_section=core --config-file="; - res.append(fi.fileInUse); + if (!fedInfo.fileInUse.empty()) { // we used the file, specify a core section + res += " --config_section=core --config-file='"; + res.append(fedInfo.fileInUse); + res.push_back('\''); } return res; } diff --git a/src/helics/application_api/FederateInfo.hpp b/src/helics/application_api/FederateInfo.hpp index 4651aa1d49..d3536baaf9 100644 --- a/src/helics/application_api/FederateInfo.hpp +++ b/src/helics/application_api/FederateInfo.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -129,7 +129,7 @@ class HELICS_CXX_EXPORT FederateInfo: public CoreFederateInfo { HELICS_CXX_EXPORT FederateInfo loadFederateInfo(const std::string& configString); /** generate string for passing arguments to the core*/ -HELICS_CXX_EXPORT std::string generateFullCoreInitString(const FederateInfo& fi); +HELICS_CXX_EXPORT std::string generateFullCoreInitString(const FederateInfo& fedInfo); /** get an integer/time property/flag from a string name of the property or flag @param val a name of property to get an integer index code for used in /ref diff --git a/src/helics/application_api/FilterOperations.cpp b/src/helics/application_api/FilterOperations.cpp index f6ceacc672..fbc88958f6 100644 --- a/src/helics/application_api/FilterOperations.cpp +++ b/src/helics/application_api/FilterOperations.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/application_api/FilterOperations.hpp b/src/helics/application_api/FilterOperations.hpp index fdcfb07fd2..22f20d9c5c 100644 --- a/src/helics/application_api/FilterOperations.hpp +++ b/src/helics/application_api/FilterOperations.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/application_api/Filters.cpp b/src/helics/application_api/Filters.cpp index c2fc155b32..4e93a9e640 100644 --- a/src/helics/application_api/Filters.cpp +++ b/src/helics/application_api/Filters.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -44,6 +44,11 @@ FilterTypes filterTypeFromString(std::string_view filterType) noexcept return FilterTypes::UNRECOGNIZED; } +void Filter::setFilterType(std::int32_t type) +{ + addOperations(this, static_cast(type), nullptr); +} + void addOperations(Filter* filt, FilterTypes type, Core* /*cptr*/) { switch (type) { @@ -51,28 +56,28 @@ void addOperations(Filter* filt, FilterTypes type, Core* /*cptr*/) default: break; case FilterTypes::RANDOM_DELAY: { - auto op = std::make_shared(); - filt->setFilterOperations(std::move(op)); + auto operation = std::make_shared(); + filt->setFilterOperations(std::move(operation)); } break; case FilterTypes::DELAY: { - auto op = std::make_shared(); - filt->setFilterOperations(std::move(op)); + auto operation = std::make_shared(); + filt->setFilterOperations(std::move(operation)); } break; case FilterTypes::RANDOM_DROP: { - auto op = std::make_shared(); - filt->setFilterOperations(std::move(op)); + auto operation = std::make_shared(); + filt->setFilterOperations(std::move(operation)); } break; case FilterTypes::REROUTE: { - auto op = std::make_shared(); - filt->setFilterOperations(std::move(op)); + auto operation = std::make_shared(); + filt->setFilterOperations(std::move(operation)); } break; case FilterTypes::CLONE: { - auto op = std::make_shared(); - filt->setFilterOperations(std::move(op)); + auto operation = std::make_shared(); + filt->setFilterOperations(std::move(operation)); } break; case FilterTypes::FIREWALL: { - auto op = std::make_shared(); - filt->setFilterOperations(std::move(op)); + auto operation = std::make_shared(); + filt->setFilterOperations(std::move(operation)); } break; } } @@ -106,18 +111,18 @@ Filter::Filter(InterfaceVisibility locality, Federate* ffed, std::string_view fi Filter::Filter(Core* core, std::string_view filtName): Interface(core, InterfaceHandle(), filtName) { - handle = cr->registerFilter(filtName, std::string_view{}, std::string_view{}); + handle = core->registerFilter(filtName, std::string_view{}, std::string_view{}); } -void Filter::setOperator(std::shared_ptr mo) +void Filter::setOperator(std::shared_ptr filterOp) { - cr->setFilterOperator(handle, std::move(mo)); + mCore->setFilterOperator(handle, std::move(filterOp)); } void Filter::setFilterOperations(std::shared_ptr filterOps) { filtOp = std::move(filterOps); - cr->setFilterOperator(handle, (filtOp) ? filtOp->getOperator() : nullptr); + mCore->setFilterOperator(handle, (filtOp) ? filtOp->getOperator() : nullptr); } void Filter::set(std::string_view property, double val) @@ -137,7 +142,7 @@ void Filter::setString(std::string_view property, std::string_view val) CloningFilter::CloningFilter(Core* core, std::string_view filtName): Filter(core, filtName, InterfaceHandle()) { - handle = cr->registerCloningFilter(filtName, std::string_view(), std::string_view()); + handle = mCore->registerCloningFilter(filtName, std::string_view(), std::string_view()); setFilterOperations(std::make_shared()); } @@ -231,22 +236,22 @@ Filter& make_filter(InterfaceVisibility locality, return dfilt; } -std::unique_ptr make_filter(FilterTypes type, Core* cr, std::string_view name) +std::unique_ptr make_filter(FilterTypes type, Core* core, std::string_view name) { if (type == FilterTypes::CLONE) { - std::unique_ptr dfilt = std::make_unique(cr, name); - addOperations(dfilt.get(), type, cr); + std::unique_ptr dfilt = std::make_unique(core, name); + addOperations(dfilt.get(), type, core); dfilt->setString("delivery", name); return dfilt; } - auto dfilt = std::make_unique(cr, name); - addOperations(dfilt.get(), type, cr); + auto dfilt = std::make_unique(core, name); + addOperations(dfilt.get(), type, core); return dfilt; } -std::unique_ptr make_filter(FilterTypes type, CoreApp& cr, std::string_view name) +std::unique_ptr make_filter(FilterTypes type, CoreApp& core, std::string_view name) { - return make_filter(type, cr.getCopyofCorePointer().get(), name); + return make_filter(type, core.getCopyofCorePointer().get(), name); } CloningFilter& make_cloning_filter(FilterTypes type, @@ -280,13 +285,13 @@ CloningFilter& make_cloning_filter(InterfaceVisibility locality, } std::unique_ptr make_cloning_filter(FilterTypes type, - Core* cr, + Core* core, std::string_view delivery, std::string_view name) { - auto dfilt = std::make_unique(cr, name); - addOperations(dfilt.get(), type, cr); + auto dfilt = std::make_unique(core, name); + addOperations(dfilt.get(), type, core); if (!delivery.empty()) { dfilt->addDeliveryEndpoint(delivery); } @@ -294,12 +299,12 @@ std::unique_ptr make_cloning_filter(FilterTypes type, } std::unique_ptr make_cloning_filter(FilterTypes type, - CoreApp& cr, + CoreApp& core, std::string_view delivery, std::string_view name) { - return make_cloning_filter(type, cr.getCopyofCorePointer().get(), delivery, name); + return make_cloning_filter(type, core.getCopyofCorePointer().get(), delivery, name); } } // namespace helics diff --git a/src/helics/application_api/Filters.hpp b/src/helics/application_api/Filters.hpp index 7399b0ca05..93f01afd35 100644 --- a/src/helics/application_api/Filters.hpp +++ b/src/helics/application_api/Filters.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -68,7 +68,7 @@ class HELICS_CXX_EXPORT Filter: public Interface { /** check if the filter is a cloning filter*/ bool isCloningFilter() const { return cloning; } /** set a message operator to process the message*/ - void setOperator(std::shared_ptr mo); + void setOperator(std::shared_ptr filterOp); virtual const std::string& getDisplayName() const override { return getName(); } @@ -86,6 +86,9 @@ class HELICS_CXX_EXPORT Filter: public Interface { void addTarget(std::string_view target) { addSourceTarget(target); } + /** set the type of operations specifying how the filter should operate*/ + void setFilterType(std::int32_t type); + protected: /** set a filter operations object */ void setFilterOperations(std::shared_ptr filterOps); @@ -159,23 +162,23 @@ HELICS_CXX_EXPORT Filter& make_filter(InterfaceVisibility locality, /** create a filter @param type the type of filter to create -@param cr the core to create the filter through +@param core the core to create the filter through @param name the name of the filter (optional) @return a unique pointer to a source Filter object, note destroying the object does not deactivate the filter */ HELICS_CXX_EXPORT std::unique_ptr - make_filter(FilterTypes type, Core* cr, std::string_view name = EMPTY_STRING); + make_filter(FilterTypes type, Core* core, std::string_view name = EMPTY_STRING); /** create a filter @param type the type of filter to create -@param cr the core to create the filter through +@param core the core to create the filter through @param name the name of the filter (optional) @return a unique pointer to a source Filter object, note destroying the object does not deactivate the filter */ HELICS_CXX_EXPORT std::unique_ptr - make_filter(FilterTypes type, CoreApp& cr, std::string_view name = EMPTY_STRING); + make_filter(FilterTypes type, CoreApp& core, std::string_view name = EMPTY_STRING); /** create a filter @param type the type of filter to create @@ -207,7 +210,7 @@ HELICS_CXX_EXPORT CloningFilter& make_cloning_filter(InterfaceVisibility localit /** create a cloning filter with a delivery location @param type the type of filter to create -@param cr the core to create the filter through +@param core the core to create the filter through @param delivery the endpoint to deliver the cloned message to @param name the name of the filter (optional) @return a unique pointer to a source Filter object, note destroying the object does not deactivate @@ -215,13 +218,13 @@ the filter */ HELICS_CXX_EXPORT std::unique_ptr make_cloning_filter(FilterTypes type, - Core* cr, + Core* core, std::string_view delivery, std::string_view name = EMPTY_STRING); /** create a cloning filter with a delivery location @param type the type of filter to create -@param cr the core to create the filter through +@param core the core to create the filter through @param delivery the endpoint to deliver the cloned message to @param name the name of the filter (optional) @return a unique pointer to a source Filter object, note destroying the object does not deactivate @@ -229,7 +232,7 @@ the filter */ HELICS_CXX_EXPORT std::unique_ptr make_cloning_filter(FilterTypes type, - CoreApp& cr, + CoreApp& core, std::string_view delivery, std::string_view name = EMPTY_STRING); diff --git a/src/helics/application_api/HelicsPrimaryTypes.hpp b/src/helics/application_api/HelicsPrimaryTypes.hpp index 088a7b1b53..b14ad95ee8 100644 --- a/src/helics/application_api/HelicsPrimaryTypes.hpp +++ b/src/helics/application_api/HelicsPrimaryTypes.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -23,8 +23,11 @@ SPDX-License-Identifier: BSD-3-Clause API and core */ namespace helics { -/** define a variant with the different types*/ +/** detect if a string is not a string that represents false*/ +HELICS_CXX_EXPORT bool isTrueString(std::string_view str); + +/** define a variant with the different types*/ using defV = std::variant(obj); } /** extract the value from a variant to a string*/ -HELICS_CXX_EXPORT void valueExtract(const defV& dv, std::string& val); +HELICS_CXX_EXPORT void valueExtract(const defV& data, std::string& val); /** extract the value from a variant to a complex number*/ -HELICS_CXX_EXPORT void valueExtract(const defV& dv, std::complex& val); +HELICS_CXX_EXPORT void valueExtract(const defV& data, std::complex& val); /** extract the value from a variant to a vector of doubles*/ -HELICS_CXX_EXPORT void valueExtract(const defV& dv, std::vector& val); +HELICS_CXX_EXPORT void valueExtract(const defV& data, std::vector& val); /** extract the value from a variant to a complex vector of doubles*/ -HELICS_CXX_EXPORT void valueExtract(const defV& dv, std::vector>& val); +HELICS_CXX_EXPORT void valueExtract(const defV& data, std::vector>& val); /** extract the value from a variant to a named point*/ -HELICS_CXX_EXPORT void valueExtract(const defV& dv, NamedPoint& val); +HELICS_CXX_EXPORT void valueExtract(const defV& data, NamedPoint& val); /** extract the value from a variant to a named point*/ -HELICS_CXX_EXPORT void valueExtract(const defV& dv, Time& val); +HELICS_CXX_EXPORT void valueExtract(const defV& data, Time& val); /** extract the value from a variant to a character*/ -HELICS_CXX_EXPORT void valueExtract(const defV& dv, char& val); +HELICS_CXX_EXPORT void valueExtract(const defV& data, char& val); /** extract the value from a variant to a bool*/ -HELICS_CXX_EXPORT void valueExtract(const defV& dv, bool& val); +HELICS_CXX_EXPORT void valueExtract(const defV& data, bool& val); -HELICS_CXX_EXPORT defV readJsonValue(const data_view& dv); +HELICS_CXX_EXPORT defV readJsonValue(const data_view& data); -HELICS_CXX_EXPORT void valueExtract(const data_view& dv, DataType baseType, std::string& val); +HELICS_CXX_EXPORT void valueExtract(const data_view& data, DataType baseType, std::string& val); HELICS_CXX_EXPORT void - valueExtract(const data_view& dv, DataType baseType, std::vector& val); + valueExtract(const data_view& data, DataType baseType, std::vector& val); HELICS_CXX_EXPORT void - valueExtract(const data_view& dv, DataType baseType, std::complex& val); + valueExtract(const data_view& data, DataType baseType, std::complex& val); HELICS_CXX_EXPORT void - valueExtract(const data_view& dv, DataType baseType, std::vector>& val); + valueExtract(const data_view& data, DataType baseType, std::vector>& val); -HELICS_CXX_EXPORT void valueExtract(const data_view& dv, DataType baseType, NamedPoint& val); +HELICS_CXX_EXPORT void valueExtract(const data_view& data, DataType baseType, NamedPoint& val); -HELICS_CXX_EXPORT void valueExtract(const data_view& dv, DataType baseType, Time& val); +HELICS_CXX_EXPORT void valueExtract(const data_view& data, DataType baseType, Time& val); -HELICS_CXX_EXPORT void valueExtract(const data_view& dv, DataType baseType, bool& val); +HELICS_CXX_EXPORT void valueExtract(const data_view& data, DataType baseType, bool& val); -HELICS_CXX_EXPORT void valueExtract(const data_view& dv, DataType baseType, defV& val); +HELICS_CXX_EXPORT void valueExtract(const data_view& data, DataType baseType, defV& val); -HELICS_CXX_EXPORT void valueExtract(const data_view& dv, DataType baseType, char& val); +HELICS_CXX_EXPORT void valueExtract(const data_view& data, DataType baseType, char& val); /** extract the value from a variant to a numerical type*/ template std::enable_if_t::value && (!std::is_same::value)> - valueExtract(const defV& dv, X& val) + valueExtract(const defV& data, X& val) { - switch (dv.index()) { + switch (data.index()) { case double_loc: // double - val = static_cast(std::get(dv)); + val = static_cast(std::get(data)); break; case int_loc: // int64_t - val = static_cast(std::get(dv)); + val = static_cast(std::get(data)); break; case string_loc: // string default: { - const auto& v = std::get(dv); + const auto& v = std::get(data); if (v.find_first_of(".eE[]") == std::string::npos) { val = static_cast(getIntFromString(v)); } else { @@ -189,20 +192,20 @@ std::enable_if_t::value && (!std::is_same::value) break; case complex_loc: // complex { - auto& cv = std::get>(dv); + auto& cv = std::get>(data); val = static_cast((cv.imag() != 0.0) ? std::abs(cv) : cv.real()); } break; case vector_loc: // vector { - const auto& vec = std::get>(dv); + const auto& vec = std::get>(data); val = static_cast((vec.size() == 1) ? vec[0] : vectorNorm(vec)); break; } case complex_vector_loc: // complex vector { - const auto& vec = std::get>>(dv); + const auto& vec = std::get>>(data); double vald{0.0}; if (vec.size() == 1) { if (vec[0].imag() == 0.0) { @@ -217,7 +220,7 @@ std::enable_if_t::value && (!std::is_same::value) break; } case named_point_loc: { - const auto& np = std::get(dv); + const auto& np = std::get(data); if (std::isnan(np.value)) { if (np.name.find_first_of(".eE[]") == std::string::npos) { val = static_cast(getIntFromString(np.name)); @@ -235,19 +238,19 @@ std::enable_if_t::value && (!std::is_same::value) /** assume it is some numeric type (int or double)*/ template std::enable_if_t::value && (!std::is_same::value)> - valueExtract(const data_view& dv, DataType baseType, X& val) + valueExtract(const data_view& data, DataType baseType, X& val) { switch (baseType) { case DataType::HELICS_ANY: { defV val_dv; - valueExtract(dv, baseType, val_dv); + valueExtract(data, baseType, val_dv); valueExtract(val_dv, val); break; } case DataType::HELICS_STRING: case DataType::HELICS_CHAR: default: { - const auto v = ValueConverter::interpret(dv); + const auto v = ValueConverter::interpret(data); if (v.find_first_of(".eE[]") == std::string_view::npos) { val = static_cast(getIntFromString(v)); } else { @@ -257,10 +260,10 @@ std::enable_if_t::value && (!std::is_same::value) break; case DataType::HELICS_BOOL: - val = static_cast((ValueConverter::interpret(dv) != "0")); + val = static_cast((ValueConverter::interpret(data) != "0")); break; case DataType::HELICS_NAMED_POINT: { - auto npval = ValueConverter::interpret(dv); + auto npval = ValueConverter::interpret(data); if (std::isnan(npval.value)) { try { if (npval.name.find_first_of(".eE[]") == std::string::npos) { @@ -281,24 +284,24 @@ std::enable_if_t::value && (!std::is_same::value) break; } case DataType::HELICS_DOUBLE: { - auto V = ValueConverter::interpret(dv); + auto V = ValueConverter::interpret(data); val = static_cast(V); break; } case DataType::HELICS_INT: { - auto V = ValueConverter::interpret(dv); + auto V = ValueConverter::interpret(data); val = static_cast(V); break; } case DataType::HELICS_TIME: { Time vtime; - vtime.setBaseTimeCode(ValueConverter::interpret(dv)); + vtime.setBaseTimeCode(ValueConverter::interpret(data)); val = std::is_integral::value ? static_cast(vtime.getBaseTimeCode()) : static_cast(static_cast(vtime)); break; } case DataType::HELICS_VECTOR: { - auto V = ValueConverter>::interpret(dv); + auto V = ValueConverter>::interpret(data); if (V.size() == 1) { val = static_cast(V[0]); } else { @@ -307,13 +310,13 @@ std::enable_if_t::value && (!std::is_same::value) break; } case DataType::HELICS_COMPLEX: { - auto V = ValueConverter>::interpret(dv); + auto V = ValueConverter>::interpret(data); val = static_cast((V.imag() != 0) ? std::abs(V) : V.real()); break; } case DataType::HELICS_COMPLEX_VECTOR: { - auto V = ValueConverter>>::interpret(dv); + auto V = ValueConverter>>::interpret(data); if (V.size() == 1) { if (V[0].imag() == 0) { val = static_cast(V[0].real()); @@ -327,7 +330,7 @@ std::enable_if_t::value && (!std::is_same::value) break; } case DataType::HELICS_JSON: - valueExtract(readJsonValue(dv), val); + valueExtract(readJsonValue(data), val); break; case DataType::HELICS_CUSTOM: throw(std::invalid_argument("unrecognized helics type")); diff --git a/src/helics/application_api/Inputs.cpp b/src/helics/application_api/Inputs.cpp index 579bd37a21..e505c36cd2 100644 --- a/src/helics/application_api/Inputs.cpp +++ b/src/helics/application_api/Inputs.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/application_api/Inputs.hpp b/src/helics/application_api/Inputs.hpp index 1aa3e695da..81f391b97f 100644 --- a/src/helics/application_api/Inputs.hpp +++ b/src/helics/application_api/Inputs.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/application_api/MessageFederate.cpp b/src/helics/application_api/MessageFederate.cpp index 5847736591..a87d2477ca 100644 --- a/src/helics/application_api/MessageFederate.cpp +++ b/src/helics/application_api/MessageFederate.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -18,44 +18,31 @@ SPDX-License-Identifier: BSD-3-Clause #include namespace helics { -MessageFederate::MessageFederate(std::string_view fedName, const FederateInfo& fi): - Federate(fedName, fi) +MessageFederate::MessageFederate(std::string_view fedName, const FederateInfo& fedInfo): + Federate(fedName, fedInfo) { - mfManager = std::make_unique(coreObject.get(), - this, - getID(), - singleThreadFederate); + loadFederateData(); } MessageFederate::MessageFederate(std::string_view fedName, const std::shared_ptr& core, - const FederateInfo& fi): - Federate(fedName, core, fi) + const FederateInfo& fedInfo): + Federate(fedName, core, fedInfo) { - mfManager = std::make_unique(coreObject.get(), - this, - getID(), - singleThreadFederate); + loadFederateData(); } -MessageFederate::MessageFederate(std::string_view fedName, CoreApp& core, const FederateInfo& fi): - Federate(fedName, core, fi) +MessageFederate::MessageFederate(std::string_view fedName, + CoreApp& core, + const FederateInfo& fedInfo): + Federate(fedName, core, fedInfo) { - mfManager = std::make_unique(coreObject.get(), - this, - getID(), - singleThreadFederate); + loadFederateData(); } MessageFederate::MessageFederate(std::string_view fedName, const std::string& configString): Federate(fedName, loadFederateInfo(configString)) { - mfManager = std::make_unique(coreObject.get(), - this, - getID(), - singleThreadFederate); - if (looksLikeFile(configString)) { - MessageFederate::registerInterfaces(configString); - } + loadFederateData(); } MessageFederate::MessageFederate(const std::string& configString): @@ -77,10 +64,7 @@ MessageFederate::MessageFederate(bool /*unused*/) { // this constructor should only be called by child class that has already constructed the // underlying federate in // a virtual inheritance - mfManager = std::make_unique(coreObject.get(), - this, - getID(), - singleThreadFederate); + loadFederateData(); } MessageFederate::MessageFederate(MessageFederate&&) noexcept = default; @@ -96,6 +80,16 @@ MessageFederate& MessageFederate::operator=(MessageFederate&& mFed) noexcept MessageFederate::~MessageFederate() = default; +void MessageFederate::loadFederateData() +{ + mfManager = std::make_unique(coreObject.get(), + this, + getID(), + singleThreadFederate); + if (!configFile.empty()) { + MessageFederate::registerMessageInterfaces(configFile); + } +} void MessageFederate::disconnect() { Federate::disconnect(); @@ -171,7 +165,7 @@ static void loadOptions(MessageFederate* fed, const Inp& data, Endpoint& ept) using fileops::getOrDefault; addTargets(data, "flags", [&ept, fed](const std::string& target) { auto oindex = getOptionIndex((target.front() != '-') ? target : target.substr(1)); - int val = (target.front() != '-') ? 1 : 0; + const int val = (target.front() != '-') ? 1 : 0; if (oindex == HELICS_INVALID_OPTION_INDEX) { fed->logWarningMessage(target + " is not a recognized flag"); return; @@ -193,12 +187,26 @@ static void loadOptions(MessageFederate* fed, const Inp& data, Endpoint& ept) }); addTargets(data, "subscriptions", [&ept](std::string_view sub) { ept.subscribe(sub); }); addTargets(data, "filters", [&ept](std::string_view filt) { ept.addSourceFilter(filt); }); - addTargets(data, "sourceFilters", [&ept](std::string_view filt) { ept.addSourceFilter(filt); }); + addTargetVariations(data, "source", "inputs", [&ept](std::string_view ipt) { + ept.subscribe(ipt); + }); + addTargetVariations(data, "source", "filters", [&ept](std::string_view filt) { + ept.addSourceFilter(filt); + }); + addTargetVariations(data, "destination", "filters", [&ept](std::string_view filt) { + ept.addDestinationFilter(filt); + }); + addTargetVariations(data, "source", "endpoints", [&ept](std::string_view endpoint) { + ept.addSourceEndpoint(endpoint); + }); + addTargetVariations(data, "destination", "endpoints", [&ept](std::string_view endpoint) { + ept.addDestinationEndpoint(endpoint); + }); addTargets(data, "destFilters", [&ept](std::string_view filt) { ept.addDestinationFilter(filt); }); - auto defTarget = getOrDefault(data, "target", emptyStr); + auto defTarget = fileops::getOrDefault(data, "target", emptyStr); fileops::replaceIfMember(data, "destination", defTarget); if (!defTarget.empty()) { ept.setDefaultDestination(defTarget); @@ -214,7 +222,7 @@ void MessageFederate::registerMessageInterfacesJson(const std::string& jsonStrin for (const auto& ept : doc["endpoints"]) { auto eptName = fileops::getName(ept); auto type = fileops::getOrDefault(ept, "type", emptyStr); - bool global = fileops::getOrDefault(ept, "global", defaultGlobal); + const bool global = fileops::getOrDefault(ept, "global", defaultGlobal); Endpoint& epObj = (global) ? registerGlobalEndpoint(eptName, type) : registerEndpoint(eptName, type); @@ -252,7 +260,7 @@ void MessageFederate::registerMessageInterfacesToml(const std::string& tomlStrin for (auto& ept : eptArray) { auto key = fileops::getName(ept); auto type = fileops::getOrDefault(ept, "type", emptyStr); - bool global = fileops::getOrDefault(ept, "global", defaultGlobal); + const bool global = fileops::getOrDefault(ept, "global", defaultGlobal); Endpoint& epObj = (global) ? registerGlobalEndpoint(key, type) : registerEndpoint(key, type); @@ -329,11 +337,11 @@ std::unique_ptr MessageFederate::getMessage(const Endpoint& ept) Endpoint& MessageFederate::getEndpoint(std::string_view eptName) const { - auto& id = mfManager->getEndpoint(eptName); - if (!id.isValid()) { + auto& ept = mfManager->getEndpoint(eptName); + if (!ept.isValid()) { return mfManager->getEndpoint(localNameGenerator(eptName)); } - return id; + return ept; } Endpoint& MessageFederate::getDataSink(std::string_view sinkName) const diff --git a/src/helics/application_api/MessageFederate.hpp b/src/helics/application_api/MessageFederate.hpp index 6b2cc87e5c..8c3e915c44 100644 --- a/src/helics/application_api/MessageFederate.hpp +++ b/src/helics/application_api/MessageFederate.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -25,31 +25,31 @@ class HELICS_CXX_EXPORT MessageFederate: public: /**constructor taking a federate information structure and using the default core @param fedName the name of the messageFederate, can be left empty to use a default or one from - fi - @param fi a federate information structure + fedInfo + @param fedInfo a federate information structure */ - MessageFederate(std::string_view fedName, const FederateInfo& fi); - /**constructor taking a core and a federate information structure, core information in fi is - ignored + MessageFederate(std::string_view fedName, const FederateInfo& fedInfo); + /**constructor taking a core and a federate information structure, core information in fedInfo + is ignored @param fedName the name of the messageFederate, can be left empty to use a default or one from - fi + fedInfo @param core a shared ptr to a core to join - @param fi a federate information structure + @param fedInfo a federate information structure */ MessageFederate(std::string_view fedName, const std::shared_ptr& core, - const FederateInfo& fi = FederateInfo{}); + const FederateInfo& fedInfo = FederateInfo{}); - /**constructor taking a core and a federate information structure, core information in fi is - ignored + /**constructor taking a core and a federate information structure, core information in fedInfo + is ignored @param fedName the name of the messageFederate, can be left empty to use a default or one from - fi + fedInfo @param core a CoreApp object representing the core to connect to - @param fi a federate information structure + @param fedInfo a federate information structure */ MessageFederate(std::string_view fedName, CoreApp& core, - const FederateInfo& fi = FederateInfo{}); + const FederateInfo& fedInfo = FederateInfo{}); /**constructor taking a string with the required information @param name the name of the federate, can be empty to get name from config @@ -153,6 +153,8 @@ class HELICS_CXX_EXPORT MessageFederate: void registerMessageInterfaces(const std::string& configString); private: + /** function to register the federate with the core*/ + void loadFederateData(); /** register a set Message interfaces from JSON @details call is only valid in startup mode it is a protected call to add an @param jsonString the location of the file or JSON String to load to generate the interfaces diff --git a/src/helics/application_api/MessageFederateManager.cpp b/src/helics/application_api/MessageFederateManager.cpp index 5d13884b4c..d5b267b607 100644 --- a/src/helics/application_api/MessageFederateManager.cpp +++ b/src/helics/application_api/MessageFederateManager.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/application_api/MessageFederateManager.hpp b/src/helics/application_api/MessageFederateManager.hpp index d614785683..13b9c27f8a 100644 --- a/src/helics/application_api/MessageFederateManager.hpp +++ b/src/helics/application_api/MessageFederateManager.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/application_api/MessageOperators.cpp b/src/helics/application_api/MessageOperators.cpp index 6c5307e6e9..76166de529 100644 --- a/src/helics/application_api/MessageOperators.cpp +++ b/src/helics/application_api/MessageOperators.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/application_api/MessageOperators.hpp b/src/helics/application_api/MessageOperators.hpp index 3f6eb344c6..07d627bf7d 100644 --- a/src/helics/application_api/MessageOperators.hpp +++ b/src/helics/application_api/MessageOperators.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/application_api/Publications.cpp b/src/helics/application_api/Publications.cpp index 531f1366b8..8966846865 100644 --- a/src/helics/application_api/Publications.cpp +++ b/src/helics/application_api/Publications.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/application_api/Publications.hpp b/src/helics/application_api/Publications.hpp index 276afae6c8..62e5d26194 100644 --- a/src/helics/application_api/Publications.hpp +++ b/src/helics/application_api/Publications.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/application_api/Subscriptions.hpp b/src/helics/application_api/Subscriptions.hpp index 9f5e2528a4..5bbe790836 100644 --- a/src/helics/application_api/Subscriptions.hpp +++ b/src/helics/application_api/Subscriptions.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -20,33 +20,6 @@ SPDX-License-Identifier: BSD-3-Clause namespace helics { -/** get a value directly from the subscription key name -@details this is a convenience function to get a value directly from the subscription key name -this function should not be used as the primary means of retrieving value as it does involve an -additional map find operation vs the member getValue calls -@param fed a reference to a valueFederate -@param key the name of the publication -*/ -template -X getValue(ValueFederate& fed, std::string_view key) -{ - return fed.getInput(key).getValue(); -} - -/** get a value directly from the subscription key name -@details this is a convenience function to get a value directly from the subscription key name -this function should not be used as the primary means of retrieving value as it does involve an -additional map find operation vs the member getValue calls -@param fed a reference to a valueFederate -@param key the name of the publication -@param obj the obj to store the retrieved value -*/ -template -void getValue(ValueFederate& fed, std::string_view key, X& obj) -{ - fed.getSubscription(key).getValue(obj); -} - /** class to handle a Vector Subscription @tparam X the class of the value associated with the vector subscription */ diff --git a/src/helics/application_api/Translator.cpp b/src/helics/application_api/Translator.cpp index 3b7bc97b56..b177c438ba 100644 --- a/src/helics/application_api/Translator.cpp +++ b/src/helics/application_api/Translator.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -43,12 +43,12 @@ void addOperations(Translator* trans, TranslatorTypes type) default: break; case TranslatorTypes::JSON: { - auto op = std::make_shared(); - trans->setTranslatorOperations(std::move(op)); + auto operation = std::make_shared(); + trans->setTranslatorOperations(std::move(operation)); } break; case TranslatorTypes::BINARY: { - auto op = std::make_shared(); - trans->setTranslatorOperations(std::move(op)); + auto operation = std::make_shared(); + trans->setTranslatorOperations(std::move(operation)); } break; } } @@ -66,15 +66,15 @@ Translator::Translator(Core* core, std::string_view translatorName, InterfaceHan Translator::Translator(Core* core, const std::string_view translatorName): Interface(core, InterfaceHandle(), translatorName) { - if (cr != nullptr) { - handle = cr->registerTranslator(translatorName, std::string_view{}, std::string_view{}); + if (mCore != nullptr) { + handle = mCore->registerTranslator(translatorName, std::string_view{}, std::string_view{}); } } -void Translator::setOperator(std::shared_ptr mo) +void Translator::setOperator(std::shared_ptr operation) { - if (mo) { - setTranslatorOperations(std::make_shared(std::move(mo))); + if (operation) { + setTranslatorOperations(std::make_shared(std::move(operation))); } else { setTranslatorOperations(nullptr); } @@ -83,8 +83,8 @@ void Translator::setOperator(std::shared_ptr mo) void Translator::setTranslatorOperations(std::shared_ptr translatorOps) { transOp = std::move(translatorOps); - if (cr != nullptr) { - cr->setTranslatorOperator(handle, (transOp) ? transOp->getOperator() : nullptr); + if (mCore != nullptr) { + mCore->setTranslatorOperator(handle, (transOp) ? transOp->getOperator() : nullptr); } } diff --git a/src/helics/application_api/Translator.hpp b/src/helics/application_api/Translator.hpp index 0ce7fdbe51..f87ce63c20 100644 --- a/src/helics/application_api/Translator.hpp +++ b/src/helics/application_api/Translator.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -58,7 +58,7 @@ class HELICS_CXX_EXPORT Translator: public Interface { Translator& operator=(const Translator& trans) = default; /** set a message operator to process the message*/ - void setOperator(std::shared_ptr mo); + void setOperator(std::shared_ptr operation); virtual const std::string& getDisplayName() const override { return getName(); } diff --git a/src/helics/application_api/TranslatorOperations.cpp b/src/helics/application_api/TranslatorOperations.cpp index e2216e016f..4c4064f9e1 100644 --- a/src/helics/application_api/TranslatorOperations.cpp +++ b/src/helics/application_api/TranslatorOperations.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/application_api/TranslatorOperations.hpp b/src/helics/application_api/TranslatorOperations.hpp index 4d60c4af8f..4e11839390 100644 --- a/src/helics/application_api/TranslatorOperations.hpp +++ b/src/helics/application_api/TranslatorOperations.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/application_api/ValueConverter.cpp b/src/helics/application_api/ValueConverter.cpp index 3ee0be300b..441b00e565 100644 --- a/src/helics/application_api/ValueConverter.cpp +++ b/src/helics/application_api/ValueConverter.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -13,314 +13,313 @@ SPDX-License-Identifier: BSD-3-Clause #include #include -namespace helics { - -namespace detail { - namespace checks { - /*! This code in checks namespace exerpted from cereal portable binary archives - code is modified slightly to fit name conventions and make use of C++17 - - Copyright (c) 2014, Randolph Voorhies, Shane Grant - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of cereal nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - //! Returns true if the current machine is little endian - /*! @ingroup Internal */ - inline bool isLittleEndian() - { - static constexpr std::int32_t test{1}; - return *reinterpret_cast(&test) == 1; - } - - //! Swaps the order of bytes for some chunk of memory - /*! @param data The data as a uint8_t pointer - @tparam DataSize The true size of the data - @ingroup Internal */ - template - inline void swapBytes(std::byte* data) - { - for (std::size_t i = 0, end = DataSize / 2; i < end; ++i) { - std::swap(data[i], data[DataSize - i - 1]); - } - } - } // namespace checks - static constexpr const std::byte doubleCode{0xB0}; - static constexpr const std::byte intCode{0x50}; - static constexpr const std::byte complexCode{0x12}; - static constexpr const std::byte stringCode{0x0E}; - static constexpr const std::byte vectorCode{0x6C}; - static constexpr const std::byte npCode{0xAE}; - static constexpr const std::byte cvCode{0x62}; - static constexpr const std::byte customCode{0xF4}; - - static constexpr std::byte endianMask{0x01}; - // static constexpr std::byte lowByteMask{0xFF}; - // static constexpr std::byte codeMask{0xFE}; - - static const std::byte endianCode = checks::isLittleEndian() ? std::byte{0} : std::byte{1}; - - static constexpr const std::byte littleEndianCode{0x0}; - // static constexpr const std::byte bigEndianCode{0x01}; - - static inline void addCodeAndSize(std::byte* data, std::byte code, size_t size) +namespace helics::detail { + +namespace checks { + /*! This code in checks namespace exerpted from cereal portable binary archives + code is modified slightly to fit name conventions and make use of C++17 + + Copyright (c) 2014, Randolph Voorhies, Shane Grant + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of cereal nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + //! Returns true if the current machine is little endian + /*! @ingroup Internal */ + inline bool isLittleEndian() { - std::memset(data, 0, 8); - data[0] = code; - data[3] = littleEndianCode; - data[4] = std::byte((size >> 24U) & 0xFFU); - data[5] = std::byte((size >> 16U) & 0xFFU); - data[6] = std::byte((size >> 8U) & 0xFFU); - data[7] = std::byte((size & 0xFFU)); + static constexpr std::int32_t test{1}; + return *reinterpret_cast(&test) == 1; } - size_t convertToBinary(std::byte* data, double val) + //! Swaps the order of bytes for some chunk of memory + /*! @param data The data as a uint8_t pointer + @tparam DataSize The true size of the data + @ingroup Internal */ + template + inline void swapBytes(std::byte* data) { - addCodeAndSize(data, doubleCode, 1); - std::memcpy(data + 8, &val, 8); - return 16; + for (std::size_t i = 0, end = DataSize / 2; i < end; ++i) { + std::swap(data[i], data[DataSize - i - 1]); + } } +} // namespace checks +static constexpr const std::byte doubleCode{0xB0}; +static constexpr const std::byte intCode{0x50}; +static constexpr const std::byte complexCode{0x12}; +static constexpr const std::byte stringCode{0x0E}; +static constexpr const std::byte vectorCode{0x6C}; +static constexpr const std::byte npCode{0xAE}; +static constexpr const std::byte cvCode{0x62}; +static constexpr const std::byte customCode{0xF4}; + +static constexpr std::byte endianMask{0x01}; +// static constexpr std::byte lowByteMask{0xFF}; +// static constexpr std::byte codeMask{0xFE}; + +static const std::byte endianCode = checks::isLittleEndian() ? std::byte{0} : std::byte{1}; + +static constexpr const std::byte littleEndianCode{0x0}; +// static constexpr const std::byte bigEndianCode{0x01}; + +static inline void addCodeAndSize(std::byte* data, std::byte code, size_t size) +{ + std::memset(data, 0, 8); + data[0] = code; + data[3] = littleEndianCode; + data[4] = static_cast((size >> 24U) & 0xFFU); + data[5] = static_cast((size >> 16U) & 0xFFU); + data[6] = static_cast((size >> 8U) & 0xFFU); + data[7] = static_cast((size & 0xFFU)); +} - size_t convertToBinary(std::byte* data, std::int64_t val) - { - addCodeAndSize(data, intCode, 1); - std::memcpy(data + 8, &val, 8); - return 16; - } +size_t convertToBinary(std::byte* data, double val) +{ + addCodeAndSize(data, doubleCode, 1); + std::memcpy(data + 8, &val, 8); + return 16; +} - size_t convertToBinary(std::byte* data, std::complex val) - { - addCodeAndSize(data, complexCode, 2); - std::memcpy(data + 8, &val, 16); - return 24; - } +size_t convertToBinary(std::byte* data, std::int64_t val) +{ + addCodeAndSize(data, intCode, 1); + std::memcpy(data + 8, &val, 8); + return 16; +} - size_t convertToBinary(std::byte* data, std::string_view val) - { - addCodeAndSize(data, stringCode, val.size()); - if (!val.empty()) { - std::memcpy(data + 8U, val.data(), val.size()); - } - return val.size() + 8U; - } +size_t convertToBinary(std::byte* data, std::complex val) +{ + addCodeAndSize(data, complexCode, 2); + std::memcpy(data + 8, &val, 16); + return 24; +} - size_t convertToBinary(std::byte* data, const NamedPoint& val) - { - addCodeAndSize(data, npCode, val.name.size()); - std::memcpy(data + 8, &val.value, 8); - if (!val.name.empty()) { - std::memcpy(data + 16, val.name.data(), val.name.size()); - } - return val.name.size() + 16U; +size_t convertToBinary(std::byte* data, std::string_view val) +{ + addCodeAndSize(data, stringCode, val.size()); + if (!val.empty()) { + std::memcpy(data + 8U, val.data(), val.size()); } + return val.size() + 8U; +} - size_t convertToBinary(std::byte* data, const std::vector& val) - { - addCodeAndSize(data, vectorCode, val.size()); - if (!val.empty()) { - std::memcpy(data + 8, val.data(), val.size() * sizeof(double)); - } - return val.size() * sizeof(double) + 8U; +size_t convertToBinary(std::byte* data, const NamedPoint& val) +{ + addCodeAndSize(data, npCode, val.name.size()); + std::memcpy(data + 8, &val.value, 8); + if (!val.name.empty()) { + std::memcpy(data + 16, val.name.data(), val.name.size()); } + return val.name.size() + 16U; +} - size_t convertToBinary(std::byte* data, const double* val, size_t size) - { - addCodeAndSize(data, vectorCode, size); - if (size > 0) { - std::memcpy(data + 8, val, size * sizeof(double)); - } - return size * sizeof(double) + 8U; +size_t convertToBinary(std::byte* data, const std::vector& val) +{ + addCodeAndSize(data, vectorCode, val.size()); + if (!val.empty()) { + std::memcpy(data + 8, val.data(), val.size() * sizeof(double)); } + return val.size() * sizeof(double) + 8U; +} - size_t convertToBinary(std::byte* data, const std::vector>& val) - { - addCodeAndSize(data, cvCode, val.size()); - if (!val.empty()) { - std::memcpy(data + 8, val.data(), val.size() * sizeof(double) * 2); - } - return val.size() * sizeof(double) * 2U + 8U; +size_t convertToBinary(std::byte* data, const double* val, size_t size) +{ + addCodeAndSize(data, vectorCode, size); + if (size > 0) { + std::memcpy(data + 8, val, size * sizeof(double)); } + return size * sizeof(double) + 8U; +} - size_t convertToBinary(std::byte* data, const std::complex* val, size_t size) - { - addCodeAndSize(data, cvCode, size); - std::memcpy(data + 8, val, size * sizeof(double) * 2); - return size * sizeof(double) * 2U + 8U; +size_t convertToBinary(std::byte* data, const std::vector>& val) +{ + addCodeAndSize(data, cvCode, val.size()); + if (!val.empty()) { + std::memcpy(data + 8, val.data(), val.size() * sizeof(double) * 2); } + return val.size() * sizeof(double) * 2U + 8U; +} - size_t getDataSize(const std::byte* data) - { - return (std::to_integer(data[4]) << 24U) + - (std::to_integer(data[5]) << 16U) + (std::to_integer(data[6]) << 8U) + - std::to_integer(data[7]); - } +size_t convertToBinary(std::byte* data, const std::complex* val, size_t size) +{ + addCodeAndSize(data, cvCode, size); + std::memcpy(data + 8, val, size * sizeof(double) * 2); + return size * sizeof(double) * 2U + 8U; +} - static constexpr const frozen::unordered_map typeDetect{ - {std::to_integer(intCode), DataType::HELICS_INT}, - {std::to_integer(doubleCode), DataType::HELICS_DOUBLE}, - {std::to_integer(complexCode), DataType::HELICS_COMPLEX}, - {std::to_integer(vectorCode), DataType::HELICS_VECTOR}, - {std::to_integer(cvCode), DataType::HELICS_COMPLEX_VECTOR}, - {std::to_integer(npCode), DataType::HELICS_NAMED_POINT}, - {std::to_integer(customCode), DataType::HELICS_CUSTOM}, - {std::to_integer(stringCode), DataType::HELICS_STRING}}; - - DataType detectType(const std::byte* data) - { - const auto* res = typeDetect.find(std::to_integer(data[0])); - return (res != typeDetect.end()) ? res->second : DataType::HELICS_UNKNOWN; - } +size_t getDataSize(const std::byte* data) +{ + return (std::to_integer(data[4]) << 24U) + (std::to_integer(data[5]) << 16U) + + (std::to_integer(data[6]) << 8U) + std::to_integer(data[7]); +} - void convertFromBinary(const std::byte* data, double& val) - { - std::memcpy(&val, data + 8, 8); - if ((data[0] & endianMask) != littleEndianCode) { - checks::swapBytes<8>(reinterpret_cast(&val)); - } +static constexpr const frozen::unordered_map typeDetect{ + {std::to_integer(intCode), DataType::HELICS_INT}, + {std::to_integer(doubleCode), DataType::HELICS_DOUBLE}, + {std::to_integer(complexCode), DataType::HELICS_COMPLEX}, + {std::to_integer(vectorCode), DataType::HELICS_VECTOR}, + {std::to_integer(cvCode), DataType::HELICS_COMPLEX_VECTOR}, + {std::to_integer(npCode), DataType::HELICS_NAMED_POINT}, + {std::to_integer(customCode), DataType::HELICS_CUSTOM}, + {std::to_integer(stringCode), DataType::HELICS_STRING}}; + +DataType detectType(const std::byte* data) +{ + const auto* res = typeDetect.find(std::to_integer(data[0])); + return (res != typeDetect.end()) ? res->second : DataType::HELICS_UNKNOWN; +} + +void convertFromBinary(const std::byte* data, double& val) +{ + std::memcpy(&val, data + 8, 8); + if ((data[0] & endianMask) != littleEndianCode) { + checks::swapBytes<8>(reinterpret_cast(&val)); } +} - void convertFromBinary(const std::byte* data, std::int64_t& val) - { - std::memcpy(&val, data + 8, 8); - if ((data[0] & endianMask) != littleEndianCode) { - checks::swapBytes<8>(reinterpret_cast(&val)); - } +void convertFromBinary(const std::byte* data, std::int64_t& val) +{ + std::memcpy(&val, data + 8, 8); + if ((data[0] & endianMask) != littleEndianCode) { + checks::swapBytes<8>(reinterpret_cast(&val)); } +} #if defined(__GNUC__) # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wstrict-aliasing" - // std::complex is explicitly allowed to alias like this in the standard +// std::complex is explicitly allowed to alias like this in the standard #endif - void convertFromBinary(const std::byte* data, std::complex& val) - { - // https://en.cppreference.com/w/cpp/numeric/complex - // the layout used here is guaranteed by the standard - std::memcpy(&reinterpret_cast(val)[0], data + 8, 8); - std::memcpy(&reinterpret_cast(val)[1], data + 16, 8); - if ((data[0] & endianMask) != littleEndianCode) { - checks::swapBytes<8>(reinterpret_cast(&val)); - checks::swapBytes<8>(reinterpret_cast(&val) + 8); - } +void convertFromBinary(const std::byte* data, std::complex& val) +{ + // https://en.cppreference.com/w/cpp/numeric/complex + // the layout used here is guaranteed by the standard + std::memcpy(&reinterpret_cast(val)[0], data + 8, 8); + std::memcpy(&reinterpret_cast(val)[1], data + 16, 8); + if ((data[0] & endianMask) != littleEndianCode) { + checks::swapBytes<8>(reinterpret_cast(&val)); + checks::swapBytes<8>(reinterpret_cast(&val) + 8); } +} #if defined(__GNUC__) # pragma GCC diagnostic pop #endif - void convertFromBinary(const std::byte* data, std::string& val) - { - std::size_t size = getDataSize(data); - val.assign(reinterpret_cast(data) + 8, - reinterpret_cast(data) + 8 + size); - } +void convertFromBinary(const std::byte* data, std::string& val) +{ + const std::size_t size = getDataSize(data); + val.assign(reinterpret_cast(data) + 8, + reinterpret_cast(data) + 8 + size); +} - void convertFromBinary(const std::byte* data, std::string_view& val) - { - std::size_t size = getDataSize(data); - val = std::string_view(reinterpret_cast(data) + 8, size); - } +void convertFromBinary(const std::byte* data, std::string_view& val) +{ + const std::size_t size = getDataSize(data); + val = std::string_view(reinterpret_cast(data) + 8, size); +} - void convertFromBinary(const std::byte* data, char* val) - { - std::size_t size = getDataSize(data); - memcpy(val, data + 8, size); - } +void convertFromBinary(const std::byte* data, char* val) +{ + const std::size_t size = getDataSize(data); + memcpy(val, data + 8, size); +} - void convertFromBinary(const std::byte* data, NamedPoint& val) - { - std::memcpy(&val.value, data + 8, 8); - std::size_t size = getDataSize(data); - val.name.assign(reinterpret_cast(data) + 16U, - reinterpret_cast(data) + 16U + size); - if ((data[0] & endianMask) != littleEndianCode) { - checks::swapBytes<8>(reinterpret_cast(&val.value)); - } +void convertFromBinary(const std::byte* data, NamedPoint& val) +{ + std::memcpy(&val.value, data + 8, 8); + const std::size_t size = getDataSize(data); + val.name.assign(reinterpret_cast(data) + 16U, + reinterpret_cast(data) + 16U + size); + if ((data[0] & endianMask) != littleEndianCode) { + checks::swapBytes<8>(reinterpret_cast(&val.value)); } +} - void convertFromBinary(const std::byte* data, std::vector& val) - { - std::size_t size = getDataSize(data); - val.resize(size); - if (size > 0) { - std::memcpy(val.data(), data + 8, size * sizeof(double)); - } - if ((data[0] & endianMask) != littleEndianCode) { - for (auto& v : val) { - checks::swapBytes<8>(reinterpret_cast(&v)); - } +void convertFromBinary(const std::byte* data, std::vector& val) +{ + const std::size_t size = getDataSize(data); + val.resize(size); + if (size > 0) { + std::memcpy(val.data(), data + 8, size * sizeof(double)); + } + if ((data[0] & endianMask) != littleEndianCode) { + for (auto& element : val) { + checks::swapBytes<8>(reinterpret_cast(&element)); } } +} - void convertFromBinary(const std::byte* data, double* val) - { - std::size_t size = getDataSize(data); - if (val != nullptr && size > 0) { - std::memcpy(val, data + 8, size * sizeof(double)); - } - if ((data[0] & endianMask) != littleEndianCode) { - double* v = val; - double* end = val + size; - while (v != end) { - checks::swapBytes<8>(reinterpret_cast(v++)); - } +void convertFromBinary(const std::byte* data, double* val) +{ + const std::size_t size = getDataSize(data); + if (val != nullptr && size > 0) { + std::memcpy(val, data + 8, size * sizeof(double)); + } + if ((data[0] & endianMask) != littleEndianCode) { + double* currentVal = val; + double* end = currentVal + size; + while (currentVal != end) { + checks::swapBytes<8>(reinterpret_cast(currentVal++)); } } +} #if defined(__GNUC__) # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wstrict-aliasing" - // std::complex is explicitly allowed to alias like this in the standard +// std::complex is explicitly allowed to alias like this in the standard #endif - void convertFromBinary(const std::byte* data, std::vector>& val) - { - std::size_t size = getDataSize(data); - val.resize(size); - if (size > 0) { - std::memcpy(reinterpret_cast(val.data()), - data + 8, - size * sizeof(std::complex)); - } - if ((data[0] & endianMask) != littleEndianCode) { - for (auto& v : val) { - // making use of array oriented access for complex numbers - // See https://en.cppreference.com/w/cpp/numeric/complex - checks::swapBytes<8>(reinterpret_cast(&v)); - checks::swapBytes<8>(reinterpret_cast(&v) + 8); - } +void convertFromBinary(const std::byte* data, std::vector>& val) +{ + const std::size_t size = getDataSize(data); + val.resize(size); + if (size > 0) { + std::memcpy(reinterpret_cast(val.data()), + data + 8, + size * sizeof(std::complex)); + } + if ((data[0] & endianMask) != littleEndianCode) { + for (auto& value : val) { + // making use of array oriented access for complex numbers + // See https://en.cppreference.com/w/cpp/numeric/complex + checks::swapBytes<8>(reinterpret_cast(&value)); + checks::swapBytes<8>(reinterpret_cast(&value) + 8); } } +} #if defined(__GNUC__) # pragma GCC diagnostic pop #endif -} // namespace detail +} // namespace helics::detail +namespace helics { void ValueConverter>::convert(const std::vector& val, SmallBuffer& store) { - Json::Value V(Json::arrayValue); + Json::Value json(Json::arrayValue); for (const auto& str : val) { - V.append(str); + json.append(str); } - auto strgen = fileops::generateJsonString(V); + auto strgen = fileops::generateJsonString(json); return ValueConverter::convert(strgen, store); } @@ -331,11 +330,11 @@ void ValueConverter>::interpret(const data_view& block, val.clear(); auto str = ValueConverter::interpret(block); try { - Json::Value V = fileops::loadJsonStr(str); - if (V.isArray()) { - val.reserve(V.size()); - for (auto& av : V) { - val.emplace_back(av.asString()); + const Json::Value json = fileops::loadJsonStr(str); + if (json.isArray()) { + val.reserve(json.size()); + for (const auto& arrayVal : json) { + val.emplace_back(arrayVal.asString()); } } else { val.emplace_back(str); diff --git a/src/helics/application_api/ValueConverter.hpp b/src/helics/application_api/ValueConverter.hpp index 8e1e869a3d..dfd17532df 100644 --- a/src/helics/application_api/ValueConverter.hpp +++ b/src/helics/application_api/ValueConverter.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/application_api/ValueFederate.cpp b/src/helics/application_api/ValueFederate.cpp index f26e5960d3..a591edbbf2 100644 --- a/src/helics/application_api/ValueFederate.cpp +++ b/src/helics/application_api/ValueFederate.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -25,49 +25,29 @@ SPDX-License-Identifier: BSD-3-Clause namespace helics { /**constructor taking a core engine and federate info structure */ -ValueFederate::ValueFederate(std::string_view fedName, const FederateInfo& fi): - Federate(fedName, fi) +ValueFederate::ValueFederate(std::string_view fedName, const FederateInfo& fedInfo): + Federate(fedName, fedInfo) { - // the core object get instantiated in the Federate constructor - vfManager = std::make_unique(coreObject.get(), - this, - getID(), - singleThreadFederate); - vfManager->useJsonSerialization = fi.useJsonSerialization; + loadFederateData(); } ValueFederate::ValueFederate(std::string_view fedName, const std::shared_ptr& core, - const FederateInfo& fi): - Federate(fedName, core, fi) + const FederateInfo& fedInfo): + Federate(fedName, core, fedInfo) { - vfManager = std::make_unique(coreObject.get(), - this, - getID(), - singleThreadFederate); - vfManager->useJsonSerialization = fi.useJsonSerialization; + loadFederateData(); } -ValueFederate::ValueFederate(std::string_view fedName, CoreApp& core, const FederateInfo& fi): - Federate(fedName, core, fi) +ValueFederate::ValueFederate(std::string_view fedName, CoreApp& core, const FederateInfo& fedInfo): + Federate(fedName, core, fedInfo) { - vfManager = std::make_unique(coreObject.get(), - this, - getID(), - singleThreadFederate); - vfManager->useJsonSerialization = fi.useJsonSerialization; + loadFederateData(); } ValueFederate::ValueFederate(std::string_view fedName, const std::string& configString): Federate(fedName, loadFederateInfo(configString)) { - vfManager = std::make_unique(coreObject.get(), - this, - getID(), - singleThreadFederate); - vfManager->useJsonSerialization = useJsonSerialization; - if (looksLikeFile(configString)) { - ValueFederate::registerInterfaces(configString); - } + loadFederateData(); } ValueFederate::ValueFederate(const std::string& configString): @@ -83,18 +63,26 @@ ValueFederate::ValueFederate(const char* configString): ValueFederate::ValueFederate() = default; ValueFederate::ValueFederate(bool /*res*/) +{ + loadFederateData(); +} + +ValueFederate::ValueFederate(ValueFederate&&) noexcept = default; + +ValueFederate::~ValueFederate() = default; + +void ValueFederate::loadFederateData() { vfManager = std::make_unique(coreObject.get(), this, getID(), singleThreadFederate); vfManager->useJsonSerialization = useJsonSerialization; + if (!configFile.empty()) { + ValueFederate::registerValueInterfaces(configFile); + } } -ValueFederate::ValueFederate(ValueFederate&&) noexcept = default; - -ValueFederate::~ValueFederate() = default; - void ValueFederate::disconnect() { Federate::disconnect(); @@ -213,7 +201,7 @@ static void loadOptions(ValueFederate* fed, const Inp& data, Obj& objUpdate) addTargets(data, "flags", [&objUpdate, fed](const std::string& target) { auto oindex = getOptionIndex((target.front() != '-') ? target : target.substr(1)); - int val = (target.front() != '-') ? 1 : 0; + const int val = (target.front() != '-') ? 1 : 0; if (oindex == HELICS_INVALID_OPTION_INDEX) { fed->logWarningMessage(target + " is not a valid flag"); return; @@ -261,7 +249,7 @@ void ValueFederate::registerValueInterfacesJson(const std::string& jsonString) auto type = fileops::getOrDefault(pub, "type", emptyStr); auto units = fileops::getOrDefault(pub, "unit", emptyStr); fileops::replaceIfMember(pub, "units", units); - bool global = fileops::getOrDefault(pub, "global", defaultGlobal); + const bool global = fileops::getOrDefault(pub, "global", defaultGlobal); if (global) { pubAct = ®isterGlobalPublication(name, type, units); } else { @@ -270,6 +258,11 @@ void ValueFederate::registerValueInterfacesJson(const std::string& jsonString) } loadOptions(this, pub, *pubAct); + auto addDestTarget = [pubAct](const std::string& target) { + pubAct->addDestinationTarget(target); + }; + addTargetVariations(pub, "destination", "inputs", addDestTarget); + addTargetVariations(pub, "destination", "targets", addDestTarget); } } if (doc.isMember("subscriptions")) { @@ -297,6 +290,11 @@ void ValueFederate::registerValueInterfacesJson(const std::string& jsonString) subAct->setDefault(defStr); } loadOptions(this, sub, *subAct); + auto addSourceTarget = [subAct](const std::string& target) { + subAct->addSourceTarget(target); + }; + addTargetVariations(sub, "source", "publications", addSourceTarget); + addTargetVariations(sub, "source", "targets", addSourceTarget); } } if (doc.isMember("inputs")) { @@ -309,7 +307,7 @@ void ValueFederate::registerValueInterfacesJson(const std::string& jsonString) auto type = fileops::getOrDefault(ipt, "type", emptyStr); auto units = fileops::getOrDefault(ipt, "unit", emptyStr); fileops::replaceIfMember(ipt, "units", units); - bool global = fileops::getOrDefault(ipt, "global", defaultGlobal); + const bool global = fileops::getOrDefault(ipt, "global", defaultGlobal); if (global) { inp = ®isterGlobalInput(name, type, units); } else { @@ -321,6 +319,11 @@ void ValueFederate::registerValueInterfacesJson(const std::string& jsonString) inp->setDefault(defStr); } loadOptions(this, ipt, *inp); + auto addSourceTarget = [inp](const std::string& target) { + inp->addSourceTarget(target); + }; + addTargetVariations(ipt, "source", "publications", addSourceTarget); + addTargetVariations(ipt, "source", "targets", addSourceTarget); } } } @@ -355,7 +358,7 @@ void ValueFederate::registerValueInterfacesToml(const std::string& tomlString) auto type = getOrDefault(pub, "type", emptyStr); auto units = getOrDefault(pub, "unit", emptyStr); replaceIfMember(pub, "units", units); - bool global = getOrDefault(pub, "global", defaultGlobal); + const bool global = getOrDefault(pub, "global", defaultGlobal); if (global) { pubObj = ®isterGlobalPublication(name, type, units); } else { @@ -363,6 +366,11 @@ void ValueFederate::registerValueInterfacesToml(const std::string& tomlString) } } loadOptions(this, pub, *pubObj); + auto addDestTarget = [pubObj](const std::string& target) { + pubObj->addDestinationTarget(target); + }; + addTargetVariations(pub, "destination", "inputs", addDestTarget); + addTargetVariations(pub, "destination", "targets", addDestTarget); } } if (isMember(doc, "subscriptions")) { @@ -381,23 +389,26 @@ void ValueFederate::registerValueInterfacesToml(const std::string& tomlString) fileops::replaceIfMember(sub, "target", name); skipNameTarget = true; } - Input* id = &vfManager->getInputByTarget(name); - if (!id->isValid()) { + Input* inp = &vfManager->getInputByTarget(name); + if (!inp->isValid()) { auto type = getOrDefault(sub, "type", emptyStr); auto units = getOrDefault(sub, "unit", emptyStr); replaceIfMember(sub, "units", units); - id = ®isterInput(emptyStr, type, units); + inp = ®isterInput(emptyStr, type, units); if (!skipNameTarget) { // this check is to prevent some warnings since targets get added later - id->addTarget(name); + inp->addTarget(name); } } auto defStr = fileops::getOrDefault(sub, "default", emptyStr); if (!defStr.empty()) { - id->setDefault(defStr); + inp->setDefault(defStr); } - loadOptions(this, sub, *id); + loadOptions(this, sub, *inp); + auto addDestTarget = [inp](const std::string& target) { inp->addSourceTarget(target); }; + addTargetVariations(sub, "source", "publications", addDestTarget); + addTargetVariations(sub, "source", "targets", addDestTarget); } } if (isMember(doc, "inputs")) { @@ -410,23 +421,26 @@ void ValueFederate::registerValueInterfacesToml(const std::string& tomlString) for (const auto& ipt : iptArray) { auto name = fileops::getName(ipt); - Input* id = &vfManager->getInput(name); - if (!id->isValid()) { + Input* inp = &vfManager->getInput(name); + if (!inp->isValid()) { auto type = getOrDefault(ipt, "type", emptyStr); auto units = getOrDefault(ipt, "unit", emptyStr); replaceIfMember(ipt, "units", units); - bool global = getOrDefault(ipt, "global", defaultGlobal); + const bool global = getOrDefault(ipt, "global", defaultGlobal); if (global) { - id = ®isterGlobalInput(name, type, units); + inp = ®isterGlobalInput(name, type, units); } else { - id = ®isterInput(name, type, units); + inp = ®isterInput(name, type, units); } } auto defStr = fileops::getOrDefault(ipt, "default", emptyStr); if (!defStr.empty()) { - id->setDefault(defStr); + inp->setDefault(defStr); } - loadOptions(this, ipt, *id); + loadOptions(this, ipt, *inp); + auto addDestTarget = [inp](const std::string& target) { inp->addSourceTarget(target); }; + addTargetVariations(ipt, "source", "publications", addDestTarget); + addTargetVariations(ipt, "source", "targets", addDestTarget); } } } @@ -458,16 +472,15 @@ static void generateData(std::vector>& vpairs, char separator, Json::Value val) { - auto mn = val.getMemberNames(); - for (auto& name : mn) { - auto& so = val[name]; - if (so.isObject()) { - generateData(vpairs, prefix + name + separator, separator, so); + for (auto& name : val.getMemberNames()) { + auto& field = val[name]; + if (field.isObject()) { + generateData(vpairs, prefix + name + separator, separator, field); } else { - if (so.isDouble()) { - vpairs.emplace_back(prefix + name, so.asDouble()); + if (field.isDouble()) { + vpairs.emplace_back(prefix + name, field.asDouble()); } else { - vpairs.emplace_back(prefix + name, so.asString()); + vpairs.emplace_back(prefix + name, field.asString()); } } } @@ -475,7 +488,7 @@ static void generateData(std::vector>& vpairs, void ValueFederate::registerFromPublicationJSON(const std::string& jsonString) { - auto jv = [&]() { + auto json = [&]() { try { return fileops::loadJson(jsonString); } @@ -485,14 +498,14 @@ void ValueFederate::registerFromPublicationJSON(const std::string& jsonString) }(); std::vector> vpairs; - generateData(vpairs, "", nameSegmentSeparator, jv); + generateData(vpairs, "", nameSegmentSeparator, json); - for (auto& vp : vpairs) { + for (auto& value : vpairs) { try { - if (vp.second.index() == 0) { - registerPublication(vp.first); + if (value.second.index() == 0) { + registerPublication(value.first); } else { - registerPublication(vp.first); + registerPublication(value.first); } } catch (const helics::RegistrationFailure&) { @@ -503,7 +516,7 @@ void ValueFederate::registerFromPublicationJSON(const std::string& jsonString) void ValueFederate::publishJSON(const std::string& jsonString) { - auto jv = [&]() { + auto json = [&]() { try { return fileops::loadJson(jsonString); } @@ -512,15 +525,15 @@ void ValueFederate::publishJSON(const std::string& jsonString) } }(); std::vector> vpairs; - generateData(vpairs, "", nameSegmentSeparator, jv); + generateData(vpairs, "", nameSegmentSeparator, json); - for (auto& vp : vpairs) { - auto& pub = getPublication(vp.first); + for (auto& value : vpairs) { + auto& pub = getPublication(value.first); if (pub.isValid()) { - if (vp.second.index() == 0) { - pub.publish(std::get(vp.second)); + if (value.second.index() == 0) { + pub.publish(std::get(value.second)); } else { - pub.publish(std::get(vp.second)); + pub.publish(std::get(value.second)); } } } diff --git a/src/helics/application_api/ValueFederate.hpp b/src/helics/application_api/ValueFederate.hpp index 790d216bb3..b4a030a133 100644 --- a/src/helics/application_api/ValueFederate.hpp +++ b/src/helics/application_api/ValueFederate.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -28,29 +28,31 @@ class HELICS_CXX_EXPORT ValueFederate: { public: /**constructor taking a federate information structure and using the default core - @param fedName the name of the federate, can be empty to use the name from fi or an auto + @param fedName the name of the federate, can be empty to use the name from fedInfo or an auto generated one - @param fi a federate information structure + @param fedInfo a federate information structure */ - ValueFederate(std::string_view fedName, const FederateInfo& fi); + ValueFederate(std::string_view fedName, const FederateInfo& fedInfo); - /**constructor taking a core and a federate information structure, core information in fi is - ignored - @param fedName the name of the federate, can be empty to use the name from fi or an auto + /**constructor taking a core and a federate information structure, core information in fedInfo + is ignored + @param fedName the name of the federate, can be empty to use the name from fedInfo or an auto generated one @param core a shared ptr to a core to join - @param fi a federate information structure + @param fedInfo a federate information structure */ ValueFederate(std::string_view fedName, const std::shared_ptr& core, - const FederateInfo& fi = FederateInfo{}); + const FederateInfo& fedInfo = FederateInfo{}); /**constructor taking a CoreApp and a federate information structure @param fedName the name of the federate can be empty to use a name from the federateInfo @param core a CoreApp with the core to connect to. - @param fi a federate information structure + @param fedInfo a federate information structure */ - ValueFederate(std::string_view fedName, CoreApp& core, const FederateInfo& fi = FederateInfo{}); + ValueFederate(std::string_view fedName, + CoreApp& core, + const FederateInfo& fedInfo = FederateInfo{}); /**constructor taking a string with the required information @param configString can be either a JSON file a TOML file (with extension TOML) or a string @@ -320,6 +322,8 @@ class HELICS_CXX_EXPORT ValueFederate: void registerValueInterfaces(const std::string& configString); private: + void loadFederateData(); + /** register interfaces through a json file or string*/ void registerValueInterfacesJson(const std::string& jsonString); /** register interface through a toml value or string*/ diff --git a/src/helics/application_api/ValueFederateManager.cpp b/src/helics/application_api/ValueFederateManager.cpp index 3eb8e524d2..a407d65cc3 100644 --- a/src/helics/application_api/ValueFederateManager.cpp +++ b/src/helics/application_api/ValueFederateManager.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/application_api/ValueFederateManager.hpp b/src/helics/application_api/ValueFederateManager.hpp index 5dc88643df..aba0dfaf6e 100644 --- a/src/helics/application_api/ValueFederateManager.hpp +++ b/src/helics/application_api/ValueFederateManager.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/application_api/data_view.hpp b/src/helics/application_api/data_view.hpp index 00c828ac52..f296a6ebea 100644 --- a/src/helics/application_api/data_view.hpp +++ b/src/helics/application_api/data_view.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/application_api/helicsPrimaryTypes.cpp b/src/helics/application_api/helicsPrimaryTypes.cpp index 83b35714ca..bbc94dab40 100644 --- a/src/helics/application_api/helicsPrimaryTypes.cpp +++ b/src/helics/application_api/helicsPrimaryTypes.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -29,30 +29,26 @@ bool changeDetected(const defV& prevValue, std::string_view val, double /*deltaV return true; } -static const std::set falseString{"0", - "", - "false", - "False", - "FALSE", - "f", - "F", - "0", - std::string(1, '\0'), - " ", - "no", - "NO", - "No", - "-"}; +static constexpr int nullstringRep{0}; +static const std::set falseString{ + "0", "", "false", + "False", "FALSE", "off", + "Off", "OFF", "disabled", + "Disabled", "DISABLED", "disable", + "Disable", "DISABLE", "f", + "F", "0", std::string_view(reinterpret_cast(&nullstringRep), 1), + " ", "no", "NO", + "No", "-"}; -static bool isTrueString(const std::string& str) +bool isTrueString(const std::string_view str) { - if (str == "1") { + if (str.size() == 1 && str[0] == '1') { return true; } - if (str == "0") { + if (str.size() == 1 && str[0] == '0') { return false; } - return (falseString.find(str) != falseString.end()); + return (falseString.find(str) == falseString.end()); } bool changeDetected(const defV& prevValue, bool val, double /*deltaV*/) @@ -171,55 +167,55 @@ bool changeDetected(const defV& prevValue, const NamedPoint& val, double deltaV) return true; } -void valueExtract(const defV& dv, std::string& val) +void valueExtract(const defV& data, std::string& val) { - switch (dv.index()) { + switch (data.index()) { case double_loc: // double - val = std::to_string(std::get(dv)); + val = std::to_string(std::get(data)); break; case int_loc: // int64_t - val = std::to_string(std::get(dv)); + val = std::to_string(std::get(data)); break; case string_loc: // string default: - val = std::get(dv); + val = std::get(data); break; case complex_loc: // complex - val = helicsComplexString(std::get>(dv)); + val = helicsComplexString(std::get>(data)); break; case vector_loc: // vector - val = helicsVectorString(std::get>(dv)); + val = helicsVectorString(std::get>(data)); break; case complex_vector_loc: // vector - val = helicsComplexVectorString(std::get>>(dv)); + val = helicsComplexVectorString(std::get>>(data)); break; case named_point_loc: { - const auto& np = std::get(dv); - val = (std::isnan(np.value)) ? np.name : helicsNamedPointString(np); + const auto& point = std::get(data); + val = (std::isnan(point.value)) ? point.name : helicsNamedPointString(point); break; } } } -void valueExtract(const defV& dv, std::complex& val) +void valueExtract(const defV& data, std::complex& val) { - switch (dv.index()) { + switch (data.index()) { case double_loc: // double - val = std::complex(std::get(dv), 0.0); + val = std::complex(std::get(data), 0.0); break; case int_loc: // int64_t - val = std::complex(static_cast(std::get(dv)), 0.0); + val = std::complex(static_cast(std::get(data)), 0.0); break; case string_loc: // string default: - val = getComplexFromString(std::get(dv)); + val = getComplexFromString(std::get(data)); break; case complex_loc: // complex - val = std::get>(dv); + val = std::get>(data); break; case vector_loc: // vector { - const auto& vec = std::get>(dv); + const auto& vec = std::get>(data); if (vec.size() == 1) { val = std::complex(vec[0], 0.0); } else if (vec.size() >= 2) { @@ -228,54 +224,54 @@ void valueExtract(const defV& dv, std::complex& val) break; } case complex_vector_loc: { - const auto& vec = std::get>>(dv); + const auto& vec = std::get>>(data); if (!vec.empty()) { val = vec.front(); } break; } case named_point_loc: { - const auto& np = std::get(dv); - if (std::isnan(np.value)) { - val = getComplexFromString(np.name); + const auto& point = std::get(data); + if (std::isnan(point.value)) { + val = getComplexFromString(point.name); } else { - val = std::complex(np.value, 0.0); + val = std::complex(point.value, 0.0); } } break; } } -void valueExtract(const defV& dv, std::vector& val) +void valueExtract(const defV& data, std::vector& val) { val.resize(0); - switch (dv.index()) { + switch (data.index()) { case double_loc: // double - val.push_back(std::get(dv)); + val.push_back(std::get(data)); break; case int_loc: // int64_t - val.push_back(static_cast(std::get(dv))); + val.push_back(static_cast(std::get(data))); break; case string_loc: // string default: - helicsGetVector(std::get(dv), val); + helicsGetVector(std::get(data), val); break; case complex_loc: // complex { - auto cval = std::get>(dv); + auto cval = std::get>(data); val.push_back(cval.real()); if (cval.imag() != 0.0) { val.push_back(cval.imag()); } } break; case vector_loc: // vector - val = std::get>(dv); + val = std::get>(data); break; case complex_vector_loc: // complex { - const auto& cv = std::get>>(dv); - val.reserve(cv.size()); + const auto& cvec = std::get>>(data); + val.reserve(cvec.size()); val.clear(); - for (const auto& cval : cv) { + for (const auto& cval : cvec) { if (cval.imag() == 0.0) { val.push_back(cval.real()); } else { @@ -285,88 +281,88 @@ void valueExtract(const defV& dv, std::vector& val) } break; case named_point_loc: // named point { - const auto& np = std::get(dv); - if (std::isnan(np.value)) { - val = helicsGetVector(np.name); + const auto& point = std::get(data); + if (std::isnan(point.value)) { + val = helicsGetVector(point.name); } else { val.resize(1); - val[0] = np.value; + val[0] = point.value; } break; } } } -void valueExtract(const defV& dv, std::vector>& val) +void valueExtract(const defV& data, std::vector>& val) { val.resize(0); - switch (dv.index()) { + switch (data.index()) { case double_loc: // double - val.emplace_back(std::get(dv), 0.0); + val.emplace_back(std::get(data), 0.0); break; case int_loc: // int64_t - val.emplace_back(static_cast(std::get(dv)), 0.0); + val.emplace_back(static_cast(std::get(data)), 0.0); break; case string_loc: // string default: - helicsGetComplexVector(std::get(dv), val); + helicsGetComplexVector(std::get(data), val); break; case complex_loc: // complex { - val.push_back(std::get>(dv)); + val.push_back(std::get>(data)); } break; case vector_loc: // vector { - const auto& v = std::get>(dv); - val.reserve(v.size() + 1 / 2); + const auto& vec = std::get>(data); + val.reserve(vec.size() + 1 / 2); val.clear(); - for (size_t ii = 0; ii < v.size() - 1; ii += 2) { - val.emplace_back(v[ii], v[ii + 1]); + for (size_t ii = 0; ii < vec.size() - 1; ii += 2) { + val.emplace_back(vec[ii], vec[ii + 1]); } - if (v.size() % 2 == 1) { - val.emplace_back(v.back(), 0.0); + if (vec.size() % 2 == 1) { + val.emplace_back(vec.back(), 0.0); } break; } case complex_vector_loc: // complex - val = std::get>>(dv); + val = std::get>>(data); break; case named_point_loc: // named point { - const auto& np = std::get(dv); - if (std::isnan(np.value)) { - val = helicsGetComplexVector(np.name); + const auto& point = std::get(data); + if (std::isnan(point.value)) { + val = helicsGetComplexVector(point.name); } else { val.resize(1); - val[0] = std::complex(np.value, 0.0); + val[0] = std::complex(point.value, 0.0); } break; } } } -void valueExtract(const defV& dv, NamedPoint& val) +void valueExtract(const defV& data, NamedPoint& val) { - switch (dv.index()) { + switch (data.index()) { case double_loc: // double val.name = "value"; - val.value = std::get(dv); + val.value = std::get(data); break; case int_loc: // int64_t val.name = "value"; - val.value = static_cast(std::get(dv)); + val.value = static_cast(std::get(data)); break; case string_loc: // string default: - val = helicsGetNamedPoint(std::get(dv)); + val = helicsGetNamedPoint(std::get(data)); break; case complex_loc: // complex - val.name = helicsComplexString(std::get>(dv)); + val.name = helicsComplexString(std::get>(data)); val.value = std::nan("0"); break; case vector_loc: // vector { - const auto& vec = std::get>(dv); + const auto& vec = std::get>(data); if (vec.size() == 1) { val.name = "value"; val.value = vec[0]; @@ -379,7 +375,7 @@ void valueExtract(const defV& dv, NamedPoint& val) } case complex_vector_loc: { val.value = std::nan("0"); - const auto& vec = std::get>>(dv); + const auto& vec = std::get>>(data); if (vec.size() == 1) { val.name = helicsComplexString(vec[0]); } else { @@ -388,32 +384,32 @@ void valueExtract(const defV& dv, NamedPoint& val) break; } case named_point_loc: - val = std::get(dv); + val = std::get(data); break; } } -void valueExtract(const defV& dv, Time& val) +void valueExtract(const defV& data, Time& val) { - switch (dv.index()) { + switch (data.index()) { case double_loc: // double - val = std::get(dv); + val = std::get(data); break; case int_loc: // int64_t default: - val.setBaseTimeCode(std::get(dv)); + val.setBaseTimeCode(std::get(data)); break; case string_loc: // string { size_t index; - const auto& str = std::get(dv); + const auto& str = std::get(data); try { - auto ul = std::stoll(str, &index); + auto timeCodeValue = std::stoll(str, &index); if ((index == std::string::npos) || (index == str.size())) { - val.setBaseTimeCode(ul); + val.setBaseTimeCode(timeCodeValue); } else { val = gmlc::utilities::loadTimeFromString( - std::get(dv)); + std::get(data)); } } catch (...) { @@ -422,117 +418,117 @@ void valueExtract(const defV& dv, Time& val) break; } case complex_loc: // complex - val = std::get>(dv).real(); + val = std::get>(data).real(); break; case vector_loc: // vector { - const auto& vec = std::get>(dv); + const auto& vec = std::get>(data); val = (!vec.empty()) ? Time(vec[0]) : timeZero; break; } case complex_vector_loc: { - const auto& vec = std::get>>(dv); + const auto& vec = std::get>>(data); val = (!vec.empty()) ? Time(vec[0].real()) : timeZero; break; } case named_point_loc: - auto np = std::get(dv); - if (std::isnan(np.value)) { - if (np.name.find(".[eE") == std::string::npos) { - std::int64_t v = getIntFromString(np.name); + auto point = std::get(data); + if (std::isnan(point.value)) { + if (point.name.find(".[eE") == std::string::npos) { + std::int64_t v = getIntFromString(point.name); val.setBaseTimeCode(v); } else { - val = getDoubleFromString(np.name); + val = getDoubleFromString(point.name); } } else { - val = np.value; + val = point.value; } break; } } -void valueExtract(const defV& dv, char& val) +void valueExtract(const defV& data, char& val) { - switch (dv.index()) { + switch (data.index()) { case double_loc: // double - val = static_cast(std::get(dv)); + val = static_cast(std::get(data)); break; case int_loc: // int64_t default: - val = static_cast(std::get(dv)); + val = static_cast(std::get(data)); break; case string_loc: // string { - const auto& str = std::get(dv); + const auto& str = std::get(data); val = (str.empty()) ? '\0' : str[0]; break; } case complex_loc: // complex - val = static_cast(std::get>(dv).real()); + val = static_cast(std::get>(data).real()); break; case vector_loc: // vector { - const auto& vec = std::get>(dv); + const auto& vec = std::get>(data); val = (!vec.empty()) ? static_cast(vec[0]) : '\0'; break; } case complex_vector_loc: { - const auto& vec = std::get>>(dv); + const auto& vec = std::get>>(data); val = (!vec.empty()) ? static_cast(vec[0].real()) : '\0'; break; } case named_point_loc: { - const auto& np = std::get(dv); - if (std::isnan(np.value)) { - double vald = getDoubleFromString(np.name); + const auto& point = std::get(data); + if (std::isnan(point.value)) { + double vald = getDoubleFromString(point.name); if (vald != invalidDouble) { val = static_cast(vald); } else { - val = !np.name.empty() ? np.name[0] : 0; + val = !point.name.empty() ? point.name[0] : 0; } } else { - val = static_cast(np.value); + val = static_cast(point.value); } } break; } } -void valueExtract(const defV& dv, bool& val) +void valueExtract(const defV& data, bool& val) { - switch (dv.index()) { + switch (data.index()) { case double_loc: // double - val = std::abs(std::get(dv)) > 0.0; + val = std::abs(std::get(data)) > 0.0; break; case int_loc: // int64_t default: - val = (std::get(dv) != 0); + val = (std::get(data) != 0); break; case string_loc: // string { - const auto& str = std::get(dv); + const auto& str = std::get(data); val = helicsBoolValue(str); break; } case complex_loc: // complex - val = std::abs(std::get>(dv)) > 0.0; + val = std::abs(std::get>(data)) > 0.0; break; case vector_loc: // vector { - const auto& vec = std::get>(dv); + const auto& vec = std::get>(data); val = vectorNorm(vec) != 0.0; break; } case complex_vector_loc: { - const auto& vec = std::get>>(dv); + const auto& vec = std::get>>(data); val = vectorNorm(vec) != 0.0; break; } case named_point_loc: { - const auto& np = std::get(dv); - const auto& str = np.name; + const auto& point = std::get(data); + const auto& str = point.name; val = str.empty() || helicsBoolValue(str); if (val) { - if ((str == "value" || str.empty()) && np.value == 0.0) { + if ((str == "value" || str.empty()) && point.value == 0.0) { val = false; } } @@ -540,31 +536,32 @@ void valueExtract(const defV& dv, bool& val) } } -defV readJsonValue(const data_view& dv) +defV readJsonValue(const data_view& data) { defV result; try { - auto jv = fileops::loadJsonStr(dv.string_view()); - switch (getTypeFromString(jv["type"].asCString())) { + auto json = fileops::loadJsonStr(data.string_view()); + switch (getTypeFromString(json["type"].asCString())) { case DataType::HELICS_DOUBLE: - result = jv["value"].asDouble(); + result = json["value"].asDouble(); break; case DataType::HELICS_COMPLEX: - result = std::complex(jv["value"][0].asDouble(), jv["value"][1].asDouble()); + result = + std::complex(json["value"][0].asDouble(), json["value"][1].asDouble()); break; case DataType::HELICS_BOOL: - result = static_cast(jv["value"].asBool()); + result = static_cast(json["value"].asBool()); break; case DataType::HELICS_VECTOR: { std::vector res; - for (const auto& v : jv["value"]) { + for (const auto& v : json["value"]) { res.push_back(v.asDouble()); } result = std::move(res); } break; case DataType::HELICS_COMPLEX_VECTOR: { std::vector> res; - auto ca = jv["value"]; + auto ca = json["value"]; for (Json::ArrayIndex ii = 0; ii < ca.size() - 1; ii += 2) { res.emplace_back(ca[ii].asDouble(), ca[ii + 1].asDouble()); } @@ -572,89 +569,96 @@ defV readJsonValue(const data_view& dv) } break; case DataType::HELICS_INT: case DataType::HELICS_TIME: - result = jv["value"].asInt64(); + result = json["value"].asInt64(); break; case DataType::HELICS_STRING: case DataType::HELICS_CHAR: - result = jv["value"].asString(); + result = json["value"].asString(); break; case DataType::HELICS_NAMED_POINT: - result = NamedPoint(jv["name"].asCString(), jv["value"].asDouble()); + result = NamedPoint(json["name"].asCString(), json["value"].asDouble()); break; + case DataType::HELICS_MULTI: default: - result = dv.string(); + result = data.string(); } } catch (...) { - result = dv.string(); + result = data.string(); } return result; } -void valueExtract(const data_view& dv, DataType baseType, std::string& val) +void valueExtract(const data_view& data, DataType baseType, std::string& val) { switch (baseType) { case DataType::HELICS_DOUBLE: { - auto V = ValueConverter::interpret(dv); - val = helicsDoubleString(V); + auto value = ValueConverter::interpret(data); + val = helicsDoubleString(value); break; } case DataType::HELICS_INT: case DataType::HELICS_TIME: { - auto V = ValueConverter::interpret(dv); - val = helicsIntString(V); + auto value = ValueConverter::interpret(data); + val = helicsIntString(value); break; } case DataType::HELICS_STRING: case DataType::HELICS_CHAR: - default: - val = ValueConverter::interpret(dv); + case DataType::HELICS_BOOL: + case DataType::HELICS_ANY: + val = ValueConverter::interpret(data); + break; + case DataType::HELICS_UNKNOWN: + case DataType::HELICS_CUSTOM: + case DataType::HELICS_MULTI: + val = data.string(); break; case DataType::HELICS_NAMED_POINT: { - auto npv = ValueConverter::interpret(dv); + auto npv = ValueConverter::interpret(data); val = std::isnan(npv.value) ? npv.name : helicsNamedPointString(npv); break; } case DataType::HELICS_VECTOR: - val = helicsVectorString(ValueConverter>::interpret(dv)); + val = helicsVectorString(ValueConverter>::interpret(data)); break; case DataType::HELICS_COMPLEX: - val = helicsComplexString(ValueConverter>::interpret(dv)); + val = helicsComplexString(ValueConverter>::interpret(data)); break; case DataType::HELICS_COMPLEX_VECTOR: val = helicsComplexVectorString( - ValueConverter>>::interpret(dv)); + ValueConverter>>::interpret(data)); break; case DataType::HELICS_JSON: - valueExtract(readJsonValue(dv), val); + valueExtract(readJsonValue(data), val); break; } } -void valueExtract(const data_view& dv, DataType baseType, std::vector& val) +void valueExtract(const data_view& data, DataType baseType, std::vector& val) { val.resize(0); switch (baseType) { case DataType::HELICS_DOUBLE: { - val.push_back(ValueConverter::interpret(dv)); + val.push_back(ValueConverter::interpret(data)); break; } case DataType::HELICS_INT: { - val.push_back(static_cast(ValueConverter::interpret(dv))); + val.push_back(static_cast(ValueConverter::interpret(data))); break; } case DataType::HELICS_TIME: { - Time tm(ValueConverter::interpret(dv), time_units::ns); - val.push_back(static_cast(tm)); + Time time(ValueConverter::interpret(data), time_units::ns); + val.push_back(static_cast(time)); } break; case DataType::HELICS_STRING: case DataType::HELICS_CHAR: default: { - helicsGetVector(ValueConverter::interpret(dv), val); + helicsGetVector(ValueConverter::interpret(data), val); break; } case DataType::HELICS_NAMED_POINT: { - auto npval = ValueConverter::interpret(dv); + auto npval = ValueConverter::interpret(data); if (std::isnan(npval.value)) { val = helicsGetVector(npval.name); } else { @@ -663,11 +667,11 @@ void valueExtract(const data_view& dv, DataType baseType, std::vector& v break; } case DataType::HELICS_VECTOR: { - ValueConverter>::interpret(dv, val); + ValueConverter>::interpret(data, val); break; } case DataType::HELICS_COMPLEX: { - auto cval = ValueConverter>::interpret(dv); + auto cval = ValueConverter>::interpret(data); val.push_back(cval.real()); if (cval.imag() != 0.0) { val.push_back(cval.imag()); @@ -675,9 +679,9 @@ void valueExtract(const data_view& dv, DataType baseType, std::vector& v break; } case DataType::HELICS_COMPLEX_VECTOR: { - auto cv = ValueConverter>>::interpret(dv); - val.reserve(cv.size()); - for (auto& cval : cv) { + auto cvec = ValueConverter>>::interpret(data); + val.reserve(cvec.size()); + for (auto& cval : cvec) { if (cval.imag() == 0.0) { val.push_back(cval.real()); } else { @@ -687,50 +691,50 @@ void valueExtract(const data_view& dv, DataType baseType, std::vector& v break; } case DataType::HELICS_JSON: - valueExtract(readJsonValue(dv), val); + valueExtract(readJsonValue(data), val); break; } } -void valueExtract(const data_view& dv, DataType baseType, std::vector>& val) +void valueExtract(const data_view& data, DataType baseType, std::vector>& val) { val.resize(0); switch (baseType) { case DataType::HELICS_DOUBLE: { - val.emplace_back(ValueConverter::interpret(dv), 0.0); + val.emplace_back(ValueConverter::interpret(data), 0.0); break; } case DataType::HELICS_INT: { - val.emplace_back(static_cast(ValueConverter::interpret(dv)), 0.0); + val.emplace_back(static_cast(ValueConverter::interpret(data)), 0.0); break; } case DataType::HELICS_TIME: { - Time tm(ValueConverter::interpret(dv), time_units::ns); + Time tm(ValueConverter::interpret(data), time_units::ns); val.emplace_back(static_cast(tm), 0.0); } break; case DataType::HELICS_STRING: case DataType::HELICS_CHAR: default: { - helicsGetComplexVector(ValueConverter::interpret(dv), val); + helicsGetComplexVector(ValueConverter::interpret(data), val); break; } case DataType::HELICS_VECTOR: { - auto V = ValueConverter>::interpret(dv); - for (size_t ii = 0; ii < V.size() - 1; ii += 2) { - val.emplace_back(V[ii], V[ii + 1]); + auto vec = ValueConverter>::interpret(data); + for (size_t ii = 0; ii < vec.size() - 1; ii += 2) { + val.emplace_back(vec[ii], vec[ii + 1]); } - if (V.size() % 2 == 1) { - val.emplace_back(V.back(), 0.0); + if (vec.size() % 2 == 1) { + val.emplace_back(vec.back(), 0.0); } break; } case DataType::HELICS_COMPLEX_VECTOR: { - ValueConverter>>::interpret(dv, val); + ValueConverter>>::interpret(data, val); break; } case DataType::HELICS_NAMED_POINT: { - auto npval = ValueConverter::interpret(dv); + auto npval = ValueConverter::interpret(data); if (std::isnan(npval.value)) { val = helicsGetComplexVector(npval.name); } else { @@ -739,40 +743,41 @@ void valueExtract(const data_view& dv, DataType baseType, std::vector>::interpret(dv); + auto cval = ValueConverter>::interpret(data); val.push_back(cval); break; } case DataType::HELICS_JSON: - valueExtract(readJsonValue(dv), val); + valueExtract(readJsonValue(data), val); break; } } -void valueExtract(const data_view& dv, DataType baseType, std::complex& val) +void valueExtract(const data_view& data, DataType baseType, std::complex& val) { switch (baseType) { case DataType::HELICS_DOUBLE: { - val = std::complex(ValueConverter::interpret(dv), 0.0); + val = std::complex(ValueConverter::interpret(data), 0.0); break; } case DataType::HELICS_INT: { - val = std::complex(static_cast(ValueConverter::interpret(dv)), - 0.0); + val = + std::complex(static_cast(ValueConverter::interpret(data)), + 0.0); break; } case DataType::HELICS_TIME: { - Time tm(ValueConverter::interpret(dv), time_units::ns); + Time tm(ValueConverter::interpret(data), time_units::ns); val = std::complex(static_cast(tm), 0.0); } break; case DataType::HELICS_STRING: case DataType::HELICS_CHAR: default: { - val = helicsGetComplex(ValueConverter::interpret(dv)); + val = helicsGetComplex(ValueConverter::interpret(data)); break; } case DataType::HELICS_NAMED_POINT: { - auto npval = ValueConverter::interpret(dv); + auto npval = ValueConverter::interpret(data); if (std::isnan(npval.value)) { val = helicsGetComplex(npval.name); } else { @@ -781,7 +786,7 @@ void valueExtract(const data_view& dv, DataType baseType, std::complex& break; } case DataType::HELICS_VECTOR: { - auto vec = ValueConverter>::interpret(dv); + auto vec = ValueConverter>::interpret(data); if (vec.size() == 1) { val = std::complex(vec[0], 0.0); } else if (vec.size() >= 2) { @@ -790,49 +795,49 @@ void valueExtract(const data_view& dv, DataType baseType, std::complex& break; } case DataType::HELICS_COMPLEX: - val = ValueConverter>::interpret(dv); + val = ValueConverter>::interpret(data); break; case DataType::HELICS_COMPLEX_VECTOR: { - auto cvec = ValueConverter>>::interpret(dv); + auto cvec = ValueConverter>>::interpret(data); if (!cvec.empty()) { val = cvec[0]; } break; } case DataType::HELICS_JSON: - valueExtract(readJsonValue(dv), val); + valueExtract(readJsonValue(data), val); break; } } -void valueExtract(const data_view& dv, DataType baseType, NamedPoint& val) +void valueExtract(const data_view& data, DataType baseType, NamedPoint& val) { switch (baseType) { case DataType::HELICS_DOUBLE: { - auto V = ValueConverter::interpret(dv); + auto value = ValueConverter::interpret(data); val.name = "value"; - val.value = V; + val.value = value; break; } case DataType::HELICS_INT: { - auto V = ValueConverter::interpret(dv); + auto value = ValueConverter::interpret(data); val.name = "value"; - val.value = static_cast(V); + val.value = static_cast(value); break; } case DataType::HELICS_TIME: { - Time tm(ValueConverter::interpret(dv), time_units::ns); + Time tm(ValueConverter::interpret(data), time_units::ns); val.name = "time"; val.value = static_cast(tm); } break; case DataType::HELICS_STRING: case DataType::HELICS_CHAR: default: { - val = helicsGetNamedPoint(ValueConverter::interpret(dv)); + val = helicsGetNamedPoint(ValueConverter::interpret(data)); break; } case DataType::HELICS_VECTOR: { - auto vec = ValueConverter>::interpret(dv); + auto vec = ValueConverter>::interpret(data); if (vec.size() == 1) { val.name = "value"; @@ -844,7 +849,7 @@ void valueExtract(const data_view& dv, DataType baseType, NamedPoint& val) break; } case DataType::HELICS_COMPLEX: { - auto cval = ValueConverter>::interpret(dv); + auto cval = ValueConverter>::interpret(data); if (cval.imag() == 0) { val.name = "value"; val.value = cval.real(); @@ -856,7 +861,7 @@ void valueExtract(const data_view& dv, DataType baseType, NamedPoint& val) break; } case DataType::HELICS_COMPLEX_VECTOR: { - auto cvec = ValueConverter>>::interpret(dv); + auto cvec = ValueConverter>>::interpret(data); if (cvec.size() == 1) { val.name = helicsComplexString(cvec[0]); val.value = std::nan("0"); @@ -867,24 +872,24 @@ void valueExtract(const data_view& dv, DataType baseType, NamedPoint& val) break; } case DataType::HELICS_NAMED_POINT: - val = ValueConverter::interpret(dv); + val = ValueConverter::interpret(data); break; case DataType::HELICS_JSON: - valueExtract(readJsonValue(dv), val); + valueExtract(readJsonValue(data), val); break; } } -void valueExtract(const data_view& dv, DataType baseType, Time& val) +void valueExtract(const data_view& data, DataType baseType, Time& val) { switch (baseType) { case DataType::HELICS_DOUBLE: { - val = ValueConverter::interpret(dv); + val = ValueConverter::interpret(data); break; } case DataType::HELICS_INT: case DataType::HELICS_TIME: { - val.setBaseTimeCode(ValueConverter::interpret(dv)); + val.setBaseTimeCode(ValueConverter::interpret(data)); break; } case DataType::HELICS_STRING: @@ -892,12 +897,12 @@ void valueExtract(const data_view& dv, DataType baseType, Time& val) default: { size_t index; try { - auto data = ValueConverter::interpret(dv); - auto ul = std::stoll(std::string(data), &index); - if ((index == std::string::npos) || (index == data.size())) { - val.setBaseTimeCode(ul); + auto stringData = ValueConverter::interpret(data); + auto timeCode = std::stoll(std::string(stringData), &index); + if ((index == std::string::npos) || (index == stringData.size())) { + val.setBaseTimeCode(timeCode); } else { - val = gmlc::utilities::loadTimeFromString(data); + val = gmlc::utilities::loadTimeFromString(stringData); } } catch (...) { @@ -907,59 +912,59 @@ void valueExtract(const data_view& dv, DataType baseType, Time& val) break; } case DataType::HELICS_VECTOR: { - auto vec = ValueConverter>::interpret(dv); + auto vec = ValueConverter>::interpret(data); val = (!vec.empty()) ? Time(vec[0]) : timeZero; break; } case DataType::HELICS_COMPLEX: { - auto cval = ValueConverter>::interpret(dv); + auto cval = ValueConverter>::interpret(data); val = cval.real(); break; } case DataType::HELICS_COMPLEX_VECTOR: { - auto cvec = ValueConverter>>::interpret(dv); + auto cvec = ValueConverter>>::interpret(data); val = (!cvec.empty()) ? Time(cvec[0].real()) : timeZero; break; } case DataType::HELICS_NAMED_POINT: { - auto np = ValueConverter::interpret(dv); - if (std::isnan(np.value)) { - if (np.name.find(".[eE") == std::string::npos) { - std::int64_t v = getIntFromString(np.name); + auto point = ValueConverter::interpret(data); + if (std::isnan(point.value)) { + if (point.name.find(".[eE") == std::string::npos) { + std::int64_t v = getIntFromString(point.name); val.setBaseTimeCode(v); } else { - val = getDoubleFromString(np.name); + val = getDoubleFromString(point.name); } } else { - val = np.value; + val = point.value; } break; } case DataType::HELICS_JSON: - valueExtract(readJsonValue(dv), val); + valueExtract(readJsonValue(data), val); break; } } -void valueExtract(const data_view& dv, DataType baseType, bool& val) +void valueExtract(const data_view& data, DataType baseType, bool& val) { switch (baseType) { case DataType::HELICS_ANY: { defV val_dv; - valueExtract(dv, baseType, val_dv); + valueExtract(data, baseType, val_dv); valueExtract(val_dv, val); break; } case DataType::HELICS_STRING: case DataType::HELICS_CHAR: default: - val = helicsBoolValue(ValueConverter::interpret(dv)); + val = helicsBoolValue(ValueConverter::interpret(data)); break; case DataType::HELICS_BOOL: - val = (ValueConverter::interpret(dv) != "0"); + val = (ValueConverter::interpret(data) != "0"); break; case DataType::HELICS_NAMED_POINT: { - auto npval = ValueConverter::interpret(dv); + auto npval = ValueConverter::interpret(data); auto& str = npval.name; val = str.empty() || helicsBoolValue(str); if (val) { @@ -971,78 +976,78 @@ void valueExtract(const data_view& dv, DataType baseType, bool& val) break; } case DataType::HELICS_DOUBLE: { - auto V = ValueConverter::interpret(dv); - val = std::abs(V) != 0; + auto value = ValueConverter::interpret(data); + val = std::abs(value) != 0; break; } case DataType::HELICS_INT: case DataType::HELICS_TIME: { - auto V = ValueConverter::interpret(dv); - val = (V != 0); + auto value = ValueConverter::interpret(data); + val = (value != 0); break; } case DataType::HELICS_VECTOR: { - auto V = ValueConverter>::interpret(dv); - val = (vectorNorm(V) != 0.0); + auto value = ValueConverter>::interpret(data); + val = (vectorNorm(value) != 0.0); break; } case DataType::HELICS_COMPLEX: { - auto V = ValueConverter>::interpret(dv); - val = (std::abs(V) != 0.0); + auto value = ValueConverter>::interpret(data); + val = (std::abs(value) != 0.0); break; } case DataType::HELICS_COMPLEX_VECTOR: { - auto V = ValueConverter>>::interpret(dv); - val = (vectorNorm(V) != 0.0); + auto value = ValueConverter>>::interpret(data); + val = (vectorNorm(value) != 0.0); break; } case DataType::HELICS_JSON: - valueExtract(readJsonValue(dv), val); + valueExtract(readJsonValue(data), val); break; case DataType::HELICS_CUSTOM: throw(std::invalid_argument("unrecognized helics type")); } } -void valueExtract(const data_view& dv, DataType baseType, char& val) +void valueExtract(const data_view& data, DataType baseType, char& val) { switch (baseType) { case DataType::HELICS_ANY: { defV val_dv; - valueExtract(dv, baseType, val_dv); + valueExtract(data, baseType, val_dv); valueExtract(val_dv, val); break; } case DataType::HELICS_STRING: case DataType::HELICS_CHAR: default: { - auto sv = ValueConverter::interpret(dv); - if (sv.size() == 1) { - val = sv[0]; + auto value = ValueConverter::interpret(data); + if (value.size() == 1) { + val = value[0]; } else { - double v = getDoubleFromString(sv); - if (v != invalidDouble) { - val = static_cast(v); + double dval = getDoubleFromString(value); + if (dval != invalidDouble) { + val = static_cast(dval); } else { - val = sv[0]; + val = value[0]; } } } break; case DataType::HELICS_BOOL: - val = ValueConverter::interpret(dv)[0]; + val = ValueConverter::interpret(data)[0]; break; case DataType::HELICS_NAMED_POINT: { - auto npval = ValueConverter::interpret(dv); + auto npval = ValueConverter::interpret(data); if (std::isnan(npval.value)) { if (npval.name.size() == 1) { val = npval.name[0]; } else { - double v = getDoubleFromString(npval.name); - if (v != invalidDouble) { - val = static_cast(v); + double value = getDoubleFromString(npval.name); + if (value != invalidDouble) { + val = static_cast(value); } else { val = npval.name[0]; } @@ -1053,73 +1058,81 @@ void valueExtract(const data_view& dv, DataType baseType, char& val) break; } case DataType::HELICS_DOUBLE: { - val = static_cast(ValueConverter::interpret(dv)); + val = static_cast(ValueConverter::interpret(data)); break; } case DataType::HELICS_INT: case DataType::HELICS_TIME: { - auto V = ValueConverter::interpret(dv); + auto V = ValueConverter::interpret(data); val = static_cast(V); break; } case DataType::HELICS_VECTOR: { - auto V = ValueConverter>::interpret(dv); - val = static_cast((V.size() == 1) ? V[0] : vectorNorm(V)); + auto vec = ValueConverter>::interpret(data); + val = static_cast((vec.size() == 1) ? vec[0] : vectorNorm(vec)); break; } case DataType::HELICS_COMPLEX: { - auto V = ValueConverter>::interpret(dv); - val = static_cast((V.imag() == 0.0) ? V.real() : std::abs(V)); + auto cval = ValueConverter>::interpret(data); + val = static_cast((cval.imag() == 0.0) ? cval.real() : std::abs(cval)); break; } case DataType::HELICS_COMPLEX_VECTOR: { - auto V = ValueConverter>>::interpret(dv); - val = static_cast((V.size() == 1) ? - ((V[0].imag() == 0.0) ? V[0].real() : std::abs(V[0])) : - vectorNorm(V)); + auto cvec = ValueConverter>>::interpret(data); + val = static_cast( + (cvec.size() == 1) ? + ((cvec[0].imag() == 0.0) ? cvec[0].real() : std::abs(cvec[0])) : + vectorNorm(cvec)); break; } case DataType::HELICS_JSON: - valueExtract(readJsonValue(dv), val); + valueExtract(readJsonValue(data), val); break; case DataType::HELICS_CUSTOM: + case DataType::HELICS_MULTI: throw(std::invalid_argument("unrecognized helics type")); } } -void valueExtract(const data_view& dv, DataType baseType, defV& val) +void valueExtract(const data_view& data, DataType baseType, defV& val) { if (baseType == DataType::HELICS_ANY || baseType == DataType::HELICS_UNKNOWN) { - baseType = detail::detectType(dv.bytes()); + baseType = detail::detectType(data.bytes()); } switch (baseType) { case DataType::HELICS_DOUBLE: - val = ValueConverter::interpret(dv); + val = ValueConverter::interpret(data); break; case DataType::HELICS_INT: case DataType::HELICS_TIME: - val = ValueConverter::interpret(dv); + val = ValueConverter::interpret(data); break; case DataType::HELICS_STRING: case DataType::HELICS_CHAR: - default: - val = std::string(ValueConverter::interpret(dv)); + case DataType::HELICS_BOOL: + case DataType::HELICS_ANY: + val = std::string(ValueConverter::interpret(data)); + break; + case DataType::HELICS_UNKNOWN: + case DataType::HELICS_CUSTOM: + case DataType::HELICS_MULTI: + val = data.string(); break; case DataType::HELICS_VECTOR: - val = ValueConverter>::interpret(dv); + val = ValueConverter>::interpret(data); break; case DataType::HELICS_COMPLEX: - val = ValueConverter>::interpret(dv); + val = ValueConverter>::interpret(data); break; case DataType::HELICS_COMPLEX_VECTOR: - val = ValueConverter>>::interpret(dv); + val = ValueConverter>>::interpret(data); break; case DataType::HELICS_NAMED_POINT: - val = ValueConverter::interpret(dv); + val = ValueConverter::interpret(data); break; case DataType::HELICS_JSON: - val = readJsonValue(dv); + val = readJsonValue(data); break; } } @@ -1132,27 +1145,27 @@ void valueConvert(defV& val, DataType newType) if (index == double_loc) { return; } - double V{0}; - valueExtract(val, V); - val = V; + double value{0}; + valueExtract(val, value); + val = value; break; } case DataType::HELICS_INT: { if (index == int_loc) { return; } - int64_t V{0}; - valueExtract(val, V); - val = V; + int64_t value{0}; + valueExtract(val, value); + val = value; break; } case DataType::HELICS_TIME: { if (index == int_loc) { return; } - Time V{timeZero}; - valueExtract(val, V); - val = V.getBaseTimeCode(); + Time value{timeZero}; + valueExtract(val, value); + val = value.getBaseTimeCode(); break; } case DataType::HELICS_JSON: @@ -1163,45 +1176,45 @@ void valueConvert(defV& val, DataType newType) if (index == string_loc) { return; } - std::string V; - valueExtract(val, V); - val = std::move(V); + std::string value; + valueExtract(val, value); + val = std::move(value); break; } case DataType::HELICS_VECTOR: { if (index == vector_loc) { return; } - std::vector V; - valueExtract(val, V); - val = std::move(V); + std::vector vec; + valueExtract(val, vec); + val = std::move(vec); break; } case DataType::HELICS_COMPLEX: { if (index == complex_loc) { return; } - std::complex V; - valueExtract(val, V); - val = V; + std::complex cval; + valueExtract(val, cval); + val = cval; break; } case DataType::HELICS_COMPLEX_VECTOR: { if (index == complex_vector_loc) { return; } - std::vector> V; - valueExtract(val, V); - val = std::move(V); + std::vector> cvec; + valueExtract(val, cvec); + val = std::move(cvec); break; } case DataType::HELICS_NAMED_POINT: { if (index == named_point_loc) { return; } - NamedPoint V; - valueExtract(val, V); - val = std::move(V); + NamedPoint point; + valueExtract(val, point); + val = std::move(point); break; } } diff --git a/src/helics/application_api/helicsTypes.cpp b/src/helics/application_api/helicsTypes.cpp index edc6a40954..894ed71489 100644 --- a/src/helics/application_api/helicsTypes.cpp +++ b/src/helics/application_api/helicsTypes.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -11,13 +11,13 @@ SPDX-License-Identifier: BSD-3-Clause #include "../common/JsonProcessingFunctions.hpp" #include "../common/frozen_map.h" #include "ValueConverter.hpp" -#include "fmt/format.h" #include "gmlc/utilities/demangle.hpp" #include "gmlc/utilities/stringConversion.h" #include "gmlc/utilities/stringOps.h" #include "gmlc/utilities/string_viewConversion.h" #include +#include #include #include #include @@ -34,11 +34,11 @@ struct fmt::formatter> { static constexpr auto parse(format_parse_context& ctx) { return ctx.end(); } template - auto format(const std::complex& p, FormatContext& ctx) const + auto format(const std::complex& value, FormatContext& ctx) const { // ctx.out() is an output iterator to write to. // return format(ctx.out(), "[{},{}]",p.real(), p.imag()); - return fmt::vformat_to(ctx.out(), "[{},{}]", fmt::make_format_args(p.real(), p.imag())); + return fmt::format_to(ctx.out(), "[{},{}]", value.real(), value.imag()); } }; @@ -296,15 +296,15 @@ std::complex helicsGetComplex(std::string_view val) if (val.empty()) { return invalidValue>(); } - double re{invalidValue()}; - double im{0.0}; + double real{invalidValue()}; + double imag{0.0}; if (val.front() == '[') { auto sep = val.find_first_of(','); if (sep == std::string_view::npos) { val.remove_prefix(1); val.remove_suffix(1); - re = numConv(val); - return {re, im}; + real = numConv(val); + return {real, imag}; } if (val.find_first_of(',', sep + 1) != std::string_view::npos) { auto V = helicsGetVector(val); @@ -313,10 +313,10 @@ std::complex helicsGetComplex(std::string_view val) } return invalidValue>(); } - re = numConv(val.substr(1, sep)); + real = numConv(val.substr(1, sep)); val.remove_suffix(1); - im = numConv(val.substr(sep + 1)); - return {re, im}; + imag = numConv(val.substr(sep + 1)); + return {real, imag}; } std::smatch m; @@ -324,30 +324,30 @@ std::complex helicsGetComplex(std::string_view val) std::regex_search(temp, m, creg); try { if (m.size() == 9) { - re = numConv(m[1]); + real = numConv(m[1]); - im = numConv(m[6]); + imag = numConv(m[6]); if (*m[5].first == '-') { - im = -im; + imag = -imag; } } else { if ((val.back() == 'j') || (val.back() == 'i')) { auto strval = val.substr(0, val.size() - 1); string_viewOps::trimString(strval); - im = numConv(strval); - re = 0.0; + imag = numConv(strval); + real = 0.0; } else { auto strval = val; string_viewOps::trimString(strval); - re = numConv(strval); + real = numConv(strval); } } } catch (const std::invalid_argument&) { - re = invalidValue(); + real = invalidValue(); } - return {re, im}; + return {real, imag}; } std::string helicsIntString(std::int64_t val) @@ -749,16 +749,16 @@ SmallBuffer typeConvert(DataType type, double val) case DataType::HELICS_NAMED_POINT: return ValueConverter::convert(NamedPoint{"value", val}); case DataType::HELICS_COMPLEX_VECTOR: { - std::complex v2(val, 0.0); + const std::complex v2(val, 0.0); return ValueConverter>::convert(&v2, 1); } case DataType::HELICS_VECTOR: return ValueConverter::convert(&val, 1); case DataType::HELICS_JSON: { - Json::Value jv; - jv["type"] = typeNameStringRef(DataType::HELICS_DOUBLE); - jv["value"] = val; - return fileops::generateJsonString(jv); + Json::Value json; + json["type"] = typeNameStringRef(DataType::HELICS_DOUBLE); + json["value"] = val; + return fileops::generateJsonString(json); } } } @@ -791,18 +791,18 @@ SmallBuffer typeConvert(DataType type, int64_t val) } case DataType::HELICS_COMPLEX_VECTOR: { - std::complex v2(static_cast(val), 0.0); + const std::complex v2(static_cast(val), 0.0); return ValueConverter>::convert(&v2, 1); } case DataType::HELICS_VECTOR: { - auto v2 = static_cast(val); - return ValueConverter::convert(&v2, 1); + const auto doubleVal = static_cast(val); + return ValueConverter::convert(&doubleVal, 1); } case DataType::HELICS_JSON: { - Json::Value jv; - jv["type"] = typeNameStringRef(DataType::HELICS_INT); - jv["value"] = val; - return fileops::generateJsonString(jv); + Json::Value json; + json["type"] = typeNameStringRef(DataType::HELICS_INT); + json["value"] = val; + return fileops::generateJsonString(json); } } } @@ -837,10 +837,10 @@ SmallBuffer typeConvert(DataType type, std::string_view val) case DataType::HELICS_VECTOR: return ValueConverter>::convert(helicsGetVector(val)); case DataType::HELICS_JSON: { - Json::Value jv; - jv["type"] = typeNameStringRef(DataType::HELICS_STRING); - jv["value"] = std::string(val); - return fileops::generateJsonString(jv); + Json::Value json; + json["type"] = typeNameStringRef(DataType::HELICS_STRING); + json["value"] = std::string(val); + return fileops::generateJsonString(json); } } } @@ -867,8 +867,8 @@ SmallBuffer typeConvert(DataType type, const double* vals, size_t size) case DataType::HELICS_INT: return ValueConverter::convert(static_cast(vectorNorm(vals, size))); case DataType::HELICS_COMPLEX: { - std::complex V(vals[0], vals[1]); - return ValueConverter>::convert(V); + const std::complex cval(vals[0], vals[1]); + return ValueConverter>::convert(cval); } case DataType::HELICS_BOOL: return ValueConverter::convert((vectorNorm(vals, size) != 0.0) ? "1" : @@ -920,8 +920,8 @@ SmallBuffer typeConvertComplex(DataType type, const double* vals, size_t size) case DataType::HELICS_INT: return ValueConverter::convert(static_cast(vectorNorm(vals, size))); case DataType::HELICS_COMPLEX: { - std::complex V(vals[0], vals[1]); - return ValueConverter>::convert(V); + const std::complex cval(vals[0], vals[1]); + return ValueConverter>::convert(cval); } case DataType::HELICS_BOOL: return ValueConverter::convert((vectorNorm(vals, size) != 0.0) ? "1" : @@ -1040,17 +1040,17 @@ SmallBuffer typeConvert(DataType type, const std::complex& val) case DataType::HELICS_COMPLEX_VECTOR: return ValueConverter>::convert(&val, 1); case DataType::HELICS_VECTOR: { - std::vector V{val.real(), val.imag()}; + const std::vector V{val.real(), val.imag()}; return ValueConverter>::convert(V); } case DataType::HELICS_JSON: { - Json::Value jv; - jv["type"] = typeNameStringRef(DataType::HELICS_COMPLEX); + Json::Value json; + json["type"] = typeNameStringRef(DataType::HELICS_COMPLEX); Json::Value vv = Json::arrayValue; vv.append(val.real()); vv.append(val.imag()); - jv["value"] = std::move(vv); - return fileops::generateJsonString(jv); + json["value"] = std::move(vv); + return fileops::generateJsonString(json); } } } @@ -1084,17 +1084,17 @@ SmallBuffer typeConvert(DataType type, const NamedPoint& val) return ValueConverter::convert( (std::isnan(val.value)) ? val.name : helicsNamedPointString(val)); case DataType::HELICS_COMPLEX_VECTOR: { - std::complex v2(val.value, 0.0); + const std::complex v2(val.value, 0.0); return ValueConverter>::convert(&v2, 1); } case DataType::HELICS_VECTOR: return ValueConverter::convert(&(val.value), 1); case DataType::HELICS_JSON: { - Json::Value jv; - jv["type"] = typeNameStringRef(DataType::HELICS_NAMED_POINT); - jv["name"] = val.name; - jv["value"] = val.value; - return fileops::generateJsonString(jv); + Json::Value json; + json["type"] = typeNameStringRef(DataType::HELICS_NAMED_POINT); + json["name"] = val.name; + json["value"] = val.value; + return fileops::generateJsonString(json); } } } @@ -1125,17 +1125,17 @@ SmallBuffer typeConvert(DataType type, std::string_view str, double val) case DataType::HELICS_CHAR: return ValueConverter::convert(helicsNamedPointString(str, val)); case DataType::HELICS_COMPLEX_VECTOR: { - std::complex v2(val, 0.0); + const std::complex v2(val, 0.0); return ValueConverter>::convert(&v2, 1); } case DataType::HELICS_VECTOR: return ValueConverter::convert(&(val), 1); case DataType::HELICS_JSON: { - Json::Value jv; - jv["type"] = typeNameStringRef(DataType::HELICS_NAMED_POINT); - jv["name"] = std::string(str); - jv["value"] = val; - return fileops::generateJsonString(jv); + Json::Value json; + json["type"] = typeNameStringRef(DataType::HELICS_NAMED_POINT); + json["name"] = std::string(str); + json["value"] = val; + return fileops::generateJsonString(json); } } } @@ -1157,11 +1157,11 @@ SmallBuffer typeConvert(DataType type, bool val) default: return ValueConverter::convert(val ? "1" : "0"); case DataType::HELICS_NAMED_POINT: { - NamedPoint np{"value", val ? 1.0 : 0.0}; + const NamedPoint np{"value", val ? 1.0 : 0.0}; return ValueConverter::convert(np); } case DataType::HELICS_COMPLEX_VECTOR: { - std::complex v2(val ? 1.0 : 0.0, 0.0); + const std::complex v2(val ? 1.0 : 0.0, 0.0); return ValueConverter>::convert(&v2, 1); } case DataType::HELICS_VECTOR: { @@ -1169,10 +1169,10 @@ SmallBuffer typeConvert(DataType type, bool val) return ValueConverter::convert(&v2, 1); } case DataType::HELICS_JSON: { - Json::Value jv; - jv["type"] = typeNameStringRef(DataType::HELICS_BOOL); - jv["value"] = val; - return fileops::generateJsonString(jv); + Json::Value json; + json["type"] = typeNameStringRef(DataType::HELICS_BOOL); + json["value"] = val; + return fileops::generateJsonString(json); } } } @@ -1194,22 +1194,22 @@ SmallBuffer typeConvert(DataType type, char val) default: return ValueConverter::convert(std::string_view(&val, 1)); case DataType::HELICS_NAMED_POINT: { - NamedPoint np{"value", static_cast(val)}; + const NamedPoint np{"value", static_cast(val)}; return ValueConverter::convert(np); } case DataType::HELICS_COMPLEX_VECTOR: { - std::complex v2(static_cast(val), 0.0); - return ValueConverter>::convert(&v2, 1); + const std::complex cvec(static_cast(val), 0.0); + return ValueConverter>::convert(&cvec, 1); } case DataType::HELICS_VECTOR: { - auto v2 = static_cast(val); + const auto v2 = static_cast(val); return ValueConverter::convert(&v2, 1); } case DataType::HELICS_JSON: { - Json::Value jv; - jv["type"] = typeNameStringRef(DataType::HELICS_INT); - jv["value"] = val; - return fileops::generateJsonString(jv); + Json::Value json; + json["type"] = typeNameStringRef(DataType::HELICS_INT); + json["value"] = val; + return fileops::generateJsonString(json); } } } @@ -1248,14 +1248,14 @@ SmallBuffer typeConvert(DataType type, Time val) return ValueConverter>>::convert(cv); } case DataType::HELICS_VECTOR: { - std::vector V{static_cast(val)}; - return ValueConverter>::convert(V); + const std::vector vec{static_cast(val)}; + return ValueConverter>::convert(vec); } case DataType::HELICS_JSON: { - Json::Value jv; - jv["type"] = typeNameStringRef(DataType::HELICS_TIME); - jv["value"] = val.getBaseTimeCode(); - return fileops::generateJsonString(jv); + Json::Value json; + json["type"] = typeNameStringRef(DataType::HELICS_TIME); + json["value"] = val.getBaseTimeCode(); + return fileops::generateJsonString(json); } } } diff --git a/src/helics/application_api/helicsTypes.hpp b/src/helics/application_api/helicsTypes.hpp index a368aaf29c..6319ef6ef9 100644 --- a/src/helics/application_api/helicsTypes.hpp +++ b/src/helics/application_api/helicsTypes.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/application_api/queryFunctions.cpp b/src/helics/application_api/queryFunctions.cpp index 2169104f22..17119c971b 100644 --- a/src/helics/application_api/queryFunctions.cpp +++ b/src/helics/application_api/queryFunctions.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/application_api/queryFunctions.hpp b/src/helics/application_api/queryFunctions.hpp index fbed207151..ecc44bdecb 100644 --- a/src/helics/application_api/queryFunctions.hpp +++ b/src/helics/application_api/queryFunctions.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/application_api/timeOperations.cpp b/src/helics/application_api/timeOperations.cpp index 6015fe5623..73fd6b2c06 100644 --- a/src/helics/application_api/timeOperations.cpp +++ b/src/helics/application_api/timeOperations.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/application_api/timeOperations.hpp b/src/helics/application_api/timeOperations.hpp index 23e59f90d9..be46256abc 100644 --- a/src/helics/application_api/timeOperations.hpp +++ b/src/helics/application_api/timeOperations.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/application_api/typeOperations.cpp b/src/helics/application_api/typeOperations.cpp index 7c92665cd4..10c9e83e37 100644 --- a/src/helics/application_api/typeOperations.cpp +++ b/src/helics/application_api/typeOperations.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -7,6 +7,7 @@ SPDX-License-Identifier: BSD-3-Clause #include "typeOperations.hpp" #include "../core/coreTypeOperations.hpp" +#include "../core/helicsVersion.hpp" namespace helics { std::string to_string(CoreType type) @@ -23,4 +24,10 @@ bool isCoreTypeAvailable(CoreType type) noexcept { return core::isCoreTypeAvailable(type); } + +std::string systemInfo() +{ + return core::systemInfo(); +} + } // namespace helics diff --git a/src/helics/application_api/typeOperations.hpp b/src/helics/application_api/typeOperations.hpp index 909f2c2161..2bc9711d91 100644 --- a/src/helics/application_api/typeOperations.hpp +++ b/src/helics/application_api/typeOperations.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -29,4 +29,8 @@ HELICS_CXX_EXPORT CoreType coreTypeFromString(std::string_view type) noexcept; * Returns true if core/broker type specified is available in current compilation. */ HELICS_CXX_EXPORT bool isCoreTypeAvailable(CoreType type) noexcept; + +/** get a string with the system info*/ +HELICS_CXX_EXPORT std::string systemInfo(); + } // namespace helics diff --git a/src/helics/apps/AsioBrokerServer.cpp b/src/helics/apps/AsioBrokerServer.cpp index 3e963fdb3d..fb553634dd 100644 --- a/src/helics/apps/AsioBrokerServer.cpp +++ b/src/helics/apps/AsioBrokerServer.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/apps/AsioBrokerServer.hpp b/src/helics/apps/AsioBrokerServer.hpp index 7458e120d3..aeeac4d346 100644 --- a/src/helics/apps/AsioBrokerServer.hpp +++ b/src/helics/apps/AsioBrokerServer.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/apps/BrokerApp.hpp b/src/helics/apps/BrokerApp.hpp index e9a6398fc6..68b34f99e1 100644 --- a/src/helics/apps/BrokerApp.hpp +++ b/src/helics/apps/BrokerApp.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/apps/BrokerServer.cpp b/src/helics/apps/BrokerServer.cpp index 89bfeeaa20..62b07d7913 100644 --- a/src/helics/apps/BrokerServer.cpp +++ b/src/helics/apps/BrokerServer.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/apps/BrokerServer.hpp b/src/helics/apps/BrokerServer.hpp index 1c3f729212..b802739dae 100644 --- a/src/helics/apps/BrokerServer.hpp +++ b/src/helics/apps/BrokerServer.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/apps/CMakeLists.txt b/src/helics/apps/CMakeLists.txt index 63e3c72824..93bf20b020 100644 --- a/src/helics/apps/CMakeLists.txt +++ b/src/helics/apps/CMakeLists.txt @@ -1,5 +1,5 @@ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Copyright (c) 2017-2023, Battelle Memorial Institute; Lawrence Livermore +# Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore # National Security, LLC; Alliance for Sustainable Energy, LLC. # See the top-level NOTICE for additional details. # All rights reserved. @@ -24,6 +24,7 @@ if(HELICS_BUILD_APP_LIBRARY) Clone.hpp CoreApp.hpp Probe.hpp + Connector.hpp BrokerApp.hpp ) @@ -44,6 +45,7 @@ if(HELICS_BUILD_APP_LIBRARY) helicsApp.cpp Clone.cpp Probe.cpp + Connector.cpp ) set(helics_apps_broker_files MultiBroker.cpp BrokerServer.cpp zmqBrokerServer.cpp @@ -114,6 +116,14 @@ if(HELICS_BUILD_APP_LIBRARY) COMPONENT applications ) + add_executable(helics_connector connectorMain.cpp) + target_link_libraries(helics_connector PUBLIC HELICS::apps) + target_link_libraries(helics_connector PRIVATE compile_flags_target) + set_target_properties(helics_connector PROPERTIES FOLDER apps) + install(TARGETS helics_connector ${HELICS_EXPORT_COMMAND} + DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT applications + ) + add_executable(helics_broker helics-broker.cpp) target_link_libraries(helics_broker PUBLIC HELICS::apps) target_link_libraries(helics_broker PRIVATE compile_flags_target) diff --git a/src/helics/apps/Clone.cpp b/src/helics/apps/Clone.cpp index 7100e0775f..bc3831db76 100644 --- a/src/helics/apps/Clone.cpp +++ b/src/helics/apps/Clone.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -10,14 +10,14 @@ SPDX-License-Identifier: BSD-3-Clause #include "../application_api/Filters.hpp" #include "../application_api/queryFunctions.hpp" #include "../common/JsonProcessingFunctions.hpp" -#include "../common/fmt_format.h" -#include "../common/fmt_ostream.h" #include "../core/helicsCLI11.hpp" #include "PrecHelper.hpp" #include "gmlc/utilities/base64.h" #include "gmlc/utilities/stringOps.h" #include +#include +#include #include #include #include @@ -39,336 +39,345 @@ static std::string encode(std::string_view str2encode) ']'; } -namespace helics { -namespace apps { - Clone::Clone(std::string_view appName, FederateInfo& fi): App(appName, fi) - { - fed->setFlagOption(HELICS_FLAG_OBSERVER); - } +namespace helics::apps { +Clone::Clone(std::string_view appName, FederateInfo& fedInfo): App(appName, fedInfo) +{ + initialSetup(); +} - Clone::Clone(std::vector args): App("Clone", std::move(args)) - { - processArgs(); - } +Clone::Clone(std::vector args): App("Clone", std::move(args)) +{ + processArgs(); + initialSetup(); +} - Clone::Clone(int argc, char* argv[]): App("Clone", argc, argv) - { - processArgs(); - } +Clone::Clone(int argc, char* argv[]): App("Clone", argc, argv) +{ + processArgs(); + initialSetup(); +} - void Clone::processArgs() - { - auto app = buildArgParserApp(); - if (!deactivated) { - fed->setFlagOption(HELICS_FLAG_OBSERVER); - app->parse(remArgs); - if (!masterFileName.empty()) { - loadFile(masterFileName); - } - } else if (helpMode) { - app->remove_helics_specifics(); - std::cout << app->help(); - } +void Clone::processArgs() +{ + auto app = buildArgParserApp(); + if (!deactivated) { + app->parse(remArgs); + } else if (helpMode) { + app->remove_helics_specifics(); + std::cout << app->help(); } +} - Clone::Clone(std::string_view appName, - const std::shared_ptr& core, - const FederateInfo& fi): - App(appName, core, fi) - { - fed->setFlagOption(HELICS_FLAG_OBSERVER); - } +Clone::Clone(std::string_view appName, + const std::shared_ptr& core, + const FederateInfo& fedInfo): + App(appName, core, fedInfo) +{ + initialSetup(); +} - Clone::Clone(std::string_view appName, CoreApp& core, const FederateInfo& fi): - App(appName, core, fi) - { - fed->setFlagOption(HELICS_FLAG_OBSERVER); +Clone::Clone(std::string_view appName, CoreApp& core, const FederateInfo& fedInfo): + App(appName, core, fedInfo) +{ + initialSetup(); +} + +Clone::Clone(std::string_view appName, const std::string& jsonString): App(appName, jsonString) +{ + processArgs(); + initialSetup(); +} + +Clone::~Clone() +{ + try { + if (!fileSaved && !outFileName.empty()) { + saveFile(outFileName); + } + } + catch (...) { } +} - Clone::Clone(std::string_view appName, const std::string& jsonString): App(appName, jsonString) - { +void Clone::initialSetup() +{ + if (!deactivated) { fed->setFlagOption(HELICS_FLAG_OBSERVER); - Clone::loadJsonFile(jsonString); + loadInputFiles(); } +} - Clone::~Clone() - { - try { - if (!fileSaved && !outFileName.empty()) { - saveFile(outFileName); - } +void Clone::saveFile(const std::string& filename) +{ + if (filename.empty()) { + if (!outFileName.empty()) { + saveFile(outFileName); } - catch (...) { + return; + } + Json::Value doc = fileops::loadJsonStr(fedConfig); + doc["defaultglobal"] = true; + if (!cloneSubscriptionNames.empty()) { + doc["optional"] = true; + + doc["subscriptions"] = Json::Value(Json::arrayValue); + for (auto& sub : cloneSubscriptionNames) { + Json::Value subsc; + subsc["key"] = sub; + doc["subscriptions"].append(subsc); } } - - void Clone::saveFile(const std::string& filename) - { - if (filename.empty()) { - if (!outFileName.empty()) { - saveFile(outFileName); + if (!points.empty()) { + doc["points"] = Json::Value(Json::arrayValue); + for (auto& point : points) { + Json::Value pointData; + pointData["key"] = subscriptions[point.index].getTarget(); + pointData["value"] = point.value; + pointData["time"] = static_cast(point.time); + if (point.iteration > 0) { + pointData["iteration"] = point.iteration; } - return; - } - Json::Value doc = fileops::loadJsonStr(fedConfig); - doc["defaultglobal"] = true; - if (!cloneSubscriptionNames.empty()) { - doc["optional"] = true; - - doc["subscriptions"] = Json::Value(Json::arrayValue); - for (auto& sub : cloneSubscriptionNames) { - Json::Value subsc; - subsc["key"] = sub; - doc["subscriptions"].append(subsc); - } - } - if (!points.empty()) { - doc["points"] = Json::Value(Json::arrayValue); - for (auto& v : points) { - Json::Value point; - point["key"] = subscriptions[v.index].getTarget(); - point["value"] = v.value; - point["time"] = static_cast(v.time); - if (v.iteration > 0) { - point["iteration"] = v.iteration; - } - if (v.first) { - point["type"] = subscriptions[v.index].getPublicationType(); - } - doc["points"].append(point); + if (point.first) { + pointData["type"] = subscriptions[point.index].getPublicationType(); } + doc["points"].append(pointData); } + } - if (!messages.empty()) { - doc["messages"] = Json::Value(Json::arrayValue); - for (auto& mess : messages) { - Json::Value message; - message["time"] = static_cast(mess->time); - message["src"] = mess->source; - if ((!mess->original_source.empty()) && (mess->original_source != mess->source)) { - message["original_source"] = mess->original_source; - } - if ((mess->dest.size() < 7) || - (mess->dest.compare(mess->dest.size() - 6, 6, "cloneE") != 0)) { - message["dest"] = mess->dest; - message["orig_dest"] = mess->original_dest; + if (!messages.empty()) { + doc["messages"] = Json::Value(Json::arrayValue); + for (auto& mess : messages) { + Json::Value message; + message["time"] = static_cast(mess->time); + message["src"] = mess->source; + if ((!mess->original_source.empty()) && (mess->original_source != mess->source)) { + message["original_source"] = mess->original_source; + } + if ((mess->dest.size() < 7) || + (mess->dest.compare(mess->dest.size() - 6, 6, "cloneE") != 0)) { + message["dest"] = mess->dest; + message["orig_dest"] = mess->original_dest; + } else { + message["dest"] = mess->original_dest; + } + if (isBinaryData(mess->data)) { + if (isEscapableData(mess->data)) { + message["message"] = std::string(mess->data.to_string()); } else { - message["dest"] = mess->original_dest; + message["encoding"] = "base64"; + message["message"] = encode(std::string(mess->data.to_string())); } - if (isBinaryData(mess->data)) { - if (isEscapableData(mess->data)) { - message["message"] = std::string(mess->data.to_string()); - } else { - message["encoding"] = "base64"; - message["message"] = encode(std::string(mess->data.to_string())); - } - } else { - message["message"] = std::string(mess->data.to_string()); - } - doc["messages"].append(message); + } else { + message["message"] = std::string(mess->data.to_string()); } + doc["messages"].append(message); } - - std::ofstream o(filename); - o << doc << std::endl; - fileSaved = true; } - void Clone::initialize() - { - generateInterfaces(); + std::ofstream outfile(filename); + outfile << doc << std::endl; + fileSaved = true; +} - pubPointCount.resize(subids.size(), 0); +void Clone::initialize() +{ + generateInterfaces(); - fed->enterInitializingMode(); - captureForCurrentTime(-1.0); + pubPointCount.resize(subids.size(), 0); - fed->enterExecutingMode(); - captureForCurrentTime(0.0); - } + fed->enterInitializingMode(); + captureForCurrentTime(-1.0); - void Clone::generateInterfaces() - { - auto res = waitForInit(fed.get(), captureFederate); - if (res) { - fed->query("root", "global_flush", HELICS_SEQUENCING_MODE_ORDERED); - auto pubs = vectorizeQueryResult( - fed->query(captureFederate, "publications", HELICS_SEQUENCING_MODE_ORDERED)); - for (auto& pub : pubs) { - if (pub.empty()) { - continue; - } - addSubscription(pub); + fed->enterExecutingMode(); + captureForCurrentTime(0.0); +} + +void Clone::generateInterfaces() +{ + auto res = waitForInit(fed.get(), captureFederate); + if (res) { + fed->query("root", "global_flush", HELICS_SEQUENCING_MODE_ORDERED); + auto pubs = vectorizeQueryResult( + fed->query(captureFederate, "publications", HELICS_SEQUENCING_MODE_ORDERED)); + for (auto& pub : pubs) { + if (pub.empty()) { + continue; } - auto epts = vectorizeQueryResult( - fed->query(captureFederate, "endpoints", HELICS_SEQUENCING_MODE_ORDERED)); - for (auto& ept : epts) { - if (ept.empty()) { - continue; - } - addSourceEndpointClone(ept); + addSubscription(pub); + } + auto epts = vectorizeQueryResult( + fed->query(captureFederate, "endpoints", HELICS_SEQUENCING_MODE_ORDERED)); + for (auto& ept : epts) { + if (ept.empty()) { + continue; } - cloneSubscriptionNames = - vectorizeQueryResult(queryFederateSubscriptions(fed.get(), captureFederate)); - // get rid of any empty strings that may have come to be - cloneSubscriptionNames.erase(std::remove(cloneSubscriptionNames.begin(), - cloneSubscriptionNames.end(), - std::string{}), - cloneSubscriptionNames.end()); - - fedConfig = fed->query(captureFederate, "config", HELICS_SEQUENCING_MODE_ORDERED); + addSourceEndpointClone(ept); } + cloneSubscriptionNames = + vectorizeQueryResult(queryFederateSubscriptions(fed.get(), captureFederate)); + // get rid of any empty strings that may have come to be + cloneSubscriptionNames.erase(std::remove(cloneSubscriptionNames.begin(), + cloneSubscriptionNames.end(), + std::string{}), + cloneSubscriptionNames.end()); + + fedConfig = fed->query(captureFederate, "config", HELICS_SEQUENCING_MODE_ORDERED); } +} - void Clone::captureForCurrentTime(Time currentTime, int iteration) - { - for (auto& sub : subscriptions) { - if (sub.isUpdated()) { - auto val = sub.getValue(); - int ii = subids[sub.getHandle()]; - points.emplace_back(currentTime, ii, val); - if (iteration > 0) { - points.back().iteration = iteration; - } - if (verbose) { - std::string valstr; - if (val.size() < 150) { - if (iteration > 0) { - valstr = fmt::format( - "[{}:{}]value {}={}", currentTime, iteration, sub.getTarget(), val); - } else { - valstr = - fmt::format("[{}]value {}={}", currentTime, sub.getTarget(), val); - } +void Clone::captureForCurrentTime(Time currentTime, int iteration) +{ + for (auto& sub : subscriptions) { + if (sub.isUpdated()) { + auto val = sub.getValue(); + const int subid = subids[sub.getHandle()]; + points.emplace_back(currentTime, subid, val); + if (iteration > 0) { + points.back().iteration = iteration; + } + if (verbose) { + std::string valstr; + if (val.size() < 150) { + if (iteration > 0) { + valstr = fmt::format("[{}:{}]value {}={}", + static_cast(currentTime), + iteration, + sub.getTarget(), + val); } else { - if (iteration > 0) { - valstr = fmt::format("[{}:{}]value {}=block[{}]", - currentTime, - iteration, - sub.getTarget(), - val.size()); - } else { - valstr = fmt::format("[{}]value {}=block[{}]", - currentTime, - sub.getTarget(), - val.size()); - } + valstr = fmt::format("[{}]value {}={}", + static_cast(currentTime), + sub.getTarget(), + val); + } + } else { + if (iteration > 0) { + valstr = fmt::format("[{}:{}]value {}=block[{}]", + static_cast(currentTime), + iteration, + sub.getTarget(), + val.size()); + } else { + valstr = fmt::format("[{}]value {}=block[{}]", + static_cast(currentTime), + sub.getTarget(), + val.size()); } - spdlog::info(valstr); - } - if (pubPointCount[ii] == 0) { - points.back().first = true; } - ++pubPointCount[ii]; + spdlog::info(valstr); } + if (pubPointCount[subid] == 0) { + points.back().first = true; + } + ++pubPointCount[subid]; } + } - // get the clone endpoints - if (cloneEndpoint) { - while (cloneEndpoint->hasMessage()) { - messages.push_back(cloneEndpoint->getMessage()); - } + // get the clone endpoints + if (cloneEndpoint) { + while (cloneEndpoint->hasMessage()) { + messages.push_back(cloneEndpoint->getMessage()); } } +} - /** run the Player until the specified time*/ - void Clone::runTo(Time runToTime) - { - initialize(); - - Time nextPrintTime = (nextPrintTimeStep > timeZero) ? nextPrintTimeStep : Time::maxVal(); - try { - int iteration = 0; - while (true) { - helics::Time T; - if (allow_iteration) { - auto ItRes = - fed->requestTimeIterative(runToTime, IterationRequest::ITERATE_IF_NEEDED); - if (ItRes.state == IterationResult::NEXT_STEP) { - iteration = 0; - } - T = ItRes.grantedTime; - captureForCurrentTime(T, iteration); - ++iteration; - } else { - T = fed->requestTime(runToTime); - captureForCurrentTime(T); +/** run the Player until the specified time*/ +void Clone::runTo(Time runToTime) +{ + initialize(); + + Time nextPrintTime = (nextPrintTimeStep > timeZero) ? nextPrintTimeStep : Time::maxVal(); + try { + int iteration = 0; + while (true) { + helics::Time grantedTime; + if (allow_iteration) { + auto ItRes = + fed->requestTimeIterative(runToTime, IterationRequest::ITERATE_IF_NEEDED); + if (ItRes.state == IterationResult::NEXT_STEP) { + iteration = 0; } + grantedTime = ItRes.grantedTime; + captureForCurrentTime(grantedTime, iteration); + ++iteration; + } else { + grantedTime = fed->requestTime(runToTime); + captureForCurrentTime(grantedTime); + } - if (T >= runToTime) { - break; - } - if ((T >= nextPrintTime) && (nextPrintTimeStep > timeZero)) { - std::cout << "processed for time " << static_cast(T) << "\n"; - nextPrintTime += nextPrintTimeStep; - } + if (grantedTime >= runToTime) { + break; + } + if ((grantedTime >= nextPrintTime) && (nextPrintTimeStep > timeZero)) { + std::cout << "processed for time " << static_cast(grantedTime) << "\n"; + nextPrintTime += nextPrintTimeStep; } - } - catch (...) { } } - /** add a subscription to record*/ - void Clone::addSubscription(std::string_view key) - { - auto res = subkeys.find(key); - if ((res == subkeys.end()) || (res->second == -1)) { - subscriptions.emplace_back(fed->registerSubscription(key)); - auto index = static_cast(subscriptions.size()) - 1; - auto id = subscriptions.back().getHandle(); - subids[id] = index; // this is a new element - subkeys[subscriptions.back().getTarget()] = index; // this is a potential replacement - } + catch (...) { } - - void Clone::addSourceEndpointClone(std::string_view sourceEndpoint) - { - if (!cFilt) { - cFilt = std::make_unique(fed.get()); - cloneEndpoint = std::make_unique(fed.get(), "cloneE"); - cFilt->addDeliveryEndpoint(cloneEndpoint->getName()); - } - cFilt->addSourceTarget(sourceEndpoint); +} +/** add a subscription to record*/ +void Clone::addSubscription(std::string_view key) +{ + auto res = subkeys.find(key); + if ((res == subkeys.end()) || (res->second == -1)) { + subscriptions.emplace_back(fed->registerSubscription(key)); + auto index = static_cast(subscriptions.size()) - 1; + auto subid = subscriptions.back().getHandle(); + subids[subid] = index; // this is a new element + subkeys[subscriptions.back().getTarget()] = index; // this is a potential replacement } +} - void Clone::setFederateToClone(std::string_view federateName) - { - captureFederate = federateName; +void Clone::addSourceEndpointClone(std::string_view sourceEndpoint) +{ + if (!cFilt) { + cFilt = std::make_unique(fed.get()); + cloneEndpoint = std::make_unique(fed.get(), "cloneE"); + cFilt->addDeliveryEndpoint(cloneEndpoint->getName()); } + cFilt->addSourceTarget(sourceEndpoint); +} - std::tuple Clone::getValue(int index) const - { - if (isValidIndex(index, points)) { - return {points[index].time, - subscriptions[points[index].index].getTarget(), - points[index].value}; - } - return {Time(), std::string(), std::string()}; +void Clone::setFederateToClone(std::string_view federateName) +{ + captureFederate = federateName; +} + +std::tuple Clone::getValue(int index) const +{ + if (isValidIndex(index, points)) { + return {points[index].time, + subscriptions[points[index].index].getTarget(), + points[index].value}; } + return {Time(), std::string(), std::string()}; +} - std::unique_ptr Clone::getMessage(int index) const - { - if (isValidIndex(index, messages)) { - return std::make_unique(*messages[index]); - } - return nullptr; +std::unique_ptr Clone::getMessage(int index) const +{ + if (isValidIndex(index, messages)) { + return std::make_unique(*messages[index]); } + return nullptr; +} - std::shared_ptr Clone::buildArgParserApp() - { - auto app = std::make_shared("Command line options for the Clone App"); - if (!app) { - throw(FunctionExecutionFailure("unable to allocate application CLI")); - } - app->add_flag("--allow_iteration", allow_iteration, "allow iteration on values") - ->ignore_underscore(); +std::shared_ptr Clone::buildArgParserApp() +{ + auto app = std::make_shared("Command line options for the Clone App"); + if (!app) { + throw(FunctionExecutionFailure("unable to allocate application CLI")); + } + app->add_flag("--allow_iteration", allow_iteration, "allow iteration on values") + ->ignore_underscore(); - app->add_option("--output,-o", outFileName, "the output file for recording the data") - ->capture_default_str(); - app->add_option("capture", captureFederate, "name of the federate to clone"); + app->add_option("--output,-o", outFileName, "the output file for recording the data") + ->capture_default_str(); + app->add_option("capture", captureFederate, "name of the federate to clone"); - return app; - } + return app; +} -} // namespace apps -} // namespace helics +} // namespace helics::apps diff --git a/src/helics/apps/Clone.hpp b/src/helics/apps/Clone.hpp index c4163fa9f8..75f76ef6b4 100644 --- a/src/helics/apps/Clone.hpp +++ b/src/helics/apps/Clone.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -30,9 +30,9 @@ namespace apps { /** construct from a FederateInfo structure @param appName the name of the Recorder, can be left empty for the default or to pull from the federateInfo object - @param fi a federate information structure + @param fedInfo a federate information structure */ - Clone(std::string_view appName, FederateInfo& fi); + Clone(std::string_view appName, FederateInfo& fedInfo); /** construct from command line arguments in a vector @param args the command line arguments to pass in a reverse vector */ @@ -44,16 +44,18 @@ namespace apps { @param appName the name of the Recorder, can be left empty for the default or to pull from the federateInfo object @param core a pointer to core object which the federate can join - @param fi a federate information structure + @param fedInfo a federate information structure */ - Clone(std::string_view appName, const std::shared_ptr& core, const FederateInfo& fi); + Clone(std::string_view appName, + const std::shared_ptr& core, + const FederateInfo& fedInfo); /**constructor taking a federate information structure and using the given core - @param appName the name of the federate (can be empty to use defaults from fi) + @param appName the name of the federate (can be empty to use defaults from fedInfo) @param core a coreApp object that can be joined - @param fi a federate information structure + @param fedInfo a federate information structure */ - Clone(std::string_view appName, CoreApp& core, const FederateInfo& fi); + Clone(std::string_view appName, CoreApp& core, const FederateInfo& fedInfo); /**constructor taking a file with the required information @param appName the name of the app @@ -105,6 +107,9 @@ namespace apps { void captureForCurrentTime(Time currentTime, int iteration = 0); /** build the command line argument processing application*/ std::shared_ptr buildArgParserApp(); + + /** run any initial setup operations including file loading*/ + void initialSetup(); /** process remaining command line arguments*/ void processArgs(); diff --git a/src/helics/apps/Connector.cpp b/src/helics/apps/Connector.cpp new file mode 100644 index 0000000000..a30ace2a1d --- /dev/null +++ b/src/helics/apps/Connector.cpp @@ -0,0 +1,1202 @@ +/* +Copyright (c) 2017-2024, +Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable +Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. +SPDX-License-Identifier: BSD-3-Clause +*/ + +#include "Connector.hpp" + +#include "../application_api/HelicsPrimaryTypes.hpp" +#include "../common/JsonProcessingFunctions.hpp" +#include "../core/helicsCLI11.hpp" +#include "../core/helicsVersion.hpp" +#include "gmlc/utilities/stringOps.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace helics::apps { + +/** dataclass for potential connections*/ +struct PotentialConnections { + std::string_view federate; + std::string_view key; + bool used{false}; +}; + +/** data class for information from queries*/ +struct ConnectionsList { + std::unordered_multimap aliases; + std::vector unconnectedPubs; + std::vector unconnectedInputs; + std::vector unconnectedTargetEndpoints; + std::vector unconnectedSourceEndpoints; + std::unordered_set pubs; + std::unordered_set inputs; + std::unordered_set endpoints; + + std::unordered_map potentialPubs; + std::unordered_map potentialInputs; + std::unordered_map potentialEndpoints; + std::deque interfaces; + std::deque federatesWithPotentialInterfaces; + std::vector unknownPubs; + std::vector unknownInputs; + std::vector unknownEndpoints; + std::vector tagStrings; + std::vector tagCodes; + bool hasPotentialInterfaces{false}; +}; + +static void loadTags(ConnectionsList& connections, const Json::Value& tags) +{ + for (Json::Value::const_iterator itr = tags.begin(); itr != tags.end(); ++itr) { + if (itr.key().asString() == "tags") { + auto tagVect = gmlc::utilities::stringOps::splitlineQuotes(itr->asString()); + connections.tagStrings.insert(connections.tagStrings.end(), + tagVect.begin(), + tagVect.end()); + } else { + if (!itr->isString() || isTrueString(itr->asCString())) { + connections.tagStrings.emplace_back(itr.key().asString()); + } + } + } +} +static void coreConnectionList(ConnectionsList& connections, Json::Value& core) +{ + if (core.isMember("tags")) { + loadTags(connections, core["tags"]); + } + if (core.isMember("federates")) { + for (const auto& fed : core["federates"]) { + try { + if (fed.isMember("tags")) { + loadTags(connections, fed["tags"]); + } + if (fed.isMember("connected_inputs")) { + for (const auto& input : fed["connected_inputs"]) { + const std::string_view input1 = + connections.interfaces.emplace_back(input.asString()); + connections.inputs.insert(input1); + } + } + if (fed.isMember("connected_publications")) { + for (const auto& pub : fed["connected_publications"]) { + const std::string_view pub1 = + connections.interfaces.emplace_back(pub.asString()); + connections.pubs.insert(pub1); + } + } + if (fed.isMember("unconnected_inputs")) { + for (const auto& input : fed["unconnected_inputs"]) { + const std::string_view input1 = + connections.interfaces.emplace_back(input.asString()); + connections.unconnectedInputs.push_back(input1); + connections.inputs.insert(input1); + } + } + if (fed.isMember("unconnected_publications")) { + for (const auto& pub : fed["unconnected_publications"]) { + const std::string_view pub1 = + connections.interfaces.emplace_back(pub.asString()); + connections.unconnectedPubs.push_back(pub1); + connections.pubs.insert(pub1); + } + } + + if (fed.isMember("unconnected_target_endpoints")) { + for (const auto& endpoint : fed["unconnected_target_endpoints"]) { + const std::string_view end1 = + connections.interfaces.emplace_back(endpoint.asString()); + connections.unconnectedTargetEndpoints.push_back(end1); + connections.endpoints.insert(end1); + } + } + if (fed.isMember("unconnected_source_endpoints")) { + for (const auto& endpoint : fed["unconnected_source_endpoints"]) { + const std::string_view end1 = + connections.interfaces.emplace_back(endpoint.asString()); + connections.unconnectedSourceEndpoints.push_back(end1); + connections.endpoints.insert(end1); + } + } + if (fed.isMember("connected_endpoints")) { + for (const auto& endpoint : fed["connected_endpoints"]) { + const std::string_view end1 = + connections.interfaces.emplace_back(endpoint.asString()); + connections.endpoints.insert(end1); + } + } + if (fed.isMember("potential_interfaces")) { + connections.hasPotentialInterfaces = true; + const std::string_view federateName = + connections.federatesWithPotentialInterfaces.emplace_back( + fed["attributes"]["name"].asCString()); + const auto& potInterfaces = fed["potential_interfaces"]; + if (potInterfaces.isMember("inputs")) { + for (const auto& input : potInterfaces["inputs"]) { + if (input.isObject()) { + auto name = fileops::getName(input); + if (name.empty()) { + continue; + } + const std::string_view input1 = + connections.interfaces.emplace_back(name); + connections.potentialInputs.emplace( + input1, PotentialConnections{federateName, input1, false}); + } else if (input.isString()) { + const std::string_view input1 = + connections.interfaces.emplace_back(input.asCString()); + connections.potentialInputs.emplace( + input1, PotentialConnections{federateName, input1, false}); + } + } + } + if (potInterfaces.isMember("publications")) { + for (const auto& pub : potInterfaces["publications"]) { + if (pub.isObject()) { + auto name = fileops::getName(pub); + if (name.empty()) { + continue; + } + const std::string_view pub1 = + connections.interfaces.emplace_back(name); + connections.potentialPubs.emplace( + pub1, PotentialConnections{federateName, pub1, false}); + } else if (pub.isString()) { + const std::string_view pub1 = + connections.interfaces.emplace_back(pub.asCString()); + connections.potentialPubs.emplace( + pub1, PotentialConnections{federateName, pub1, false}); + } + } + } + if (potInterfaces.isMember("endpoints")) { + for (const auto& endpoint : potInterfaces["endpoints"]) { + if (endpoint.isObject()) { + auto name = fileops::getName(endpoint); + if (name.empty()) { + continue; + } + const std::string_view endpoint1 = + connections.interfaces.emplace_back(name); + connections.potentialEndpoints.emplace( + endpoint1, + PotentialConnections{federateName, endpoint1, false}); + } else { + const std::string_view endpoint1 = + connections.interfaces.emplace_back(endpoint.asCString()); + connections.potentialEndpoints.emplace( + endpoint1, + PotentialConnections{federateName, endpoint1, false}); + } + } + } + } + } + catch (const Json::Exception& /*ev*/) { + // TODO(PT): I think this is going to be almost impossible now, but someday might + // want to create a response + continue; + } + } + } +} + +static void brokerConnectionList(ConnectionsList& connections, Json::Value& broker) +{ + for (auto& subBroker : broker["brokers"]) { + brokerConnectionList(connections, subBroker); + } + for (auto& core : broker["cores"]) { + coreConnectionList(connections, core); + } +} + +static ConnectionsList generateConnectionsList(const std::string& connectionData) +{ + ConnectionsList connections; + auto json = fileops::loadJsonStr(connectionData); + if (json.isMember("aliases")) { + for (auto& alias : json["aliases"]) { + const std::string_view alias1 = + connections.interfaces.emplace_back(alias[0].asString()); + const std::string_view alias2 = + connections.interfaces.emplace_back(alias[1].asString()); + connections.aliases.emplace(alias1, alias2); + } + } + if (json.isMember("tags")) { + loadTags(connections, json["tags"]); + } + if (json.isMember("unknown_inputs")) { + for (const auto& input : json["unknown_inputs"]) { + connections.unknownInputs.push_back(input.asString()); + } + } + if (json.isMember("unknown_publications")) { + for (const auto& pub : json["unknown_publications"]) { + connections.unknownPubs.push_back(pub.asString()); + } + } + if (json.isMember("unknown_endpoints")) { + for (const auto& ept : json["unknown_endpoints"]) { + connections.unknownEndpoints.push_back(ept.asString()); + } + } + for (auto& broker : json["brokers"]) { + brokerConnectionList(connections, broker); + } + for (auto& core : json["cores"]) { + coreConnectionList(connections, core); + } + connections.tagStrings.push_back("default"); + connections.tagCodes.reserve(connections.tagStrings.size()); + std::transform(connections.tagStrings.begin(), + connections.tagStrings.end(), + std::back_inserter(connections.tagCodes), + std::hash()); + return connections; +} + +Connector::Connector(std::vector args): + App("connector", std::move(args)), core((fed) ? fed->getCorePointer() : nullptr) +{ + processArgs(); + initialSetup(); +} + +Connector::Connector(int argc, char* argv[]): + App("connector", argc, argv), core((fed) ? fed->getCorePointer() : nullptr) +{ + processArgs(); + initialSetup(); +} + +void Connector::processArgs() +{ + auto app = generateParser(); + + if (!deactivated) { + app->helics_parse(remArgs); + } else if (helpMode) { + app->remove_helics_specifics(); + std::cout << app->help(); + } +} + +void Connector::initialSetup() +{ + if (!deactivated) { + fed->setFlagOption(HELICS_FLAG_SOURCE_ONLY); + loadInputFiles(); + } +} + +const std::unordered_map directionNames{ + {"from_to", InterfaceDirection::FROM_TO}, + {"1", InterfaceDirection::FROM_TO}, + {"FROM_TO", InterfaceDirection::FROM_TO}, + {"to_from", InterfaceDirection::TO_FROM}, + {"TO_FROM", InterfaceDirection::TO_FROM}, + {"-1", InterfaceDirection::TO_FROM}, + {"bidirectional", InterfaceDirection::BIDIRECTIONAL}, + {"BIDIRECTIONAL", InterfaceDirection::BIDIRECTIONAL}, + {"0", InterfaceDirection::BIDIRECTIONAL}, + {"bi", InterfaceDirection::BIDIRECTIONAL}, + {"BI", InterfaceDirection::BIDIRECTIONAL}}; + +std::optional getDirection(std::string_view direction) +{ + auto res = directionNames.find(direction); + if (res != directionNames.end()) { + return res->second; + } + return std::nullopt; +} + +std::unique_ptr Connector::generateParser() +{ + auto app = std::make_unique("Command line options for the Connector App"); + app->add_option_function>>( + "--connection", + [this](const std::vector>& args) { + for (const auto& conn : args) { + addConnectionVector(conn); + } + }, + "specify connections to make in the cosimulation") + ->expected(2, CLI::detail::expected_max_vector_size) + ->type_name("[INTERFACE1,INTERFACE2,DIRECTIONALITY,TAGS...]"); + app->add_flag("--match_target_endpoints", + matchTargetEndpoints, + "set to true to enable connection of unconnected target endpoints") + ->ignore_underscore(); + app->add_flag("--match_multiple", + matchMultiple, + "set to true to enable matching of multiple connections (default false)") + ->ignore_underscore(); + app->add_flag("--always_check_regex", + alwaysCheckRegex, + "set to true to enable regex matching even if other matches are defined") + ->ignore_underscore(); + + return app; +} + +Connector::Connector(std::string_view appName, const FederateInfo& fedInfo): + App(appName, fedInfo), core((fed) ? fed->getCorePointer() : nullptr) +{ + initialSetup(); +} + +Connector::Connector(std::string_view appName, + const std::shared_ptr& core, + const FederateInfo& fedInfo): + App(appName, core, fedInfo), + core((fed) ? fed->getCorePointer() : nullptr) +{ + initialSetup(); +} + +Connector::Connector(std::string_view appName, CoreApp& core, const FederateInfo& fedInfo): + App(appName, core, fedInfo), core((fed) ? fed->getCorePointer() : nullptr) +{ + initialSetup(); +} + +Connector::Connector(std::string_view appName, const std::string& configString): + App(appName, configString), core((fed) ? fed->getCorePointer() : nullptr) +{ + initialSetup(); +} + +std::size_t Connector::addTag(std::string_view tagName) +{ + std::size_t hash = std::hash()(tagName); + tags.emplace(hash, tagName); + return hash; +} + +std::string_view Connector::addInterface(std::string_view interfaceName) +{ + auto interfaceIterator = interfaces.insert(std::string(interfaceName)); + return {*(interfaceIterator.first)}; +} + +bool Connector::addConnectionVector(const std::vector& connection) +{ + if (connection.size() <= 1) { + return false; + } + if (connection.size() == 2) { + addConnection(connection[0], connection[1]); + return true; + } + + InterfaceDirection direction{InterfaceDirection::BIDIRECTIONAL}; + std::vector newTags; + auto directionValue = getDirection(connection[2]); + if (directionValue) { + direction = *directionValue; + } else { + newTags.push_back(connection[2]); + } + + for (int ii = 3; ii < connection.size(); ++ii) { + newTags.push_back(connection[ii]); + } + addConnection(connection[0], connection[1], direction, newTags); + return true; +} + +void Connector::addConnection(std::string_view interface1, + std::string_view interface2, + InterfaceDirection direction, + const std::vector& connectionTags) +{ + std::vector svtags; + svtags.reserve(connectionTags.size()); + for (const auto& tag : connectionTags) { + svtags.push_back(addTag(tag)); + } + auto iview1 = addInterface(interface1); + auto iview2 = addInterface(interface2); + Connection conn{iview1, iview2, direction, std::move(svtags)}; + if (iview1.compare(0, 6, "REGEX:") == 0) { + switch (direction) { + case InterfaceDirection::TO_FROM: + std::swap(conn.interface1, conn.interface2); + matchers.emplace_back(std::move(conn)); + break; + case InterfaceDirection::FROM_TO: + matchers.emplace_back(std::move(conn)); + break; + case InterfaceDirection::BIDIRECTIONAL: + matchers.emplace_back(conn); + std::swap(conn.interface1, conn.interface2); + matchers.emplace_back(std::move(conn)); + break; + } + } else { + switch (direction) { + case InterfaceDirection::TO_FROM: + connections.emplace(iview2, std::move(conn)); + break; + case InterfaceDirection::FROM_TO: + connections.emplace(iview1, std::move(conn)); + break; + case InterfaceDirection::BIDIRECTIONAL: + connections.emplace(iview2, conn); + if (iview1 != iview2) { + connections.emplace(iview1, std::move(conn)); + } + break; + } + } +} + +class RegexMatcher { + public: + RegexMatcher() = default; + + std::regex rmatch; + std::vector keys; + std::string_view interface1; + std::string_view interface2; + std::vector tags; + std::string generateMatch(std::string_view testString) + { + std::match_results matchResults{}; + if (std::regex_match(testString.begin(), testString.end(), matchResults, rmatch)) { + std::string matcher(interface2); + if (matcher.compare(0, 6, "REGEX:") == 0) { + matcher.erase(0, 6); + for (std::size_t ii = 0; ii < keys.size(); ++ii) { + auto keyloc = matcher.find(keys[ii]); + while (keyloc != std::string::npos) { + auto endloc = matcher.find_first_of(')', keyloc); + matcher.replace(matcher.begin() + keyloc - 1, + matcher.begin() + endloc + 1, + matchResults[ii + 1].first, + matchResults[ii + 1].second); + keyloc = matcher.find(keys[ii]); + } + } + } + + return matcher; + } + return {}; + } +}; + +void Connector::loadTextFile(const std::string& filename) +{ + using namespace gmlc::utilities::stringOps; // NOLINT + AppTextParser aparser(filename); + auto cnts = aparser.preParseFile({}); + + aparser.reset(); + + if (!aparser.configString().empty()) { + App::loadConfigOptions(aparser); + auto app = generateParser(); + std::istringstream sstr(aparser.configString()); + app->parse_from_stream(sstr); + } + connections.reserve(connections.size() + cnts[0]); + std::string str; + int lineNumber; + while (aparser.loadNextLine(str, lineNumber)) { + /* time key type value units*/ + auto blk = splitlineQuotes(str, ",\t ", default_quote_chars, delimiter_compression::on); + for (auto& seq : blk) { + CLI::detail::remove_quotes(seq); + } + addConnectionVector(blk); + } +} + +void Connector::loadJsonFile(const std::string& jsonString, + bool enableFederateInterfaceRegistration) +{ + loadJsonFileConfiguration("connector", jsonString, enableFederateInterfaceRegistration); + + auto doc = fileops::loadJson(jsonString); + + if (doc.isMember("connector")) { + auto connectorConfig = doc["connector"]; + matchTargetEndpoints = + fileops::getOrDefault(connectorConfig, "match_target_endpoints", matchTargetEndpoints); + matchMultiple = fileops::getOrDefault(connectorConfig, "match_multiple", matchMultiple); + alwaysCheckRegex = + fileops::getOrDefault(connectorConfig, "always_check_regex", alwaysCheckRegex); + } + auto connectionArray = doc["connections"]; + if (connectionArray.isArray()) { + connections.reserve(connections.size() + connectionArray.size()); + for (const auto& connectionElement : connectionArray) { + std::vector connectionObject; + for (const auto& subElement : connectionElement) { + connectionObject.push_back(subElement.asString()); + } + addConnectionVector(connectionObject); + } + } +} + +std::vector + Connector::buildPossibleConnectionList(std::string_view startingInterface, + const std::vector& tagList) const +{ + std::vector matches; + auto [first, last] = connections.equal_range(startingInterface); + if (first != connections.end()) { + std::set searched; + searched.insert(startingInterface); + + for (auto match = first; match != last; ++match) { + if (match->second.tags.empty() || + std::find_first_of(tagList.begin(), + tagList.end(), + match->second.tags.begin(), + match->second.tags.end()) != tagList.end()) { + matches.emplace_back(match->second); + if (matches.back().interface1 != startingInterface) { + std::swap(matches.back().interface1, matches.back().interface2); + } + } + } + std::size_t cascadeIndex{0}; + while (cascadeIndex < matches.size()) { + if (searched.find(matches[cascadeIndex].interface2) != searched.end()) { + ++cascadeIndex; + continue; + } + searched.insert(matches[cascadeIndex].interface2); + std::tie(first, last) = connections.equal_range(matches[cascadeIndex].interface2); + if (first != connections.end()) { + for (auto match = first; match != last; ++match) { + if (match->second.tags.empty() || + std::find_first_of(tagList.begin(), + tagList.end(), + match->second.tags.begin(), + match->second.tags.end()) != tagList.end()) { + matches.emplace_back(match->second); + if (matches.back().interface1 != matches[cascadeIndex].interface2) { + std::swap(matches.back().interface1, matches.back().interface2); + } + if (searched.find(matches.back().interface2) != searched.end()) { + // this would already be references and create a cyclic reference + matches.pop_back(); + } + } + } + } + ++cascadeIndex; + } + } + if (matches.empty() || alwaysCheckRegex) { + if (!regexMatchers.empty()) { + for (const auto& rmatcher : regexMatchers) { + if (rmatcher->tags.empty() || + std::find_first_of(tagList.begin(), + tagList.end(), + rmatcher->tags.begin(), + rmatcher->tags.end()) != tagList.end()) { + auto mstring = rmatcher->generateMatch(startingInterface); + if (!mstring.empty()) { + Connection connection; + connection.stringBuffer = std::make_shared(mstring); + connection.interface1 = rmatcher->interface1; + connection.tags = rmatcher->tags; + connection.interface2 = *connection.stringBuffer; + connection.direction = InterfaceDirection::FROM_TO; + matches.push_back(std::move(connection)); + } + } + } + } + } + return matches; +} + +static std::set + generateAliases(const std::string_view target, + const std::unordered_multimap& aliases) +{ + std::set matches; + auto [first, last] = aliases.equal_range(target); + if (first == aliases.end()) { + return matches; + } + matches.emplace(target); + std::vector matchList; + for (auto match = first; match != last; ++match) { + matches.emplace(match->second); + matchList.emplace_back(match->second); + } + std::size_t cascadeIndex{1}; + while (cascadeIndex < matchList.size()) { + std::tie(first, last) = aliases.equal_range(matchList[cascadeIndex]); + for (auto match = first; match != last; ++match) { + auto [iterator, newAlias] = matches.emplace(match->second); + if (newAlias) { + matchList.emplace_back(match->second); + } + } + ++cascadeIndex; + } + return matches; +} + +bool Connector::makePotentialConnection( + std::string_view interface, + const std::vector& tagList, + std::unordered_map& potentials, + const std::unordered_multimap& aliases) +{ + auto connectionOptions = buildPossibleConnectionList(interface, tagList); + for (const auto& option : connectionOptions) { + auto located = potentials.find(option.interface2); + if (located != potentials.end()) { + /* source, target*/ + located->second.used = true; + return true; + } + auto aliasList = generateAliases(option.interface2, aliases); + for (const auto& alias : aliasList) { + located = potentials.find(alias); + if (located != potentials.end()) { + /* source, target*/ + located->second.used = true; + return true; + } + } + } + return false; +} + +bool Connector::checkPotentialConnection( + std::string_view interfaceName, + const std::vector& tagList, + std::unordered_set& possibleConnections, + std::unordered_map& potentials, + const std::unordered_multimap& aliases) +{ + static auto nullConnector = [this](std::string_view, std::string_view) {}; + /** potential inputs*/ + auto matched = + makeTargetConnection(interfaceName, tagList, possibleConnections, aliases, nullConnector); + if (matched > 0) { + return true; + } + if (makePotentialConnection(interfaceName, tagList, potentials, aliases)) { + return true; + } + if (!aliases.empty()) { + auto aliasList = generateAliases(interfaceName, aliases); + for (const auto& alias : aliasList) { + if (alias == interfaceName) { + continue; + } + if (makePotentialConnection(alias, tagList, potentials, aliases)) { + return true; + } + } + } + return false; +} + +int Connector::makeTargetConnection( + std::string_view origin, + const std::vector& tagList, + std::unordered_set& possibleConnections, + const std::unordered_multimap& aliases, + const std::function& callback) +{ + int matched{0}; + auto connectionOptions = buildPossibleConnectionList(origin, tagList); + for (const auto& option : connectionOptions) { + auto located = possibleConnections.find(option.interface2); + if (located != possibleConnections.end()) { + /* source, target*/ + callback(origin, option.interface2); + ++matched; + if (!matchMultiple) { + return matched; + } + + } else { + if (!aliases.empty()) { + auto aliasList = generateAliases(option.interface2, aliases); + for (const auto& alias : aliasList) { + if (alias == option.interface2) { + continue; + } + located = possibleConnections.find(alias); + if (located != possibleConnections.end()) { + callback(origin, option.interface2); + ++matched; + if (!matchMultiple) { + return matched; + } + break; + } + } + } + } + } + if (!aliases.empty()) { + auto aliasList = generateAliases(origin, aliases); + for (const auto& alias : aliasList) { + if (alias == origin) { + continue; + } + auto aliasOptions = buildPossibleConnectionList(alias, tagList); + for (const auto& option : aliasOptions) { + auto located = possibleConnections.find(option.interface2); + if (located != possibleConnections.end()) { + /* source, target*/ + callback(origin, option.interface2); + ++matched; + if (!matchMultiple) { + return matched; + } + + } else { + if (!aliases.empty()) { + auto interfaceAliasList = generateAliases(option.interface2, aliases); + for (const auto& interfaceAlias : interfaceAliasList) { + if (alias == option.interface2) { + continue; + } + located = possibleConnections.find(interfaceAlias); + if (located != possibleConnections.end()) { + callback(origin, option.interface2); + ++matched; + if (!matchMultiple) { + return matched; + } + break; + } + } + } + } + } + } + } + return matched; +} + +void Connector::makeConnections(ConnectionsList& possibleConnections) +{ + int logLevel = fed->getIntegerProperty(HELICS_PROPERTY_INT_LOG_LEVEL); + auto inputConnector = [this, logLevel](std::string_view origin, std::string_view source) { + core.dataLink(source, origin); + if (logLevel >= HELICS_LOG_LEVEL_CONNECTIONS) { + fed->logMessage(HELICS_LOG_LEVEL_CONNECTIONS, + fmt::format("connecting input {} to publication {}", origin, source)); + } + }; + auto pubConnector = [this, logLevel](std::string_view origin, std::string_view target) { + core.dataLink(origin, target); + if (logLevel >= HELICS_LOG_LEVEL_CONNECTIONS) { + fed->logMessage(HELICS_LOG_LEVEL_CONNECTIONS, + fmt::format("connecting publication {} to input {}", origin, target)); + } + }; + auto sourceEndpointConnector = [this, logLevel](std::string_view origin, + std::string_view target) { + core.linkEndpoints(origin, target); + if (logLevel >= HELICS_LOG_LEVEL_CONNECTIONS) { + fed->logMessage(HELICS_LOG_LEVEL_CONNECTIONS, + fmt::format("connecting source endpoint {} to target endpoint {}", + origin, + target)); + } + }; + auto targetEndpointConnector = [this, logLevel](std::string_view origin, + std::string_view source) { + core.linkEndpoints(source, origin); + if (logLevel >= HELICS_LOG_LEVEL_CONNECTIONS) { + fed->logMessage(HELICS_LOG_LEVEL_CONNECTIONS, + fmt::format("connecting target endpoint {} to source endpoint {}", + origin, + source)); + } + }; + + auto tagList = possibleConnections.tagCodes; + /** unconnected inputs*/ + for (const auto& uInp : possibleConnections.unconnectedInputs) { + matchCount += makeTargetConnection( + uInp, tagList, possibleConnections.pubs, possibleConnections.aliases, inputConnector); + } + /** unconnected publications*/ + for (const auto& uPub : possibleConnections.unconnectedPubs) { + matchCount += makeTargetConnection( + uPub, tagList, possibleConnections.inputs, possibleConnections.aliases, pubConnector); + } + + /** unconnected source endpoints*/ + for (const auto& uEnd : possibleConnections.unconnectedSourceEndpoints) { + matchCount += makeTargetConnection(uEnd, + tagList, + possibleConnections.endpoints, + possibleConnections.aliases, + sourceEndpointConnector); + } + + if (matchTargetEndpoints) { + /** unconnected target endpoints*/ + for (const auto& uEnd : possibleConnections.unconnectedTargetEndpoints) { + matchCount += makeTargetConnection(uEnd, + tagList, + possibleConnections.endpoints, + possibleConnections.aliases, + targetEndpointConnector); + } + } + if (logLevel >= HELICS_LOG_LEVEL_SUMMARY) { + fed->logInfoMessage(fmt::format("{} connections made", matchCount)); + } +} + +void Connector::establishPotentialInterfaces(ConnectionsList& possibleConnections) +{ + auto nullConnector = [this](std::string_view, std::string_view) {}; + auto tagList = possibleConnections.tagCodes; + /** potential inputs*/ + for (auto& pInp : possibleConnections.potentialInputs) { + if (checkPotentialConnection(pInp.first, + tagList, + possibleConnections.pubs, + possibleConnections.potentialPubs, + possibleConnections.aliases)) { + pInp.second.used = true; + } + } + /* potential publications*/ + for (auto& pPub : possibleConnections.potentialPubs) { + if (pPub.second.used) { + continue; + } + if (checkPotentialConnection(pPub.first, + tagList, + possibleConnections.inputs, + possibleConnections.potentialInputs, + possibleConnections.aliases)) { + pPub.second.used = true; + } + } + + /* potential endpoints*/ + for (auto& pEnd : possibleConnections.potentialEndpoints) { + if (pEnd.second.used) { + continue; + } + if (checkPotentialConnection(pEnd.first, + tagList, + possibleConnections.endpoints, + possibleConnections.potentialEndpoints, + possibleConnections.aliases)) { + pEnd.second.used = true; + } + } + /** now try to match unconnected interfaces to some of the potential ones*/ + /** unconnected inputs*/ + for (const auto& uInp : possibleConnections.unconnectedInputs) { + if (makePotentialConnection( + uInp, tagList, possibleConnections.potentialPubs, possibleConnections.aliases)) { + continue; + } + if (!possibleConnections.aliases.empty()) { + auto aliasList = generateAliases(uInp, possibleConnections.aliases); + for (const auto& alias : aliasList) { + if (alias == uInp) { + continue; + } + if (makePotentialConnection(alias, + tagList, + possibleConnections.potentialPubs, + possibleConnections.aliases)) { + break; + } + } + } + } + + /** unconnected publications*/ + for (const auto& uPub : possibleConnections.unconnectedPubs) { + if (makePotentialConnection( + uPub, tagList, possibleConnections.potentialInputs, possibleConnections.aliases)) { + continue; + } + if (!possibleConnections.aliases.empty()) { + auto aliasList = generateAliases(uPub, possibleConnections.aliases); + for (const auto& alias : aliasList) { + if (alias == uPub) { + continue; + } + if (makePotentialConnection(alias, + tagList, + possibleConnections.potentialInputs, + possibleConnections.aliases)) { + break; + } + } + } + } + + /** unconnected source endpoints*/ + for (const auto& uEnd : possibleConnections.unconnectedSourceEndpoints) { + if (makePotentialConnection(uEnd, + tagList, + possibleConnections.potentialEndpoints, + possibleConnections.aliases)) { + continue; + } + if (!possibleConnections.aliases.empty()) { + auto aliasList = generateAliases(uEnd, possibleConnections.aliases); + for (const auto& alias : aliasList) { + if (alias == uEnd) { + continue; + } + if (makePotentialConnection(alias, + tagList, + possibleConnections.potentialEndpoints, + possibleConnections.aliases)) { + break; + } + } + } + } + + /** unconnected target endpoints*/ + for (const auto& uEnd : possibleConnections.unconnectedTargetEndpoints) { + if (makePotentialConnection(uEnd, + tagList, + possibleConnections.potentialEndpoints, + possibleConnections.aliases)) { + continue; + } + if (!possibleConnections.aliases.empty()) { + auto aliasList = generateAliases(uEnd, possibleConnections.aliases); + for (const auto& alias : aliasList) { + if (alias == uEnd) { + continue; + } + if (makePotentialConnection(alias, + tagList, + possibleConnections.potentialEndpoints, + possibleConnections.aliases)) { + break; + } + } + } + } + + for (const auto& uInp : possibleConnections.unknownInputs) { + auto fnd = possibleConnections.potentialInputs.find(uInp); + if (fnd != possibleConnections.potentialInputs.end()) { + fnd->second.used = true; + } + auto aliasList = generateAliases(uInp, possibleConnections.aliases); + for (const auto& alias : aliasList) { + if (alias == uInp) { + continue; + } + fnd = possibleConnections.potentialInputs.find(alias); + if (fnd != possibleConnections.potentialInputs.end()) { + fnd->second.used = true; + } + } + } + + for (const auto& uPub : possibleConnections.unknownPubs) { + auto fnd = possibleConnections.potentialPubs.find(uPub); + if (fnd != possibleConnections.potentialPubs.end()) { + fnd->second.used = true; + } + auto aliasList = generateAliases(uPub, possibleConnections.aliases); + for (const auto& alias : aliasList) { + if (alias == uPub) { + continue; + } + fnd = possibleConnections.potentialPubs.find(alias); + if (fnd != possibleConnections.potentialPubs.end()) { + fnd->second.used = true; + } + } + } + + for (const auto& uEpt : possibleConnections.unknownEndpoints) { + auto fnd = possibleConnections.potentialEndpoints.find(uEpt); + if (fnd != possibleConnections.potentialEndpoints.end()) { + fnd->second.used = true; + } + auto aliasList = generateAliases(uEpt, possibleConnections.aliases); + for (const auto& alias : aliasList) { + if (alias == uEpt) { + continue; + } + fnd = possibleConnections.potentialEndpoints.find(alias); + if (fnd != possibleConnections.potentialEndpoints.end()) { + fnd->second.used = true; + } + } + } + int logLevel = fed->getIntegerProperty(HELICS_PROPERTY_INT_LOG_LEVEL); + for (auto& possibleFed : possibleConnections.federatesWithPotentialInterfaces) { + Json::Value establishInterfaces; + establishInterfaces["command"] = "register_interfaces"; + std::vector> + enabledInputs; + std::copy_if(possibleConnections.potentialInputs.begin(), + possibleConnections.potentialInputs.end(), + std::back_inserter(enabledInputs), + [possibleFed](auto& pInterface) { + return (pInterface.second.federate == possibleFed && + pInterface.second.used == true); + }); + if (!enabledInputs.empty()) { + establishInterfaces["inputs"] = Json::arrayValue; + for (const auto& input : enabledInputs) { + establishInterfaces["inputs"].append(std::string(input.first)); + ++interfacesRequested; + if (logLevel >= HELICS_LOG_LEVEL_CONNECTIONS) { + fed->logMessage(HELICS_LOG_LEVEL_CONNECTIONS, + fmt::format("federate {} request input {}", + possibleFed, + input.first)); + } + } + } + std::vector> + enabledPublications; + std::copy_if(possibleConnections.potentialPubs.begin(), + possibleConnections.potentialPubs.end(), + std::back_inserter(enabledPublications), + [possibleFed](auto& pInterface) { + return (pInterface.second.federate == possibleFed && + pInterface.second.used == true); + }); + if (!enabledPublications.empty()) { + establishInterfaces["publications"] = Json::arrayValue; + for (const auto& pub : enabledPublications) { + establishInterfaces["publications"].append(std::string(pub.first)); + ++interfacesRequested; + if (logLevel >= HELICS_LOG_LEVEL_CONNECTIONS) { + fed->logMessage(HELICS_LOG_LEVEL_CONNECTIONS, + fmt::format("federate {} request publication {}", + possibleFed, + pub.first)); + } + } + } + + std::vector< + std::remove_reference_t> + enabledEndpoints; + std::copy_if(possibleConnections.potentialEndpoints.begin(), + possibleConnections.potentialEndpoints.end(), + std::back_inserter(enabledEndpoints), + [possibleFed](auto& pInterface) { + return (pInterface.second.federate == possibleFed && + pInterface.second.used == true); + }); + if (!enabledEndpoints.empty()) { + establishInterfaces["endpoints"] = Json::arrayValue; + for (const auto& ept : enabledEndpoints) { + establishInterfaces["endpoints"].append(std::string(ept.first)); + ++interfacesRequested; + if (logLevel >= HELICS_LOG_LEVEL_CONNECTIONS) { + fed->logMessage(HELICS_LOG_LEVEL_CONNECTIONS, + fmt::format("federate {} request endpoint {}", + possibleFed, + ept.first)); + } + } + } + fed->sendCommand(possibleFed, fileops::generateJsonString(establishInterfaces)); + if (logLevel >= HELICS_LOG_LEVEL_SUMMARY) { + fed->logInfoMessage(fmt::format("{} interfaces requested", interfacesRequested)); + } + } +} + +void Connector::generateRegexMatchers() +{ + for (auto& rmatch : matchers) { + auto rmatcher = std::make_unique(); + std::string rstring{rmatch.interface1.substr(6, std::string_view::npos)}; + auto nvloc = rstring.find("(?<"); + while (nvloc != std::string::npos) { + auto finishloc = rstring.find_first_of('>', nvloc + 2); + rmatcher->keys.push_back(rstring.substr(nvloc + 1, finishloc - nvloc)); + rstring.erase(rstring.begin() + nvloc + 1, rstring.begin() + finishloc + 1); + nvloc = rstring.find("(?<"); + } + rmatcher->interface2 = rmatch.interface2; + rmatcher->tags = rmatch.tags; + try { + rmatcher->rmatch = std::regex(rstring); + regexMatchers.push_back(std::move(rmatcher)); + } + catch (const std::regex_error& e) { + fed->localError(-101, e.what()); + } + } +} + +void Connector::initialize() +{ + auto cmode = fed->getCurrentMode(); + if (cmode == Federate::Modes::STARTUP) { + if (!matchers.empty()) { + generateRegexMatchers(); + } + fed->enterInitializingModeIterative(); + + auto connectionsData = + generateConnectionsList(fed->query("root", "unconnected_interfaces")); + if (connectionsData.hasPotentialInterfaces) { + establishPotentialInterfaces(connectionsData); + fed->enterInitializingModeIterative(); + // need to do this twice to sync enverything + fed->enterInitializingModeIterative(); + connectionsData = generateConnectionsList(fed->query("root", "unconnected_interfaces")); + } + makeConnections(connectionsData); + fed->enterInitializingMode(); + } +} + +void Connector::runTo([[maybe_unused]] Time stopTime_input) +{ + auto cmode = fed->getCurrentMode(); + if (cmode == Federate::Modes::STARTUP) { + initialize(); + } + if (cmode < Federate::Modes::EXECUTING) { + fed->enterExecutingMode(); + } else { + fed->disconnect(); + } +} + +} // namespace helics::apps diff --git a/src/helics/apps/Connector.hpp b/src/helics/apps/Connector.hpp new file mode 100644 index 0000000000..16118bbbf9 --- /dev/null +++ b/src/helics/apps/Connector.hpp @@ -0,0 +1,183 @@ +/* +Copyright (c) 2017-2024, +Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable +Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. +SPDX-License-Identifier: BSD-3-Clause +*/ +#pragma once + +#include "CoreApp.hpp" +#include "helicsApp.hpp" + +#include +#include +#include +#include +#include +#include + +namespace helics::apps { +enum class InterfaceDirection { TO_FROM = -1, BIDIRECTIONAL = 0, FROM_TO = 1 }; + +struct Connection { + std::string_view interface1; + std::string_view interface2; + InterfaceDirection direction; + std::vector tags; + std::shared_ptr stringBuffer; +}; + +struct ConnectionsList; +struct PotentialConnections; +class RegexMatcher; + +/** class implementing a Connector object, which is capable of automatically connecting interfaces +in HELICS +@details the Connector class is not thread-safe, don't try to use it from multiple threads +without external protection, that will result in undefined behavior +*/ +class HELICS_CXX_EXPORT Connector: public App { + public: + /** default constructor*/ + Connector() = default; + /** construct from command line arguments in a vector +@param args the command line arguments to pass in a reverse vector +*/ + explicit Connector(std::vector args); + /** construct from command line arguments +@param argc the number of arguments +@param argv the strings in the input +*/ + Connector(int argc, char* argv[]); + /** construct from a federate info object +@param name the name of the federate (can be empty to use defaults from fedInfo) +@param fedInfo a federate info object containing information on the desired federate configuration +*/ + explicit Connector(std::string_view name, const FederateInfo& fedInfo); + /**constructor taking a federate information structure and using the given core +@param name the name of the federate (can be empty to use defaults from fedInfo) +@param core a pointer to core object which the federate can join +@param fedInfo a federate information structure +*/ + Connector(std::string_view name, + const std::shared_ptr& core, + const FederateInfo& fedInfo); + /**constructor taking a federate information structure and using the given core +@param name the name of the federate (can be empty to use defaults from fedInfo) +@param core a coreApp object that can be joined +@param fedInfo a federate information structure +*/ + Connector(std::string_view name, CoreApp& core, const FederateInfo& fedInfo); + /**constructor taking a file with the required information +@param appName the name of the app +@param configString JSON, TOML or text file or JSON string defining the federate information and +other configuration +*/ + Connector(std::string_view appName, const std::string& configString); + + /** move construction*/ + Connector(Connector&& other_player) = default; + /** move assignment*/ + Connector& operator=(Connector&& fed) = default; + + /** initialize the Player federate +@details generate all the publications and organize the points, the final publication count will +be available after this time and the Player will enter the initialization mode, which means it +will not be possible to add more publications; calling run will automatically do this if +necessary +*/ + virtual void initialize() override; + + /** run the Player until the specified time +@param stopTime_input the desired stop time +*/ + virtual void runTo(Time stopTime_input) override; + + /** add a connection to a connector +@param interface1 the identifier of the first interface +@param interface2 the identifier of the second interface +@param direction the directionality of the interface +@param tags any string tags associated with the connection +*/ + void addConnection(std::string_view interface1, + std::string_view interface2, + InterfaceDirection direction = InterfaceDirection::BIDIRECTIONAL, + const std::vector& tags = {}); + + /** add a tag for later reference, return a string_view reference for the tag*/ + std::size_t addTag(std::string_view tagName); + + /** add an interface name for later reference, return a string_view reference for the interface + * name*/ + std::string_view addInterface(std::string_view interfaceName); + + /** get the number of connections*/ + auto connectionCount() const { return connections.size(); } + /** get the number of made connections*/ + auto madeConnections() const { return matchCount; } + void allowMultipleConnections(bool value = true) { matchMultiple = value; } + void matchEndpointTargets(bool value = true) { matchTargetEndpoints = value; } + + private: + std::unique_ptr generateParser(); + /** process remaining command line arguments*/ + void processArgs(); + + /** run any initial setup operations including file loading*/ + void initialSetup(); + /** load from a jsonString +@param jsonString either a JSON filename or a string containing JSON +*/ + virtual void loadJsonFile(const std::string& jsonString, + bool enableFederateInterfaceRegistration) override; + /** load a text file*/ + virtual void loadTextFile(const std::string& filename) override; + + bool addConnectionVector(const std::vector& connection); + /** go through and make potential connections between interfaces*/ + void establishPotentialInterfaces(ConnectionsList& possibleConnections); + /** actually go through and make connections*/ + void makeConnections(ConnectionsList& possibleConnections); + /** try to make a connection for an input*/ + int makeTargetConnection( + std::string_view origin, + const std::vector& tags, + std::unordered_set& possibleConnections, + const std::unordered_multimap& aliases, + const std::function& callback); + bool makePotentialConnection( + std::string_view interfaceName, + const std::vector& tags, + std::unordered_map& potentials, + const std::unordered_multimap& aliases); + + bool checkPotentialConnection( + std::string_view interface, + const std::vector& tags, + std::unordered_set& possibleConnections, + std::unordered_map& potentials, + const std::unordered_multimap& aliases); + /** get a list of the possible connections to based on the connections map*/ + std::vector buildPossibleConnectionList(std::string_view startingInterface, + const std::vector& tags) const; + /** load the regex matchers */ + void generateRegexMatchers(); + + private: + CoreApp core; + /// the connections descriptors + std::unordered_multimap connections; + std::vector matchers; + std::vector> regexMatchers; + std::unordered_map tags; + std::unordered_set interfaces; + std::uint64_t matchCount{0}; + std::uint64_t interfacesRequested{0}; + /// indicator to match unconnected target endpoints default{false} + bool matchTargetEndpoints{false}; + /// indicator to do multiple matches [default is to stop at first match] + bool matchMultiple{false}; + /// indicator that regex matches should always be checked + bool alwaysCheckRegex{false}; +}; +} // namespace helics::apps diff --git a/src/helics/apps/CoreApp.hpp b/src/helics/apps/CoreApp.hpp index ae8a0b49ac..a9deff8590 100644 --- a/src/helics/apps/CoreApp.hpp +++ b/src/helics/apps/CoreApp.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/apps/Echo.cpp b/src/helics/apps/Echo.cpp index dcbbfb4552..787f20ac70 100644 --- a/src/helics/apps/Echo.cpp +++ b/src/helics/apps/Echo.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -25,11 +25,21 @@ namespace apps { Echo::Echo(std::vector args): App("echo", std::move(args)) { processArgs(); + initialSetup(); } Echo::Echo(int argc, char* argv[]): App("echo", argc, argv) { processArgs(); + initialSetup(); + } + + void Echo::initialSetup() + { + if (!deactivated) { + fed->setFlagOption(HELICS_FLAG_EVENT_TRIGGERED); + loadInputFiles(); + } } void Echo::processArgs() @@ -37,11 +47,7 @@ namespace apps { helicsCLI11App app("Options specific to the Echo App"); app.add_option("--delay", delayTime, "the delay with which the echo app will echo message"); if (!deactivated) { - fed->setFlagOption(HELICS_FLAG_EVENT_TRIGGERED); app.parse(remArgs); - if (!masterFileName.empty()) { - loadFile(masterFileName); - } } else if (helpMode) { app.remove_helics_specifics(); std::cout << app.help(); @@ -50,24 +56,24 @@ namespace apps { Echo::Echo(std::string_view name, const FederateInfo& fi): App(name, fi) { - fed->setFlagOption(HELICS_FLAG_EVENT_TRIGGERED); + initialSetup(); } Echo::Echo(std::string_view name, const std::shared_ptr& core, const FederateInfo& fi): App(name, core, fi) { - fed->setFlagOption(HELICS_FLAG_EVENT_TRIGGERED); + initialSetup(); } Echo::Echo(std::string_view name, CoreApp& core, const FederateInfo& fi): App(name, core, fi) { - fed->setFlagOption(HELICS_FLAG_EVENT_TRIGGERED); + initialSetup(); } Echo::Echo(std::string_view name, const std::string& jsonString): App(name, jsonString) { - fed->setFlagOption(HELICS_FLAG_EVENT_TRIGGERED); - Echo::loadJsonFile(jsonString); + processArgs(); + initialSetup(); } Echo::Echo(Echo&& other_echo) noexcept: @@ -126,9 +132,9 @@ namespace apps { [this](const Endpoint& ept, Time messageTime) { echoMessage(ept, messageTime); }); } - void Echo::loadJsonFile(const std::string& jsonFile) + void Echo::loadJsonFile(const std::string& jsonFile, bool enableFederateInterfaceRegistration) { - loadJsonFileConfiguration("echo", jsonFile); + loadJsonFileConfiguration("echo", jsonFile, enableFederateInterfaceRegistration); auto eptCount = fed->getEndpointCount(); for (int ii = 0; ii < eptCount; ++ii) { endpoints.emplace_back(fed->getEndpoint(ii)); diff --git a/src/helics/apps/Echo.hpp b/src/helics/apps/Echo.hpp index ddc195487c..3fb708cfe3 100644 --- a/src/helics/apps/Echo.hpp +++ b/src/helics/apps/Echo.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -88,11 +88,14 @@ consistent answers if used from multiple threads unless protected. private: /** load information from a JSON file*/ - virtual void loadJsonFile(const std::string& jsonFile) override; + virtual void loadJsonFile(const std::string& jsonFile, + bool enableFederateInterfaceRegistration) override; /** echo an actual message from an endpoint*/ void echoMessage(const Endpoint& ept, Time currentTime); private: + /** run any initial setup operations including file loading*/ + void initialSetup(); /** process remaining command line arguments*/ void processArgs(); std::deque endpoints; //!< the actual endpoint objects diff --git a/src/helics/apps/MultiBroker.cpp b/src/helics/apps/MultiBroker.cpp index cd2de854a4..66664f0401 100644 --- a/src/helics/apps/MultiBroker.cpp +++ b/src/helics/apps/MultiBroker.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/apps/MultiBroker.hpp b/src/helics/apps/MultiBroker.hpp index ecc8a5fc5c..b57b8e128a 100644 --- a/src/helics/apps/MultiBroker.hpp +++ b/src/helics/apps/MultiBroker.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/apps/Player.cpp b/src/helics/apps/Player.cpp index 1887ad7ba1..e467ec2d09 100644 --- a/src/helics/apps/Player.cpp +++ b/src/helics/apps/Player.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -58,11 +58,13 @@ static inline bool mComp(const MessageHolder& m1, const MessageHolder& m2) Player::Player(std::vector args): App("player_${#}", std::move(args)) { processArgs(); + initialSetup(); } Player::Player(int argc, char* argv[]): App("player_${#}", argc, argv) { processArgs(); + initialSetup(); } void Player::processArgs() @@ -70,17 +72,21 @@ void Player::processArgs() auto app = generateParser(); if (!deactivated) { - fed->setFlagOption(HELICS_FLAG_SOURCE_ONLY); app->helics_parse(remArgs); - if (!masterFileName.empty()) { - loadFile(masterFileName); - } } else if (helpMode) { app->remove_helics_specifics(); std::cout << app->help(); } } +void Player::initialSetup() +{ + if (!deactivated) { + fed->setFlagOption(HELICS_FLAG_SOURCE_ONLY); + loadInputFiles(); + } +} + std::unique_ptr Player::generateParser() { auto app = std::make_unique("Command line options for the Player App"); @@ -119,28 +125,30 @@ std::unique_ptr Player::generateParser() return app; } -Player::Player(std::string_view appName, const FederateInfo& fi): App(appName, fi) +Player::Player(std::string_view appName, const FederateInfo& fedInfo): App(appName, fedInfo) { - fed->setFlagOption(HELICS_FLAG_SOURCE_ONLY); + initialSetup(); } -Player::Player(std::string_view appName, const std::shared_ptr& core, const FederateInfo& fi): - App(appName, core, fi) +Player::Player(std::string_view appName, + const std::shared_ptr& core, + const FederateInfo& fedInfo): + App(appName, core, fedInfo) { - fed->setFlagOption(HELICS_FLAG_SOURCE_ONLY); + initialSetup(); } -Player::Player(std::string_view appName, CoreApp& core, const FederateInfo& fi): - App(appName, core, fi) +Player::Player(std::string_view appName, CoreApp& core, const FederateInfo& fedInfo): + App(appName, core, fedInfo) { - fed->setFlagOption(HELICS_FLAG_SOURCE_ONLY); + initialSetup(); } Player::Player(std::string_view appName, const std::string& configString): App(appName, configString) { - fed->setFlagOption(HELICS_FLAG_SOURCE_ONLY); - Player::loadJsonFile(configString); + processArgs(); + initialSetup(); } void Player::addMessage(Time sendTime, @@ -187,94 +195,29 @@ helics::Time Player::extractTime(std::string_view str, int lineNumber) const void Player::loadTextFile(const std::string& filename) { - App::loadTextFile(filename); using namespace gmlc::utilities::stringOps; // NOLINT - std::ifstream infile(filename); - std::string str; - int mcnt = 0; - int pcnt = 0; - bool mlineComment = false; - // count the lines - while (std::getline(infile, str)) { - if (str.empty()) { - continue; - } - auto fc = str.find_first_not_of(" \t\n\r\0"); - if (fc == std::string::npos) { - continue; - } - if (mlineComment) { - if (fc + 2 < str.size()) { - if ((str[fc] == '#') && (str[fc + 1] == '#') && (str[fc + 2] == ']')) { - mlineComment = false; - } - } - continue; - } - if (str[fc] == '#') { - if (fc + 2 < str.size()) { - if ((str[fc + 1] == '#') && (str[fc + 2] == '[')) { - mlineComment = true; - } - } - continue; - } - if ((str[fc] == 'm') || (str[fc] == 'M')) { - ++mcnt; - } else { - ++pcnt; - } - } + AppTextParser aparser(filename); + auto cnts = aparser.preParseFile({'m', 'M'}); + + int mcnt = cnts[1] + cnts[2]; + int pcnt = cnts[0] - mcnt; int pIndex = static_cast(points.size()); points.resize(points.size() + pcnt); int mIndex = static_cast(messages.size()); messages.resize(messages.size() + mcnt); - // now start over and actual do the loading - infile.close(); - infile.open(filename); - - int lcount = 0; - while (std::getline(infile, str)) { - if (str.empty()) { - continue; - } - auto fc = str.find_first_not_of(" \t\n\r\0"); - if (fc == std::string::npos) { - continue; - } - if (mlineComment) { - if (fc + 2 < str.size()) { - if ((str[fc] == '#') && (str[fc + 1] == '#') && (str[fc + 2] == ']')) { - mlineComment = false; - } - } - continue; - } - if (str[fc] == '#') { - if (fc + 2 < str.size()) { - if ((str[fc + 1] == '#') && (str[fc + 2] == '[')) { - mlineComment = true; - } else if (str[fc + 1] == '!') { - /* //allow configuration inside the regular text file - - - + aparser.reset(); - - if (playerConfig.find("time_units") != playerConfig.end()) - { - if (playerConfig["time_units"] == "ns") - { - timeMultiplier = 1e-9; - } - } - */ - } - } - continue; - } + if (!aparser.configString().empty()) { + App::loadConfigOptions(aparser); + auto app = generateParser(); + std::istringstream sstr(aparser.configString()); + app->parse_from_stream(sstr); + } + std::string str; + int lineNumber; + while (aparser.loadNextLine(str, lineNumber)) { /* time key type value units*/ auto blk = splitlineBracket(str, ",\t ", default_bracket_chars, delimiter_compression::on); @@ -283,7 +226,7 @@ void Player::loadTextFile(const std::string& filename) // deal with messages switch (blk.size()) { case 5: - if ((messages[mIndex].sendTime = extractTime(blk[1], lcount)) == + if ((messages[mIndex].sendTime = extractTime(blk[1], lineNumber)) == Time::minVal()) { continue; } @@ -294,21 +237,21 @@ void Player::loadTextFile(const std::string& filename) messages[mIndex].mess.data = decode(std::move(blk[4])); break; case 6: - if ((messages[mIndex].sendTime = extractTime(blk[1], lcount)) == + if ((messages[mIndex].sendTime = extractTime(blk[1], lineNumber)) == Time::minVal()) { continue; } messages[mIndex].mess.source = blk[3]; messages[mIndex].mess.dest = blk[4]; - if ((messages[mIndex].mess.time = extractTime(blk[2], lcount)) == + if ((messages[mIndex].mess.time = extractTime(blk[2], lineNumber)) == Time::minVal()) { continue; } messages[mIndex].mess.data = decode(std::move(blk[5])); break; default: - std::cerr << "unknown message format line " << lcount << '\n'; + std::cerr << "unknown message format line " << lineNumber << '\n'; break; } ++mIndex; @@ -316,13 +259,13 @@ void Player::loadTextFile(const std::string& filename) if (blk.size() == 2) { auto cloc = blk[0].find_last_of(':'); if (cloc == std::string::npos) { - if ((points[pIndex].time = extractTime(trim(blk[0]), lcount)) == + if ((points[pIndex].time = extractTime(trim(blk[0]), lineNumber)) == Time::minVal()) { continue; } } else { - if ((points[pIndex].time = extractTime(trim(blk[0]).substr(0, cloc), lcount)) == - Time::minVal()) { + if ((points[pIndex].time = extractTime(trim(blk[0]).substr(0, cloc), + lineNumber)) == Time::minVal()) { continue; } points[pIndex].iteration = std::stoi(blk[0].substr(cloc + 1)); @@ -332,20 +275,20 @@ void Player::loadTextFile(const std::string& filename) } else { std::cerr << "lines without publication name but follow one with a publication line " - << lcount << '\n'; + << lineNumber << '\n'; } points[pIndex].value = decode(std::move(blk[1])); ++pIndex; } else if (blk.size() == 3) { auto cloc = blk[0].find_last_of(':'); if (cloc == std::string::npos) { - if ((points[pIndex].time = extractTime(trim(blk[0]), lcount)) == + if ((points[pIndex].time = extractTime(trim(blk[0]), lineNumber)) == Time::minVal()) { continue; } } else { - if ((points[pIndex].time = extractTime(trim(blk[0]).substr(0, cloc), lcount)) == - Time::minVal()) { + if ((points[pIndex].time = extractTime(trim(blk[0]).substr(0, cloc), + lineNumber)) == Time::minVal()) { continue; } points[pIndex].iteration = std::stoi(blk[0].substr(cloc + 1)); @@ -361,13 +304,13 @@ void Player::loadTextFile(const std::string& filename) } else if (blk.size() == 4) { auto cloc = blk[0].find_last_of(':'); if (cloc == std::string::npos) { - if ((points[pIndex].time = extractTime(trim(blk[0]), lcount)) == + if ((points[pIndex].time = extractTime(trim(blk[0]), lineNumber)) == Time::minVal()) { continue; } } else { - if ((points[pIndex].time = extractTime(trim(blk[0]).substr(0, cloc), lcount)) == - Time::minVal()) { + if ((points[pIndex].time = extractTime(trim(blk[0]).substr(0, cloc), + lineNumber)) == Time::minVal()) { continue; } points[pIndex].iteration = std::stoi(blk[0].substr(cloc + 1)); @@ -381,15 +324,15 @@ void Player::loadTextFile(const std::string& filename) points[pIndex].value = decode(std::move(blk[3])); ++pIndex; } else { - std::cerr << "unknown publish format line " << lcount << '\n'; + std::cerr << "unknown publish format line " << lineNumber << '\n'; } } } } -void Player::loadJsonFile(const std::string& jsonString) +void Player::loadJsonFile(const std::string& jsonString, bool enableFederateInterfaceRegistration) { - loadJsonFileConfiguration("player", jsonString); + loadJsonFileConfiguration("player", jsonString, enableFederateInterfaceRegistration); auto pubCount = fed->getPublicationCount(); for (int ii = 0; ii < pubCount; ++ii) { @@ -405,14 +348,14 @@ void Player::loadJsonFile(const std::string& jsonString) auto doc = fileops::loadJson(jsonString); if (doc.isMember("player")) { - auto playerConfig = doc["player"]; + auto& playerConfig = doc["player"]; if (playerConfig.isMember("time_units")) { if (playerConfig["time_units"].asString() == "ns") { timeMultiplier = 1e-9; } } } - auto pointArray = doc["points"]; + auto& pointArray = doc["points"]; if (pointArray.isArray()) { points.reserve(points.size() + pointArray.size()); for (const auto& pointElement : pointArray) { @@ -452,7 +395,7 @@ void Player::loadJsonFile(const std::string& jsonString) } defV val; if (pointElement.isMember("value")) { - auto M = pointElement["value"]; + auto& M = pointElement["value"]; if (M.isInt64()) { val = M.asInt64(); } else if (M.isDouble()) { @@ -461,7 +404,7 @@ void Player::loadJsonFile(const std::string& jsonString) val = M.asString(); } } else if (pointElement.isMember("v")) { - auto M = pointElement["v"]; + auto& M = pointElement["v"]; if (M.isInt64()) { val = M.asInt64(); } else if (M.isDouble()) { @@ -495,7 +438,7 @@ void Player::loadJsonFile(const std::string& jsonString) } } - auto messageArray = doc["messages"]; + auto& messageArray = doc["messages"]; if (messageArray.isArray()) { messages.reserve(messages.size() + messageArray.size()); for (const auto& messageElement : messageArray) { @@ -708,13 +651,14 @@ void Player::runTo(Time stopTime_input) nextSendTime = std::min(nextSendTime, messages[messageIndex].sendTime); nextIteration = 0; } - if (nextSendTime > stopTime_input) { - break; - } if (nextSendTime == Time::maxVal()) { moreToSend = false; continue; } + if (nextSendTime > stopTime_input) { + break; + } + if ((nextIteration == 0) || (nextSendTime > fed->getCurrentTime())) { auto newTime = fed->requestTime(nextSendTime); currentIteration = 0; @@ -730,6 +674,9 @@ void Player::runTo(Time stopTime_input) sendInformation(nextSendTime, currentIteration); } } + while (fed->getCurrentTime() < stopTime_input) { + fed->requestTime(stopTime_input); + } } void Player::addPublication(std::string_view name, DataType type, std::string_view pubUnits) @@ -751,7 +698,16 @@ void Player::addPublication(std::string_view name, DataType type, std::string_vi helics::InterfaceVisibility::GLOBAL, fed.get(), name, type, pubUnits); } } - pubids[publications.back().getName()] = static_cast(publications.size()) - 1; + std::string_view keyname = publications.back().getName(); + auto index = static_cast(publications.size()) - 1; + pubids[keyname] = index; + if (useLocal) { + auto& fedName = fed->getName(); + if (keyname.compare(0, fedName.size(), fedName) == 0) { + auto localName = keyname.substr(fedName.size() + 1); + pubids[localName] = index; + } + } } void Player::addEndpoint(std::string_view endpointName, std::string_view endpointType) diff --git a/src/helics/apps/Player.hpp b/src/helics/apps/Player.hpp index 9b6189e3cd..66119cf348 100644 --- a/src/helics/apps/Player.hpp +++ b/src/helics/apps/Player.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -12,10 +12,10 @@ SPDX-License-Identifier: BSD-3-Clause #include "helicsApp.hpp" #include -#include #include #include #include +#include #include namespace helics { @@ -198,10 +198,14 @@ external protection, that will result in undefined behavior std::unique_ptr generateParser(); /** process remaining command line arguments*/ void processArgs(); + + /** run any initial setup operations including file loading*/ + void initialSetup(); /** load from a jsonString @param jsonString either a JSON filename or a string containing JSON */ - virtual void loadJsonFile(const std::string& jsonString) override; + virtual void loadJsonFile(const std::string& jsonString, + bool enableFederateInterfaceRegistration) override; /** load a text file*/ virtual void loadTextFile(const std::string& filename) override; /** helper function to sort through the tags*/ @@ -225,12 +229,12 @@ external protection, that will result in undefined behavior private: std::vector points; //!< the points to generate into the federation std::vector messages; //!< list of message to hold - std::map tags; //!< map of the key and type strings + std::unordered_map tags; //!< map of the key and type strings std::set epts; //!< set of the used endpoints std::deque publications; //!< the actual publication objects std::deque endpoints; //!< the actual endpoint objects - std::map pubids; //!< publication id map - std::map eptids; //!< endpoint id maps + std::unordered_map pubids; //!< publication id map + std::unordered_map eptids; //!< endpoint id maps helics::DataType defType = helics::DataType::HELICS_STRING; //!< the default data type unless otherwise specified size_t pointIndex = 0; //!< the current point index diff --git a/src/helics/apps/PrecHelper.cpp b/src/helics/apps/PrecHelper.cpp index 6302fda380..2d85f3fc56 100644 --- a/src/helics/apps/PrecHelper.cpp +++ b/src/helics/apps/PrecHelper.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/apps/PrecHelper.hpp b/src/helics/apps/PrecHelper.hpp index d74f181594..0158d3940f 100644 --- a/src/helics/apps/PrecHelper.hpp +++ b/src/helics/apps/PrecHelper.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/apps/Probe.cpp b/src/helics/apps/Probe.cpp index a643d8ab77..0f4b044e4c 100644 --- a/src/helics/apps/Probe.cpp +++ b/src/helics/apps/Probe.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -22,15 +22,17 @@ Probe::Probe(int argc, char* argv[]): App("probe_${#}", argc, argv) {} Probe::Probe(std::vector args): App("probe_${#}", std::move(args)) {} -Probe::Probe(std::string_view appName, const FederateInfo& fi): App(appName, fi) {} +Probe::Probe(std::string_view appName, const FederateInfo& fedInfo): App(appName, fedInfo) {} -Probe::Probe(std::string_view appName, const std::shared_ptr& core, const FederateInfo& fi): - App(appName, core, fi) +Probe::Probe(std::string_view appName, + const std::shared_ptr& core, + const FederateInfo& fedInfo): + App(appName, core, fedInfo) { } -Probe::Probe(std::string_view appName, CoreApp& core, const FederateInfo& fi): - App(appName, core, fi) +Probe::Probe(std::string_view appName, CoreApp& core, const FederateInfo& fedInfo): + App(appName, core, fedInfo) { } @@ -38,14 +40,14 @@ Probe::Probe(std::string_view name, const std::string& configString): App(name, void Probe::initialize() { - auto md = fed->getCurrentMode(); - if (md != Federate::Modes::STARTUP) { + auto currentMode = fed->getCurrentMode(); + if (currentMode != Federate::Modes::STARTUP) { return; } auto period = fed->getTimeProperty(HELICS_PROPERTY_TIME_PERIOD); if (period <= Time::epsilon()) { - auto td = fed->getTimeProperty(HELICS_PROPERTY_TIME_DELTA); - if (td <= Time::epsilon()) { + auto delta = fed->getTimeProperty(HELICS_PROPERTY_TIME_DELTA); + if (delta <= Time::epsilon()) { fed->setProperty(HELICS_PROPERTY_TIME_PERIOD, 1.0); } } @@ -77,12 +79,12 @@ void Probe::initialize() void Probe::runTo(Time stopTime_input) { - auto md = fed->getCurrentMode(); - if (md == Federate::Modes::STARTUP) { + auto currentMode = fed->getCurrentMode(); + if (currentMode == Federate::Modes::STARTUP) { initialize(); } - if (md < Federate::Modes::EXECUTING) { + if (currentMode < Federate::Modes::EXECUTING) { fed->enterExecutingMode(); } @@ -98,12 +100,15 @@ void Probe::runProbe() { auto ctime = fed->getCurrentTime(); while (endpoint.hasMessage()) { - auto m = endpoint.getMessage(); - fed->logInfoMessage( - fmt::format("Message from {} at Time {}: [{}]", m->source, ctime, m->to_string())); + auto message = endpoint.getMessage(); + fed->logInfoMessage(fmt::format("Message from {} at Time {}: [{}]", + message->source, + static_cast(ctime), + message->to_string())); ++messagesReceived; } - endpoint.send(fmt::format("message from {},time {}", fed->getName(), ctime)); + endpoint.send( + fmt::format("message from {},time {}", fed->getName(), static_cast(ctime))); } } // namespace helics::apps diff --git a/src/helics/apps/Probe.hpp b/src/helics/apps/Probe.hpp index 269169b8b4..00c72c6b22 100644 --- a/src/helics/apps/Probe.hpp +++ b/src/helics/apps/Probe.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -37,25 +37,25 @@ class HELICS_CXX_EXPORT Probe: public App { */ Probe(int argc, char* argv[]); /** construct from a federate info object -@param name the name of the source object (can be empty to use defaults from fi) -@param fi a pointer info object containing information on the desired federate configuration +@param name the name of the source object (can be empty to use defaults from fedInfo) +@param fedInfo a pointer info object containing information on the desired federate configuration */ - Probe(std::string_view name, const FederateInfo& fi); + Probe(std::string_view name, const FederateInfo& fedInfo); /**constructor taking a federate information structure and using the given core -@param name the name of the source object (can be empty to use defaults from fi) +@param name the name of the source object (can be empty to use defaults from fedInfo) @param core a pointer to core object which the federate can join -@param fi a federate information structure +@param fedInfo a federate information structure */ - Probe(std::string_view name, const std::shared_ptr& core, const FederateInfo& fi); + Probe(std::string_view name, const std::shared_ptr& core, const FederateInfo& fedInfo); /**constructor taking a federate information structure and using the given core -@param name the name of the federate (can be empty to use defaults from fi) +@param name the name of the federate (can be empty to use defaults from fedInfo) @param core a coreApp object that can be joined -@param fi a federate information structure +@param fedInfo a federate information structure */ - Probe(std::string_view name, CoreApp& core, const FederateInfo& fi); + Probe(std::string_view name, CoreApp& core, const FederateInfo& fedInfo); /**constructor taking a file with the required information -@param name the name of the source object (can be empty to use defaults from fi) +@param name the name of the source object (can be empty to use defaults from fedInfo) @param configString file a JSON or TOML file or string containing configuration informatino */ Probe(std::string_view name, const std::string& configString); diff --git a/src/helics/apps/Recorder.cpp b/src/helics/apps/Recorder.cpp index 319589498a..774da2f466 100644 --- a/src/helics/apps/Recorder.cpp +++ b/src/helics/apps/Recorder.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -10,14 +10,14 @@ SPDX-License-Identifier: BSD-3-Clause #include "../application_api/Filters.hpp" #include "../application_api/queryFunctions.hpp" #include "../common/JsonProcessingFunctions.hpp" -#include "../common/fmt_format.h" -#include "../common/fmt_ostream.h" #include "../core/helicsCLI11.hpp" #include "PrecHelper.hpp" #include "gmlc/utilities/base64.h" #include "gmlc/utilities/stringOps.h" #include +#include +#include #include #include #include @@ -40,30 +40,28 @@ static std::string encode(std::string_view str2encode) } namespace helics::apps { -Recorder::Recorder(std::string_view appName, FederateInfo& fi): App(appName, fi) +Recorder::Recorder(std::string_view appName, FederateInfo& fedInfo): App(appName, fedInfo) { - fed->setFlagOption(HELICS_FLAG_OBSERVER); + initialSetup(); } Recorder::Recorder(std::vector args): App("recorder", std::move(args)) { processArgs(); + initialSetup(); } Recorder::Recorder(int argc, char* argv[]): App("recorder", argc, argv) { processArgs(); + initialSetup(); } void Recorder::processArgs() { auto app = buildArgParserApp(); if (!deactivated) { - fed->setFlagOption(HELICS_FLAG_OBSERVER); app->parse(remArgs); - if (!masterFileName.empty()) { - loadFile(masterFileName); - } } else if (helpMode) { app->remove_helics_specifics(); std::cout << app->help(); @@ -72,23 +70,23 @@ void Recorder::processArgs() Recorder::Recorder(std::string_view appName, const std::shared_ptr& core, - const FederateInfo& fi): - App(appName, core, fi) + const FederateInfo& fedInfo): + App(appName, core, fedInfo) { - fed->setFlagOption(HELICS_FLAG_OBSERVER); + initialSetup(); } -Recorder::Recorder(std::string_view appName, CoreApp& core, const FederateInfo& fi): - App(appName, core, fi) +Recorder::Recorder(std::string_view appName, CoreApp& core, const FederateInfo& fedInfo): + App(appName, core, fedInfo) { - fed->setFlagOption(HELICS_FLAG_OBSERVER); + initialSetup(); } Recorder::Recorder(std::string_view appName, const std::string& jsonString): App(appName, jsonString) { - fed->setFlagOption(HELICS_FLAG_OBSERVER); - Recorder::loadJsonFile(jsonString); + processArgs(); + initialSetup(); } Recorder::~Recorder() @@ -100,9 +98,17 @@ Recorder::~Recorder() } } -void Recorder::loadJsonFile(const std::string& jsonString) +void Recorder::initialSetup() +{ + if (!deactivated) { + fed->setFlagOption(HELICS_FLAG_OBSERVER); + loadInputFiles(); + } +} + +void Recorder::loadJsonFile(const std::string& jsonString, bool enableFederateInterfaceRegistration) { - loadJsonFileConfiguration("recorder", jsonString); + loadJsonFileConfiguration("recorder", jsonString, enableFederateInterfaceRegistration); auto subCount = fed->getInputCount(); for (int ii = 0; ii < subCount; ++ii) { @@ -132,16 +138,16 @@ void Recorder::loadJsonFile(const std::string& jsonString) } auto sourceClone = doc["sourceclone"]; if (sourceClone.isArray()) { - for (const auto& sc : sourceClone) { - addSourceEndpointClone(sc.asString()); + for (const auto& clone : sourceClone) { + addSourceEndpointClone(clone.asString()); } } else if (sourceClone.isString()) { addSourceEndpointClone(sourceClone.asString()); } auto destClone = doc["destclone"]; if (destClone.isArray()) { - for (const auto& dc : destClone) { - addDestEndpointClone(dc.asString()); + for (const auto& clone : destClone) { + addDestEndpointClone(clone.asString()); } } else if (destClone.isString()) { addDestEndpointClone(destClone.asString()); @@ -172,14 +178,14 @@ void Recorder::loadTextFile(const std::string& textFile) std::ifstream infile(textFile); std::string str; - int lc = 0; + int lineCount = 0; while (std::getline(infile, str)) { - ++lc; + ++lineCount; if (str.empty()) { continue; } - auto fc = str.find_first_not_of(" \t\n\r\0"); - if ((fc == std::string::npos) || (str[fc] == '#')) { + auto firstChar = str.find_first_not_of(" \t\n\r\0"); + if ((firstChar == std::string::npos) || (str[firstChar] == '#')) { continue; } auto blk = splitlineQuotes(str, ",\t ", default_quote_chars, delimiter_compression::on); @@ -205,7 +211,7 @@ void Recorder::loadTextFile(const std::string& textFile) addSourceEndpointClone(removeQuotes(blk[1])); addDestEndpointClone(removeQuotes(blk[1])); } else { - std::cerr << "Unable to process line " << lc << ':' << str << '\n'; + std::cerr << "Unable to process line " << lineCount << ':' << str << '\n'; } break; case 3: @@ -215,10 +221,10 @@ void Recorder::loadTextFile(const std::string& textFile) } else if ((blk[1] == "dest") || (blk[1] == "destination")) { addDestEndpointClone(removeQuotes(blk[2])); } else { - std::cerr << "Unable to process line " << lc << ':' << str << '\n'; + std::cerr << "Unable to process line " << lineCount << ':' << str << '\n'; } } else { - std::cerr << "Unable to process line " << lc << ':' << str << '\n'; + std::cerr << "Unable to process line " << lineCount << ':' << str << '\n'; } break; default: @@ -233,18 +239,18 @@ void Recorder::writeJsonFile(const std::string& filename) Json::Value doc; if (!points.empty()) { doc["points"] = Json::Value(Json::arrayValue); - for (auto& v : points) { - Json::Value point; - point["key"] = subscriptions[v.index].getTarget(); - point["value"] = v.value; - point["time"] = static_cast(v.time); - if (v.iteration > 0) { - point["iteration"] = v.iteration; + for (auto& point : points) { + Json::Value pointData; + pointData["key"] = subscriptions[point.index].getTarget(); + pointData["value"] = point.value; + pointData["time"] = static_cast(point.time); + if (point.iteration > 0) { + pointData["iteration"] = point.iteration; } - if (v.first) { - point["type"] = subscriptions[v.index].getPublicationType(); + if (point.first) { + pointData["type"] = subscriptions[point.index].getPublicationType(); } - doc["points"].append(point); + doc["points"].append(pointData); } } @@ -279,8 +285,8 @@ void Recorder::writeJsonFile(const std::string& filename) } } - std::ofstream o(filename); - o << doc << std::endl; + std::ofstream out(filename); + out << doc << std::endl; } void Recorder::writeTextFile(const std::string& filename) @@ -289,44 +295,46 @@ void Recorder::writeTextFile(const std::string& filename) if (!points.empty()) { outFile << "#time \ttag\t type*\t value\n"; } - for (auto& v : points) { - if (v.first) { - outFile << static_cast(v.time) << "\t\t" << subscriptions[v.index].getTarget() - << '\t' << subscriptions[v.index].getPublicationType() << '\t' - << Json::valueToQuotedString(v.value.c_str()) << '\n'; + for (auto& point : points) { + if (point.first) { + outFile << static_cast(point.time) << "\t\t" + << subscriptions[point.index].getTarget() << '\t' + << subscriptions[point.index].getPublicationType() << '\t' + << Json::valueToQuotedString(point.value.c_str()) << '\n'; } else { - if (v.iteration > 0) { - outFile << static_cast(v.time) << ':' << v.iteration << "\t\t" - << subscriptions[v.index].getTarget() << '\t' - << Json::valueToQuotedString(v.value.c_str()) << '\n'; + if (point.iteration > 0) { + outFile << static_cast(point.time) << ':' << point.iteration << "\t\t" + << subscriptions[point.index].getTarget() << '\t' + << Json::valueToQuotedString(point.value.c_str()) << '\n'; } else { - outFile << static_cast(v.time) << "\t\t" - << subscriptions[v.index].getTarget() << '\t' - << Json::valueToQuotedString(v.value.c_str()) << '\n'; + outFile << static_cast(point.time) << "\t\t" + << subscriptions[point.index].getTarget() << '\t' + << Json::valueToQuotedString(point.value.c_str()) << '\n'; } } } if (!messages.empty()) { outFile << "# m\t time \tsource\t dest\t message\n"; } - for (auto& m : messages) { - outFile << "m\t" << static_cast(m->time) << '\t' << m->source << '\t'; - if ((m->dest.size() < 7) || (m->dest.compare(m->dest.size() - 6, 6, "cloneE") != 0)) { - outFile << m->dest; + for (auto& mess : messages) { + outFile << "m\t" << static_cast(mess->time) << '\t' << mess->source << '\t'; + if ((mess->dest.size() < 7) || + (mess->dest.compare(mess->dest.size() - 6, 6, "cloneE") != 0)) { + outFile << mess->dest; } else { - outFile << m->original_dest; + outFile << mess->original_dest; } - if (isBinaryData(m->data)) { - if (isEscapableData(m->data)) { + if (isBinaryData(mess->data)) { + if (isEscapableData(mess->data)) { outFile << "\t" - << Json::valueToQuotedString(std::string(m->data.to_string()).c_str()) + << Json::valueToQuotedString(std::string(mess->data.to_string()).c_str()) << "\n"; } else { - outFile << "\t\"" << encode(m->data.to_string()) << "\"\n"; + outFile << "\t\"" << encode(mess->data.to_string()) << "\"\n"; } } else { - outFile << "\t\"" << m->data.to_string() << "\"\n"; + outFile << "\t\"" << mess->data.to_string() << "\"\n"; } } } @@ -379,8 +387,8 @@ void Recorder::captureForCurrentTime(Time currentTime, int iteration) for (auto& sub : subscriptions) { if (sub.isUpdated()) { auto val = sub.getValue(); - int ii = subids[sub.getHandle()]; - points.emplace_back(currentTime, ii, val); + const int subId = subids[sub.getHandle()]; + points.emplace_back(currentTime, subId, val); if (iteration > 0) { points.back().iteration = iteration; } @@ -388,33 +396,39 @@ void Recorder::captureForCurrentTime(Time currentTime, int iteration) std::string valstr; if (val.size() < 150) { if (iteration > 0) { - valstr = fmt::format( - "[{}:{}]value {}={}", currentTime, iteration, sub.getTarget(), val); + valstr = fmt::format("[{}:{}]value {}={}", + static_cast(currentTime), + iteration, + sub.getTarget(), + val); } else { - valstr = fmt::format("[{}]value {}={}", currentTime, sub.getTarget(), val); + valstr = fmt::format("[{}]value {}={}", + static_cast(currentTime), + sub.getTarget(), + val); } } else { if (iteration > 0) { valstr = fmt::format("[{}:{}]value {}=block[{}]", - currentTime, + static_cast(currentTime), iteration, sub.getTarget(), val.size()); } else { valstr = fmt::format("[{}]value {}=block[{}]", - currentTime, + static_cast(currentTime), sub.getTarget(), val.size()); } } spdlog::info(valstr); } - if (vStat[ii].cnt == 0) { + if (vStat[subId].cnt == 0) { points.back().first = true; } - ++vStat[ii].cnt; - vStat[ii].lastVal = val; - vStat[ii].time = -1.0; + ++vStat[subId].cnt; + vStat[subId].lastVal = val; + vStat[subId].time = -1.0; } } @@ -425,13 +439,13 @@ void Recorder::captureForCurrentTime(Time currentTime, int iteration) std::string messstr; if (mess->data.size() < 50) { messstr = fmt::format("[{}]message from {} to {}::{}", - currentTime, + static_cast(currentTime), mess->source, mess->dest, mess->data.to_string()); } else { messstr = fmt::format("[{}]message from {} to {}:: size {}", - currentTime, + static_cast(currentTime), mess->source, mess->dest, mess->data.size()); @@ -475,19 +489,19 @@ void Recorder::runTo(Time runToTime) try { int iteration = 0; while (true) { - helics::Time T; + helics::Time grantedTime; if (allow_iteration) { auto ItRes = fed->requestTimeIterative(runToTime, IterationRequest::ITERATE_IF_NEEDED); if (ItRes.state == IterationResult::NEXT_STEP) { iteration = 0; } - T = ItRes.grantedTime; - captureForCurrentTime(T, iteration); + grantedTime = ItRes.grantedTime; + captureForCurrentTime(grantedTime, iteration); ++iteration; } else { - T = fed->requestTime(runToTime); - captureForCurrentTime(T); + grantedTime = fed->requestTime(runToTime); + captureForCurrentTime(grantedTime); } if (!mapfile.empty()) { std::ofstream out(mapfile); @@ -501,11 +515,11 @@ void Recorder::runTo(Time runToTime) } out.flush(); } - if (T >= runToTime) { + if (grantedTime >= runToTime) { break; } - if ((T >= nextPrintTime) && (nextPrintTimeStep > timeZero)) { - std::cout << "processed for time " << static_cast(T) << "\n"; + if ((grantedTime >= nextPrintTime) && (nextPrintTimeStep > timeZero)) { + std::cout << "processed for time " << static_cast(grantedTime) << "\n"; nextPrintTime += nextPrintTimeStep; } } @@ -521,8 +535,8 @@ void Recorder::addSubscription(std::string_view key) subscriptions.emplace_back(fed->registerSubscription(key)); targets.emplace_back(key); auto index = static_cast(subscriptions.size()) - 1; - auto id = subscriptions.back().getHandle(); - subids[id] = index; // this is a new element + auto subId = subscriptions.back().getHandle(); + subids[subId] = index; // this is a new element subkeys[subscriptions.back().getTarget()] = index; // this is a potential replacement } } @@ -533,8 +547,8 @@ void Recorder::addEndpoint(std::string_view endpoint) if ((res == eptNames.end()) || (res->second == -1)) { endpoints.emplace_back(InterfaceVisibility::GLOBAL, fed.get(), endpoint); auto index = static_cast(endpoints.size()) - 1; - auto id = endpoints.back().getHandle(); - eptids.emplace(id, index); // this is a new element + auto endpointId = endpoints.back().getHandle(); + eptids.emplace(endpointId, index); // this is a new element eptNames[endpoints.back().getName()] = index; // this is a potential replacement } } diff --git a/src/helics/apps/Recorder.hpp b/src/helics/apps/Recorder.hpp index 40beb37b04..a3f7aba447 100644 --- a/src/helics/apps/Recorder.hpp +++ b/src/helics/apps/Recorder.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -29,9 +29,9 @@ namespace apps { /** construct from a FederateInfo structure @param name the name of the Recorder, can be left empty for the default or to pull from the federateInfo object - @param fi a federate information structure + @param fedInfo a federate information structure */ - Recorder(std::string_view name, FederateInfo& fi); + Recorder(std::string_view name, FederateInfo& fedInfo); /** construct from command line arguments in a vector @param args the command line arguments to pass in a reverse vector */ @@ -43,15 +43,17 @@ namespace apps { @param name the name of the Recorder, can be left empty for the default or to pull from the federateInfo object @param core a pointer to core object which the federate can join - @param fi a federate information structure + @param fedInfo a federate information structure */ - Recorder(std::string_view name, const std::shared_ptr& core, const FederateInfo& fi); + Recorder(std::string_view name, + const std::shared_ptr& core, + const FederateInfo& fedInfo); /**constructor taking a federate information structure and using the given core - @param name the name of the federate (can be empty to use defaults from fi) + @param name the name of the federate (can be empty to use defaults from fedInfo) @param core a coreApp object that can be joined - @param fi a federate information structure + @param fedInfo a federate information structure */ - Recorder(std::string_view name, CoreApp& core, const FederateInfo& fi); + Recorder(std::string_view name, CoreApp& core, const FederateInfo& fedInfo); /**constructor taking a file with the required information @param name the name of the app @param jsonString a file or JSON string defining the federate information in JSON @@ -96,10 +98,13 @@ namespace apps { std::unique_ptr getMessage(std::size_t index) const; private: + /** run any initial setup operations including file loading*/ + void initialSetup(); /** load from a jsonString @param jsonString either a JSON filename or a string containing JSON */ - virtual void loadJsonFile(const std::string& jsonString) override; + virtual void loadJsonFile(const std::string& jsonString, + bool enableFederateInterfaceRegistration) override; /** load a text file*/ virtual void loadTextFile(const std::string& textFile) override; /** helper function to write the date to a JSON file*/ diff --git a/src/helics/apps/RestApiConnection.cpp b/src/helics/apps/RestApiConnection.cpp index 4c0b3750c6..09d2e25db1 100644 --- a/src/helics/apps/RestApiConnection.cpp +++ b/src/helics/apps/RestApiConnection.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/apps/RestApiConnection.hpp b/src/helics/apps/RestApiConnection.hpp index 7d7a6aba04..2b2885f932 100644 --- a/src/helics/apps/RestApiConnection.hpp +++ b/src/helics/apps/RestApiConnection.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/apps/SignalGenerators.cpp b/src/helics/apps/SignalGenerators.cpp index 9d2610b957..a74882fdbb 100644 --- a/src/helics/apps/SignalGenerators.cpp +++ b/src/helics/apps/SignalGenerators.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/apps/SignalGenerators.hpp b/src/helics/apps/SignalGenerators.hpp index 2543e3297b..0f6d023ba9 100644 --- a/src/helics/apps/SignalGenerators.hpp +++ b/src/helics/apps/SignalGenerators.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/apps/Source.cpp b/src/helics/apps/Source.cpp index 5192bb4c58..f6329a1eff 100644 --- a/src/helics/apps/Source.cpp +++ b/src/helics/apps/Source.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -31,14 +31,16 @@ namespace apps { /** set a string parameter*/ void SignalGenerator::setString(std::string_view /*parameter*/, std::string_view /*val*/) {} - Source::Source(int argc, char* argv[]): App("source", argc, argv) + Source::Source(int argc, char* argv[]): App("source_${#}", argc, argv) { processArgs(); + initialSetup(); } - Source::Source(std::vector args): App("source", std::move(args)) + Source::Source(std::vector args): App("source_${#}", std::move(args)) { processArgs(); + initialSetup(); } void Source::processArgs() @@ -46,11 +48,7 @@ namespace apps { helicsCLI11App app("Options specific to the Source App"); app.add_option("--default_period", defaultPeriod, "the default period publications"); if (!deactivated) { - fed->setFlagOption(HELICS_FLAG_SOURCE_ONLY); app.parse(remArgs); - if (!masterFileName.empty()) { - loadFile(masterFileName); - } } else if (helpMode) { app.remove_helics_specifics(); std::cout << app.help(); @@ -58,7 +56,7 @@ namespace apps { } Source::Source(std::string_view appName, const FederateInfo& fi): App(appName, fi) { - fed->setFlagOption(HELICS_FLAG_SOURCE_ONLY); + initialSetup(); } Source::Source(std::string_view appName, @@ -66,20 +64,27 @@ namespace apps { const FederateInfo& fi): App(appName, core, fi) { - fed->setFlagOption(HELICS_FLAG_SOURCE_ONLY); + initialSetup(); } Source::Source(std::string_view appName, CoreApp& core, const FederateInfo& fi): App(appName, core, fi) { - fed->setFlagOption(HELICS_FLAG_SOURCE_ONLY); + initialSetup(); } Source::Source(std::string_view name, const std::string& configString): App(name, configString) { - fed->setFlagOption(HELICS_FLAG_SOURCE_ONLY); + processArgs(); + initialSetup(); + } - Source::loadJsonFile(configString); + void Source::initialSetup() + { + if (!deactivated) { + fed->setFlagOption(HELICS_FLAG_SOURCE_ONLY); + loadInputFiles(); + } } static void @@ -102,7 +107,8 @@ namespace apps { } } - void Source::loadJsonFile(const std::string& jsonString) + void Source::loadJsonFile(const std::string& jsonString, + bool enableFederateInterfaceRegistration) { // we want to load the default period before constructing the interfaces so the default // period works @@ -115,7 +121,7 @@ namespace apps { } } - loadJsonFileConfiguration("source", jsonString); + loadJsonFileConfiguration("source", jsonString, enableFederateInterfaceRegistration); auto pubCount = fed->getPublicationCount(); for (int ii = 0; ii < pubCount; ++ii) { sources.emplace_back(fed->getPublication(ii), defaultPeriod); diff --git a/src/helics/apps/Source.hpp b/src/helics/apps/Source.hpp index c53165b78b..bfd09375d5 100644 --- a/src/helics/apps/Source.hpp +++ b/src/helics/apps/Source.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -156,12 +156,15 @@ external protection, that will result in undefined behavior std::shared_ptr getGenerator(int index); private: + /** run any initial setup operations including file loading*/ + void initialSetup(); /** process remaining command line arguments*/ void processArgs(); /** load from a jsonString @param jsonString either a JSON filename or a string containing JSON */ - virtual void loadJsonFile(const std::string& jsonString) override; + virtual void loadJsonFile(const std::string& jsonString, + bool enableFederateInterfaceRegistration) override; /** execute a source object and update its time return the next execution time*/ Time runSource(SourceObject& obj, Time currentTime); /** execute all the sources*/ diff --git a/src/helics/apps/Tracer.cpp b/src/helics/apps/Tracer.cpp index 7fe2a5c3d8..c6bb579108 100644 --- a/src/helics/apps/Tracer.cpp +++ b/src/helics/apps/Tracer.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -12,13 +12,13 @@ SPDX-License-Identifier: BSD-3-Clause #include "../application_api/ValueFederate.hpp" #include "../application_api/queryFunctions.hpp" #include "../common/JsonProcessingFunctions.hpp" -#include "../common/fmt_format.h" #include "../core/helicsCLI11.hpp" #include "../core/helicsVersion.hpp" #include "PrecHelper.hpp" #include "gmlc/utilities/stringOps.h" #include +#include #include #include #include @@ -30,496 +30,504 @@ SPDX-License-Identifier: BSD-3-Clause #include #include -namespace helics { -namespace apps { - Tracer::Tracer(std::string_view appName, FederateInfo& fi): App(appName, fi) - { - fed->setFlagOption(HELICS_FLAG_OBSERVER); - } - - Tracer::Tracer(std::vector args): App("tracer", std::move(args)) - { - processArgs(); +namespace helics::apps { +Tracer::Tracer(std::string_view appName, FederateInfo& fedInfo): App(appName, fedInfo) +{ + fed->setFlagOption(HELICS_FLAG_OBSERVER); +} + +Tracer::Tracer(std::vector args): App("tracer", std::move(args)) +{ + processArgs(); + initialSetup(); +} + +Tracer::Tracer(int argc, char* argv[]): App("tracer", argc, argv) +{ + processArgs(); + initialSetup(); +} + +void Tracer::processArgs() +{ + auto app = buildArgParserApp(); + if (!deactivated) { + app->parse(remArgs); + } else if (helpMode) { + app->remove_helics_specifics(); + std::cout << app->help(); } - - Tracer::Tracer(int argc, char* argv[]): App("tracer", argc, argv) - { - processArgs(); - } - - void Tracer::processArgs() - { - auto app = buildArgParserApp(); - if (!deactivated) { - fed->setFlagOption(HELICS_FLAG_OBSERVER); - app->parse(remArgs); - if (!masterFileName.empty()) { - loadFile(masterFileName); - } - } else if (helpMode) { - app->remove_helics_specifics(); - std::cout << app->help(); - } - } - Tracer::Tracer(std::string_view appName, - const std::shared_ptr& core, - const FederateInfo& fi): - App(appName, core, fi) - { +} +Tracer::Tracer(std::string_view appName, + const std::shared_ptr& core, + const FederateInfo& fedInfo): + App(appName, core, fedInfo) +{ + initialSetup(); +} + +Tracer::Tracer(std::string_view appName, CoreApp& core, const FederateInfo& fedInfo): + App(appName, core, fedInfo) +{ + initialSetup(); +} + +Tracer::Tracer(std::string_view name, const std::string& configString): App(name, configString) +{ + processArgs(); + initialSetup(); +} + +Tracer::~Tracer() = default; + +void Tracer::initialSetup() +{ + if (!deactivated) { fed->setFlagOption(HELICS_FLAG_OBSERVER); + loadInputFiles(); } +} - Tracer::Tracer(std::string_view appName, CoreApp& core, const FederateInfo& fi): - App(appName, core, fi) - { - fed->setFlagOption(HELICS_FLAG_OBSERVER); - } +void Tracer::loadJsonFile(const std::string& jsonString, bool enableFederateInterfaceRegistration) +{ + loadJsonFileConfiguration("tracer", jsonString, enableFederateInterfaceRegistration); - Tracer::Tracer(std::string_view name, const std::string& file): App(name, file) - { - fed->setFlagOption(HELICS_FLAG_OBSERVER); - Tracer::loadJsonFile(file); + auto subCount = fed->getInputCount(); + for (int ii = 0; ii < subCount; ++ii) { + subscriptions.emplace_back(fed->getInput(ii)); + subkeys.emplace(subscriptions.back().getName(), static_cast(subscriptions.size()) - 1); + } + auto eptCount = fed->getEndpointCount(); + for (int ii = 0; ii < eptCount; ++ii) { + endpoints.emplace_back(fed->getEndpoint(ii)); + eptNames[endpoints.back().getName()] = static_cast(endpoints.size() - 1); } - Tracer::~Tracer() = default; - - void Tracer::loadJsonFile(const std::string& jsonString) - { - loadJsonFileConfiguration("tracer", jsonString); + auto doc = fileops::loadJson(jsonString); - auto subCount = fed->getInputCount(); - for (int ii = 0; ii < subCount; ++ii) { - subscriptions.emplace_back(fed->getInput(ii)); - subkeys.emplace(subscriptions.back().getName(), - static_cast(subscriptions.size()) - 1); + auto tags = doc["tag"]; + if (tags.isArray()) { + for (const auto& tag : tags) { + addSubscription(tag.asString()); } - auto eptCount = fed->getEndpointCount(); - for (int ii = 0; ii < eptCount; ++ii) { - endpoints.emplace_back(fed->getEndpoint(ii)); - eptNames[endpoints.back().getName()] = static_cast(endpoints.size() - 1); + } else if (tags.isString()) { + addSubscription(tags.asString()); + } + auto sourceClone = doc["sourceclone"]; + if (sourceClone.isArray()) { + for (const auto& clone : sourceClone) { + addSourceEndpointClone(clone.asString()); } - - auto doc = fileops::loadJson(jsonString); - - auto tags = doc["tag"]; - if (tags.isArray()) { - for (const auto& tag : tags) { - addSubscription(tag.asString()); - } - } else if (tags.isString()) { - addSubscription(tags.asString()); + } else if (sourceClone.isString()) { + addSourceEndpointClone(sourceClone.asString()); + } + auto destClone = doc["destclone"]; + if (destClone.isArray()) { + for (const auto& clone : destClone) { + addDestEndpointClone(clone.asString()); } - auto sourceClone = doc["sourceclone"]; - if (sourceClone.isArray()) { - for (const auto& sc : sourceClone) { - addSourceEndpointClone(sc.asString()); - } - } else if (sourceClone.isString()) { - addSourceEndpointClone(sourceClone.asString()); + } else if (destClone.isString()) { + addDestEndpointClone(destClone.asString()); + } + auto clones = doc["clone"]; + if (clones.isArray()) { + for (const auto& clone : clones) { + addSourceEndpointClone(clone.asString()); + addDestEndpointClone(clone.asString()); } - auto destClone = doc["destclone"]; - if (destClone.isArray()) { - for (const auto& dc : destClone) { - addDestEndpointClone(dc.asString()); - } - } else if (destClone.isString()) { - addDestEndpointClone(destClone.asString()); + } else if (clones.isString()) { + addSourceEndpointClone(clones.asString()); + addDestEndpointClone(clones.asString()); + } + auto captures = doc["capture"]; + if (captures.isArray()) { + for (const auto& capture : captures) { + addCapture(capture.asString()); } - auto clones = doc["clone"]; - if (clones.isArray()) { - for (const auto& clone : clones) { - addSourceEndpointClone(clone.asString()); - addDestEndpointClone(clone.asString()); - } - } else if (clones.isString()) { - addSourceEndpointClone(clones.asString()); - addDestEndpointClone(clones.asString()); + } else if (captures.isString()) { + addCapture(captures.asString()); + } +} + +void Tracer::loadTextFile(const std::string& textFile) +{ + using namespace gmlc::utilities::stringOps; // NOLINT + App::loadTextFile(textFile); + std::ifstream infile(textFile); + std::string str; + int lineCount = 0; + while (std::getline(infile, str)) { + ++lineCount; + if (str.empty()) { + continue; } - auto captures = doc["capture"]; - if (captures.isArray()) { - for (const auto& capture : captures) { - addCapture(capture.asString()); - } - } else if (captures.isString()) { - addCapture(captures.asString()); + auto firstChar = str.find_first_not_of(" \t\n\r\0"); + if ((firstChar == std::string::npos) || (str[firstChar] == '#') || + (str[firstChar] == '!')) { + continue; } - } - - void Tracer::loadTextFile(const std::string& textFile) - { - using namespace gmlc::utilities::stringOps; // NOLINT - App::loadTextFile(textFile); - std::ifstream infile(textFile); - std::string str; - int lc = 0; - while (std::getline(infile, str)) { - ++lc; - if (str.empty()) { - continue; - } - auto fc = str.find_first_not_of(" \t\n\r\0"); - if ((fc == std::string::npos) || (str[fc] == '#') || (str[fc] == '!')) { - continue; - } - auto blk = splitlineQuotes(str, ",\t ", default_quote_chars, delimiter_compression::on); - - switch (blk.size()) { - case 1: - addSubscription(removeQuotes(blk[0])); - break; - case 2: - if ((blk[0] == "subscription") || (blk[0] == "s") || (blk[0] == "sub") || - (blk[0] == "tag")) { - addSubscription(removeQuotes(blk[1])); - } else if ((blk[0] == "endpoint") || (blk[0] == "ept") || (blk[0] == "e")) { - addEndpoint(removeQuotes(blk[1])); - } else if ((blk[0] == "sourceclone") || (blk[0] == "source") || - (blk[0] == "src")) { - addSourceEndpointClone(removeQuotes(blk[1])); - } else if ((blk[0] == "destclone") || (blk[0] == "dest") || - (blk[0] == "destination")) { - addDestEndpointClone(removeQuotes(blk[1])); - } else if (blk[0] == "capture") { - addCapture(removeQuotes(blk[1])); - } else if (blk[0] == "clone") { - addSourceEndpointClone(removeQuotes(blk[1])); - addDestEndpointClone(removeQuotes(blk[1])); - } else { - std::cerr << "Unable to process line " << lc << ':' << str << '\n'; - } - break; - case 3: - if (blk[0] == "clone") { - if ((blk[1] == "source") || (blk[1] == "src")) { - addSourceEndpointClone(removeQuotes(blk[2])); - } else if ((blk[1] == "dest") || (blk[1] == "destination")) { - addDestEndpointClone(removeQuotes(blk[2])); - } else { - std::cerr << "Unable to process line " << lc << ':' << str << '\n'; - } + auto blk = splitlineQuotes(str, ",\t ", default_quote_chars, delimiter_compression::on); + + switch (blk.size()) { + case 1: + addSubscription(removeQuotes(blk[0])); + break; + case 2: + if ((blk[0] == "subscription") || (blk[0] == "s") || (blk[0] == "sub") || + (blk[0] == "tag")) { + addSubscription(removeQuotes(blk[1])); + } else if ((blk[0] == "endpoint") || (blk[0] == "ept") || (blk[0] == "e")) { + addEndpoint(removeQuotes(blk[1])); + } else if ((blk[0] == "sourceclone") || (blk[0] == "source") || (blk[0] == "src")) { + addSourceEndpointClone(removeQuotes(blk[1])); + } else if ((blk[0] == "destclone") || (blk[0] == "dest") || + (blk[0] == "destination")) { + addDestEndpointClone(removeQuotes(blk[1])); + } else if (blk[0] == "capture") { + addCapture(removeQuotes(blk[1])); + } else if (blk[0] == "clone") { + addSourceEndpointClone(removeQuotes(blk[1])); + addDestEndpointClone(removeQuotes(blk[1])); + } else { + std::cerr << "Unable to process line " << lineCount << ':' << str << '\n'; + } + break; + case 3: + if (blk[0] == "clone") { + if ((blk[1] == "source") || (blk[1] == "src")) { + addSourceEndpointClone(removeQuotes(blk[2])); + } else if ((blk[1] == "dest") || (blk[1] == "destination")) { + addDestEndpointClone(removeQuotes(blk[2])); } else { - std::cerr << "Unable to process line " << lc << ':' << str << '\n'; + std::cerr << "Unable to process line " << lineCount << ':' << str << '\n'; } - break; - default: - break; - } + } else { + std::cerr << "Unable to process line " << lineCount << ':' << str << '\n'; + } + break; + default: + break; } - infile.close(); } + infile.close(); +} - void Tracer::initialize() - { - auto state = fed->getCurrentMode(); - if (state == Federate::Modes::STARTUP) { - generateInterfaces(); +void Tracer::initialize() +{ + auto state = fed->getCurrentMode(); + if (state == Federate::Modes::STARTUP) { + generateInterfaces(); - fed->enterInitializingMode(); - captureForCurrentTime(-1.0); - } + fed->enterInitializingMode(); + captureForCurrentTime(-1.0); } +} - void Tracer::generateInterfaces() - { - for (auto& tag : subkeys) { - if (tag.second == -1) { - addSubscription(tag.first); - } +void Tracer::generateInterfaces() +{ + for (auto& tag : subkeys) { + if (tag.second == -1) { + addSubscription(tag.first); } - - loadCaptureInterfaces(); } - void Tracer::loadCaptureInterfaces() - { - for (auto& capt : captureInterfaces) { - auto res = waitForInit(fed.get(), capt); - if (res) { - fed->query("root", "global_flush", HELICS_SEQUENCING_MODE_ORDERED); - auto pubs = vectorizeQueryResult( - fed->query(capt, "publications", HELICS_SEQUENCING_MODE_ORDERED)); - for (auto& pub : pubs) { - addSubscription(pub); - } + loadCaptureInterfaces(); +} + +void Tracer::loadCaptureInterfaces() +{ + for (auto& capt : captureInterfaces) { + auto res = waitForInit(fed.get(), capt); + if (res) { + fed->query("root", "global_flush", HELICS_SEQUENCING_MODE_ORDERED); + auto pubs = vectorizeQueryResult( + fed->query(capt, "publications", HELICS_SEQUENCING_MODE_ORDERED)); + for (auto& pub : pubs) { + addSubscription(pub); } } } - - void Tracer::captureForCurrentTime(Time currentTime, int iteration) - { - for (auto& sub : subscriptions) { - if (sub.isUpdated()) { - auto val = sub.getValue(); - - if (printMessage) { - std::string valstr; - if (val.size() < 150) { - if (iteration > 0) { - valstr = fmt::format( - "[{}:{}]value {}={}", currentTime, iteration, sub.getTarget(), val); - } else { - valstr = - fmt::format("[{}]value {}={}", currentTime, sub.getTarget(), val); - } +} + +void Tracer::captureForCurrentTime(Time currentTime, int iteration) +{ + for (auto& sub : subscriptions) { + if (sub.isUpdated()) { + auto val = sub.getValue(); + + if (printMessage) { + std::string valstr; + if (val.size() < 150) { + if (iteration > 0) { + valstr = fmt::format("[{}:{}]value {}={}", + static_cast(currentTime), + iteration, + sub.getTarget(), + val); } else { - if (iteration > 0) { - valstr = fmt::format("[{}:{}]value {}=block[{}]", - currentTime, - iteration, - sub.getTarget(), - val.size()); - } else { - valstr = fmt::format("[{}]value {}=block[{}]", - currentTime, - sub.getTarget(), - val.size()); - } + valstr = fmt::format("[{}]value {}={}", + static_cast(currentTime), + sub.getTarget(), + val); } - if (skiplog) { - std::cout << valstr << '\n'; + } else { + if (iteration > 0) { + valstr = fmt::format("[{}:{}]value {}=block[{}]", + static_cast(currentTime), + iteration, + sub.getTarget(), + val.size()); } else { - spdlog::info(valstr); + valstr = fmt::format("[{}]value {}=block[{}]", + static_cast(currentTime), + sub.getTarget(), + val.size()); } } - if (valueCallback) { - valueCallback(currentTime, sub.getTarget(), val); + if (skiplog) { + std::cout << valstr << '\n'; + } else { + spdlog::info(valstr); } } + if (valueCallback) { + valueCallback(currentTime, sub.getTarget(), val); + } } + } - for (auto& ept : endpoints) { - while (ept.hasMessage()) { - auto mess = ept.getMessage(); - if (printMessage) { - std::string messstr; - if (mess->data.size() < 50) { - messstr = fmt::format("[{}]message from {} to {}::{}", - currentTime, - mess->source, - mess->dest, - mess->data.to_string()); - } else { - messstr = fmt::format("[{}]message from {} to {}:: size {}", - currentTime, - mess->source, - mess->dest, - mess->data.size()); - } - if (skiplog) { - std::cout << messstr << '\n'; - } else { - spdlog::info(messstr); - } + for (auto& ept : endpoints) { + while (ept.hasMessage()) { + auto mess = ept.getMessage(); + if (printMessage) { + std::string messstr; + if (mess->data.size() < 50) { + messstr = fmt::format("[{}]message from {} to {}::{}", + static_cast(currentTime), + mess->source, + mess->dest, + mess->data.to_string()); + } else { + messstr = fmt::format("[{}]message from {} to {}:: size {}", + static_cast(currentTime), + mess->source, + mess->dest, + mess->data.size()); } - if (endpointMessageCallback) { - endpointMessageCallback(currentTime, ept.getName(), std::move(mess)); + if (skiplog) { + std::cout << messstr << '\n'; + } else { + spdlog::info(messstr); } } + if (endpointMessageCallback) { + endpointMessageCallback(currentTime, ept.getName(), std::move(mess)); + } } + } - // get the clone endpoints - if (cloneEndpoint) { - while (cloneEndpoint->hasMessage()) { - auto mess = cloneEndpoint->getMessage(); - if (printMessage) { - std::string messstr; - if (mess->data.size() < 50) { - messstr = fmt::format("[{}]message from {} to {}::{}", - currentTime, - mess->source, - mess->original_dest, - mess->data.to_string()); - } else { - messstr = fmt::format("[{}]message from %s to %s:: size %d", - currentTime, - mess->source, - mess->original_dest, - mess->data.size()); - } - if (skiplog) { - std::cout << messstr << '\n'; - } else { - spdlog::info(messstr); - } + // get the clone endpoints + if (cloneEndpoint) { + while (cloneEndpoint->hasMessage()) { + auto mess = cloneEndpoint->getMessage(); + if (printMessage) { + std::string messstr; + if (mess->data.size() < 50) { + messstr = fmt::format("[{}]message from {} to {}::{}", + static_cast(currentTime), + mess->source, + mess->original_dest, + mess->data.to_string()); + } else { + messstr = fmt::format("[{}]message from %s to %s:: size %d", + static_cast(currentTime), + mess->source, + mess->original_dest, + mess->data.size()); } - if (clonedMessageCallback) { - clonedMessageCallback(currentTime, std::move(mess)); + if (skiplog) { + std::cout << messstr << '\n'; + } else { + spdlog::info(messstr); } } + if (clonedMessageCallback) { + clonedMessageCallback(currentTime, std::move(mess)); + } } } +} + +/** run the Player until the specified time*/ +void Tracer::runTo(Time runToTime) +{ + auto state = fed->getCurrentMode(); + if (state == Federate::Modes::STARTUP) { + initialize(); + state = Federate::Modes::INITIALIZING; + } - /** run the Player until the specified time*/ - void Tracer::runTo(Time runToTime) - { - auto state = fed->getCurrentMode(); - if (state == Federate::Modes::STARTUP) { - initialize(); - state = Federate::Modes::INITIALIZING; - } - - if (state == Federate::Modes::INITIALIZING) { - fed->enterExecutingMode(); - captureForCurrentTime(0.0); - } + if (state == Federate::Modes::INITIALIZING) { + fed->enterExecutingMode(); + captureForCurrentTime(0.0); + } - Time nextPrintTime = 10.0; - try { - int iteration = 0; - while (true) { - helics::Time T; - - if (allow_iteration) { - auto ItRes = - fed->requestTimeIterative(runToTime, IterationRequest::ITERATE_IF_NEEDED); - if (ItRes.state == IterationResult::NEXT_STEP) { - iteration = 0; - } - T = ItRes.grantedTime; - captureForCurrentTime(T, iteration); - ++iteration; - } else { - T = fed->requestTime(runToTime); - captureForCurrentTime(T); - } - if (T >= runToTime) { - break; - } - if (T >= nextPrintTime) { - std::cout << "processed for time " << static_cast(T) << "\n"; - nextPrintTime += 10.0; + Time nextPrintTime = 10.0; + try { + int iteration = 0; + while (true) { + helics::Time grantedTime; + + if (allow_iteration) { + auto ItRes = + fed->requestTimeIterative(runToTime, IterationRequest::ITERATE_IF_NEEDED); + if (ItRes.state == IterationResult::NEXT_STEP) { + iteration = 0; } + grantedTime = ItRes.grantedTime; + captureForCurrentTime(grantedTime, iteration); + ++iteration; + } else { + grantedTime = fed->requestTime(runToTime); + captureForCurrentTime(grantedTime); + } + if (grantedTime >= runToTime) { + break; + } + if (grantedTime >= nextPrintTime) { + std::cout << "processed for time " << static_cast(grantedTime) << "\n"; + nextPrintTime += 10.0; } - } - catch (...) { } } - /** add a subscription to record*/ - void Tracer::addSubscription(std::string_view key) - { - auto res = subkeys.find(key); - if ((res == subkeys.end()) || (res->second == -1)) { - subscriptions.push_back(fed->registerSubscription(key)); - auto index = static_cast(subscriptions.size()) - 1; - subkeys[subscriptions.back().getTarget()] = index; // this is a potential replacement - } + catch (...) { } - - /** add an endpoint*/ - void Tracer::addEndpoint(std::string_view endpoint) - { - auto res = eptNames.find(endpoint); - if ((res == eptNames.end()) || (res->second == -1)) { - endpoints.emplace_back(InterfaceVisibility::GLOBAL, fed, endpoint); - auto index = static_cast(endpoints.size()) - 1; - eptNames[endpoints.back().getName()] = index; // this is a potential replacement - } +} +/** add a subscription to record*/ +void Tracer::addSubscription(std::string_view key) +{ + auto res = subkeys.find(key); + if ((res == subkeys.end()) || (res->second == -1)) { + subscriptions.push_back(fed->registerSubscription(key)); + auto index = static_cast(subscriptions.size()) - 1; + subkeys[subscriptions.back().getTarget()] = index; // this is a potential replacement } - void Tracer::addSourceEndpointClone(std::string_view sourceEndpoint) - { - if (!cFilt) { - cFilt = std::make_unique(fed.get()); - cloneEndpoint = std::make_unique(fed.get(), "cloneE"); - cFilt->addDeliveryEndpoint(cloneEndpoint->getName()); - } - cFilt->addSourceTarget(sourceEndpoint); +} + +/** add an endpoint*/ +void Tracer::addEndpoint(std::string_view endpoint) +{ + auto res = eptNames.find(endpoint); + if ((res == eptNames.end()) || (res->second == -1)) { + endpoints.emplace_back(InterfaceVisibility::GLOBAL, fed, endpoint); + auto index = static_cast(endpoints.size()) - 1; + eptNames[endpoints.back().getName()] = index; // this is a potential replacement } - - void Tracer::addDestEndpointClone(std::string_view destEndpoint) - { - if (!cFilt) { - cFilt = std::make_unique(fed.get()); - cloneEndpoint = std::make_unique(fed.get(), "cloneE"); - cFilt->addDeliveryEndpoint(cloneEndpoint->getName()); - } - cFilt->addDestinationTarget(destEndpoint); +} +void Tracer::addSourceEndpointClone(std::string_view sourceEndpoint) +{ + if (!cFilt) { + cFilt = std::make_unique(fed.get()); + cloneEndpoint = std::make_unique(fed.get(), "cloneE"); + cFilt->addDeliveryEndpoint(cloneEndpoint->getName()); } - - void Tracer::addCapture(std::string_view captureDesc) - { - captureInterfaces.emplace_back(captureDesc); + cFilt->addSourceTarget(sourceEndpoint); +} + +void Tracer::addDestEndpointClone(std::string_view destEndpoint) +{ + if (!cFilt) { + cFilt = std::make_unique(fed.get()); + cloneEndpoint = std::make_unique(fed.get(), "cloneE"); + cFilt->addDeliveryEndpoint(cloneEndpoint->getName()); } + cFilt->addDestinationTarget(destEndpoint); +} + +void Tracer::addCapture(std::string_view captureDesc) +{ + captureInterfaces.emplace_back(captureDesc); +} + +std::shared_ptr Tracer::buildArgParserApp() +{ + using gmlc::utilities::stringOps::removeQuotes; + using gmlc::utilities::stringOps::splitlineQuotes; + + auto app = std::make_shared("Command line options for the Tracer App"); + app->add_flag("--allow_iteration", allow_iteration, "allow iteration on values") + ->ignore_underscore(); + app->add_flag("--print", printMessage, "print messages to the screen"); + app->add_flag("--skiplog", skiplog, "print messages to the screen through cout"); + auto* clone_group = + app->add_option_group("cloning", + "Options related to endpoint cloning operations and specifications"); + clone_group->add_option("--clone", "existing endpoints to clone all packets to and from") + ->each([this](const std::string& clone) { + addDestEndpointClone(clone); + addSourceEndpointClone(clone); + }) + ->delimiter(',') + ->type_size(-1); + + clone_group + ->add_option( + "--sourceclone", + "existing endpoints to capture generated packets from, this argument may be specified multiple time") + ->each([this](const std::string& clone) { addSourceEndpointClone(clone); }) + ->delimiter(',') + ->ignore_underscore() + ->type_size(-1); + + clone_group + ->add_option("--destclone", + "existing endpoints to capture all packets with the specified endpoint as a " + "destination, this argument may be specified multiple time") + ->each([this](const std::string& clone) { addSourceEndpointClone(clone); }) + ->delimiter(',') + ->ignore_underscore() + ->type_size(-1); + + auto* capture_group = + app->add_option_group("capture_group", + "Options related to capturing publications, endpoints, or federates"); + capture_group + ->add_option( + "--tag,--publication,--pub", + "tags(publications) to record, this argument may be specified any number of times") + ->each([this](const std::string& tag) { + auto taglist = splitlineQuotes(tag); + for (const auto& tagname : taglist) { + subkeys.emplace(removeQuotes(tagname), -1); + } + }) + ->type_size(-1); + + capture_group + ->add_option("--endpoints", + "endpoints to capture, this argument may be specified multiple time") + ->each([this](const std::string& ept) { + auto eptlist = splitlineQuotes(ept); + for (const auto& eptname : eptlist) { + eptNames.emplace(removeQuotes(eptname), -1); + } + }) + ->type_size(-1); + + capture_group + ->add_option("--capture", + "capture all the publications of a particular federate capture=\"fed1;fed2\" " + "supports multiple arguments or a semicolon/comma separated list") + ->each([this](const std::string& capt) { + auto captFeds = splitlineQuotes(capt); + for (auto& captFed : captFeds) { + auto actCapt = removeQuotes(captFed); + captureInterfaces.push_back(actCapt); + } + }) + ->type_size(-1); - std::shared_ptr Tracer::buildArgParserApp() - { - using gmlc::utilities::stringOps::removeQuotes; - using gmlc::utilities::stringOps::splitlineQuotes; - - auto app = std::make_shared("Command line options for the Tracer App"); - app->add_flag("--allow_iteration", allow_iteration, "allow iteration on values") - ->ignore_underscore(); - app->add_flag("--print", printMessage, "print messages to the screen"); - app->add_flag("--skiplog", skiplog, "print messages to the screen through cout"); - auto* clone_group = app->add_option_group( - "cloning", "Options related to endpoint cloning operations and specifications"); - clone_group->add_option("--clone", "existing endpoints to clone all packets to and from") - ->each([this](const std::string& clone) { - addDestEndpointClone(clone); - addSourceEndpointClone(clone); - }) - ->delimiter(',') - ->type_size(-1); - - clone_group - ->add_option( - "--sourceclone", - "existing endpoints to capture generated packets from, this argument may be specified multiple time") - ->each([this](const std::string& clone) { addSourceEndpointClone(clone); }) - ->delimiter(',') - ->ignore_underscore() - ->type_size(-1); - - clone_group - ->add_option( - "--destclone", - "existing endpoints to capture all packets with the specified endpoint as a " - "destination, this argument may be specified multiple time") - ->each([this](const std::string& clone) { addSourceEndpointClone(clone); }) - ->delimiter(',') - ->ignore_underscore() - ->type_size(-1); - - auto* capture_group = app->add_option_group( - "capture_group", "Options related to capturing publications, endpoints, or federates"); - capture_group - ->add_option( - "--tag,--publication,--pub", - "tags(publications) to record, this argument may be specified any number of times") - ->each([this](const std::string& tag) { - auto taglist = splitlineQuotes(tag); - for (const auto& tagname : taglist) { - subkeys.emplace(removeQuotes(tagname), -1); - } - }) - ->type_size(-1); - - capture_group - ->add_option("--endpoints", - "endpoints to capture, this argument may be specified multiple time") - ->each([this](const std::string& ept) { - auto eptlist = splitlineQuotes(ept); - for (const auto& eptname : eptlist) { - eptNames.emplace(removeQuotes(eptname), -1); - } - }) - ->type_size(-1); - - capture_group - ->add_option( - "--capture", - "capture all the publications of a particular federate capture=\"fed1;fed2\" " - "supports multiple arguments or a semicolon/comma separated list") - ->each([this](const std::string& capt) { - auto captFeds = splitlineQuotes(capt); - for (auto& captFed : captFeds) { - auto actCapt = removeQuotes(captFed); - captureInterfaces.push_back(actCapt); - } - }) - ->type_size(-1); - - return app; - } + return app; +} -} // namespace apps -} // namespace helics +} // namespace helics::apps diff --git a/src/helics/apps/Tracer.hpp b/src/helics/apps/Tracer.hpp index 4faa9bb280..099b863ee3 100644 --- a/src/helics/apps/Tracer.hpp +++ b/src/helics/apps/Tracer.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -26,7 +26,7 @@ namespace apps { class HELICS_CXX_EXPORT Tracer: public App { public: /** construct from a FederateInfo structure*/ - explicit Tracer(std::string_view name, FederateInfo& fi); + explicit Tracer(std::string_view name, FederateInfo& fedInfo); /** construct from command line arguments in a vector @param args the command line arguments to pass in a reverse vector */ @@ -36,24 +36,26 @@ namespace apps { Tracer(int argc, char* argv[]); /**constructor taking a federate information structure and using the given core - @param name the name of the tracer object, if empty it tries to figure it out from fi + @param name the name of the tracer object, if empty it tries to figure it out from fedInfo @param core a pointer to core object which the federate can join - @param fi a federate information structure + @param fedInfo a federate information structure */ - Tracer(std::string_view name, const std::shared_ptr& core, const FederateInfo& fi); + Tracer(std::string_view name, + const std::shared_ptr& core, + const FederateInfo& fedInfo); /**constructor taking a federate information structure and using the given core - @param name the name of the federate (can be empty to use defaults from fi) + @param name the name of the federate (can be empty to use defaults from fedInfo) @param core a coreApp object that can be joined - @param fi a federate information structure + @param fedInfo a federate information structure */ - Tracer(std::string_view name, CoreApp& core, const FederateInfo& fi); + Tracer(std::string_view name, CoreApp& core, const FederateInfo& fedInfo); /**constructor taking a file with the required information @param name the name of the app may be empty to pull name from the file @param file a file defining the federate information */ - Tracer(std::string_view name, const std::string& file); + Tracer(std::string_view name, const std::string& configString); /** move construction*/ Tracer(Tracer&& other_tracer) = default; /** move assignment*/ @@ -105,10 +107,13 @@ namespace apps { void disableTextOutput() { printMessage = false; } private: + /** run any initial setup operations including file loading*/ + void initialSetup(); /** load from a jsonString @param jsonString either a JSON filename or a string containing JSON */ - virtual void loadJsonFile(const std::string& jsonString) override; + virtual void loadJsonFile(const std::string& jsonString, + bool enableFederateInterfaceRegistration) override; /** load a text file*/ virtual void loadTextFile(const std::string& textFile) override; diff --git a/src/helics/apps/TypedBrokerServer.cpp b/src/helics/apps/TypedBrokerServer.cpp index 167b58293a..ba12b58242 100644 --- a/src/helics/apps/TypedBrokerServer.cpp +++ b/src/helics/apps/TypedBrokerServer.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/apps/TypedBrokerServer.hpp b/src/helics/apps/TypedBrokerServer.hpp index cbd1ee5e51..0ce0cfd5ff 100644 --- a/src/helics/apps/TypedBrokerServer.hpp +++ b/src/helics/apps/TypedBrokerServer.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/apps/appMain.cpp b/src/helics/apps/appMain.cpp index 4db43b32ed..db5dc94704 100644 --- a/src/helics/apps/appMain.cpp +++ b/src/helics/apps/appMain.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -9,6 +9,7 @@ SPDX-License-Identifier: BSD-3-Clause #include "../core/core-exceptions.hpp" #include "../core/helicsCLI11.hpp" #include "Clone.hpp" +#include "Connector.hpp" #include "Echo.hpp" #include "Player.hpp" #include "Probe.hpp" @@ -61,6 +62,18 @@ int main(int argc, char* argv[]) helics::apps::Clone rec({"-?"}); return std::string{}; }); + app.add_subcommand("connector", "Helics Connector App") + ->callback([&app]() { + helics::apps::Connector connector(app.remaining_for_passthrough(true)); + std::cout << "clone subcommand\n"; + if (connector.isActive()) { + connector.run(); + } + }) + ->footer([] { + helics::apps::Connector conn({"-?"}); + return std::string{}; + }); app.add_subcommand("echo", "Helics Echo App") ->callback([&app]() { std::cout << "echo subcommand\n"; diff --git a/src/helics/apps/connectorMain.cpp b/src/helics/apps/connectorMain.cpp new file mode 100644 index 0000000000..b2e3c85584 --- /dev/null +++ b/src/helics/apps/connectorMain.cpp @@ -0,0 +1,32 @@ +/* +Copyright (c) 2017-2024, +Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable +Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. +SPDX-License-Identifier: BSD-3-Clause +*/ +#include "../core/core-exceptions.hpp" +#include "Connector.hpp" + +#include + +int main(int argc, char* argv[]) +{ + int ret = 0; + try { + helics::apps::Connector Connector(argc, argv); + if (Connector.isActive()) { + Connector.run(); + } + } + catch (const std::invalid_argument& ia) { + std::cerr << ia.what() << std::endl; + ret = -2; + } + catch (const helics::HelicsException& he) { + std::cerr << he.what() << std::endl; + ret = -4; + } + + helics::cleanupHelicsLibrary(); + return ret; +} diff --git a/src/helics/apps/helics-broker-server.cpp b/src/helics/apps/helics-broker-server.cpp index 761bf16a3a..e82b524c0e 100644 --- a/src/helics/apps/helics-broker-server.cpp +++ b/src/helics/apps/helics-broker-server.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -156,7 +156,7 @@ void terminalFunction(std::vector args) broker->forceTerminate (); broker = nullptr; broker = std::make_unique (args); - std::cout << "broker was forceably terminated and restarted\n"; + std::cout << "broker was forcibly terminated and restarted\n"; } else { @@ -234,7 +234,7 @@ void terminalFunction(std::vector args) (restart->remaining_for_passthrough (), false); }); auto frestart = - termProg.add_subcommand ("restart!", "forceably terminate the broker and restart + termProg.add_subcommand ("restart!", "forcibly terminate the broker and restart it")->allow_extras (); frestart->callback ( [restartBroker, &restart] () { restartBroker (restart->remaining_for_passthrough (), true); }); diff --git a/src/helics/apps/helics-broker.cpp b/src/helics/apps/helics-broker.cpp index 623e604fe3..10eb68f310 100644 --- a/src/helics/apps/helics-broker.cpp +++ b/src/helics/apps/helics-broker.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -189,7 +189,7 @@ void terminalFunction(std::vector args) broker->forceTerminate(); broker = nullptr; broker = std::make_unique(args); - std::cout << "broker was forceably terminated and restarted\n"; + std::cout << "broker was forcibly terminated and restarted\n"; } else { std::cout << "broker is currently running unable to restart\n"; } @@ -232,7 +232,7 @@ void terminalFunction(std::vector args) ->callback([&cmdcont]() { cmdcont = false; }); termProg.add_subcommand("terminate", "terminate the broker")->callback(closeBroker); - termProg.add_subcommand("terminate!", "forceably terminate the broker and exit") + termProg.add_subcommand("terminate!", "forcibly terminate the broker and exit") ->callback([closeBroker, &cmdcont]() { cmdcont = false; closeBroker(); @@ -246,7 +246,7 @@ void terminalFunction(std::vector args) }); auto* frestart = - termProg.add_subcommand("restart!", "forceably terminate the broker and restart it") + termProg.add_subcommand("restart!", "forcibly terminate the broker and restart it") ->allow_extras(); frestart->callback( [restartBroker, &restart]() { restartBroker(restart->remaining_for_passthrough(), true); }); diff --git a/src/helics/apps/helicsApp.cpp b/src/helics/apps/helicsApp.cpp index b016c01b24..f5075d5e97 100644 --- a/src/helics/apps/helicsApp.cpp +++ b/src/helics/apps/helicsApp.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -7,6 +7,7 @@ SPDX-License-Identifier: BSD-3-Clause #include "helicsApp.hpp" #include "../common/JsonProcessingFunctions.hpp" +#include "../common/TomlProcessingFunctions.hpp" #include "../core/helicsCLI11.hpp" #include "../core/helicsVersion.hpp" #include "PrecHelper.hpp" @@ -15,6 +16,7 @@ SPDX-License-Identifier: BSD-3-Clause #include #include #include +#include #include #include #include @@ -35,23 +37,23 @@ namespace helics::apps { App::App(std::string_view defaultAppName, std::vector args) { auto app = generateParser(); - FederateInfo fi; - fi.injectParser(app.get()); + FederateInfo fedInfo; + fedInfo.injectParser(app.get()); app->helics_parse(std::move(args)); - processArgs(app, fi, defaultAppName); + processArgs(app, fedInfo, defaultAppName); } App::App(std::string_view defaultAppName, int argc, char* argv[]) { auto app = generateParser(); - FederateInfo fi; - fi.injectParser(app.get()); + FederateInfo fedInfo; + fedInfo.injectParser(app.get()); app->helics_parse(argc, argv); - processArgs(app, fi, defaultAppName); + processArgs(app, fedInfo, defaultAppName); } void App::processArgs(std::unique_ptr& app, - FederateInfo& fi, + FederateInfo& fedInfo, std::string_view defaultAppName) { remArgs = app->remaining_for_passthrough(); @@ -64,42 +66,44 @@ void App::processArgs(std::unique_ptr& app, return; } - if (masterFileName.empty()) { + if (inputFileName.empty()) { if (!fileLoaded) { if (CLI::ExistingFile("helics.json").empty()) { - masterFileName = "helics.json"; + inputFileName = "helics.json"; } } } - if (fi.defName.empty()) { - fi.defName = defaultAppName; + if (fedInfo.defName.empty()) { + fedInfo.defName = defaultAppName; } - fed = std::make_shared("", fi); + fed = std::make_shared("", fedInfo); + configFileName = fed->getConfigFile(); } -App::App(std::string_view appName, const FederateInfo& fi): - fed(std::make_shared(appName, fi)) +App::App(std::string_view appName, const FederateInfo& fedInfo): + fed(std::make_shared(appName, fedInfo)) { + configFileName = fed->getConfigFile(); } -App::App(std::string_view appName, const std::shared_ptr& core, const FederateInfo& fi): - fed(std::make_shared(appName, core, fi)) +App::App(std::string_view appName, const std::shared_ptr& core, const FederateInfo& fedInfo): + fed(std::make_shared(appName, core, fedInfo)) { + configFileName = fed->getConfigFile(); } -App::App(std::string_view appName, CoreApp& core, const FederateInfo& fi): - fed(std::make_shared(appName, core, fi)) +App::App(std::string_view appName, CoreApp& core, const FederateInfo& fedInfo): + fed(std::make_shared(appName, core, fedInfo)) { + configFileName = fed->getConfigFile(); } App::App(std::string_view appName, const std::string& jsonString): fed(std::make_shared(appName, jsonString)) { - if (jsonString.size() < 200) { - masterFileName = jsonString; - } + configFileName = fed->getConfigFile(); } App::~App() = default; @@ -112,52 +116,162 @@ std::unique_ptr App::generateParser() app->add_flag("--local", useLocal, "Specify otherwise unspecified endpoints and publications as local " - "(i.e. the names will be prepended with the player name)"); + "(i.e. the names will be prepended with the app name)"); app->add_option("--stop", stopTime, "The time to stop the app"); - app->add_option("--input,input", masterFileName, "The primary input file") + app->add_option("--input,input", + inputFileName, + "The primary input file containing app configuration") ->check(CLI::ExistingFile); app->allow_extras()->validate_positionals(); return app; } -void App::loadFile(const std::string& filename) +void App::loadFile(const std::string& filename, bool enableFederateInterfaceRegistration) { if (fileops::hasJsonExtension(filename)) { - loadJsonFile(filename); + loadJsonFile(filename, enableFederateInterfaceRegistration); + } else if (fileops::hasTomlExtension(filename)) { + if (enableFederateInterfaceRegistration) { + fed->registerInterfaces(filename); + } else { + fed->logWarningMessage("Toml files are not support for app configuration"); + } } else { loadTextFile(filename); } } -void App::loadTextFile(const std::string& textFile) +AppTextParser::AppTextParser(const std::string& filename): filePtr(filename), mFileName(filename) {} + +std::vector AppTextParser::preParseFile(const std::vector& klines) { - // using namespace gmlc::utilities::stringOps; - std::ifstream infile(textFile); + reset(); + std::vector counts(1 + klines.size()); std::string str; - + bool inMline{false}; // count the lines - while (std::getline(infile, str)) { + while (std::getline(filePtr, str)) { if (str.empty()) { continue; } auto fc = str.find_first_not_of(" \t\n\r\0"); - if ((fc == std::string::npos) || (str[fc] == '#')) { + if (fc == std::string::npos) { + continue; + } + if (inMline) { + if (fc + 2 < str.size()) { + if ((str[fc] == '#') && (str[fc + 1] == '#') && (str[fc + 2] == ']')) { + inMline = false; + } + } + continue; + } + if (str[fc] == '#') { + if (fc + 2 < str.size()) { + if ((str[fc + 1] == '#') && (str[fc + 2] == '[')) { + inMline = true; + } + } continue; } if (str[fc] == '!') { + configStr += str.substr(fc + 1); + configStr.push_back('\n'); + continue; + } + + ++counts[0]; + for (int ii = 0; ii < klines.size(); ++ii) { + if (str[fc] == klines[ii]) { + ++counts[ii + 1]; + } + } + } + return counts; +} + +bool AppTextParser::loadNextLine(std::string& line, int& lineNumber) +{ + while (std::getline(filePtr, line)) { + ++currentLineNumber; + if (line.empty()) { + continue; + } + auto fc = line.find_first_not_of(" \t\n\r\0"); + if (fc == std::string::npos) { + continue; } + if (mLineComment) { + if (fc + 2 < line.size()) { + if ((line[fc] == '#') && (line[fc + 1] == '#') && (line[fc + 2] == ']')) { + mLineComment = false; + } + } + continue; + } + if (line[fc] == '#') { + if (fc + 2 < line.size()) { + if ((line[fc + 1] == '#') && (line[fc + 2] == '[')) { + mLineComment = true; + } + } + continue; + } + if (line[fc] == '!') { + continue; + } + lineNumber = currentLineNumber; + return true; + } + return false; +} + +void AppTextParser::reset() +{ + filePtr.close(); + filePtr.open(mFileName); + mLineComment = false; +} + +void App::loadConfigOptions(AppTextParser& aparser) +{ + if (!aparser.configString().empty()) { + auto app = generateParser(); + std::istringstream sstr(aparser.configString()); + app->parse_from_stream(sstr); } } -void App::loadJsonFile(const std::string& jsonString) +void App::loadTextFile(const std::string& textFile) +{ + AppTextParser aparser(textFile); + aparser.preParseFile({}); + loadConfigOptions(aparser); +} + +void App::loadInputFiles() { - loadJsonFileConfiguration("application", jsonString); + if (!configFileName.empty()) { + /** this one would have been loaded through the federate already*/ + loadFile(configFileName, false); + } + if (!inputFileName.empty()) { + loadFile(inputFileName, true); + } } -void App::loadJsonFileConfiguration(const std::string& appName, const std::string& jsonString) +void App::loadJsonFile(const std::string& jsonString, bool enableFederateInterfaceRegistration) { - fed->registerInterfaces(jsonString); + loadJsonFileConfiguration("application", jsonString, enableFederateInterfaceRegistration); +} +void App::loadJsonFileConfiguration(const std::string& appName, + const std::string& jsonString, + bool enableFederateInterfaceRegistration) +{ + if (enableFederateInterfaceRegistration) { + fed->registerInterfaces(jsonString); + } auto doc = fileops::loadJson(jsonString); if (doc.isMember("app")) { diff --git a/src/helics/apps/helicsApp.hpp b/src/helics/apps/helicsApp.hpp index d8832f2cfc..0b29ee175a 100644 --- a/src/helics/apps/helicsApp.hpp +++ b/src/helics/apps/helicsApp.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -8,6 +8,7 @@ SPDX-License-Identifier: BSD-3-Clause #include "../application_api/CombinationFederate.hpp" +#include #include #include #include @@ -20,122 +21,155 @@ namespace Json { class Value; } // namespace Json -namespace helics { -namespace apps { - /** class defining a basic helics App +namespace helics::apps { + +class AppTextParser; + +/** class defining a basic helics App @details the App class is not thread-safe in non-const methods, don't try to use it from multiple threads without external protection, that will result in undefined behavior */ - class HELICS_CXX_EXPORT App { - public: - /** default constructor*/ - App() = default; - /** construct from command line arguments in a vector - @param defaultAppName the name to use if not specified in one of the arguments - @param args the command line arguments to pass in a reverse vector - */ - App(std::string_view defaultAppName, std::vector args); - /** construct from command line arguments - @param defaultAppName the name to use if not specified in one of the arguments - @param argc the number of arguments - @param argv the strings in the input - */ - App(std::string_view defaultAppName, int argc, char* argv[]); - /** construct from a federate info object - @param appName the name of the application, can be left empty to use a name specified in fi - @param fi a pointer info object containing information on the desired federate configuration - */ - App(std::string_view appName, const FederateInfo& fi); - /**constructor taking a federate information structure and using the given core - @param appName the name of the application, can be left empty to use a name specified in fi - @param core a pointer to core object which the federate can join - @param fi a federate information structure - */ - App(std::string_view appName, const std::shared_ptr& core, const FederateInfo& fi); - /**constructor taking a federate information structure and using the given coreApp - @param appName the name of the application, can be left empty to use a name specified in fi - @param core a pointer to core object which the federate can join - @param fi a federate information structure - */ - App(std::string_view appName, CoreApp& core, const FederateInfo& fi); - /**constructor taking a file with the required information - @param appName the name of the application, can be left empty to use a name specified in - jsonString - @param jsonString file or JSON string defining the federate information and other configuration - */ - App(std::string_view appName, const std::string& jsonString); - - /** move construction*/ - App(App&& other_app) = default; - /** don't allow the copy constructor*/ - App(const App& other_app) = delete; - /** move assignment*/ - App& operator=(App&& app) = default; - /** don't allow the copy assignment, the default would fail anyway since federates are not - * copyable either*/ - App& operator=(const App& app) = delete; - virtual ~App(); - - /** load a file containing publication information - @param filename the file containing the configuration and App data accepted format are JSON, - xml, and a App format which is tab delimited or comma delimited*/ - void loadFile(const std::string& filename); - /** initialize the App federate - @details generate all the publications and organize the points, the final publication count will - be available after this time and the App will enter the initialization mode, which means it - will not be possible to add more publications calling run will automatically do this if - necessary - */ - virtual void initialize(); - /*run the Player*/ - virtual void run(); - - /** run the Player until the specified time - @param stopTime_input the desired stop time - */ - virtual void runTo(Time stopTime_input) = 0; - - /** finalize the Player federate*/ - virtual void finalize(); - - /** check if the Player is ready to run*/ - bool isActive() const { return !deactivated; } - /** get a const reference to the federate*/ - const CombinationFederate& accessUnderlyingFederate() const { return *fed; } - - protected: - /** load from a jsonString - @param jsonString either a JSON filename or a string containing JSON - */ - virtual void loadJsonFile(const std::string& jsonString); - /** load from a jsonString and check a field named appName for configuration options - @param appName the name of the app which may be used in section of the JSON for some local - configuration - @param jsonString either a JSON filename or a string containing JSON - */ - void loadJsonFileConfiguration(const std::string& appName, const std::string& jsonString); - /** load a text file*/ - virtual void loadTextFile(const std::string& textFile); - - private: - void loadConfigOptions(const Json::Value& element); - /** generate the command line parser*/ - std::unique_ptr generateParser(); - /** process the command line arguments */ - void processArgs(std::unique_ptr& app, - FederateInfo& fi, - std::string_view defaultAppName); - - protected: - std::shared_ptr fed; //!< the federate created for the App - Time stopTime = Time::maxVal(); //!< the time the App should stop - std::string masterFileName; //!< the name of the master file used to do the construction - bool useLocal{false}; - bool fileLoaded{false}; - bool deactivated{false}; - bool quietMode{false}; - bool helpMode{false}; - std::vector remArgs; - }; -} // namespace apps -} // namespace helics +class HELICS_CXX_EXPORT App { + public: + /** default constructor*/ + App() = default; + /** construct from command line arguments in a vector +@param defaultAppName the name to use if not specified in one of the arguments +@param args the command line arguments to pass in a reverse vector +*/ + App(std::string_view defaultAppName, std::vector args); + /** construct from command line arguments +@param defaultAppName the name to use if not specified in one of the arguments +@param argc the number of arguments +@param argv the strings in the input +*/ + App(std::string_view defaultAppName, int argc, char* argv[]); + /** construct from a federate info object +@param appName the name of the application, can be left empty to use a name specified in fedInfo +@param fedInfo a pointer info object containing information on the desired federate +configuration +*/ + App(std::string_view appName, const FederateInfo& fedInfo); + /**constructor taking a federate information structure and using the given core +@param appName the name of the application, can be left empty to use a name specified in fedInfo +@param core a pointer to core object which the federate can join +@param fedInfo a federate information structure +*/ + App(std::string_view appName, const std::shared_ptr& core, const FederateInfo& fedInfo); + /**constructor taking a federate information structure and using the given coreApp +@param appName the name of the application, can be left empty to use a name specified in fedInfo +@param core a pointer to core object which the federate can join +@param fedInfo a federate information structure +*/ + App(std::string_view appName, CoreApp& core, const FederateInfo& fedInfo); + /**constructor taking a file with the required information +@param appName the name of the application, can be left empty to use a name specified in +configString +@param configString file or JSON string defining the federate information and other +configuration +*/ + App(std::string_view appName, const std::string& configString); + + /** move construction*/ + App(App&& other_app) = default; + /** don't allow the copy constructor*/ + App(const App& other_app) = delete; + /** move assignment*/ + App& operator=(App&& app) = default; + /** don't allow the copy assignment, the default would fail anyway since federates are not + * copyable either*/ + App& operator=(const App& app) = delete; + virtual ~App(); + + /** load a file containing interface information +@param filename the file containing the configuration and App data accepted format are JSON, +and a App format which is tab delimited or comma delimited toml file can be used load interfaces +but not app configuration +@param enableFederateInterfaceRegistration default true, if set to false will not load federate +information*/ + void loadFile(const std::string& filename, bool enableFederateInterfaceRegistration = true); + /** initialize the App federate +@details generate all the publications and organize the points, the final publication count will +be available after this time and the App will enter the initialization mode, which means it +will not be possible to add more publications calling run will automatically do this if +necessary +*/ + virtual void initialize(); + /*run the Player*/ + virtual void run(); + + /** run the Player until the specified time +@param stopTime_input the desired stop time +*/ + virtual void runTo(Time stopTime_input) = 0; + + /** finalize the Player federate*/ + virtual void finalize(); + + /** check if the Player is ready to run*/ + bool isActive() const { return !deactivated; } + /** get a const reference to the federate*/ + const CombinationFederate& accessUnderlyingFederate() const { return *fed; } + + protected: + /** load from a jsonString +@param jsonString either a JSON filename or a string containing JSON +*/ + virtual void loadJsonFile(const std::string& jsonString, + bool enableFederateInterfaceRegistration); + /** load from a jsonString and check a field named appName for configuration options +@param appName the name of the app which may be used in section of the JSON for some local +configuration +@param jsonString either a JSON filename or a string containing JSON +*/ + void loadJsonFileConfiguration(const std::string& appName, + const std::string& jsonString, + bool enableFederateInterfaceRegistration); + /** load a text file*/ + virtual void loadTextFile(const std::string& textFile); + /** actively load the specified files from the configuration*/ + void loadInputFiles(); + /** load the config options from a text parser*/ + void loadConfigOptions(AppTextParser& aparser); + + private: + void loadConfigOptions(const Json::Value& element); + /** generate the command line parser*/ + std::unique_ptr generateParser(); + /** process the command line arguments */ + void processArgs(std::unique_ptr& app, + FederateInfo& fedInfo, + std::string_view defaultAppName); + + protected: + std::shared_ptr fed; //!< the federate created for the App + Time stopTime = Time::maxVal(); //!< the time the App should stop + std::string configFileName; //!< name of the config file used for constructing the federate + std::string inputFileName; //!< the name of the app input file + bool useLocal{false}; + bool fileLoaded{false}; + bool deactivated{false}; + bool quietMode{false}; + bool helpMode{false}; + std::vector remArgs; +}; + +class AppTextParser { + public: + explicit AppTextParser(const std::string& filename); + /** run a preparse on the counting lines and extracting command strings*/ + std::vector preParseFile(const std::vector& klines); + + const std::string& configString() const { return configStr; } + /** load the next meaningful line and its linenumber*/ + bool loadNextLine(std::string& line, int& lineNumber); + void reset(); + + private: + bool mLineComment{false}; + std::ifstream filePtr; + std::string configStr; + std::string mFileName; + int currentLineNumber{0}; +}; +} // namespace helics::apps diff --git a/src/helics/apps/helicsWebServer.cpp b/src/helics/apps/helicsWebServer.cpp index e92ca62733..af1826430a 100644 --- a/src/helics/apps/helicsWebServer.cpp +++ b/src/helics/apps/helicsWebServer.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/apps/helicsWebServer.hpp b/src/helics/apps/helicsWebServer.hpp index 0cf3074e45..0c433b2380 100644 --- a/src/helics/apps/helicsWebServer.hpp +++ b/src/helics/apps/helicsWebServer.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/apps/indexPage.hpp b/src/helics/apps/indexPage.hpp index e0e691b974..474c3d1aa6 100644 --- a/src/helics/apps/indexPage.hpp +++ b/src/helics/apps/indexPage.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/apps/playerMain.cpp b/src/helics/apps/playerMain.cpp index 3318cddcee..3ee263e1d8 100644 --- a/src/helics/apps/playerMain.cpp +++ b/src/helics/apps/playerMain.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/apps/recorderMain.cpp b/src/helics/apps/recorderMain.cpp index 8828c220ff..45fc179f99 100644 --- a/src/helics/apps/recorderMain.cpp +++ b/src/helics/apps/recorderMain.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/apps/zmqBrokerServer.cpp b/src/helics/apps/zmqBrokerServer.cpp index 02db6bd674..226f5f3b61 100644 --- a/src/helics/apps/zmqBrokerServer.cpp +++ b/src/helics/apps/zmqBrokerServer.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/apps/zmqBrokerServer.hpp b/src/helics/apps/zmqBrokerServer.hpp index 769cf330ad..888a8a4352 100644 --- a/src/helics/apps/zmqBrokerServer.hpp +++ b/src/helics/apps/zmqBrokerServer.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/common/CMakeLists.txt b/src/helics/common/CMakeLists.txt index 5a43a7dfd0..4eaa0c6224 100644 --- a/src/helics/common/CMakeLists.txt +++ b/src/helics/common/CMakeLists.txt @@ -1,5 +1,5 @@ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Copyright (c) 2017-2023, Battelle Memorial Institute; Lawrence Livermore +# Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore # National Security, LLC; Alliance for Sustainable Energy, LLC. # See the top-level NOTICE for additional details. # All rights reserved. diff --git a/src/helics/common/GuardedTypes.hpp b/src/helics/common/GuardedTypes.hpp index 75debc295c..ff199e168f 100644 --- a/src/helics/common/GuardedTypes.hpp +++ b/src/helics/common/GuardedTypes.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/common/JsonBuilder.cpp b/src/helics/common/JsonBuilder.cpp index d897749979..d5bfbd0678 100644 --- a/src/helics/common/JsonBuilder.cpp +++ b/src/helics/common/JsonBuilder.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/common/JsonBuilder.hpp b/src/helics/common/JsonBuilder.hpp index 3e66c46491..c5bf052f51 100644 --- a/src/helics/common/JsonBuilder.hpp +++ b/src/helics/common/JsonBuilder.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/common/JsonGeneration.hpp b/src/helics/common/JsonGeneration.hpp index 0a5700e6de..1fef30760d 100644 --- a/src/helics/common/JsonGeneration.hpp +++ b/src/helics/common/JsonGeneration.hpp @@ -1,14 +1,14 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause */ #pragma once -#include "fmt_format.h" #include "json/json.h" #include "json/writer.h" +#include #include namespace helics { diff --git a/src/helics/common/JsonProcessingFunctions.cpp b/src/helics/common/JsonProcessingFunctions.cpp index 807c46a328..f2d98080b5 100644 --- a/src/helics/common/JsonProcessingFunctions.cpp +++ b/src/helics/common/JsonProcessingFunctions.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -16,6 +16,17 @@ SPDX-License-Identifier: BSD-3-Clause namespace helics::fileops { +bool looksLikeCommandLine(std::string_view testString) +{ + if (testString.empty()) { + return false; + } + if (testString.front() == '-') { + return true; + } + return testString.find(" -") != std::string::npos; +} + bool hasJsonExtension(std::string_view jsonString) { auto ext = jsonString.substr(jsonString.length() - 4); @@ -37,9 +48,9 @@ Json::Value loadJson(const std::string& jsonString) if (file.is_open()) { Json::Value doc; - Json::CharReaderBuilder rbuilder; + const Json::CharReaderBuilder rbuilder; std::string errs; - bool ok = Json::parseFromStream(rbuilder, file, &doc, &errs); + const bool ok = Json::parseFromStream(rbuilder, file, &doc, &errs); if (!ok) { throw(std::invalid_argument(errs.c_str())); } @@ -51,10 +62,11 @@ Json::Value loadJson(const std::string& jsonString) Json::Value loadJsonStr(std::string_view jsonString) { Json::Value doc; - Json::CharReaderBuilder rbuilder; + const Json::CharReaderBuilder rbuilder; std::string errs; auto reader = std::unique_ptr(rbuilder.newCharReader()); - bool ok = reader->parse(jsonString.data(), jsonString.data() + jsonString.size(), &doc, &errs); + const bool ok = + reader->parse(jsonString.data(), jsonString.data() + jsonString.size(), &doc, &errs); if (!ok) { throw(std::invalid_argument(errs.c_str())); } diff --git a/src/helics/common/JsonProcessingFunctions.hpp b/src/helics/common/JsonProcessingFunctions.hpp index 80ed1e08b4..e9b8b12317 100644 --- a/src/helics/common/JsonProcessingFunctions.hpp +++ b/src/helics/common/JsonProcessingFunctions.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -19,7 +19,8 @@ them using the jsoncpp library #include namespace helics::fileops { - +/** check if a string looks like a command line string*/ +bool looksLikeCommandLine(std::string_view testString); /** check if the file has a valid JSON extension*/ bool hasJsonExtension(std::string_view jsonString); diff --git a/src/helics/common/LogBuffer.cpp b/src/helics/common/LogBuffer.cpp index 58e0cbfbbf..4baab4197b 100644 --- a/src/helics/common/LogBuffer.cpp +++ b/src/helics/common/LogBuffer.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -52,8 +52,8 @@ void LogBuffer::process( return; } auto block = mBuffer.lock_shared(); - for (const auto& lm : block) { - procFunc(std::get<0>(lm), std::get<1>(lm), std::get<2>(lm)); + for (const auto& logMessage : *block) { + procFunc(std::get<0>(logMessage), std::get<1>(logMessage), std::get<2>(logMessage)); } } diff --git a/src/helics/common/LogBuffer.hpp b/src/helics/common/LogBuffer.hpp index b291795d74..75b9ac28fa 100644 --- a/src/helics/common/LogBuffer.hpp +++ b/src/helics/common/LogBuffer.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/common/TomlProcessingFunctions.cpp b/src/helics/common/TomlProcessingFunctions.cpp index a067fe323d..82ab5abe0f 100644 --- a/src/helics/common/TomlProcessingFunctions.cpp +++ b/src/helics/common/TomlProcessingFunctions.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/common/TomlProcessingFunctions.hpp b/src/helics/common/TomlProcessingFunctions.hpp index a66abb0048..d70b0024c0 100644 --- a/src/helics/common/TomlProcessingFunctions.hpp +++ b/src/helics/common/TomlProcessingFunctions.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/common/addTargets.cpp b/src/helics/common/addTargets.cpp index 471c114356..ab8a80485d 100644 --- a/src/helics/common/addTargets.cpp +++ b/src/helics/common/addTargets.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/common/addTargets.hpp b/src/helics/common/addTargets.hpp index a5092c8ba9..f89a28e266 100644 --- a/src/helics/common/addTargets.hpp +++ b/src/helics/common/addTargets.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -8,13 +8,16 @@ SPDX-License-Identifier: BSD-3-Clause #include "configFileHelpers.hpp" +#include #include #include namespace helics { + template -void addTargets(const toml::value& section, std::string targetName, Callable callback) +bool addTargets(const toml::value& section, std::string targetName, Callable callback) { + bool found{false}; toml::value uval; // There should probably be a static_assert here but there isn't a nice type trait to check that auto targets = toml::find_or(section, targetName, uval); @@ -27,20 +30,24 @@ void addTargets(const toml::value& section, std::string targetName, Callable cal } else { callback(static_cast(targets.as_string())); } + found = true; } if (targetName.back() == 's') { targetName.pop_back(); std::string target; target = toml::find_or(section, targetName, target); if (!target.empty()) { + found = true; callback(target); } } + return found; } template -void addTargets(const Json::Value& section, std::string targetName, Callable callback) +bool addTargets(const Json::Value& section, std::string targetName, Callable callback) { + bool found{false}; // There should probably be a static_assert here but there isn't a nice type trait to check that if (section.isMember(targetName)) { auto targets = section[targetName]; @@ -51,13 +58,32 @@ void addTargets(const Json::Value& section, std::string targetName, Callable cal } else { callback(targets.asString()); } + found = true; } if (targetName.back() == 's') { targetName.pop_back(); if (section.isMember(targetName)) { callback(section[targetName].asString()); + found = true; } } + return found; +} + +template +void addTargetVariations(const Block& section, + const std::string& name1, + std::string name2, + Callable callback) +{ + bool found = addTargets(section, name1 + "_" + name2, callback); + if (!found) { + found = addTargets(section, name1 + name2, callback); + } + if (!found) { + name2.front() = std::toupper(name2.front()); + addTargets(section, name1 + name2, callback); + } } void processOptions(const toml::value& section, diff --git a/src/helics/common/configFileHelpers.cpp b/src/helics/common/configFileHelpers.cpp index a3cb708da0..9dd85ec654 100644 --- a/src/helics/common/configFileHelpers.cpp +++ b/src/helics/common/configFileHelpers.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/common/configFileHelpers.hpp b/src/helics/common/configFileHelpers.hpp index 90656995ca..9f55406e95 100644 --- a/src/helics/common/configFileHelpers.hpp +++ b/src/helics/common/configFileHelpers.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/common/fmt_format.h b/src/helics/common/fmt_format.h index 03674eaa49..a57d47b940 100644 --- a/src/helics/common/fmt_format.h +++ b/src/helics/common/fmt_format.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/common/fmt_ostream.h b/src/helics/common/fmt_ostream.h index 56c91196ae..1187d12c57 100644 --- a/src/helics/common/fmt_ostream.h +++ b/src/helics/common/fmt_ostream.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/common/frozen_map.h b/src/helics/common/frozen_map.h index db92f5251f..f87ddb1529 100644 --- a/src/helics/common/frozen_map.h +++ b/src/helics/common/frozen_map.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/common/logging.cpp b/src/helics/common/logging.cpp index 2d85c95f9e..7cbefa7988 100644 --- a/src/helics/common/logging.cpp +++ b/src/helics/common/logging.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/common/logging.hpp b/src/helics/common/logging.hpp index 2c87130370..94dc22b8bb 100644 --- a/src/helics/common/logging.hpp +++ b/src/helics/common/logging.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/core/ActionMessage.cpp b/src/helics/core/ActionMessage.cpp index 4c5467e17a..bbb79c548c 100644 --- a/src/helics/core/ActionMessage.cpp +++ b/src/helics/core/ActionMessage.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -13,13 +13,13 @@ SPDX-License-Identifier: BSD-3-Clause #include "ActionMessage.hpp" #include "../common/JsonProcessingFunctions.hpp" -#include "../common/fmt_format.h" #include "flagOperations.hpp" #include "gmlc/utilities/base64.h" #include #include #include +#include #include #include #include @@ -169,7 +169,7 @@ void ActionMessage::setString(int index, std::string_view str) static inline std::uint8_t isLittleEndian() { static std::int32_t test{1}; - return (*reinterpret_cast(&test) == 1) ? std::uint8_t(1) : 0; + return (*reinterpret_cast(&test) == 1) ? static_cast(1) : 0; } // action_message_base_size= 7 header fields(7*4 bytes)+flags(2 bytes)+counter(2 bytes)+time(8 @@ -191,10 +191,10 @@ int ActionMessage::toByteArray(std::byte* data, std::size_t buffer_size) const std::byte* dataStart = data; - *data = std::byte{littleEndian}; - data[1] = std::byte(ssize >> 16U); - data[2] = std::byte((ssize >> 8U) & 0xFFU); - data[3] = std::byte(ssize & 0xFFU); + *data = static_cast(littleEndian); + data[1] = static_cast(ssize >> 16U); + data[2] = static_cast((ssize >> 8U) & 0xFFU); + data[3] = static_cast(ssize & 0xFFU); data += sizeof(uint32_t); // 4 *reinterpret_cast(data) = messageAction; data += sizeof(action_message_def::action_t); @@ -214,19 +214,19 @@ int ActionMessage::toByteArray(std::byte* data, std::size_t buffer_size) const data += sizeof(uint16_t); // 28 *reinterpret_cast(data) = sequenceID; data += sizeof(int32_t); // 32 - auto bt = actionTime.getBaseTimeCode(); - std::memcpy(data, &(bt), sizeof(Time::baseType)); + auto baseTimeCode = actionTime.getBaseTimeCode(); + std::memcpy(data, &(baseTimeCode), sizeof(Time::baseType)); data += sizeof(Time::baseType); // 40 if (messageAction == CMD_TIME_REQUEST) { - bt = Te.getBaseTimeCode(); - std::memcpy(data, &(bt), sizeof(Time::baseType)); + baseTimeCode = Te.getBaseTimeCode(); + std::memcpy(data, &(baseTimeCode), sizeof(Time::baseType)); data += sizeof(Time::baseType); - bt = Tdemin.getBaseTimeCode(); - std::memcpy(data, &(bt), sizeof(Time::baseType)); + baseTimeCode = Tdemin.getBaseTimeCode(); + std::memcpy(data, &(baseTimeCode), sizeof(Time::baseType)); data += sizeof(Time::baseType); - bt = Tso.getBaseTimeCode(); - std::memcpy(data, &(bt), sizeof(Time::baseType)); + baseTimeCode = Tso.getBaseTimeCode(); + std::memcpy(data, &(baseTimeCode), sizeof(Time::baseType)); data += sizeof(Time::baseType); *data = std::byte{0}; ++data; @@ -242,7 +242,7 @@ int ActionMessage::toByteArray(std::byte* data, std::size_t buffer_size) const // *data = 0; // ++data; // } else { - *data = std::byte(stringData.size()); + *data = static_cast(stringData.size()); ++data; ssize += action_message_base_size; for (const auto& str : stringData) { @@ -287,9 +287,9 @@ std::string ActionMessage::to_string() const if (checkActionFlag(*this, use_json_serialization_flag)) { data = to_json_string(); } else { - auto sz = serializedByteCount(); - data.resize(sz); - toByteArray(reinterpret_cast(&(data[0])), sz); + auto size = serializedByteCount(); + data.resize(size); + toByteArray(reinterpret_cast(data.data()), size); } return data; } @@ -352,9 +352,9 @@ std::string ActionMessage::packetize_json() const void ActionMessage::packetize(std::string& data) const { - auto sz = serializedByteCount(); - data.resize(sizeof(uint32_t) + static_cast(sz)); - toByteArray(reinterpret_cast(&(data[4])), sz); + auto size = serializedByteCount(); + data.resize(sizeof(uint32_t) + static_cast(size)); + toByteArray(reinterpret_cast(&(data[4])), size); data[0] = LEADING_CHAR; // now generate a length header @@ -369,31 +369,31 @@ void ActionMessage::packetize(std::string& data) const std::vector ActionMessage::to_vector() const { std::vector data; - auto sz = serializedByteCount(); - data.resize(sz); - toByteArray(reinterpret_cast(data.data()), sz); + auto size = serializedByteCount(); + data.resize(size); + toByteArray(reinterpret_cast(data.data()), size); return data; } void ActionMessage::to_vector(std::vector& data) const { - auto sz = serializedByteCount(); - data.resize(sz); - toByteArray(reinterpret_cast(data.data()), sz); + auto size = serializedByteCount(); + data.resize(size); + toByteArray(reinterpret_cast(data.data()), size); } void ActionMessage::to_string(std::string& data) const { - auto sz = serializedByteCount(); - data.resize(sz); - toByteArray(reinterpret_cast(&(data[0])), sz); + auto size = serializedByteCount(); + data.resize(size); + toByteArray(reinterpret_cast(data.data()), size); } template inline void swap_bytes(std::uint8_t* data) { - for (std::size_t i = 0, end = DataSize / 2; i < end; ++i) { - std::swap(data[i], data[DataSize - i - 1]); + for (std::size_t ii = 0, end = DataSize / 2; ii < end; ++ii) { + std::swap(data[ii], data[DataSize - ii - 1]); } } @@ -405,7 +405,7 @@ std::size_t ActionMessage::fromByteArray(const std::byte* data, std::size_t buff messageAction = CMD_INVALID; return (0); } - if (data[0] == std::byte(LEADING_CHAR)) { + if (data[0] == static_cast(LEADING_CHAR)) { auto res = depacketize(data, buffer_size); if (res > 0) { return static_cast(res); @@ -415,14 +415,14 @@ std::size_t ActionMessage::fromByteArray(const std::byte* data, std::size_t buff if (data[0] == std::byte{'{'}) { return 0; } - std::size_t sz = 256 * 256 * (std::to_integer(data[1])) + - 256 * std::to_integer(data[2]) + std::to_integer(data[3]); - tsize += sz; + const std::size_t size = 256ULL * 256ULL * (std::to_integer(data[1])) + + 256ULL * std::to_integer(data[2]) + std::to_integer(data[3]); + tsize += size; if (buffer_size < tsize) { messageAction = CMD_INVALID; return (0); } - bool swap = (data[0] != std::byte{littleEndian}); + const bool swap = (data[0] != static_cast(littleEndian)); data += sizeof(uint32_t); memcpy(&messageAction, data, sizeof(action_message_def::action_t)); // messageAction = *reinterpret_cast (data); @@ -480,9 +480,9 @@ std::size_t ActionMessage::fromByteArray(const std::byte* data, std::size_t buff Tdemin = timeZero; Tso = timeZero; } - if (sz > 0) { - payload.assign(data, sz); - data += sz; + if (size > 0) { + payload.assign(data, size); + data += size; } auto stringCount = std::to_integer(*data); ++data; @@ -542,7 +542,7 @@ std::size_t ActionMessage::fromByteArray(const std::byte* data, std::size_t buff std::size_t ActionMessage::depacketize(const void* data, std::size_t buffer_size) { const auto* bytes = reinterpret_cast(data); - if (bytes[0] != std::byte(LEADING_CHAR)) { + if (bytes[0] != static_cast(LEADING_CHAR)) { return 0; } if (buffer_size < 6) { @@ -556,10 +556,10 @@ std::size_t ActionMessage::depacketize(const void* data, std::size_t buffer_size if (buffer_size < (static_cast(message_size) + 2)) { return 0; } - if (bytes[message_size] != std::byte(TAIL_CHAR1)) { + if (bytes[message_size] != static_cast(TAIL_CHAR1)) { return 0; } - if (bytes[message_size + 1] != std::byte(TAIL_CHAR2)) { + if (bytes[message_size + 1] != static_cast(TAIL_CHAR2)) { return 0; } @@ -620,7 +620,7 @@ bool ActionMessage::from_json_string(std::string_view data) std::size_t ActionMessage::from_vector(const std::vector& data) { - std::size_t bytesUsed = + const std::size_t bytesUsed = fromByteArray(reinterpret_cast(data.data()), data.size()); if (bytesUsed == 0 && !data.empty() && data.front() == '{') { if (from_json_string(std::string_view(data.data(), data.size()))) { @@ -845,8 +845,8 @@ std::string errorMessageString(const ActionMessage& command) std::string prettyPrintString(const ActionMessage& command) { - std::string ret(actionMessageType(command.action())); - if (std::string_view(ret) == std::string_view(unknownStr)) { + std::string ret{actionMessageType(command.action())}; + if (std::string_view{ret} == std::string_view{unknownStr}) { ret.push_back(' '); ret.append(std::to_string(static_cast(command.action()))); return ret; @@ -916,18 +916,18 @@ std::string prettyPrintString(const ActionMessage& command) return ret; } -std::ostream& operator<<(std::ostream& os, const ActionMessage& command) +std::ostream& operator<<(std::ostream& out, const ActionMessage& command) { - os << prettyPrintString(command); - return os; + out << prettyPrintString(command); + return out; } -int appendMessage(ActionMessage& m, const ActionMessage& newMessage) +int appendMessage(ActionMessage& multiMessage, const ActionMessage& newMessage) { - if (m.action() == CMD_MULTI_MESSAGE) { - if (m.counter < 255) { - m.setString(m.counter++, newMessage.to_string()); - return m.counter; + if (multiMessage.action() == CMD_MULTI_MESSAGE) { + if (multiMessage.counter < 255) { + multiMessage.setString(multiMessage.counter++, newMessage.to_string()); + return multiMessage.counter; } } return (-1); diff --git a/src/helics/core/ActionMessage.hpp b/src/helics/core/ActionMessage.hpp index 27e39fdd8a..29c904a94f 100644 --- a/src/helics/core/ActionMessage.hpp +++ b/src/helics/core/ActionMessage.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -26,19 +26,19 @@ constexpr int typeOutStringLoc{1}; constexpr int32_t cmd_info_basis{65536}; -/** class defining the primary message object used in HELICS */ +/** class defining the primary multiMessage object used in HELICS */ class ActionMessage { // need to try to make sure this object is under 64 bytes in size to fit in cache lines NOT // there yet private: action_message_def::action_t messageAction{CMD_IGNORE}; // 4 -- command public: - int32_t messageID{0}; //!< 8 -- message ID for a variety of purposes + int32_t messageID{0}; //!< 8 -- multiMessage ID for a variety of purposes GlobalFederateId source_id{parent_broker_id}; //!< 12 -- for federate_id or route_id InterfaceHandle source_handle{}; //!< 16 -- for local handle or local code - GlobalFederateId dest_id{parent_broker_id}; //!< 20 fed_id for a targeted message - InterfaceHandle dest_handle{}; //!< 24 local handle for a targeted message - uint16_t counter{0}; //!< 26 counter for filter tracking or message counter + GlobalFederateId dest_id{parent_broker_id}; //!< 20 fed_id for a targeted multiMessage + InterfaceHandle dest_handle{}; //!< 24 local handle for a targeted multiMessage + uint16_t counter{0}; //!< 26 counter for filter tracking or multiMessage counter uint16_t flags{0}; //!< 28 set of messageFlags uint32_t sequenceID{0}; //!< 32 a sequence number for ordering Time actionTime{timeZero}; //!< 40 the time an action took place or will take place //32 @@ -80,11 +80,12 @@ class ActionMessage { /** move assignment*/ ActionMessage& operator=(ActionMessage&& act) noexcept; /** move assignment from message data into the actionMessage - @details take ownership of the message and move the contents out then destroy the message shell + @details take ownership of the message and move the contents out then destroy the + message shell @param message the message to move. */ ActionMessage& operator=(std::unique_ptr message) noexcept; - /** get the action of the message*/ + /** get the action of the multiMessage*/ action_message_def::action_t action() const noexcept { return messageAction; } /** set the action*/ void setAction(action_message_def::action_t newAction); @@ -163,7 +164,7 @@ class ActionMessage { int32_t getExtraDestData() const { return source_handle.baseValue(); } // functions that convert to and from a byte stream - /** generate a size of the message in bytes if it were to be serialized*/ + /** generate a size of the multiMessage in bytes if it were to be serialized*/ int serializedByteCount() const; /** convert a command to a raw data bytes @param[out] data pointer to memory to store the command @@ -177,11 +178,11 @@ class ActionMessage { std::string to_string() const; /** convert to a json string*/ std::string to_json_string() const; - /** packetize the message with a simple header and tail sequence + /** packetize the multiMessage with a simple header and tail sequence */ std::string packetize() const; void packetize(std::string& data) const; - /** packetize the message with a simple header and tail sequence using json serialization + /** packetize the multiMessage with a simple header and tail sequence using json serialization */ std::string packetize_json() const; /** convert to a byte vector using a reference*/ @@ -212,13 +213,13 @@ inline bool operator<(const ActionMessage& cmd, const ActionMessage& cmd2) return (cmd.actionTime < cmd2.actionTime); } -/** create a new message object that copies all the information from the ActionMessage into newly - * allocated memory for the message +/** create a new multiMessage object that copies all the information from the ActionMessage into + * newly allocated memory for the multiMessage */ std::unique_ptr createMessageFromCommand(const ActionMessage& cmd); -/** create a new message object that moves all the information from the ActionMessage into newly - * allocated memory for the message +/** create a new multiMessage object that moves all the information from the ActionMessage into + * newly allocated memory for the multiMessage */ std::unique_ptr createMessageFromCommand(ActionMessage&& cmd); @@ -347,13 +348,13 @@ std::string prettyPrintString(const ActionMessage& command); /** stream operator for a command */ -std::ostream& operator<<(std::ostream& os, const ActionMessage& command); +std::ostream& operator<<(std::ostream& out, const ActionMessage& command); -/** append a message to multi message container -@param m the message to add the extra message to -@param newMessage the message to append -@return the integer location of the message in the stringData section*/ -int appendMessage(ActionMessage& m, const ActionMessage& newMessage); +/** append a multiMessage to multi multiMessage container +@param multiMessage the multiMessage to add the extra multiMessage to +@param newMessage the multiMessage to append +@return the integer location of the multiMessage in the stringData section*/ +int appendMessage(ActionMessage& multiMessage, const ActionMessage& newMessage); /** generate a string representing an error from an ActionMessage @param command the command to generate the error string for diff --git a/src/helics/core/ActionMessageDefintions.hpp b/src/helics/core/ActionMessageDefintions.hpp index 63d5763de7..38b6bff8fa 100644 --- a/src/helics/core/ActionMessageDefintions.hpp +++ b/src/helics/core/ActionMessageDefintions.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/core/AsyncTimeCoordinator.cpp b/src/helics/core/AsyncTimeCoordinator.cpp index 2a88f3d93d..cae859bad7 100644 --- a/src/helics/core/AsyncTimeCoordinator.cpp +++ b/src/helics/core/AsyncTimeCoordinator.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -7,12 +7,12 @@ SPDX-License-Identifier: BSD-3-Clause #include "AsyncTimeCoordinator.hpp" -#include "../common/fmt_format.h" #include "flagOperations.hpp" #include "helics_definitions.hpp" #include "json/json.h" #include +#include #include #include #include diff --git a/src/helics/core/AsyncTimeCoordinator.hpp b/src/helics/core/AsyncTimeCoordinator.hpp index c179421e86..39c46df7bc 100644 --- a/src/helics/core/AsyncTimeCoordinator.hpp +++ b/src/helics/core/AsyncTimeCoordinator.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/core/BaseTimeCoordinator.cpp b/src/helics/core/BaseTimeCoordinator.cpp index b0dc4a2ffc..d6cee0d982 100644 --- a/src/helics/core/BaseTimeCoordinator.cpp +++ b/src/helics/core/BaseTimeCoordinator.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -7,12 +7,12 @@ SPDX-License-Identifier: BSD-3-Clause #include "BaseTimeCoordinator.hpp" -#include "../common/fmt_format.h" #include "flagOperations.hpp" #include "helics_definitions.hpp" #include "json/json.h" #include +#include #include #include #include @@ -51,12 +51,12 @@ void BaseTimeCoordinator::enteringExecMode(IterationRequest /*mode*/) updateTimeFactors(); auto res = dependencies.checkForIssues(false); if (res.first != 0) { - ActionMessage ge(CMD_GLOBAL_ERROR); - ge.dest_id = parent_broker_id; - ge.source_id = mSourceId; - ge.messageID = res.first; - ge.payload = res.second; - sendMessageFunction(ge); + ActionMessage error(CMD_GLOBAL_ERROR); + error.dest_id = parent_broker_id; + error.source_id = mSourceId; + error.messageID = res.first; + error.payload = res.second; + sendMessageFunction(error); return; } } @@ -387,12 +387,12 @@ TimeProcessingResult BaseTimeCoordinator::processTimeMessage(const ActionMessage if (procRes == TimeProcessingResult::PROCESSED_AND_CHECK) { auto checkRes = dependencies.checkForIssues(false); if (checkRes.first != 0) { - ActionMessage ge(CMD_GLOBAL_ERROR); - ge.dest_id = parent_broker_id; - ge.source_id = mSourceId; - ge.messageID = checkRes.first; - ge.payload = checkRes.second; - sendMessageFunction(ge); + ActionMessage error(CMD_GLOBAL_ERROR); + error.dest_id = parent_broker_id; + error.source_id = mSourceId; + error.messageID = checkRes.first; + error.payload = checkRes.second; + sendMessageFunction(error); } } return procRes; diff --git a/src/helics/core/BaseTimeCoordinator.hpp b/src/helics/core/BaseTimeCoordinator.hpp index 34e2b59d03..ce5e4093d7 100644 --- a/src/helics/core/BaseTimeCoordinator.hpp +++ b/src/helics/core/BaseTimeCoordinator.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/core/BasicHandleInfo.cpp b/src/helics/core/BasicHandleInfo.cpp index 5ad09d7796..0aca661e0f 100644 --- a/src/helics/core/BasicHandleInfo.cpp +++ b/src/helics/core/BasicHandleInfo.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/core/BasicHandleInfo.hpp b/src/helics/core/BasicHandleInfo.hpp index 4813db168c..c8d2ccc6d0 100644 --- a/src/helics/core/BasicHandleInfo.hpp +++ b/src/helics/core/BasicHandleInfo.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/core/Broker.hpp b/src/helics/core/Broker.hpp index 2389d549a3..18d013f9e4 100644 --- a/src/helics/core/Broker.hpp +++ b/src/helics/core/Broker.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/core/BrokerBase.cpp b/src/helics/core/BrokerBase.cpp index bc54e0e097..bcd4bb7c4a 100644 --- a/src/helics/core/BrokerBase.cpp +++ b/src/helics/core/BrokerBase.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -7,7 +7,6 @@ SPDX-License-Identifier: BSD-3-Clause #include "BrokerBase.hpp" -#include "../common/fmt_format.h" #include "../common/logging.hpp" #include "AsyncTimeCoordinator.hpp" #include "ForwardingTimeCoordinator.hpp" @@ -24,6 +23,8 @@ SPDX-License-Identifier: BSD-3-Clause #include "helicsCLI11.hpp" #include "loggingHelper.hpp" +#include + #ifndef HELICS_DISABLE_ASIO # include "gmlc/networking/AsioContextManager.h" @@ -43,22 +44,23 @@ SPDX-License-Identifier: BSD-3-Clause static inline std::string genId() { - std::string nm = gmlc::utilities::randomString(24); + std::string newid = gmlc::utilities::randomString(24); - nm[0] = '-'; - nm[6] = '-'; - nm[12] = '-'; - nm[18] = '-'; + newid[0] = '-'; + newid[6] = '-'; + newid[12] = '-'; + newid[18] = '-'; #ifdef _WIN32 - std::string pid_str = std::to_string(GetCurrentProcessId()) + nm; + std::string pid_str = std::to_string(GetCurrentProcessId()) + newid; #else - std::string pid_str = std::to_string(getpid()) + nm; + std::string pid_str = std::to_string(getpid()) + newid; #endif return pid_str; } namespace helics { + BrokerBase::BrokerBase(bool DisableQueue) noexcept: queueDisabled(DisableQueue), mLogManager(std::make_shared()) { @@ -357,10 +359,10 @@ void BrokerBase::configureBase() timeCoord->setMessageSender([this](const ActionMessage& msg) { addActionMessage(msg); }); timeCoord->setRestrictivePolicy(restrictive_time_policy); - mLogManager->setTransmitCallback([this](ActionMessage&& m) { + mLogManager->setTransmitCallback([this](ActionMessage&& message) { if (getBrokerState() < BrokerState::TERMINATING) { - m.source_id = global_id.load(); - addActionMessage(std::move(m)); + message.source_id = global_id.load(); + addActionMessage(std::move(message)); } }); mLogManager->initializeLogging(identifier); @@ -376,7 +378,7 @@ bool BrokerBase::sendToLogger(GlobalFederateId federateID, std::string_view message, bool fromRemote) const { - bool noID = (federateID != global_id.load()) || (!name.empty() && name.back() == ']'); + const bool noID = (federateID != global_id.load()) || (!name.empty() && name.back() == ']'); std::string header; if (noID) { @@ -384,13 +386,13 @@ bool BrokerBase::sendToLogger(GlobalFederateId federateID, } else { std::string timeString; - Time currentTime = getSimulationTime(); + const Time currentTime = getSimulationTime(); if (currentTime <= mInvalidSimulationTime || currentTime >= cHelicsBigNumber) { timeString.push_back('['); timeString.append(brokerStateName(getBrokerState())); timeString.push_back(']'); } else { - timeString = fmt::format("[t={}]", currentTime); + timeString = fmt::format("[t={}]", static_cast(currentTime)); } header = fmt::format("{} ({}){}", name, federateID.baseValue(), timeString); } @@ -436,11 +438,11 @@ void BrokerBase::setErrorState(int eCode, std::string_view estring) } if (errorDelay <= timeZero || eCode == HELICS_ERROR_TERMINATED || eCode == HELICS_ERROR_USER_ABORT) { - ActionMessage halt(CMD_USER_DISCONNECT, global_id.load(), global_id.load()); + const ActionMessage halt(CMD_USER_DISCONNECT, global_id.load(), global_id.load()); addActionMessage(halt); } else { errorTimeStart = std::chrono::steady_clock::now(); - ActionMessage echeck(CMD_ERROR_CHECK, global_id.load(), global_id.load()); + const ActionMessage echeck(CMD_ERROR_CHECK, global_id.load(), global_id.load()); addActionMessage(echeck); } } @@ -488,7 +490,7 @@ std::pair> LOG_SUMMARY(global_broker_id_local, identifier, " received terminate instruction via command instruction") - ActionMessage udisconnect(CMD_USER_DISCONNECT); + const ActionMessage udisconnect(CMD_USER_DISCONNECT); addActionMessage(udisconnect); } } else if (res[0] == "echo") { @@ -580,35 +582,35 @@ void BrokerBase::setLogLevels(int32_t consoleLevel, int32_t fileLevel) maxLogLevel.store(mLogManager->getMaxLevel()); } -void BrokerBase::addActionMessage(const ActionMessage& m) +void BrokerBase::addActionMessage(const ActionMessage& message) { - if (isPriorityCommand(m)) { - actionQueue.pushPriority(m); + if (isPriorityCommand(message)) { + actionQueue.pushPriority(message); } else { // just route to the general queue; - actionQueue.push(m); + actionQueue.push(message); } } -void BrokerBase::addActionMessage(ActionMessage&& m) +void BrokerBase::addActionMessage(ActionMessage&& message) { - if (isPriorityCommand(m)) { - actionQueue.emplacePriority(std::move(m)); + if (isPriorityCommand(message)) { + actionQueue.emplacePriority(std::move(message)); } else { // just route to the general queue; - actionQueue.emplace(std::move(m)); + actionQueue.emplace(std::move(message)); } } -void BrokerBase::addActionMessage(ActionMessage&& m) const +void BrokerBase::addActionMessage(ActionMessage&& message) const { // the queue is thread safe so can be run in a const situation without possibility of issues auto& lQueue = const_cast(actionQueue); - if (isPriorityCommand(m)) { - lQueue.emplacePriority(std::move(m)); + if (isPriorityCommand(message)) { + lQueue.emplacePriority(std::move(message)); } else { // just route to the general queue; - lQueue.emplace(std::move(m)); + lQueue.emplace(std::move(message)); } } @@ -619,10 +621,10 @@ static bool haltTimer(activeProtector& active, asio::steady_timer& tickTimer) { bool TimerRunning = true; { - auto p = active.lock(); - if (p->second) { - p->first = false; - p.unlock(); + auto protector = active.lock(); + if (protector->second) { + protector->first = false; + protector.unlock(); auto cancelled = tickTimer.cancel(); if (cancelled == 0) { TimerRunning = false; @@ -631,17 +633,17 @@ static bool haltTimer(activeProtector& active, asio::steady_timer& tickTimer) TimerRunning = false; } } - int ii = 0; + int timerLoopCount = 0; while (TimerRunning) { - if (ii % 4 != 3) { + if (timerLoopCount % 4 != 3) { std::this_thread::yield(); } else { std::this_thread::sleep_for(std::chrono::milliseconds(40)); } auto res = active.load(); TimerRunning = res.second; - ++ii; - if (ii == 100) { + ++timerLoopCount; + if (timerLoopCount == 100) { // assume the timer was never started so just exit and hope it doesn't somehow get // called later and generate a seg fault. return false; @@ -653,8 +655,8 @@ static bool haltTimer(activeProtector& active, asio::steady_timer& tickTimer) static void timerTickHandler(BrokerBase* bbase, activeProtector& active, const std::error_code& error) { - auto p = active.lock(); - if (p->first) { + auto timeProtector = active.lock(); + if (timeProtector->first) { if (error != asio::error::operation_aborted) { try { bbase->addActionMessage(CMD_TICK); @@ -663,12 +665,12 @@ static void std::cerr << "exception caught from addActionMessage" << e.what() << std::endl; } } else { - ActionMessage M(CMD_TICK); - setActionFlag(M, error_flag); - bbase->addActionMessage(M); + ActionMessage tick(CMD_TICK); + setActionFlag(tick, error_flag); + bbase->addActionMessage(tick); } } - p->second = false; + timeProtector->second = false; } #endif @@ -692,8 +694,8 @@ void BrokerBase::queueProcessingLoop() asio::steady_timer ticktimer(serv->getBaseContext()); activeProtector active(true, false); - auto timerCallback = [this, &active](const std::error_code& ec) { - timerTickHandler(this, active, ec); + auto timerCallback = [this, &active](const std::error_code& errorCode) { + timerTickHandler(this, active, errorCode); }; if (tickTimer > timeZero && !disable_timer) { if (tickTimer < Time(0.5)) { @@ -761,8 +763,8 @@ void BrokerBase::queueProcessingLoop() // deal with error state timeout if (brokerState.load() == BrokerState::CONNECTED_ERROR) { auto ctime = std::chrono::steady_clock::now(); - auto td = ctime - errorTimeStart; - if (td >= errorDelay.to_ms()) { + auto timeDiff = ctime - errorTimeStart; + if (timeDiff >= errorDelay.to_ms()) { command.setAction(CMD_USER_DISCONNECT); addActionMessage(command); } else { @@ -816,13 +818,13 @@ void BrokerBase::queueProcessingLoop() case CMD_ERROR_CHECK: if (brokerState.load() == BrokerState::CONNECTED_ERROR) { auto ctime = std::chrono::steady_clock::now(); - auto td = ctime - errorTimeStart; - if (td > errorDelay.to_ms()) { + auto timeDiff = ctime - errorTimeStart; + if (timeDiff > errorDelay.to_ms()) { command.setAction(CMD_USER_DISCONNECT); addActionMessage(command); } else { #ifndef HELICS_DISABLE_ASIO - if (tickTimer > td * 2 || disable_timer) { + if (tickTimer > timeDiff * 2 || disable_timer) { std::this_thread::sleep_for(std::chrono::milliseconds(200)); addActionMessage(command); } @@ -970,13 +972,13 @@ action_message_def::action_t BrokerBase::commandProcessor(ActionMessage& command for (int ii = 0; ii < command.counter; ++ii) { ActionMessage NMess; NMess.from_string(command.getString(ii)); - auto V = commandProcessor(NMess); - if (V != CMD_IGNORE) { + auto commandAction = commandProcessor(NMess); + if (commandAction != CMD_IGNORE) { // overwrite the abort command but ignore ticks in a multi-message context // they shouldn't be there - if (V != CMD_TICK) { + if (commandAction != CMD_TICK) { command = NMess; - return V; + return commandAction; } } } diff --git a/src/helics/core/BrokerBase.hpp b/src/helics/core/BrokerBase.hpp index 3af9df4075..643bd6e2a3 100644 --- a/src/helics/core/BrokerBase.hpp +++ b/src/helics/core/BrokerBase.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -188,9 +188,9 @@ class BrokerBase { virtual void configureBase(); /** add an action Message to the process queue*/ - void addActionMessage(const ActionMessage& m); + void addActionMessage(const ActionMessage& message); /** move a action Message into the commandQueue*/ - void addActionMessage(ActionMessage&& m); + void addActionMessage(ActionMessage&& message); /** set the logging callback function @param logFunction a function with a signature of void(int level, std::string_view identifier, @@ -228,7 +228,7 @@ class BrokerBase { /** move a action Message into the commandQueue allow const in this case to allow messages to be sent internally in a few specific instances*/ - void addActionMessage(ActionMessage&& m) const; + void addActionMessage(ActionMessage&& message) const; protected: /** check whether a code contains a specific reason*/ diff --git a/src/helics/core/BrokerFactory.cpp b/src/helics/core/BrokerFactory.cpp index eeb344d2a0..e9961221b9 100644 --- a/src/helics/core/BrokerFactory.cpp +++ b/src/helics/core/BrokerFactory.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -15,10 +15,10 @@ SPDX-License-Identifier: BSD-3-Clause #include "gmlc/concurrency/DelayedDestructor.hpp" #include "gmlc/concurrency/SearchableObjectHolder.hpp" #include "gmlc/concurrency/TripWire.hpp" -#include "helics/common/fmt_format.h" #include "helics/helics-config.h" #include +#include #include #include @@ -29,17 +29,17 @@ namespace helics::BrokerFactory { things that call it so it needs to be a static member of function call*/ class MasterBrokerBuilder { public: - using BuildT = std::tuple>; + using BuilderData = std::tuple>; - static void addBuilder(std::shared_ptr cb, std::string_view name, int code) + static void addBuilder(std::shared_ptr builder, std::string_view name, int code) { - instance()->builders.emplace_back(code, name, std::move(cb)); + instance()->builders.emplace_back(code, name, std::move(builder)); } static const std::shared_ptr& getBuilder(int code) { - for (auto& bb : instance()->builders) { - if (std::get<0>(bb) == code) { - return std::get<2>(bb); + for (auto& builder : instance()->builders) { + if (std::get<0>(builder) == code) { + return std::get<2>(builder); } } throw(HelicsException("core type is not available")); @@ -56,9 +56,9 @@ class MasterBrokerBuilder { static const std::shared_ptr& getDefaultBuilder() { const auto& blder = instance(); - for (auto& bb : instance()->builders) { - if (std::get<0>(bb) <= 10) { - return std::get<2>(bb); + for (auto& builder : instance()->builders) { + if (std::get<0>(builder) <= 10) { + return std::get<2>(builder); } } if (blder->builders.empty()) { @@ -69,7 +69,7 @@ class MasterBrokerBuilder { static const std::shared_ptr& instance() { - static std::shared_ptr iptr(new MasterBrokerBuilder()); + static const std::shared_ptr iptr(new MasterBrokerBuilder()); return iptr; } @@ -77,12 +77,12 @@ class MasterBrokerBuilder { /** private constructor since we only really want one of them accessed through the instance static member*/ MasterBrokerBuilder() = default; - std::vector builders; //!< container for the builders + std::vector builders; //!< container for the builders }; -void defineBrokerBuilder(std::shared_ptr cb, std::string_view name, int code) +void defineBrokerBuilder(std::shared_ptr builder, std::string_view name, int code) { - MasterBrokerBuilder::addBuilder(std::move(cb), name, code); + MasterBrokerBuilder::addBuilder(std::move(builder), name, code); } std::shared_ptr makeBroker(CoreType type, std::string_view name) @@ -110,8 +110,7 @@ std::shared_ptr throw(helics::RegistrationFailure("unable to create broker")); } broker->configure(configureString); - bool reg = registerBroker(broker, type); - if (!reg) { + if (!registerBroker(broker, type)) { throw(helics::RegistrationFailure("unable to register broker")); } broker->connect(); @@ -128,8 +127,7 @@ std::shared_ptr create(CoreType type, std::string_view brokerName, int a { auto broker = makeBroker(type, brokerName); broker->configureFromArgs(argc, argv); - bool reg = registerBroker(broker, type); - if (!reg) { + if (!registerBroker(broker, type)) { throw(helics::RegistrationFailure("unable to register broker")); } broker->connect(); @@ -147,8 +145,7 @@ std::shared_ptr { auto broker = makeBroker(type, brokerName); broker->configureFromVector(std::move(args)); - bool reg = registerBroker(broker, type); - if (!reg) { + if (!registerBroker(broker, type)) { throw(helics::RegistrationFailure("unable to register broker")); } broker->connect(); @@ -309,7 +306,7 @@ void unregisterBroker(std::string_view name) void addAssociatedBrokerType(std::string_view name, CoreType type) { - std::string sname{name}; + const std::string sname{name}; searchableBrokers.addType(sname, type); addExtraTypes(sname, type); } diff --git a/src/helics/core/BrokerFactory.hpp b/src/helics/core/BrokerFactory.hpp index 077175ff48..f0c287c2a0 100644 --- a/src/helics/core/BrokerFactory.hpp +++ b/src/helics/core/BrokerFactory.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -42,7 +42,9 @@ namespace BrokerFactory { }; /** define a new Broker Builder from the builder give a name and build code*/ - void defineBrokerBuilder(std::shared_ptr cb, std::string_view name, int code); + void defineBrokerBuilder(std::shared_ptr builder, + std::string_view name, + int code); /** template function to create a builder and link it into the library*/ template diff --git a/src/helics/core/CMakeLists.txt b/src/helics/core/CMakeLists.txt index dd1d4bacab..134d6dcbeb 100644 --- a/src/helics/core/CMakeLists.txt +++ b/src/helics/core/CMakeLists.txt @@ -1,5 +1,5 @@ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Copyright (c) 2017-2023, Battelle Memorial Institute; Lawrence Livermore +# Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore # National Security, LLC; Alliance for Sustainable Energy, LLC. # See the top-level NOTICE for additional details. # All rights reserved. diff --git a/src/helics/core/CommonCore.cpp b/src/helics/core/CommonCore.cpp index 76b8ccb28b..6612091264 100644 --- a/src/helics/core/CommonCore.cpp +++ b/src/helics/core/CommonCore.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -9,7 +9,6 @@ SPDX-License-Identifier: BSD-3-Clause #include "../common/JsonGeneration.hpp" #include "../common/JsonProcessingFunctions.hpp" #include "../common/LogBuffer.hpp" -#include "../common/fmt_format.h" #include "../common/logging.hpp" #include "ActionMessage.hpp" #include "BaseTimeCoordinator.hpp" @@ -40,6 +39,7 @@ SPDX-License-Identifier: BSD-3-Clause #include #include #include +#include #include #include #include @@ -55,12 +55,12 @@ namespace helics { const std::string& stateString(OperatingState state) { - static const std::string c1{"connected"}; + static const std::string connected{"connected"}; static const std::string estate{"error"}; static const std::string dis{"disconnected"}; switch (state) { case OperatingState::OPERATING: - return c1; + return connected; case OperatingState::DISCONNECTED: return dis; case OperatingState::ERROR_STATE: @@ -70,12 +70,12 @@ const std::string& stateString(OperatingState state) } // timeoutMon is a unique_ptr -CommonCore::CommonCore() noexcept: timeoutMon(new TimeoutMonitor) {} +CommonCore::CommonCore() noexcept: timeoutMon(std::make_unique()) {} -CommonCore::CommonCore(bool /*arg*/) noexcept: timeoutMon(new TimeoutMonitor) {} +CommonCore::CommonCore(bool /*arg*/) noexcept: timeoutMon(std::make_unique()) {} CommonCore::CommonCore(std::string_view coreName): - BrokerBase(coreName), timeoutMon(new TimeoutMonitor) + BrokerBase(coreName), timeoutMon(std::make_unique()) { } @@ -136,31 +136,31 @@ bool CommonCore::connect() if (cBrokerState >= BrokerState::CONFIGURED) { if (transitionBrokerState(BrokerState::CONFIGURED, BrokerState::CONNECTING)) { timeoutMon->setTimeout(timeout.to_ms()); - bool res = brokerConnect(); + const bool res = brokerConnect(); if (res) { // now register this core object as a broker - ActionMessage m(CMD_REG_BROKER); - m.source_id = GlobalFederateId{}; - m.name(getIdentifier()); - m.setStringData(getAddress()); + ActionMessage reg(CMD_REG_BROKER); + reg.source_id = GlobalFederateId{}; + reg.name(getIdentifier()); + reg.setStringData(getAddress()); if (!brokerKey.empty()) { - m.setString(1, brokerKey); + reg.setString(1, brokerKey); } - setActionFlag(m, core_flag); + setActionFlag(reg, core_flag); if (useJsonSerialization) { - setActionFlag(m, use_json_serialization_flag); + setActionFlag(reg, use_json_serialization_flag); } if (no_ping) { - setActionFlag(m, slow_responding_flag); + setActionFlag(reg, slow_responding_flag); } if (observer) { - setActionFlag(m, observer_flag); + setActionFlag(reg, observer_flag); } - transmit(parent_route_id, m); + transmit(parent_route_id, reg); setBrokerState(BrokerState::CONNECTED); disconnection.activate(); } else { @@ -228,7 +228,7 @@ void CommonCore::processDisconnect(bool skipUnregister) void CommonCore::disconnect() { - ActionMessage udisconnect(CMD_USER_DISCONNECT); + const ActionMessage udisconnect(CMD_USER_DISCONNECT); addActionMessage(udisconnect); int cnt{0}; while (!waitForDisconnect(std::chrono::milliseconds(200))) { @@ -377,29 +377,29 @@ void CommonCore::globalError(LocalFederateId federateID, std::string_view errorString) { if (federateID == gLocalCoreId) { - ActionMessage m(CMD_GLOBAL_ERROR); - m.source_id = getGlobalId(); - m.messageID = errorCode; - m.payload = errorString; - addActionMessage(m); + ActionMessage error(CMD_GLOBAL_ERROR); + error.source_id = getGlobalId(); + error.messageID = errorCode; + error.payload = errorString; + addActionMessage(error); return; } auto* fed = getFederateAt(federateID); if (fed == nullptr) { throw(InvalidIdentifier("federateID not valid error")); } - ActionMessage m(CMD_GLOBAL_ERROR); - m.source_id = fed->global_id.load(); - m.messageID = errorCode; - m.payload = errorString; + ActionMessage error(CMD_GLOBAL_ERROR); + error.source_id = fed->global_id.load(); + error.messageID = errorCode; + error.payload = errorString; if (fed->isCallbackFederate()) { - setActionFlag(m, indicator_flag); + setActionFlag(error, indicator_flag); } - addActionMessage(m); + addActionMessage(error); if (fed->isCallbackFederate()) { return; } - fed->addAction(m); + fed->addAction(error); MessageProcessingResult ret = MessageProcessingResult::NEXT_STEP; while (ret != MessageProcessingResult::ERROR_RESULT) { if (fed->getState() == FederateStates::FINISHED || @@ -424,18 +424,18 @@ void CommonCore::localError(LocalFederateId federateID, int errorCode, std::stri if (fed == nullptr) { throw(InvalidIdentifier("federateID not valid error")); } - ActionMessage m(CMD_LOCAL_ERROR); - m.source_id = fed->global_id.load(); - m.messageID = errorCode; - m.payload = errorString; + ActionMessage error(CMD_LOCAL_ERROR); + error.source_id = fed->global_id.load(); + error.messageID = errorCode; + error.payload = errorString; if (fed->isCallbackFederate()) { - setActionFlag(m, indicator_flag); + setActionFlag(error, indicator_flag); } - addActionMessage(m); + addActionMessage(error); if (fed->isCallbackFederate()) { return; } - fed->addAction(m); + fed->addAction(error); MessageProcessingResult ret = MessageProcessingResult::NEXT_STEP; while (ret != MessageProcessingResult::ERROR_RESULT) { if (fed->getState() == FederateStates::FINISHED || @@ -530,13 +530,13 @@ bool CommonCore::allDisconnected() const OperatingState CommonCore::minFederateState() const { - OperatingState op{OperatingState::DISCONNECTED}; + OperatingState state{OperatingState::DISCONNECTED}; for (const auto& fed : loopFederates) { - if (fed.state < op) { - op = fed.state; + if (fed.state < state) { + state = fed.state; } } - return op; + return state; } double CommonCore::getSimulationTime() const @@ -611,15 +611,15 @@ bool CommonCore::enterInitializingMode(LocalFederateId federateID, IterationRequ bool exp = false; // only enter this loop once per federate if (fed->initRequested.compare_exchange_strong(exp, true)) { - ActionMessage m(CMD_INIT); - m.source_id = fed->global_id.load(); + ActionMessage init(CMD_INIT); + init.source_id = fed->global_id.load(); if (request != IterationRequest::NO_ITERATIONS) { - setIterationFlags(m, request); + setIterationFlags(init, request); fed->initIterating.store(true); initIterations.store(true); } - addActionMessage(m); + addActionMessage(init); if (fed->isCallbackFederate()) { return false; @@ -660,8 +660,7 @@ iteration_time CommonCore::enterExecutingMode(LocalFederateId federateID, Iterat } // do an exec check on the fed to process previously received messages so it can't get in a // deadlocked state - ActionMessage execc(CMD_EXEC_CHECK); - fed->addAction(execc); + fed->addAction(CMD_EXEC_CHECK); // do a check on the core to make sure it isn't stopped auto cBrokerState = getBrokerState(); @@ -734,10 +733,10 @@ LocalFederateId CommonCore::registerFederate(std::string_view name, const CoreFe throw(RegistrationFailure("maximum number of federates in the core has been reached")); } - auto id = feds->insert(std::string(name), std::string(name), info); - if (id) { - local_id = LocalFederateId(static_cast(*id)); - fed = (*feds)[*id]; + auto fedid = feds->insert(std::string(name), std::string(name), info); + if (fedid) { + local_id = LocalFederateId(static_cast(*fedid)); + fed = (*feds)[*fedid]; } else { throw(RegistrationFailure( fmt::format("duplicate names {} detected: multiple federates with the same name", @@ -764,15 +763,15 @@ LocalFederateId CommonCore::registerFederate(std::string_view name, const CoreFe if (enable_profiling) { fed->setOptionFlag(defs::PROFILING, true); } - ActionMessage m(CMD_REG_FED); - m.name(name); + ActionMessage reg(CMD_REG_FED); + reg.name(name); if (observer || fed->getOptionFlag(HELICS_FLAG_OBSERVER)) { - setActionFlag(m, observer_flag); + setActionFlag(reg, observer_flag); } if (fed->indexGroup > 0) { - m.counter = static_cast(fed->indexGroup); + reg.counter = static_cast(fed->indexGroup); } - addActionMessage(m); + addActionMessage(reg); // check some properties that should be inherited from the federate if it is the first one if (checkProperties) { // if this is the first federate then the core should inherit the logging level properties @@ -1204,9 +1203,9 @@ FederateState* CommonCore::checkNewInterface(LocalFederateId federateID, } } if (!key.empty()) { - const auto* ci = handles.read( - [&key, type, &tname](auto& hand) { return hand.getInterfaceHandle(key, type); }); - if (ci != nullptr) { // this key is already found + const auto* info = + handles.read([&key, type](auto& hand) { return hand.getInterfaceHandle(key, type); }); + if (info != nullptr) { // this key is already found throw(RegistrationFailure(fmt::format("named {} already exists", tname))); } } @@ -1227,31 +1226,31 @@ InterfaceHandle CommonCore::registerInput(LocalFederateId federateID, units, fed->getInterfaceFlags()); - auto id = handle.getInterfaceHandle(); - fed->createInterface(InterfaceType::INPUT, id, key, type, units, fed->getInterfaceFlags()); + auto hid = handle.getInterfaceHandle(); + fed->createInterface(InterfaceType::INPUT, hid, key, type, units, fed->getInterfaceFlags()); LOG_INTERFACES(parent_broker_id, fed->getIdentifier(), fmt::format("registering Input {}", key)); - ActionMessage m(CMD_REG_INPUT); - m.source_id = fed->global_id.load(); - m.source_handle = id; - m.flags = handle.flags; - m.name(key); - m.setStringData(type, units); + ActionMessage reg(CMD_REG_INPUT); + reg.source_id = fed->global_id.load(); + reg.source_handle = hid; + reg.flags = handle.flags; + reg.name(key); + reg.setStringData(type, units); - actionQueue.push(std::move(m)); - return id; + actionQueue.push(std::move(reg)); + return hid; } InterfaceHandle CommonCore::getInput(LocalFederateId federateID, std::string_view key) const { - const auto* ci = handles.read( + const auto* info = handles.read( [&key](auto& hand) { return hand.getInterfaceHandle(key, InterfaceType::INPUT); }); - if (ci->local_fed_id != federateID) { + if (info->local_fed_id != federateID) { return {}; } - return ci->getInterfaceHandle(); + return info->getInterfaceHandle(); } InterfaceHandle CommonCore::registerPublication(LocalFederateId federateID, @@ -1268,19 +1267,19 @@ InterfaceHandle CommonCore::registerPublication(LocalFederateId federateID, units, fed->getInterfaceFlags()); - auto id = handle.handle.handle; + auto hid = handle.handle.handle; fed->createInterface( - InterfaceType::PUBLICATION, id, key, type, units, fed->getInterfaceFlags()); + InterfaceType::PUBLICATION, hid, key, type, units, fed->getInterfaceFlags()); - ActionMessage m(CMD_REG_PUB); - m.source_id = fed->global_id.load(); - m.source_handle = id; - m.name(key); - m.flags = handle.flags; - m.setStringData(type, units); + ActionMessage reg(CMD_REG_PUB); + reg.source_id = fed->global_id.load(); + reg.source_handle = hid; + reg.name(key); + reg.flags = handle.flags; + reg.setStringData(type, units); - actionQueue.push(std::move(m)); - return id; + actionQueue.push(std::move(reg)); + return hid; } InterfaceHandle CommonCore::getPublication(LocalFederateId federateID, std::string_view key) const @@ -1524,12 +1523,18 @@ void CommonCore::addDestinationTarget(InterfaceHandle handle, "translators cannot have publications as destination targets")); break; case InterfaceType::ENDPOINT: - default: cmd.setAction(CMD_ADD_NAMED_ENDPOINT); break; case InterfaceType::FILTER: cmd.setAction(CMD_ADD_NAMED_FILTER); break; + default: + // translators have two outputs + cmd.setAction(CMD_ADD_NAMED_ENDPOINT); + // need to send 2 messages then one now and one at the end + addActionMessage(cmd); + cmd.setAction(CMD_ADD_NAMED_INPUT); + break; } break; case InterfaceType::FILTER: @@ -1590,9 +1595,9 @@ void CommonCore::addSourceTarget(InterfaceHandle handle, case InterfaceType::TRANSLATOR: switch (hint) { case InterfaceType::PUBLICATION: - default: cmd.setAction(CMD_ADD_NAMED_PUBLICATION); break; + case InterfaceType::INPUT: throw(InvalidIdentifier("translators cannot have inputs as a source")); break; @@ -1602,6 +1607,12 @@ void CommonCore::addSourceTarget(InterfaceHandle handle, case InterfaceType::FILTER: cmd.setAction(CMD_ADD_NAMED_FILTER); break; + default: + // translators can have two inputs + cmd.setAction(CMD_ADD_NAMED_PUBLICATION); + addActionMessage(cmd); + cmd.setAction(CMD_ADD_NAMED_ENDPOINT); + break; } break; case InterfaceType::FILTER: @@ -1717,37 +1728,37 @@ void CommonCore::setValue(InterfaceHandle handle, const char* data, uint64_t len return; } if (subs.size() == 1) { - ActionMessage mv(CMD_PUB); - mv.source_id = handleInfo->getFederateId(); - mv.source_handle = handle; - mv.setDestination(subs[0]); - mv.counter = static_cast(fed->getCurrentIteration()); - mv.payload.assign(data, len); - mv.actionTime = fed->nextAllowedSendTime(); - actionQueue.push(std::move(mv)); + ActionMessage pub(CMD_PUB); + pub.source_id = handleInfo->getFederateId(); + pub.source_handle = handle; + pub.setDestination(subs[0]); + pub.counter = static_cast(fed->getCurrentIteration()); + pub.payload.assign(data, len); + pub.actionTime = fed->nextAllowedSendTime(); + actionQueue.push(std::move(pub)); return; } ActionMessage package(CMD_MULTI_MESSAGE); package.source_id = handleInfo->getFederateId(); package.source_handle = handle; - ActionMessage mv(CMD_PUB); - mv.source_id = handleInfo->getFederateId(); - mv.source_handle = handle; - mv.counter = static_cast(fed->getCurrentIteration()); - mv.payload.assign(data, len); - mv.actionTime = fed->nextAllowedSendTime(); + ActionMessage pub(CMD_PUB); + pub.source_id = handleInfo->getFederateId(); + pub.source_handle = handle; + pub.counter = static_cast(fed->getCurrentIteration()); + pub.payload.assign(data, len); + pub.actionTime = fed->nextAllowedSendTime(); for (auto& target : subs) { - mv.setDestination(target); - auto res = appendMessage(package, mv); + pub.setDestination(target); + auto res = appendMessage(package, pub); if (res < 0) // deal with max package size if there are a lot of subscribers { actionQueue.push(std::move(package)); package = ActionMessage(CMD_MULTI_MESSAGE); package.source_id = handleInfo->getFederateId(); package.source_handle = handle; - appendMessage(package, mv); + appendMessage(package, pub); } } actionQueue.push(std::move(package)); @@ -1766,7 +1777,7 @@ const std::shared_ptr& CommonCore::getValue(InterfaceHandle h throw(InvalidIdentifier("Handle does not identify an input")); } auto& fed = *getFederateAt(handleInfo->local_fed_id); - std::lock_guard lk(fed); + const std::lock_guard lock(fed); return fed.getValue(handle, inputIndex); } @@ -1782,7 +1793,7 @@ const std::vector>& throw(InvalidIdentifier("Handle does not identify an input")); } auto& fed = *getFederateAt(handleInfo->local_fed_id); - std::lock_guard lk(fed); + const std::lock_guard lock(fed); return fed.getAllValues(handle); } @@ -1808,39 +1819,40 @@ InterfaceHandle CommonCore::registerEndpoint(LocalFederateId federateID, std::string{}, fed->getInterfaceFlags()); - auto id = handle.getInterfaceHandle(); + auto hid = handle.getInterfaceHandle(); fed->createInterface( - InterfaceType::ENDPOINT, id, name, type, gEmptyString, fed->getInterfaceFlags()); - ActionMessage m(CMD_REG_ENDPOINT); - m.source_id = fed->global_id.load(); - m.source_handle = id; - m.name(name); - m.setStringData(type); - m.flags = handle.flags; - actionQueue.push(std::move(m)); + InterfaceType::ENDPOINT, hid, name, type, gEmptyString, fed->getInterfaceFlags()); + ActionMessage reg(CMD_REG_ENDPOINT); + reg.source_id = fed->global_id.load(); + reg.source_handle = hid; + reg.name(name); + reg.setStringData(type); + reg.flags = handle.flags; + actionQueue.push(std::move(reg)); - return id; + return hid; } InterfaceHandle CommonCore::registerDataSink(LocalFederateId federateID, std::string_view name) { auto* fed = checkNewInterface(federateID, name, InterfaceType::SINK); - uint16_t sinkFlags = fed->getInterfaceFlags() | make_flags(receive_only_flag, targeted_flag); + const uint16_t sinkFlags = + fed->getInterfaceFlags() | make_flags(receive_only_flag, targeted_flag); const auto& handle = createBasicHandle( fed->global_id, fed->local_id, InterfaceType::SINK, name, "sink", std::string{}, sinkFlags); - auto id = handle.getInterfaceHandle(); - fed->createInterface(InterfaceType::SINK, id, name, "sink", gEmptyString, sinkFlags); - ActionMessage m(CMD_REG_DATASINK); - m.source_id = fed->global_id.load(); - m.source_handle = id; - m.name(name); - m.setStringData("sink"); - m.flags = handle.flags; - actionQueue.push(std::move(m)); + auto hid = handle.getInterfaceHandle(); + fed->createInterface(InterfaceType::SINK, hid, name, "sink", gEmptyString, sinkFlags); + ActionMessage reg(CMD_REG_DATASINK); + reg.source_id = fed->global_id.load(); + reg.source_handle = hid; + reg.name(name); + reg.setStringData("sink"); + reg.flags = handle.flags; + actionQueue.push(std::move(reg)); - return id; + return hid; } InterfaceHandle CommonCore::registerTargetedEndpoint(LocalFederateId federateID, @@ -1854,17 +1866,17 @@ InterfaceHandle CommonCore::registerTargetedEndpoint(LocalFederateId federateID, const auto& handle = createBasicHandle( fed->global_id, fed->local_id, InterfaceType::ENDPOINT, name, type, std::string{}, flags); - auto id = handle.getInterfaceHandle(); - fed->createInterface(InterfaceType::ENDPOINT, id, name, type, gEmptyString, flags); - ActionMessage m(CMD_REG_ENDPOINT); - m.source_id = fed->global_id.load(); - m.source_handle = id; - m.name(name); - m.setStringData(type); - m.flags = handle.flags; - actionQueue.push(std::move(m)); + auto hid = handle.getInterfaceHandle(); + fed->createInterface(InterfaceType::ENDPOINT, hid, name, type, gEmptyString, flags); + ActionMessage reg(CMD_REG_ENDPOINT); + reg.source_id = fed->global_id.load(); + reg.source_handle = hid; + reg.name(name); + reg.setStringData(type); + reg.flags = handle.flags; + actionQueue.push(std::move(reg)); - return id; + return hid; } InterfaceHandle CommonCore::getEndpoint(LocalFederateId federateID, std::string_view name) const @@ -1896,17 +1908,17 @@ InterfaceHandle CommonCore::registerFilter(std::string_view filterName, const auto& handle = createBasicHandle( fid, LocalFederateId(), InterfaceType::FILTER, filterName, type_in, type_out); - auto id = handle.getInterfaceHandle(); + auto hid = handle.getInterfaceHandle(); - ActionMessage m(CMD_REG_FILTER); - m.source_id = fid; - m.source_handle = id; - m.name(handle.key); + ActionMessage reg(CMD_REG_FILTER); + reg.source_id = fid; + reg.source_handle = hid; + reg.name(handle.key); if ((!type_in.empty()) || (!type_out.empty())) { - m.setStringData(type_in, type_out); + reg.setStringData(type_in, type_out); } - actionQueue.push(std::move(m)); - return id; + actionQueue.push(std::move(reg)); + return hid; } InterfaceHandle CommonCore::registerCloningFilter(std::string_view filterName, @@ -1924,18 +1936,18 @@ InterfaceHandle CommonCore::registerCloningFilter(std::string_view filterName, type_out, make_flags(clone_flag)); - auto id = handle.getInterfaceHandle(); + auto hid = handle.getInterfaceHandle(); - ActionMessage m(CMD_REG_FILTER); - m.source_id = fid; - m.source_handle = id; - m.name(handle.key); - setActionFlag(m, clone_flag); + ActionMessage reg(CMD_REG_FILTER); + reg.source_id = fid; + reg.source_handle = hid; + reg.name(handle.key); + setActionFlag(reg, clone_flag); if ((!type_in.empty()) || (!type_out.empty())) { - m.setStringData(type_in, type_out); + reg.setStringData(type_in, type_out); } - actionQueue.push(std::move(m)); - return id; + actionQueue.push(std::move(reg)); + return hid; } InterfaceHandle CommonCore::registerTranslator(std::string_view translatorName, @@ -1949,17 +1961,17 @@ InterfaceHandle CommonCore::registerTranslator(std::string_view translatorName, const auto& handle = createBasicHandle( fid, LocalFederateId(), InterfaceType::TRANSLATOR, translatorName, endpointType, units); - auto id = handle.getInterfaceHandle(); + auto hid = handle.getInterfaceHandle(); - ActionMessage m(CMD_REG_TRANSLATOR); - m.source_id = fid; - m.source_handle = id; - m.name(handle.key); + ActionMessage reg(CMD_REG_TRANSLATOR); + reg.source_id = fid; + reg.source_handle = hid; + reg.name(handle.key); if ((!endpointType.empty()) || (!units.empty())) { - m.setStringData(endpointType, units); + reg.setStringData(endpointType, units); } - actionQueue.push(std::move(m)); - return id; + actionQueue.push(std::move(reg)); + return hid; } InterfaceHandle CommonCore::getFilter(std::string_view name) const @@ -1993,43 +2005,43 @@ void CommonCore::makeConnections(const std::string& file) void CommonCore::linkEndpoints(std::string_view source, std::string_view dest) { - ActionMessage M(CMD_ENDPOINT_LINK); - M.name(source); - M.setStringData(dest); - addActionMessage(std::move(M)); + ActionMessage link(CMD_ENDPOINT_LINK); + link.name(source); + link.setStringData(dest); + addActionMessage(std::move(link)); } void CommonCore::addAlias(std::string_view interfaceKey, std::string_view alias) { - ActionMessage M(CMD_ADD_ALIAS); - M.name(interfaceKey); - M.setStringData(alias); - addActionMessage(std::move(M)); + ActionMessage addAlias(CMD_ADD_ALIAS); + addAlias.name(interfaceKey); + addAlias.setStringData(alias); + addActionMessage(std::move(addAlias)); } void CommonCore::dataLink(std::string_view source, std::string_view target) { - ActionMessage M(CMD_DATA_LINK); - M.name(source); - M.setStringData(target); - addActionMessage(std::move(M)); + ActionMessage link(CMD_DATA_LINK); + link.name(source); + link.setStringData(target); + addActionMessage(std::move(link)); } void CommonCore::addSourceFilterToEndpoint(std::string_view filter, std::string_view endpoint) { - ActionMessage M(CMD_FILTER_LINK); - M.name(filter); - M.setStringData(endpoint); - addActionMessage(std::move(M)); + ActionMessage link(CMD_FILTER_LINK); + link.name(filter); + link.setStringData(endpoint); + addActionMessage(std::move(link)); } void CommonCore::addDestinationFilterToEndpoint(std::string_view filter, std::string_view endpoint) { - ActionMessage M(CMD_FILTER_LINK); - M.name(filter); - M.setStringData(endpoint); - setActionFlag(M, destination_target); - addActionMessage(std::move(M)); + ActionMessage link(CMD_FILTER_LINK); + link.name(filter); + link.setStringData(endpoint); + setActionFlag(link, destination_target); + addActionMessage(std::move(link)); } void CommonCore::addDependency(LocalFederateId federateID, std::string_view federateName) @@ -2072,16 +2084,16 @@ void CommonCore::sendTo(InterfaceHandle sourceHandle, throw(InvalidParameter("targeted endpoint destination not in target list")); } } - ActionMessage m(CMD_SEND_MESSAGE); + ActionMessage message(CMD_SEND_MESSAGE); - m.messageID = ++messageCounter; - m.source_handle = sourceHandle; - m.source_id = hndl->getFederateId(); - m.flags = hndl->flags; - m.payload.assign(data, length); - m.setStringData(destination, hndl->key, hndl->key); - m.actionTime = fed->nextAllowedSendTime(); - addActionMessage(std::move(m)); + message.messageID = ++messageCounter; + message.source_handle = sourceHandle; + message.source_id = hndl->getFederateId(); + message.flags = hndl->flags; + message.payload.assign(data, length); + message.setStringData(destination, hndl->key, hndl->key); + message.actionTime = fed->nextAllowedSendTime(); + addActionMessage(std::move(message)); } void CommonCore::sendToAt(InterfaceHandle sourceHandle, @@ -2114,19 +2126,19 @@ void CommonCore::sendToAt(InterfaceHandle sourceHandle, } } - ActionMessage m(CMD_SEND_MESSAGE); + ActionMessage message(CMD_SEND_MESSAGE); - m.messageID = ++messageCounter; - m.source_handle = sourceHandle; - m.source_id = hndl->getFederateId(); + message.messageID = ++messageCounter; + message.source_handle = sourceHandle; + message.source_id = hndl->getFederateId(); auto minTime = fed->nextAllowedSendTime(); - m.actionTime = std::max(sendTime, minTime); - m.flags = hndl->flags; + message.actionTime = std::max(sendTime, minTime); + message.flags = hndl->flags; - m.payload.assign(data, length); - m.setStringData(destination, hndl->key, hndl->key); + message.payload.assign(data, length); + message.setStringData(destination, hndl->key, hndl->key); - addActionMessage(std::move(m)); + addActionMessage(std::move(message)); } void CommonCore::generateMessages( @@ -2176,14 +2188,14 @@ void CommonCore::send(InterfaceHandle sourceHandle, const void* data, uint64_t l return; } - ActionMessage m(CMD_SEND_MESSAGE); - m.source_handle = sourceHandle; - m.source_id = hndl->getFederateId(); - m.actionTime = fed->nextAllowedSendTime(); - m.payload.assign(data, length); - m.messageID = ++messageCounter; - m.setStringData("", hndl->key, hndl->key); - generateMessages(m, targets); + ActionMessage message(CMD_SEND_MESSAGE); + message.source_handle = sourceHandle; + message.source_id = hndl->getFederateId(); + message.actionTime = fed->nextAllowedSendTime(); + message.payload.assign(data, length); + message.messageID = ++messageCounter; + message.setStringData("", hndl->key, hndl->key); + generateMessages(message, targets); } void CommonCore::sendAt(InterfaceHandle sourceHandle, const void* data, uint64_t length, Time time) @@ -2201,15 +2213,15 @@ void CommonCore::sendAt(InterfaceHandle sourceHandle, const void* data, uint64_t return; } - ActionMessage m(CMD_SEND_MESSAGE); - m.source_handle = sourceHandle; - m.source_id = hndl->getFederateId(); + ActionMessage message(CMD_SEND_MESSAGE); + message.source_handle = sourceHandle; + message.source_id = hndl->getFederateId(); auto minTime = fed->nextAllowedSendTime(); - m.actionTime = std::max(time, minTime); - m.payload.assign(data, length); - m.messageID = ++messageCounter; - m.setStringData("", hndl->key, hndl->key); - generateMessages(m, targets); + message.actionTime = std::max(time, minTime); + message.payload.assign(data, length); + message.messageID = ++messageCounter; + message.setStringData("", hndl->key, hndl->key); + generateMessages(message, targets); } void CommonCore::sendMessage(InterfaceHandle sourceHandle, std::unique_ptr message) @@ -2219,10 +2231,10 @@ void CommonCore::sendMessage(InterfaceHandle sourceHandle, std::unique_ptrkey); - m.source_id = hndl->getFederateId(); - m.source_handle = sourceHandle; - if (m.messageID == 0) { - m.messageID = ++messageCounter; + mess.setString(sourceStringLoc, hndl->key); + mess.source_id = hndl->getFederateId(); + mess.source_handle = sourceHandle; + if (mess.messageID == 0) { + mess.messageID = ++messageCounter; } auto* fed = getFederateAt(hndl->local_fed_id); auto minTime = fed->nextAllowedSendTime(); - if (m.actionTime < minTime) { - m.actionTime = minTime; + if (mess.actionTime < minTime) { + mess.actionTime = minTime; } if (fed->loggingLevel() >= HELICS_LOG_LEVEL_DATA) { fed->logMessage(HELICS_LOG_LEVEL_DATA, "", - fmt::format("send_message {}", prettyPrintString(m))); + fmt::format("send_message {}", prettyPrintString(mess))); } - if (m.getString(targetStringLoc).empty()) { + if (mess.getString(targetStringLoc).empty()) { if (checkActionFlag(*hndl, targeted_flag)) { auto targets = fed->getMessageDestinations(sourceHandle); if (targets.empty()) { return; } - generateMessages(m, targets); + generateMessages(mess, targets); } else { throw(InvalidParameter("no destination specified in message")); } @@ -2270,14 +2282,13 @@ void CommonCore::sendMessage(InterfaceHandle sourceHandle, std::unique_ptrgetMessageDestinations(sourceHandle); auto res = std::find_if(targets.begin(), targets.end(), - [destination = m.getString(targetStringLoc)](const auto& val) { - return (val.second == destination); - }); + [destination = mess.getString(targetStringLoc)]( + const auto& val) { return (val.second == destination); }); if (res == targets.end()) { throw(InvalidParameter("targeted endpoint destination not in target list")); } } - addActionMessage(std::move(m)); + addActionMessage(std::move(mess)); } } @@ -2394,12 +2405,12 @@ void CommonCore::logMessage(LocalFederateId federateID, int logLevel, std::strin } gid = fed->global_id; } - ActionMessage m(CMD_LOG); - m.source_id = gid; - m.dest_id = gid; - m.messageID = logLevel; - m.payload = messageToLog; - actionQueue.push(m); + ActionMessage log(CMD_LOG); + log.source_id = gid; + log.dest_id = gid; + log.messageID = logLevel; + log.payload = messageToLog; + actionQueue.push(log); } void CommonCore::setLoggingLevel(int logLevel) @@ -2448,9 +2459,9 @@ void CommonCore::setLoggingCallback( loggerUpdate.source_id = global_id.load(); loggerUpdate.dest_id = global_id.load(); if (logFunction) { - auto ii = getNextAirlockIndex(); - dataAirlocks[ii].load(std::move(logFunction)); - loggerUpdate.counter = ii; + auto index = getNextAirlockIndex(); + dataAirlocks[index].load(std::move(logFunction)); + loggerUpdate.counter = index; } else { setActionFlag(loggerUpdate, empty_flag); } @@ -2487,7 +2498,7 @@ uint16_t CommonCore::getNextAirlockIndex() void CommonCore::setFilterOperator(InterfaceHandle filter, std::shared_ptr callback) { - static std::shared_ptr nullFilt = std::make_shared(); + static const std::shared_ptr nullFilt = std::make_shared(); const auto* hndl = getHandleInfo(filter); if (hndl == nullptr) { throw(InvalidIdentifier("filter is not a valid handle")); @@ -2500,9 +2511,9 @@ void CommonCore::setFilterOperator(InterfaceHandle filter, std::shared_ptrgetFederateId(); filtOpUpdate.source_handle = filter; actionQueue.push(filtOpUpdate); @@ -2510,7 +2521,7 @@ void CommonCore::setFilterOperator(InterfaceHandle filter, std::shared_ptr callbacks) { - static std::shared_ptr nullTranslator = + static const std::shared_ptr nullTranslator = std::make_shared(); const auto* hndl = getHandleInfo(translator); if (hndl == nullptr) { @@ -2524,9 +2535,9 @@ void CommonCore::setTranslatorOperator(InterfaceHandle translator, if (!callbacks) { callbacks = nullTranslator; } - auto ii = getNextAirlockIndex(); - dataAirlocks[ii].load(std::move(callbacks)); - transOpUpdate.counter = ii; + auto index = getNextAirlockIndex(); + dataAirlocks[index].load(std::move(callbacks)); + transOpUpdate.counter = index; transOpUpdate.source_id = hndl->getFederateId(); transOpUpdate.source_handle = translator; actionQueue.push(transOpUpdate); @@ -2535,7 +2546,7 @@ void CommonCore::setTranslatorOperator(InterfaceHandle translator, void CommonCore::setFederateOperator(LocalFederateId federateID, std::shared_ptr callbacks) { - static std::shared_ptr nullFederate = + static const std::shared_ptr nullFederate = std::make_shared(); auto* fed = getFederateAt(federateID); @@ -2548,9 +2559,9 @@ void CommonCore::setFederateOperator(LocalFederateId federateID, if (!callbacks) { callbacks = nullFederate; } - auto ii = getNextAirlockIndex(); - dataAirlocks[ii].load(std::move(callbacks)); - fedOpUpdate.counter = ii; + auto index = getNextAirlockIndex(); + dataAirlocks[index].load(std::move(callbacks)); + fedOpUpdate.counter = index; fedOpUpdate.source_id = fed->global_id.load(); actionQueue.push(fedOpUpdate); } @@ -2573,6 +2584,7 @@ static const std::map> ma {"barriers", {BARRIERS, QueryReuse::DISABLED}}, {"global_state", {GLOBAL_STATE, QueryReuse::DISABLED}}, {"global_time_debugging", {GLOBAL_TIME_DEBUGGING, QueryReuse::DISABLED}}, + {"unconnected_interfaces", {UNCONNECTED_INTERFACES, QueryReuse::DISABLED}}, {"global_flush", {GLOBAL_FLUSH, QueryReuse::DISABLED}}}; void CommonCore::setQueryCallback(LocalFederateId federateID, @@ -2639,9 +2651,9 @@ std::string CommonCore::federateQuery(const FederateState* fed, return resultString; } if (queryStr == "interfaces") { - auto jv = generateInterfaceConfig(loopHandles, fed->global_id); - jv["name"] = fed->getIdentifier(); - return fileops::generateJsonString(jv); + auto json = generateInterfaceConfig(loopHandles, fed->global_id); + json["name"] = fed->getIdentifier(); + return fileops::generateJsonString(json); } if ((queryStr == "queries") || (queryStr == "available_queries")) { return std::string( @@ -2750,9 +2762,9 @@ void CommonCore::initializeMapBuilder(std::string_view request, if (loopFederates.size() > 0 || filterFed != nullptr || translatorFed != nullptr) { base["federates"] = Json::arrayValue; for (const auto& fed : loopFederates) { - int brkindex = + const int brkindex = builder.generatePlaceHolder("federates", fed->global_id.load().baseValue()); - std::string ret = federateQuery(fed.fed, request, force_ordering); + const std::string ret = federateQuery(fed.fed, request, force_ordering); if (ret == "#wait") { if (fed->getState() <= FederateStates::EXECUTING) { queryReq.messageID = brkindex; @@ -2769,14 +2781,15 @@ void CommonCore::initializeMapBuilder(std::string_view request, } } if (filterFed != nullptr) { - int brkindex = builder.generatePlaceHolder("federates", filterFedID.load().baseValue()); - std::string ret = filterFed->query(request); + const int brkindex = + builder.generatePlaceHolder("federates", filterFedID.load().baseValue()); + const std::string ret = filterFed->query(request); builder.addComponent(ret, brkindex); } if (translatorFed != nullptr) { - int brkindex = + const int brkindex = builder.generatePlaceHolder("federates", translatorFedID.load().baseValue()); - std::string ret = translatorFed->query(request); + const std::string ret = translatorFed->query(request); builder.addComponent(ret, brkindex); } } @@ -2810,6 +2823,15 @@ void CommonCore::initializeMapBuilder(std::string_view request, timeCoord->generateDebuggingTimeInfo(base["time"]); } break; + case UNCONNECTED_INTERFACES: + if (!tags.empty()) { + Json::Value tagBlock = Json::objectValue; + for (const auto& tag : tags) { + tagBlock[tag.first] = tag.second; + } + base["tags"] = tagBlock; + } + break; default: break; } @@ -2846,17 +2868,17 @@ std::string CommonCore::coreQuery(std::string_view queryStr, bool force_ordering } if (queryStr == "tags") { Json::Value tagBlock = Json::objectValue; - for (const auto& tg : tags) { - tagBlock[tg.first] = tg.second; + for (const auto& tag : tags) { + tagBlock[tag.first] = tag.second; } return fileops::generateJsonString(tagBlock); } if (queryStr.compare(0, 4, "tag/") == 0) { - std::string_view tag = queryStr; - tag.remove_prefix(4); - for (const auto& tg : tags) { - if (tag == tg.first) { - return Json::valueToQuotedString(tg.second.c_str()); + std::string_view queriedTag = queryStr; + queriedTag.remove_prefix(4); + for (const auto& tag : tags) { + if (queriedTag == tag.first) { + return Json::valueToQuotedString(tag.second.c_str()); } } return "\"\""; @@ -2921,10 +2943,10 @@ std::string CommonCore::coreQuery(std::string_view queryStr, bool force_ordering }); return fileops::generateJsonString(base); } - auto mi = mapIndex.find(queryStr); - if (mi != mapIndex.end()) { - auto index = mi->second.first; - if (isValidIndex(index, mapBuilders) && mi->second.second == QueryReuse::ENABLED) { + auto maploc = mapIndex.find(queryStr); + if (maploc != mapIndex.end()) { + auto index = maploc->second.first; + if (isValidIndex(index, mapBuilders) && maploc->second.second == QueryReuse::ENABLED) { auto& builder = std::get<0>(mapBuilders[index]); if (builder.isCompleted()) { auto center = generateMapObjectCounter(); @@ -2938,9 +2960,9 @@ std::string CommonCore::coreQuery(std::string_view queryStr, bool force_ordering } } - initializeMapBuilder(queryStr, index, mi->second.second, force_ordering); + initializeMapBuilder(queryStr, index, maploc->second.second, force_ordering); if (std::get<0>(mapBuilders[index]).isCompleted()) { - if (mi->second.second == QueryReuse::ENABLED) { + if (maploc->second.second == QueryReuse::ENABLED) { auto center = generateMapObjectCounter(); std::get<0>(mapBuilders[index]).setCounterCode(center); } @@ -2974,17 +2996,17 @@ std::string CommonCore::coreQuery(std::string_view queryStr, bool force_ordering // add core tags if needed if (!tags.empty()) { Json::Value tagBlock = Json::objectValue; - for (const auto& tg : tags) { - tagBlock[tg.first] = tg.second; + for (const auto& tag : tags) { + tagBlock[tag.first] = tag.second; } base["tags"] = tagBlock; } return fileops::generateJsonString(base); } // check tag value for a matching string - for (const auto& tg : tags) { - if (tg.first == queryStr) { - return Json::valueToQuotedString(tg.second.c_str()); + for (const auto& tag : tags) { + if (tag.first == queryStr) { + return Json::valueToQuotedString(tag.second.c_str()); } } // if nothing found generate an error response @@ -3145,7 +3167,7 @@ void CommonCore::processPriorityCommand(ActionMessage&& command) command.source_id = global_broker_id_local; transmit(parent_route_id, std::move(command)); } else { - // this will get processed when this core is assigned a global id + // this will get processed when this core is assigned a global hid delayTransmitQueue.push(std::move(command)); } break; @@ -3183,13 +3205,13 @@ void CommonCore::processPriorityCommand(ActionMessage&& command) LOG_ERROR(parent_broker_id, identifier, estring); break; } - global_id = GlobalBrokerId(command.dest_id); - global_broker_id_local = GlobalBrokerId(command.dest_id); + global_id = GlobalBrokerId{command.dest_id}; + global_broker_id_local = GlobalBrokerId{command.dest_id}; filterFedID = getSpecialFederateId(global_broker_id_local, 0); translatorFedID = getSpecialFederateId(global_broker_id_local, 1); timeCoord->setSourceId(global_broker_id_local); - higher_broker_id = GlobalBrokerId(command.source_id); + higher_broker_id = GlobalBrokerId{command.source_id}; transmitDelayedMessages(); timeoutMon->setParentId(higher_broker_id); if (checkActionFlag(command, slow_responding_flag)) { @@ -3290,7 +3312,7 @@ void CommonCore::processPriorityCommand(ActionMessage&& command) command.source_id = global_broker_id_local; transmit(parent_route_id, std::move(command)); } else { - // this will get processed when this core is assigned a global id + // this will get processed when this core is assigned a global hid delayTransmitQueue.push(std::move(command)); } break; @@ -3366,8 +3388,8 @@ void CommonCore::transmitDelayedMessages(GlobalFederateId source) } if (!buffer.empty()) { - for (auto& am : buffer) { - delayTransmitQueue.push(std::move(am)); + for (auto& message : buffer) { + delayTransmitQueue.push(std::move(message)); } } @@ -3390,33 +3412,7 @@ void CommonCore::processCommand(ActionMessage&& command) case CMD_IGNORE: break; case CMD_TICK: - if (isReasonForTick(command.messageID, TickForwardingReasons::PING_RESPONSE) || - isReasonForTick(command.messageID, TickForwardingReasons::NO_COMMS)) { - if (getBrokerState() == BrokerState::OPERATING) { - timeoutMon->tick(this); - LOG_SUMMARY(global_broker_id_local, getIdentifier(), " core tick"); - } - } - if (isReasonForTick(command.messageID, TickForwardingReasons::QUERY_TIMEOUT)) { - checkQueryTimeouts(); - } - if (isReasonForTick(command.messageID, TickForwardingReasons::DISCONNECT_TIMEOUT)) { - auto now = std::chrono::steady_clock::now(); - if (now - disconnectTime > (3 * tickTimer).to_ms()) { - LOG_WARNING(global_broker_id_local, - getIdentifier(), - " disconnect Timer expired forcing disconnect"); - ActionMessage bye(CMD_DISCONNECT_FED_ACK); - bye.source_id = parent_broker_id; - for (auto fed : loopFederates) { - if (fed->getState() != FederateStates::FINISHED) { - bye.dest_id = fed->global_id.load(); - fed->addAction(bye); - } - } - addActionMessage(CMD_STOP); - } - } + processTimingTick(command); break; case CMD_PING: case CMD_BROKER_PING: // broker ping for core is the same as core @@ -3437,13 +3433,13 @@ void CommonCore::processCommand(ActionMessage&& command) if (command.messageID == static_cast(CMD_REG_BROKER)) { if ((global_id.load() == parent_broker_id) || (!(global_id.load().isValid()))) { LOG_WARNING_SIMPLE("resending broker reg"); - ActionMessage m(CMD_REG_BROKER); - m.source_id = GlobalFederateId{}; - m.name(getIdentifier()); - m.setStringData(getAddress()); - setActionFlag(m, core_flag); - m.counter = 1; - transmit(parent_route_id, m); + ActionMessage reg(CMD_REG_BROKER); + reg.source_id = GlobalFederateId{}; + reg.name(getIdentifier()); + reg.setStringData(getAddress()); + setActionFlag(reg, core_flag); + reg.counter = 1; + transmit(parent_route_id, reg); } } break; @@ -3484,30 +3480,7 @@ void CommonCore::processCommand(ActionMessage&& command) } [[fallthrough]]; case CMD_EXEC_REQUEST: - if (isLocal(GlobalBrokerId(command.source_id))) { - if (hasTimeBlock(command.source_id)) { - delayedTimingMessages[command.source_id.baseValue()].push_back(command); - break; - } - } - if (command.dest_id == global_broker_id_local) { - timeCoord->processTimeMessage(command); - if (!enteredExecutionMode) { - auto res = timeCoord->checkExecEntry(); - if (res == MessageProcessingResult::NEXT_STEP) { - enteredExecutionMode = true; - LOG_TIMING(global_broker_id_local, getIdentifier(), "entering Exec Mode"); - } else { - timeCoord->updateTimeFactors(); - } - } - } else if (!command.dest_id.isValid() && command.source_id == global_broker_id_local) { - for (auto& dep : timeCoord->getDependents()) { - routeMessage(command, dep); - } - } else { - routeMessage(command); - } + processExecRequest(command); break; case CMD_TIME_GRANT: if (command.source_id == keyFed) { @@ -3659,14 +3632,14 @@ void CommonCore::processCommand(ActionMessage&& command) case CMD_CORE_TAG: if (command.source_id == global_broker_id_local && command.dest_id == global_broker_id_local) { - auto tag = command.getString(0); - for (auto& tg : tags) { - if (tg.first == tag) { - tg.second = command.getString(1); + const auto& keyTag = command.getString(0); + for (auto& tag : tags) { + if (tag.first == keyTag) { + tag.second = command.getString(1); break; } } - tags.emplace_back(tag, command.getString(1)); + tags.emplace_back(keyTag, command.getString(1)); } break; case CMD_CORE_CONFIGURE: @@ -3679,78 +3652,10 @@ void CommonCore::processCommand(ActionMessage&& command) } break; } - case CMD_INIT: { - auto* fed = getFederateCore(command.source_id); - if (fed == nullptr) { - break; - } - - fed->init_transmitted = true; - - if (allInitReady()) { - if (transitionBrokerState(BrokerState::CONNECTED, - BrokerState::INITIALIZING)) { // make sure we only - // do this once - if (initIterations) { - setActionFlag(command, iteration_requested_flag); - } else { - checkDependencies(); - } - command.source_id = global_broker_id_local; - transmit(parent_route_id, command); - } else if (checkActionFlag(command, observer)) { - command.source_id = global_broker_id_local; - transmit(parent_route_id, command); - } - } - - } break; + case CMD_INIT: case CMD_INIT_GRANT: - if (checkActionFlag(command, iteration_requested_flag)) { - if (initIterations) { - if (transitionBrokerState(BrokerState::INITIALIZING, BrokerState::CONNECTED)) { - loopFederates.apply([&command](auto& fed) { - if (fed->initIterating.load()) { - fed->addAction(command); - } - }); - } else if (checkActionFlag(command, observer_flag) || - checkActionFlag(command, dynamic_join_flag)) { - routeMessage(command); - } - initIterations.store(false); - } - } else { - if (transitionBrokerState( - BrokerState::INITIALIZING, - BrokerState::OPERATING)) { // forward the grant to all federates - if (filterFed != nullptr) { - filterFed->organizeFilterOperations(); - } - - loopFederates.apply([&command](auto& fed) { fed->addAction(command); }); - if (filterFed != nullptr && (filterTiming || globalTime)) { - filterFed->handleMessage(command); - } - if (translatorFed != nullptr) { - translatorFed->handleMessage(command); - } - timeCoord->enteringExecMode(); - auto res = timeCoord->checkExecEntry(); - if (res == MessageProcessingResult::NEXT_STEP) { - enteredExecutionMode = true; - } - if (!timeCoord->hasActiveTimeDependencies()) { - timeCoord->disconnect(); - } - } else if (checkActionFlag(command, observer_flag) || - checkActionFlag(command, dynamic_join_flag)) { - routeMessage(command); - } - } - + processInitRequest(command); break; - case CMD_SEND_MESSAGE: if (checkActionFlag(command, filter_processing_required_flag) || ((command.dest_id == parent_broker_id) && (isLocal(command.source_id)))) { @@ -3803,11 +3708,11 @@ void CommonCore::registerInterface(ActionMessage& command) { if (command.dest_id == parent_broker_id) { auto handle = command.source_handle; - auto& lH = loopHandles; - handles.read([handle, &lH](auto& hand) { + auto& loopHandleRef = loopHandles; + handles.read([handle, &loopHandleRef](auto& hand) { auto ifc = hand.getHandleInfo(handle.baseValue()); if (ifc != nullptr) { - lH.addHandleAtIndex(*ifc, handle.baseValue()); + loopHandleRef.addHandleAtIndex(*ifc, handle.baseValue()); } }); @@ -3897,16 +3802,20 @@ void CommonCore::generateTranslatorFederate() translatorThread.store(std::this_thread::get_id()); translatorFedID.store(fid); - translatorFed->setCallbacks([this](const ActionMessage& m) { addActionMessage(m); }, - [this](ActionMessage&& m) { addActionMessage(std::move(m)); }, - [this](const ActionMessage& m) { routeMessage(m); }, - [this](ActionMessage&& m) { routeMessage(std::move(m)); }); + translatorFed->setCallbacks([this](const ActionMessage& message) { addActionMessage(message); }, + [this](ActionMessage&& message) { + addActionMessage(std::move(message)); + }, + [this](const ActionMessage& message) { routeMessage(message); }, + [this](ActionMessage&& message) { + routeMessage(std::move(message)); + }); translatorFed->setHandleManager(&loopHandles); translatorFed->setLogger([this](int level, std::string_view name, std::string_view message) { sendToLogger(global_broker_id_local, level, name, message); }); - translatorFed->setDeliver([this](ActionMessage& m) { deliverMessage(m); }); + translatorFed->setDeliver([this](ActionMessage& message) { deliverMessage(message); }); translatorFed->setAirLockFunction([this](int index) { return std::ref(dataAirlocks[index]); }); ActionMessage newFed(CMD_REG_FED); setActionFlag(newFed, child_flag); @@ -3929,10 +3838,12 @@ void CommonCore::generateFilterFederate() filterThread.store(std::this_thread::get_id()); filterFedID.store(fid); - filterFed->setCallbacks([this](const ActionMessage& m) { addActionMessage(m); }, - [this](ActionMessage&& m) { addActionMessage(std::move(m)); }, - [this](const ActionMessage& m) { routeMessage(m); }, - [this](ActionMessage&& m) { routeMessage(std::move(m)); }); + filterFed->setCallbacks([this](const ActionMessage& message) { addActionMessage(message); }, + [this](ActionMessage&& message) { + addActionMessage(std::move(message)); + }, + [this](const ActionMessage& message) { routeMessage(message); }, + [this](ActionMessage&& message) { routeMessage(std::move(message)); }); hasFilters = true; filterFed->setHandleManager(&loopHandles); @@ -3940,7 +3851,7 @@ void CommonCore::generateFilterFederate() sendToLogger(global_broker_id_local, level, name, message); }); filterFed->setAirLockFunction([this](int index) { return std::ref(dataAirlocks[index]); }); - filterFed->setDeliver([this](ActionMessage& m) { deliverMessage(m); }); + filterFed->setDeliver([this](ActionMessage& message) { deliverMessage(message); }); ActionMessage newFed(CMD_REG_FED); setActionFlag(newFed, child_flag); setActionFlag(newFed, non_counting_flag); @@ -3964,20 +3875,20 @@ void CommonCore::connectFilterTiming() auto fid = filterFedID.load(); if (globalTime) { if (!asyncTime) { - ActionMessage ad(CMD_ADD_DEPENDENT); - setActionFlag(ad, parent_flag); - ad.dest_id = fid; - ad.source_id = gRootBrokerID; - filterFed->handleMessage(ad); - - ad.setAction(CMD_ADD_DEPENDENCY); - filterFed->handleMessage(ad); - clearActionFlag(ad, parent_flag); - setActionFlag(ad, child_flag); - ad.swapSourceDest(); - transmit(parent_route_id, ad); - ad.setAction(CMD_ADD_DEPENDENT); - transmit(parent_route_id, ad); + ActionMessage add(CMD_ADD_DEPENDENT); + setActionFlag(add, parent_flag); + add.dest_id = fid; + add.source_id = gRootBrokerID; + filterFed->handleMessage(add); + + add.setAction(CMD_ADD_DEPENDENCY); + filterFed->handleMessage(add); + clearActionFlag(add, parent_flag); + setActionFlag(add, child_flag); + add.swapSourceDest(); + transmit(parent_route_id, add); + add.setAction(CMD_ADD_DEPENDENT); + transmit(parent_route_id, add); } } else { if (timeCoord->addDependent(higher_broker_id)) { @@ -3990,16 +3901,16 @@ void CommonCore::connectFilterTiming() // now add the filterFederate as a timeDependency timeCoord->addDependency(fid); timeCoord->setAsChild(fid); - ActionMessage ad(CMD_ADD_DEPENDENT); - setActionFlag(ad, parent_flag); - ad.dest_id = fid; - ad.source_id = global_broker_id_local; - filterFed->handleMessage(ad); + ActionMessage add(CMD_ADD_DEPENDENT); + setActionFlag(add, parent_flag); + add.dest_id = fid; + add.source_id = global_broker_id_local; + filterFed->handleMessage(add); // TODO(PT) this should be conditional as it probably isn't needed in all cases - ad.setAction(CMD_ADD_DEPENDENCY); + add.setAction(CMD_ADD_DEPENDENCY); timeCoord->addDependent(fid); timeCoord->setAsChild(fid); - filterFed->handleMessage(ad); + filterFed->handleMessage(add); } // @@ -4259,12 +4170,12 @@ void CommonCore::addTargetToInterface(ActionMessage& command) fed->getState() > FederateStates::CREATED) { auto lastData = fed->getPublishedValue(command.dest_handle); if (lastData.second > Time::minVal() && !lastData.first.empty()) { - ActionMessage mv(CMD_PUB); - mv.setSource(handle->handle); - mv.setDestination(command.getSource()); - mv.payload = std::move(lastData.first); - mv.actionTime = lastData.second; - routeMessage(std::move(mv)); + ActionMessage pub(CMD_PUB); + pub.setSource(handle->handle); + pub.setDestination(command.getSource()); + pub.payload = std::move(lastData.first); + pub.actionTime = lastData.second; + routeMessage(std::move(pub)); } } } @@ -4295,14 +4206,15 @@ void CommonCore::checkQueryTimeouts() { if (!queryTimeouts.empty()) { auto ctime = std::chrono::steady_clock::now(); - for (auto& qt : queryTimeouts) { - if (activeQueries.isRecognized(qt.first) && !activeQueries.isCompleted(qt.first)) { - if (Time(ctime - qt.second) > queryTimeout) { + for (auto& qTimeout : queryTimeouts) { + if (activeQueries.isRecognized(qTimeout.first) && + !activeQueries.isCompleted(qTimeout.first)) { + if (Time(ctime - qTimeout.second) > queryTimeout) { activeQueries.setDelayedValue( - qt.first, + qTimeout.first, generateJsonErrorResponse(JsonErrorCodes::GATEWAY_TIMEOUT, "query timeout")); - qt.first = 0; + qTimeout.first = 0; } } } @@ -4315,38 +4227,38 @@ void CommonCore::checkQueryTimeouts() } } -void CommonCore::processQueryResponse(const ActionMessage& m) +void CommonCore::processQueryResponse(const ActionMessage& message) { - if (m.counter == GENERAL_QUERY) { - activeQueries.setDelayedValue(m.messageID, std::string(m.payload.to_string())); + if (message.counter == GENERAL_QUERY) { + activeQueries.setDelayedValue(message.messageID, std::string(message.payload.to_string())); return; } - if (isValidIndex(m.counter, mapBuilders)) { - auto& builder = std::get<0>(mapBuilders[m.counter]); - auto& requestors = std::get<1>(mapBuilders[m.counter]); - if (builder.addComponent(std::string(m.payload.to_string()), m.messageID)) { + if (isValidIndex(message.counter, mapBuilders)) { + auto& builder = std::get<0>(mapBuilders[message.counter]); + auto& requesters = std::get<1>(mapBuilders[message.counter]); + if (builder.addComponent(std::string(message.payload.to_string()), message.messageID)) { auto str = builder.generate(); - if (m.counter == GLOBAL_FLUSH) { + if (message.counter == GLOBAL_FLUSH) { str = "{\"status\":true}"; } - for (int ii = 0; ii < static_cast(requestors.size()) - 1; ++ii) { - if (requestors[ii].dest_id == global_broker_id_local) { - activeQueries.setDelayedValue(requestors[ii].messageID, str); + for (int ii = 0; ii < static_cast(requesters.size()) - 1; ++ii) { + if (requesters[ii].dest_id == global_broker_id_local) { + activeQueries.setDelayedValue(requesters[ii].messageID, str); } else { - requestors[ii].payload = str; - routeMessage(std::move(requestors[ii])); + requesters[ii].payload = str; + routeMessage(std::move(requesters[ii])); } } - if (requestors.back().dest_id == global_broker_id_local || - requestors.back().dest_id == gDirectCoreId) { - activeQueries.setDelayedValue(requestors.back().messageID, std::move(str)); + if (requesters.back().dest_id == global_broker_id_local || + requesters.back().dest_id == gDirectCoreId) { + activeQueries.setDelayedValue(requesters.back().messageID, std::move(str)); } else { - requestors.back().payload = std::move(str); - routeMessage(std::move(requestors.back())); + requesters.back().payload = std::move(str); + routeMessage(std::move(requesters.back())); } - requestors.clear(); - if (std::get<2>(mapBuilders[m.counter]) == QueryReuse::DISABLED) { + requesters.clear(); + if (std::get<2>(mapBuilders[message.counter]) == QueryReuse::DISABLED) { builder.reset(); } else { builder.setCounterCode(generateMapObjectCounter()); @@ -4644,6 +4556,147 @@ void CommonCore::processLogAndErrorCommand(ActionMessage& cmd) break; } } + +void CommonCore::processTimingTick(ActionMessage& cmd) +{ + if (isReasonForTick(cmd.messageID, TickForwardingReasons::PING_RESPONSE) || + isReasonForTick(cmd.messageID, TickForwardingReasons::NO_COMMS)) { + if (getBrokerState() == BrokerState::OPERATING) { + timeoutMon->tick(this); + LOG_SUMMARY(global_broker_id_local, getIdentifier(), " core tick"); + } + } + if (isReasonForTick(cmd.messageID, TickForwardingReasons::QUERY_TIMEOUT)) { + checkQueryTimeouts(); + } + if (isReasonForTick(cmd.messageID, TickForwardingReasons::DISCONNECT_TIMEOUT)) { + auto now = std::chrono::steady_clock::now(); + if (now - disconnectTime > (3 * tickTimer).to_ms()) { + LOG_WARNING(global_broker_id_local, + getIdentifier(), + " disconnect Timer expired forcing disconnect"); + ActionMessage bye(CMD_DISCONNECT_FED_ACK); + bye.source_id = parent_broker_id; + for (auto fed : loopFederates) { + if (fed->getState() != FederateStates::FINISHED) { + bye.dest_id = fed->global_id.load(); + fed->addAction(bye); + } + } + addActionMessage(CMD_STOP); + } + } +} + +void CommonCore::processInitRequest(ActionMessage& cmd) +{ + switch (cmd.action()) { + case CMD_INIT: { + auto* fed = getFederateCore(cmd.source_id); + if (fed == nullptr) { + break; + } + + fed->init_transmitted = true; + + if (allInitReady()) { + if (transitionBrokerState(BrokerState::CONNECTED, + BrokerState::INITIALIZING)) { // make sure we only + // do this once + if (initIterations) { + setActionFlag(cmd, iteration_requested_flag); + } else { + checkDependencies(); + } + cmd.source_id = global_broker_id_local; + transmit(parent_route_id, cmd); + } else if (checkActionFlag(cmd, observer)) { + cmd.source_id = global_broker_id_local; + transmit(parent_route_id, cmd); + } + } + + } break; + case CMD_INIT_GRANT: + if (checkActionFlag(cmd, iteration_requested_flag)) { + if (initIterations) { + if (transitionBrokerState(BrokerState::INITIALIZING, BrokerState::CONNECTED)) { + loopFederates.apply([&cmd](auto& fed) { + if (fed->initIterating.load()) { + fed->initIterating.store(false); + fed->init_transmitted = false; + fed->addAction(cmd); + } + }); + } else if (checkActionFlag(cmd, observer_flag) || + checkActionFlag(cmd, dynamic_join_flag)) { + routeMessage(cmd); + } + initIterations.store(false); + } + } else { + if (transitionBrokerState( + BrokerState::INITIALIZING, + BrokerState::OPERATING)) { // forward the grant to all federates + if (filterFed != nullptr) { + filterFed->organizeFilterOperations(); + } + + loopFederates.apply([&cmd](auto& fed) { fed->addAction(cmd); }); + if (filterFed != nullptr && (filterTiming || globalTime)) { + filterFed->handleMessage(cmd); + } + if (translatorFed != nullptr) { + translatorFed->handleMessage(cmd); + } + timeCoord->enteringExecMode(); + auto res = timeCoord->checkExecEntry(); + if (res == MessageProcessingResult::NEXT_STEP) { + enteredExecutionMode = true; + } + if (!timeCoord->hasActiveTimeDependencies()) { + timeCoord->disconnect(); + } + } else if (checkActionFlag(cmd, observer_flag) || + checkActionFlag(cmd, dynamic_join_flag)) { + routeMessage(cmd); + } + } + + break; + default: + break; + } +} + +void CommonCore::processExecRequest(ActionMessage& cmd) +{ + if (isLocal(GlobalBrokerId{cmd.source_id})) { + if (hasTimeBlock(cmd.source_id)) { + delayedTimingMessages[cmd.source_id.baseValue()].push_back(cmd); + return; + } + } + if (cmd.dest_id == global_broker_id_local) { + timeCoord->processTimeMessage(cmd); + if (!enteredExecutionMode) { + auto res = timeCoord->checkExecEntry(); + if (res == MessageProcessingResult::NEXT_STEP) { + enteredExecutionMode = true; + LOG_TIMING(global_broker_id_local, getIdentifier(), "entering Exec Mode"); + } else { + timeCoord->updateTimeFactors(); + } + } + } else if (!cmd.dest_id.isValid() && cmd.source_id == global_broker_id_local) { + for (auto& dep : timeCoord->getDependents()) { + routeMessage(cmd, dep); + } + } else { + routeMessage(cmd); + } +} + void CommonCore::processDisconnectCommand(ActionMessage& cmd) { switch (cmd.action()) { @@ -4686,7 +4739,8 @@ void CommonCore::processDisconnectCommand(ActionMessage& cmd) timeCoord->generateDebuggingTimeInfo(base["time"]); base["federates"] = Json::arrayValue; for (const auto& fed : loopFederates) { - std::string ret = federateQuery(fed.fed, "global_time_debugging", false); + const std::string ret = + federateQuery(fed.fed, "global_time_debugging", false); if (ret == "#wait") { if (fed->getState() <= FederateStates::EXECUTING) { cmd.dest_id = fed->global_id.load(); @@ -4857,14 +4911,14 @@ void CommonCore::processCoreConfigureCommands(ActionMessage& cmd) if (checkActionFlag(cmd, empty_flag)) { setLoggerFunction(nullptr); } else { - auto op = dataAirlocks[cmd.counter].try_unload(); - if (op) { + auto locker = dataAirlocks[cmd.counter].try_unload(); + if (locker) { try { - auto M = std::any_cast< + auto callback = std::any_cast< std::function>( - std::move(*op)); - M(0, identifier, "logging callback activated"); - setLoggerFunction(std::move(M)); + std::move(*locker)); + callback(0, identifier, "logging callback activated"); + setLoggerFunction(std::move(callback)); } catch (const std::bad_any_cast&) { // This shouldn't really happen unless someone is being malicious so just @@ -4890,14 +4944,14 @@ void CommonCore::processCoreConfigureCommands(ActionMessage& cmd) if (checkActionFlag(cmd, empty_flag)) { setLoggerFunction(nullptr); } else { - auto op = dataAirlocks[cmd.counter].try_unload(); - if (op) { + auto locker = dataAirlocks[cmd.counter].try_unload(); + if (locker) { try { auto* fed = getFederateCore(cmd.source_id); if (fed != nullptr) { - auto FO = - std::any_cast>(std::move(*op)); - fed->setCallbackOperator(std::move(FO)); + auto fedop = std::any_cast>( + std::move(*locker)); + fed->setCallbackOperator(std::move(fedop)); } } catch (const std::bad_any_cast&) { @@ -4986,7 +5040,7 @@ void CommonCore::processQueryCommand(ActionMessage& cmd) cmd.source_id = global_broker_id_local; transmit(parent_route_id, std::move(cmd)); } else { - // this will get processed when this core is assigned a global id + // this will get processed when this core is assigned a global hid cmd.source_id = gDirectCoreId; delayTransmitQueue.push(std::move(cmd)); } @@ -5076,9 +5130,9 @@ void CommonCore::processCommandsForCore(const ActionMessage& cmd) } else if (cmd.action() == CMD_TIME_BLOCK || cmd.action() == CMD_TIME_UNBLOCK) { manageTimeBlocks(cmd); } else if (cmd.action() == CMD_GRANT_TIMEOUT_CHECK) { - auto v = timeCoord->grantTimeoutCheck(cmd); - if (!v.isNull()) { - auto debugString = fileops::generateJsonString(v); + auto json = timeCoord->grantTimeoutCheck(cmd); + if (!json.isNull()) { + auto debugString = fileops::generateJsonString(json); debugString.insert(0, "TIME DEBUGGING::"); LOG_WARNING(global_broker_id_local, getIdentifier(), debugString); } @@ -5091,9 +5145,9 @@ void CommonCore::processCommandsForCore(const ActionMessage& cmd) bool CommonCore::hasTimeBlock(GlobalFederateId federateID) { - for (auto& tb : timeBlocks) { - if (federateID == tb.first) { - return (tb.second != 0); + for (auto& block : timeBlocks) { + if (federateID == block.first) { + return (block.second != 0); } } return false; @@ -5125,9 +5179,9 @@ bool CommonCore::waitCoreRegistration() } if (sleepcnt == 20) { LOG_WARNING(parent_broker_id, identifier, "resending reg message"); - ActionMessage M(CMD_RESEND); - M.messageID = static_cast(CMD_REG_BROKER); - addActionMessage(M); + ActionMessage resend(CMD_RESEND); + resend.messageID = static_cast(CMD_REG_BROKER); + addActionMessage(resend); } std::this_thread::sleep_for(std::chrono::milliseconds(100)); brkid = global_id.load(); @@ -5143,9 +5197,9 @@ void CommonCore::manageTimeBlocks(const ActionMessage& command) { if (command.action() == CMD_TIME_BLOCK) { bool found{false}; - for (auto& tb : timeBlocks) { - if (command.source_id == tb.first) { - ++tb.second; + for (auto& block : timeBlocks) { + if (command.source_id == block.first) { + ++block.second; found = true; } } @@ -5153,11 +5207,11 @@ void CommonCore::manageTimeBlocks(const ActionMessage& command) timeBlocks.emplace_back(command.source_id, 1); } } else if (command.action() == CMD_TIME_UNBLOCK) { - for (auto& tb : timeBlocks) { - if (command.source_id == tb.first) { - --tb.second; - if (tb.second <= 0) { - tb.second = 0; + for (auto& block : timeBlocks) { + if (command.source_id == block.first) { + --block.second; + if (block.second <= 0) { + block.second = 0; transmitDelayedMessages(command.source_id); } } @@ -5217,31 +5271,31 @@ int CommonCore::generateMapObjectCounter() const void CommonCore::checkInFlightQueriesForDisconnect() { - for (auto& mb : mapBuilders) { - auto& builder = std::get<0>(mb); - auto& requestors = std::get<1>(mb); + for (auto& builderData : mapBuilders) { + auto& builder = std::get<0>(builderData); + auto& requesters = std::get<1>(builderData); if (builder.isCompleted()) { return; } if (builder.clearComponents()) { auto str = builder.generate(); - for (int ii = 0; ii < static_cast(requestors.size()) - 1; ++ii) { - if (requestors[ii].dest_id == global_broker_id_local) { - activeQueries.setDelayedValue(requestors[ii].messageID, str); + for (int ii = 0; ii < static_cast(requesters.size()) - 1; ++ii) { + if (requesters[ii].dest_id == global_broker_id_local) { + activeQueries.setDelayedValue(requesters[ii].messageID, str); } else { - requestors[ii].payload = str; - routeMessage(std::move(requestors[ii])); + requesters[ii].payload = str; + routeMessage(std::move(requesters[ii])); } } - if (requestors.back().dest_id == global_broker_id_local) { - activeQueries.setDelayedValue(requestors.back().messageID, std::move(str)); + if (requesters.back().dest_id == global_broker_id_local) { + activeQueries.setDelayedValue(requesters.back().messageID, std::move(str)); } else { - requestors.back().payload = std::move(str); - routeMessage(std::move(requestors.back())); + requesters.back().payload = std::move(str); + routeMessage(std::move(requesters.back())); } - requestors.clear(); - if (std::get<2>(mb) == QueryReuse::DISABLED) { + requesters.clear(); + if (std::get<2>(builderData) == QueryReuse::DISABLED) { builder.reset(); } } @@ -5270,9 +5324,9 @@ void CommonCore::sendDisconnect(action_message_def::action_t disconnectType) if (filterFed != nullptr) { filterFed->handleMessage(bye); } - ActionMessage m(CMD_DISCONNECT); - m.source_id = global_broker_id_local; - transmit(parent_route_id, m); + ActionMessage disconnect(CMD_DISCONNECT); + disconnect.source_id = global_broker_id_local; + transmit(parent_route_id, disconnect); } bool CommonCore::checkForLocalPublication(ActionMessage& cmd) @@ -5395,7 +5449,7 @@ void CommonCore::routeMessage(ActionMessage&& cmd, GlobalFederateId dest) void CommonCore::routeMessage(ActionMessage&& cmd) { - GlobalFederateId dest = cmd.dest_id; + const GlobalFederateId dest = cmd.dest_id; if ((dest == parent_broker_id) || (dest == higher_broker_id)) { transmit(parent_route_id, cmd); } else if (dest == global_broker_id_local) { @@ -5423,20 +5477,20 @@ void CommonCore::routeMessage(ActionMessage&& cmd) } // namespace helics // Checks for filter operations -ActionMessage& CommonCore::processMessage(ActionMessage& m) +ActionMessage& CommonCore::processMessage(ActionMessage& message) { - auto* handle = loopHandles.getInterfaceHandle(m.source_handle, InterfaceType::ENDPOINT); + auto* handle = loopHandles.getInterfaceHandle(message.source_handle, InterfaceType::ENDPOINT); if (handle == nullptr) { - return m; + return message; } - clearActionFlag(m, filter_processing_required_flag); + clearActionFlag(message, filter_processing_required_flag); if (checkActionFlag(*handle, has_source_filter_flag)) { if (filterFed != nullptr) { - return filterFed->processMessage(m, handle); + return filterFed->processMessage(message, handle); } } - return m; + return message; } const std::string& CommonCore::getInterfaceInfo(InterfaceHandle handle) const diff --git a/src/helics/core/CommonCore.hpp b/src/helics/core/CommonCore.hpp index dfb592aadc..3489f8cd4e 100644 --- a/src/helics/core/CommonCore.hpp +++ b/src/helics/core/CommonCore.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -406,15 +406,22 @@ class CommonCore: public Core, public BrokerBase { /** check if we can remove some dependencies*/ void checkDependencies(); /** deal with a query response addressed to this core*/ - void processQueryResponse(const ActionMessage& m); + void processQueryResponse(const ActionMessage& message); /** manage query timeouts*/ void checkQueryTimeouts(); /** handle command with the core itself as a destination at the core*/ void processCommandsForCore(const ActionMessage& cmd); /** process configure commands for the core*/ void processCoreConfigureCommands(ActionMessage& cmd); + /** handle init messages*/ + void processInitRequest(ActionMessage& cmd); + /** process and exec request command*/ + void processExecRequest(ActionMessage& cmd); /** process commands related to disconnect messages*/ void processDisconnectCommand(ActionMessage& cmd); + + /** process a timing tick message */ + void processTimingTick(ActionMessage& cmd); /** handle the processing for a query command*/ void processQueryCommand(ActionMessage& cmd); /** handle logging and error related commands*/ diff --git a/src/helics/core/Core.hpp b/src/helics/core/Core.hpp index 6f8802c2c7..78e4dbaea0 100644 --- a/src/helics/core/Core.hpp +++ b/src/helics/core/Core.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/core/CoreBroker.cpp b/src/helics/core/CoreBroker.cpp index 1557a4c766..f018409cd2 100644 --- a/src/helics/core/CoreBroker.cpp +++ b/src/helics/core/CoreBroker.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -9,7 +9,6 @@ SPDX-License-Identifier: BSD-3-Clause #include "../common/JsonGeneration.hpp" #include "../common/JsonProcessingFunctions.hpp" -#include "../common/fmt_format.h" #include "../common/logging.hpp" #include "BaseTimeCoordinator.hpp" #include "BrokerFactory.hpp" @@ -25,6 +24,7 @@ SPDX-License-Identifier: BSD-3-Clause #include "loggingHelper.hpp" #include "queryHelpers.hpp" +#include #include #include #include @@ -38,7 +38,7 @@ constexpr char universalKey[] = "**"; const std::string& stateString(ConnectionState state) { - static const std::string c1{"connected"}; + static const std::string connected{"connected"}; static const std::string init{"init_requested"}; static const std::string operating{"operating"}; static const std::string estate{"error"}; @@ -49,7 +49,7 @@ const std::string& stateString(ConnectionState state) case ConnectionState::INIT_REQUESTED: return init; case ConnectionState::CONNECTED: - return c1; + return connected; case ConnectionState::REQUEST_DISCONNECT: case ConnectionState::DISCONNECTED: return dis; @@ -61,7 +61,7 @@ const std::string& stateString(ConnectionState state) CoreBroker::~CoreBroker() { - std::lock_guard lock(name_mutex_); + const std::lock_guard lock(name_mutex_); // make sure everything is synchronized } @@ -69,7 +69,7 @@ void CoreBroker::setIdentifier(std::string_view name) { if (getBrokerState() <= BrokerState::CONNECTING) // can't be changed after initialization { - std::lock_guard lock(name_mutex_); + const std::lock_guard lock(name_mutex_); identifier.assign(name); } } @@ -121,9 +121,9 @@ void CoreBroker::setLoggingCallback( loggerUpdate.messageID = UPDATE_LOGGING_CALLBACK; loggerUpdate.source_id = global_id.load(); if (logFunction) { - auto ii = getNextAirlockIndex(); - dataAirlocks[ii].load(std::move(logFunction)); - loggerUpdate.counter = ii; + auto index = getNextAirlockIndex(); + dataAirlocks[index].load(std::move(logFunction)); + loggerUpdate.counter = index; } else { setActionFlag(loggerUpdate, empty_flag); } @@ -176,43 +176,43 @@ void CoreBroker::makeConnections(const std::string& file) void CoreBroker::linkEndpoints(std::string_view source, std::string_view target) { - ActionMessage M(CMD_ENDPOINT_LINK); - M.name(source); - M.setStringData(target); - addActionMessage(std::move(M)); + ActionMessage link(CMD_ENDPOINT_LINK); + link.name(source); + link.setStringData(target); + addActionMessage(std::move(link)); } void CoreBroker::dataLink(std::string_view publication, std::string_view input) { - ActionMessage M(CMD_DATA_LINK); - M.name(publication); - M.setStringData(input); - addActionMessage(std::move(M)); + ActionMessage link(CMD_DATA_LINK); + link.name(publication); + link.setStringData(input); + addActionMessage(std::move(link)); } void CoreBroker::addSourceFilterToEndpoint(std::string_view filter, std::string_view endpoint) { - ActionMessage M(CMD_FILTER_LINK); - M.name(filter); - M.setStringData(endpoint); - addActionMessage(std::move(M)); + ActionMessage link(CMD_FILTER_LINK); + link.name(filter); + link.setStringData(endpoint); + addActionMessage(std::move(link)); } void CoreBroker::addDestinationFilterToEndpoint(std::string_view filter, std::string_view endpoint) { - ActionMessage M(CMD_FILTER_LINK); - M.name(filter); - M.setStringData(endpoint); - setActionFlag(M, destination_target); - addActionMessage(std::move(M)); + ActionMessage link(CMD_FILTER_LINK); + link.name(filter); + link.setStringData(endpoint); + setActionFlag(link, destination_target); + addActionMessage(std::move(link)); } void CoreBroker::addAlias(std::string_view interfaceKey, std::string_view alias) { - ActionMessage M(CMD_ADD_ALIAS); - M.name(interfaceKey); - M.setStringData(alias); - addActionMessage(std::move(M)); + ActionMessage link(CMD_ADD_ALIAS); + link.name(interfaceKey); + link.setStringData(alias); + addActionMessage(std::move(link)); } route_id CoreBroker::fillMessageRouteInformation(ActionMessage& mess) @@ -251,7 +251,7 @@ void CoreBroker::sendBrokerErrorAck(ActionMessage& command, std::int32_t errorCo { route_id newroute; bool route_created = false; - bool jsonReply = checkActionFlag(command, use_json_serialization_flag); + const bool jsonReply = checkActionFlag(command, use_json_serialization_flag); if ((!command.source_id.isValid()) || (command.source_id == parent_broker_id)) { newroute = generateRouteId(jsonReply ? json_route_code : 0, routeCount++); addRoute(newroute, command.getExtraData(), command.getString(targetStringLoc)); @@ -287,7 +287,7 @@ void CoreBroker::brokerRegistration(ActionMessage&& command) earlyMessages.push_back(std::move(command)); return; } - bool jsonReply = checkActionFlag(command, use_json_serialization_flag); + const bool jsonReply = checkActionFlag(command, use_json_serialization_flag); if (command.counter > 0) { // this indicates it is a resend auto brk = mBrokers.find(command.name()); if (brk != mBrokers.end()) { @@ -448,10 +448,10 @@ std::string CoreBroker::generateRename(std::string_view name) std::string newName{name}; auto cntLoc = newName.find("${#}"); if (cntLoc != std::string::npos) { - auto rn = renamers.find(newName); - if (rn != renamers.end()) { - newName.replace(cntLoc, 4, std::to_string(rn->second + 1)); - rn->second++; + auto renamer = renamers.find(newName); + if (renamer != renamers.end()) { + newName.replace(cntLoc, 4, std::to_string(renamer->second + 1)); + renamer->second++; } else { newName.replace(cntLoc, 4, "1"); renamers.emplace(name, 1); @@ -467,7 +467,7 @@ void CoreBroker::fedRegistration(ActionMessage&& command) earlyMessages.push_back(std::move(command)); return; } - bool countable = !checkActionFlag(command, non_counting_flag); + const bool countable = !checkActionFlag(command, non_counting_flag); bool dynamicFed{false}; if (countable && getCountableFederates() >= maxFederateCount) { sendFedErrorAck(command, max_federate_count_exceeded); @@ -480,7 +480,8 @@ void CoreBroker::fedRegistration(ActionMessage&& command) transmit(parent_route_id, noInit); } } else if (getBrokerState() == BrokerState::OPERATING) { - bool allowed = dynamicFederation || !countable || checkActionFlag(command, observer_flag); + const bool allowed = + dynamicFederation || !countable || checkActionFlag(command, observer_flag); if (!allowed) { // we are initialized already sendFedErrorAck(command, already_init_error_code); @@ -608,11 +609,11 @@ void CoreBroker::processPriorityCommand(ActionMessage&& command) timeCoord->setSourceId(global_broker_id_local); connectionEstablished = true; if (!earlyMessages.empty()) { - for (auto& M : earlyMessages) { - if (isPriorityCommand(M)) { - processPriorityCommand(std::move(M)); + for (auto& message : earlyMessages) { + if (isPriorityCommand(message)) { + processPriorityCommand(std::move(message)); } else { - processCommand(std::move(M)); + processCommand(std::move(message)); } } earlyMessages.clear(); @@ -683,27 +684,27 @@ void CoreBroker::processPriorityCommand(ActionMessage&& command) } auto broker = mBrokers.find(command.name()); if (broker != mBrokers.end()) { - if (broker->global_id == GlobalBrokerId(command.dest_id)) { + if (broker->global_id == GlobalBrokerId{command.dest_id}) { // drop the packet since we have seen this ack already LOG_WARNING(global_broker_id_local, identifier, "repeated broker acks"); return; } - broker->global_id = GlobalBrokerId(command.dest_id); + broker->global_id = GlobalBrokerId{command.dest_id}; auto route = broker->route; - mBrokers.addSearchTerm(GlobalBrokerId(command.dest_id), broker->name); + mBrokers.addSearchTerm(GlobalBrokerId{command.dest_id}, broker->name); routing_table.emplace(broker->global_id, route); command.source_id = global_broker_id_local; // we want the intermediate broker to // change the source_id transmit(route, command); } else { - mBrokers.insert(command.name(), GlobalBrokerId(command.dest_id), command.name()); + mBrokers.insert(command.name(), GlobalBrokerId{command.dest_id}, command.name()); mBrokers.back().route = getRoute(command.source_id); - mBrokers.back().global_id = GlobalBrokerId(command.dest_id); + mBrokers.back().global_id = GlobalBrokerId{command.dest_id}; routing_table.emplace(broker->global_id, mBrokers.back().route); } } break; case CMD_PRIORITY_DISCONNECT: { - auto* brk = getBrokerById(GlobalBrokerId(command.source_id)); + auto* brk = getBrokerById(GlobalBrokerId{command.source_id}); if (brk != nullptr) { brk->state = ConnectionState::DISCONNECTED; } @@ -786,9 +787,9 @@ std::string CoreBroker::generateFederationSummary() const return fileops::generateJsonString(summary); } -void CoreBroker::generateTimeBarrier(ActionMessage& m) +void CoreBroker::generateTimeBarrier(ActionMessage& message) { - if (checkActionFlag(m, cancel_flag)) { + if (checkActionFlag(message, cancel_flag)) { ActionMessage cancelBarrier(CMD_TIME_BARRIER_CLEAR); cancelBarrier.source_id = global_broker_id_local; if (cancelBarrier.messageID == 0) { @@ -798,14 +799,14 @@ void CoreBroker::generateTimeBarrier(ActionMessage& m) broadcast(cancelBarrier); return; } - m.setAction(CMD_TIME_BARRIER); - m.source_id = global_broker_id_local; - if (m.messageID == 0) { - m.messageID = global_broker_id_local.baseValue(); + message.setAction(CMD_TIME_BARRIER); + message.source_id = global_broker_id_local; + if (message.messageID == 0) { + message.messageID = global_broker_id_local.baseValue(); } - mNextTimeBarrier = m.actionTime; + mNextTimeBarrier = message.actionTime; // time should already be set - broadcast(m); + broadcast(message); } int CoreBroker::generateMapObjectCounter() const @@ -900,24 +901,24 @@ void CoreBroker::loadTimeMonitor(bool firstLoad, std::string_view newFederate) } } -void CoreBroker::processTimeMonitorMessage(ActionMessage& m) +void CoreBroker::processTimeMonitorMessage(ActionMessage& message) { - if (m.source_id != mTimeMonitorFederateId) { + if (message.source_id != mTimeMonitorFederateId) { return; } - switch (m.action()) { + switch (message.action()) { case CMD_EXEC_GRANT: mTimeMonitorLastLogTime = timeZero; mTimeMonitorCurrentTime = timeZero; simTime.store(static_cast(mTimeMonitorCurrentTime)); - LOG_SUMMARY(m.source_id, mTimeMonitorFederate, "TIME: exec granted"); + LOG_SUMMARY(message.source_id, mTimeMonitorFederate, "TIME: exec granted"); break; case CMD_TIME_GRANT: - mTimeMonitorCurrentTime = m.actionTime; + mTimeMonitorCurrentTime = message.actionTime; simTime.store(static_cast(mTimeMonitorCurrentTime)); if (mTimeMonitorCurrentTime - mTimeMonitorPeriod >= mTimeMonitorLastLogTime) { - LOG_SUMMARY(m.source_id, + LOG_SUMMARY(message.source_id, mTimeMonitorFederate, fmt::format("TIME: granted time={}", static_cast(mTimeMonitorCurrentTime))); @@ -925,7 +926,7 @@ void CoreBroker::processTimeMonitorMessage(ActionMessage& m) } break; case CMD_DISCONNECT: - LOG_SUMMARY(m.source_id, + LOG_SUMMARY(message.source_id, mTimeMonitorFederate, fmt::format("TIME: disconnected, last time {}", static_cast(mTimeMonitorCurrentTime))); @@ -1067,7 +1068,7 @@ void CoreBroker::processCommand(ActionMessage&& command) processDisconnectCommand(command); } else { if (isRootc) { - std::string lcom = + const std::string lcom = fmt::format("lost comms with {}", command.source_id.baseValue()); LOG_ERROR(global_broker_id_local, getIdentifier(), lcom); ActionMessage elink(CMD_ERROR); @@ -1204,9 +1205,9 @@ void CoreBroker::processCommand(ActionMessage&& command) // haven't done so already timeCoord->disconnect(); if (!isRootc) { - ActionMessage m(CMD_DISCONNECT); - m.source_id = global_broker_id_local; - transmit(parent_route_id, m); + ActionMessage disconnect(CMD_DISCONNECT); + disconnect.source_id = global_broker_id_local; + transmit(parent_route_id, disconnect); } } activeQueries.fulfillAllPromises("#disconnected"); @@ -1299,8 +1300,8 @@ void CoreBroker::processCommand(ActionMessage&& command) if (command.dest_id == parent_broker_id) { auto route = fillMessageRouteInformation(command); if (route == parent_route_id && isRootc && command.action() == CMD_SEND_MESSAGE) { - bool optional_flag_set = checkActionFlag(command, optional_flag); - bool required_flag_set = checkActionFlag(command, required_flag); + const bool optional_flag_set = checkActionFlag(command, optional_flag); + const bool required_flag_set = checkActionFlag(command, required_flag); if (!optional_flag_set) { ActionMessage warn(required_flag_set ? CMD_ERROR : CMD_WARNING); @@ -1323,9 +1324,9 @@ void CoreBroker::processCommand(ActionMessage&& command) case CMD_GRANT_TIMEOUT_CHECK: if (command.dest_id == global_broker_id_local || (isRootc && command.dest_id == parent_broker_id)) { - auto v = timeCoord->grantTimeoutCheck(command); - if (!v.isNull()) { - auto debugString = fileops::generateJsonString(v); + auto json = timeCoord->grantTimeoutCheck(command); + if (!json.isNull()) { + auto debugString = fileops::generateJsonString(json); debugString.insert(0, "TIME DEBUGGING::"); LOG_WARNING(global_broker_id_local, "broker", debugString); } @@ -1535,7 +1536,7 @@ void CoreBroker::processInitCommand(ActionMessage& cmd) } transmit(parent_route_id, cmd); } - auto* brk = getBrokerById(GlobalBrokerId(cmd.source_id)); + auto* brk = getBrokerById(GlobalBrokerId{cmd.source_id}); if (brk != nullptr) { brk->state = ConnectionState::CONNECTED; brk->initIterating = false; @@ -1601,14 +1602,14 @@ void CoreBroker::processBrokerConfigureCommands(ActionMessage& cmd) if (checkActionFlag(cmd, empty_flag)) { setLoggerFunction(nullptr); } else { - auto op = dataAirlocks[cmd.counter].try_unload(); - if (op) { + auto locker = dataAirlocks[cmd.counter].try_unload(); + if (locker) { try { - auto M = std::any_cast< + auto callback = std::any_cast< std::function>( - std::move(*op)); - M(0, identifier, "logging callback activated"); - setLoggerFunction(std::move(M)); + std::move(*locker)); + callback(0, identifier, "logging callback activated"); + setLoggerFunction(std::move(callback)); } catch (const std::bad_any_cast&) { // This shouldn't really happen unless someone is being malicious so just @@ -1887,13 +1888,13 @@ void CoreBroker::removeNamedTarget(ActionMessage& command) } } -void CoreBroker::addLocalInfo(BasicHandleInfo& handleInfo, const ActionMessage& m) +void CoreBroker::addLocalInfo(BasicHandleInfo& handleInfo, const ActionMessage& message) { - auto res = global_id_translation.find(m.source_id); + auto res = global_id_translation.find(message.source_id); if (res != global_id_translation.end()) { handleInfo.local_fed_id = res->second; } - handleInfo.flags = m.flags; + handleInfo.flags = message.flags; } void CoreBroker::propagateError(ActionMessage&& cmd) @@ -1917,50 +1918,51 @@ void CoreBroker::propagateError(ActionMessage&& cmd) routeMessage(std::move(cmd)); } -bool CoreBroker::checkInterfaceCreation(ActionMessage& m, InterfaceType type) +bool CoreBroker::checkInterfaceCreation(ActionMessage& message, InterfaceType type) { bool existingName{false}; if (type == InterfaceType::TRANSLATOR) { existingName = - (handles.getInterfaceHandle(m.name(), InterfaceType::ENDPOINT) != nullptr || - handles.getInterfaceHandle(m.name(), InterfaceType::INPUT) != nullptr || - handles.getInterfaceHandle(m.name(), InterfaceType::PUBLICATION) != nullptr); + (handles.getInterfaceHandle(message.name(), InterfaceType::ENDPOINT) != nullptr || + handles.getInterfaceHandle(message.name(), InterfaceType::INPUT) != nullptr || + handles.getInterfaceHandle(message.name(), InterfaceType::PUBLICATION) != nullptr); } else { - existingName = (handles.getInterfaceHandle(m.name(), type) != nullptr); + existingName = (handles.getInterfaceHandle(message.name(), type) != nullptr); } // detect duplicate InterfaceName; if (existingName) { - ActionMessage eret(CMD_LOCAL_ERROR, global_broker_id_local, m.source_id); - eret.dest_handle = m.source_handle; + ActionMessage eret(CMD_LOCAL_ERROR, global_broker_id_local, message.source_id); + eret.dest_handle = message.source_handle; eret.messageID = defs::Errors::REGISTRATION_FAILURE; - eret.payload = fmt::format("Duplicate {} names ({})", interfaceTypeName(type), m.name()); + eret.payload = + fmt::format("Duplicate {} names ({})", interfaceTypeName(type), message.name()); propagateError(std::move(eret)); return false; } if (disableDynamicSources && type != InterfaceType::INPUT) { if (getBrokerState() == BrokerState::OPERATING) { - auto fed = mFederates.find(m.source_id); + auto fed = mFederates.find(message.source_id); if (fed == mFederates.end()) { - ActionMessage eret(CMD_LOCAL_ERROR, global_broker_id_local, m.source_id); - eret.dest_handle = m.source_handle; + ActionMessage eret(CMD_LOCAL_ERROR, global_broker_id_local, message.source_id); + eret.dest_handle = message.source_handle; eret.messageID = defs::Errors::REGISTRATION_FAILURE; eret.payload = fmt::format("Source {} not allowed after entering initializing mode ({})", interfaceTypeName(type), - m.name()); + message.name()); propagateError(std::move(eret)); return false; - } else if (!(fed->observer || - (fed->dynamic && fed->state == ConnectionState::CONNECTED))) { - ActionMessage eret(CMD_LOCAL_ERROR, global_broker_id_local, m.source_id); - eret.dest_handle = m.source_handle; + } + if (!(fed->observer && (!fed->dynamic || fed->state != ConnectionState::CONNECTED))) { + ActionMessage eret(CMD_LOCAL_ERROR, global_broker_id_local, message.source_id); + eret.dest_handle = message.source_handle; eret.messageID = defs::Errors::REGISTRATION_FAILURE; eret.payload = fmt::format( "Source {} from {} not allowed after entering initializing mode ({})", interfaceTypeName(type), fed->name, - m.name()); + message.name()); propagateError(std::move(eret)); return false; } @@ -1969,61 +1971,61 @@ bool CoreBroker::checkInterfaceCreation(ActionMessage& m, InterfaceType type) return true; } -void CoreBroker::addPublication(ActionMessage& m) +void CoreBroker::addPublication(ActionMessage& message) { - if (!checkInterfaceCreation(m, InterfaceType::PUBLICATION)) { + if (!checkInterfaceCreation(message, InterfaceType::PUBLICATION)) { return; } - auto& pub = handles.addHandle(m.source_id, - m.source_handle, + auto& pub = handles.addHandle(message.source_id, + message.source_handle, InterfaceType::PUBLICATION, - m.name(), - m.getString(typeStringLoc), - m.getString(unitStringLoc)); + message.name(), + message.getString(typeStringLoc), + message.getString(unitStringLoc)); - addLocalInfo(pub, m); + addLocalInfo(pub, message); if (!isRootc) { - transmit(parent_route_id, m); + transmit(parent_route_id, message); } else { findAndNotifyPublicationTargets(pub, pub.key); } } -void CoreBroker::addInput(ActionMessage& m) +void CoreBroker::addInput(ActionMessage& message) { - if (!checkInterfaceCreation(m, InterfaceType::INPUT)) { + if (!checkInterfaceCreation(message, InterfaceType::INPUT)) { return; } - auto& inp = handles.addHandle(m.source_id, - m.source_handle, + auto& inp = handles.addHandle(message.source_id, + message.source_handle, InterfaceType::INPUT, - m.name(), - m.getString(typeStringLoc), - m.getString(unitStringLoc)); + message.name(), + message.getString(typeStringLoc), + message.getString(unitStringLoc)); - addLocalInfo(inp, m); + addLocalInfo(inp, message); if (!isRootc) { - transmit(parent_route_id, m); + transmit(parent_route_id, message); } else { findAndNotifyInputTargets(inp, inp.key); } } -void CoreBroker::addEndpoint(ActionMessage& m) +void CoreBroker::addEndpoint(ActionMessage& message) { - if (!checkInterfaceCreation(m, InterfaceType::ENDPOINT)) { + if (!checkInterfaceCreation(message, InterfaceType::ENDPOINT)) { return; } - auto& ept = handles.addHandle(m.source_id, - m.source_handle, + auto& ept = handles.addHandle(message.source_id, + message.source_handle, InterfaceType::ENDPOINT, - m.name(), - m.getString(typeStringLoc), - m.getString(unitStringLoc)); + message.name(), + message.getString(typeStringLoc), + message.getString(unitStringLoc)); - addLocalInfo(ept, m); + addLocalInfo(ept, message); if (!isRootc) { - transmit(parent_route_id, m); + transmit(parent_route_id, message); if (!hasTimeDependency && !globalTime && !asyncTime) { if (timeCoord->addDependency(higher_broker_id)) { hasTimeDependency = true; @@ -2041,41 +2043,41 @@ void CoreBroker::addEndpoint(ActionMessage& m) findAndNotifyEndpointTargets(ept, ept.key); } } -void CoreBroker::addFilter(ActionMessage& m) +void CoreBroker::addFilter(ActionMessage& message) { - if (!checkInterfaceCreation(m, InterfaceType::FILTER)) { + if (!checkInterfaceCreation(message, InterfaceType::FILTER)) { return; } - auto& filt = handles.addHandle(m.source_id, - m.source_handle, + auto& filt = handles.addHandle(message.source_id, + message.source_handle, InterfaceType::FILTER, - m.name(), - m.getString(typeStringLoc), - m.getString(typeOutStringLoc)); - addLocalInfo(filt, m); + message.name(), + message.getString(typeStringLoc), + message.getString(typeOutStringLoc)); + addLocalInfo(filt, message); if (!isRootc) { - transmit(parent_route_id, m); + transmit(parent_route_id, message); } else { findAndNotifyFilterTargets(filt, filt.key); } } -void CoreBroker::addTranslator(ActionMessage& m) +void CoreBroker::addTranslator(ActionMessage& message) { - if (!checkInterfaceCreation(m, InterfaceType::TRANSLATOR)) { + if (!checkInterfaceCreation(message, InterfaceType::TRANSLATOR)) { return; } - auto& trans = handles.addHandle(m.source_id, - m.source_handle, + auto& trans = handles.addHandle(message.source_id, + message.source_handle, InterfaceType::TRANSLATOR, - m.name(), - m.getString(typeStringLoc), - m.getString(typeOutStringLoc)); - addLocalInfo(trans, m); + message.name(), + message.getString(typeStringLoc), + message.getString(typeOutStringLoc)); + addLocalInfo(trans, message); if (!isRootc) { - transmit(parent_route_id, m); + transmit(parent_route_id, message); if (!hasFilters) { hasFilters = true; if (!globalTime && !asyncTime) { @@ -2094,21 +2096,21 @@ void CoreBroker::addTranslator(ActionMessage& m) } } -void CoreBroker::addDataSink(ActionMessage& m) +void CoreBroker::addDataSink(ActionMessage& message) { - if (!checkInterfaceCreation(m, InterfaceType::SINK)) { + if (!checkInterfaceCreation(message, InterfaceType::SINK)) { return; } - auto& sink = handles.addHandle(m.source_id, - m.source_handle, + auto& sink = handles.addHandle(message.source_id, + message.source_handle, InterfaceType::SINK, - m.name(), - m.getString(typeStringLoc), - m.getString(unitStringLoc)); - addLocalInfo(sink, m); + message.name(), + message.getString(typeStringLoc), + message.getString(unitStringLoc)); + addLocalInfo(sink, message); if (!isRootc) { - transmit(parent_route_id, m); + transmit(parent_route_id, message); } else { findAndNotifyInputTargets(sink, sink.key); findAndNotifyEndpointTargets(sink, sink.key); @@ -2203,9 +2205,18 @@ void CoreBroker::linkInterfaces(ActionMessage& command) } } break; case CMD_ADD_ALIAS: - handles.addAlias(command.payload.to_string(), command.getString(targetStringLoc)); - if (!isRootc) { - routeMessage(std::move(command), parent_broker_id); + try { + handles.addAlias(command.payload.to_string(), command.getString(targetStringLoc)); + if (!isRootc) { + routeMessage(std::move(command), parent_broker_id); + } + } + catch (const std::runtime_error& rtError) { + ActionMessage error(CMD_ERROR); + error.setDestination(command.getSource()); + error.source_id = global_broker_id_local; + error.payload = rtError.what(); + routeMessage(std::move(error)); } break; default: @@ -2214,12 +2225,13 @@ void CoreBroker::linkInterfaces(ActionMessage& command) } CoreBroker::CoreBroker(bool setAsRootBroker) noexcept: - _isRoot(setAsRootBroker), isRootc(setAsRootBroker), timeoutMon(new TimeoutMonitor) + _isRoot(setAsRootBroker), isRootc(setAsRootBroker), + timeoutMon(std::make_unique()) { } CoreBroker::CoreBroker(std::string_view broker_name): - BrokerBase(broker_name), timeoutMon(new TimeoutMonitor) + BrokerBase(broker_name), timeoutMon(std::make_unique()) { } @@ -2308,24 +2320,23 @@ bool CoreBroker::connect() if (res) { disconnection.activate(); setBrokerState(BrokerState::CONNECTED); - ActionMessage setup(CMD_BROKER_SETUP); - addActionMessage(setup); + addActionMessage(CMD_BROKER_SETUP); if (!_isRoot) { - ActionMessage m(CMD_REG_BROKER); - m.source_id = GlobalFederateId{}; - m.name(getIdentifier()); + ActionMessage reg(CMD_REG_BROKER); + reg.source_id = GlobalFederateId{}; + reg.name(getIdentifier()); if (no_ping) { - setActionFlag(m, slow_responding_flag); + setActionFlag(reg, slow_responding_flag); } if (useJsonSerialization) { - setActionFlag(m, use_json_serialization_flag); + setActionFlag(reg, use_json_serialization_flag); } if (!brokerKey.empty() && brokerKey != universalKey) { - m.setStringData(getAddress(), brokerKey); + reg.setStringData(getAddress(), brokerKey); } else { - m.setStringData(getAddress()); + reg.setStringData(getAddress()); } - transmit(parent_route_id, m); + transmit(parent_route_id, reg); } LOG_SUMMARY(parent_broker_id, getIdentifier(), @@ -2368,11 +2379,11 @@ void CoreBroker::clearTimeBarrier() void CoreBroker::globalError(int32_t errorCode, std::string_view errorString) { - ActionMessage m(CMD_GLOBAL_ERROR); - m.source_id = getGlobalId(); - m.messageID = errorCode; - m.payload = errorString; - addActionMessage(m); + ActionMessage error(CMD_GLOBAL_ERROR); + error.source_id = getGlobalId(); + error.messageID = errorCode; + error.payload = errorString; + addActionMessage(error); } bool CoreBroker::isConnected() const @@ -2429,8 +2440,7 @@ void CoreBroker::unregister() void CoreBroker::disconnect() { - ActionMessage udisconnect(CMD_USER_DISCONNECT); - addActionMessage(udisconnect); + addActionMessage(CMD_USER_DISCONNECT); int cnt{0}; while (!waitForDisconnect(std::chrono::milliseconds(200))) { ++cnt; @@ -2449,7 +2459,7 @@ void CoreBroker::disconnect() getIdentifier(), fmt::format("sending disconnect again; total message count = {}", currentMessageCounter())); - addActionMessage(udisconnect); + addActionMessage(CMD_USER_DISCONNECT); } if (cnt % 13 == 0) { std::cerr << "waiting on disconnect " << std::endl; @@ -2573,39 +2583,39 @@ static InterfaceType getMatchType(InterfaceType type) } void CoreBroker::connectInterfaces( const BasicHandleInfo& origin, + uint32_t originFlags, const BasicHandleInfo& target, - uint32_t flagsSource, - uint32_t flagsDest, + uint32_t targetFlags, std::pair actions) { - // notify the target about a source - ActionMessage m(actions.first); - m.setSource(origin.handle); - m.setDestination(target.handle); - m.flags = flagsSource; - m.name(origin.key); + // notify the target about an origin + ActionMessage connect(actions.first); + connect.setSource(origin.handle); + connect.setDestination(target.handle); + connect.flags = originFlags; + connect.name(origin.key); if (!origin.type.empty()) { - m.setString(typeStringLoc, origin.type); + connect.setString(typeStringLoc, origin.type); } if (!origin.units.empty()) { - m.setString(unitStringLoc, origin.units); + connect.setString(unitStringLoc, origin.units); } - transmit(getRoute(m.dest_id), m); + transmit(getRoute(connect.dest_id), connect); - m.setAction(actions.second); - m.name(target.key); - m.clearStringData(); + connect.setAction(actions.second); + connect.name(target.key); + connect.clearStringData(); if (!target.type.empty()) { - m.setString(typeStringLoc, target.type); + connect.setString(typeStringLoc, target.type); } if (!target.units.empty()) { - m.setString(unitStringLoc, target.units); + connect.setString(unitStringLoc, target.units); } - m.flags = flagsDest; + connect.flags = targetFlags; - m.swapSourceDest(); - transmit(getRoute(m.dest_id), m); + connect.swapSourceDest(); + transmit(getRoute(connect.dest_id), connect); } void CoreBroker::findRegexMatch(const std::string& target, @@ -2634,9 +2644,10 @@ void CoreBroker::findRegexMatch(const std::string& target, destFlags = toggle_flag(destFlags, destination_target); } connectInterfaces(*hnd, + flags, (dest != nullptr) ? *dest : BasicHandleInfo(handle, getMatchType(type)), - flags, + destFlags, std::make_pair(getAction(type), getMatchAction(type, @@ -2657,15 +2668,15 @@ static constexpr auto regexKey = "REGEX:"; void CoreBroker::executeInitializationOperations(bool iterating) { if (iterating) { - ActionMessage m(CMD_INIT_GRANT); - m.source_id = global_broker_id_local; - setActionFlag(m, iteration_requested_flag); + ActionMessage init(CMD_INIT_GRANT); + init.source_id = global_broker_id_local; + setActionFlag(init, iteration_requested_flag); setBrokerState(BrokerState::CONNECTED); - mBrokers.apply([&m, this](auto& broker) { + mBrokers.apply([&init, this](auto& broker) { if ((!broker._nonLocal) && (broker.state < ConnectionState::DISCONNECTED)) { if (broker.initIterating) { - m.dest_id = broker.global_id; - transmit(broker.route, m); + init.dest_id = broker.global_id; + transmit(broker.route, init); broker.initIterating = false; broker.state = ConnectionState::CONNECTED; } @@ -2682,6 +2693,30 @@ void CoreBroker::executeInitializationOperations(bool iterating) loadTimeMonitor(true, std::string_view{}); } if (unknownHandles.hasUnknowns()) { + unknownHandles.processUnknownLinks([this](const std::string& origin, + InterfaceType originType, + const std::string& target, + InterfaceType targetType) { + const auto* originHandle = handles.getInterfaceHandle(origin, originType); + if (originHandle != nullptr) { + const auto* targetHandle = handles.getInterfaceHandle(target, targetType); + if (targetHandle != nullptr) { + if (originType == InterfaceType::PUBLICATION) { + ActionMessage datalink(CMD_DATA_LINK); + datalink.name(originHandle->key); + datalink.setString(targetStringLoc, targetHandle->key); + linkInterfaces(datalink); + } else if (originType == InterfaceType::ENDPOINT && + targetType == InterfaceType::ENDPOINT) { + ActionMessage eptlink(CMD_ENDPOINT_LINK); + eptlink.name(originHandle->key); + eptlink.setString(targetStringLoc, targetHandle->key); + linkInterfaces(eptlink); + } + // TODO(PT):: make this work for filters + } + } + }); std::vector> foundAliasHandles; foundAliasHandles.resize(4); bool useRegex{false}; @@ -2689,8 +2724,8 @@ void CoreBroker::executeInitializationOperations(bool iterating) [this, &foundAliasHandles, &useRegex](const std::string& target, InterfaceType type, UnknownHandleManager::TargetInfo /*target*/) { - const auto* p = handles.getInterfaceHandle(target, type); - if (p == nullptr) { + const auto* info = handles.getInterfaceHandle(target, type); + if (info == nullptr) { if (!useRegex) { if (target.compare(0, 6, regexKey) == 0) { useRegex = true; @@ -2717,26 +2752,26 @@ void CoreBroker::executeInitializationOperations(bool iterating) }); if (!foundAliasHandles[0].empty()) { for (const auto& target : foundAliasHandles[0]) { - auto* p = handles.getInterfaceHandle(target, InterfaceType::PUBLICATION); - findAndNotifyPublicationTargets(*p, target); + auto* info = handles.getInterfaceHandle(target, InterfaceType::PUBLICATION); + findAndNotifyPublicationTargets(*info, target); } } if (!foundAliasHandles[1].empty()) { for (const auto& target : foundAliasHandles[1]) { - auto* p = handles.getInterfaceHandle(target, InterfaceType::INPUT); - findAndNotifyInputTargets(*p, target); + auto* info = handles.getInterfaceHandle(target, InterfaceType::INPUT); + findAndNotifyInputTargets(*info, target); } } if (!foundAliasHandles[2].empty()) { for (const auto& target : foundAliasHandles[2]) { - auto* p = handles.getInterfaceHandle(target, InterfaceType::ENDPOINT); - findAndNotifyEndpointTargets(*p, target); + auto* info = handles.getInterfaceHandle(target, InterfaceType::ENDPOINT); + findAndNotifyEndpointTargets(*info, target); } } if (!foundAliasHandles[3].empty()) { for (const auto& target : foundAliasHandles[3]) { - auto* p = handles.getInterfaceHandle(target, InterfaceType::FILTER); - findAndNotifyFilterTargets(*p, target); + auto* info = handles.getInterfaceHandle(target, InterfaceType::FILTER); + findAndNotifyFilterTargets(*info, target); } } if (useRegex) { @@ -2747,12 +2782,14 @@ void CoreBroker::executeInitializationOperations(bool iterating) findRegexMatch(target, type, tinfo.first, tinfo.second); } }); - unknownHandles.clearUnknownsIf([this](const std::string& target, - InterfaceType /*type*/, - UnknownHandleManager::TargetInfo /*tinfo*/) { + unknownHandles.clearUnknownsIf([](const std::string& target, + InterfaceType /*type*/, + UnknownHandleManager::TargetInfo /*tinfo*/) { return (target.compare(0, 6, regexKey) == 0); }); } + /** now do a check on the unknownLinks*/ + if (unknownHandles.hasNonOptionalUnknowns()) { if (unknownHandles.hasRequiredUnknowns()) { ActionMessage eMiss(CMD_ERROR); @@ -2795,10 +2832,10 @@ void CoreBroker::executeInitializationOperations(bool iterating) } } - ActionMessage m(CMD_INIT_GRANT); - m.source_id = global_broker_id_local; + ActionMessage init(CMD_INIT_GRANT); + init.source_id = global_broker_id_local; setBrokerState(BrokerState::OPERATING); - broadcast(m); + broadcast(init); timeCoord->enteringExecMode(); auto res = timeCoord->checkExecEntry(); if (res == MessageProcessingResult::NEXT_STEP) { @@ -2814,16 +2851,18 @@ void CoreBroker::findAndNotifyInputTargets(BasicHandleInfo& handleInfo, const st auto* pub = handles.findHandle(target.first); if (pub == nullptr) { connectInterfaces(handleInfo, + handleInfo.flags, BasicHandleInfo(target.first.fed_id, target.first.handle, InterfaceType::PUBLICATION), - handleInfo.flags, + target.second, std::make_pair(CMD_ADD_SUBSCRIBER, CMD_ADD_PUBLISHER)); } else { connectInterfaces(handleInfo, - *pub, handleInfo.flags, + *pub, + target.second, std::make_pair(CMD_ADD_SUBSCRIBER, CMD_ADD_PUBLISHER)); } @@ -2839,18 +2878,19 @@ void CoreBroker::findAndNotifyPublicationTargets(BasicHandleInfo& handleInfo, auto subHandles = unknownHandles.checkForPublications(key); for (const auto& sub : subHandles) { connectInterfaces(handleInfo, - BasicHandleInfo(sub.first.fed_id, sub.first.handle, InterfaceType::INPUT), sub.second, + BasicHandleInfo(sub.first.fed_id, sub.first.handle, InterfaceType::INPUT), + handleInfo.flags, std::make_pair(CMD_ADD_PUBLISHER, CMD_ADD_SUBSCRIBER)); } auto Pubtargets = unknownHandles.checkForLinks(key); for (const auto& sub : Pubtargets) { - ActionMessage m(CMD_ADD_NAMED_INPUT); - m.name(sub); - m.setSource(handleInfo.handle); - checkForNamedInterface(m); + ActionMessage link(CMD_ADD_NAMED_INPUT); + link.name(sub); + link.setSource(handleInfo.handle); + checkForNamedInterface(link); } if (!(subHandles.empty() && Pubtargets.empty())) { unknownHandles.clearPublication(key); @@ -2859,8 +2899,8 @@ void CoreBroker::findAndNotifyPublicationTargets(BasicHandleInfo& handleInfo, void CoreBroker::findAndNotifyEndpointTargets(BasicHandleInfo& handleInfo, const std::string& key) { - auto Handles = unknownHandles.checkForEndpoints(key); - for (const auto& target : Handles) { + auto uHandles = unknownHandles.checkForEndpoints(key); + for (const auto& target : uHandles) { const auto* iface = handles.findHandle(target.first); auto destFlags = target.second; if (iface->handleType != InterfaceType::FILTER) { @@ -2868,25 +2908,27 @@ void CoreBroker::findAndNotifyEndpointTargets(BasicHandleInfo& handleInfo, const } connectInterfaces(handleInfo, - *iface, target.second, + *iface, + destFlags, std::make_pair(CMD_ADD_ENDPOINT, (iface->handleType != InterfaceType::FILTER) ? CMD_ADD_ENDPOINT : CMD_ADD_FILTER)); } - auto EptTargets = unknownHandles.checkForEndpointLinks(key); - for (const auto& ept : EptTargets) { - ActionMessage m(CMD_ADD_NAMED_ENDPOINT); - m.name(ept); - m.setSource(handleInfo.handle); - setActionFlag(m, destination_target); - m.counter = static_cast(InterfaceType::ENDPOINT); - checkForNamedInterface(m); + + auto eptTargets = unknownHandles.checkForEndpointLinks(key); + for (const auto& ept : eptTargets) { + ActionMessage link(CMD_ADD_NAMED_ENDPOINT); + link.name(ept); + link.setSource(handleInfo.handle); + setActionFlag(link, destination_target); + link.counter = static_cast(InterfaceType::ENDPOINT); + checkForNamedInterface(link); } - if (!Handles.empty()) { + if (!(uHandles.empty() && eptTargets.empty())) { unknownHandles.clearEndpoint(key); } } @@ -2900,37 +2942,38 @@ void CoreBroker::findAndNotifyFilterTargets(BasicHandleInfo& handleInfo, const s flags |= make_flags(clone_flag); } connectInterfaces(handleInfo, + flags, BasicHandleInfo(target.first.fed_id, target.first.handle, InterfaceType::ENDPOINT), - flags, + flags, std::make_pair(CMD_ADD_FILTER, CMD_ADD_ENDPOINT)); } auto FiltDestTargets = unknownHandles.checkForFilterDestTargets(key); for (const auto& target : FiltDestTargets) { - ActionMessage m(CMD_ADD_NAMED_ENDPOINT); - m.name(target); - m.setSource(handleInfo.handle); - m.flags = handleInfo.flags; - setActionFlag(m, destination_target); + ActionMessage link(CMD_ADD_NAMED_ENDPOINT); + link.name(target); + link.setSource(handleInfo.handle); + link.flags = handleInfo.flags; + setActionFlag(link, destination_target); if (checkActionFlag(handleInfo, clone_flag)) { - setActionFlag(m, clone_flag); + setActionFlag(link, clone_flag); } - checkForNamedInterface(m); + checkForNamedInterface(link); } auto FiltSourceTargets = unknownHandles.checkForFilterSourceTargets(key); for (const auto& target : FiltSourceTargets) { - ActionMessage m(CMD_ADD_NAMED_ENDPOINT); - m.name(target); - m.flags = handleInfo.flags; - m.setSource(handleInfo.handle); + ActionMessage link(CMD_ADD_NAMED_ENDPOINT); + link.name(target); + link.flags = handleInfo.flags; + link.setSource(handleInfo.handle); if (checkActionFlag(handleInfo, clone_flag)) { - setActionFlag(m, clone_flag); + setActionFlag(link, clone_flag); } - checkForNamedInterface(m); + checkForNamedInterface(link); } if (!(Handles.empty() && FiltDestTargets.empty() && FiltSourceTargets.empty())) { unknownHandles.clearFilter(key); @@ -2965,7 +3008,7 @@ void CoreBroker::processError(ActionMessage& command) return; } - auto* brk = getBrokerById(GlobalBrokerId(command.source_id)); + auto* brk = getBrokerById(GlobalBrokerId{command.source_id}); if (brk == nullptr) { auto fed = mFederates.find(command.source_id); if (fed != mFederates.end()) { @@ -3007,99 +3050,103 @@ void CoreBroker::processError(ActionMessage& command) } } +void CoreBroker::disconnectTiming(ActionMessage& command) +{ + if (hasTimeDependency) { + if (!enteredExecutionMode) { + if (getBrokerState() >= BrokerState::OPERATING) { + if (timeCoord->processTimeMessage(command) != TimeProcessingResult::NOT_PROCESSED) { + auto res = timeCoord->checkExecEntry(); + if (res == MessageProcessingResult::NEXT_STEP) { + enteredExecutionMode = true; + } + } + } + } else { + if (timeCoord->processTimeMessage(command) != TimeProcessingResult::NOT_PROCESSED) { + timeCoord->updateTimeFactors(); + } + } + } +} + +void CoreBroker::processBrokerDisconnect(ActionMessage& command, BasicBrokerInfo* brk) +{ + if (!isRootc) { + if (command.source_id == higher_broker_id) { + LOG_CONNECTIONS(parent_broker_id, getIdentifier(), "got disconnect from parent"); + sendDisconnect(CMD_GLOBAL_DISCONNECT); + addActionMessage(CMD_STOP); + return; + } + } + + if (brk != nullptr) { + LOG_CONNECTIONS(parent_broker_id, + getIdentifier(), + fmt::format("got disconnect from {}({})", + brk->name, + command.source_id.baseValue())); + disconnectBroker(*brk); + } + + if ((getAllConnectionState() >= ConnectionState::DISCONNECTED)) { + timeCoord->disconnect(); + if (!isRootc) { + ActionMessage dis(CMD_DISCONNECT); + dis.source_id = global_broker_id_local; + transmit(parent_route_id, dis); + } else { + if ((brk != nullptr) && (!brk->_nonLocal)) { + if (!checkActionFlag(command, error_flag)) { + ActionMessage dis((brk->_core) ? CMD_DISCONNECT_CORE_ACK : + CMD_DISCONNECT_BROKER_ACK); + dis.source_id = global_broker_id_local; + dis.dest_id = brk->global_id; + transmit(brk->route, dis); + } + brk->_sent_disconnect_ack = true; + removeRoute(brk->route); + } + addActionMessage(CMD_STOP); + } + } else { + if ((brk != nullptr) && (!brk->_nonLocal)) { + if (!checkActionFlag(command, error_flag)) { + ActionMessage dis((brk->_core) ? CMD_DISCONNECT_CORE_ACK : + CMD_DISCONNECT_BROKER_ACK); + dis.source_id = global_broker_id_local; + dis.dest_id = brk->global_id; + transmit(brk->route, dis); + } + brk->_sent_disconnect_ack = true; + if ((!isRootc) && (getBrokerState() < BrokerState::OPERATING)) { + command.setAction((brk->_core) ? CMD_DISCONNECT_CORE : CMD_DISCONNECT_BROKER); + transmit(parent_route_id, command); + } + removeRoute(brk->route); + } else { + if ((!isRootc) && (getBrokerState() < BrokerState::OPERATING)) { + if (brk != nullptr) { + command.setAction((brk->_core) ? CMD_DISCONNECT_CORE : CMD_DISCONNECT_BROKER); + transmit(parent_route_id, command); + } + } + } + } +} + void CoreBroker::processDisconnectCommand(ActionMessage& command) { - auto* brk = getBrokerById(GlobalBrokerId(command.source_id)); + auto* brk = getBrokerById(GlobalBrokerId{command.source_id}); switch (command.action()) { case CMD_DISCONNECT: case CMD_PRIORITY_DISCONNECT: if (command.dest_id == global_broker_id_local) { // deal with the time implications of the message - if (hasTimeDependency) { - if (!enteredExecutionMode) { - if (getBrokerState() >= BrokerState::OPERATING) { - if (timeCoord->processTimeMessage(command) != - TimeProcessingResult::NOT_PROCESSED) { - auto res = timeCoord->checkExecEntry(); - if (res == MessageProcessingResult::NEXT_STEP) { - enteredExecutionMode = true; - } - } - } - } else { - if (timeCoord->processTimeMessage(command) != - TimeProcessingResult::NOT_PROCESSED) { - timeCoord->updateTimeFactors(); - } - } - } + disconnectTiming(command); } else if (command.dest_id == parent_broker_id) { - if (!isRootc) { - if (command.source_id == higher_broker_id) { - LOG_CONNECTIONS(parent_broker_id, - getIdentifier(), - "got disconnect from parent"); - sendDisconnect(CMD_GLOBAL_DISCONNECT); - addActionMessage(CMD_STOP); - return; - } - } - - if (brk != nullptr) { - LOG_CONNECTIONS(parent_broker_id, - getIdentifier(), - fmt::format("got disconnect from {}({})", - brk->name, - command.source_id.baseValue())); - disconnectBroker(*brk); - } - - if ((getAllConnectionState() >= ConnectionState::DISCONNECTED)) { - timeCoord->disconnect(); - if (!isRootc) { - ActionMessage dis(CMD_DISCONNECT); - dis.source_id = global_broker_id_local; - transmit(parent_route_id, dis); - } else { - if ((brk != nullptr) && (!brk->_nonLocal)) { - if (!checkActionFlag(command, error_flag)) { - ActionMessage dis((brk->_core) ? CMD_DISCONNECT_CORE_ACK : - CMD_DISCONNECT_BROKER_ACK); - dis.source_id = global_broker_id_local; - dis.dest_id = brk->global_id; - transmit(brk->route, dis); - } - brk->_sent_disconnect_ack = true; - removeRoute(brk->route); - } - addActionMessage(CMD_STOP); - } - } else { - if ((brk != nullptr) && (!brk->_nonLocal)) { - if (!checkActionFlag(command, error_flag)) { - ActionMessage dis((brk->_core) ? CMD_DISCONNECT_CORE_ACK : - CMD_DISCONNECT_BROKER_ACK); - dis.source_id = global_broker_id_local; - dis.dest_id = brk->global_id; - transmit(brk->route, dis); - } - brk->_sent_disconnect_ack = true; - if ((!isRootc) && (getBrokerState() < BrokerState::OPERATING)) { - command.setAction((brk->_core) ? CMD_DISCONNECT_CORE : - CMD_DISCONNECT_BROKER); - transmit(parent_route_id, command); - } - removeRoute(brk->route); - } else { - if ((!isRootc) && (getBrokerState() < BrokerState::OPERATING)) { - if (brk != nullptr) { - command.setAction((brk->_core) ? CMD_DISCONNECT_CORE : - CMD_DISCONNECT_BROKER); - transmit(parent_route_id, command); - } - } - } - } + processBrokerDisconnect(command, brk); } else if (command.dest_id == mTimeMonitorLocalFederateId) { processTimeMonitorMessage(command); } else { @@ -3122,31 +3169,31 @@ void CoreBroker::processDisconnectCommand(ActionMessage& command) void CoreBroker::checkInFlightQueries(GlobalBrokerId brkid) { - for (auto& mb : mapBuilders) { - auto& builder = std::get<0>(mb); - auto& requestors = std::get<1>(mb); + for (auto& builderData : mapBuilders) { + auto& builder = std::get<0>(builderData); + auto& requesters = std::get<1>(builderData); if (builder.isCompleted()) { return; } if (builder.clearComponents(brkid.baseValue())) { auto str = builder.generate(); - for (int ii = 0; ii < static_cast(requestors.size()) - 1; ++ii) { - if (requestors[ii].dest_id == global_broker_id_local) { - activeQueries.setDelayedValue(requestors[ii].messageID, str); + for (int ii = 0; ii < static_cast(requesters.size()) - 1; ++ii) { + if (requesters[ii].dest_id == global_broker_id_local) { + activeQueries.setDelayedValue(requesters[ii].messageID, str); } else { - requestors[ii].payload = str; - routeMessage(std::move(requestors[ii])); + requesters[ii].payload = str; + routeMessage(std::move(requesters[ii])); } } - if (requestors.back().dest_id == global_broker_id_local) { - activeQueries.setDelayedValue(requestors.back().messageID, std::move(str)); + if (requesters.back().dest_id == global_broker_id_local) { + activeQueries.setDelayedValue(requesters.back().messageID, std::move(str)); } else { - requestors.back().payload = std::move(str); - routeMessage(std::move(requestors.back())); + requesters.back().payload = std::move(str); + routeMessage(std::move(requesters.back())); } - requestors.clear(); - if (std::get<2>(mb) == QueryReuse::DISABLED) { + requesters.clear(); + if (std::get<2>(builderData) == QueryReuse::DISABLED) { builder.reset(); } } @@ -3378,6 +3425,7 @@ static const std::set querySet{"isinit", "global_state", "global_flush", "current_state", + "unconnected_interfaces", "logs"}; static const std::map> mapIndex{ @@ -3390,6 +3438,7 @@ static const std::map> ma {"global_time_debugging", {GLOBAL_TIME_DEBUGGING, QueryReuse::DISABLED}}, {"global_status", {GLOBAL_STATUS, QueryReuse::DISABLED}}, {"barriers", {BARRIERS, QueryReuse::DISABLED}}, + {"unconnected_interfaces", {UNCONNECTED_INTERFACES, QueryReuse::DISABLED}}, {"global_flush", {GLOBAL_FLUSH, QueryReuse::DISABLED}}}; std::string CoreBroker::quickBrokerQueries(std::string_view request) const @@ -3534,20 +3583,20 @@ std::string CoreBroker::generateQueryAnswer(std::string_view request, bool force } if (request == "global_status") { if (!isConnected()) { - Json::Value gs; - addBaseInformation(gs, !isRootc); - gs["status"] = "disconnected"; - gs["timestep"] = -1; - return fileops::generateJsonString(gs); + Json::Value json; + addBaseInformation(json, !isRootc); + json["status"] = "disconnected"; + json["timestep"] = -1; + return fileops::generateJsonString(json); } } if (request.compare(0, 7, "rename:") == 0) { return generateRename(request.substr(7)); } - auto mi = mapIndex.find(request); - if (mi != mapIndex.end()) { - auto index = mi->second.first; - if (isValidIndex(index, mapBuilders) && mi->second.second == QueryReuse::ENABLED) { + auto mapping = mapIndex.find(request); + if (mapping != mapIndex.end()) { + auto index = mapping->second.first; + if (isValidIndex(index, mapBuilders) && mapping->second.second == QueryReuse::ENABLED) { auto& builder = std::get<0>(mapBuilders[index]); if (builder.isCompleted()) { auto center = generateMapObjectCounter(); @@ -3561,9 +3610,9 @@ std::string CoreBroker::generateQueryAnswer(std::string_view request, bool force } } - initializeMapBuilder(request, index, mi->second.second, force_ordering); + initializeMapBuilder(request, index, mapping->second.second, force_ordering); if (std::get<0>(mapBuilders[index]).isCompleted()) { - if (mi->second.second == QueryReuse::ENABLED) { + if (mapping->second.second == QueryReuse::ENABLED) { auto center = generateMapObjectCounter(); std::get<0>(mapBuilders[index]).setCounterCode(center); } @@ -3608,45 +3657,46 @@ std::string CoreBroker::generateQueryAnswer(std::string_view request, bool force std::string CoreBroker::generateGlobalStatus(fileops::JsonMapBuilder& builder) { auto cstate = generateQueryAnswer("current_state", false); - auto jv = fileops::loadJsonStr(cstate); + auto jsonStatus = fileops::loadJsonStr(cstate); std::string state; - if (jv["federates"][0].isObject()) { - state = jv["state"].asString(); + if (jsonStatus["federates"][0].isObject()) { + state = jsonStatus["state"].asString(); } else { state = "init_requested"; } if (state != "operating") { - Json::Value v; - v["status"] = state; - v["timestep"] = -1; - return fileops::generateJsonString(v); + Json::Value json; + json["status"] = state; + json["timestep"] = -1; + return fileops::generateJsonString(json); } - Time mv{Time::maxVal()}; + Time minTime{Time::maxVal()}; if (!builder.getJValue()["cores"][0].isObject()) { state = "init_requested"; } - for (auto& cr : builder.getJValue()["cores"]) { - for (auto& fed : cr["federates"]) { - auto dv = fed["granted_time"].asDouble(); - if (dv < mv) { - mv = dv; + for (auto& core : builder.getJValue()["cores"]) { + for (auto& fed : core["federates"]) { + auto granted = fed["granted_time"].asDouble(); + if (granted < minTime) { + minTime = granted; } } } - std::string tste = (mv >= timeZero) ? std::string("operating") : std::string("init_requested"); + const std::string tste = + (minTime >= timeZero) ? std::string("operating") : std::string("init_requested"); - Json::Value v; + Json::Value json; if (tste != "operating") { - v["status"] = tste; - v["timestep"] = -1; + json["status"] = tste; + json["timestep"] = -1; } else { - v["status"] = jv; - v["timestep"] = builder.getJValue(); + json["status"] = jsonStatus; + json["timestep"] = builder.getJValue(); } - return fileops::generateJsonString(v); + return fileops::generateJsonString(json); } std::string CoreBroker::getNameList(std::string_view gidString) const @@ -3787,19 +3837,85 @@ void CoreBroker::initializeMapBuilder(std::string_view request, timeCoord->generateDebuggingTimeInfo(base["time"]); } break; + case UNCONNECTED_INTERFACES: + if (!global_values.empty()) { + Json::Value tagBlock = Json::objectValue; + for (const auto& global : global_values) { + tagBlock[global.first] = global.second; + } + base["tags"] = tagBlock; + } + const auto& aliases = handles.getAliases(); + if (!aliases.empty()) { + base["aliases"] = Json::arrayValue; + for (const auto& alias : aliases) { + const std::string_view interfaceName = alias.first; + const auto& aliasNames = alias.second; + for (const auto& aliasName : aliasNames) { + Json::Value aliasSet = Json::arrayValue; + aliasSet.append(std::string(interfaceName)); + aliasSet.append(std::string(aliasName)); + base["aliases"].append(std::move(aliasSet)); + } + } + } + if (unknownHandles.hasUnknowns()) { + base["unknown_publications"] = Json::arrayValue; + base["unknown_inputs"] = Json::arrayValue; + base["unknown_endpoints"] = Json::arrayValue; + auto unknownProcessor = [&base](const std::string& name, + InterfaceType type, + UnknownHandleManager::TargetInfo /*target*/) { + switch (type) { + case InterfaceType::INPUT: + base["unknown_inputs"].append(name); + break; + case InterfaceType::PUBLICATION: + base["unknown_publications"].append(name); + break; + case InterfaceType::ENDPOINT: + base["unknown_endpoints"].append(name); + break; + default: + break; + } + }; + unknownHandles.processUnknowns(unknownProcessor); + auto unknownLinkProcessor = [&base](const std::string& origin, + InterfaceType type1, + const std::string& target, + InterfaceType type2) { + switch (type2) { + case InterfaceType::INPUT: + base["unknown_inputs"].append(target); + base["unknown_publications"].append(origin); + break; + case InterfaceType::ENDPOINT: + base["unknown_endpoints"].append(target); + if (type1 == InterfaceType::ENDPOINT) { + base["unknown_endpoints"].append(origin); + } + break; + default: + break; + } + }; + unknownHandles.processUnknownLinks(unknownLinkProcessor); + } + break; } } -void CoreBroker::processLocalQuery(const ActionMessage& m) +void CoreBroker::processLocalQuery(const ActionMessage& message) { - bool force_ordered = - (m.action() == CMD_QUERY_ORDERED || m.action() == CMD_BROKER_QUERY_ORDERED); + const bool force_ordered = + (message.action() == CMD_QUERY_ORDERED || message.action() == CMD_BROKER_QUERY_ORDERED); ActionMessage queryRep(force_ordered ? CMD_QUERY_REPLY_ORDERED : CMD_QUERY_REPLY); queryRep.source_id = global_broker_id_local; - queryRep.dest_id = m.source_id; - queryRep.messageID = m.messageID; - queryRep.payload = generateQueryAnswer(m.payload.to_string(), force_ordered); - queryRep.counter = m.counter; + queryRep.dest_id = message.source_id; + queryRep.messageID = message.messageID; + queryRep.payload = generateQueryAnswer(message.payload.to_string(), force_ordered); + queryRep.counter = message.counter; if (queryRep.payload.to_string() == "#wait") { if (queryRep.dest_id == global_broker_id_local) { if (queryTimeouts.empty()) { @@ -3807,11 +3923,12 @@ void CoreBroker::processLocalQuery(const ActionMessage& m) } queryTimeouts.emplace_back(queryRep.messageID, std::chrono::steady_clock::now()); } - std::get<1>(mapBuilders[mapIndex.at(m.payload.to_string()).first]).push_back(queryRep); + std::get<1>(mapBuilders[mapIndex.at(message.payload.to_string()).first]) + .push_back(queryRep); } else if (queryRep.dest_id == global_broker_id_local) { - activeQueries.setDelayedValue(m.messageID, std::string(queryRep.payload.to_string())); + activeQueries.setDelayedValue(message.messageID, std::string(queryRep.payload.to_string())); } else { - routeMessage(std::move(queryRep), m.source_id); + routeMessage(std::move(queryRep), message.source_id); } } @@ -3906,49 +4023,51 @@ void CoreBroker::processQueryCommand(ActionMessage& cmd) } } -void CoreBroker::processQuery(ActionMessage& m) +void CoreBroker::processQuery(ActionMessage& message) { - bool force_ordered = - (m.action() == CMD_QUERY_ORDERED || m.action() == CMD_BROKER_QUERY_ORDERED); - const auto& target = m.getString(targetStringLoc); + const bool force_ordered = + (message.action() == CMD_QUERY_ORDERED || message.action() == CMD_BROKER_QUERY_ORDERED); + const auto& target = message.getString(targetStringLoc); if ((target == getIdentifier() || target == "broker") || (isRootc && (target == "root" || target == "federation"))) { - processLocalQuery(m); + processLocalQuery(message); } else if (isRootc && target == "gid_to_name") { ActionMessage queryResp(force_ordered ? CMD_QUERY_REPLY_ORDERED : CMD_QUERY_REPLY); - queryResp.dest_id = m.source_id; + queryResp.dest_id = message.source_id; queryResp.source_id = global_broker_id_local; - queryResp.messageID = m.messageID; - queryResp.payload = getNameList(m.payload.to_string()); + queryResp.messageID = message.messageID; + queryResp.payload = getNameList(message.payload.to_string()); if (queryResp.dest_id == global_broker_id_local) { - activeQueries.setDelayedValue(m.messageID, std::string(queryResp.payload.to_string())); + activeQueries.setDelayedValue(message.messageID, + std::string(queryResp.payload.to_string())); } else { transmit(getRoute(queryResp.dest_id), queryResp); } } else if ((isRootc) && (target == "global" || target == "global_value")) { ActionMessage queryResp(force_ordered ? CMD_QUERY_REPLY_ORDERED : CMD_QUERY_REPLY); - queryResp.dest_id = m.source_id; + queryResp.dest_id = message.source_id; queryResp.source_id = global_broker_id_local; - queryResp.messageID = m.messageID; + queryResp.messageID = message.messageID; - auto gfind = global_values.find(std::string(m.payload.to_string())); + auto gfind = global_values.find(std::string(message.payload.to_string())); if (gfind != global_values.end()) { if (target == "global_value") { queryResp.payload = gfind->second; } else { - Json::Value v; - v["name"] = std::string(m.payload.to_string()); - v["value"] = gfind->second; - queryResp.payload = fileops::generateJsonString(v); - } - } else if (m.payload.to_string() == "list") { - queryResp.payload = - generateStringVector(global_values, [](const auto& gv) { return gv.first; }); - } else if (m.payload.to_string() == "all") { + Json::Value json; + json["name"] = std::string(message.payload.to_string()); + json["value"] = gfind->second; + queryResp.payload = fileops::generateJsonString(json); + } + } else if (message.payload.to_string() == "list") { + queryResp.payload = generateStringVector(global_values, [](const auto& globalValue) { + return globalValue.first; + }); + } else if (message.payload.to_string() == "all") { fileops::JsonMapBuilder globalSet; - auto& jv = globalSet.getJValue(); + auto& json = globalSet.getJValue(); for (auto& val : global_values) { - jv[val.first] = val.second; + json[val.first] = val.second; } queryResp.payload = globalSet.generate(); } else { @@ -3956,7 +4075,8 @@ void CoreBroker::processQuery(ActionMessage& m) generateJsonErrorResponse(JsonErrorCodes::NOT_FOUND, "Global value not found"); } if (queryResp.dest_id == global_broker_id_local) { - activeQueries.setDelayedValue(m.messageID, std::string(queryResp.payload.to_string())); + activeQueries.setDelayedValue(message.messageID, + std::string(queryResp.payload.to_string())); } else { transmit(getRoute(queryResp.dest_id), queryResp); } @@ -3966,8 +4086,8 @@ void CoreBroker::processQuery(ActionMessage& m) std::string response; if (fed != mFederates.end()) { route = fed->route; - m.dest_id = fed->parent; - response = checkFedQuery(*fed, m.payload.to_string()); + message.dest_id = fed->parent; + response = checkFedQuery(*fed, message.payload.to_string()); if (response.empty() && fed->state >= ConnectionState::ERROR_STATE) { route = parent_route_id; switch (fed->state) { @@ -3988,8 +4108,8 @@ void CoreBroker::processQuery(ActionMessage& m) auto broker = mBrokers.find(target); if (broker != mBrokers.end()) { route = broker->route; - m.dest_id = broker->global_id; - response = checkBrokerQuery(*broker, m.payload.to_string()); + message.dest_id = broker->global_id; + response = checkBrokerQuery(*broker, message.payload.to_string()); if (response.empty() && broker->state >= ConnectionState::ERROR_STATE) { route = parent_route_id; switch (broker->state) { @@ -4008,7 +4128,7 @@ void CoreBroker::processQuery(ActionMessage& m) break; } } - } else if (isRootc && m.payload.to_string() == "exists") { + } else if (isRootc && message.payload.to_string() == "exists") { response = "false"; } } @@ -4017,25 +4137,25 @@ void CoreBroker::processQuery(ActionMessage& m) response = generateJsonErrorResponse(JsonErrorCodes::NOT_FOUND, "query not valid"); } ActionMessage queryResp(force_ordered ? CMD_QUERY_REPLY_ORDERED : CMD_QUERY_REPLY); - queryResp.dest_id = m.source_id; + queryResp.dest_id = message.source_id; queryResp.source_id = global_broker_id_local; - queryResp.messageID = m.messageID; + queryResp.messageID = message.messageID; queryResp.payload = response; if (queryResp.dest_id == global_broker_id_local) { - activeQueries.setDelayedValue(m.messageID, + activeQueries.setDelayedValue(message.messageID, std::string(queryResp.payload.to_string())); } else { transmit(getRoute(queryResp.dest_id), queryResp); } } else { - if (m.source_id == global_broker_id_local) { + if (message.source_id == global_broker_id_local) { if (queryTimeouts.empty()) { setTickForwarding(TickForwardingReasons::QUERY_TIMEOUT, true); } - queryTimeouts.emplace_back(m.messageID, std::chrono::steady_clock::now()); + queryTimeouts.emplace_back(message.messageID, std::chrono::steady_clock::now()); } - transmit(route, m); + transmit(route, message); } } } @@ -4044,14 +4164,15 @@ void CoreBroker::checkQueryTimeouts() { if (!queryTimeouts.empty()) { auto ctime = std::chrono::steady_clock::now(); - for (auto& qt : queryTimeouts) { - if (activeQueries.isRecognized(qt.first) && !activeQueries.isCompleted(qt.first)) { - if (Time(ctime - qt.second) > queryTimeout) { + for (auto& qtimeout : queryTimeouts) { + if (activeQueries.isRecognized(qtimeout.first) && + !activeQueries.isCompleted(qtimeout.first)) { + if (Time(ctime - qtimeout.second) > queryTimeout) { activeQueries.setDelayedValue( - qt.first, + qtimeout.first, generateJsonErrorResponse(JsonErrorCodes::GATEWAY_TIMEOUT, "query timeout")); - qt.first = 0; + qtimeout.first = 0; } } } @@ -4064,18 +4185,18 @@ void CoreBroker::checkQueryTimeouts() } } -void CoreBroker::processQueryResponse(const ActionMessage& m) +void CoreBroker::processQueryResponse(const ActionMessage& message) { - if (m.counter == GENERAL_QUERY) { - activeQueries.setDelayedValue(m.messageID, std::string(m.payload.to_string())); + if (message.counter == GENERAL_QUERY) { + activeQueries.setDelayedValue(message.messageID, std::string(message.payload.to_string())); return; } - if (isValidIndex(m.counter, mapBuilders)) { - auto& builder = std::get<0>(mapBuilders[m.counter]); - auto& requestors = std::get<1>(mapBuilders[m.counter]); - if (builder.addComponent(std::string(m.payload.to_string()), m.messageID)) { + if (isValidIndex(message.counter, mapBuilders)) { + auto& builder = std::get<0>(mapBuilders[message.counter]); + auto& requesters = std::get<1>(mapBuilders[message.counter]); + if (builder.addComponent(std::string(message.payload.to_string()), message.messageID)) { std::string str; - switch (m.counter) { + switch (message.counter) { case GLOBAL_STATUS: str = generateGlobalStatus(builder); break; @@ -4087,23 +4208,23 @@ void CoreBroker::processQueryResponse(const ActionMessage& m) break; } - for (int ii = 0; ii < static_cast(requestors.size()) - 1; ++ii) { - if (requestors[ii].dest_id == global_broker_id_local) { - activeQueries.setDelayedValue(requestors[ii].messageID, str); + for (int ii = 0; ii < static_cast(requesters.size()) - 1; ++ii) { + if (requesters[ii].dest_id == global_broker_id_local) { + activeQueries.setDelayedValue(requesters[ii].messageID, str); } else { - requestors[ii].payload = str; - routeMessage(std::move(requestors[ii])); + requesters[ii].payload = str; + routeMessage(std::move(requesters[ii])); } } - if (requestors.back().dest_id == global_broker_id_local) { - activeQueries.setDelayedValue(requestors.back().messageID, std::move(str)); + if (requesters.back().dest_id == global_broker_id_local) { + activeQueries.setDelayedValue(requesters.back().messageID, std::move(str)); } else { - requestors.back().payload = std::move(str); - routeMessage(std::move(requestors.back())); + requesters.back().payload = std::move(str); + routeMessage(std::move(requesters.back())); } - requestors.clear(); - if (std::get<2>(mapBuilders[m.counter]) == QueryReuse::DISABLED) { + requesters.clear(); + if (std::get<2>(mapBuilders[message.counter]) == QueryReuse::DISABLED) { builder.reset(); } else { builder.setCounterCode(generateMapObjectCounter()); @@ -4112,9 +4233,9 @@ void CoreBroker::processQueryResponse(const ActionMessage& m) } } -void CoreBroker::processLocalCommandInstruction(ActionMessage& m) +void CoreBroker::processLocalCommandInstruction(ActionMessage& message) { - auto [processed, res] = processBaseCommands(m); + auto [processed, res] = processBaseCommands(message); if (processed) { return; } @@ -4162,8 +4283,8 @@ void CoreBroker::processLocalCommandInstruction(ActionMessage& m) } else { auto warnString = fmt::format(" unrecognized command instruction \"{}\"", res[0]); LOG_WARNING(global_broker_id_local, getIdentifier(), warnString); - if (m.source_id != global_broker_id_local) { - ActionMessage warn(CMD_WARNING, global_broker_id_local, m.source_id); + if (message.source_id != global_broker_id_local) { + ActionMessage warn(CMD_WARNING, global_broker_id_local, message.source_id); warn.payload = std::move(warnString); warn.messageID = HELICS_LOG_LEVEL_WARNING; warn.setString(0, getIdentifier()); @@ -4172,36 +4293,36 @@ void CoreBroker::processLocalCommandInstruction(ActionMessage& m) } } -void CoreBroker::processCommandInstruction(ActionMessage& m) +void CoreBroker::processCommandInstruction(ActionMessage& message) { - if (m.dest_id == global_broker_id_local) { - processLocalCommandInstruction(m); - } else if (m.dest_id == parent_broker_id) { - const auto& target = m.getString(targetStringLoc); + if (message.dest_id == global_broker_id_local) { + processLocalCommandInstruction(message); + } else if (message.dest_id == parent_broker_id) { + const auto& target = message.getString(targetStringLoc); if (target == "broker" || target == getIdentifier()) { - processLocalCommandInstruction(m); + processLocalCommandInstruction(message); } else if (isRootc) { if (target == "federation" || target == "root") { - processLocalCommandInstruction(m); + processLocalCommandInstruction(message); } else { route_id route = parent_route_id; auto fed = mFederates.find(target); if (fed != mFederates.end()) { route = fed->route; - m.dest_id = fed->global_id; - transmit(route, std::move(m)); + message.dest_id = fed->global_id; + transmit(route, std::move(message)); } else { auto broker = mBrokers.find(target); if (broker != mBrokers.end()) { route = broker->route; - m.dest_id = broker->global_id; - transmit(route, std::move(m)); + message.dest_id = broker->global_id; + transmit(route, std::move(message)); } else { - m.swapSourceDest(); - m.source_id = global_broker_id_local; - m.setAction(CMD_ERROR); - m.payload = "unable to locate target for command"; - transmit(getRoute(m.dest_id), std::move(m)); + message.swapSourceDest(); + message.source_id = global_broker_id_local; + message.setAction(CMD_ERROR); + message.payload = "unable to locate target for command"; + transmit(getRoute(message.dest_id), std::move(message)); } } } @@ -4210,21 +4331,21 @@ void CoreBroker::processCommandInstruction(ActionMessage& m) auto fed = mFederates.find(target); if (fed != mFederates.end()) { route = fed->route; - m.dest_id = fed->global_id; - transmit(route, std::move(m)); + message.dest_id = fed->global_id; + transmit(route, std::move(message)); } else { auto broker = mBrokers.find(target); if (broker != mBrokers.end()) { route = broker->route; - m.dest_id = broker->global_id; - transmit(route, std::move(m)); + message.dest_id = broker->global_id; + transmit(route, std::move(message)); } else { - transmit(parent_route_id, std::move(m)); + transmit(parent_route_id, std::move(message)); } } } } else { - transmit(getRoute(m.dest_id), std::move(m)); + transmit(getRoute(message.dest_id), std::move(message)); } } @@ -4366,7 +4487,7 @@ bool CoreBroker::allInitReady() const return false; } } - bool initReady = (getAllConnectionState() >= ConnectionState::INIT_REQUESTED); + const bool initReady = (getAllConnectionState() >= ConnectionState::INIT_REQUESTED); if (initReady) { // now do a more formal count of federates as there may be non-counting ones return (getCountableFederates() >= minFederateCount); diff --git a/src/helics/core/CoreBroker.hpp b/src/helics/core/CoreBroker.hpp index 4c8cbd3c38..26e9cab689 100644 --- a/src/helics/core/CoreBroker.hpp +++ b/src/helics/core/CoreBroker.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -337,10 +337,10 @@ class CoreBroker: public Broker, public BrokerBase { void checkDependencies(); void connectInterfaces( - const BasicHandleInfo& source, - const BasicHandleInfo& dest, - uint32_t flags, - uint32_t flagsDest, + const BasicHandleInfo& origin, + uint32_t originFlags, + const BasicHandleInfo& target, + uint32_t targetFlags, std::pair actions); /** find any existing publishers for a subscription*/ @@ -356,6 +356,10 @@ class CoreBroker: public Broker, public BrokerBase { uint16_t flags); /** process a disconnect message*/ void processDisconnectCommand(ActionMessage& command); + /** handle disconnect timing */ + void disconnectTiming(ActionMessage& command); + /** processBrokerDisconnect */ + void processBrokerDisconnect(ActionMessage& command, BasicBrokerInfo* brk); /** process an error message*/ void processError(ActionMessage& command); /** disconnect a broker/core*/ @@ -371,23 +375,23 @@ class CoreBroker: public Broker, public BrokerBase { /** handle the processing for a query command*/ void processQueryCommand(ActionMessage& cmd); /** answer a query or route the message the appropriate location*/ - void processQuery(ActionMessage& m); + void processQuery(ActionMessage& message); /** process and init related command*/ void processInitCommand(ActionMessage& cmd); /** manage query timeouts*/ void checkQueryTimeouts(); /** answer a query or route the message the appropriate location*/ - void processQueryResponse(const ActionMessage& m); + void processQueryResponse(const ActionMessage& message); /** generate an answer to a local query*/ - void processLocalQuery(const ActionMessage& m); + void processLocalQuery(const ActionMessage& message); /** generate an actual response string to a query*/ std::string generateQueryAnswer(std::string_view request, bool force_ordering); /** run queries that are not dependent on the main loop to be running*/ std::string quickBrokerQueries(std::string_view request) const; /** process a command instruction message*/ - void processCommandInstruction(ActionMessage& m); + void processCommandInstruction(ActionMessage& message); /** process a command instruction targeted at this broker*/ - void processLocalCommandInstruction(ActionMessage& m); + void processLocalCommandInstruction(ActionMessage& message); /** generate a list of names of interfaces from a list of global_ids in a string*/ std::string getNameList(std::string_view gidString) const; /** locate the route to take to a particular federate*/ @@ -399,15 +403,15 @@ class CoreBroker: public Broker, public BrokerBase { BasicBrokerInfo* getBrokerById(GlobalBrokerId brokerid); - void addLocalInfo(BasicHandleInfo& handleInfo, const ActionMessage& m); - void addPublication(ActionMessage& m); - void addInput(ActionMessage& m); - void addEndpoint(ActionMessage& m); - void addFilter(ActionMessage& m); - void addTranslator(ActionMessage& m); - void addDataSink(ActionMessage& m); + void addLocalInfo(BasicHandleInfo& handleInfo, const ActionMessage& message); + void addPublication(ActionMessage& message); + void addInput(ActionMessage& message); + void addEndpoint(ActionMessage& message); + void addFilter(ActionMessage& message); + void addTranslator(ActionMessage& message); + void addDataSink(ActionMessage& message); - bool checkInterfaceCreation(ActionMessage& m, InterfaceType type); + bool checkInterfaceCreation(ActionMessage& message, InterfaceType type); // Handle the registration of new brokers void brokerRegistration(ActionMessage&& command); /// @brief send an error response to broker registration @@ -440,11 +444,11 @@ class CoreBroker: public Broker, public BrokerBase { void labelAsDisconnected(GlobalBrokerId brkid); /** process message for the time monitor*/ - void processTimeMonitorMessage(ActionMessage& m); + void processTimeMonitorMessage(ActionMessage& message); /** load up the monitor federate*/ void loadTimeMonitor(bool firstLoad, std::string_view newFederate); /** generate a time barrier request*/ - void generateTimeBarrier(ActionMessage& m); + void generateTimeBarrier(ActionMessage& message); int generateMapObjectCounter() const; /** handle the renaming operation*/ std::string generateRename(std::string_view name); diff --git a/src/helics/core/CoreFactory.cpp b/src/helics/core/CoreFactory.cpp index 1246a34a2d..66b5c2bb61 100644 --- a/src/helics/core/CoreFactory.cpp +++ b/src/helics/core/CoreFactory.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -16,15 +16,16 @@ SPDX-License-Identifier: BSD-3-Clause #include "gmlc/concurrency/DelayedDestructor.hpp" #include "gmlc/concurrency/SearchableObjectHolder.hpp" #include "gmlc/libguarded/shared_guarded.hpp" -#include "helics/common/fmt_format.h" #include "helics/helics-config.h" #include "helicsCLI11.hpp" #include #include +#include #include #include +// NOLINTNEXTLINE DECLARE_TRIPLINE() namespace helics::CoreFactory { @@ -36,17 +37,17 @@ static constexpr std::string_view gHelicsEmptyString; that call it so it needs to be a static member of function call*/ class MasterCoreBuilder { public: - using BuildT = std::tuple>; + using BuilderData = std::tuple>; - static void addBuilder(std::shared_ptr cb, std::string_view name, int code) + static void addBuilder(std::shared_ptr builder, std::string_view name, int code) { - instance()->builders.emplace_back(code, name, std::move(cb)); + instance()->builders.emplace_back(code, name, std::move(builder)); } static const std::shared_ptr& getBuilder(int code) { - for (auto& bb : instance()->builders) { - if (std::get<0>(bb) == code) { - return std::get<2>(bb); + for (auto& builder : instance()->builders) { + if (std::get<0>(builder) == code) { + return std::get<2>(builder); } } throw(HelicsException("core type is not available")); @@ -61,7 +62,7 @@ class MasterCoreBuilder { } static const std::shared_ptr& instance() { - static std::shared_ptr iptr(new MasterCoreBuilder()); + static const std::shared_ptr iptr(new MasterCoreBuilder()); return iptr; } static size_t size() @@ -82,12 +83,12 @@ class MasterCoreBuilder { /** private constructor since we only really want one of them accessed through the instance static member*/ MasterCoreBuilder() = default; - std::vector builders; //!< container for the different builders + std::vector builders; //!< container for the different builders }; -void defineCoreBuilder(std::shared_ptr cb, std::string_view name, int code) +void defineCoreBuilder(std::shared_ptr builder, std::string_view name, int code) { - MasterCoreBuilder::addBuilder(std::move(cb), name, code); + MasterCoreBuilder::addBuilder(std::move(builder), name, code); } std::vector getAvailableCoreTypes() @@ -123,8 +124,8 @@ std::shared_ptr getEmptyCore() Core* getEmptyCorePtr() { - static EmptyCore c1; - return &c1; + static EmptyCore eCore; + return &eCore; } std::shared_ptr create(std::string_view initializationString) @@ -225,8 +226,7 @@ std::shared_ptr core = makeCore(type, coreName); core->configureFromVector(std::move(args)); - bool success = registerCore(core, type); - if (!success) { + if (!registerCore(core, type)) { core = findCore(coreName); if (core) { return core; @@ -246,8 +246,7 @@ std::shared_ptr core = makeCore(type, coreName); core->configure(configureString); - bool success = registerCore(core, type); - if (!success) { + if (!registerCore(core, type)) { core = findCore(coreName); if (core) { return core; @@ -266,8 +265,7 @@ std::shared_ptr FindOrCreate(CoreType type, std::string_view coreName, int core = makeCore(type, coreName); core->configureFromArgs(argc, argv); - bool success = registerCore(core, type); - if (!success) { + if (!registerCore(core, type)) { core = findCore(coreName); if (core) { return core; @@ -358,8 +356,8 @@ size_t cleanUpCores(std::chrono::milliseconds delay) void terminateAllCores() { auto cores = searchableCores.getObjects(); - for (auto& cr : cores) { - cr->disconnect(); + for (auto& core : cores) { + core->disconnect(); } cleanUpCores(std::chrono::milliseconds(250)); } @@ -367,14 +365,14 @@ void terminateAllCores() void abortAllCores(int errorCode, std::string_view errorString) { auto cores = searchableCores.getObjects(); - for (auto& cr : cores) { - cr->globalError(gLocalCoreId, - errorCode, - fmt::format("{} sent abort message: '{}'", - cr->getIdentifier(), - errorString)); - - cr->disconnect(); + for (auto& core : cores) { + core->globalError(gLocalCoreId, + errorCode, + fmt::format("{} sent abort message: '{}'", + core->getIdentifier(), + errorString)); + + core->disconnect(); } cleanUpCores(std::chrono::milliseconds(250)); } @@ -407,15 +405,15 @@ void displayHelp(CoreType type) { if (type == CoreType::DEFAULT || type == CoreType::UNRECOGNIZED) { std::cout << "All core types have similar options\n"; - auto cr = makeCore(CoreType::DEFAULT, gHelicsEmptyString); - cr->configure(helpStr); + auto core = makeCore(CoreType::DEFAULT, gHelicsEmptyString); + core->configure(helpStr); #ifdef HELICS_ENABLE_TCP_CORE - cr = makeCore(CoreType::TCP_SS, gHelicsEmptyString); - cr->configure(helpStr); + core = makeCore(CoreType::TCP_SS, gHelicsEmptyString); + core->configure(helpStr); #endif } else { - auto cr = makeCore(type, gHelicsEmptyString); - cr->configure(helpStr); + auto core = makeCore(type, gHelicsEmptyString); + core->configure(helpStr); } } } // namespace helics::CoreFactory diff --git a/src/helics/core/CoreFactory.hpp b/src/helics/core/CoreFactory.hpp index 20649b21ba..10584b64ae 100644 --- a/src/helics/core/CoreFactory.hpp +++ b/src/helics/core/CoreFactory.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -44,8 +44,9 @@ namespace CoreFactory { }; //** define a new Core Builder from the builder give a name and build code*/ - void - defineCoreBuilder(std::shared_ptr cb, std::string_view coreTypeName, int code); + void defineCoreBuilder(std::shared_ptr builder, + std::string_view coreTypeName, + int code); /** template function to create a builder and link it into the library*/ template diff --git a/src/helics/core/CoreFederateInfo.hpp b/src/helics/core/CoreFederateInfo.hpp index 8981b7c42b..9aa9fc3495 100644 --- a/src/helics/core/CoreFederateInfo.hpp +++ b/src/helics/core/CoreFederateInfo.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/core/CoreTypes.hpp b/src/helics/core/CoreTypes.hpp index 8be8781c31..05fb024e13 100644 --- a/src/helics/core/CoreTypes.hpp +++ b/src/helics/core/CoreTypes.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -8,6 +8,7 @@ SPDX-License-Identifier: BSD-3-Clause #include "../helics_enums.h" +#include #include #include diff --git a/src/helics/core/EmptyCore.cpp b/src/helics/core/EmptyCore.cpp index 2f5d6b7e19..95f9633033 100644 --- a/src/helics/core/EmptyCore.cpp +++ b/src/helics/core/EmptyCore.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/core/EmptyCore.hpp b/src/helics/core/EmptyCore.hpp index 40785cb45c..86986dc2d5 100644 --- a/src/helics/core/EmptyCore.hpp +++ b/src/helics/core/EmptyCore.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/core/EndpointInfo.cpp b/src/helics/core/EndpointInfo.cpp index 9be32a006a..b2a82fd479 100644 --- a/src/helics/core/EndpointInfo.cpp +++ b/src/helics/core/EndpointInfo.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -9,10 +9,10 @@ SPDX-License-Identifier: BSD-3-Clause #include "../common/JsonGeneration.hpp" #include "helics_definitions.hpp" // #include "core/core-data.hpp" -#include "../common/fmt_format.h" #include #include +#include #include #include #include @@ -24,14 +24,14 @@ bool EndpointInfo::updateTimeUpTo(Time newTime) int index{0}; auto handle = message_queue.lock(); - auto cv = handle.begin(); + auto message = handle.begin(); auto it_final = handle.end(); - while (cv != it_final) { - if ((*cv)->time >= newTime) { + while (message != it_final) { + if ((*message)->time >= newTime) { break; } ++index; - ++cv; + ++message; } if (index != mAvailableMessages.load()) { mAvailableMessages.store(index); @@ -45,14 +45,14 @@ bool EndpointInfo::updateTimeNextIteration(Time newTime) int index{0}; auto handle = message_queue.lock(); - auto cv = handle.begin(); + auto message = handle.begin(); auto it_final = handle.end(); - while (cv != it_final) { - if ((*cv)->time > newTime) { + while (message != it_final) { + if ((*message)->time > newTime) { break; } ++index; - ++cv; + ++message; } if (index != mAvailableMessages.load()) { mAvailableMessages.store(index); @@ -66,14 +66,14 @@ bool EndpointInfo::updateTimeInclusive(Time newTime) int index{0}; auto handle = message_queue.lock(); - auto cv = handle.begin(); + auto message = handle.begin(); auto it_final = handle.end(); - while (cv != it_final) { - if ((*cv)->time > newTime) { + while (message != it_final) { + if ((*message)->time > newTime) { break; } ++index; - ++cv; + ++message; } if (index != mAvailableMessages.load()) { mAvailableMessages.store(index); @@ -108,10 +108,11 @@ Time EndpointInfo::firstMessageTime() const } // this is the function which determines message order -static auto msgSorter = [](const auto& m1, const auto& m2) { +static auto msgSorter = [](const auto& message1, const auto& message2) { // first by time - return (m1->time != m2->time) ? (m1->time < m2->time) : - (m1->original_source < m2->original_source); + return (message1->time != message2->time) ? + (message1->time < message2->time) : + (message1->original_source < message2->original_source); }; void EndpointInfo::addMessage(std::unique_ptr message) @@ -132,11 +133,26 @@ int32_t EndpointInfo::availableMessages() const return mAvailableMessages; } +bool EndpointInfo::hasConnection() const +{ + return !(targetInformation.empty() && sourceInformation.empty()); +} + +bool EndpointInfo::hasSource() const +{ + return !(sourceInformation.empty()); +} + +bool EndpointInfo::hasTarget() const +{ + return !(targetInformation.empty()); +} + int32_t EndpointInfo::queueSize(Time maxTime) const { auto handle = message_queue.lock_shared(); int32_t cnt = 0; - for (auto& msg : *handle) { + for (const auto& msg : *handle) { if (msg->time <= maxTime) { ++cnt; } else { @@ -150,7 +166,7 @@ int32_t EndpointInfo::queueSizeUpTo(Time maxTime) const { auto handle = message_queue.lock_shared(); int32_t cnt = 0; - for (auto& msg : *handle) { + for (const auto& msg : *handle) { if (msg->time < maxTime) { ++cnt; } else { @@ -164,8 +180,8 @@ void EndpointInfo::addDestination(GlobalHandle dest, std::string_view destName, std::string_view destType) { - for (const auto& ti : targetInformation) { - if (ti.id == dest) { + for (const auto& tinfo : targetInformation) { + if (tinfo.id == dest) { return; } } @@ -173,8 +189,8 @@ void EndpointInfo::addDestination(GlobalHandle dest, /** now update the target information*/ targets.reserve(targetInformation.size()); targets.clear(); - for (const auto& ti : targetInformation) { - targets.emplace_back(ti.id, ti.key); + for (const auto& tinfo : targetInformation) { + targets.emplace_back(tinfo.id, tinfo.key); } } @@ -183,8 +199,8 @@ void EndpointInfo::addSource(GlobalHandle source, std::string_view sourceName, std::string_view sourceType) { - for (const auto& si : sourceInformation) { - if (si.id == source) { + for (const auto& info : sourceInformation) { + if (info.id == source) { return; } } @@ -194,10 +210,10 @@ void EndpointInfo::addSource(GlobalHandle source, /** remove a target from connection*/ void EndpointInfo::removeTarget(GlobalHandle targetId) { - auto ti = targetInformation.begin(); - while (ti != targetInformation.end()) { - if (ti->id == targetId) { - targetInformation.erase(ti); + auto tinfo = targetInformation.begin(); + while (tinfo != targetInformation.end()) { + if (tinfo->id == targetId) { + targetInformation.erase(tinfo); targets.clear(); for (const auto& targetInfo : targetInformation) { targets.emplace_back(targetInfo.id, targetInfo.key); @@ -205,10 +221,10 @@ void EndpointInfo::removeTarget(GlobalHandle targetId) break; } } - auto si = sourceInformation.begin(); - while (si != sourceInformation.end()) { - if (si->id == targetId) { - sourceInformation.erase(si); + auto sinfo = sourceInformation.begin(); + while (sinfo != sourceInformation.end()) { + if (sinfo->id == targetId) { + sourceInformation.erase(sinfo); return; } } @@ -305,7 +321,7 @@ void EndpointInfo::checkInterfacesForIssues(std::vector + // NOLINTNEXTLINE static const std::string gHelicsEmptyStr; #define LOG_ERROR(message) logMessage(HELICS_LOG_LEVEL_ERROR, gHelicsEmptyStr, message) @@ -118,7 +119,7 @@ FederateState::FederateState(const std::string& fedName, const CoreFederateInfo& setOptionFlag(prop.first, prop.second); } mLogManager->setTransmitCallback( - [this](ActionMessage&& m) { mParent->addActionMessage(std::move(m)); }); + [this](ActionMessage&& message) { mParent->addActionMessage(std::move(message)); }); maxLogLevel = mLogManager->getMaxLevel(); } @@ -183,7 +184,7 @@ int32_t FederateState::getCurrentIteration() const bool FederateState::checkAndSetValue(InterfaceHandle pub_id, const char* data, uint64_t len) { - std::lock_guard plock(*this); + const std::lock_guard plock(*this); // this function could be called externally in a multi-threaded context auto* pub = interfaceInformation.getPublication(pub_id); auto res = pub->CheckSetValue(data, len, time_granted, only_transmit_on_change); @@ -198,6 +199,10 @@ void FederateState::generateConfig(Json::Value& base) const base["source_only"] = mSourceOnly; base["strict_input_type_checking"] = strict_input_type_checking; base["slow_responding"] = mSlowResponding; + if (!mAllowRemoteControl) { + base["disable_remote_control"] = !mAllowRemoteControl; + } + if (rt_lag > timeZero) { base["rt_lag"] = static_cast(rt_lag); } @@ -206,9 +211,9 @@ void FederateState::generateConfig(Json::Value& base) const } } -uint64_t FederateState::getQueueSize(InterfaceHandle id) const +uint64_t FederateState::getQueueSize(InterfaceHandle hid) const { - const auto* epI = interfaceInformation.getEndpoint(id); + const auto* epI = interfaceInformation.getEndpoint(hid); return (epI != nullptr) ? epI->availableMessages() : 0; } @@ -227,25 +232,25 @@ void FederateState::setLogger( mLogManager->setLoggerFunction(std::move(logFunction)); } -std::unique_ptr FederateState::receive(InterfaceHandle id) +std::unique_ptr FederateState::receive(InterfaceHandle hid) { - auto* epI = interfaceInformation.getEndpoint(id); + auto* epI = interfaceInformation.getEndpoint(hid); if (epI != nullptr) { return epI->getMessage(time_granted); } return nullptr; } -std::unique_ptr FederateState::receiveAny(InterfaceHandle& id) +std::unique_ptr FederateState::receiveAny(InterfaceHandle& hid) { Time earliest_time = Time::maxVal(); EndpointInfo* endpointI = nullptr; auto elock = interfaceInformation.getEndpoints(); // Find the end point with the earliest message time for (const auto& end_point : elock) { - auto t = end_point->firstMessageTime(); - if (t < earliest_time) { - earliest_time = t; + auto firstTime = end_point->firstMessageTime(); + if (firstTime < earliest_time) { + earliest_time = firstTime; endpointI = end_point.get(); } } @@ -255,11 +260,11 @@ std::unique_ptr FederateState::receiveAny(InterfaceHandle& id) // Return the message found and remove from the queue if (earliest_time <= time_granted) { auto result = endpointI->getMessage(time_granted); - id = (result) ? endpointI->id.handle : InterfaceHandle{}; + hid = (result) ? endpointI->id.handle : InterfaceHandle{}; return result; } - id = InterfaceHandle(); + hid = InterfaceHandle(); return nullptr; } @@ -341,7 +346,7 @@ void FederateState::createInterface(InterfaceType htype, std::string_view units, uint16_t flags) { - std::lock_guard plock(*this); + const std::lock_guard plock(*this); // this function could be called externally in a multi-threaded context switch (htype) { case InterfaceType::PUBLICATION: @@ -362,9 +367,6 @@ void FederateState::createInterface(InterfaceType htype, } break; case InterfaceType::ENDPOINT: - interfaceInformation.createEndpoint(handle, key, type, flags); - - break; case InterfaceType::SINK: interfaceInformation.createEndpoint(handle, key, type, flags); break; @@ -447,7 +449,7 @@ IterationResult FederateState::waitSetup() } // this function can fail try_lock gracefully - std::lock_guard fedlock(*this); + const std::lock_guard fedlock(*this); IterationResult ret; switch (getState()) { case FederateStates::CREATED: { // we are still in the created state @@ -549,7 +551,7 @@ iteration_time FederateState::enterExecutingMode(IterationRequest iterate, bool // the following code is for a situation in which this method has been called multiple times // from different threads, which really shouldn't be done but it isn't really an error so we // need to deal with it. - std::lock_guard plock(*this); + const std::lock_guard plock(*this); IterationResult ret; switch (getState()) { case FederateStates::ERRORED: @@ -607,7 +609,7 @@ void FederateState::updateDataForExecEntry(MessageProcessingResult result, Itera std::vector FederateState::getSubscribers(InterfaceHandle handle) { - std::lock_guard fedlock(*this); + const std::lock_guard fedlock(*this); std::vector subs; auto* pubInfo = interfaceInformation.getPublication(handle); if (pubInfo != nullptr) { @@ -621,7 +623,7 @@ std::vector FederateState::getSubscribers(InterfaceHandle handle) std::vector> FederateState::getMessageDestinations(InterfaceHandle handle) { - std::lock_guard fedlock(*this); + const std::lock_guard fedlock(*this); const auto* eptInfo = interfaceInformation.getEndpoint(handle); if (eptInfo != nullptr) { return eptInfo->getTargets(); @@ -731,7 +733,7 @@ iteration_time FederateState::requestTime(Time nextTime, IterationRequest iterat LOG_WARNING("duplicate locking attempted"); // this would not be good practice to get into this part of the function // but the area must protect itself against the possibility and should return something sensible - std::lock_guard fedlock(*this); + const std::lock_guard fedlock(*this); IterationResult ret = iterating ? IterationResult::ITERATING : IterationResult::NEXT_STEP; if (state == FederateStates::FINISHED) { ret = IterationResult::HALTED; @@ -785,14 +787,12 @@ void FederateState::fillEventVectorUpTo(Time currentTime) events.clear(); eventMessages.clear(); for (const auto& ipt : interfaceInformation.getInputs()) { - bool updated = ipt->updateTimeUpTo(currentTime); - if (updated) { + if (ipt->updateTimeUpTo(currentTime)) { events.push_back(ipt->id.handle); } } for (const auto& ept : interfaceInformation.getEndpoints()) { - bool updated = ept->updateTimeUpTo(currentTime); - if (updated) { + if (ept->updateTimeUpTo(currentTime)) { eventMessages.push_back(ept->id.handle); } } @@ -802,15 +802,13 @@ void FederateState::fillEventVectorInclusive(Time currentTime) { events.clear(); for (const auto& ipt : interfaceInformation.getInputs()) { - bool updated = ipt->updateTimeInclusive(currentTime); - if (updated) { + if (ipt->updateTimeInclusive(currentTime)) { events.push_back(ipt->id.handle); } } eventMessages.clear(); for (const auto& ept : interfaceInformation.getEndpoints()) { - bool updated = ept->updateTimeInclusive(currentTime); - if (updated) { + if (ept->updateTimeInclusive(currentTime)) { eventMessages.push_back(ept->id.handle); } } @@ -820,15 +818,13 @@ void FederateState::fillEventVectorNextIteration(Time currentTime) { events.clear(); for (const auto& ipt : interfaceInformation.getInputs()) { - bool updated = ipt->updateTimeNextIteration(currentTime); - if (updated) { + if (ipt->updateTimeNextIteration(currentTime)) { events.push_back(ipt->id.handle); } } eventMessages.clear(); for (const auto& ept : interfaceInformation.getEndpoints()) { - bool updated = ept->updateTimeNextIteration(currentTime); - if (updated) { + if (ept->updateTimeNextIteration(currentTime)) { eventMessages.push_back(ept->id.handle); } } @@ -945,8 +941,8 @@ MessageProcessingResult FederateState::processDelayQueue() noexcept delayedFederates.clear(); auto ret_code = MessageProcessingResult::CONTINUE_PROCESSING; if (!delayQueues.empty()) { - for (auto& dQ : delayQueues) { - auto& tempQueue = dQ.second; + for (auto& dqueue : delayQueues) { + auto& tempQueue = dqueue.second; ret_code = MessageProcessingResult::CONTINUE_PROCESSING; // we specifically want to stop the loop on a delay_message return while ((ret_code == MessageProcessingResult::CONTINUE_PROCESSING) && @@ -971,23 +967,23 @@ MessageProcessingResult FederateState::processDelayQueue() noexcept return ret_code; } -void FederateState::addFederateToDelay(GlobalFederateId id) +void FederateState::addFederateToDelay(GlobalFederateId gid) { - if ((delayedFederates.empty()) || (id > delayedFederates.back())) { - delayedFederates.push_back(id); + if ((delayedFederates.empty()) || (gid > delayedFederates.back())) { + delayedFederates.push_back(gid); return; } - auto res = std::lower_bound(delayedFederates.begin(), delayedFederates.end(), id); + auto res = std::lower_bound(delayedFederates.begin(), delayedFederates.end(), gid); if (res == delayedFederates.end()) { - delayedFederates.push_back(id); + delayedFederates.push_back(gid); return; } - if (*res != id) { - delayedFederates.insert(res, id); + if (*res != gid) { + delayedFederates.insert(res, gid); } } -bool FederateState::messageShouldBeDelayed(const ActionMessage& cmd) const +bool FederateState::messageShouldBeDelayed(const ActionMessage& cmd) const noexcept { switch (delayedFederates.size()) { case 0: @@ -1009,7 +1005,7 @@ void FederateState::generateProfilingMarker() { auto ctime = std::chrono::steady_clock::now(); auto gtime = std::chrono::system_clock::now(); - std::string message = fmt::format( + const std::string message = fmt::format( "{}[{}]({})MARKER<{}|{}>[t={}]", name, global_id.load().baseValue(), @@ -1034,7 +1030,7 @@ void FederateState::generateProfilingMessage(bool enterHelicsCode) auto ctime = std::chrono::steady_clock::now(); static constexpr std::string_view entry_string("ENTRY"); static constexpr std::string_view exit_string("EXIT"); - std::string message = fmt::format( + const std::string message = fmt::format( "{}[{}]({})HELICS CODE {}<{}>[t={}]", name, global_id.load().baseValue(), @@ -1271,7 +1267,7 @@ MessageProcessingResult FederateState::processQueue() noexcept } auto initError = (state == FederateStates::ERRORED); bool error_cmd{false}; - bool profilerActive{mProfilerActive}; + const bool profilerActive{mProfilerActive}; queueProcessing.store(true); if (profilerActive) { generateProfilingMessage(true); @@ -1323,32 +1319,10 @@ MessageProcessingResult FederateState::processQueue() noexcept return ret_code; } -MessageProcessingResult FederateState::processActionMessage(ActionMessage& cmd) +std::optional FederateState::checkProcResult( + std::tuple& proc_result, + ActionMessage& cmd) { - LOG_TRACE(fmt::format("processing command {}", prettyPrintString(cmd))); - - if (cmd.action() == CMD_TIME_REQUEST) { - if ((cmd.source_id == global_id.load()) && - checkActionFlag(cmd, indicator_flag)) { // this sets up a time request - requestingMode.store(true); - IterationRequest iterate = IterationRequest::NO_ITERATIONS; - if (checkActionFlag(cmd, iteration_requested_flag)) { - iterate = (checkActionFlag(cmd, required_flag)) ? - IterationRequest::FORCE_ITERATION : - IterationRequest::ITERATE_IF_NEEDED; - } - timeCoord->timeRequest(cmd.actionTime, iterate, nextValueTime(), nextMessageTime()); - timeGranted_mode = false; - auto ret = processDelayQueue(); - if (returnableResult(ret)) { - return ret; - } - cmd.setAction(CMD_TIME_CHECK); - } - } - auto proc_result = processCoordinatorMessage( - cmd, timeCoord.get(), getState(), timeGranted_mode, global_id.load()); - timeGranted_mode = std::get<2>(proc_result); if (getState() != std::get<0>(proc_result)) { @@ -1404,26 +1378,53 @@ MessageProcessingResult FederateState::processActionMessage(ActionMessage& cmd) allowed_send_time = timeCoord->allowedSendTime(); if (cmd.action() == CMD_FORCE_TIME_GRANT) { if (!ignore_time_mismatch_warnings) { - LOG_WARNING(fmt::format("forced Granted Time={}", time_granted)); + LOG_WARNING(fmt::format("forced Granted Time={}", + static_cast(time_granted))); } } else { - LOG_TIMING(fmt::format("Granted Time={}", time_granted)); + LOG_TIMING(fmt::format("Granted Time={}", static_cast(time_granted))); } } return (std::get<1>(proc_result)); } + return std::nullopt; +} + +MessageProcessingResult FederateState::processActionMessage(ActionMessage& cmd) +{ + LOG_TRACE(fmt::format("processing command {}", prettyPrintString(cmd))); + + if (cmd.action() == CMD_TIME_REQUEST) { + if ((cmd.source_id == global_id.load()) && + checkActionFlag(cmd, indicator_flag)) { // this sets up a time request + requestingMode.store(true); + IterationRequest iterate = IterationRequest::NO_ITERATIONS; + if (checkActionFlag(cmd, iteration_requested_flag)) { + iterate = (checkActionFlag(cmd, required_flag)) ? + IterationRequest::FORCE_ITERATION : + IterationRequest::ITERATE_IF_NEEDED; + } + timeCoord->timeRequest(cmd.actionTime, iterate, nextValueTime(), nextMessageTime()); + timeGranted_mode = false; + auto ret = processDelayQueue(); + if (returnableResult(ret)) { + return ret; + } + cmd.setAction(CMD_TIME_CHECK); + } + } + auto proc_result = processCoordinatorMessage( + cmd, timeCoord.get(), getState(), timeGranted_mode, global_id.load()); + + auto result = checkProcResult(proc_result, cmd); + if (result) { + return *result; + } switch (cmd.action()) { case CMD_IGNORE: default: break; - case CMD_LOG: - case CMD_REMOTE_LOG: - logMessage(cmd.messageID, - cmd.getString(0), - cmd.payload.to_string(), - cmd.action() == CMD_REMOTE_LOG); - break; case CMD_EXEC_REQUEST: if ((cmd.source_id == global_id.load()) && @@ -1482,159 +1483,146 @@ MessageProcessingResult FederateState::processActionMessage(ActionMessage& cmd) } } break; + case CMD_SEND_MESSAGE: + case CMD_PUB: + processDataMessage(cmd); + break; + case CMD_LOG: + case CMD_REMOTE_LOG: + case CMD_WARNING: + case CMD_SET_PROFILER_FLAG: + case CMD_TIMEOUT_DISCONNECT: + processLoggingMessage(cmd); + break; + case CMD_GRANT_TIMEOUT_CHECK: + timeoutCheck(cmd); + break; + case CMD_ADD_PUBLISHER: + case CMD_ADD_SUBSCRIBER: + case CMD_ADD_ENDPOINT: + case CMD_REMOVE_NAMED_PUBLICATION: + case CMD_REMOVE_PUBLICATION: + case CMD_REMOVE_SUBSCRIBER: + case CMD_REMOVE_ENDPOINT: case CMD_CLOSE_INTERFACE: - if (cmd.source_id == global_id.load()) { - closeInterface(cmd.source_handle, static_cast(cmd.counter)); - } + processDataConnectionMessage(cmd); break; - case CMD_SEND_MESSAGE: { - auto* epi = interfaceInformation.getEndpoint(cmd.dest_handle); - if (epi != nullptr && !epi->sourceOnly) { - // if (!epi->not_interruptible) - { - timeCoord->updateMessageTime(cmd.actionTime, !timeGranted_mode); - } - LOG_DATA(fmt::format("receive_message {}", prettyPrintString(cmd))); - if (cmd.actionTime < time_granted && - timeMethod != TimeSynchronizationMethod::ASYNC) { - LOG_WARNING( - fmt::format("received message {} at time({}) earlier than granted time({})", - prettyPrintString(cmd), - cmd.actionTime, - time_granted)); - auto qres = processQueryActual("global_time_debugging"); - qres.insert(0, "TIME DEBUGGING::"); - LOG_WARNING(qres); - } - - if (state <= FederateStates::EXECUTING) { - timeCoord->processTimeMessage(cmd); - } - epi->addMessage(createMessageFromCommand(std::move(cmd))); - } - } break; - case CMD_PUB: { - auto* subI = interfaceInformation.getInput(InterfaceHandle(cmd.dest_handle)); - if (subI == nullptr) { - auto* eptI = interfaceInformation.getEndpoint(cmd.dest_handle); - if (eptI != nullptr) { - // if (!epi->not_interruptible) - { - timeCoord->updateMessageTime(cmd.actionTime, !timeGranted_mode); - } - LOG_DATA(fmt::format("receive_message {}", prettyPrintString(cmd))); - if (cmd.actionTime < time_granted && - timeMethod != TimeSynchronizationMethod::ASYNC) { - LOG_WARNING(fmt::format( - "received message {} at time({}) earlier than granted time({})", - prettyPrintString(cmd), - cmd.actionTime, - time_granted)); - } - auto mess = std::make_unique(); - mess->data = std::move(cmd.payload); - mess->dest = eptI->key; - mess->flags = cmd.flags; - mess->time = cmd.actionTime; - mess->counter = cmd.counter; - mess->messageID = cmd.messageID; - mess->original_dest = eptI->key; - eptI->addMessage(std::move(mess)); - if (state <= FederateStates::EXECUTING) { - timeCoord->processTimeMessage(cmd); - } - } + case CMD_FED_ACK: + if (state != FederateStates::CREATED) { break; } - for (auto& src : subI->input_sources) { - auto valueTime = cmd.actionTime; - if (timeMethod == TimeSynchronizationMethod::ASYNC) { - if (valueTime < time_granted) { - valueTime = time_granted; - } + if (cmd.name() == name) { + if (checkActionFlag(cmd, error_flag)) { + setState(FederateStates::ERRORED); + errorString = commandErrorString(cmd.messageID); + return MessageProcessingResult::ERROR_RESULT; } - if ((cmd.source_id == src.fed_id) && (cmd.source_handle == src.handle)) { - if (subI->addData(src, - valueTime, - cmd.counter, - std::make_shared( - std::move(cmd.payload)))) { - if (!subI->not_interruptible) { - timeCoord->updateValueTime(valueTime, !timeGranted_mode); - LOG_TRACE(timeCoord->printTimeStatus()); - } - LOG_DATA(fmt::format("receive PUBLICATION {} from {}", - prettyPrintString(cmd), - subI->getSourceName(src))); + if (checkActionFlag(cmd, global_timing_flag)) { + if (checkActionFlag(cmd, async_timing_flag)) { + timeMethod = TimeSynchronizationMethod::ASYNC; + } else { + timeMethod = TimeSynchronizationMethod::GLOBAL; + addDependent(gRootBrokerID); + addDependency(gRootBrokerID); + timeCoord->setAsParent(gRootBrokerID); } + timeCoord->globalTime = true; } + global_id = cmd.dest_id; + interfaceInformation.setGlobalId(cmd.dest_id); + timeCoord->setSourceId(global_id); + return MessageProcessingResult::NEXT_STEP; } - if (state <= FederateStates::EXECUTING) { - timeCoord->processTimeMessage(cmd); - } - } break; - case CMD_WARNING: - if (cmd.payload.empty()) { - cmd.payload = commandErrorString(cmd.messageID); - if (cmd.payload.to_string() == "unknown") { - cmd.payload.append(" code:"); - cmd.payload.append(std::to_string(cmd.messageID)); - } - } - LOG_WARNING(cmd.payload.to_string()); break; - case CMD_GRANT_TIMEOUT_CHECK: - if (timeGranted_mode && cmd.actionTime != Time::maxVal()) { - break; - } - if (mGrantCount != static_cast(cmd.getExtraData())) { - // time has been granted since this was triggered - break; - } - if (cmd.counter == 0) { - auto blockFed = timeCoord->getMinGrantedDependency(); - if (blockFed.first.isValid()) { - LOG_WARNING(fmt::format("grant timeout exceeded sim time {} waiting on {}", - time_granted, - blockFed.first.baseValue())); - } else { - LOG_WARNING(fmt::format("grant timeout exceeded sim time {}", time_granted)); - } + case CMD_FED_CONFIGURE_TIME: + setProperty(cmd.messageID, cmd.actionTime); + break; + case CMD_FED_CONFIGURE_INT: + setProperty(cmd.messageID, cmd.getExtraData()); + break; + case CMD_FED_CONFIGURE_FLAG: + setOptionFlag(cmd.messageID, checkActionFlag(cmd, indicator_flag)); + break; + case CMD_INTERFACE_CONFIGURE: + setInterfaceProperty(cmd); + break; + case CMD_SEND_COMMAND: + case CMD_SEND_COMMAND_ORDERED: + sendCommand(cmd); + break; - } else if (cmd.counter == 3) { - LOG_WARNING("grant timeout stage 2 requesting time resend"); - timeCoord->requestTimeCheck(); - } else if (cmd.counter == 6) { - LOG_WARNING("grant timeout stage 3 diagnostics"); - auto qres = processQueryActual("global_time_debugging"); - qres.insert(0, "TIME DEBUGGING::"); - LOG_WARNING(qres); - auto parentID = timeCoord->getParent(); - if (parentID.isValid()) { - auto brokerTimeoutCheck = cmd; - brokerTimeoutCheck.source_id = global_id.load(); - brokerTimeoutCheck.dest_id = parentID; - routeMessage(brokerTimeoutCheck); - LOG_WARNING( - fmt::format("sending grant time out check to {}", parentID.baseValue())); - } - } else if (cmd.counter == 10) { - if (cmd.actionTime == Time::maxVal()) { - LOG_WARNING("finalize blocking"); - } else { - LOG_WARNING("grant timeout stage 4 error actions (none available)"); - } - } + case CMD_QUERY_ORDERED: + case CMD_QUERY: { + ActionMessage queryResp(cmd.action() == CMD_QUERY ? CMD_QUERY_REPLY : + CMD_QUERY_REPLY_ORDERED); + queryResp.dest_id = cmd.source_id; + queryResp.source_id = cmd.dest_id; + queryResp.messageID = cmd.messageID; + queryResp.counter = cmd.counter; + + queryResp.payload = processQueryActual(cmd.payload.to_string()); + routeMessage(std::move(queryResp)); + } break; + } + return MessageProcessingResult::CONTINUE_PROCESSING; +} + +void FederateState::timeoutCheck(ActionMessage& cmd) +{ + if (timeGranted_mode && cmd.actionTime != Time::maxVal()) { + return; + } + if (mGrantCount != static_cast(cmd.getExtraData())) { + // time has been granted since this was triggered + return; + } + if (cmd.counter == 0) { + auto blockFed = timeCoord->getMinGrantedDependency(); + if (blockFed.first.isValid()) { + LOG_WARNING(fmt::format("grant timeout exceeded sim time {} waiting on {}", + static_cast(time_granted), + blockFed.first.baseValue())); + } else { + LOG_WARNING(fmt::format("grant timeout exceeded sim time {}", + static_cast(time_granted))); + } + + } else if (cmd.counter == 3) { + LOG_WARNING("grant timeout stage 2 requesting time resend"); + timeCoord->requestTimeCheck(); + } else if (cmd.counter == 6) { + LOG_WARNING("grant timeout stage 3 diagnostics"); + auto qres = processQueryActual("global_time_debugging"); + qres.insert(0, "TIME DEBUGGING::"); + LOG_WARNING(qres); + auto parentID = timeCoord->getParent(); + if (parentID.isValid()) { + ActionMessage brokerTimeoutCheck{cmd}; + brokerTimeoutCheck.source_id = global_id.load(); + brokerTimeoutCheck.dest_id = parentID; + routeMessage(brokerTimeoutCheck); + LOG_WARNING(fmt::format("sending grant time out check to {}", parentID.baseValue())); + } + } else if (cmd.counter == 10) { + if (cmd.actionTime == Time::maxVal()) { + LOG_WARNING("finalize blocking"); + } else { + LOG_WARNING("grant timeout stage 4 error actions (none available)"); + } + } #ifndef HELICS_DISABLE_ASIO - if (mTimer) { - ++cmd.counter; - mTimer->updateTimerFromNow(grantTimeoutTimeIndex, - grantTimeOutPeriod.to_ms(), - std::move(cmd)); - } + if (mTimer) { + ++cmd.counter; + mTimer->updateTimerFromNow(grantTimeoutTimeIndex, + grantTimeOutPeriod.to_ms(), + std::move(cmd)); + } #endif - break; +} +void FederateState::processDataConnectionMessage(ActionMessage& cmd) +{ + switch (cmd.action()) { case CMD_ADD_PUBLISHER: { auto* subI = interfaceInformation.getInput(cmd.dest_handle); if (subI != nullptr) { @@ -1666,13 +1654,13 @@ MessageProcessingResult FederateState::processActionMessage(ActionMessage& cmd) } if (getState() > FederateStates::CREATED) { if (!pubI->data.empty() && pubI->lastPublishTime > Time::minVal()) { - ActionMessage mv(CMD_PUB); - mv.setSource(pubI->id); - mv.setDestination(cmd.getSource()); - mv.counter = static_cast(getCurrentIteration()); - mv.payload = pubI->data; - mv.actionTime = pubI->lastPublishTime; - routeMessage(std::move(mv)); + ActionMessage pub(CMD_PUB); + pub.setSource(pubI->id); + pub.setDestination(cmd.getSource()); + pub.counter = static_cast(getCurrentIteration()); + pub.payload = pubI->data; + pub.actionTime = pubI->lastPublishTime; + routeMessage(std::move(pub)); } } } @@ -1719,74 +1707,146 @@ MessageProcessingResult FederateState::processActionMessage(ActionMessage& cmd) pubI->removeSubscriber(cmd.getSource()); } } break; - case CMD_REMOVE_ENDPOINT: + case CMD_CLOSE_INTERFACE: + if (cmd.source_id == global_id.load()) { + closeInterface(cmd.source_handle, static_cast(cmd.counter)); + } break; - case CMD_SET_PROFILER_FLAG: - setOptionFlag(defs::PROFILING, checkActionFlag(cmd, indicator_flag)); + + case CMD_REMOVE_ENDPOINT: + default: break; - case CMD_FED_ACK: - if (state != FederateStates::CREATED) { + } +} + +void FederateState::processDataMessage(ActionMessage& cmd) +{ + switch (cmd.action()) { + case CMD_SEND_MESSAGE: { + auto* epi = interfaceInformation.getEndpoint(cmd.dest_handle); + if (epi != nullptr && !epi->sourceOnly) { + // if (!epi->not_interruptible) + { + timeCoord->updateMessageTime(cmd.actionTime, !timeGranted_mode); + } + LOG_DATA(fmt::format("receive_message {}", prettyPrintString(cmd))); + if (cmd.actionTime < time_granted && + timeMethod != TimeSynchronizationMethod::ASYNC) { + LOG_WARNING( + fmt::format("received message {} at time({}) earlier than granted time({})", + prettyPrintString(cmd), + static_cast(cmd.actionTime), + static_cast(time_granted))); + auto qres = processQueryActual("global_time_debugging"); + qres.insert(0, "TIME DEBUGGING::"); + LOG_WARNING(qres); + } + + if (state <= FederateStates::EXECUTING) { + timeCoord->processTimeMessage(cmd); + } + epi->addMessage(createMessageFromCommand(std::move(cmd))); + } + } break; + case CMD_PUB: { + auto* subI = interfaceInformation.getInput(InterfaceHandle(cmd.dest_handle)); + if (subI == nullptr) { + auto* eptI = interfaceInformation.getEndpoint(cmd.dest_handle); + if (eptI != nullptr) { + // if (!epi->not_interruptible) + { + timeCoord->updateMessageTime(cmd.actionTime, !timeGranted_mode); + } + LOG_DATA(fmt::format("receive_message {}", prettyPrintString(cmd))); + if (cmd.actionTime < time_granted && + timeMethod != TimeSynchronizationMethod::ASYNC) { + LOG_WARNING(fmt::format( + "received message {} at time({}) earlier than granted time({})", + prettyPrintString(cmd), + static_cast(cmd.actionTime), + static_cast(time_granted))); + } + auto mess = std::make_unique(); + mess->data = std::move(cmd.payload); + mess->dest = eptI->key; + mess->flags = cmd.flags; + mess->time = cmd.actionTime; + mess->counter = cmd.counter; + mess->messageID = cmd.messageID; + mess->original_dest = eptI->key; + eptI->addMessage(std::move(mess)); + if (state <= FederateStates::EXECUTING) { + timeCoord->processTimeMessage(cmd); + } + } break; } - if (cmd.name() == name) { - if (checkActionFlag(cmd, error_flag)) { - setState(FederateStates::ERRORED); - errorString = commandErrorString(cmd.messageID); - return MessageProcessingResult::ERROR_RESULT; + for (auto& src : subI->input_sources) { + auto valueTime = cmd.actionTime; + if (timeMethod == TimeSynchronizationMethod::ASYNC) { + if (valueTime < time_granted) { + valueTime = time_granted; + } } - if (checkActionFlag(cmd, global_timing_flag)) { - if (checkActionFlag(cmd, async_timing_flag)) { - timeMethod = TimeSynchronizationMethod::ASYNC; - } else { - timeMethod = TimeSynchronizationMethod::GLOBAL; - addDependent(gRootBrokerID); - addDependency(gRootBrokerID); - timeCoord->setAsParent(gRootBrokerID); + if ((cmd.source_id == src.fed_id) && (cmd.source_handle == src.handle)) { + if (subI->addData(src, + valueTime, + cmd.counter, + std::make_shared( + std::move(cmd.payload)))) { + if (!subI->not_interruptible) { + timeCoord->updateValueTime(valueTime, !timeGranted_mode); + LOG_TRACE(timeCoord->printTimeStatus()); + } + LOG_DATA(fmt::format("receive PUBLICATION {} from {}", + prettyPrintString(cmd), + subI->getSourceName(src))); } - timeCoord->globalTime = true; + // this can only match once + break; } - global_id = cmd.dest_id; - interfaceInformation.setGlobalId(cmd.dest_id); - timeCoord->setSourceId(global_id); - return MessageProcessingResult::NEXT_STEP; } + if (state <= FederateStates::EXECUTING) { + timeCoord->processTimeMessage(cmd); + } + } break; + default: break; - case CMD_FED_CONFIGURE_TIME: - setProperty(cmd.messageID, cmd.actionTime); - break; - case CMD_FED_CONFIGURE_INT: - setProperty(cmd.messageID, cmd.getExtraData()); - break; - case CMD_FED_CONFIGURE_FLAG: - setOptionFlag(cmd.messageID, checkActionFlag(cmd, indicator_flag)); + } +} + +void FederateState::processLoggingMessage(ActionMessage& cmd) +{ + switch (cmd.action()) { + case CMD_LOG: + case CMD_REMOTE_LOG: + logMessage(cmd.messageID, + cmd.getString(0), + cmd.payload.to_string(), + cmd.action() == CMD_REMOTE_LOG); break; - case CMD_INTERFACE_CONFIGURE: - setInterfaceProperty(cmd); + + case CMD_WARNING: + if (cmd.payload.empty()) { + cmd.payload = commandErrorString(cmd.messageID); + if (cmd.payload.to_string() == "unknown") { + cmd.payload.append(" code:"); + cmd.payload.append(std::to_string(cmd.messageID)); + } + } + LOG_WARNING(cmd.payload.to_string()); break; - case CMD_SEND_COMMAND: - case CMD_SEND_COMMAND_ORDERED: - sendCommand(cmd); + case CMD_SET_PROFILER_FLAG: + setOptionFlag(defs::PROFILING, checkActionFlag(cmd, indicator_flag)); break; case CMD_TIMEOUT_DISCONNECT: { auto qres = processQueryActual("global_time_debugging"); qres.insert(0, "TIME DEBUGGING::"); LOG_WARNING(qres); } break; - case CMD_QUERY_ORDERED: - case CMD_QUERY: { - std::string repStr; - ActionMessage queryResp(cmd.action() == CMD_QUERY ? CMD_QUERY_REPLY : - CMD_QUERY_REPLY_ORDERED); - queryResp.dest_id = cmd.source_id; - queryResp.source_id = cmd.dest_id; - queryResp.messageID = cmd.messageID; - queryResp.counter = cmd.counter; - - queryResp.payload = processQueryActual(cmd.payload.to_string()); - routeMessage(std::move(queryResp)); - } break; + default: + break; } - return MessageProcessingResult::CONTINUE_PROCESSING; } void FederateState::setProperties(const ActionMessage& cmd) @@ -2248,8 +2308,8 @@ Time FederateState::nextValueTime() const Time FederateState::nextMessageTime() const { auto firstMessageTime = Time::maxVal(); - for (const auto& ep : interfaceInformation.getEndpoints()) { - auto messageTime = ep->firstMessageTime(); + for (const auto& endpoint : interfaceInformation.getEndpoints()) { + auto messageTime = endpoint->firstMessageTime(); if (messageTime < time_granted) { messageTime = time_granted; } @@ -2276,11 +2336,11 @@ void FederateState::logMessage(int level, return; } std::string header; - auto t = grantedTime(); + auto currentTime = grantedTime(); std::string timeString; - if (t < timeZero) { + if (currentTime < timeZero) { timeString = fmt::format("[{}]", fedStateString(getState())); - } else if (t == Time::maxVal()) { + } else if (currentTime == Time::maxVal()) { timeString = "[MAXTIME]"; } else { timeString = fmt::format("[{}]", static_cast(grantedTime())); @@ -2298,7 +2358,7 @@ void FederateState::logMessage(int level, const std::string& fedStateString(FederateStates state) { - static const std::string c1{"created"}; + static const std::string created{"created"}; static const std::string estate{"error"}; static const std::string init{"initializing"}; static const std::string dis{"disconnected"}; @@ -2308,7 +2368,7 @@ const std::string& fedStateString(FederateStates state) switch (state) { case FederateStates::CREATED: - return c1; + return created; case FederateStates::INITIALIZING: return init; case FederateStates::EXECUTING: @@ -2485,21 +2545,24 @@ std::string FederateState::processQueryActual(std::string_view query) const }; auto qres = generateInterfaceQueryResults(query, interfaceInformation, addHeader); + if (!qres.empty()) { + return qres; + } if (query == "global_flush") { return "{\"status\":true}"; } if (query == "subscriptions") { - std::ostringstream s; - s << "["; + std::ostringstream subs; + subs << "["; auto ipts = interfaceInformation.getInputs(); for (const auto& ipt : ipts) { for (const auto& isrc : ipt->input_sources) { - s << isrc.fed_id << ':' << isrc.handle << ';'; + subs << isrc.fed_id << ':' << isrc.handle << ';'; } } ipts.unlock(); unlock(); - auto str = s.str(); + auto str = subs.str(); if (str.back() == ';') { str.pop_back(); } @@ -2528,10 +2591,10 @@ std::string FederateState::processQueryActual(std::string_view query) const addHeader(base); base["barriers"] = Json::arrayValue; - for (const auto& br : timeCoord->getBarriers()) { + for (const auto& barrier : timeCoord->getBarriers()) { Json::Value br1 = Json::objectValue; - br1["id"] = br.second; - br1["time"] = static_cast(br.first); + br1["id"] = barrier.second; + br1["time"] = static_cast(barrier.first); base["barriers"].append(std::move(br1)); } return fileops::generateJsonString(base); @@ -2566,19 +2629,48 @@ std::string FederateState::processQueryActual(std::string_view query) const addFederateTags(base, this); return fileops::generateJsonString(base); } + if (query == "unconnected_interfaces") { + Json::Value base; + addHeader(base); + interfaceInformation.getUnconnectedInterfaces(base); + + if (!tags.empty()) { + Json::Value tagBlock = Json::objectValue; + for (const auto& tag : tags) { + tagBlock[tag.first] = tag.second; + } + base["tags"] = tagBlock; + } + if (queryCallback) { + auto potential = queryCallback("potential_interfaces"); + if (!potential.empty()) { + try { + auto json = fileops::loadJsonStr(potential); + + if (!json.isMember("error")) { + base["potential_interfaces"] = json; + } + } + catch (const std::invalid_argument&) { + ; + } + } + } + return fileops::generateJsonString(base); + } if (query == "tags") { Json::Value tagBlock = Json::objectValue; - for (const auto& tg : tags) { - tagBlock[tg.first] = tg.second; + for (const auto& tag : tags) { + tagBlock[tag.first] = tag.second; } return fileops::generateJsonString(tagBlock); } if (query.compare(0, 4, "tag/") == 0) { - std::string_view tag = query; - tag.remove_prefix(4); - for (const auto& tg : tags) { - if (tag == tg.first) { - return Json::valueToQuotedString(tg.second.c_str()); + std::string_view keyTag = query; + keyTag.remove_prefix(4); + for (const auto& tag : tags) { + if (keyTag == tag.first) { + return Json::valueToQuotedString(tag.second.c_str()); } } return "\"\""; @@ -2596,7 +2688,7 @@ std::string FederateState::processQueryActual(std::string_view query) const if (query == "data_flow_graph") { Json::Value base; addHeader(base); - interfaceInformation.GenerateDataFlowGraph(base); + interfaceInformation.generateDataFlowGraph(base); return fileops::generateJsonString(base); } if (query == "global_time" || query == "global_status") { @@ -2626,10 +2718,10 @@ std::string FederateState::processQueryActual(std::string_view query) const return val; } } - // check tag value for a matching string - for (const auto& tg : tags) { - if (tg.first == query) { - return Json::valueToQuotedString(tg.second.c_str()); + // check existingTag value for a matching string + for (const auto& tag : tags) { + if (tag.first == query) { + return Json::valueToQuotedString(tag.second.c_str()); } } return generateJsonErrorResponse(JsonErrorCodes::BAD_REQUEST, "unrecognized Federate query"); @@ -2644,7 +2736,7 @@ std::string FederateState::processQuery(std::string_view query, bool force_order qstring = processQueryActual(query); } else if ((query == "queries") || (query == "available_queries")) { qstring = - R"("publications","inputs","logs","endpoints","subscriptions","current_state","global_state","dependencies","timeconfig","config","dependents","current_time","global_time","global_status")"; + R"("publications","inputs","logs","endpoints","subscriptions","current_state","global_state","dependencies","timeconfig","config","dependents","current_time","global_time","global_status","unconnected_interfaces")"; } else if (query == "state") { qstring = fmt::format("\"{}\"", fedStateString(getState())); } else { // the rest might need be locked to prevent a race condition @@ -2666,10 +2758,10 @@ int FederateState::loggingLevel() const void FederateState::setTag(std::string_view tag, std::string_view value) { spinlock(); - for (auto& tg : tags) { - if (tg.first == tag) { + for (auto& testTag : tags) { + if (testTag.first == tag) { unlock(); - tg.second = value; + testTag.second = value; return; } } @@ -2680,10 +2772,10 @@ void FederateState::setTag(std::string_view tag, std::string_view value) const std::string& FederateState::getTag(std::string_view tag) const { spinlock(); - for (const auto& tg : tags) { - if (tg.first == tag) { + for (const auto& existingTag : tags) { + if (existingTag.first == tag) { unlock(); - return tg.second; + return existingTag.second; } } unlock(); diff --git a/src/helics/core/FederateState.hpp b/src/helics/core/FederateState.hpp index 9be8a61082..ffdbc3f3c2 100644 --- a/src/helics/core/FederateState.hpp +++ b/src/helics/core/FederateState.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -20,8 +20,10 @@ SPDX-License-Identifier: BSD-3-Clause #include #include #include +#include #include #include +#include #include #include @@ -159,9 +161,9 @@ class FederateState { void setState(FederateStates newState); /** check if a message should be delayed*/ - bool messageShouldBeDelayed(const ActionMessage& cmd) const; + bool messageShouldBeDelayed(const ActionMessage& cmd) const noexcept; /** add a federate to the delayed list*/ - void addFederateToDelay(GlobalFederateId id); + void addFederateToDelay(GlobalFederateId gid); /** generate a component of json config string*/ void generateConfig(Json::Value& base) const; @@ -180,7 +182,7 @@ class FederateState { const InterfaceInfo& interfaces() const { return interfaceInformation; } /** get the size of a message queue for a specific endpoint or filter handle*/ - uint64_t getQueueSize(InterfaceHandle id) const; + uint64_t getQueueSize(InterfaceHandle hid) const; /** get the sum of all message queue sizes i.e. the total number of messages available in all * endpoints*/ uint64_t getQueueSize() const; @@ -189,12 +191,12 @@ class FederateState { */ int32_t getCurrentIteration() const; /** get the next available message for an endpoint - @param id the handle of an endpoint or filter + @param hid the handle of an endpoint or filter @return a pointer to a message -the ownership of the message is transferred to the caller*/ - std::unique_ptr receive(InterfaceHandle id); + std::unique_ptr receive(InterfaceHandle hid); /** get any message ready for reception - @param[out] id the endpoint related to the message*/ - std::unique_ptr receiveAny(InterfaceHandle& id); + @param[out] hid the endpoint related to the message*/ + std::unique_ptr receiveAny(InterfaceHandle& hid); /** * Return the data for the specified handle or the latest input */ @@ -309,10 +311,26 @@ class FederateState { @return a convergence state value with an indicator of return reason and state of convergence */ MessageProcessingResult processDelayQueue() noexcept; + + std::optional + checkProcResult(std::tuple& proc_result, + ActionMessage& cmd); /** process a single message @return a convergence state value with an indicator of return reason and state of convergence */ MessageProcessingResult processActionMessage(ActionMessage& cmd); + + /** process a data connection management message + */ + void processDataConnectionMessage(ActionMessage& cmd); + + /** process a message containing data + */ + void processDataMessage(ActionMessage& cmd); + /** run a timeout check*/ + void timeoutCheck(ActionMessage& cmd); + /** process a logging message*/ + void processLoggingMessage(ActionMessage& cmd); /** fill event list @param currentTime the time of the update */ diff --git a/src/helics/core/FilterCoordinator.cpp b/src/helics/core/FilterCoordinator.cpp index 04a8a0e8cb..21b2cd1ad8 100644 --- a/src/helics/core/FilterCoordinator.cpp +++ b/src/helics/core/FilterCoordinator.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/core/FilterCoordinator.hpp b/src/helics/core/FilterCoordinator.hpp index 0b451c2153..b6e55a73ae 100644 --- a/src/helics/core/FilterCoordinator.hpp +++ b/src/helics/core/FilterCoordinator.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/core/FilterFederate.cpp b/src/helics/core/FilterFederate.cpp index e0a684bb85..cca650494a 100644 --- a/src/helics/core/FilterFederate.cpp +++ b/src/helics/core/FilterFederate.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/core/FilterFederate.hpp b/src/helics/core/FilterFederate.hpp index 4887c8bf84..fe9b795c31 100644 --- a/src/helics/core/FilterFederate.hpp +++ b/src/helics/core/FilterFederate.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/core/FilterInfo.cpp b/src/helics/core/FilterInfo.cpp index e96c8329be..e0c36f7714 100644 --- a/src/helics/core/FilterInfo.cpp +++ b/src/helics/core/FilterInfo.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/core/FilterInfo.hpp b/src/helics/core/FilterInfo.hpp index c16139d5e6..e0aa795263 100644 --- a/src/helics/core/FilterInfo.hpp +++ b/src/helics/core/FilterInfo.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/core/ForwardingTimeCoordinator.cpp b/src/helics/core/ForwardingTimeCoordinator.cpp index 27516c6fbb..efe7cbeb31 100644 --- a/src/helics/core/ForwardingTimeCoordinator.cpp +++ b/src/helics/core/ForwardingTimeCoordinator.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -7,13 +7,13 @@ SPDX-License-Identifier: BSD-3-Clause #include "ForwardingTimeCoordinator.hpp" -#include "../common/fmt_format.h" #include "flagOperations.hpp" #include "helics_definitions.hpp" -#include "json/json.h" #include +#include #include +#include #include #include #include @@ -71,10 +71,11 @@ bool ForwardingTimeCoordinator::updateTimeFactors() } auto td = generateMinTimeUpstream( dependencies, restrictive_time_policy, mSourceId, downstream.minFed, 0); - DependencyInfo di; - di.update(td); - auto upd_delayed = - generateTimeRequest(di, downstream.minFed, di.responseSequenceCounter); + DependencyInfo dependency; + dependency.update(td); + auto upd_delayed = generateTimeRequest(dependency, + downstream.minFed, + dependency.responseSequenceCounter); if (sendMessageFunction) { sendMessageFunction(upd_delayed); } @@ -86,12 +87,13 @@ bool ForwardingTimeCoordinator::updateTimeFactors() } } else if (dependencies.hasDelayedDependency() && mTimeDownstream.minFed == dependencies.delayedDependency() && executionMode) { - auto td = generateMinTimeUpstream( + auto minTimeUpstream = generateMinTimeUpstream( dependencies, restrictive_time_policy, mSourceId, mTimeDownstream.minFed, 0); - DependencyInfo di; - di.update(td); - auto upd_delayed = - generateTimeRequest(di, mTimeDownstream.minFed, di.responseSequenceCounter); + DependencyInfo dependency; + dependency.update(minTimeUpstream); + auto upd_delayed = generateTimeRequest(dependency, + mTimeDownstream.minFed, + dependency.responseSequenceCounter); if (sendMessageFunction) { sendMessageFunction(upd_delayed); } diff --git a/src/helics/core/ForwardingTimeCoordinator.hpp b/src/helics/core/ForwardingTimeCoordinator.hpp index b1ec36c727..da8e6cd2e4 100644 --- a/src/helics/core/ForwardingTimeCoordinator.hpp +++ b/src/helics/core/ForwardingTimeCoordinator.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/core/GlobalFederateId.hpp b/src/helics/core/GlobalFederateId.hpp index 7e35ff6607..c1c154270d 100644 --- a/src/helics/core/GlobalFederateId.hpp +++ b/src/helics/core/GlobalFederateId.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/core/GlobalTimeCoordinator.cpp b/src/helics/core/GlobalTimeCoordinator.cpp index 103d6def57..8765ef9bcc 100644 --- a/src/helics/core/GlobalTimeCoordinator.cpp +++ b/src/helics/core/GlobalTimeCoordinator.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -7,13 +7,13 @@ SPDX-License-Identifier: BSD-3-Clause #include "GlobalTimeCoordinator.hpp" -#include "../common/fmt_format.h" #include "flagOperations.hpp" #include "helics_definitions.hpp" -#include "json/json.h" #include +#include #include +#include #include #include #include diff --git a/src/helics/core/GlobalTimeCoordinator.hpp b/src/helics/core/GlobalTimeCoordinator.hpp index 956f5fca6e..15e1c4301b 100644 --- a/src/helics/core/GlobalTimeCoordinator.hpp +++ b/src/helics/core/GlobalTimeCoordinator.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/core/HandleManager.cpp b/src/helics/core/HandleManager.cpp index 728e1d1913..859039b8a5 100644 --- a/src/helics/core/HandleManager.cpp +++ b/src/helics/core/HandleManager.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/core/HandleManager.hpp b/src/helics/core/HandleManager.hpp index 36330710d7..2949b3a730 100644 --- a/src/helics/core/HandleManager.hpp +++ b/src/helics/core/HandleManager.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -109,6 +109,11 @@ class HandleManager { /* search for handles based on a regex string and type*/ std::vector regexSearch(const std::string& regexExpression, InterfaceType type) const; + /** get all the aliases*/ + const std::unordered_map>& getAliases() const + { + return aliases; + } private: void addSearchFields(const BasicHandleInfo& handle, int32_t index); diff --git a/src/helics/core/InputInfo.cpp b/src/helics/core/InputInfo.cpp index 11f55e6157..fda9be6a7a 100644 --- a/src/helics/core/InputInfo.cpp +++ b/src/helics/core/InputInfo.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/core/InputInfo.hpp b/src/helics/core/InputInfo.hpp index a1c421a130..3d8e2a000d 100644 --- a/src/helics/core/InputInfo.hpp +++ b/src/helics/core/InputInfo.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/core/InterfaceInfo.cpp b/src/helics/core/InterfaceInfo.cpp index 404b23894f..f905bd7f86 100644 --- a/src/helics/core/InterfaceInfo.cpp +++ b/src/helics/core/InterfaceInfo.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -7,10 +7,10 @@ SPDX-License-Identifier: BSD-3-Clause #include "InterfaceInfo.hpp" #include "../common/JsonProcessingFunctions.hpp" -#include "../common/fmt_format.h" #include "flagOperations.hpp" #include "helics_definitions.hpp" +#include #include #include #include @@ -98,9 +98,9 @@ void InterfaceInfo::setChangeUpdateFlag(bool updateFlag) { if (updateFlag != only_update_on_change) { only_update_on_change = updateFlag; - // ip is a reference to a unique_ptr - for (auto& ip : inputs.lock()) { // NOLINT(readability-qualified-auto) - ip->only_update_on_change = updateFlag; + // input is a reference to a unique_ptr + for (auto& input : inputs.lock()) { // NOLINT(readability-qualified-auto) + input->only_update_on_change = updateFlag; } } } @@ -165,9 +165,9 @@ EndpointInfo* InterfaceInfo::getEndpoint(InterfaceHandle handle) return endpoints.lock()->find(handle); } -bool InterfaceInfo::setInputProperty(InterfaceHandle id, int32_t option, int32_t value) +bool InterfaceInfo::setInputProperty(InterfaceHandle hid, int32_t option, int32_t value) { - auto* ipt = getInput(id); + auto* ipt = getInput(hid); if (ipt == nullptr) { return false; } @@ -175,9 +175,9 @@ bool InterfaceInfo::setInputProperty(InterfaceHandle id, int32_t option, int32_t return true; } -bool InterfaceInfo::setPublicationProperty(InterfaceHandle id, int32_t option, int32_t value) +bool InterfaceInfo::setPublicationProperty(InterfaceHandle hid, int32_t option, int32_t value) { - auto* pub = getPublication(id); + auto* pub = getPublication(hid); if (pub == nullptr) { return false; } @@ -185,9 +185,9 @@ bool InterfaceInfo::setPublicationProperty(InterfaceHandle id, int32_t option, i return true; } -bool InterfaceInfo::setEndpointProperty(InterfaceHandle id, int32_t option, int32_t value) +bool InterfaceInfo::setEndpointProperty(InterfaceHandle hid, int32_t option, int32_t value) { - auto* ept = getEndpoint(id); + auto* ept = getEndpoint(hid); if (ept == nullptr) { return false; } @@ -196,27 +196,27 @@ bool InterfaceInfo::setEndpointProperty(InterfaceHandle id, int32_t option, int3 return true; } -int32_t InterfaceInfo::getInputProperty(InterfaceHandle id, int32_t option) const +int32_t InterfaceInfo::getInputProperty(InterfaceHandle hid, int32_t option) const { - const auto* ipt = getInput(id); + const auto* ipt = getInput(hid); if (ipt == nullptr) { return 0; } return ipt->getProperty(option); } -int32_t InterfaceInfo::getPublicationProperty(InterfaceHandle id, int32_t option) const +int32_t InterfaceInfo::getPublicationProperty(InterfaceHandle hid, int32_t option) const { - const auto* pub = getPublication(id); + const auto* pub = getPublication(hid); if (pub == nullptr) { return 0; } return pub->getProperty(option); } -int32_t InterfaceInfo::getEndpointProperty(InterfaceHandle id, int32_t option) const +int32_t InterfaceInfo::getEndpointProperty(InterfaceHandle hid, int32_t option) const { - const auto* ept = getEndpoint(id); + const auto* ept = getEndpoint(hid); if (ept == nullptr) { return 0; } @@ -317,6 +317,65 @@ std::vector> InterfaceInfo::checkInterfacesForIssues return issues; } +void InterfaceInfo::getUnconnectedInterfaces(Json::Value& base) const +{ + auto ihandle = inputs.lock_shared(); + if (ihandle->size() > 0) { + base["unconnected_inputs"] = Json::arrayValue; + base["connected_inputs"] = Json::arrayValue; + for (const auto& ipt : ihandle) { + if (!ipt->key.empty()) { + if (!ipt->has_target) { + base["unconnected_inputs"].append(ipt->key); + } else { + base["connected_inputs"].append(ipt->key); + } + } + } + } + ihandle.unlock(); + auto phandle = publications.lock(); + if (phandle->size() > 0) { + base["unconnected_publications"] = Json::arrayValue; + base["connected_publications"] = Json::arrayValue; + for (const auto& pub : phandle) { + if (!pub->key.empty()) { + if (pub->subscribers.empty()) { + base["unconnected_publications"].append(pub->key); + } else { + base["connected_publications"].append(pub->key); + } + } + } + } + phandle.unlock(); + + auto ehandle = endpoints.lock_shared(); + if (ehandle->size() > 0) { + base["unconnected_source_endpoints"] = Json::arrayValue; + base["unconnected_destination_endpoints"] = Json::arrayValue; + base["connected_endpoints"] = Json::arrayValue; + for (const auto& ept : ehandle) { + if (!ept->key.empty()) { + if (ept->targetedEndpoint) { + if (!ept->hasSource()) { + base["unconnected_target_endpoints"].append(ept->key); + } + if (!ept->hasTarget()) { + base["unconnected_source_endpoints"].append(ept->key); + } + if (ept->hasConnection()) { + base["connected_endpoints"].append(ept->key); + } + } else { + base["connected_endpoints"].append(ept->key); + } + } + } + } + ehandle.unlock(); +} + void InterfaceInfo::generateInferfaceConfig(Json::Value& base) const { auto ihandle = inputs.lock_shared(); @@ -370,11 +429,11 @@ void InterfaceInfo::generateInferfaceConfig(Json::Value& base) const } } } - phandle.unlock(); + ehandle.unlock(); base["extra"] = "configuration"; } -void InterfaceInfo::GenerateDataFlowGraph(Json::Value& base) const +void InterfaceInfo::generateDataFlowGraph(Json::Value& base) const { auto ihandle = inputs.lock_shared(); if (ihandle->size() > 0) { diff --git a/src/helics/core/InterfaceInfo.hpp b/src/helics/core/InterfaceInfo.hpp index 98d682d83c..024067f135 100644 --- a/src/helics/core/InterfaceInfo.hpp +++ b/src/helics/core/InterfaceInfo.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -70,20 +70,22 @@ class InterfaceInfo { /** get the current value of the change update flag*/ bool getChangeUpdateFlag() const { return only_update_on_change; } /** set a property on a specific interface*/ - bool setInputProperty(InterfaceHandle id, int32_t option, int32_t value); - bool setPublicationProperty(InterfaceHandle id, int32_t option, int32_t value); - bool setEndpointProperty(InterfaceHandle id, int32_t option, int32_t value); + bool setInputProperty(InterfaceHandle hid, int32_t option, int32_t value); + bool setPublicationProperty(InterfaceHandle hid, int32_t option, int32_t value); + bool setEndpointProperty(InterfaceHandle hid, int32_t option, int32_t value); /** get properties for an interface*/ - int32_t getInputProperty(InterfaceHandle id, int32_t option) const; - int32_t getPublicationProperty(InterfaceHandle id, int32_t option) const; - int32_t getEndpointProperty(InterfaceHandle id, int32_t option) const; + int32_t getInputProperty(InterfaceHandle hid, int32_t option) const; + int32_t getPublicationProperty(InterfaceHandle hid, int32_t option) const; + int32_t getEndpointProperty(InterfaceHandle hid, int32_t option) const; /** check the interfaces for specific issues*/ std::vector> checkInterfacesForIssues(); /** generate a configuration script for the interfaces*/ void generateInferfaceConfig(Json::Value& base) const; /** load a dependency graph for the interfaces*/ - void GenerateDataFlowGraph(Json::Value& base) const; + void generateDataFlowGraph(Json::Value& base) const; + /** generate a list of unconnected interfaces*/ + void getUnconnectedInterfaces(Json::Value& base) const; private: std::atomic global_id; diff --git a/src/helics/core/LocalFederateId.cpp b/src/helics/core/LocalFederateId.cpp index 71afad86d0..ecae1aa7c7 100644 --- a/src/helics/core/LocalFederateId.cpp +++ b/src/helics/core/LocalFederateId.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/core/LocalFederateId.hpp b/src/helics/core/LocalFederateId.hpp index d5cbadf8d4..1bf243fb38 100644 --- a/src/helics/core/LocalFederateId.hpp +++ b/src/helics/core/LocalFederateId.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/core/LogManager.cpp b/src/helics/core/LogManager.cpp index 8cf8db08ff..ae6ce101f6 100644 --- a/src/helics/core/LogManager.cpp +++ b/src/helics/core/LogManager.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/core/LogManager.hpp b/src/helics/core/LogManager.hpp index e27c4e9eaf..2fab941082 100644 --- a/src/helics/core/LogManager.hpp +++ b/src/helics/core/LogManager.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/core/MessageTimer.cpp b/src/helics/core/MessageTimer.cpp index 3d4419b1e5..930ac656e1 100644 --- a/src/helics/core/MessageTimer.cpp +++ b/src/helics/core/MessageTimer.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/core/MessageTimer.hpp b/src/helics/core/MessageTimer.hpp index 8909752af9..52ba50fada 100644 --- a/src/helics/core/MessageTimer.hpp +++ b/src/helics/core/MessageTimer.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/core/ProfilerBuffer.cpp b/src/helics/core/ProfilerBuffer.cpp index efb166120a..1a6e5de01d 100644 --- a/src/helics/core/ProfilerBuffer.cpp +++ b/src/helics/core/ProfilerBuffer.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/core/ProfilerBuffer.hpp b/src/helics/core/ProfilerBuffer.hpp index 45a4804125..56a6ada20e 100644 --- a/src/helics/core/ProfilerBuffer.hpp +++ b/src/helics/core/ProfilerBuffer.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/core/PublicationInfo.cpp b/src/helics/core/PublicationInfo.cpp index 6391430d4e..672e20d4a0 100644 --- a/src/helics/core/PublicationInfo.cpp +++ b/src/helics/core/PublicationInfo.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/core/PublicationInfo.hpp b/src/helics/core/PublicationInfo.hpp index 7882bd6ceb..d0d51245d3 100644 --- a/src/helics/core/PublicationInfo.hpp +++ b/src/helics/core/PublicationInfo.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/core/SmallBuffer.hpp b/src/helics/core/SmallBuffer.hpp index ab96bda9f3..a9b3d3789c 100644 --- a/src/helics/core/SmallBuffer.hpp +++ b/src/helics/core/SmallBuffer.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -8,6 +8,7 @@ SPDX-License-Identifier: BSD-3-Clause #include #include +#include #include #include #include @@ -91,6 +92,17 @@ class SmallBuffer { } SmallBuffer& operator=(SmallBuffer&& sb) noexcept { + if (locked) { + // if locked then use the copy operation not move + const SmallBuffer& buf = sb; + try { + return operator=(buf); + } + catch (std::bad_alloc&) { + errorCondition = 2; + return *this; + } + } if (usingAllocatedBuffer) { if (nonOwning) { if (sb.heap == heap) { @@ -106,6 +118,7 @@ class SmallBuffer { delete[] heap; } } + if (sb.usingAllocatedBuffer) { heap = sb.heap; bufferCapacity = sb.bufferCapacity; @@ -310,6 +323,8 @@ class SmallBuffer { void lock(bool lockStatus = true) { locked = lockStatus; } bool isLocked() const { return locked; } + /** get the error condition*/ + std::int8_t errorState() const { return errorCondition; } /** check if the buffer is empty*/ bool empty() const { return (bufferSize == 0); } /** get the current size of the buffer*/ @@ -380,6 +395,7 @@ class SmallBuffer { bool nonOwning{false}; bool locked{false}; bool usingAllocatedBuffer{false}; + std::int8_t errorCondition{0}; public: std::uint32_t userKey{0}; // 32 bits of user data for whatever purpose is desired has no impact diff --git a/src/helics/core/TimeCoordinator.cpp b/src/helics/core/TimeCoordinator.cpp index a0e12dc3e0..df41034001 100644 --- a/src/helics/core/TimeCoordinator.cpp +++ b/src/helics/core/TimeCoordinator.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -7,12 +7,12 @@ SPDX-License-Identifier: BSD-3-Clause #include "TimeCoordinator.hpp" -#include "../common/fmt_format.h" #include "flagOperations.hpp" #include "helics_definitions.hpp" #include "json/json.h" #include +#include #include #include #include diff --git a/src/helics/core/TimeCoordinator.hpp b/src/helics/core/TimeCoordinator.hpp index b12ea4a6c6..efb19a4bc6 100644 --- a/src/helics/core/TimeCoordinator.hpp +++ b/src/helics/core/TimeCoordinator.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/core/TimeCoordinatorProcessing.cpp b/src/helics/core/TimeCoordinatorProcessing.cpp index 22250fc474..7e163242f1 100644 --- a/src/helics/core/TimeCoordinatorProcessing.cpp +++ b/src/helics/core/TimeCoordinatorProcessing.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/core/TimeCoordinatorProcessing.hpp b/src/helics/core/TimeCoordinatorProcessing.hpp index 1310e41e26..96b146dd5d 100644 --- a/src/helics/core/TimeCoordinatorProcessing.hpp +++ b/src/helics/core/TimeCoordinatorProcessing.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/core/TimeDependencies.cpp b/src/helics/core/TimeDependencies.cpp index 8a68ec7dd1..dd96503214 100644 --- a/src/helics/core/TimeDependencies.cpp +++ b/src/helics/core/TimeDependencies.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/core/TimeDependencies.hpp b/src/helics/core/TimeDependencies.hpp index c32d5ccf63..48772b8750 100644 --- a/src/helics/core/TimeDependencies.hpp +++ b/src/helics/core/TimeDependencies.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -89,8 +89,8 @@ class TimeData { TimeState startState = TimeState::initialized, std::uint8_t resLevel = 0U): next{start}, - Te{start}, minDe{start}, TeAlt{start}, mTimeState{startState}, restrictionLevel{ - resLevel} {}; + Te{start}, minDe{start}, TeAlt{start}, mTimeState{startState}, + restrictionLevel{resLevel} {}; /** check if there is an update to the current dependency info and assign*/ bool update(const TimeData& update); }; diff --git a/src/helics/core/TimeoutMonitor.cpp b/src/helics/core/TimeoutMonitor.cpp index fcf895d175..d852f960c8 100644 --- a/src/helics/core/TimeoutMonitor.cpp +++ b/src/helics/core/TimeoutMonitor.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/core/TimeoutMonitor.h b/src/helics/core/TimeoutMonitor.h index 0810d4d811..e549c80f6f 100644 --- a/src/helics/core/TimeoutMonitor.h +++ b/src/helics/core/TimeoutMonitor.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/core/TranslatorFederate.cpp b/src/helics/core/TranslatorFederate.cpp index 2074b77962..dfa56a0932 100644 --- a/src/helics/core/TranslatorFederate.cpp +++ b/src/helics/core/TranslatorFederate.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -69,8 +69,7 @@ void TranslatorFederate::executeTranslator(ActionMessage& command, TranslatorInf if (targets.empty()) { break; } - auto m = createMessageFromCommand(command); - auto val = trans->tranOp->convertToValue(std::move(m)); + auto val = trans->tranOp->convertToValue(createMessageFromCommand(command)); if (!val.empty()) { if (targets.size() == 1) { ActionMessage sendM(CMD_PUB); @@ -85,8 +84,8 @@ void TranslatorFederate::executeTranslator(ActionMessage& command, TranslatorInf sendM.setSource(trans->id); sendM.actionTime = trans->tranOp->computeNewValueTime(command.actionTime); sendM.payload = std::move(val); - for (const auto& tg : targets) { - sendM.setDestination(tg.first); + for (const auto& target : targets) { + sendM.setDestination(target.first); mSendMessage(sendM); } } @@ -111,10 +110,10 @@ void TranslatorFederate::executeTranslator(ActionMessage& command, TranslatorInf sendM.setDestination(targets.front().first); mDeliverMessage(sendM); } else { - for (const auto& tg : targets) { + for (const auto& target : targets) { auto messageCopy(sendM); - messageCopy.setString(targetStringLoc, tg.second); - messageCopy.setDestination(tg.first); + messageCopy.setString(targetStringLoc, target.second); + messageCopy.setDestination(target.first); mDeliverMessage(messageCopy); } } @@ -266,10 +265,11 @@ void TranslatorFederate::handleMessage(ActionMessage& command) if (command.messageID == UPDATE_TRANSLATOR_OPERATOR) { auto* tranI = getTranslatorInfo(mFedID, command.source_handle); if (tranI != nullptr) { - auto op = mGetAirLock(command.counter).try_unload(); - if (op) { - auto M = std::any_cast>(std::move(*op)); - tranI->tranOp = std::move(M); + auto locker = mGetAirLock(command.counter).try_unload(); + if (locker) { + auto operation = + std::any_cast>(std::move(*locker)); + tranI->tranOp = std::move(operation); } } } @@ -293,7 +293,7 @@ TranslatorInfo* TranslatorFederate::createTranslator(GlobalBrokerId dest, std::string_view units) { auto tran = std::make_unique( - GlobalHandle{(dest == parent_broker_id || dest == mCoreID) ? GlobalBrokerId(mFedID) : dest, + GlobalHandle{(dest == parent_broker_id || dest == mCoreID) ? GlobalBrokerId{mFedID} : dest, handle}, key, endpointType, @@ -319,9 +319,9 @@ TranslatorInfo* TranslatorFederate::createTranslator(GlobalBrokerId dest, return retTarget; } -TranslatorInfo* TranslatorFederate::getTranslatorInfo(GlobalHandle id) +TranslatorInfo* TranslatorFederate::getTranslatorInfo(GlobalHandle gid) { - return translators.find(id); + return translators.find(gid); } TranslatorInfo* TranslatorFederate::getTranslatorInfo(GlobalFederateId fed, InterfaceHandle handle) @@ -430,17 +430,12 @@ std::string TranslatorFederate::query(std::string_view queryStr) const Json::Value tran; tran["id"] = trans->id.handle.baseValue(); tran["name"] = trans->key; - /* - tran["source_targets"] = generateStringVector(filt->sourceTargets, [](auto& dep) { - return std::to_string(dep.fed_id.baseValue()) + - "::" + std::to_string(dep.handle.baseValue()); - }); - tran["dest_targets"] = generateStringVector(filt->destTargets, [](auto& dep) { - return std::to_string(dep.fed_id.baseValue()) + - "::" + std::to_string(dep.handle.baseValue()); - }); - */ - tran["translators"].append(std::move(tran)); + + tran["source_endpoints"] = trans->getEndpointInfo()->getSourceTargets(); + tran["destination_endpoints"] = trans->getEndpointInfo()->getDestinationTargets(); + tran["source_publications"] = trans->getPubInfo()->getTargets(); + tran["destination_inputs"] = trans->getInputInfo()->getTargets(); + base["translators"].append(std::move(tran)); } } return fileops::generateJsonString(base); diff --git a/src/helics/core/TranslatorFederate.hpp b/src/helics/core/TranslatorFederate.hpp index f0f66d99e5..008a76b21e 100644 --- a/src/helics/core/TranslatorFederate.hpp +++ b/src/helics/core/TranslatorFederate.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/core/TranslatorInfo.cpp b/src/helics/core/TranslatorInfo.cpp index 6d3d73904c..bcbc48309b 100644 --- a/src/helics/core/TranslatorInfo.cpp +++ b/src/helics/core/TranslatorInfo.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/core/TranslatorInfo.hpp b/src/helics/core/TranslatorInfo.hpp index 1c8ff13fba..a1a5b6524d 100644 --- a/src/helics/core/TranslatorInfo.hpp +++ b/src/helics/core/TranslatorInfo.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/core/UnknownHandleManager.cpp b/src/helics/core/UnknownHandleManager.cpp index 480decf387..2622d532e8 100644 --- a/src/helics/core/UnknownHandleManager.cpp +++ b/src/helics/core/UnknownHandleManager.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -8,6 +8,8 @@ SPDX-License-Identifier: BSD-3-Clause #include "flagOperations.hpp" +#include + namespace helics { /** add a missingPublication*/ void UnknownHandleManager::addUnknownPublication(std::string_view key, @@ -65,12 +67,12 @@ static auto const std::string& target) { std::vector targets; - auto rp = tmap.equal_range(target); - if (rp.first != tmap.end()) { - auto it = rp.first; - while (it != rp.second) { - targets.push_back(it->second); - ++it; + auto [firstTarget, lastTarget] = tmap.equal_range(target); + if (firstTarget != tmap.end()) { + auto currentTarget = firstTarget; + while (currentTarget != lastTarget) { + targets.push_back(currentTarget->second); + ++currentTarget; } } return targets; @@ -80,12 +82,12 @@ static auto getTargets(const std::unordered_multimap& const std::string& target) { std::vector targets; - auto rp = tmap.equal_range(target); - if (rp.first != tmap.end()) { - auto it = rp.first; - while (it != rp.second) { - targets.push_back(it->second); - ++it; + auto [firstTarget, lastTarget] = tmap.equal_range(target); + if (firstTarget != tmap.end()) { + auto currentTarget = firstTarget; + while (currentTarget != lastTarget) { + targets.push_back(currentTarget->second); + ++currentTarget; } } return targets; @@ -154,58 +156,27 @@ bool UnknownHandleManager::hasNonOptionalUnknowns() const unknown_src_filters.empty())) { return true; } - for (const auto& upub : unknown_publications) { - if ((upub.second.second & make_flags(optional_flag)) != 0) { - continue; - } - return true; - } - for (const auto& uept : unknown_endpoints) { - if ((uept.second.second & make_flags(optional_flag)) != 0) { - continue; - } - return true; - } - for (const auto& uinp : unknown_inputs) { - if ((uinp.second.second & make_flags(optional_flag)) != 0) { - continue; - } - return true; - } - for (const auto& ufilt : unknown_filters) { - if ((ufilt.second.second & make_flags(optional_flag)) != 0) { - continue; - } - return true; - } - return false; + auto optionalCheck = [](const auto& uInterface) { + return ((uInterface.second.second & make_flags(optional_flag)) != 0); + }; + return ( + !((std::all_of(unknown_publications.begin(), unknown_publications.end(), optionalCheck)) && + (std::all_of(unknown_inputs.begin(), unknown_inputs.end(), optionalCheck)) && + (std::all_of(unknown_endpoints.begin(), unknown_endpoints.end(), optionalCheck)) && + (std::all_of(unknown_filters.begin(), unknown_filters.end(), optionalCheck)))); } bool UnknownHandleManager::hasRequiredUnknowns() const { - for (const auto& upub : unknown_publications) { - if ((upub.second.second & make_flags(required_flag)) != 0) { - return true; - } - } - for (const auto& uept : unknown_endpoints) { - if ((uept.second.second & make_flags(required_flag)) != 0) { - return true; - } - } - for (const auto& uinp : unknown_inputs) { - if ((uinp.second.second & make_flags(required_flag)) != 0) { - return true; - } - } - - for (const auto& ufilt : unknown_filters) { - if ((ufilt.second.second & make_flags(required_flag)) != 0) { - return true; - } - } - return false; + auto requiredCheck = [](const auto& uInterface) { + return ((uInterface.second.second & make_flags(required_flag)) != 0); + }; + return ( + (std::any_of(unknown_publications.begin(), unknown_publications.end(), requiredCheck)) || + (std::any_of(unknown_inputs.begin(), unknown_inputs.end(), requiredCheck)) || + (std::any_of(unknown_endpoints.begin(), unknown_endpoints.end(), requiredCheck)) || + (std::any_of(unknown_filters.begin(), unknown_filters.end(), requiredCheck))); } void UnknownHandleManager::processUnknowns( @@ -225,6 +196,25 @@ void UnknownHandleManager::processUnknowns( } } +void UnknownHandleManager::processUnknownLinks( + const std::function< + void(const std::string& origin, InterfaceType, const std::string& target, InterfaceType)>& + cfunc) const +{ + for (const auto& dlink : unknown_links) { + cfunc(dlink.first, InterfaceType::PUBLICATION, dlink.second, InterfaceType::INPUT); + } + for (const auto& uept : unknown_endpoint_links) { + cfunc(uept.first, InterfaceType::ENDPOINT, uept.second, InterfaceType::ENDPOINT); + } + for (const auto& ufilt : unknown_dest_filters) { + cfunc(ufilt.first, InterfaceType::FILTER, ufilt.second, InterfaceType::ENDPOINT); + } + for (const auto& ufilt : unknown_src_filters) { + cfunc(ufilt.first, InterfaceType::FILTER, ufilt.second, InterfaceType::ENDPOINT); + } +} + void UnknownHandleManager::processNonOptionalUnknowns( const std::function& cfunc) const { @@ -314,34 +304,35 @@ template void maperase_if(ContainerT& items, const PredicateT& predicate) { for (auto it = items.begin(); it != items.end();) { - if (predicate(*it)) + if (predicate(*it)) { it = items.erase(it); - else + } else { ++it; + } } } -void UnknownHandleManager::clearFederateUnknowns(GlobalFederateId id) +void UnknownHandleManager::clearFederateUnknowns(GlobalFederateId gid) { - auto ck = [id](const auto& it) { return it.second.first.fed_id == id; }; - maperase_if(unknown_publications, ck); - maperase_if(unknown_endpoints, ck); - maperase_if(unknown_filters, ck); - maperase_if(unknown_inputs, ck); + auto clearCall = [gid](const auto& it) { return it.second.first.fed_id == gid; }; + maperase_if(unknown_publications, clearCall); + maperase_if(unknown_endpoints, clearCall); + maperase_if(unknown_filters, clearCall); + maperase_if(unknown_inputs, clearCall); } void UnknownHandleManager::clearUnknownsIf( const std::function& cfunc) { InterfaceType type = InterfaceType::PUBLICATION; - auto ck = [&cfunc, &type](const auto& it) { return cfunc(it.first, type, it.second); }; - maperase_if(unknown_publications, ck); + auto clearCall = [&cfunc, &type](const auto& it) { return cfunc(it.first, type, it.second); }; + maperase_if(unknown_publications, clearCall); type = InterfaceType::ENDPOINT; - maperase_if(unknown_endpoints, ck); + maperase_if(unknown_endpoints, clearCall); type = InterfaceType::FILTER; - maperase_if(unknown_filters, ck); + maperase_if(unknown_filters, clearCall); type = InterfaceType::INPUT; - maperase_if(unknown_inputs, ck); + maperase_if(unknown_inputs, clearCall); } } // namespace helics diff --git a/src/helics/core/UnknownHandleManager.hpp b/src/helics/core/UnknownHandleManager.hpp index be3b8a1606..9dcecd2158 100644 --- a/src/helics/core/UnknownHandleManager.hpp +++ b/src/helics/core/UnknownHandleManager.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -117,6 +117,15 @@ class UnknownHandleManager { */ void processUnknowns( const std::function& cfunc) const; + + /** run a callback for each Unknown Link + @param cfunc a callback function with the signature of the name of the interface, + the interface type, the name of the target, and type of the target. + */ + void processUnknownLinks(const std::function& cfunc) const; }; } // namespace helics diff --git a/src/helics/core/basic_CoreTypes.hpp b/src/helics/core/basic_CoreTypes.hpp index b53316909a..af2ddf7755 100644 --- a/src/helics/core/basic_CoreTypes.hpp +++ b/src/helics/core/basic_CoreTypes.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/core/core-data.hpp b/src/helics/core/core-data.hpp index d8ea04c793..c3b472705c 100644 --- a/src/helics/core/core-data.hpp +++ b/src/helics/core/core-data.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/core/core-exceptions.hpp b/src/helics/core/core-exceptions.hpp index 9815de7a09..7b14232f45 100644 --- a/src/helics/core/core-exceptions.hpp +++ b/src/helics/core/core-exceptions.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/core/coreTypeOperations.cpp b/src/helics/core/coreTypeOperations.cpp index 96b43b5504..35b470049e 100644 --- a/src/helics/core/coreTypeOperations.cpp +++ b/src/helics/core/coreTypeOperations.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/core/coreTypeOperations.hpp b/src/helics/core/coreTypeOperations.hpp index 4402b5a0f7..dbf74ee1f7 100644 --- a/src/helics/core/coreTypeOperations.hpp +++ b/src/helics/core/coreTypeOperations.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -36,4 +36,8 @@ bool isCoreTypeAvailable(CoreType type) noexcept; @return true if the types are compatible with each other */ bool matchingTypes(std::string_view type1, std::string_view type2); + +/** generate an extended version and system info string in json format*/ +std::string systemInfo(); + } // namespace helics::core diff --git a/src/helics/core/fileConnections.hpp b/src/helics/core/fileConnections.hpp index 2de1aa13ec..3ed29404bc 100644 --- a/src/helics/core/fileConnections.hpp +++ b/src/helics/core/fileConnections.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/core/flagOperations.hpp b/src/helics/core/flagOperations.hpp index 5f1fc11bf2..d4724a4e6f 100644 --- a/src/helics/core/flagOperations.hpp +++ b/src/helics/core/flagOperations.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/core/helicsCLI11.hpp b/src/helics/core/helicsCLI11.hpp index 776bc7e0a2..4e82a70608 100644 --- a/src/helics/core/helicsCLI11.hpp +++ b/src/helics/core/helicsCLI11.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -24,12 +24,15 @@ SPDX-License-Identifier: BSD-3-Clause using helics::coreTypeFromString; using helics::loadTimeFromString; +using helics::systemInfo; using helics::to_string; + #else # include "../utilities/timeStringOps.hpp" # include "coreTypeOperations.hpp" using helics::core::coreTypeFromString; +using helics::core::systemInfo; using helics::core::to_string; /** generate a local function that uses the utilities library*/ inline helics::Time loadTimeFromString(std::string_view str, time_units defUnit) @@ -143,7 +146,7 @@ class helicsCLI11App: public CLI::App { add_flag_callback( "--system", []() { - std::cout << helics::systemInfo() << std::endl; + std::cout << systemInfo() << std::endl; throw CLI::Success{}; }, "display system information details"); diff --git a/src/helics/core/helicsCLI11JsonConfig.cpp b/src/helics/core/helicsCLI11JsonConfig.cpp index 3097c03271..2d5c277142 100644 --- a/src/helics/core/helicsCLI11JsonConfig.cpp +++ b/src/helics/core/helicsCLI11JsonConfig.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/core/helicsCLI11JsonConfig.hpp b/src/helics/core/helicsCLI11JsonConfig.hpp index 30dab34f29..fcc32b3249 100644 --- a/src/helics/core/helicsCLI11JsonConfig.hpp +++ b/src/helics/core/helicsCLI11JsonConfig.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/core/helicsTime.hpp b/src/helics/core/helicsTime.hpp index 1e0936ea4c..86b282c0e4 100644 --- a/src/helics/core/helicsTime.hpp +++ b/src/helics/core/helicsTime.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -39,12 +39,6 @@ constexpr Time cBigTime = Time{static_cast(HELICS_BIG_NUMBER * 1000000) /** common definition of currentTime in initialization mode*/ constexpr Time initializationTime = negEpsilon; -/** user defined literal for a time variable*/ -constexpr Time operator"" _t(long double val) -{ - return {static_cast(val)}; -} // NOLINT - /** simple structure with the time and completion marker for iterations or dense time steps*/ struct iteration_time { Time grantedTime; //!< the time of the granted step diff --git a/src/helics/core/helicsVersion.cpp b/src/helics/core/helicsVersion.cpp index c7e1164a2b..a56e143254 100644 --- a/src/helics/core/helicsVersion.cpp +++ b/src/helics/core/helicsVersion.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -133,8 +133,8 @@ std::string os_info() std::uint64_t getTotalSystemMemory() { - std::uint64_t pages = sysconf(_SC_PHYS_PAGES); - std::uint64_t page_size = sysconf(_SC_PAGE_SIZE); + const std::uint64_t pages = sysconf(_SC_PHYS_PAGES); + const std::uint64_t page_size = sysconf(_SC_PAGE_SIZE); return pages * page_size; } @@ -143,7 +143,7 @@ std::string os_info() std::string osInfo; utsname details = {}; - int ret = uname(&details); + const int ret = uname(&details); if (ret == 0) { osInfo.append(details.sysname); @@ -190,7 +190,7 @@ std::string getHostName() return computerName; } -namespace helics { +namespace helics::core { std::string systemInfo() { @@ -229,4 +229,4 @@ std::string systemInfo() return fileops::generateJsonString(base); } -} // namespace helics +} // namespace helics::core diff --git a/src/helics/core/helicsVersion.hpp b/src/helics/core/helicsVersion.hpp index 01d6e07522..70aeade3a3 100644 --- a/src/helics/core/helicsVersion.hpp +++ b/src/helics/core/helicsVersion.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -33,6 +33,5 @@ constexpr auto buildFlags = HELICS_BUILD_FLAGS_DEBUG; #endif /** compiler used to build helics*/ constexpr auto compiler = HELICS_COMPILER_VERSION; -/** generate an extended version and system info string in json format*/ -std::string systemInfo(); + } // namespace helics diff --git a/src/helics/core/helics_definitions.hpp b/src/helics/core/helics_definitions.hpp index f50ed9db68..a47a9b156d 100644 --- a/src/helics/core/helics_definitions.hpp +++ b/src/helics/core/helics_definitions.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/core/loggingHelper.hpp b/src/helics/core/loggingHelper.hpp index 0fde18ea9f..8936a6edfe 100644 --- a/src/helics/core/loggingHelper.hpp +++ b/src/helics/core/loggingHelper.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/core/queryHelpers.cpp b/src/helics/core/queryHelpers.cpp index 7d6e400bd1..5ce8ed668d 100644 --- a/src/helics/core/queryHelpers.cpp +++ b/src/helics/core/queryHelpers.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/core/queryHelpers.hpp b/src/helics/core/queryHelpers.hpp index 6e02b37eb3..3c8e14e9a6 100644 --- a/src/helics/core/queryHelpers.hpp +++ b/src/helics/core/queryHelpers.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -31,7 +31,8 @@ enum Subqueries : std::uint16_t { GLOBAL_TIME_DEBUGGING = 7, GLOBAL_FLUSH = 8, GLOBAL_STATUS = 9, - BARRIERS = 11 + BARRIERS = 11, + UNCONNECTED_INTERFACES = 14 }; /// Enumeration of if query result is reusable diff --git a/src/helics/cpp98/Broker.hpp b/src/helics/cpp98/Broker.hpp index 2085cc7d11..71692e511a 100644 --- a/src/helics/cpp98/Broker.hpp +++ b/src/helics/cpp98/Broker.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/cpp98/CMakeLists.txt b/src/helics/cpp98/CMakeLists.txt index abccab248c..193fd69e81 100644 --- a/src/helics/cpp98/CMakeLists.txt +++ b/src/helics/cpp98/CMakeLists.txt @@ -1,5 +1,5 @@ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Copyright (c) 2017-2023, Battelle Memorial Institute; Lawrence Livermore +# Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore # National Security, LLC; Alliance for Sustainable Energy, LLC. # See the top-level NOTICE for additional details. # All rights reserved. diff --git a/src/helics/cpp98/CombinationFederate.hpp b/src/helics/cpp98/CombinationFederate.hpp index 5f7c3bf24d..323b997021 100644 --- a/src/helics/cpp98/CombinationFederate.hpp +++ b/src/helics/cpp98/CombinationFederate.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/cpp98/Core.hpp b/src/helics/cpp98/Core.hpp index b22d01182f..580145a6e7 100644 --- a/src/helics/cpp98/Core.hpp +++ b/src/helics/cpp98/Core.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/cpp98/DataBuffer.hpp b/src/helics/cpp98/DataBuffer.hpp index 74dcbdb2bc..2c1e8d0d8b 100644 --- a/src/helics/cpp98/DataBuffer.hpp +++ b/src/helics/cpp98/DataBuffer.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -19,35 +19,55 @@ class DataBuffer { public: DataBuffer() HELICS_NOTHROW: buff(helicsCreateDataBuffer(0)) {} explicit DataBuffer(int capacity): buff(helicsCreateDataBuffer(capacity)) {} - - void toBytes(double val) { helicsDoubleToBytes(val, buff); } - void toBytes(int64_t val) { helicsIntegerToBytes(val, buff); } - void toBytes(const std::string& val) { helicsStringToBytes(val.c_str(), buff); } - void toBytes(const std::vector& val) + /** create a dataBuffer object from an existing C API buffer*/ + explicit DataBuffer(HelicsDataBuffer buffer): buff(buffer) {} + DataBuffer(void* buffer, int32_t datasize, int32_t capacity): + buff(helicsWrapDataInBuffer(buffer, datasize, capacity)) { - helicsVectorToBytes(val.data(), static_cast(val.size()), buff); } - void toBytes(const std::complex val) + /** destructor*/ + ~DataBuffer() { helicsDataBufferFree(buff); } + void fill(double val) { helicsDataBufferFillFromDouble(buff, val); } + void fill(int64_t val) { helicsDataBufferFillFromInteger(buff, val); } + void fill(const std::string& val) { helicsDataBufferFillFromString(buff, val.c_str()); } + void fill(const char* val) { helicsDataBufferFillFromString(buff, val); } + void fill(const std::vector& val) { - helicsComplexToBytes(val.real(), val.imag(), buff); + helicsDataBufferFillFromVector(buff, val.data(), static_cast(val.size())); } - void toBytes(const double* vals, int size) { helicsVectorToBytes(vals, size, buff); } - void toBytes(const std::string& name, double val) + void fill(const std::complex val) { - helicsNamedPointToBytes(name.c_str(), val, buff); + helicsDataBufferFillFromComplex(buff, val.real(), val.imag()); } - void toBytes(bool val) { helicsBooleanToBytes(val ? HELICS_TRUE : HELICS_FALSE, buff); } - void toBytes(char val) { helicsCharToBytes(val, buff); } - + void fill(const double* vals, int size) { helicsDataBufferFillFromVector(buff, vals, size); } + void fill(const std::string& name, double val) + { + helicsDataBufferFillFromNamedPoint(buff, name.c_str(), val); + } + void fill(bool val) { helicsDataBufferFillFromBoolean(buff, val ? HELICS_TRUE : HELICS_FALSE); } + void fill(char val) { helicsDataBufferFillFromChar(buff, val); } + /** make a deep copy of the buffer*/ + DataBuffer clone() { return DataBuffer(helicsDataBufferClone(buff)); } /** get the size of the raw value */ int size() { return helicsDataBufferSize(buff); } /** get the size of the raw value */ int capacity() { return helicsDataBufferCapacity(buff); } - + /** get a pointer to the raw data*/ + void* data() { return helicsDataBufferData(buff); } + /** reserve a capacity in the buffer*/ + bool reserve(int32_t newCapacity) + { + return helicsDataBufferReserve(buff, newCapacity) == HELICS_TRUE; + } /** get the size of the value as a string */ int stringSize() { return helicsDataBufferStringSize(buff); } - + /** get the size of the value as a vector */ + int vectorSize() { return helicsDataBufferVectorSize(buff); } + /** get the type of data contained in the buffer*/ + int type() const { return helicsDataBufferType(buff); } + /** check if the buffer is valid*/ + bool isValid() const { return (helicsDataBufferIsValid(buff) == HELICS_TRUE); } /** get the current value as a string*/ std::string toString() { @@ -134,6 +154,15 @@ class DataBuffer { // maxlen contains the actual length now return maxlen; } + /** convert the data in a data buffer to a different type representation + @param newDataType the type that it is desired for the buffer to be converted to + @return true if the conversion was successful*/ + bool convertToType(int newDataType) + { + return (helicsDataBufferConvertToType(buff, newDataType) == HELICS_TRUE); + } + /** get the C API dataobject */ + HelicsDataBuffer getHelicsDataBuffer() { return buff; } private: HelicsDataBuffer buff; diff --git a/src/helics/cpp98/Endpoint.hpp b/src/helics/cpp98/Endpoint.hpp index d69eb78fd2..b494b9640e 100644 --- a/src/helics/cpp98/Endpoint.hpp +++ b/src/helics/cpp98/Endpoint.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -8,6 +8,7 @@ SPDX-License-Identifier: BSD-3-Clause #define HELICS_CPP98_ENDPOINT_HPP_ #pragma once +#include "DataBuffer.hpp" #include "helics/helics.h" #include "helicsExceptions.hpp" @@ -136,6 +137,12 @@ class Message { helicsMessageSetString(mo, str, hThrowOnError()); return *this; } + /** set the data a data buffer object*/ + Message& data(DataBuffer buffer) + { + helicsMessageSetDataBuffer(mo, buffer.getHelicsDataBuffer(), hThrowOnError()); + return *this; + } /** append data to the message data field*/ Message& append(const void* ptr, int size) { @@ -186,6 +193,8 @@ class Message { return mreturn; } void clear() { helicsMessageClear(mo, HELICS_IGNORE_ERROR); } + /** get the data buffer from the message */ + DataBuffer dataBuffer() { return DataBuffer(helicsMessageDataBuffer(mo, HELICS_IGNORE_ERROR)); } /** generate a new message in a federate*/ Message& newMessageObject(const Federate& fed); diff --git a/src/helics/cpp98/Federate.hpp b/src/helics/cpp98/Federate.hpp index 45302c101d..b022a80b60 100644 --- a/src/helics/cpp98/Federate.hpp +++ b/src/helics/cpp98/Federate.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/cpp98/Filter.hpp b/src/helics/cpp98/Filter.hpp index c8a70c08ad..1deca3c937 100644 --- a/src/helics/cpp98/Filter.hpp +++ b/src/helics/cpp98/Filter.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/cpp98/Input.hpp b/src/helics/cpp98/Input.hpp index d927c33165..b793af6e02 100644 --- a/src/helics/cpp98/Input.hpp +++ b/src/helics/cpp98/Input.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -8,6 +8,7 @@ SPDX-License-Identifier: BSD-3-Clause #define HELICS_CPP98_INPUT_HPP_ #pragma once +#include "DataBuffer.hpp" #include "helics/helics.h" #include "helicsExceptions.hpp" @@ -218,7 +219,11 @@ class Input { #if defined(__GNUC__) # pragma GCC diagnostic pop #endif - + /** get a data buffer with the input value*/ + DataBuffer getDataBuffer() + { + return DataBuffer(helicsInputGetDataBuffer(inp, hThrowOnError())); + } /** Check if an input is updated **/ bool isUpdated() const { return (helicsInputIsUpdated(inp) > 0); } diff --git a/src/helics/cpp98/MessageFederate.hpp b/src/helics/cpp98/MessageFederate.hpp index 2314ff9e56..497b6df0ff 100644 --- a/src/helics/cpp98/MessageFederate.hpp +++ b/src/helics/cpp98/MessageFederate.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/cpp98/Publication.hpp b/src/helics/cpp98/Publication.hpp index ba2e08be8b..d129ef4faa 100644 --- a/src/helics/cpp98/Publication.hpp +++ b/src/helics/cpp98/Publication.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -8,6 +8,7 @@ SPDX-License-Identifier: BSD-3-Clause #define HELICS_CPP98_PUBLICATION_HPP_ #pragma once +#include "DataBuffer.hpp" #include "helics/helics.h" #include "helicsExceptions.hpp" @@ -117,6 +118,11 @@ class Publication { { helicsPublicationPublishBoolean(pub, val ? HELICS_TRUE : HELICS_FALSE, HELICS_IGNORE_ERROR); } + /** publish a data buffer value*/ + void publish(DataBuffer& buffer) + { + helicsPublicationPublishDataBuffer(pub, buffer.getHelicsDataBuffer(), hThrowOnError()); + } /** get the name of the publication*/ const char* getName() const { return helicsPublicationGetName(pub); } /** get the units of the publication*/ diff --git a/src/helics/cpp98/Translator.hpp b/src/helics/cpp98/Translator.hpp index e9d2349866..c6364ac43f 100644 --- a/src/helics/cpp98/Translator.hpp +++ b/src/helics/cpp98/Translator.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/cpp98/ValueFederate.hpp b/src/helics/cpp98/ValueFederate.hpp index a8c3b0e0df..c92d888c53 100644 --- a/src/helics/cpp98/ValueFederate.hpp +++ b/src/helics/cpp98/ValueFederate.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/cpp98/config.hpp b/src/helics/cpp98/config.hpp index c8f3dc0cf9..8238f41fe3 100644 --- a/src/helics/cpp98/config.hpp +++ b/src/helics/cpp98/config.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/cpp98/helics.hpp b/src/helics/cpp98/helics.hpp index b13221e1fd..c826506fe6 100644 --- a/src/helics/cpp98/helics.hpp +++ b/src/helics/cpp98/helics.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/cpp98/helicsExceptions.hpp b/src/helics/cpp98/helicsExceptions.hpp index d67b1c7d50..a63b95620e 100644 --- a/src/helics/cpp98/helicsExceptions.hpp +++ b/src/helics/cpp98/helicsExceptions.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/cxx_shared_library/CMakeLists.txt b/src/helics/cxx_shared_library/CMakeLists.txt index 5b4a353a8b..302c930869 100644 --- a/src/helics/cxx_shared_library/CMakeLists.txt +++ b/src/helics/cxx_shared_library/CMakeLists.txt @@ -1,5 +1,5 @@ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Copyright (c) 2017-2023, Battelle Memorial Institute; Lawrence Livermore +# Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore # National Security, LLC; Alliance for Sustainable Energy, LLC. # See the top-level NOTICE for additional details. # All rights reserved. diff --git a/src/helics/cxx_shared_library/collect_cxx_shared_headers.cmake b/src/helics/cxx_shared_library/collect_cxx_shared_headers.cmake index e7e4cf745f..5253b642ed 100644 --- a/src/helics/cxx_shared_library/collect_cxx_shared_headers.cmake +++ b/src/helics/cxx_shared_library/collect_cxx_shared_headers.cmake @@ -1,5 +1,5 @@ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Copyright (c) 2017-2023, Battelle Memorial Institute; Lawrence Livermore +# Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore # National Security, LLC; Alliance for Sustainable Energy, LLC. # See the top-level NOTICE for additional details. # All rights reserved. diff --git a/src/helics/cxx_shared_library/cxx_file_list.cmake b/src/helics/cxx_shared_library/cxx_file_list.cmake index c524945257..59e9025e42 100644 --- a/src/helics/cxx_shared_library/cxx_file_list.cmake +++ b/src/helics/cxx_shared_library/cxx_file_list.cmake @@ -1,5 +1,5 @@ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Copyright (c) 2017-2023, Battelle Memorial Institute; Lawrence Livermore +# Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore # National Security, LLC; Alliance for Sustainable Energy, LLC. # See the top-level NOTICE for additional details. # All rights reserved. diff --git a/src/helics/helics.hpp b/src/helics/helics.hpp index 8955779c35..b70327a54a 100644 --- a/src/helics/helics.hpp +++ b/src/helics/helics.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/helics_apps.hpp b/src/helics/helics_apps.hpp index 368cc3520a..46f7cef998 100644 --- a/src/helics/helics_apps.hpp +++ b/src/helics/helics_apps.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/helics_enums.h b/src/helics/helics_enums.h index 497b015f3d..c7f3a2a3f3 100644 --- a/src/helics/helics_enums.h +++ b/src/helics/helics_enums.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/network/CMakeLists.txt b/src/helics/network/CMakeLists.txt index 1b9804703e..36c38e4ec8 100644 --- a/src/helics/network/CMakeLists.txt +++ b/src/helics/network/CMakeLists.txt @@ -1,5 +1,5 @@ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Copyright (c) 2017-2023, Battelle Memorial Institute; Lawrence Livermore +# Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore # National Security, LLC; Alliance for Sustainable Energy, LLC. # See the top-level NOTICE for additional details. # All rights reserved. diff --git a/src/helics/network/CommsBroker.cpp b/src/helics/network/CommsBroker.cpp index 730ddcde9f..92d9dee54f 100644 --- a/src/helics/network/CommsBroker.cpp +++ b/src/helics/network/CommsBroker.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/network/CommsBroker.hpp b/src/helics/network/CommsBroker.hpp index 4c0b8cef3a..aa220cfeee 100644 --- a/src/helics/network/CommsBroker.hpp +++ b/src/helics/network/CommsBroker.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/network/CommsBroker_impl.hpp b/src/helics/network/CommsBroker_impl.hpp index 524e3e004a..4b1ec92210 100644 --- a/src/helics/network/CommsBroker_impl.hpp +++ b/src/helics/network/CommsBroker_impl.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/network/CommsInterface.cpp b/src/helics/network/CommsInterface.cpp index 307d90fb0e..0be581c3a5 100644 --- a/src/helics/network/CommsInterface.cpp +++ b/src/helics/network/CommsInterface.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -25,17 +25,18 @@ namespace CommFactory { things that call it so it needs to be a static member of function call*/ class MasterCommBuilder { public: - using BuildT = std::tuple>; + using BuilderData = std::tuple>; - static void addBuilder(std::shared_ptr cb, std::string_view name, int code) + static void + addBuilder(std::shared_ptr builder, std::string_view name, int code) { - instance()->builders.emplace_back(code, name, std::move(cb)); + instance()->builders.emplace_back(code, name, std::move(builder)); } static const std::shared_ptr& getBuilder(int code) { - for (auto& bb : instance()->builders) { - if (std::get<0>(bb) == code) { - return std::get<2>(bb); + for (auto& builder : instance()->builders) { + if (std::get<0>(builder) == code) { + return std::get<2>(builder); } } throw(HelicsException("comm type is not available")); @@ -43,9 +44,9 @@ namespace CommFactory { static const std::shared_ptr& getBuilder(std::string_view type) { - for (auto& bb : instance()->builders) { - if (std::get<1>(bb) == type) { - return std::get<2>(bb); + for (auto& builder : instance()->builders) { + if (std::get<1>(builder) == type) { + return std::get<2>(builder); } } throw(HelicsException("comm type is not available")); @@ -60,7 +61,7 @@ namespace CommFactory { } static const std::shared_ptr& instance() { - static std::shared_ptr iptr(new MasterCommBuilder()); + static const std::shared_ptr iptr(new MasterCommBuilder()); return iptr; } @@ -68,12 +69,12 @@ namespace CommFactory { /** private constructor since we only really want one of them accessed through the instance static member*/ MasterCommBuilder() = default; - std::vector builders; //!< container for the different builders + std::vector builders; //!< container for the different builders }; - void defineCommBuilder(std::shared_ptr cb, std::string_view name, int code) + void defineCommBuilder(std::shared_ptr builder, std::string_view name, int code) { - MasterCommBuilder::addBuilder(std::move(cb), name, code); + MasterCommBuilder::addBuilder(std::move(builder), name, code); } std::unique_ptr create(CoreType type) @@ -187,19 +188,19 @@ void CommsInterface::transmit(route_id rid, ActionMessage&& cmd) void CommsInterface::addRoute(route_id rid, std::string_view routeInfo) { - ActionMessage rt(CMD_PROTOCOL_PRIORITY); - rt.payload = routeInfo; - rt.messageID = NEW_ROUTE; - rt.setExtraData(rid.baseValue()); - transmit(control_route, std::move(rt)); + ActionMessage route(CMD_PROTOCOL_PRIORITY); + route.payload = routeInfo; + route.messageID = NEW_ROUTE; + route.setExtraData(rid.baseValue()); + transmit(control_route, std::move(route)); } void CommsInterface::removeRoute(route_id rid) { - ActionMessage rt(CMD_PROTOCOL); - rt.messageID = REMOVE_ROUTE; - rt.setExtraData(rid.baseValue()); - transmit(control_route, rt); + ActionMessage route(CMD_PROTOCOL); + route.messageID = REMOVE_ROUTE; + route.setExtraData(rid.baseValue()); + transmit(control_route, route); } void CommsInterface::setTxStatus(ConnectionStatus status) @@ -457,7 +458,7 @@ void CommsInterface::disconnect() void CommsInterface::join_tx_rx_thread() { - std::lock_guard syncLock(threadSyncLock); + const std::lock_guard syncLock(threadSyncLock); if (!singleThread) { if (queue_watcher.joinable()) { queue_watcher.join(); @@ -589,9 +590,9 @@ void CommsInterface::logError(std::string_view message) const void CommsInterface::closeTransmitter() { - ActionMessage rt(CMD_PROTOCOL); - rt.messageID = DISCONNECT; - transmit(control_route, rt); + ActionMessage close(CMD_PROTOCOL); + close.messageID = DISCONNECT; + transmit(control_route, close); } void CommsInterface::closeReceiver() @@ -603,9 +604,9 @@ void CommsInterface::closeReceiver() void CommsInterface::reconnectTransmitter() { - ActionMessage rt(CMD_PROTOCOL); - rt.messageID = RECONNECT_TRANSMITTER; - transmit(control_route, rt); + ActionMessage reconnect(CMD_PROTOCOL); + reconnect.messageID = RECONNECT_TRANSMITTER; + transmit(control_route, reconnect); } void CommsInterface::reconnectReceiver() diff --git a/src/helics/network/CommsInterface.hpp b/src/helics/network/CommsInterface.hpp index 9e5c9296a8..cf4989091e 100644 --- a/src/helics/network/CommsInterface.hpp +++ b/src/helics/network/CommsInterface.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -211,8 +211,9 @@ namespace CommFactory { }; /** define a new Comm Builder from the builder give a name and build code*/ - void - defineCommBuilder(std::shared_ptr cb, std::string_view commTypeName, int code); + void defineCommBuilder(std::shared_ptr builder, + std::string_view commTypeName, + int code); /** template function to create a builder and link it into the library*/ template diff --git a/src/helics/network/NetworkBroker.hpp b/src/helics/network/NetworkBroker.hpp index 2a18de3090..45810d3a4d 100644 --- a/src/helics/network/NetworkBroker.hpp +++ b/src/helics/network/NetworkBroker.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/network/NetworkBrokerData.cpp b/src/helics/network/NetworkBrokerData.cpp index cac6ca1119..1046e599f7 100644 --- a/src/helics/network/NetworkBrokerData.cpp +++ b/src/helics/network/NetworkBrokerData.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/network/NetworkBrokerData.hpp b/src/helics/network/NetworkBrokerData.hpp index d089c42691..6a8e6771b1 100644 --- a/src/helics/network/NetworkBrokerData.hpp +++ b/src/helics/network/NetworkBrokerData.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/network/NetworkBroker_impl.hpp b/src/helics/network/NetworkBroker_impl.hpp index 8eb4ffc801..b4e0c7338a 100644 --- a/src/helics/network/NetworkBroker_impl.hpp +++ b/src/helics/network/NetworkBroker_impl.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/network/NetworkCommsInterface.cpp b/src/helics/network/NetworkCommsInterface.cpp index 2b19103d00..53a493d3fa 100644 --- a/src/helics/network/NetworkCommsInterface.cpp +++ b/src/helics/network/NetworkCommsInterface.cpp @@ -1,18 +1,18 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause */ #include "NetworkCommsInterface.hpp" -#include "../common/fmt_format.h" #include "NetworkBrokerData.hpp" #include "helics/core/ActionMessage.hpp" #include "helics/helics-config.h" #ifndef HELICS_ENABLE_ENCRYPTION # include #endif +#include #include #include diff --git a/src/helics/network/NetworkCommsInterface.hpp b/src/helics/network/NetworkCommsInterface.hpp index b332ac848c..5ee3606165 100644 --- a/src/helics/network/NetworkCommsInterface.hpp +++ b/src/helics/network/NetworkCommsInterface.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/network/NetworkCore.hpp b/src/helics/network/NetworkCore.hpp index 27ad243ab6..c9a336dc9d 100644 --- a/src/helics/network/NetworkCore.hpp +++ b/src/helics/network/NetworkCore.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/network/NetworkCore_impl.hpp b/src/helics/network/NetworkCore_impl.hpp index 2db75aff52..571bfbf83e 100644 --- a/src/helics/network/NetworkCore_impl.hpp +++ b/src/helics/network/NetworkCore_impl.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/network/inproc/InprocBroker.cpp b/src/helics/network/inproc/InprocBroker.cpp index 01abc82064..fef52a0792 100644 --- a/src/helics/network/inproc/InprocBroker.cpp +++ b/src/helics/network/inproc/InprocBroker.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/network/inproc/InprocBroker.h b/src/helics/network/inproc/InprocBroker.h index fb627aeaae..81ee095ec9 100644 --- a/src/helics/network/inproc/InprocBroker.h +++ b/src/helics/network/inproc/InprocBroker.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/network/inproc/InprocComms.cpp b/src/helics/network/inproc/InprocComms.cpp index 9881507855..f669ca6b41 100644 --- a/src/helics/network/inproc/InprocComms.cpp +++ b/src/helics/network/inproc/InprocComms.cpp @@ -1,12 +1,11 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause */ #include "InprocComms.h" -#include "../../common/fmt_format.h" #include "../../core/ActionMessage.hpp" #include "../../core/BrokerFactory.hpp" #include "../../core/CommonCore.hpp" @@ -14,6 +13,7 @@ SPDX-License-Identifier: BSD-3-Clause #include "../../core/CoreFactory.hpp" #include "../NetworkBrokerData.hpp" +#include #include #include #include diff --git a/src/helics/network/inproc/InprocComms.h b/src/helics/network/inproc/InprocComms.h index edc3700db2..c050a8abfc 100644 --- a/src/helics/network/inproc/InprocComms.h +++ b/src/helics/network/inproc/InprocComms.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/network/inproc/InprocCore.cpp b/src/helics/network/inproc/InprocCore.cpp index e2bb68fe4f..a7a64ec273 100644 --- a/src/helics/network/inproc/InprocCore.cpp +++ b/src/helics/network/inproc/InprocCore.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/network/inproc/InprocCore.h b/src/helics/network/inproc/InprocCore.h index 5b5d4702f8..9c190796fe 100644 --- a/src/helics/network/inproc/InprocCore.h +++ b/src/helics/network/inproc/InprocCore.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/network/ipc/IpcBroker.cpp b/src/helics/network/ipc/IpcBroker.cpp index de631d1187..9a0df15ff9 100644 --- a/src/helics/network/ipc/IpcBroker.cpp +++ b/src/helics/network/ipc/IpcBroker.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/network/ipc/IpcBroker.h b/src/helics/network/ipc/IpcBroker.h index 18d43c66b2..8a72593b77 100644 --- a/src/helics/network/ipc/IpcBroker.h +++ b/src/helics/network/ipc/IpcBroker.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/network/ipc/IpcComms.cpp b/src/helics/network/ipc/IpcComms.cpp index 9220fea646..05c727f54d 100644 --- a/src/helics/network/ipc/IpcComms.cpp +++ b/src/helics/network/ipc/IpcComms.cpp @@ -1,12 +1,11 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause */ #include "IpcComms.h" -#include "../../common/fmt_format.h" #include "../../core/ActionMessage.hpp" #include "../../core/helics_definitions.hpp" #include "IpcQueueHelper.h" @@ -16,6 +15,7 @@ SPDX-License-Identifier: BSD-3-Clause #include #include #include +#include #include #include #include diff --git a/src/helics/network/ipc/IpcComms.h b/src/helics/network/ipc/IpcComms.h index 2f3e3a681f..fff62b43f4 100644 --- a/src/helics/network/ipc/IpcComms.h +++ b/src/helics/network/ipc/IpcComms.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/network/ipc/IpcCore.cpp b/src/helics/network/ipc/IpcCore.cpp index 50ebb329e4..2c5adadf46 100644 --- a/src/helics/network/ipc/IpcCore.cpp +++ b/src/helics/network/ipc/IpcCore.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/network/ipc/IpcCore.h b/src/helics/network/ipc/IpcCore.h index 8a7a61c4ad..991181b788 100644 --- a/src/helics/network/ipc/IpcCore.h +++ b/src/helics/network/ipc/IpcCore.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/network/ipc/IpcQueueHelper.cpp b/src/helics/network/ipc/IpcQueueHelper.cpp index bce423d52d..235ffb5f7c 100644 --- a/src/helics/network/ipc/IpcQueueHelper.cpp +++ b/src/helics/network/ipc/IpcQueueHelper.cpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/network/ipc/IpcQueueHelper.h b/src/helics/network/ipc/IpcQueueHelper.h index b22704bebc..09b18a8754 100644 --- a/src/helics/network/ipc/IpcQueueHelper.h +++ b/src/helics/network/ipc/IpcQueueHelper.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/network/loadCores.cpp b/src/helics/network/loadCores.cpp index 4ebeb9d16b..1e43bbda44 100644 --- a/src/helics/network/loadCores.cpp +++ b/src/helics/network/loadCores.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/network/loadCores.hpp b/src/helics/network/loadCores.hpp index 586c1e6470..a755f77e59 100644 --- a/src/helics/network/loadCores.hpp +++ b/src/helics/network/loadCores.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/network/mpi/MpiBroker.cpp b/src/helics/network/mpi/MpiBroker.cpp index 32caa37515..ce59604cdc 100644 --- a/src/helics/network/mpi/MpiBroker.cpp +++ b/src/helics/network/mpi/MpiBroker.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/network/mpi/MpiComms.cpp b/src/helics/network/mpi/MpiComms.cpp index c57366bdfd..2ec9dddd68 100644 --- a/src/helics/network/mpi/MpiComms.cpp +++ b/src/helics/network/mpi/MpiComms.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/network/mpi/MpiComms.h b/src/helics/network/mpi/MpiComms.h index 96c566541b..4769c2550f 100644 --- a/src/helics/network/mpi/MpiComms.h +++ b/src/helics/network/mpi/MpiComms.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/network/mpi/MpiCore.cpp b/src/helics/network/mpi/MpiCore.cpp index 0b2f11dd86..e074a7708c 100644 --- a/src/helics/network/mpi/MpiCore.cpp +++ b/src/helics/network/mpi/MpiCore.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/network/mpi/MpiCore.h b/src/helics/network/mpi/MpiCore.h index 377381a244..e7fadab58f 100644 --- a/src/helics/network/mpi/MpiCore.h +++ b/src/helics/network/mpi/MpiCore.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/network/mpi/MpiService.cpp b/src/helics/network/mpi/MpiService.cpp index 523d244c47..92d8e71dec 100644 --- a/src/helics/network/mpi/MpiService.cpp +++ b/src/helics/network/mpi/MpiService.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/network/mpi/MpiService.h b/src/helics/network/mpi/MpiService.h index 09660b21b1..5bc6614432 100644 --- a/src/helics/network/mpi/MpiService.h +++ b/src/helics/network/mpi/MpiService.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/network/networkDefaults.cpp b/src/helics/network/networkDefaults.cpp index 5c86e5534c..6226871597 100644 --- a/src/helics/network/networkDefaults.cpp +++ b/src/helics/network/networkDefaults.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/network/networkDefaults.hpp b/src/helics/network/networkDefaults.hpp index 5645538dc2..208577a30a 100644 --- a/src/helics/network/networkDefaults.hpp +++ b/src/helics/network/networkDefaults.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/network/tcp/TcpBroker.cpp b/src/helics/network/tcp/TcpBroker.cpp index 8c12ee14b5..38842dae57 100644 --- a/src/helics/network/tcp/TcpBroker.cpp +++ b/src/helics/network/tcp/TcpBroker.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/network/tcp/TcpBroker.h b/src/helics/network/tcp/TcpBroker.h index 77fa6718fb..0e70e6d478 100644 --- a/src/helics/network/tcp/TcpBroker.h +++ b/src/helics/network/tcp/TcpBroker.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/network/tcp/TcpComms.cpp b/src/helics/network/tcp/TcpComms.cpp index becf48c43e..64a1154ed3 100644 --- a/src/helics/network/tcp/TcpComms.cpp +++ b/src/helics/network/tcp/TcpComms.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/network/tcp/TcpComms.h b/src/helics/network/tcp/TcpComms.h index b751efee7a..ededbb659d 100644 --- a/src/helics/network/tcp/TcpComms.h +++ b/src/helics/network/tcp/TcpComms.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/network/tcp/TcpCommsCommon.cpp b/src/helics/network/tcp/TcpCommsCommon.cpp index 22dab92728..df04f01222 100644 --- a/src/helics/network/tcp/TcpCommsCommon.cpp +++ b/src/helics/network/tcp/TcpCommsCommon.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/network/tcp/TcpCommsCommon.h b/src/helics/network/tcp/TcpCommsCommon.h index 741ea07c60..81f777c1a7 100644 --- a/src/helics/network/tcp/TcpCommsCommon.h +++ b/src/helics/network/tcp/TcpCommsCommon.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/network/tcp/TcpCommsSS.cpp b/src/helics/network/tcp/TcpCommsSS.cpp index fbe726568c..4773190077 100644 --- a/src/helics/network/tcp/TcpCommsSS.cpp +++ b/src/helics/network/tcp/TcpCommsSS.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/network/tcp/TcpCommsSS.h b/src/helics/network/tcp/TcpCommsSS.h index a99e009acd..9fcfa54f34 100644 --- a/src/helics/network/tcp/TcpCommsSS.h +++ b/src/helics/network/tcp/TcpCommsSS.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/network/tcp/TcpCore.cpp b/src/helics/network/tcp/TcpCore.cpp index faaba872ea..466de4c979 100644 --- a/src/helics/network/tcp/TcpCore.cpp +++ b/src/helics/network/tcp/TcpCore.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/network/tcp/TcpCore.h b/src/helics/network/tcp/TcpCore.h index 1ca0ff4398..050b4857bb 100644 --- a/src/helics/network/tcp/TcpCore.h +++ b/src/helics/network/tcp/TcpCore.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/network/test/TestBroker.cpp b/src/helics/network/test/TestBroker.cpp index 9b256c0c61..b9e0c7df55 100644 --- a/src/helics/network/test/TestBroker.cpp +++ b/src/helics/network/test/TestBroker.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/network/test/TestBroker.h b/src/helics/network/test/TestBroker.h index 55549b0ebd..76f2fbb1a7 100644 --- a/src/helics/network/test/TestBroker.h +++ b/src/helics/network/test/TestBroker.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/network/test/TestComms.cpp b/src/helics/network/test/TestComms.cpp index e21798c283..5f853ac27c 100644 --- a/src/helics/network/test/TestComms.cpp +++ b/src/helics/network/test/TestComms.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/network/test/TestComms.h b/src/helics/network/test/TestComms.h index 4cd9b9c219..ed0cd90225 100644 --- a/src/helics/network/test/TestComms.h +++ b/src/helics/network/test/TestComms.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/network/test/TestCore.cpp b/src/helics/network/test/TestCore.cpp index 49649846e3..b75764af94 100644 --- a/src/helics/network/test/TestCore.cpp +++ b/src/helics/network/test/TestCore.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/network/test/TestCore.h b/src/helics/network/test/TestCore.h index 7e1be747f7..b6ff6eb54f 100644 --- a/src/helics/network/test/TestCore.h +++ b/src/helics/network/test/TestCore.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/network/udp/UdpBroker.cpp b/src/helics/network/udp/UdpBroker.cpp index 59ecaa4930..d872f24c7e 100644 --- a/src/helics/network/udp/UdpBroker.cpp +++ b/src/helics/network/udp/UdpBroker.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/network/udp/UdpBroker.h b/src/helics/network/udp/UdpBroker.h index b5e8b47e4e..66eb0f096d 100644 --- a/src/helics/network/udp/UdpBroker.h +++ b/src/helics/network/udp/UdpBroker.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/network/udp/UdpComms.cpp b/src/helics/network/udp/UdpComms.cpp index f1e0bd94a9..761bdd4259 100644 --- a/src/helics/network/udp/UdpComms.cpp +++ b/src/helics/network/udp/UdpComms.cpp @@ -1,18 +1,18 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause */ #include "UdpComms.h" -#include "../../common/fmt_format.h" #include "../../core/ActionMessage.hpp" #include "../NetworkBrokerData.hpp" #include "../networkDefaults.hpp" #include "gmlc/networking/AsioContextManager.h" #include +#include #include #include #include diff --git a/src/helics/network/udp/UdpComms.h b/src/helics/network/udp/UdpComms.h index 406cfe9cb5..a9a29b259d 100644 --- a/src/helics/network/udp/UdpComms.h +++ b/src/helics/network/udp/UdpComms.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/network/udp/UdpCore.cpp b/src/helics/network/udp/UdpCore.cpp index ff0c4b4e70..4313aec633 100644 --- a/src/helics/network/udp/UdpCore.cpp +++ b/src/helics/network/udp/UdpCore.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/network/udp/UdpCore.h b/src/helics/network/udp/UdpCore.h index 14242408a2..f5966492ad 100644 --- a/src/helics/network/udp/UdpCore.h +++ b/src/helics/network/udp/UdpCore.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/network/zmq/ZmqBroker.cpp b/src/helics/network/zmq/ZmqBroker.cpp index a9b21a5c36..43e873900e 100644 --- a/src/helics/network/zmq/ZmqBroker.cpp +++ b/src/helics/network/zmq/ZmqBroker.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/network/zmq/ZmqBroker.h b/src/helics/network/zmq/ZmqBroker.h index 79c15ae273..8d4a3b7fd6 100644 --- a/src/helics/network/zmq/ZmqBroker.h +++ b/src/helics/network/zmq/ZmqBroker.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/network/zmq/ZmqComms.cpp b/src/helics/network/zmq/ZmqComms.cpp index 3cff984e1c..8623209184 100644 --- a/src/helics/network/zmq/ZmqComms.cpp +++ b/src/helics/network/zmq/ZmqComms.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/network/zmq/ZmqComms.h b/src/helics/network/zmq/ZmqComms.h index ef290dd862..774fc64260 100644 --- a/src/helics/network/zmq/ZmqComms.h +++ b/src/helics/network/zmq/ZmqComms.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/network/zmq/ZmqCommsCommon.cpp b/src/helics/network/zmq/ZmqCommsCommon.cpp index 1487f3c395..86d8dbdf59 100644 --- a/src/helics/network/zmq/ZmqCommsCommon.cpp +++ b/src/helics/network/zmq/ZmqCommsCommon.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/network/zmq/ZmqCommsCommon.h b/src/helics/network/zmq/ZmqCommsCommon.h index bc1b3f81d7..d5f3320181 100644 --- a/src/helics/network/zmq/ZmqCommsCommon.h +++ b/src/helics/network/zmq/ZmqCommsCommon.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/network/zmq/ZmqCommsSS.cpp b/src/helics/network/zmq/ZmqCommsSS.cpp index 3bf21e9054..a29ca81974 100644 --- a/src/helics/network/zmq/ZmqCommsSS.cpp +++ b/src/helics/network/zmq/ZmqCommsSS.cpp @@ -1,5 +1,5 @@ /* - Copyright (c) 2017-2023, + Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/network/zmq/ZmqCommsSS.h b/src/helics/network/zmq/ZmqCommsSS.h index 9b67ee83f3..8084a421a7 100644 --- a/src/helics/network/zmq/ZmqCommsSS.h +++ b/src/helics/network/zmq/ZmqCommsSS.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/network/zmq/ZmqContextManager.cpp b/src/helics/network/zmq/ZmqContextManager.cpp index fcb90a7d10..e2656be1ae 100644 --- a/src/helics/network/zmq/ZmqContextManager.cpp +++ b/src/helics/network/zmq/ZmqContextManager.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/network/zmq/ZmqContextManager.h b/src/helics/network/zmq/ZmqContextManager.h index d4af480002..8d2533befe 100644 --- a/src/helics/network/zmq/ZmqContextManager.h +++ b/src/helics/network/zmq/ZmqContextManager.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/network/zmq/ZmqCore.cpp b/src/helics/network/zmq/ZmqCore.cpp index 6091f4befb..a979a0f4d6 100644 --- a/src/helics/network/zmq/ZmqCore.cpp +++ b/src/helics/network/zmq/ZmqCore.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/network/zmq/ZmqCore.h b/src/helics/network/zmq/ZmqCore.h index 8e4f4b1e0a..6674ea9e7e 100644 --- a/src/helics/network/zmq/ZmqCore.h +++ b/src/helics/network/zmq/ZmqCore.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/network/zmq/ZmqHelper.cpp b/src/helics/network/zmq/ZmqHelper.cpp index 1fc783f286..383da19e7b 100644 --- a/src/helics/network/zmq/ZmqHelper.cpp +++ b/src/helics/network/zmq/ZmqHelper.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/network/zmq/ZmqHelper.h b/src/helics/network/zmq/ZmqHelper.h index b9733e0103..03b4ea5527 100644 --- a/src/helics/network/zmq/ZmqHelper.h +++ b/src/helics/network/zmq/ZmqHelper.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/network/zmq/ZmqRequestSets.cpp b/src/helics/network/zmq/ZmqRequestSets.cpp index df8f788e6b..df8c896670 100644 --- a/src/helics/network/zmq/ZmqRequestSets.cpp +++ b/src/helics/network/zmq/ZmqRequestSets.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/network/zmq/ZmqRequestSets.h b/src/helics/network/zmq/ZmqRequestSets.h index fc12071cab..02d03a161c 100644 --- a/src/helics/network/zmq/ZmqRequestSets.h +++ b/src/helics/network/zmq/ZmqRequestSets.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/shared_api_library/.clang-tidy b/src/helics/shared_api_library/.clang-tidy index 839df9e1f0..69bcd3272c 100644 --- a/src/helics/shared_api_library/.clang-tidy +++ b/src/helics/shared_api_library/.clang-tidy @@ -47,6 +47,7 @@ WarningsAsErrors: " clang-analyzer-*, bugprone-*, -bugprone-narrowing-conversions, + -bugprone-easily-swappable-parameters, misc-*, -misc-non-private-member-variables-in-classes, portability-*, @@ -299,7 +300,7 @@ CheckOptions: - key: readability-identifier-naming.MethodSuffix value: "" - key: readability-identifier-naming.NamespaceCase - value: lowercase + value: lower_case - key: readability-identifier-naming.NamespacePrefix value: "" - key: readability-identifier-naming.NamespaceSuffix diff --git a/src/helics/shared_api_library/CMakeLists.txt b/src/helics/shared_api_library/CMakeLists.txt index a9a453063b..62979387dd 100644 --- a/src/helics/shared_api_library/CMakeLists.txt +++ b/src/helics/shared_api_library/CMakeLists.txt @@ -1,5 +1,5 @@ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Copyright (c) 2017-2023, Battelle Memorial Institute; Lawrence Livermore +# Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore # National Security, LLC; Alliance for Sustainable Energy, LLC. # See the top-level NOTICE for additional details. # All rights reserved. diff --git a/src/helics/shared_api_library/FederateExport.cpp b/src/helics/shared_api_library/FederateExport.cpp index 09ffc4bba7..5e40c443d5 100644 --- a/src/helics/shared_api_library/FederateExport.cpp +++ b/src/helics/shared_api_library/FederateExport.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -168,23 +168,23 @@ static constexpr int FederateInfoValidationIdentifier = 0x6bfb'bce1; HelicsFederateInfo helicsCreateFederateInfo() { - auto* fi = new helics::FederateInfo; - fi->uniqueKey = FederateInfoValidationIdentifier; - return reinterpret_cast(fi); + auto* fedInfo = new helics::FederateInfo; + fedInfo->uniqueKey = FederateInfoValidationIdentifier; + return reinterpret_cast(fedInfo); } static constexpr const char* invalidFedInfoString = "helics Federate info object was not valid"; -static helics::FederateInfo* getFedInfo(HelicsFederateInfo fi, HelicsError* err) +static helics::FederateInfo* getFedInfo(HelicsFederateInfo fedInfo, HelicsError* err) { if ((err != nullptr) && (err->error_code != 0)) { return nullptr; } - if (fi == nullptr) { + if (fedInfo == nullptr) { assignError(err, HELICS_ERROR_INVALID_OBJECT, invalidFedInfoString); return nullptr; } - auto* ptr = reinterpret_cast(fi); + auto* ptr = reinterpret_cast(fedInfo); if (ptr->uniqueKey != FederateInfoValidationIdentifier) { assignError(err, HELICS_ERROR_INVALID_OBJECT, invalidFedInfoString); return nullptr; @@ -192,9 +192,9 @@ static helics::FederateInfo* getFedInfo(HelicsFederateInfo fi, HelicsError* err) return ptr; } -HelicsFederateInfo helicsFederateInfoClone(HelicsFederateInfo fi, HelicsError* err) +HelicsFederateInfo helicsFederateInfoClone(HelicsFederateInfo fedInfo, HelicsError* err) { - auto* info = getFedInfo(fi, err); + auto* info = getFedInfo(fedInfo, err); if (info == nullptr) { return nullptr; } @@ -202,9 +202,9 @@ HelicsFederateInfo helicsFederateInfoClone(HelicsFederateInfo fi, HelicsError* e return reinterpret_cast(fi_new); } -void helicsFederateInfoFree(HelicsFederateInfo fi) +void helicsFederateInfoFree(HelicsFederateInfo fedInfo) { - auto* info = getFedInfo(fi, nullptr); + auto* info = getFedInfo(fedInfo, nullptr); if (info == nullptr) { // fprintf(stderr, "The HelicsFederateInfo object is not valid\n"); return; @@ -213,9 +213,9 @@ void helicsFederateInfoFree(HelicsFederateInfo fi) delete info; } -void helicsFederateInfoLoadFromArgs(HelicsFederateInfo fi, int argc, const char* const* argv, HelicsError* err) +void helicsFederateInfoLoadFromArgs(HelicsFederateInfo fedInfo, int argc, const char* const* argv, HelicsError* err) { - auto* info = getFedInfo(fi, err); + auto* info = getFedInfo(fedInfo, err); if (info == nullptr) { return; } @@ -232,9 +232,9 @@ void helicsFederateInfoLoadFromArgs(HelicsFederateInfo fi, int argc, const char* } } -void helicsFederateInfoLoadFromString(HelicsFederateInfo fi, const char* args, HelicsError* err) +void helicsFederateInfoLoadFromString(HelicsFederateInfo fedInfo, const char* args, HelicsError* err) { - auto* info = getFedInfo(fi, err); + auto* info = getFedInfo(fedInfo, err); if (info == nullptr) { return; } @@ -246,9 +246,9 @@ void helicsFederateInfoLoadFromString(HelicsFederateInfo fi, const char* args, H } } -void helicsFederateInfoSetCoreName(HelicsFederateInfo fi, const char* corename, HelicsError* err) +void helicsFederateInfoSetCoreName(HelicsFederateInfo fedInfo, const char* corename, HelicsError* err) { - auto* info = getFedInfo(fi, err); + auto* info = getFedInfo(fedInfo, err); if (info == nullptr) { return; } @@ -260,9 +260,9 @@ void helicsFederateInfoSetCoreName(HelicsFederateInfo fi, const char* corename, } } -void helicsFederateInfoSetCoreInitString(HelicsFederateInfo fi, const char* coreinit, HelicsError* err) +void helicsFederateInfoSetCoreInitString(HelicsFederateInfo fedInfo, const char* coreinit, HelicsError* err) { - auto* info = getFedInfo(fi, err); + auto* info = getFedInfo(fedInfo, err); if (info == nullptr) { return; } @@ -274,9 +274,9 @@ void helicsFederateInfoSetCoreInitString(HelicsFederateInfo fi, const char* core } } -void helicsFederateInfoSetBrokerInitString(HelicsFederateInfo fi, const char* brokerinit, HelicsError* err) +void helicsFederateInfoSetBrokerInitString(HelicsFederateInfo fedInfo, const char* brokerinit, HelicsError* err) { - auto* info = getFedInfo(fi, err); + auto* info = getFedInfo(fedInfo, err); if (info == nullptr) { return; } @@ -288,18 +288,18 @@ void helicsFederateInfoSetBrokerInitString(HelicsFederateInfo fi, const char* br } } -void helicsFederateInfoSetCoreType(HelicsFederateInfo fi, int coretype, HelicsError* err) +void helicsFederateInfoSetCoreType(HelicsFederateInfo fedInfo, int coretype, HelicsError* err) { - auto* info = getFedInfo(fi, err); + auto* info = getFedInfo(fedInfo, err); if (info == nullptr) { return; } info->coreType = static_cast(coretype); } -void helicsFederateInfoSetCoreTypeFromString(HelicsFederateInfo fi, const char* coretype, HelicsError* err) +void helicsFederateInfoSetCoreTypeFromString(HelicsFederateInfo fedInfo, const char* coretype, HelicsError* err) { - auto* info = getFedInfo(fi, err); + auto* info = getFedInfo(fedInfo, err); if (info == nullptr) { return; } @@ -318,9 +318,9 @@ void helicsFederateInfoSetCoreTypeFromString(HelicsFederateInfo fi, const char* info->coreType = ctype; } -void helicsFederateInfoSetBroker(HelicsFederateInfo fi, const char* broker, HelicsError* err) +void helicsFederateInfoSetBroker(HelicsFederateInfo fedInfo, const char* broker, HelicsError* err) { - auto* info = getFedInfo(fi, err); + auto* info = getFedInfo(fedInfo, err); if (info == nullptr) { return; } @@ -332,9 +332,9 @@ void helicsFederateInfoSetBroker(HelicsFederateInfo fi, const char* broker, Heli } } -void helicsFederateInfoSetBrokerKey(HelicsFederateInfo fi, const char* brokerkey, HelicsError* err) +void helicsFederateInfoSetBrokerKey(HelicsFederateInfo fedInfo, const char* brokerkey, HelicsError* err) { - auto* info = getFedInfo(fi, err); + auto* info = getFedInfo(fedInfo, err); if (info == nullptr) { return; } @@ -346,18 +346,18 @@ void helicsFederateInfoSetBrokerKey(HelicsFederateInfo fi, const char* brokerkey } } -void helicsFederateInfoSetBrokerPort(HelicsFederateInfo fi, int brokerPort, HelicsError* err) +void helicsFederateInfoSetBrokerPort(HelicsFederateInfo fedInfo, int brokerPort, HelicsError* err) { - auto* info = getFedInfo(fi, err); + auto* info = getFedInfo(fedInfo, err); if (info == nullptr) { return; } info->brokerPort = brokerPort; } -void helicsFederateInfoSetLocalPort(HelicsFederateInfo fi, const char* localPort, HelicsError* err) +void helicsFederateInfoSetLocalPort(HelicsFederateInfo fedInfo, const char* localPort, HelicsError* err) { - auto* info = getFedInfo(fi, err); + auto* info = getFedInfo(fedInfo, err); if (info == nullptr) { return; } @@ -404,9 +404,9 @@ int helicsGetDataType(const char* val) return static_cast(helics::getTypeFromString(val)); } -void helicsFederateInfoSetFlagOption(HelicsFederateInfo fi, int flag, HelicsBool value, HelicsError* err) +void helicsFederateInfoSetFlagOption(HelicsFederateInfo fedInfo, int flag, HelicsBool value, HelicsError* err) { - auto* info = getFedInfo(fi, err); + auto* info = getFedInfo(fedInfo, err); if (info == nullptr) { return; } @@ -427,27 +427,27 @@ void helicsFederateInfoSetFlagOption(HelicsFederateInfo fi, int flag, HelicsBool info->setFlagOption(flag, (value != HELICS_FALSE)); } -void helicsFederateInfoSetTimeProperty(HelicsFederateInfo fi, int timeProperty, HelicsTime propertyValue, HelicsError* err) +void helicsFederateInfoSetTimeProperty(HelicsFederateInfo fedInfo, int timeProperty, HelicsTime propertyValue, HelicsError* err) { - auto* info = getFedInfo(fi, err); + auto* info = getFedInfo(fedInfo, err); if (info == nullptr) { return; } info->setProperty(timeProperty, propertyValue); } -void helicsFederateInfoSetSeparator(HelicsFederateInfo fi, char separator, HelicsError* err) +void helicsFederateInfoSetSeparator(HelicsFederateInfo fedInfo, char separator, HelicsError* err) { - auto* info = getFedInfo(fi, err); + auto* info = getFedInfo(fedInfo, err); if (info == nullptr) { return; } info->separator = separator; } -void helicsFederateInfoSetIntegerProperty(HelicsFederateInfo fi, int integerProperty, int propertyValue, HelicsError* err) +void helicsFederateInfoSetIntegerProperty(HelicsFederateInfo fedInfo, int integerProperty, int propertyValue, HelicsError* err) { - auto* info = getFedInfo(fi, err); + auto* info = getFedInfo(fedInfo, err); if (info == nullptr) { return; } @@ -455,16 +455,16 @@ void helicsFederateInfoSetIntegerProperty(HelicsFederateInfo fi, int integerProp } /* Creation and destruction of Federates */ -HelicsFederate helicsCreateValueFederate(const char* fedName, HelicsFederateInfo fi, HelicsError* err) +HelicsFederate helicsCreateValueFederate(const char* fedName, HelicsFederateInfo fedInfo, HelicsError* err) { HELICS_ERROR_CHECK(err, nullptr); auto FedI = std::make_unique(); try { - if (fi == nullptr) { + if (fedInfo == nullptr) { FedI->fedptr = std::make_shared(AS_STRING(fedName), helics::FederateInfo()); } else { - auto* info = getFedInfo(fi, err); + auto* info = getFedInfo(fedInfo, err); if (info == nullptr) { return nullptr; } @@ -501,15 +501,15 @@ HelicsFederate helicsCreateValueFederateFromConfig(const char* configFile, Helic } /* Creation and destruction of Federates */ -HelicsFederate helicsCreateMessageFederate(const char* fedName, HelicsFederateInfo fi, HelicsError* err) +HelicsFederate helicsCreateMessageFederate(const char* fedName, HelicsFederateInfo fedInfo, HelicsError* err) { HELICS_ERROR_CHECK(err, nullptr); auto FedI = std::make_unique(); try { - if (fi == nullptr) { + if (fedInfo == nullptr) { FedI->fedptr = std::make_shared(AS_STRING(fedName), helics::FederateInfo()); } else { - auto* info = getFedInfo(fi, err); + auto* info = getFedInfo(fedInfo, err); if (info == nullptr) { return nullptr; } @@ -547,15 +547,15 @@ HelicsFederate helicsCreateMessageFederateFromConfig(const char* configFile, Hel } /* Creation and destruction of Federates */ -HelicsFederate helicsCreateCombinationFederate(const char* fedName, HelicsFederateInfo fi, HelicsError* err) +HelicsFederate helicsCreateCombinationFederate(const char* fedName, HelicsFederateInfo fedInfo, HelicsError* err) { HELICS_ERROR_CHECK(err, nullptr); auto FedI = std::make_unique(); try { - if (fi == nullptr) { + if (fedInfo == nullptr) { FedI->fedptr = std::make_shared(AS_STRING(fedName), helics::FederateInfo()); } else { - auto* info = getFedInfo(fi, err); + auto* info = getFedInfo(fedInfo, err); if (info == nullptr) { return nullptr; } @@ -593,15 +593,15 @@ HelicsFederate helicsCreateCombinationFederateFromConfig(const char* configFile, } /* Creation and destruction of Federates */ -HelicsFederate helicsCreateCallbackFederate(const char* fedName, HelicsFederateInfo fi, HelicsError* err) +HelicsFederate helicsCreateCallbackFederate(const char* fedName, HelicsFederateInfo fedInfo, HelicsError* err) { HELICS_ERROR_CHECK(err, nullptr); auto FedI = std::make_unique(); try { - if (fi == nullptr) { + if (fedInfo == nullptr) { FedI->fedptr = std::make_shared(AS_STRING(fedName), helics::FederateInfo()); } else { - auto* info = getFedInfo(fi, err); + auto* info = getFedInfo(fedInfo, err); if (info == nullptr) { return nullptr; } @@ -698,7 +698,7 @@ void helicsFederateProtect(const char* fedName, HelicsError* err) static constexpr const char* unrecognizedFederate = "Federate was not found"; void helicsFederateUnProtect(const char* fedName, HelicsError* err) { - bool result = getMasterHolder()->removeFed(fedName, fedPreservationIdentifier); + const bool result = getMasterHolder()->removeFed(fedName, fedPreservationIdentifier); if (!result) { if (!(getMasterHolder()->findFed(fedName) != nullptr)) { if (err != nullptr) { @@ -1391,7 +1391,7 @@ void helicsFederateErrorHandlerCallback(HelicsFederate fed, } else { fedptr->setErrorHandlerCallback([errorHandler, userdata](int errorCode, std::string_view errorMessage) { // string is to ensure we have a null terminator - std::string eMessage(errorMessage); + const std::string eMessage(errorMessage); errorHandler(errorCode, eMessage.c_str(), userdata); }); } @@ -1463,8 +1463,8 @@ void helicsCallbackFederateNextTimeIterativeCallback( fedptr->clearNextTimeCallback(); } else { fedptr->setNextTimeIterativeCallback([timeUpdate, userdata](helics::iteration_time time) { - HelicsIterationRequest request; - helics::Time newTime = timeUpdate(time.grantedTime, getIterationStatus(time.state), &request, userdata); + HelicsIterationRequest request{HELICS_ITERATION_REQUEST_ERROR}; + const helics::Time newTime = timeUpdate(time.grantedTime, getIterationStatus(time.state), &request, userdata); return std::make_pair(newTime, getIterationRequest(request)); }); } @@ -1559,9 +1559,9 @@ HelicsTime helicsFederateGetTimeProperty(HelicsFederate fed, int timeProperty, H return HELICS_TIME_INVALID; } try { - auto T = fedObj->getTimeProperty(timeProperty); + auto timeprop = fedObj->getTimeProperty(timeProperty); - return (T < helics::Time::maxVal()) ? static_cast(T) : HELICS_TIME_MAXTIME; + return (timeprop < helics::Time::maxVal()) ? static_cast(timeprop) : HELICS_TIME_MAXTIME; } // LCOV_EXCL_START catch (...) { @@ -1578,7 +1578,7 @@ HelicsBool helicsFederateGetFlagOption(HelicsFederate fed, int flag, HelicsError return HELICS_FALSE; } try { - bool res = fedObj->getFlagOption(flag); + const bool res = fedObj->getFlagOption(flag); return (res) ? HELICS_TRUE : HELICS_FALSE; } // LCOV_EXCL_START @@ -1621,8 +1621,8 @@ HelicsTime helicsFederateGetCurrentTime(HelicsFederate fed, HelicsError* err) if (fedObj == nullptr) { return HELICS_TIME_INVALID; } - auto T = fedObj->getCurrentTime(); - return (T < helics::Time::maxVal()) ? static_cast(T) : HELICS_TIME_MAXTIME; + auto time = fedObj->getCurrentTime(); + return (time < helics::Time::maxVal()) ? static_cast(time) : HELICS_TIME_MAXTIME; } static constexpr char invalidGlobalString[] = "Global name cannot be null"; @@ -1744,11 +1744,11 @@ void helicsFederateSetLogFile(HelicsFederate fed, const char* logFile, HelicsErr if (fedObj == nullptr) { return; } - const auto& cr = fedObj->getCorePointer(); + const auto& corePtr = fedObj->getCorePointer(); try { - if (cr) { - cr->setLogFile(AS_STRING(logFile)); + if (corePtr) { + corePtr->setLogFile(AS_STRING(logFile)); // LCOV_EXCL_START } else { // this can theoretically happen but it would be pretty odd assignError(err, HELICS_ERROR_INVALID_FUNCTION_CALL, invalidFederateCore); diff --git a/src/helics/shared_api_library/MessageFederate.h b/src/helics/shared_api_library/MessageFederate.h index 3c33132618..03200bd4e0 100644 --- a/src/helics/shared_api_library/MessageFederate.h +++ b/src/helics/shared_api_library/MessageFederate.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -602,6 +602,15 @@ HELICS_EXPORT void helicsMessageGetBytes(HelicsMessage message, void* data, int */ HELICS_EXPORT void* helicsMessageGetBytesPointer(HelicsMessage message); +/** + * Get a data buffer to the message object + * + * @param message A message object to get the dataBuffer for + * + * @return A HelicsDataBuffer object to the data in a message. Modifying the buffer will directly modify the message contents. + */ +HELICS_EXPORT HelicsDataBuffer helicsMessageDataBuffer(HelicsMessage message, HelicsError* err); + /** * A check if the message contains a valid payload. * @@ -737,6 +746,16 @@ HELICS_EXPORT void helicsMessageSetString(HelicsMessage message, const char* dat */ HELICS_EXPORT void helicsMessageSetData(HelicsMessage message, const void* data, int inputDataLength, HelicsError* err); +/** + * Set the data payload of a message from a HelicsDataBuffer Object + * + * @param message The message object in question. + * @param data the dataBuffer containing the appropriate data, if null will clear the message payload + * + * @param[in,out] err An error object to fill out in case of an error. + */ +HELICS_EXPORT void helicsMessageSetDataBuffer(HelicsMessage message, HelicsDataBuffer data, HelicsError* err); + /** * Append data to the payload. * diff --git a/src/helics/shared_api_library/MessageFederateExport.cpp b/src/helics/shared_api_library/MessageFederateExport.cpp index f2e630b207..a50278f0c2 100644 --- a/src/helics/shared_api_library/MessageFederateExport.cpp +++ b/src/helics/shared_api_library/MessageFederateExport.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -12,6 +12,7 @@ SPDX-License-Identifier: BSD-3-Clause #include "helicsCore.h" #include "internal/api_objects.h" +#include #include #include #include @@ -20,15 +21,41 @@ SPDX-License-Identifier: BSD-3-Clause // random integer for validation purposes of endpoints static constexpr int EndpointValidationIdentifier = 0xB453'94C2; +static auto endpointSearch = [](const helics::InterfaceHandle& hnd, const auto& testEndpoint) { + return hnd < testEndpoint->endPtr->getHandle(); +}; + static inline HelicsEndpoint addEndpoint(HelicsFederate fed, std::unique_ptr ept) { auto* fedObj = reinterpret_cast(fed); ept->valid = EndpointValidationIdentifier; + ept->fed = fedObj; HelicsEndpoint hept = ept.get(); - fedObj->epts.push_back(std::move(ept)); + + if (fedObj->epts.empty() || ept->endPtr->getHandle() > fedObj->epts.back()->endPtr->getHandle()) { + fedObj->epts.push_back(std::move(ept)); + } else { + auto ind = std::upper_bound(fedObj->epts.begin(), fedObj->epts.end(), ept->endPtr->getHandle(), endpointSearch); + fedObj->epts.insert(ind, std::move(ept)); + } return hept; } +static HelicsEndpoint findOrCreateEndpoint(HelicsFederate fed, helics::Endpoint& endp) +{ + auto* fedObj = reinterpret_cast(fed); + const auto handle = endp.getHandle(); + auto ind = std::upper_bound(fedObj->epts.begin(), fedObj->epts.end(), handle, endpointSearch); + if (ind != fedObj->epts.end() && (*ind)->endPtr->getHandle() == handle) { + HelicsEndpoint hend = ind->get(); + return hend; + } + auto end = std::make_unique(); + end->endPtr = &endp; + end->fedptr = getMessageFedSharedPtr(fed, nullptr); + return addEndpoint(fed, std::move(end)); +} + static constexpr char nullcstr[] = ""; static constexpr char invalidEndpoint[] = "The given endpoint does not point to a valid object"; @@ -142,11 +169,7 @@ HelicsEndpoint helicsFederateGetEndpoint(HelicsFederate fed, const char* name, H assignError(err, HELICS_ERROR_INVALID_ARGUMENT, invalidEndName); return nullptr; } - auto end = std::make_unique(); - end->endPtr = &id; - end->fedptr = std::move(fedObj); - end->fed = helics::getFedObject(fed, err); - return addEndpoint(fed, std::move(end)); + return findOrCreateEndpoint(fed, id); } // LCOV_EXCL_START catch (...) { @@ -168,11 +191,7 @@ HelicsEndpoint helicsFederateGetEndpointByIndex(HelicsFederate fed, int index, H assignError(err, HELICS_ERROR_INVALID_ARGUMENT, invalidEndIndex); return nullptr; } - auto end = std::make_unique(); - end->endPtr = &id; - end->fedptr = std::move(fedObj); - end->fed = helics::getFedObject(fed, err); - return addEndpoint(fed, std::move(end)); + return findOrCreateEndpoint(fed, id); } // LCOV_EXCL_START catch (...) { @@ -949,6 +968,15 @@ void* helicsMessageGetBytesPointer(HelicsMessage message) return mess->data.data(); } +HelicsDataBuffer helicsMessageDataBuffer(HelicsMessage message, HelicsError* err) +{ + auto* mess = getMessageObj(message, err); + if (mess == nullptr) { + return nullptr; + } + return message; +} + HelicsBool helicsMessageIsValid(HelicsMessage message) { auto* mess = getMessageObj(message, nullptr); @@ -1083,6 +1111,20 @@ void helicsMessageSetData(HelicsMessage message, const void* data, int inputData mess->data = std::string_view(static_cast(data), inputDataLength); } +void helicsMessageSetDataBuffer(HelicsMessage message, HelicsDataBuffer data, HelicsError* err) +{ + auto* mess = getMessageObj(message, err); + if (mess == nullptr) { + return; + } + auto* ptr = getBuffer(data); + if (ptr == nullptr) { + mess->data.clear(); + return; + } + mess->data = *ptr; +} + void helicsMessageAppendData(HelicsMessage message, const void* data, int inputDataLength, HelicsError* err) { auto* mess = getMessageObj(message, err); diff --git a/src/helics/shared_api_library/MessageFilters.h b/src/helics/shared_api_library/MessageFilters.h index f530949182..902e7d96c9 100644 --- a/src/helics/shared_api_library/MessageFilters.h +++ b/src/helics/shared_api_library/MessageFilters.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/shared_api_library/MessageFiltersExport.cpp b/src/helics/shared_api_library/MessageFiltersExport.cpp index af2f10def4..5bf848829e 100644 --- a/src/helics/shared_api_library/MessageFiltersExport.cpp +++ b/src/helics/shared_api_library/MessageFiltersExport.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -20,6 +20,55 @@ static constexpr char invalidFilterString[] = "The given filter object is not va /** this is a random identifier put in place for validating filters*/ static const int filterValidationIdentifier = 0xEC26'0127; +static auto filterSearch = [](const helics::InterfaceHandle& hnd, const auto& testFilter) { + return hnd < testFilter->filtPtr->getHandle(); +}; + +static inline HelicsFilter federateAddFilter(HelicsFederate fed, std::unique_ptr filt) +{ + auto* fedObj = reinterpret_cast(fed); + filt->valid = filterValidationIdentifier; + HelicsFilter hfilt = filt.get(); + if (fedObj->filters.empty() || filt->filtPtr->getHandle() > fedObj->filters.back()->filtPtr->getHandle()) { + fedObj->filters.push_back(std::move(filt)); + } else { + auto ind = std::upper_bound(fedObj->filters.begin(), fedObj->filters.end(), filt->filtPtr->getHandle(), filterSearch); + fedObj->filters.insert(ind, std::move(filt)); + } + return hfilt; +} + +static HelicsFilter findOrCreateFederateFilter(HelicsFederate fed, helics::Filter& filter) +{ + auto* fedObj = reinterpret_cast(fed); + const auto handle = filter.getHandle(); + auto ind = std::upper_bound(fedObj->filters.begin(), fedObj->filters.end(), handle, filterSearch); + if (ind != fedObj->filters.end() && (*ind)->filtPtr->getHandle() == handle) { + HelicsFilter hfilt = ind->get(); + return hfilt; + } + + auto filt = std::make_unique(); + filt->filtPtr = &filter; + filt->cloning = filter.isCloningFilter(); + filt->fedptr = getFedSharedPtr(fed, nullptr); + return federateAddFilter(fed, std::move(filt)); +} + +/* +static HelicsFilter findCoreFilter(HelicsCore core, helics::InterfaceHandle handle) +{ + auto* coreObj = reinterpret_cast(core); + auto ind=std::upper_bound(coreObj->filters.begin(),coreObj->filters.end(),handle,filterSearch); + if ((*ind)->filtPtr->getHandle() == handle) + { + HelicsFilter hfilt=ind->get(); + return hfilt; + } + return nullptr; +} +*/ + static helics::FilterObject* getFilterObj(HelicsFilter filt, HelicsError* err) { HELICS_ERROR_CHECK(err, nullptr); @@ -35,24 +84,19 @@ static helics::FilterObject* getFilterObj(HelicsFilter filt, HelicsError* err) return fObj; } -// fed is assumed to be valid here -static inline HelicsFilter federateAddFilter(HelicsFederate fed, std::unique_ptr filt) -{ - auto* fedObj = reinterpret_cast(fed); - filt->valid = filterValidationIdentifier; - HelicsFilter ret = filt.get(); - fedObj->filters.push_back(std::move(filt)); - return ret; -} - // core is assumed to be valid here static inline HelicsFilter coreAddFilter(HelicsCore core, std::unique_ptr filt) { auto* coreObj = reinterpret_cast(core); filt->valid = filterValidationIdentifier; - HelicsFilter ret = filt.get(); - coreObj->filters.push_back(std::move(filt)); - return ret; + HelicsFilter hfilt = filt.get(); + if (coreObj->filters.empty() || filt->filtPtr->getHandle() > coreObj->filters.back()->filtPtr->getHandle()) { + coreObj->filters.push_back(std::move(filt)); + } else { + auto ind = std::upper_bound(coreObj->filters.begin(), coreObj->filters.end(), filt->filtPtr->getHandle(), filterSearch); + coreObj->filters.insert(ind, std::move(filt)); + } + return hfilt; } HelicsFilter helicsFederateRegisterFilter(HelicsFederate fed, HelicsFilterTypes type, const char* name, HelicsError* err) @@ -197,11 +241,7 @@ HelicsFilter helicsFederateGetFilter(HelicsFederate fed, const char* name, Helic err->message = invalidFiltName; return nullptr; } - auto filt = std::make_unique(); - filt->filtPtr = &id; - filt->cloning = id.isCloningFilter(); - filt->fedptr = std::move(fedObj); - return federateAddFilter(fed, std::move(filt)); + return findOrCreateFederateFilter(fed, id); } // LCOV_EXCL_START catch (...) { @@ -233,11 +273,7 @@ HelicsFilter helicsFederateGetFilterByIndex(HelicsFederate fed, int index, Helic err->message = invalidFiltIndex; return nullptr; } - auto filt = std::make_unique(); - filt->filtPtr = &id; - filt->fedptr = std::move(fedObj); - filt->cloning = id.isCloningFilter(); - return federateAddFilter(fed, std::move(filt)); + return findOrCreateFederateFilter(fed, id); } // LCOV_EXCL_START catch (...) { diff --git a/src/helics/shared_api_library/TranslatorExport.cpp b/src/helics/shared_api_library/TranslatorExport.cpp index 69128a2f83..69ad614f9f 100644 --- a/src/helics/shared_api_library/TranslatorExport.cpp +++ b/src/helics/shared_api_library/TranslatorExport.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -22,6 +22,54 @@ static constexpr char invalidTranslatorString[] = "The given translator object i /** this is a random identifier for validating translators*/ static const int translatorValidationIdentifier = 0xB37C'352E; +static auto translatorSearch = [](const helics::InterfaceHandle& hnd, const auto& testTranslator) { + return hnd < testTranslator->transPtr->getHandle(); +}; + +// fed is assumed to be valid here +static inline HelicsTranslator federateAddTranslator(HelicsFederate fed, std::unique_ptr trans) +{ + auto* fedObj = reinterpret_cast(fed); + trans->valid = translatorValidationIdentifier; + HelicsTranslator hTrans = trans.get(); + if (fedObj->translators.empty() || trans->transPtr->getHandle() > fedObj->translators.back()->transPtr->getHandle()) { + fedObj->translators.push_back(std::move(trans)); + } else { + auto ind = std::upper_bound(fedObj->translators.begin(), fedObj->translators.end(), trans->transPtr->getHandle(), translatorSearch); + fedObj->translators.insert(ind, std::move(trans)); + } + + return hTrans; +} + +static HelicsTranslator findOrCreateFederateTranslator(HelicsFederate fed, helics::Translator& translator) +{ + auto* fedObj = reinterpret_cast(fed); + const auto handle = translator.getHandle(); + auto ind = std::upper_bound(fedObj->translators.begin(), fedObj->translators.end(), handle, translatorSearch); + if (ind != fedObj->translators.end() && (*ind)->transPtr->getHandle() == handle) { + HelicsTranslator hTrans = ind->get(); + return hTrans; + } + auto trans = std::make_unique(); + trans->transPtr = &translator; + trans->fedptr = getFedSharedPtr(fed, nullptr); + return federateAddTranslator(fed, std::move(trans)); +} + +/* +static HelicsTranslator findOrCreateCoreTranslator(HelicsCore core, helics::InterfaceHandle handle) +{ + auto* coreObj = reinterpret_cast(core); + auto ind = std::upper_bound(coreObj->translators.begin(), coreObj->translators.end(), handle, translatorSearch); + if ((*ind)->transPtr->getHandle() == handle) { + HelicsTranslator hTrans = ind->get(); + return hTrans; + } + return nullptr; +} +*/ + static helics::TranslatorObject* getTranslatorObj(HelicsTranslator trans, HelicsError* err) { HELICS_ERROR_CHECK(err, nullptr); @@ -37,24 +85,21 @@ static helics::TranslatorObject* getTranslatorObj(HelicsTranslator trans, Helics return tObj; } -// fed is assumed to be valid here -static inline HelicsTranslator federateAddTranslator(HelicsFederate fed, std::unique_ptr trans) -{ - auto* fedObj = reinterpret_cast(fed); - trans->valid = translatorValidationIdentifier; - HelicsTranslator ret = trans.get(); - fedObj->translators.push_back(std::move(trans)); - return ret; -} - // core is assumed to be valid here static inline HelicsTranslator coreAddTranslator(HelicsCore core, std::unique_ptr trans) { auto* coreObj = reinterpret_cast(core); trans->valid = translatorValidationIdentifier; - HelicsTranslator ret = trans.get(); - coreObj->translators.push_back(std::move(trans)); - return ret; + HelicsTranslator hTrans = trans.get(); + if (coreObj->translators.empty() || trans->transPtr->getHandle() > coreObj->translators.back()->transPtr->getHandle()) { + coreObj->translators.push_back(std::move(trans)); + } else { + auto ind = + std::upper_bound(coreObj->translators.begin(), coreObj->translators.end(), trans->transPtr->getHandle(), translatorSearch); + coreObj->translators.insert(ind, std::move(trans)); + } + + return hTrans; } HELICS_EXPORT HelicsTranslator helicsFederateRegisterTranslator(HelicsFederate fed, @@ -140,10 +185,7 @@ HelicsTranslator helicsFederateGetTranslator(HelicsFederate fed, const char* nam err->message = invalidTransName; return nullptr; } - auto trans = std::make_unique(); - trans->transPtr = &id; - trans->fedptr = std::move(fedObj); - return federateAddTranslator(fed, std::move(trans)); + return findOrCreateFederateTranslator(fed, id); } // LCOV_EXCL_START catch (...) { @@ -175,10 +217,7 @@ HelicsTranslator helicsFederateGetTranslatorByIndex(HelicsFederate fed, int inde err->message = invalidTransIndex; return nullptr; } - auto trans = std::make_unique(); - trans->transPtr = &id; - trans->fedptr = std::move(fedObj); - return federateAddTranslator(fed, std::move(trans)); + return findOrCreateFederateTranslator(fed, id); } // LCOV_EXCL_START catch (...) { diff --git a/src/helics/shared_api_library/Translators.h b/src/helics/shared_api_library/Translators.h index 49419be39d..ece822bcce 100644 --- a/src/helics/shared_api_library/Translators.h +++ b/src/helics/shared_api_library/Translators.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/shared_api_library/ValueFederate.h b/src/helics/shared_api_library/ValueFederate.h index 9436c86c69..793f8e2e49 100644 --- a/src/helics/shared_api_library/ValueFederate.h +++ b/src/helics/shared_api_library/ValueFederate.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -449,6 +449,17 @@ HELICS_EXPORT void */ HELICS_EXPORT void helicsPublicationPublishNamedPoint(HelicsPublication pub, const char* field, double val, HelicsError* err); +/** +* Publish the contents of a helicsDataBuffer. +* +* @param pub The publication to publish for. +* @param buffer a HelicsDataBuffer object containing the data to publish +* +* @param[in,out] err A pointer to an error object for catching errors. + +*/ +HELICS_EXPORT void helicsPublicationPublishDataBuffer(HelicsPublication pub, HelicsDataBuffer buffer, HelicsError* err); + /** * Add a named input to the list of targets a publication publishes to. * @@ -508,6 +519,16 @@ HELICS_EXPORT int helicsInputGetByteCount(HelicsInput ipt); */ HELICS_EXPORT void helicsInputGetBytes(HelicsInput ipt, void* data, int maxDataLength, int* actualSize, HelicsError* err); +/** + * Get a copy of the raw data in a HelicsDataBuffer + * + * @param inp The input to get the data for. + * + * @param[in,out] err A pointer to an error object for catching errors. + * @return A HelicsDataBuffer object containing the data + */ +HELICS_EXPORT HelicsDataBuffer helicsInputGetDataBuffer(HelicsInput inp, HelicsError* err); + /** * Get the size of a value for an input assuming return as a string. * diff --git a/src/helics/shared_api_library/ValueFederateExport.cpp b/src/helics/shared_api_library/ValueFederateExport.cpp index 9c5b98f158..56aa94cd66 100644 --- a/src/helics/shared_api_library/ValueFederateExport.cpp +++ b/src/helics/shared_api_library/ValueFederateExport.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -7,8 +7,10 @@ SPDX-License-Identifier: BSD-3-Clause #include "../core/core-exceptions.hpp" #include "../helics.hpp" #include "ValueFederate.h" +#include "helicsData.h" #include "internal/api_objects.h" +#include #include #include #include @@ -55,24 +57,69 @@ static helics::PublicationObject* verifyPublication(HelicsPublication pub, Helic return pubObj; } +static auto inputSearch = [](const helics::InterfaceHandle& hnd, const auto& testInput) { return hnd < testInput->inputPtr->getHandle(); }; + static inline HelicsInput addInput(HelicsFederate fed, std::unique_ptr inp) { auto* fedObj = reinterpret_cast(fed); inp->valid = InputValidationIdentifier; HelicsInput hinp = inp.get(); - fedObj->inputs.push_back(std::move(inp)); + if (fedObj->inputs.empty() || inp->inputPtr->getHandle() > fedObj->inputs.back()->inputPtr->getHandle()) { + fedObj->inputs.push_back(std::move(inp)); + } else { + auto ind = std::upper_bound(fedObj->inputs.begin(), fedObj->inputs.end(), inp->inputPtr->getHandle(), inputSearch); + fedObj->inputs.insert(ind, std::move(inp)); + } return hinp; } +static HelicsInput findOrCreateInput(HelicsFederate fed, helics::Input& input) +{ + auto* fedObj = reinterpret_cast(fed); + const auto handle = input.getHandle(); + auto ind = std::upper_bound(fedObj->inputs.begin(), fedObj->inputs.end(), handle, inputSearch); + if (ind != fedObj->inputs.end() && (*ind)->inputPtr->getHandle() == handle) { + HelicsInput hinp = ind->get(); + return hinp; + } + auto inp = std::make_unique(); + inp->inputPtr = &input; + inp->fedptr = getValueFedSharedPtr(fed, nullptr); + return addInput(fed, std::move(inp)); +} + +static auto pubSearch = [](const helics::InterfaceHandle& hnd, const auto& testPub) { return hnd < testPub->pubPtr->getHandle(); }; + static inline HelicsPublication addPublication(HelicsFederate fed, std::unique_ptr pub) { auto* fedObj = reinterpret_cast(fed); pub->valid = PublicationValidationIdentifier; HelicsPublication hpub = pub.get(); - fedObj->pubs.push_back(std::move(pub)); + if (fedObj->pubs.empty() || pub->pubPtr->getHandle() > fedObj->pubs.back()->pubPtr->getHandle()) { + fedObj->pubs.push_back(std::move(pub)); + } else { + auto ind = std::upper_bound(fedObj->pubs.begin(), fedObj->pubs.end(), pub->pubPtr->getHandle(), pubSearch); + fedObj->pubs.insert(ind, std::move(pub)); + } + return hpub; } +static HelicsPublication findOrCreatePublication(HelicsFederate fed, helics::Publication& pub) +{ + auto* fedObj = reinterpret_cast(fed); + const auto handle = pub.getHandle(); + auto ind = std::upper_bound(fedObj->pubs.begin(), fedObj->pubs.end(), handle, pubSearch); + if (ind != fedObj->pubs.end() && (*ind)->pubPtr->getHandle() == handle) { + HelicsPublication hpub = ind->get(); + return hpub; + } + auto pubObj = std::make_unique(); + pubObj->pubPtr = &pub; + pubObj->fedptr = getValueFedSharedPtr(fed, nullptr); + return addPublication(fed, std::move(pubObj)); +} + /* input/pub registration */ HelicsInput helicsFederateRegisterSubscription(HelicsFederate fed, const char* key, const char* units, HelicsError* err) { @@ -342,10 +389,7 @@ HelicsPublication helicsFederateGetPublication(HelicsFederate fed, const char* k assignError(err, HELICS_ERROR_INVALID_ARGUMENT, invalidPubName); return nullptr; } - auto pubObj = std::make_unique(); - pubObj->pubPtr = &pub; - pubObj->fedptr = std::move(fedObj); - return addPublication(fed, std::move(pubObj)); + return findOrCreatePublication(fed, pub); } // LCOV_EXCL_START catch (...) { @@ -362,16 +406,12 @@ HelicsPublication helicsFederateGetPublicationByIndex(HelicsFederate fed, int in return nullptr; } try { - auto& id = fedObj->getPublication(index); - if (!id.isValid()) { + auto& pub = fedObj->getPublication(index); + if (!pub.isValid()) { assignError(err, HELICS_ERROR_INVALID_ARGUMENT, invalidPubIndex); return nullptr; } - auto pub = std::make_unique(); - pub->pubPtr = &id; - - pub->fedptr = std::move(fedObj); - return addPublication(fed, std::move(pub)); + return findOrCreatePublication(fed, pub); } // LCOV_EXCL_START catch (...) { @@ -397,10 +437,7 @@ HelicsInput helicsFederateGetInput(HelicsFederate fed, const char* key, HelicsEr assignError(err, HELICS_ERROR_INVALID_ARGUMENT, invalidInputName); return nullptr; } - auto inp = std::make_unique(); - inp->inputPtr = &id; - inp->fedptr = std::move(fedObj); - return addInput(fed, std::move(inp)); + return findOrCreateInput(fed, id); } // LCOV_EXCL_START catch (...) { @@ -422,10 +459,7 @@ HelicsInput helicsFederateGetInputByIndex(HelicsFederate fed, int index, HelicsE assignError(err, HELICS_ERROR_INVALID_ARGUMENT, invalidInputIndex); return nullptr; } - auto inp = std::make_unique(); - inp->inputPtr = &id; - inp->fedptr = std::move(fedObj); - return addInput(fed, std::move(inp)); + return findOrCreateInput(fed, id); } // LCOV_EXCL_START catch (...) { @@ -455,10 +489,7 @@ HelicsInput helicsFederateGetInputByTarget(HelicsFederate fed, const char* targe assignError(err, HELICS_ERROR_INVALID_ARGUMENT, invalidTargetKey); return nullptr; } - auto inp = std::make_unique(); - inp->inputPtr = &id; - inp->fedptr = std::move(fedObj); - return addInput(fed, std::move(inp)); + return findOrCreateInput(fed, id); } // LCOV_EXCL_START catch (...) { @@ -651,6 +682,27 @@ void helicsPublicationPublishNamedPoint(HelicsPublication pub, const char* str, } } +void helicsPublicationPublishDataBuffer(HelicsPublication pub, HelicsDataBuffer buffer, HelicsError* err) +{ + auto* pubObj = verifyPublication(pub, err); + if (pubObj == nullptr) { + return; + } + try { + auto* buff = getBuffer(buffer); + if (buff == nullptr) { + pubObj->pubPtr->publish(""); + return; + } + helics::defV pubVal; + helics::valueExtract(helics::data_view(*buff), helics::DataType::HELICS_UNKNOWN, pubVal); + pubObj->pubPtr->publish(pubVal); + } + catch (...) { + helicsErrorHandler(err); + } +} + void helicsPublicationAddTarget(HelicsPublication pub, const char* target, HelicsError* err) { auto* pubObj = verifyPublication(pub, err); @@ -709,6 +761,17 @@ bool checkOutputArgString(const char* outputString, int maxlen, HelicsError* err return true; } +HelicsDataBuffer helicsInputGetDataBuffer(HelicsInput inp, HelicsError* err) +{ + auto* inpObj = verifyInput(inp, err); + if (inpObj == nullptr) { + return (nullptr); + } + helics::data_view dv = inpObj->inputPtr->getBytes(); + auto* ptr = new helics::SmallBuffer(dv.string_view()); + return createAPIDataBuffer(*ptr); +} + void helicsInputGetBytes(HelicsInput inp, void* data, int maxDatalen, int* actualSize, HelicsError* err) { auto* inpObj = verifyInput(inp, err); diff --git a/src/helics/shared_api_library/api-data.h b/src/helics/shared_api_library/api-data.h index 67daa65ccd..5041a42ae9 100644 --- a/src/helics/shared_api_library/api-data.h +++ b/src/helics/shared_api_library/api-data.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/shared_api_library/backup/helics/helics.h b/src/helics/shared_api_library/backup/helics/helics.h index 735d074728..4003a3642c 100644 --- a/src/helics/shared_api_library/backup/helics/helics.h +++ b/src/helics/shared_api_library/backup/helics/helics.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -641,44 +641,94 @@ HELICS_EXPORT void* helicsDataBufferData(HelicsDataBuffer data); @return HELICS_TRUE if the reservation was successful HELICS_FALSE otherwise*/ HELICS_EXPORT HelicsBool helicsDataBufferReserve(HelicsDataBuffer data, int32_t newCapacity); -/** create a new data buffer and copy an existing buffer*/ +/** create a new data buffer and copy an existing buffer +@return a data buffer object with a copy of the data +*/ HELICS_EXPORT HelicsDataBuffer helicsDataBufferClone(HelicsDataBuffer data); -/** convert an integer to serialized bytes*/ -HELICS_EXPORT int32_t helicsIntegerToBytes(int64_t value, HelicsDataBuffer data); +/** convert an integer to serialized bytes in a buffer +* @param data the HelicsDataBuffer to fill +* @param value the value to serialize into the dataBuffer +@return the buffer size after filling +*/ +HELICS_EXPORT int32_t helicsDataBufferFillFromInteger(HelicsDataBuffer data, int64_t value); -/** convert a double to serialized bytes*/ -HELICS_EXPORT int32_t helicsDoubleToBytes(double value, HelicsDataBuffer data); +/** convert a double to serialized bytesin a buffer +* @param data the HelicsDataBuffer to fill +* @param value the value to serialize into the dataBuffer +@return the buffer size after filling +*/ +HELICS_EXPORT int32_t helicsDataBufferFillFromDouble(HelicsDataBuffer data, double value); -/** convert a string to serialized bytes*/ -HELICS_EXPORT int32_t helicsStringToBytes(const char* value, HelicsDataBuffer data); +/** convert a string to serialized bytesin a buffer +* @param data the HelicsDataBuffer to fill +* @param value the value to serialize into the dataBuffer +@return the buffer size after filling +*/ +HELICS_EXPORT int32_t helicsDataBufferFillFromString(HelicsDataBuffer data, const char* value); -/** convert a raw string (may contain nulls) to serialized bytes*/ -HELICS_EXPORT int32_t helicsRawStringToBytes(const char* str, int stringSize, HelicsDataBuffer data); +/** convert a raw string (may contain nulls) to serialized bytesin a buffer +* @param data the HelicsDataBuffer to fill +* @param value the value to serialize into the dataBuffer +@return the buffer size after filling +*/ +HELICS_EXPORT int32_t helicsDataBufferFillFromRawString(HelicsDataBuffer data, const char* str, int stringSize); -/** convert a bool to serialized bytes*/ -HELICS_EXPORT int32_t helicsBooleanToBytes(HelicsBool value, HelicsDataBuffer data); +/** convert a bool to serialized bytesin a buffer +* @param data the HelicsDataBuffer to fill +* @param value the value to serialize into the dataBuffer +@return the buffer size after filling +*/ +HELICS_EXPORT int32_t helicsDataBufferFillFromBoolean(HelicsDataBuffer data, HelicsBool value); -/** convert a char to serialized bytes*/ -HELICS_EXPORT int32_t helicsCharToBytes(char value, HelicsDataBuffer data); +/** convert a char to serialized bytesin a buffer +* @param data the HelicsDataBuffer to fill +* @param value the value to serialize into the dataBuffer +@return the buffer size after filling +*/ +HELICS_EXPORT int32_t helicsDataBufferFillFromChar(HelicsDataBuffer data, char value); -/** convert a time to serialized bytes*/ -HELICS_EXPORT int32_t helicsTimeToBytes(HelicsTime value, HelicsDataBuffer data); +/** convert a time to serialized bytesin a buffer +* @param data the HelicsDataBuffer to fill +* @param value the value to serialize into the dataBuffer +@return the buffer size after filling +*/ +HELICS_EXPORT int32_t helicsDataBufferFillFromTime(HelicsDataBuffer data, HelicsTime value); -/** convert a complex pair to serialized bytes*/ -HELICS_EXPORT int32_t helicsComplexToBytes(double real, double imag, HelicsDataBuffer data); +/** convert a complex pair to serialized bytesin a buffer +* @param data the HelicsDataBuffer to fill +* @param value the value to serialize into the dataBuffer +@return the buffer size after filling +*/ +HELICS_EXPORT int32_t helicsDataBufferFillFromComplex(HelicsDataBuffer data, double real, double imag); -/** convert a complex object to serialized bytes*/ -HELICS_EXPORT int32_t helicsComplexObjectToBytes(HelicsComplex value, HelicsDataBuffer data); +/** convert a complex object to serialized bytesin a buffer +* @param data the HelicsDataBuffer to fill +* @param value the value to serialize into the dataBuffer +@return the buffer size after filling +*/ +HELICS_EXPORT int32_t helicsDataBufferFillFromComplexObject(HelicsDataBuffer data, HelicsComplex value); -/** convert a real vector to serialized bytes*/ -HELICS_EXPORT int32_t helicsVectorToBytes(const double* value, int dataSize, HelicsDataBuffer data); +/** convert a real vector to serialized bytesin a buffer +* @param data the HelicsDataBuffer to fill +* @param value the value to serialize into the dataBuffer +@return the buffer size after filling +*/ +HELICS_EXPORT int32_t helicsDataBufferFillFromVector(HelicsDataBuffer data, const double* value, int dataSize); -/** convert a named point to serialized bytes*/ -HELICS_EXPORT int32_t helicsNamedPointToBytes(const char* name, double value, HelicsDataBuffer data); +/** convert a named point to serialized bytesin a buffer +* @param data the HelicsDataBuffer to fill +* @param value the value to serialize into the dataBuffer +@return the buffer size after filling +*/ +HELICS_EXPORT int32_t helicsDataBufferFillFromNamedPoint(HelicsDataBuffer data, const char* name, double value); -/** convert a complex vector to serialized bytes*/ -HELICS_EXPORT int32_t helicsComplexVectorToBytes(const double* value, int dataSize, HelicsDataBuffer data); +/** convert a complex vector to serialized bytesin a buffer +* @param data the HelicsDataBuffer to fill +* @param value the value to serialize into the dataBuffer +@return the buffer size after filling +*/ +HELICS_EXPORT int32_t helicsDataBufferFillFromComplexVector(HelicsDataBuffer data, const double* value, int dataSize); /** extract the data type from the data buffer, if the type isn't recognized UNKNOWN is returned*/ HELICS_EXPORT int helicsDataBufferType(HelicsDataBuffer data); @@ -1205,15 +1255,15 @@ HELICS_EXPORT void helicsBrokerFree(HelicsBroker broker); * * @details HelicsFederate objects can be used in all functions that take a HelicsFederate or HelicsFederate object as an argument. * - * @param fedName The name of the federate to create, can NULL or an empty string to use the default name from fi or an assigned name. - * @param fi The federate info object that contains details on the federate. + * @param fedName The name of the federate to create, can NULL or an empty string to use the default name from fedInfo or an assigned name. + * @param fedInfo The federate info object that contains details on the federate. * * @param[in,out] err An error object that will contain an error code and string if any error occurred during the execution of the function. * * @return An opaque value federate object. */ -HELICS_EXPORT HelicsFederate helicsCreateValueFederate(const char* fedName, HelicsFederateInfo fi, HelicsError* err); +HELICS_EXPORT HelicsFederate helicsCreateValueFederate(const char* fedName, HelicsFederateInfo fedInfo, HelicsError* err); /** * Create a value federate from a JSON file, JSON string, or TOML file. @@ -1236,14 +1286,14 @@ HELICS_EXPORT HelicsFederate helicsCreateValueFederateFromConfig(const char* con * argument. * * @param fedName The name of the federate to create. - * @param fi The federate info object that contains details on the federate. + * @param fedInfo The federate info object that contains details on the federate. * * @param[in,out] err An error object that will contain an error code and string if any error occurred during the execution of the function. * * @return An opaque message federate object. */ -HELICS_EXPORT HelicsFederate helicsCreateMessageFederate(const char* fedName, HelicsFederateInfo fi, HelicsError* err); +HELICS_EXPORT HelicsFederate helicsCreateMessageFederate(const char* fedName, HelicsFederateInfo fedInfo, HelicsError* err); /** * Create a message federate from a JSON file or JSON string or TOML file. @@ -1266,15 +1316,15 @@ HELICS_EXPORT HelicsFederate helicsCreateMessageFederateFromConfig(const char* c * @details Combination federates are both value federates and message federates, objects can be used in all functions * that take a HelicsFederate, helics_message_federate or HelicsFederate object as an argument * - * @param fedName A string with the name of the federate, can be NULL or an empty string to pull the default name from fi. - * @param fi The federate info object that contains details on the federate. + * @param fedName A string with the name of the federate, can be NULL or an empty string to pull the default name from fedInfo. + * @param fedInfo The federate info object that contains details on the federate. * * @param[in,out] err An error object that will contain an error code and string if any error occurred during the execution of the function. * * @return An opaque value federate object nullptr if the object creation failed. */ -HELICS_EXPORT HelicsFederate helicsCreateCombinationFederate(const char* fedName, HelicsFederateInfo fi, HelicsError* err); +HELICS_EXPORT HelicsFederate helicsCreateCombinationFederate(const char* fedName, HelicsFederateInfo fedInfo, HelicsError* err); /** * Create a combination federate from a JSON file or JSON string or TOML file. @@ -1296,15 +1346,15 @@ HELICS_EXPORT HelicsFederate helicsCreateCombinationFederateFromConfig(const cha * * @details Callback federates are combination federates that run a series of callback for execution in a completely automated fashion. * -* @param fedName A string with the name of the federate, can be NULL or an empty string to pull the default name from fi. -* @param fi The federate info object that contains details on the federate. +* @param fedName A string with the name of the federate, can be NULL or an empty string to pull the default name from fedInfo. +* @param fedInfo The federate info object that contains details on the federate. * * @param[in,out] err An error object that will contain an error code and string if any error occurred during the execution of the function. * * @return An opaque value federate object; nullptr if the object creation failed. */ -HELICS_EXPORT HelicsFederate helicsCreateCallbackFederate(const char* fedName, HelicsFederateInfo fi, HelicsError* err); +HELICS_EXPORT HelicsFederate helicsCreateCallbackFederate(const char* fedName, HelicsFederateInfo fedInfo, HelicsError* err); /** * Create a callback federate from a JSON file or JSON string or TOML file. @@ -1381,42 +1431,42 @@ HELICS_EXPORT HelicsFederateInfo helicsCreateFederateInfo(void); /** * Create a federate info object from an existing one and clone the information. * - * @param fi A federateInfo object to duplicate. + * @param fedInfo A federateInfo object to duplicate. * * @param[in,out] err An error object that will contain an error code and string if any error occurred during the execution of the function. * * @return A HelicsFederateInfo object which is a reference to the created object. */ -HELICS_EXPORT HelicsFederateInfo helicsFederateInfoClone(HelicsFederateInfo fi, HelicsError* err); +HELICS_EXPORT HelicsFederateInfo helicsFederateInfoClone(HelicsFederateInfo fedInfo, HelicsError* err); /** * Load federate info from command line arguments. * - * @param fi A federateInfo object. + * @param fedInfo A federateInfo object. * @param argc The number of command line arguments. * @param argv An array of strings from the command line. * * @param[in,out] err An error object that will contain an error code and string if any error occurred during the execution of the function. */ -HELICS_EXPORT void helicsFederateInfoLoadFromArgs(HelicsFederateInfo fi, int argc, const char* const* argv, HelicsError* err); +HELICS_EXPORT void helicsFederateInfoLoadFromArgs(HelicsFederateInfo fedInfo, int argc, const char* const* argv, HelicsError* err); /** * Load federate info from command line arguments contained in a string. * - * @param fi A federateInfo object. + * @param fedInfo A federateInfo object. * @param args Command line arguments specified in a string. * * @param[in,out] err An error object that will contain an error code and string if any error occurred during the execution of the function. */ -HELICS_EXPORT void helicsFederateInfoLoadFromString(HelicsFederateInfo fi, const char* args, HelicsError* err); +HELICS_EXPORT void helicsFederateInfoLoadFromString(HelicsFederateInfo fedInfo, const char* args, HelicsError* err); /** * Delete the memory associated with a federate info object. */ -HELICS_EXPORT void helicsFederateInfoFree(HelicsFederateInfo fi); +HELICS_EXPORT void helicsFederateInfoFree(HelicsFederateInfo fedInfo); /** * Check if a federate_object is valid. @@ -1428,107 +1478,107 @@ HELICS_EXPORT HelicsBool helicsFederateIsValid(HelicsFederate fed); /** * Set the name of the core to link to for a federate. * - * @param fi The federate info object to alter. + * @param fedInfo The federate info object to alter. * @param corename The identifier for a core to link to. * * @param[in,out] err An error object that will contain an error code and string if any error occurred during the execution of the function. */ -HELICS_EXPORT void helicsFederateInfoSetCoreName(HelicsFederateInfo fi, const char* corename, HelicsError* err); +HELICS_EXPORT void helicsFederateInfoSetCoreName(HelicsFederateInfo fedInfo, const char* corename, HelicsError* err); /** * Set the initialization string for the core usually in the form of command line arguments. * - * @param fi The federate info object to alter. + * @param fedInfo The federate info object to alter. * @param coreInit A string containing command line arguments to be passed to the core. * * @param[in,out] err An error object that will contain an error code and string if any error occurred during the execution of the function. */ -HELICS_EXPORT void helicsFederateInfoSetCoreInitString(HelicsFederateInfo fi, const char* coreInit, HelicsError* err); +HELICS_EXPORT void helicsFederateInfoSetCoreInitString(HelicsFederateInfo fedInfo, const char* coreInit, HelicsError* err); /** * Set the initialization string that a core will pass to a generated broker usually in the form of command line arguments. * - * @param fi The federate info object to alter. + * @param fedInfo The federate info object to alter. * @param brokerInit A string with command line arguments for a generated broker. * * @param[in,out] err An error object that will contain an error code and string if any error occurred during the execution of the function. */ -HELICS_EXPORT void helicsFederateInfoSetBrokerInitString(HelicsFederateInfo fi, const char* brokerInit, HelicsError* err); +HELICS_EXPORT void helicsFederateInfoSetBrokerInitString(HelicsFederateInfo fedInfo, const char* brokerInit, HelicsError* err); /** * Set the core type by integer code. * * @details Valid values available by definitions in api-data.h. - * @param fi The federate info object to alter. + * @param fedInfo The federate info object to alter. * @param coretype An numerical code for a core type see /ref helics_CoreType. * * @param[in,out] err An error object that will contain an error code and string if any error occurred during the execution of the function. */ -HELICS_EXPORT void helicsFederateInfoSetCoreType(HelicsFederateInfo fi, int coretype, HelicsError* err); +HELICS_EXPORT void helicsFederateInfoSetCoreType(HelicsFederateInfo fedInfo, int coretype, HelicsError* err); /** * Set the core type from a string. * - * @param fi The federate info object to alter. + * @param fedInfo The federate info object to alter. * @param coretype A string naming a core type. * * @param[in,out] err An error object that will contain an error code and string if any error occurred during the execution of the function. */ -HELICS_EXPORT void helicsFederateInfoSetCoreTypeFromString(HelicsFederateInfo fi, const char* coretype, HelicsError* err); +HELICS_EXPORT void helicsFederateInfoSetCoreTypeFromString(HelicsFederateInfo fedInfo, const char* coretype, HelicsError* err); /** * Set the name or connection information for a broker. * * @details This is only used if the core is automatically created, the broker information will be transferred to the core for connection. - * @param fi The federate info object to alter. + * @param fedInfo The federate info object to alter. * @param broker A string which defines the connection information for a broker either a name or an address. * * @param[in,out] err An error object that will contain an error code and string if any error occurred during the execution of the function. */ -HELICS_EXPORT void helicsFederateInfoSetBroker(HelicsFederateInfo fi, const char* broker, HelicsError* err); +HELICS_EXPORT void helicsFederateInfoSetBroker(HelicsFederateInfo fedInfo, const char* broker, HelicsError* err); /** * Set the key for a broker connection. * * @details This is only used if the core is automatically created, the broker information will be transferred to the core for connection. - * @param fi The federate info object to alter. + * @param fedInfo The federate info object to alter. * @param brokerkey A string containing a key for the broker to connect. * * @param[in,out] err An error object that will contain an error code and string if any error occurred during the execution of the function. */ -HELICS_EXPORT void helicsFederateInfoSetBrokerKey(HelicsFederateInfo fi, const char* brokerkey, HelicsError* err); +HELICS_EXPORT void helicsFederateInfoSetBrokerKey(HelicsFederateInfo fedInfo, const char* brokerkey, HelicsError* err); /** * Set the port to use for the broker. * * @details This is only used if the core is automatically created, the broker information will be transferred to the core for connection. * This will only be useful for network broker connections. - * @param fi The federate info object to alter. + * @param fedInfo The federate info object to alter. * @param brokerPort The integer port number to use for connection with a broker. * * @param[in,out] err An error object that will contain an error code and string if any error occurred during the execution of the function. */ -HELICS_EXPORT void helicsFederateInfoSetBrokerPort(HelicsFederateInfo fi, int brokerPort, HelicsError* err); +HELICS_EXPORT void helicsFederateInfoSetBrokerPort(HelicsFederateInfo fedInfo, int brokerPort, HelicsError* err); /** * Set the local port to use. * * @details This is only used if the core is automatically created, the port information will be transferred to the core for connection. - * @param fi The federate info object to alter. + * @param fedInfo The federate info object to alter. * @param localPort A string with the port information to use as the local server port can be a number or "auto" or "os_local". * * @param[in,out] err An error object that will contain an error code and string if any error occurred during the execution of the function. */ -HELICS_EXPORT void helicsFederateInfoSetLocalPort(HelicsFederateInfo fi, const char* localPort, HelicsError* err); +HELICS_EXPORT void helicsFederateInfoSetLocalPort(HelicsFederateInfo fedInfo, const char* localPort, HelicsError* err); /** * Get a property index for use in /ref helicsFederateInfoSetFlagOption, /ref helicsFederateInfoSetTimeProperty, @@ -1579,36 +1629,37 @@ HELICS_EXPORT int helicsGetDataType(const char* val); * Set a flag in the info structure. * * @details Valid flags are available /ref helics_federate_flags. - * @param fi The federate info object to alter. + * @param fedInfo The federate info object to alter. * @param flag A numerical index for a flag. * @param value The desired value of the flag HELICS_TRUE or HELICS_FALSE. * * @param[in,out] err An error object that will contain an error code and string if any error occurred during the execution of the function. */ -HELICS_EXPORT void helicsFederateInfoSetFlagOption(HelicsFederateInfo fi, int flag, HelicsBool value, HelicsError* err); +HELICS_EXPORT void helicsFederateInfoSetFlagOption(HelicsFederateInfo fedInfo, int flag, HelicsBool value, HelicsError* err); /** * Set the separator character in the info structure. * * @details The separator character is the separation character for local publications/endpoints in creating their global name. * For example if the separator character is '/' then a local endpoint would have a globally reachable name of fedName/localName. - * @param fi The federate info object to alter. + * @param fedInfo The federate info object to alter. * @param separator The character to use as a separator. * * @param[in,out] err An error object that will contain an error code and string if any error occurred during the execution of the function. */ -HELICS_EXPORT void helicsFederateInfoSetSeparator(HelicsFederateInfo fi, char separator, HelicsError* err); +HELICS_EXPORT void helicsFederateInfoSetSeparator(HelicsFederateInfo fedInfo, char separator, HelicsError* err); /** * Set the output delay for a federate. * - * @param fi The federate info object to alter. + * @param fedInfo The federate info object to alter. * @param timeProperty An integer representation of the time based property to set see /ref helics_properties. * @param propertyValue The value of the property to set the timeProperty to. * * @param[in,out] err An error object that will contain an error code and string if any error occurred during the execution of the function. */ -HELICS_EXPORT void helicsFederateInfoSetTimeProperty(HelicsFederateInfo fi, int timeProperty, HelicsTime propertyValue, HelicsError* err); +HELICS_EXPORT void + helicsFederateInfoSetTimeProperty(HelicsFederateInfo fedInfo, int timeProperty, HelicsTime propertyValue, HelicsError* err); // TODO(Dheepak): what are known properties. The docstring should reference all properties that can be passed here. /** @@ -1616,13 +1667,13 @@ HELICS_EXPORT void helicsFederateInfoSetTimeProperty(HelicsFederateInfo fi, int * * @details Set known properties. * - * @param fi The federateInfo object to alter. + * @param fedInfo The federateInfo object to alter. * @param intProperty An int identifying the property. * @param propertyValue The value to set the property to. * * @param[in,out] err An error object that will contain an error code and string if any error occurred during the execution of the function. */ -HELICS_EXPORT void helicsFederateInfoSetIntegerProperty(HelicsFederateInfo fi, int intProperty, int propertyValue, HelicsError* err); +HELICS_EXPORT void helicsFederateInfoSetIntegerProperty(HelicsFederateInfo fedInfo, int intProperty, int propertyValue, HelicsError* err); /** * Load interfaces from a file. @@ -2979,6 +3030,17 @@ HELICS_EXPORT void */ HELICS_EXPORT void helicsPublicationPublishNamedPoint(HelicsPublication pub, const char* field, double val, HelicsError* err); +/** +* Publish the contents of a helicsDataBuffer. +* +* @param pub The publication to publish for. +* @param buffer a HelicsDataBuffer object containing the data to publish +* +* @param[in,out] err A pointer to an error object for catching errors. + +*/ +HELICS_EXPORT void helicsPublicationPublishDataBuffer(HelicsPublication pub, HelicsDataBuffer buffer, HelicsError* err); + /** * Add a named input to the list of targets a publication publishes to. * @@ -3038,6 +3100,16 @@ HELICS_EXPORT int helicsInputGetByteCount(HelicsInput ipt); */ HELICS_EXPORT void helicsInputGetBytes(HelicsInput ipt, void* data, int maxDataLength, int* actualSize, HelicsError* err); +/** + * Get a copy of the raw data in a HelicsDataBuffer + * + * @param inp The input to get the data for. + * + * @param[in,out] err A pointer to an error object for catching errors. + * @return A HelicsDataBuffer object containing the data + */ +HELICS_EXPORT HelicsDataBuffer helicsInputGetDataBuffer(HelicsInput inp, HelicsError* err); + /** * Get the size of a value for an input assuming return as a string. * @@ -4176,6 +4248,15 @@ HELICS_EXPORT void helicsMessageGetBytes(HelicsMessage message, void* data, int */ HELICS_EXPORT void* helicsMessageGetBytesPointer(HelicsMessage message); +/** + * Get a data buffer to the message object + * + * @param message A message object to get the dataBuffer for + * + * @return A HelicsDataBuffer object to the data in a message. Modifying the buffer will directly modify the message contents. + */ +HELICS_EXPORT HelicsDataBuffer helicsMessageDataBuffer(HelicsMessage message, HelicsError* err); + /** * A check if the message contains a valid payload. * @@ -4311,6 +4392,16 @@ HELICS_EXPORT void helicsMessageSetString(HelicsMessage message, const char* dat */ HELICS_EXPORT void helicsMessageSetData(HelicsMessage message, const void* data, int inputDataLength, HelicsError* err); +/** + * Set the data payload of a message from a HelicsDataBuffer Object + * + * @param message The message object in question. + * @param data the dataBuffer containing the appropriate data, if null will clear the message payload + * + * @param[in,out] err An error object to fill out in case of an error. + */ +HELICS_EXPORT void helicsMessageSetDataBuffer(HelicsMessage message, HelicsDataBuffer data, HelicsError* err); + /** * Append data to the payload. * diff --git a/src/helics/shared_api_library/backup/helics/helics_api.h b/src/helics/shared_api_library/backup/helics/helics_api.h index 7680f212df..9a68b3e6b1 100644 --- a/src/helics/shared_api_library/backup/helics/helics_api.h +++ b/src/helics/shared_api_library/backup/helics/helics_api.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -303,18 +303,18 @@ int32_t helicsDataBufferCapacity(HelicsDataBuffer data); void* helicsDataBufferData(HelicsDataBuffer data); HelicsBool helicsDataBufferReserve(HelicsDataBuffer data, int32_t newCapacity); HelicsDataBuffer helicsDataBufferClone(HelicsDataBuffer data); -int32_t helicsIntegerToBytes(int64_t value, HelicsDataBuffer data); -int32_t helicsDoubleToBytes(double value, HelicsDataBuffer data); -int32_t helicsStringToBytes(const char* value, HelicsDataBuffer data); -int32_t helicsRawStringToBytes(const char* str, int stringSize, HelicsDataBuffer data); -int32_t helicsBooleanToBytes(HelicsBool value, HelicsDataBuffer data); -int32_t helicsCharToBytes(char value, HelicsDataBuffer data); -int32_t helicsTimeToBytes(HelicsTime value, HelicsDataBuffer data); -int32_t helicsComplexToBytes(double real, double imag, HelicsDataBuffer data); -int32_t helicsComplexObjectToBytes(HelicsComplex value, HelicsDataBuffer data); -int32_t helicsVectorToBytes(const double* value, int dataSize, HelicsDataBuffer data); -int32_t helicsNamedPointToBytes(const char* name, double value, HelicsDataBuffer data); -int32_t helicsComplexVectorToBytes(const double* value, int dataSize, HelicsDataBuffer data); +int32_t helicsDataBufferFillFromInteger(HelicsDataBuffer data, int64_t value); +int32_t helicsDataBufferFillFromDouble(HelicsDataBuffer data, double value); +int32_t helicsDataBufferFillFromString(HelicsDataBuffer data, const char* value); +int32_t helicsDataBufferFillFromRawString(HelicsDataBuffer data, const char* str, int stringSize); +int32_t helicsDataBufferFillFromBoolean(HelicsDataBuffer data, HelicsBool value); +int32_t helicsDataBufferFillFromChar(HelicsDataBuffer data, char value); +int32_t helicsDataBufferFillFromTime(HelicsDataBuffer data, HelicsTime value); +int32_t helicsDataBufferFillFromComplex(HelicsDataBuffer data, double real, double imag); +int32_t helicsDataBufferFillFromComplexObject(HelicsDataBuffer data, HelicsComplex value); +int32_t helicsDataBufferFillFromVector(HelicsDataBuffer data, const double* value, int dataSize); +int32_t helicsDataBufferFillFromNamedPoint(HelicsDataBuffer data, const char* name, double value); +int32_t helicsDataBufferFillFromComplexVector(HelicsDataBuffer data, const double* value, int dataSize); int helicsDataBufferType(HelicsDataBuffer data); int64_t helicsDataBufferToInteger(HelicsDataBuffer data); double helicsDataBufferToDouble(HelicsDataBuffer data); @@ -378,42 +378,42 @@ void helicsBrokerDestroy(HelicsBroker broker); void helicsCoreDestroy(HelicsCore core); void helicsCoreFree(HelicsCore core); void helicsBrokerFree(HelicsBroker broker); -HelicsFederate helicsCreateValueFederate(const char* fedName, HelicsFederateInfo fi, HelicsError* err); +HelicsFederate helicsCreateValueFederate(const char* fedName, HelicsFederateInfo fedInfo, HelicsError* err); HelicsFederate helicsCreateValueFederateFromConfig(const char* configFile, HelicsError* err); -HelicsFederate helicsCreateMessageFederate(const char* fedName, HelicsFederateInfo fi, HelicsError* err); +HelicsFederate helicsCreateMessageFederate(const char* fedName, HelicsFederateInfo fedInfo, HelicsError* err); HelicsFederate helicsCreateMessageFederateFromConfig(const char* configFile, HelicsError* err); -HelicsFederate helicsCreateCombinationFederate(const char* fedName, HelicsFederateInfo fi, HelicsError* err); +HelicsFederate helicsCreateCombinationFederate(const char* fedName, HelicsFederateInfo fedInfo, HelicsError* err); HelicsFederate helicsCreateCombinationFederateFromConfig(const char* configFile, HelicsError* err); -HelicsFederate helicsCreateCallbackFederate(const char* fedName, HelicsFederateInfo fi, HelicsError* err); +HelicsFederate helicsCreateCallbackFederate(const char* fedName, HelicsFederateInfo fedInfo, HelicsError* err); HelicsFederate helicsCreateCallbackFederateFromConfig(const char* configFile, HelicsError* err); HelicsFederate helicsFederateClone(HelicsFederate fed, HelicsError* err); void helicsFederateProtect(const char* fedName, HelicsError* err); void helicsFederateUnProtect(const char* fedName, HelicsError* err); HelicsBool helicsFederateIsProtected(const char* fedName, HelicsError* err); HelicsFederateInfo helicsCreateFederateInfo(void); -HelicsFederateInfo helicsFederateInfoClone(HelicsFederateInfo fi, HelicsError* err); -void helicsFederateInfoLoadFromArgs(HelicsFederateInfo fi, int argc, const char* const* argv, HelicsError* err); -void helicsFederateInfoLoadFromString(HelicsFederateInfo fi, const char* args, HelicsError* err); -void helicsFederateInfoFree(HelicsFederateInfo fi); +HelicsFederateInfo helicsFederateInfoClone(HelicsFederateInfo fedInfo, HelicsError* err); +void helicsFederateInfoLoadFromArgs(HelicsFederateInfo fedInfo, int argc, const char* const* argv, HelicsError* err); +void helicsFederateInfoLoadFromString(HelicsFederateInfo fedInfo, const char* args, HelicsError* err); +void helicsFederateInfoFree(HelicsFederateInfo fedInfo); HelicsBool helicsFederateIsValid(HelicsFederate fed); -void helicsFederateInfoSetCoreName(HelicsFederateInfo fi, const char* corename, HelicsError* err); -void helicsFederateInfoSetCoreInitString(HelicsFederateInfo fi, const char* coreInit, HelicsError* err); -void helicsFederateInfoSetBrokerInitString(HelicsFederateInfo fi, const char* brokerInit, HelicsError* err); -void helicsFederateInfoSetCoreType(HelicsFederateInfo fi, int coretype, HelicsError* err); -void helicsFederateInfoSetCoreTypeFromString(HelicsFederateInfo fi, const char* coretype, HelicsError* err); -void helicsFederateInfoSetBroker(HelicsFederateInfo fi, const char* broker, HelicsError* err); -void helicsFederateInfoSetBrokerKey(HelicsFederateInfo fi, const char* brokerkey, HelicsError* err); -void helicsFederateInfoSetBrokerPort(HelicsFederateInfo fi, int brokerPort, HelicsError* err); -void helicsFederateInfoSetLocalPort(HelicsFederateInfo fi, const char* localPort, HelicsError* err); +void helicsFederateInfoSetCoreName(HelicsFederateInfo fedInfo, const char* corename, HelicsError* err); +void helicsFederateInfoSetCoreInitString(HelicsFederateInfo fedInfo, const char* coreInit, HelicsError* err); +void helicsFederateInfoSetBrokerInitString(HelicsFederateInfo fedInfo, const char* brokerInit, HelicsError* err); +void helicsFederateInfoSetCoreType(HelicsFederateInfo fedInfo, int coretype, HelicsError* err); +void helicsFederateInfoSetCoreTypeFromString(HelicsFederateInfo fedInfo, const char* coretype, HelicsError* err); +void helicsFederateInfoSetBroker(HelicsFederateInfo fedInfo, const char* broker, HelicsError* err); +void helicsFederateInfoSetBrokerKey(HelicsFederateInfo fedInfo, const char* brokerkey, HelicsError* err); +void helicsFederateInfoSetBrokerPort(HelicsFederateInfo fedInfo, int brokerPort, HelicsError* err); +void helicsFederateInfoSetLocalPort(HelicsFederateInfo fedInfo, const char* localPort, HelicsError* err); int helicsGetPropertyIndex(const char* val); int helicsGetFlagIndex(const char* val); int helicsGetOptionIndex(const char* val); int helicsGetOptionValue(const char* val); int helicsGetDataType(const char* val); -void helicsFederateInfoSetFlagOption(HelicsFederateInfo fi, int flag, HelicsBool value, HelicsError* err); -void helicsFederateInfoSetSeparator(HelicsFederateInfo fi, char separator, HelicsError* err); -void helicsFederateInfoSetTimeProperty(HelicsFederateInfo fi, int timeProperty, HelicsTime propertyValue, HelicsError* err); -void helicsFederateInfoSetIntegerProperty(HelicsFederateInfo fi, int intProperty, int propertyValue, HelicsError* err); +void helicsFederateInfoSetFlagOption(HelicsFederateInfo fedInfo, int flag, HelicsBool value, HelicsError* err); +void helicsFederateInfoSetSeparator(HelicsFederateInfo fedInfo, char separator, HelicsError* err); +void helicsFederateInfoSetTimeProperty(HelicsFederateInfo fedInfo, int timeProperty, HelicsTime propertyValue, HelicsError* err); +void helicsFederateInfoSetIntegerProperty(HelicsFederateInfo fedInfo, int intProperty, int propertyValue, HelicsError* err); void helicsFederateRegisterInterfaces(HelicsFederate fed, const char* file, HelicsError* err); void helicsFederateGlobalError(HelicsFederate fed, int errorCode, const char* errorString, HelicsError* err); void helicsFederateLocalError(HelicsFederate fed, int errorCode, const char* errorString, HelicsError* err); @@ -539,12 +539,14 @@ void helicsPublicationPublishComplex(HelicsPublication pub, double real, double void helicsPublicationPublishVector(HelicsPublication pub, const double* vectorInput, int vectorLength, HelicsError* err); void helicsPublicationPublishComplexVector(HelicsPublication pub, const double* vectorInput, int vectorLength, HelicsError* err); void helicsPublicationPublishNamedPoint(HelicsPublication pub, const char* field, double val, HelicsError* err); +void helicsPublicationPublishDataBuffer(HelicsPublication pub, HelicsDataBuffer buffer, HelicsError* err); void helicsPublicationAddTarget(HelicsPublication pub, const char* target, HelicsError* err); HelicsBool helicsInputIsValid(HelicsInput ipt); void helicsInputAddTarget(HelicsInput ipt, const char* target, HelicsError* err); int helicsInputGetByteCount(HelicsInput ipt); void helicsInputGetBytes(HelicsInput ipt, void* data, int maxDataLength, int* actualSize, HelicsError* err); +HelicsDataBuffer helicsInputGetDataBuffer(HelicsInput inp, HelicsError* err); int helicsInputGetStringSize(HelicsInput ipt); void helicsInputGetString(HelicsInput ipt, char* outputString, int maxStringLength, int* actualLength, HelicsError* err); int64_t helicsInputGetInteger(HelicsInput ipt, HelicsError* err); @@ -658,6 +660,7 @@ HelicsBool helicsMessageGetFlagOption(HelicsMessage message, int flag); int helicsMessageGetByteCount(HelicsMessage message); void helicsMessageGetBytes(HelicsMessage message, void* data, int maxMessageLength, int* actualSize, HelicsError* err); void* helicsMessageGetBytesPointer(HelicsMessage message); +HelicsDataBuffer helicsMessageDataBuffer(HelicsMessage message, HelicsError* err); HelicsBool helicsMessageIsValid(HelicsMessage message); void helicsMessageSetSource(HelicsMessage message, const char* src, HelicsError* err); void helicsMessageSetDestination(HelicsMessage message, const char* dst, HelicsError* err); @@ -671,6 +674,7 @@ void helicsMessageClearFlags(HelicsMessage message); void helicsMessageSetFlagOption(HelicsMessage message, int flag, HelicsBool flagValue, HelicsError* err); void helicsMessageSetString(HelicsMessage message, const char* data, HelicsError* err); void helicsMessageSetData(HelicsMessage message, const void* data, int inputDataLength, HelicsError* err); +void helicsMessageSetDataBuffer(HelicsMessage message, HelicsDataBuffer data, HelicsError* err); void helicsMessageAppendData(HelicsMessage message, const void* data, int inputDataLength, HelicsError* err); void helicsMessageCopy(HelicsMessage src_message, HelicsMessage dst_message, HelicsError* err); HelicsMessage helicsMessageClone(HelicsMessage message, HelicsError* err); diff --git a/src/helics/shared_api_library/helicsCallbacks.cpp b/src/helics/shared_api_library/helicsCallbacks.cpp index 07b8769a34..aee2a1c7c8 100644 --- a/src/helics/shared_api_library/helicsCallbacks.cpp +++ b/src/helics/shared_api_library/helicsCallbacks.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -32,9 +32,9 @@ void helicsBrokerSetLoggingCallback(HelicsBroker broker, brk->setLoggingCallback({}); } else { brk->setLoggingCallback([logger, userdata](int loglevel, std::string_view ident, std::string_view message) { - const std::string id(ident); + const std::string identifier(ident); const std::string mess(message); - logger(loglevel, id.c_str(), mess.c_str(), userdata); + logger(loglevel, identifier.c_str(), mess.c_str(), userdata); }); } } @@ -48,20 +48,20 @@ void helicsCoreSetLoggingCallback(HelicsCore core, void* userdata, HelicsError* err) { - auto* cr = getCore(core, err); - if (cr == nullptr) { + auto* coreObj = getCore(core, err); + if (coreObj == nullptr) { return; } try { if (logger == nullptr) { - cr->setLoggingCallback(helics::gLocalCoreId, {}); + coreObj->setLoggingCallback(helics::gLocalCoreId, {}); } else { - cr->setLoggingCallback(helics::gLocalCoreId, - [logger, userdata](int loglevel, std::string_view ident, std::string_view message) { - const std::string ID(ident); - const std::string mess(message); - logger(loglevel, ID.c_str(), mess.c_str(), userdata); - }); + coreObj->setLoggingCallback(helics::gLocalCoreId, + [logger, userdata](int loglevel, std::string_view ident, std::string_view message) { + const std::string identifier(ident); + const std::string mess(message); + logger(loglevel, identifier.c_str(), mess.c_str(), userdata); + }); } } catch (...) { // LCOV_EXCL_LINE @@ -84,9 +84,9 @@ void helicsFederateSetLoggingCallback(HelicsFederate fed, fedptr->setLoggingCallback({}); } else { fedptr->setLoggingCallback([logger, userdata](int loglevel, std::string_view ident, std::string_view message) { - const std::string id(ident); + const std::string identifier(ident); const std::string mess(message); - logger(loglevel, id.c_str(), mess.c_str(), userdata); + logger(loglevel, identifier.c_str(), mess.c_str(), userdata); }); } } @@ -148,7 +148,7 @@ void helicsFederateSetTimeUpdateCallback(HelicsFederate fed, void helicsQueryBufferFill(HelicsQueryBuffer buffer, const char* string, int stringSize, HelicsError* err) { - static const char* invalidBuffer = "The given buffer is not valid"; + static constexpr const char* invalidBuffer = "The given buffer is not valid"; if (((err) != nullptr) && ((err)->error_code != 0)) { return; @@ -166,6 +166,7 @@ void helicsQueryBufferFill(HelicsQueryBuffer buffer, const char* string, int str if (stringSize <= 0 || string == nullptr) { bufferStr->clear(); bufferStr->push_back('>'); + return; } bufferStr->reserve(static_cast(stringSize) + 1); bufferStr->assign(string, string + stringSize); diff --git a/src/helics/shared_api_library/helicsCallbacks.h b/src/helics/shared_api_library/helicsCallbacks.h index f18a249781..a677e8029e 100644 --- a/src/helics/shared_api_library/helicsCallbacks.h +++ b/src/helics/shared_api_library/helicsCallbacks.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/src/helics/shared_api_library/helicsCore.h b/src/helics/shared_api_library/helicsCore.h index 7a3a2ba875..056d9863d9 100644 --- a/src/helics/shared_api_library/helicsCore.h +++ b/src/helics/shared_api_library/helicsCore.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -484,15 +484,15 @@ HELICS_EXPORT void helicsBrokerFree(HelicsBroker broker); * * @details HelicsFederate objects can be used in all functions that take a HelicsFederate or HelicsFederate object as an argument. * - * @param fedName The name of the federate to create, can NULL or an empty string to use the default name from fi or an assigned name. - * @param fi The federate info object that contains details on the federate. + * @param fedName The name of the federate to create, can NULL or an empty string to use the default name from fedInfo or an assigned name. + * @param fedInfo The federate info object that contains details on the federate. * * @param[in,out] err An error object that will contain an error code and string if any error occurred during the execution of the function. * * @return An opaque value federate object. */ -HELICS_EXPORT HelicsFederate helicsCreateValueFederate(const char* fedName, HelicsFederateInfo fi, HelicsError* err); +HELICS_EXPORT HelicsFederate helicsCreateValueFederate(const char* fedName, HelicsFederateInfo fedInfo, HelicsError* err); /** * Create a value federate from a JSON file, JSON string, or TOML file. @@ -515,14 +515,14 @@ HELICS_EXPORT HelicsFederate helicsCreateValueFederateFromConfig(const char* con * argument. * * @param fedName The name of the federate to create. - * @param fi The federate info object that contains details on the federate. + * @param fedInfo The federate info object that contains details on the federate. * * @param[in,out] err An error object that will contain an error code and string if any error occurred during the execution of the function. * * @return An opaque message federate object. */ -HELICS_EXPORT HelicsFederate helicsCreateMessageFederate(const char* fedName, HelicsFederateInfo fi, HelicsError* err); +HELICS_EXPORT HelicsFederate helicsCreateMessageFederate(const char* fedName, HelicsFederateInfo fedInfo, HelicsError* err); /** * Create a message federate from a JSON file or JSON string or TOML file. @@ -545,15 +545,15 @@ HELICS_EXPORT HelicsFederate helicsCreateMessageFederateFromConfig(const char* c * @details Combination federates are both value federates and message federates, objects can be used in all functions * that take a HelicsFederate, helics_message_federate or HelicsFederate object as an argument * - * @param fedName A string with the name of the federate, can be NULL or an empty string to pull the default name from fi. - * @param fi The federate info object that contains details on the federate. + * @param fedName A string with the name of the federate, can be NULL or an empty string to pull the default name from fedInfo. + * @param fedInfo The federate info object that contains details on the federate. * * @param[in,out] err An error object that will contain an error code and string if any error occurred during the execution of the function. * * @return An opaque value federate object nullptr if the object creation failed. */ -HELICS_EXPORT HelicsFederate helicsCreateCombinationFederate(const char* fedName, HelicsFederateInfo fi, HelicsError* err); +HELICS_EXPORT HelicsFederate helicsCreateCombinationFederate(const char* fedName, HelicsFederateInfo fedInfo, HelicsError* err); /** * Create a combination federate from a JSON file or JSON string or TOML file. @@ -575,15 +575,15 @@ HELICS_EXPORT HelicsFederate helicsCreateCombinationFederateFromConfig(const cha * * @details Callback federates are combination federates that run a series of callback for execution in a completely automated fashion. * -* @param fedName A string with the name of the federate, can be NULL or an empty string to pull the default name from fi. -* @param fi The federate info object that contains details on the federate. +* @param fedName A string with the name of the federate, can be NULL or an empty string to pull the default name from fedInfo. +* @param fedInfo The federate info object that contains details on the federate. * * @param[in,out] err An error object that will contain an error code and string if any error occurred during the execution of the function. * * @return An opaque value federate object; nullptr if the object creation failed. */ -HELICS_EXPORT HelicsFederate helicsCreateCallbackFederate(const char* fedName, HelicsFederateInfo fi, HelicsError* err); +HELICS_EXPORT HelicsFederate helicsCreateCallbackFederate(const char* fedName, HelicsFederateInfo fedInfo, HelicsError* err); /** * Create a callback federate from a JSON file or JSON string or TOML file. @@ -660,42 +660,42 @@ HELICS_EXPORT HelicsFederateInfo helicsCreateFederateInfo(void); /** * Create a federate info object from an existing one and clone the information. * - * @param fi A federateInfo object to duplicate. + * @param fedInfo A federateInfo object to duplicate. * * @param[in,out] err An error object that will contain an error code and string if any error occurred during the execution of the function. * * @return A HelicsFederateInfo object which is a reference to the created object. */ -HELICS_EXPORT HelicsFederateInfo helicsFederateInfoClone(HelicsFederateInfo fi, HelicsError* err); +HELICS_EXPORT HelicsFederateInfo helicsFederateInfoClone(HelicsFederateInfo fedInfo, HelicsError* err); /** * Load federate info from command line arguments. * - * @param fi A federateInfo object. + * @param fedInfo A federateInfo object. * @param argc The number of command line arguments. * @param argv An array of strings from the command line. * * @param[in,out] err An error object that will contain an error code and string if any error occurred during the execution of the function. */ -HELICS_EXPORT void helicsFederateInfoLoadFromArgs(HelicsFederateInfo fi, int argc, const char* const* argv, HelicsError* err); +HELICS_EXPORT void helicsFederateInfoLoadFromArgs(HelicsFederateInfo fedInfo, int argc, const char* const* argv, HelicsError* err); /** * Load federate info from command line arguments contained in a string. * - * @param fi A federateInfo object. + * @param fedInfo A federateInfo object. * @param args Command line arguments specified in a string. * * @param[in,out] err An error object that will contain an error code and string if any error occurred during the execution of the function. */ -HELICS_EXPORT void helicsFederateInfoLoadFromString(HelicsFederateInfo fi, const char* args, HelicsError* err); +HELICS_EXPORT void helicsFederateInfoLoadFromString(HelicsFederateInfo fedInfo, const char* args, HelicsError* err); /** * Delete the memory associated with a federate info object. */ -HELICS_EXPORT void helicsFederateInfoFree(HelicsFederateInfo fi); +HELICS_EXPORT void helicsFederateInfoFree(HelicsFederateInfo fedInfo); /** * Check if a federate_object is valid. @@ -707,107 +707,107 @@ HELICS_EXPORT HelicsBool helicsFederateIsValid(HelicsFederate fed); /** * Set the name of the core to link to for a federate. * - * @param fi The federate info object to alter. + * @param fedInfo The federate info object to alter. * @param corename The identifier for a core to link to. * * @param[in,out] err An error object that will contain an error code and string if any error occurred during the execution of the function. */ -HELICS_EXPORT void helicsFederateInfoSetCoreName(HelicsFederateInfo fi, const char* corename, HelicsError* err); +HELICS_EXPORT void helicsFederateInfoSetCoreName(HelicsFederateInfo fedInfo, const char* corename, HelicsError* err); /** * Set the initialization string for the core usually in the form of command line arguments. * - * @param fi The federate info object to alter. + * @param fedInfo The federate info object to alter. * @param coreInit A string containing command line arguments to be passed to the core. * * @param[in,out] err An error object that will contain an error code and string if any error occurred during the execution of the function. */ -HELICS_EXPORT void helicsFederateInfoSetCoreInitString(HelicsFederateInfo fi, const char* coreInit, HelicsError* err); +HELICS_EXPORT void helicsFederateInfoSetCoreInitString(HelicsFederateInfo fedInfo, const char* coreInit, HelicsError* err); /** * Set the initialization string that a core will pass to a generated broker usually in the form of command line arguments. * - * @param fi The federate info object to alter. + * @param fedInfo The federate info object to alter. * @param brokerInit A string with command line arguments for a generated broker. * * @param[in,out] err An error object that will contain an error code and string if any error occurred during the execution of the function. */ -HELICS_EXPORT void helicsFederateInfoSetBrokerInitString(HelicsFederateInfo fi, const char* brokerInit, HelicsError* err); +HELICS_EXPORT void helicsFederateInfoSetBrokerInitString(HelicsFederateInfo fedInfo, const char* brokerInit, HelicsError* err); /** * Set the core type by integer code. * * @details Valid values available by definitions in api-data.h. - * @param fi The federate info object to alter. + * @param fedInfo The federate info object to alter. * @param coretype An numerical code for a core type see /ref helics_CoreType. * * @param[in,out] err An error object that will contain an error code and string if any error occurred during the execution of the function. */ -HELICS_EXPORT void helicsFederateInfoSetCoreType(HelicsFederateInfo fi, int coretype, HelicsError* err); +HELICS_EXPORT void helicsFederateInfoSetCoreType(HelicsFederateInfo fedInfo, int coretype, HelicsError* err); /** * Set the core type from a string. * - * @param fi The federate info object to alter. + * @param fedInfo The federate info object to alter. * @param coretype A string naming a core type. * * @param[in,out] err An error object that will contain an error code and string if any error occurred during the execution of the function. */ -HELICS_EXPORT void helicsFederateInfoSetCoreTypeFromString(HelicsFederateInfo fi, const char* coretype, HelicsError* err); +HELICS_EXPORT void helicsFederateInfoSetCoreTypeFromString(HelicsFederateInfo fedInfo, const char* coretype, HelicsError* err); /** * Set the name or connection information for a broker. * * @details This is only used if the core is automatically created, the broker information will be transferred to the core for connection. - * @param fi The federate info object to alter. + * @param fedInfo The federate info object to alter. * @param broker A string which defines the connection information for a broker either a name or an address. * * @param[in,out] err An error object that will contain an error code and string if any error occurred during the execution of the function. */ -HELICS_EXPORT void helicsFederateInfoSetBroker(HelicsFederateInfo fi, const char* broker, HelicsError* err); +HELICS_EXPORT void helicsFederateInfoSetBroker(HelicsFederateInfo fedInfo, const char* broker, HelicsError* err); /** * Set the key for a broker connection. * * @details This is only used if the core is automatically created, the broker information will be transferred to the core for connection. - * @param fi The federate info object to alter. + * @param fedInfo The federate info object to alter. * @param brokerkey A string containing a key for the broker to connect. * * @param[in,out] err An error object that will contain an error code and string if any error occurred during the execution of the function. */ -HELICS_EXPORT void helicsFederateInfoSetBrokerKey(HelicsFederateInfo fi, const char* brokerkey, HelicsError* err); +HELICS_EXPORT void helicsFederateInfoSetBrokerKey(HelicsFederateInfo fedInfo, const char* brokerkey, HelicsError* err); /** * Set the port to use for the broker. * * @details This is only used if the core is automatically created, the broker information will be transferred to the core for connection. * This will only be useful for network broker connections. - * @param fi The federate info object to alter. + * @param fedInfo The federate info object to alter. * @param brokerPort The integer port number to use for connection with a broker. * * @param[in,out] err An error object that will contain an error code and string if any error occurred during the execution of the function. */ -HELICS_EXPORT void helicsFederateInfoSetBrokerPort(HelicsFederateInfo fi, int brokerPort, HelicsError* err); +HELICS_EXPORT void helicsFederateInfoSetBrokerPort(HelicsFederateInfo fedInfo, int brokerPort, HelicsError* err); /** * Set the local port to use. * * @details This is only used if the core is automatically created, the port information will be transferred to the core for connection. - * @param fi The federate info object to alter. + * @param fedInfo The federate info object to alter. * @param localPort A string with the port information to use as the local server port can be a number or "auto" or "os_local". * * @param[in,out] err An error object that will contain an error code and string if any error occurred during the execution of the function. */ -HELICS_EXPORT void helicsFederateInfoSetLocalPort(HelicsFederateInfo fi, const char* localPort, HelicsError* err); +HELICS_EXPORT void helicsFederateInfoSetLocalPort(HelicsFederateInfo fedInfo, const char* localPort, HelicsError* err); /** * Get a property index for use in /ref helicsFederateInfoSetFlagOption, /ref helicsFederateInfoSetTimeProperty, @@ -858,36 +858,37 @@ HELICS_EXPORT int helicsGetDataType(const char* val); * Set a flag in the info structure. * * @details Valid flags are available /ref helics_federate_flags. - * @param fi The federate info object to alter. + * @param fedInfo The federate info object to alter. * @param flag A numerical index for a flag. * @param value The desired value of the flag HELICS_TRUE or HELICS_FALSE. * * @param[in,out] err An error object that will contain an error code and string if any error occurred during the execution of the function. */ -HELICS_EXPORT void helicsFederateInfoSetFlagOption(HelicsFederateInfo fi, int flag, HelicsBool value, HelicsError* err); +HELICS_EXPORT void helicsFederateInfoSetFlagOption(HelicsFederateInfo fedInfo, int flag, HelicsBool value, HelicsError* err); /** * Set the separator character in the info structure. * * @details The separator character is the separation character for local publications/endpoints in creating their global name. * For example if the separator character is '/' then a local endpoint would have a globally reachable name of fedName/localName. - * @param fi The federate info object to alter. + * @param fedInfo The federate info object to alter. * @param separator The character to use as a separator. * * @param[in,out] err An error object that will contain an error code and string if any error occurred during the execution of the function. */ -HELICS_EXPORT void helicsFederateInfoSetSeparator(HelicsFederateInfo fi, char separator, HelicsError* err); +HELICS_EXPORT void helicsFederateInfoSetSeparator(HelicsFederateInfo fedInfo, char separator, HelicsError* err); /** * Set the output delay for a federate. * - * @param fi The federate info object to alter. + * @param fedInfo The federate info object to alter. * @param timeProperty An integer representation of the time based property to set see /ref helics_properties. * @param propertyValue The value of the property to set the timeProperty to. * * @param[in,out] err An error object that will contain an error code and string if any error occurred during the execution of the function. */ -HELICS_EXPORT void helicsFederateInfoSetTimeProperty(HelicsFederateInfo fi, int timeProperty, HelicsTime propertyValue, HelicsError* err); +HELICS_EXPORT void + helicsFederateInfoSetTimeProperty(HelicsFederateInfo fedInfo, int timeProperty, HelicsTime propertyValue, HelicsError* err); // TODO(Dheepak): what are known properties. The docstring should reference all properties that can be passed here. /** @@ -895,13 +896,13 @@ HELICS_EXPORT void helicsFederateInfoSetTimeProperty(HelicsFederateInfo fi, int * * @details Set known properties. * - * @param fi The federateInfo object to alter. + * @param fedInfo The federateInfo object to alter. * @param intProperty An int identifying the property. * @param propertyValue The value to set the property to. * * @param[in,out] err An error object that will contain an error code and string if any error occurred during the execution of the function. */ -HELICS_EXPORT void helicsFederateInfoSetIntegerProperty(HelicsFederateInfo fi, int intProperty, int propertyValue, HelicsError* err); +HELICS_EXPORT void helicsFederateInfoSetIntegerProperty(HelicsFederateInfo fedInfo, int intProperty, int propertyValue, HelicsError* err); /** * Load interfaces from a file. diff --git a/src/helics/shared_api_library/helicsData.cpp b/src/helics/shared_api_library/helicsData.cpp index 4b1d5d6db1..b010e8cf40 100644 --- a/src/helics/shared_api_library/helicsData.cpp +++ b/src/helics/shared_api_library/helicsData.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -41,16 +41,25 @@ HelicsDataBuffer helicsWrapDataInBuffer(void* data, int dataSize, int dataCapaci return static_cast(ptr); } -static helics::SmallBuffer* getBuffer(HelicsDataBuffer data) +helics::SmallBuffer* getBuffer(HelicsDataBuffer data) { auto* ptr = reinterpret_cast(data); - return (ptr != nullptr && ptr->userKey == gBufferValidationIdentifier) ? ptr : nullptr; + if (ptr != nullptr && ptr->userKey == gBufferValidationIdentifier) { + return ptr; + } + auto* message = getMessageObj(data, nullptr); + if (message != nullptr) { + return &message->data; + } + return nullptr; } void helicsDataBufferFree(HelicsDataBuffer data) { - auto* ptr = getBuffer(data); - delete ptr; + auto* ptr = reinterpret_cast(data); + if (ptr != nullptr && ptr->userKey == gBufferValidationIdentifier) { + delete ptr; + } } HelicsBool helicsDataBufferIsValid(HelicsDataBuffer data) @@ -103,7 +112,7 @@ HelicsDataBuffer helicsDataBufferClone(HelicsDataBuffer data) return static_cast(newptr); } -HELICS_EXPORT int32_t helicsIntegerToBytes(int64_t value, HelicsDataBuffer data) +HELICS_EXPORT int32_t helicsDataBufferFillFromInteger(HelicsDataBuffer data, int64_t value) { auto* ptr = getBuffer(data); if (ptr == nullptr) { @@ -119,7 +128,7 @@ HELICS_EXPORT int32_t helicsIntegerToBytes(int64_t value, HelicsDataBuffer data) } /** convert a double to serialized bytes*/ -HELICS_EXPORT int32_t helicsDoubleToBytes(double value, HelicsDataBuffer data) +HELICS_EXPORT int32_t helicsDataBufferFillFromDouble(HelicsDataBuffer data, double value) { auto* ptr = getBuffer(data); if (ptr == nullptr) { @@ -135,7 +144,7 @@ HELICS_EXPORT int32_t helicsDoubleToBytes(double value, HelicsDataBuffer data) } /** convert a string to serialized bytes*/ -HELICS_EXPORT int32_t helicsStringToBytes(const char* str, HelicsDataBuffer data) +HELICS_EXPORT int32_t helicsDataBufferFillFromString(HelicsDataBuffer data, const char* str) { auto* ptr = getBuffer(data); if (ptr == nullptr) { @@ -151,7 +160,7 @@ HELICS_EXPORT int32_t helicsStringToBytes(const char* str, HelicsDataBuffer data } /** convert a string to serialized bytes*/ -HELICS_EXPORT int32_t helicsRawStringToBytes(const char* str, int stringSize, HelicsDataBuffer data) +HELICS_EXPORT int32_t helicsDataBufferFillFromRawString(HelicsDataBuffer data, const char* str, int stringSize) { auto* ptr = getBuffer(data); if (ptr == nullptr) { @@ -166,7 +175,7 @@ HELICS_EXPORT int32_t helicsRawStringToBytes(const char* str, int stringSize, He } } -int32_t helicsBooleanToBytes(HelicsBool value, HelicsDataBuffer data) +int32_t helicsDataBufferFillFromBoolean(HelicsDataBuffer data, HelicsBool value) { auto* ptr = getBuffer(data); if (ptr == nullptr) { @@ -183,7 +192,7 @@ int32_t helicsBooleanToBytes(HelicsBool value, HelicsDataBuffer data) } /** convert a char to serialized bytes*/ -int32_t helicsCharToBytes(char value, HelicsDataBuffer data) +int32_t helicsDataBufferFillFromChar(HelicsDataBuffer data, char value) { auto* ptr = getBuffer(data); if (ptr == nullptr) { @@ -199,7 +208,7 @@ int32_t helicsCharToBytes(char value, HelicsDataBuffer data) } /** convert a HelicsTime to serialized bytes*/ -int32_t helicsTimeToBytes(HelicsTime value, HelicsDataBuffer data) +int32_t helicsDataBufferFillFromTime(HelicsDataBuffer data, HelicsTime value) { auto* ptr = getBuffer(data); if (ptr == nullptr) { @@ -214,7 +223,7 @@ int32_t helicsTimeToBytes(HelicsTime value, HelicsDataBuffer data) } } -int32_t helicsComplexToBytes(double real, double imag, HelicsDataBuffer data) +int32_t helicsDataBufferFillFromComplex(HelicsDataBuffer data, double real, double imag) { auto* ptr = getBuffer(data); if (ptr == nullptr) { @@ -229,7 +238,7 @@ int32_t helicsComplexToBytes(double real, double imag, HelicsDataBuffer data) } } -int32_t helicsNamedPointToBytes(const char* name, double val, HelicsDataBuffer data) +int32_t helicsDataBufferFillFromNamedPoint(HelicsDataBuffer data, const char* name, double val) { auto* ptr = getBuffer(data); if (ptr == nullptr) { @@ -244,12 +253,12 @@ int32_t helicsNamedPointToBytes(const char* name, double val, HelicsDataBuffer d } } -int32_t helicsComplexObjectToBytes(HelicsComplex value, HelicsDataBuffer data) +int32_t helicsDataBufferFillFromComplexObject(HelicsDataBuffer data, HelicsComplex value) { - return helicsComplexToBytes(value.real, value.imag, data); + return helicsDataBufferFillFromComplex(data, value.real, value.imag); } -int32_t helicsVectorToBytes(const double* value, int dataSize, HelicsDataBuffer data) +int32_t helicsDataBufferFillFromVector(HelicsDataBuffer data, const double* value, int dataSize) { auto* ptr = getBuffer(data); if (ptr == nullptr) { @@ -270,7 +279,7 @@ int32_t helicsVectorToBytes(const double* value, int dataSize, HelicsDataBuffer // std::complex is explicitly allowed to alias like this in the standard #endif -int32_t helicsComplexVectorToBytes(const double* value, int dataSize, HelicsDataBuffer data) +int32_t helicsDataBufferFillFromComplexVector(HelicsDataBuffer data, const double* value, int dataSize) { auto* ptr = getBuffer(data); if (ptr == nullptr) { @@ -399,6 +408,8 @@ int helicsDataBufferStringSize(HelicsDataBuffer data) return static_cast(helics::detail::getDataSize(ptr->data())) + 1; case helics::DataType::HELICS_CHAR: return 1; + case helics::DataType::HELICS_UNKNOWN: + return static_cast(ptr->size()); default: { std::string v; helics::valueExtract(helics::data_view(*ptr), helics::detail::detectType(ptr->data()), v); diff --git a/src/helics/shared_api_library/helicsData.h b/src/helics/shared_api_library/helicsData.h index c730d48a1a..f3406af68c 100644 --- a/src/helics/shared_api_library/helicsData.h +++ b/src/helics/shared_api_library/helicsData.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -41,44 +41,94 @@ HELICS_EXPORT void* helicsDataBufferData(HelicsDataBuffer data); @return HELICS_TRUE if the reservation was successful HELICS_FALSE otherwise*/ HELICS_EXPORT HelicsBool helicsDataBufferReserve(HelicsDataBuffer data, int32_t newCapacity); -/** create a new data buffer and copy an existing buffer*/ +/** create a new data buffer and copy an existing buffer +@return a data buffer object with a copy of the data +*/ HELICS_EXPORT HelicsDataBuffer helicsDataBufferClone(HelicsDataBuffer data); -/** convert an integer to serialized bytes*/ -HELICS_EXPORT int32_t helicsIntegerToBytes(int64_t value, HelicsDataBuffer data); +/** convert an integer to serialized bytes in a buffer +* @param data the HelicsDataBuffer to fill +* @param value the value to serialize into the dataBuffer +@return the buffer size after filling +*/ +HELICS_EXPORT int32_t helicsDataBufferFillFromInteger(HelicsDataBuffer data, int64_t value); -/** convert a double to serialized bytes*/ -HELICS_EXPORT int32_t helicsDoubleToBytes(double value, HelicsDataBuffer data); +/** convert a double to serialized bytesin a buffer +* @param data the HelicsDataBuffer to fill +* @param value the value to serialize into the dataBuffer +@return the buffer size after filling +*/ +HELICS_EXPORT int32_t helicsDataBufferFillFromDouble(HelicsDataBuffer data, double value); -/** convert a string to serialized bytes*/ -HELICS_EXPORT int32_t helicsStringToBytes(const char* value, HelicsDataBuffer data); +/** convert a string to serialized bytesin a buffer +* @param data the HelicsDataBuffer to fill +* @param value the value to serialize into the dataBuffer +@return the buffer size after filling +*/ +HELICS_EXPORT int32_t helicsDataBufferFillFromString(HelicsDataBuffer data, const char* value); -/** convert a raw string (may contain nulls) to serialized bytes*/ -HELICS_EXPORT int32_t helicsRawStringToBytes(const char* str, int stringSize, HelicsDataBuffer data); +/** convert a raw string (may contain nulls) to serialized bytesin a buffer +* @param data the HelicsDataBuffer to fill +* @param value the value to serialize into the dataBuffer +@return the buffer size after filling +*/ +HELICS_EXPORT int32_t helicsDataBufferFillFromRawString(HelicsDataBuffer data, const char* str, int stringSize); -/** convert a bool to serialized bytes*/ -HELICS_EXPORT int32_t helicsBooleanToBytes(HelicsBool value, HelicsDataBuffer data); +/** convert a bool to serialized bytesin a buffer +* @param data the HelicsDataBuffer to fill +* @param value the value to serialize into the dataBuffer +@return the buffer size after filling +*/ +HELICS_EXPORT int32_t helicsDataBufferFillFromBoolean(HelicsDataBuffer data, HelicsBool value); -/** convert a char to serialized bytes*/ -HELICS_EXPORT int32_t helicsCharToBytes(char value, HelicsDataBuffer data); +/** convert a char to serialized bytesin a buffer +* @param data the HelicsDataBuffer to fill +* @param value the value to serialize into the dataBuffer +@return the buffer size after filling +*/ +HELICS_EXPORT int32_t helicsDataBufferFillFromChar(HelicsDataBuffer data, char value); -/** convert a time to serialized bytes*/ -HELICS_EXPORT int32_t helicsTimeToBytes(HelicsTime value, HelicsDataBuffer data); +/** convert a time to serialized bytesin a buffer +* @param data the HelicsDataBuffer to fill +* @param value the value to serialize into the dataBuffer +@return the buffer size after filling +*/ +HELICS_EXPORT int32_t helicsDataBufferFillFromTime(HelicsDataBuffer data, HelicsTime value); -/** convert a complex pair to serialized bytes*/ -HELICS_EXPORT int32_t helicsComplexToBytes(double real, double imag, HelicsDataBuffer data); +/** convert a complex pair to serialized bytesin a buffer +* @param data the HelicsDataBuffer to fill +* @param value the value to serialize into the dataBuffer +@return the buffer size after filling +*/ +HELICS_EXPORT int32_t helicsDataBufferFillFromComplex(HelicsDataBuffer data, double real, double imag); -/** convert a complex object to serialized bytes*/ -HELICS_EXPORT int32_t helicsComplexObjectToBytes(HelicsComplex value, HelicsDataBuffer data); +/** convert a complex object to serialized bytesin a buffer +* @param data the HelicsDataBuffer to fill +* @param value the value to serialize into the dataBuffer +@return the buffer size after filling +*/ +HELICS_EXPORT int32_t helicsDataBufferFillFromComplexObject(HelicsDataBuffer data, HelicsComplex value); -/** convert a real vector to serialized bytes*/ -HELICS_EXPORT int32_t helicsVectorToBytes(const double* value, int dataSize, HelicsDataBuffer data); +/** convert a real vector to serialized bytesin a buffer +* @param data the HelicsDataBuffer to fill +* @param value the value to serialize into the dataBuffer +@return the buffer size after filling +*/ +HELICS_EXPORT int32_t helicsDataBufferFillFromVector(HelicsDataBuffer data, const double* value, int dataSize); -/** convert a named point to serialized bytes*/ -HELICS_EXPORT int32_t helicsNamedPointToBytes(const char* name, double value, HelicsDataBuffer data); +/** convert a named point to serialized bytesin a buffer +* @param data the HelicsDataBuffer to fill +* @param value the value to serialize into the dataBuffer +@return the buffer size after filling +*/ +HELICS_EXPORT int32_t helicsDataBufferFillFromNamedPoint(HelicsDataBuffer data, const char* name, double value); -/** convert a complex vector to serialized bytes*/ -HELICS_EXPORT int32_t helicsComplexVectorToBytes(const double* value, int dataSize, HelicsDataBuffer data); +/** convert a complex vector to serialized bytesin a buffer +* @param data the HelicsDataBuffer to fill +* @param value the value to serialize into the dataBuffer +@return the buffer size after filling +*/ +HELICS_EXPORT int32_t helicsDataBufferFillFromComplexVector(HelicsDataBuffer data, const double* value, int dataSize); /** extract the data type from the data buffer, if the type isn't recognized UNKNOWN is returned*/ HELICS_EXPORT int helicsDataBufferType(HelicsDataBuffer data); diff --git a/src/helics/shared_api_library/helicsExport.cpp b/src/helics/shared_api_library/helicsExport.cpp index c7f83883a0..8a3441e4c4 100644 --- a/src/helics/shared_api_library/helicsExport.cpp +++ b/src/helics/shared_api_library/helicsExport.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -45,7 +45,7 @@ const char* helicsGetCompilerVersion(void) const char* helicsGetSystemInfo(void) { - static const std::string systemInfo{helics::systemInfo()}; + static const std::string systemInfo{helics::core::systemInfo()}; return systemInfo.c_str(); } @@ -102,17 +102,17 @@ static void signalHandlerThreadedNoExit(int signum) void helicsLoadSignalHandler() { - signal(SIGINT, signalHandler); + static_cast(signal(SIGINT, signalHandler)); } void helicsLoadThreadedSignalHandler() { - signal(SIGINT, signalHandlerThreaded); + static_cast(signal(SIGINT, signalHandlerThreaded)); } void helicsClearSignalHandler() { - signal(SIGINT, SIG_DFL); + static_cast(signal(SIGINT, SIG_DFL)); } static HelicsBool (*keyHandler)(int) = nullptr; @@ -166,9 +166,9 @@ void helicsLoadSignalHandlerCallback(HelicsBool (*handler)(int), HelicsBool useS keyHandler = handler; if (handler != nullptr) { if (useSeparateThread != HELICS_FALSE) { - signal(SIGINT, signalHandlerThreadedCallback); + static_cast(signal(SIGINT, signalHandlerThreadedCallback)); } else { - signal(SIGINT, signalHandlerCallback); + static_cast(signal(SIGINT, signalHandlerCallback)); } } else { @@ -185,16 +185,16 @@ void helicsLoadSignalHandlerCallbackNoExit(HelicsBool (*handler)(int), HelicsBoo keyHandler = handler; if (handler != nullptr) { if (useSeparateThread != HELICS_FALSE) { - signal(SIGINT, signalHandlerThreadedCallbackNoExit); + static_cast(signal(SIGINT, signalHandlerThreadedCallbackNoExit)); } else { - signal(SIGINT, signalHandlerCallbackNoExit); + static_cast(signal(SIGINT, signalHandlerCallbackNoExit)); } } else { if (useSeparateThread != HELICS_FALSE) { - signal(SIGINT, signalHandlerThreadedNoExit); + static_cast(signal(SIGINT, signalHandlerThreadedNoExit)); } else { - signal(SIGINT, signalHandlerNoExit); + static_cast(signal(SIGINT, signalHandlerNoExit)); } } } @@ -234,7 +234,7 @@ void helicsErrorHandler(HelicsError* err) noexcept try { try { // this is intended to be a single '=' - if (std::exception_ptr eptr = std::current_exception()) { + if (const std::exception_ptr eptr = std::current_exception()) { std::rethrow_exception(eptr); } else { // LCOV_EXCL_START @@ -364,9 +364,9 @@ HelicsCore helicsCreateCore(const char* type, const char* name, const char* init return nullptr; } - helics::CoreType ct = (type != nullptr) ? helics::core::coreTypeFromString(type) : helics::CoreType::DEFAULT; + const helics::CoreType coretype = (type != nullptr) ? helics::core::coreTypeFromString(type) : helics::CoreType::DEFAULT; - if (ct == helics::CoreType::UNRECOGNIZED) { + if (coretype == helics::CoreType::UNRECOGNIZED) { if (err != nullptr) { err->error_code = HELICS_ERROR_INVALID_ARGUMENT; err->message = getMasterHolder()->addErrorString(std::string("core type ") + type + " is not recognized"); @@ -378,9 +378,9 @@ HelicsCore helicsCreateCore(const char* type, const char* name, const char* init core->valid = gCoreValidationIdentifier; auto nstring = AS_STRING_VIEW(name); if (nstring.empty()) { - core->coreptr = helics::CoreFactory::create(ct, AS_STRING_VIEW(initString)); + core->coreptr = helics::CoreFactory::create(coretype, AS_STRING_VIEW(initString)); } else { - core->coreptr = helics::CoreFactory::FindOrCreate(ct, nstring, AS_STRING_VIEW(initString)); + core->coreptr = helics::CoreFactory::FindOrCreate(coretype, nstring, AS_STRING_VIEW(initString)); } auto* retcore = reinterpret_cast(core.get()); @@ -398,9 +398,9 @@ HelicsCore helicsCreateCoreFromArgs(const char* type, const char* name, int argc if ((err != nullptr) && (err->error_code != 0)) { return nullptr; } - helics::CoreType ct = (type != nullptr) ? helics::core::coreTypeFromString(type) : helics::CoreType::DEFAULT; + const helics::CoreType coretype = (type != nullptr) ? helics::core::coreTypeFromString(type) : helics::CoreType::DEFAULT; - if (ct == helics::CoreType::UNRECOGNIZED) { + if (coretype == helics::CoreType::UNRECOGNIZED) { if (err != nullptr) { err->error_code = HELICS_ERROR_INVALID_ARGUMENT; err->message = getMasterHolder()->addErrorString(std::string("core type ") + type + " is not recognized"); @@ -415,7 +415,7 @@ HelicsCore helicsCreateCoreFromArgs(const char* type, const char* name, int argc for (int ii = argc - 1; ii > 0; ii--) { args.emplace_back(argv[ii]); } - core->coreptr = helics::CoreFactory::FindOrCreate(ct, AS_STRING_VIEW(name), args); + core->coreptr = helics::CoreFactory::FindOrCreate(coretype, AS_STRING_VIEW(name), args); auto* retcore = reinterpret_cast(core.get()); getMasterHolder()->addCore(std::move(core)); @@ -463,9 +463,9 @@ HelicsBroker helicsCreateBroker(const char* type, const char* name, const char* if ((err != nullptr) && (err->error_code != 0)) { return nullptr; } - helics::CoreType ct = (type != nullptr) ? helics::core::coreTypeFromString(type) : helics::CoreType::DEFAULT; + const helics::CoreType coretype = (type != nullptr) ? helics::core::coreTypeFromString(type) : helics::CoreType::DEFAULT; - if (ct == helics::CoreType::UNRECOGNIZED) { + if (coretype == helics::CoreType::UNRECOGNIZED) { if (err != nullptr) { err->error_code = HELICS_ERROR_INVALID_ARGUMENT; err->message = getMasterHolder()->addErrorString(std::string("core type ") + type + " is not recognized"); @@ -475,7 +475,7 @@ HelicsBroker helicsCreateBroker(const char* type, const char* name, const char* auto broker = std::make_unique(); broker->valid = gBrokerValidationIdentifier; try { - broker->brokerptr = helics::BrokerFactory::create(ct, AS_STRING_VIEW(name), AS_STRING_VIEW(initString)); + broker->brokerptr = helics::BrokerFactory::create(coretype, AS_STRING_VIEW(name), AS_STRING_VIEW(initString)); auto* retbroker = reinterpret_cast(broker.get()); getMasterHolder()->addBroker(std::move(broker)); return retbroker; @@ -491,9 +491,9 @@ HelicsBroker helicsCreateBrokerFromArgs(const char* type, const char* name, int if ((err != nullptr) && (err->error_code != 0)) { return nullptr; } - helics::CoreType ct = (type != nullptr) ? helics::core::coreTypeFromString(type) : helics::CoreType::DEFAULT; + const helics::CoreType coretype = (type != nullptr) ? helics::core::coreTypeFromString(type) : helics::CoreType::DEFAULT; - if (ct == helics::CoreType::UNRECOGNIZED) { + if (coretype == helics::CoreType::UNRECOGNIZED) { if (err != nullptr) { err->error_code = HELICS_ERROR_INVALID_ARGUMENT; err->message = getMasterHolder()->addErrorString(std::string("core type ") + type + " is not recognized"); @@ -508,7 +508,7 @@ HelicsBroker helicsCreateBrokerFromArgs(const char* type, const char* name, int for (int ii = argc - 1; ii > 0; ii--) { args.emplace_back(argv[ii]); } - broker->brokerptr = helics::BrokerFactory::create(ct, AS_STRING_VIEW(name), args); + broker->brokerptr = helics::BrokerFactory::create(coretype, AS_STRING_VIEW(name), args); auto* retbroker = reinterpret_cast(broker.get()); getMasterHolder()->addBroker(std::move(broker)); return retbroker; @@ -568,15 +568,15 @@ void helicsBrokerDataLink(HelicsBroker broker, const char* source, const char* t void helicsCoreDataLink(HelicsCore core, const char* source, const char* target, HelicsError* err) { - auto* cr = getCore(core, err); - if (cr == nullptr) { + auto* cppcore = getCore(core, err); + if (cppcore == nullptr) { return; } if ((source == nullptr) || (target == nullptr)) { assignError(err, HELICS_ERROR_INVALID_ARGUMENT, invalidDataLinkString); return; } - cr->dataLink(source, target); + cppcore->dataLink(source, target); } static constexpr char invalidGlobalString[] = "Global name cannot be null"; @@ -599,8 +599,8 @@ static constexpr char invalidAliasName[] = "Alias cannot be empty"; void helicsCoreAddAlias(HelicsCore core, const char* interfaceName, const char* alias, HelicsError* err) { - auto* cr = getCore(core, err); - if (cr == nullptr) { + auto* cppcore = getCore(core, err); + if (cppcore == nullptr) { return; } if (interfaceName == nullptr || interfaceName[0] == '\0') { @@ -612,7 +612,7 @@ void helicsCoreAddAlias(HelicsCore core, const char* interfaceName, const char* return; } try { - cr->addAlias(interfaceName, alias); + cppcore->addAlias(interfaceName, alias); } // LCOV_EXCL_START catch (...) { @@ -701,11 +701,11 @@ void helicsBrokerGlobalError(HelicsBroker broker, int errorCode, const char* err void helicsCoreGlobalError(HelicsCore core, int errorCode, const char* errorString, HelicsError* err) { - auto* cr = getCore(core, err); - if (cr == nullptr) { + auto* cppcore = getCore(core, err); + if (cppcore == nullptr) { return; } - cr->globalError(helics::gLocalCoreId, errorCode, AS_STRING_VIEW(errorString)); + cppcore->globalError(helics::gLocalCoreId, errorCode, AS_STRING_VIEW(errorString)); } void helicsBrokerAddSourceFilterToEndpoint(HelicsBroker broker, const char* filter, const char* endpoint, HelicsError* err) @@ -750,38 +750,38 @@ void helicsBrokerMakeConnections(HelicsBroker broker, const char* file, HelicsEr void helicsCoreAddSourceFilterToEndpoint(HelicsCore core, const char* filter, const char* endpoint, HelicsError* err) { - auto* cr = getCore(core, err); - if (cr == nullptr) { + auto* cppcore = getCore(core, err); + if (cppcore == nullptr) { return; } if ((filter == nullptr) || (endpoint == nullptr)) { assignError(err, HELICS_ERROR_INVALID_ARGUMENT, invalidDataLinkString); return; } - cr->addSourceFilterToEndpoint(filter, endpoint); + cppcore->addSourceFilterToEndpoint(filter, endpoint); } void helicsCoreAddDestinationFilterToEndpoint(HelicsCore core, const char* filter, const char* endpoint, HelicsError* err) { - auto* cr = getCore(core, err); - if (cr == nullptr) { + auto* cppcore = getCore(core, err); + if (cppcore == nullptr) { return; } if ((filter == nullptr) || (endpoint == nullptr)) { assignError(err, HELICS_ERROR_INVALID_ARGUMENT, invalidDataLinkString); return; } - cr->addDestinationFilterToEndpoint(filter, endpoint); + cppcore->addDestinationFilterToEndpoint(filter, endpoint); } void helicsCoreMakeConnections(HelicsCore core, const char* file, HelicsError* err) { - auto* cr = getCore(core, err); - if (cr == nullptr) { + auto* cppcore = getCore(core, err); + if (cppcore == nullptr) { return; } try { - cr->makeConnections(AS_STRING(file)); + cppcore->makeConnections(AS_STRING(file)); } catch (...) { helicsErrorHandler(err); @@ -790,17 +790,17 @@ void helicsCoreMakeConnections(HelicsCore core, const char* file, HelicsError* e HelicsBool helicsCoreIsConnected(HelicsCore core) { - auto* cr = getCore(core, nullptr); - if (cr == nullptr) { + auto* cppcore = getCore(core, nullptr); + if (cppcore == nullptr) { return HELICS_FALSE; } - return (cr->isConnected()) ? HELICS_TRUE : HELICS_FALSE; + return (cppcore->isConnected()) ? HELICS_TRUE : HELICS_FALSE; } void helicsCoreSetGlobal(HelicsCore core, const char* valueName, const char* value, HelicsError* err) { - auto* cr = getCore(core, err); - if (cr == nullptr) { + auto* cppcore = getCore(core, err); + if (cppcore == nullptr) { return; } if (valueName == nullptr) { @@ -808,7 +808,7 @@ void helicsCoreSetGlobal(HelicsCore core, const char* valueName, const char* val return; } try { - cr->setGlobal(valueName, AS_STRING_VIEW(value)); + cppcore->setGlobal(valueName, AS_STRING_VIEW(value)); } // LCOV_EXCL_START catch (...) { @@ -819,12 +819,12 @@ void helicsCoreSetGlobal(HelicsCore core, const char* valueName, const char* val void helicsCoreSendCommand(HelicsCore core, const char* target, const char* command, HelicsError* err) { - auto* cr = getCore(core, err); - if (cr == nullptr) { + auto* cppcore = getCore(core, err); + if (cppcore == nullptr) { return; } try { - cr->sendCommand(AS_STRING_VIEW(target), AS_STRING_VIEW(command), std::string_view{}, HELICS_SEQUENCING_MODE_FAST); + cppcore->sendCommand(AS_STRING_VIEW(target), AS_STRING_VIEW(command), std::string_view{}, HELICS_SEQUENCING_MODE_FAST); } // LCOV_EXCL_START catch (...) { @@ -835,12 +835,12 @@ void helicsCoreSendCommand(HelicsCore core, const char* target, const char* comm void helicsCoreSendOrderedCommand(HelicsCore core, const char* target, const char* command, HelicsError* err) { - auto* cr = getCore(core, err); - if (cr == nullptr) { + auto* cppcore = getCore(core, err); + if (cppcore == nullptr) { return; } try { - cr->sendCommand(AS_STRING_VIEW(target), AS_STRING_VIEW(command), std::string{}, HELICS_SEQUENCING_MODE_ORDERED); + cppcore->sendCommand(AS_STRING_VIEW(target), AS_STRING_VIEW(command), std::string{}, HELICS_SEQUENCING_MODE_ORDERED); } // LCOV_EXCL_START catch (...) { @@ -851,12 +851,12 @@ void helicsCoreSendOrderedCommand(HelicsCore core, const char* target, const cha void helicsCoreSetLogFile(HelicsCore core, const char* logFileName, HelicsError* err) { - auto* cr = getCore(core, err); - if (cr == nullptr) { + auto* cppcore = getCore(core, err); + if (cppcore == nullptr) { return; } try { - cr->setLogFile(AS_STRING_VIEW(logFileName)); + cppcore->setLogFile(AS_STRING_VIEW(logFileName)); } // LCOV_EXCL_START catch (...) { @@ -877,12 +877,12 @@ const char* helicsBrokerGetIdentifier(HelicsBroker broker) const char* helicsCoreGetIdentifier(HelicsCore core) { - auto* cr = getCore(core, nullptr); - if (cr == nullptr) { + auto* cppcore = getCore(core, nullptr); + if (cppcore == nullptr) { return nullstrPtr; } - const auto& ident = cr->getIdentifier(); + const auto& ident = cppcore->getIdentifier(); return ident.c_str(); } @@ -899,23 +899,23 @@ const char* helicsBrokerGetAddress(HelicsBroker broker) const char* helicsCoreGetAddress(HelicsCore core) { - auto* cr = getCore(core, nullptr); - if (cr == nullptr) { + auto* cppcore = getCore(core, nullptr); + if (cppcore == nullptr) { return nullstrPtr; } - const auto& add = cr->getAddress(); + const auto& add = cppcore->getAddress(); return add.c_str(); } void helicsCoreSetReadyToInit(HelicsCore core, HelicsError* err) { - auto* cr = getCore(core, err); - if (cr == nullptr) { + auto* cppcore = getCore(core, err); + if (cppcore == nullptr) { return; } try { - cr->setCoreReadyToInit(); + cppcore->setCoreReadyToInit(); } // LCOV_EXCL_START catch (...) { @@ -926,13 +926,13 @@ void helicsCoreSetReadyToInit(HelicsCore core, HelicsError* err) HelicsBool helicsCoreConnect(HelicsCore core, HelicsError* err) { - auto* cr = getCore(core, err); - if (cr == nullptr) { + auto* cppcore = getCore(core, err); + if (cppcore == nullptr) { return HELICS_FALSE; } try { - return (cr->connect()) ? HELICS_TRUE : HELICS_FALSE; + return (cppcore->connect()) ? HELICS_TRUE : HELICS_FALSE; } // LCOV_EXCL_START catch (...) { @@ -944,13 +944,13 @@ HelicsBool helicsCoreConnect(HelicsCore core, HelicsError* err) void helicsCoreDisconnect(HelicsCore core, HelicsError* err) { - auto* cr = getCore(core, err); - if (cr == nullptr) { + auto* cppcore = getCore(core, err); + if (cppcore == nullptr) { return; } try { - cr->disconnect(); + cppcore->disconnect(); } // LCOV_EXCL_START catch (...) { @@ -966,7 +966,7 @@ HelicsBool helicsBrokerWaitForDisconnect(HelicsBroker broker, int msToWait, Heli return HELICS_TRUE; } try { - bool res = brk->waitForDisconnect(std::chrono::milliseconds(msToWait)); + const bool res = brk->waitForDisconnect(std::chrono::milliseconds(msToWait)); return res ? HELICS_TRUE : HELICS_FALSE; } // LCOV_EXCL_START @@ -979,12 +979,12 @@ HelicsBool helicsBrokerWaitForDisconnect(HelicsBroker broker, int msToWait, Heli HelicsBool helicsCoreWaitForDisconnect(HelicsCore core, int msToWait, HelicsError* err) { - auto* cr = getCore(core, err); - if (cr == nullptr) { + auto* cppcore = getCore(core, err); + if (cppcore == nullptr) { return HELICS_TRUE; } try { - bool res = cr->waitForDisconnect(std::chrono::milliseconds(msToWait)); + const bool res = cppcore->waitForDisconnect(std::chrono::milliseconds(msToWait)); return res ? HELICS_TRUE : HELICS_FALSE; } // LCOV_EXCL_START @@ -1090,9 +1090,9 @@ void helicsCloseLibrary(void) void helicsAbort(int errorCode, const char* message) { - auto v = getMasterHolder(); - if (v) { - v->abortAll(errorCode, message); + auto holder = getMasterHolder(); + if (holder) { + holder->abortAll(errorCode, message); } } @@ -1421,13 +1421,13 @@ void MasterObjectHolder::clearBroker(int index) void MasterObjectHolder::clearCore(int index) { - auto core = cores.lock(); - if ((index < static_cast(core->size())) && (index >= 0)) { - (*core)[index]->valid = 0; - (*core)[index] = nullptr; - if (core->size() > 10) { - if (std::none_of(core->begin(), core->end(), [](const auto& cr) { return static_cast(cr); })) { - core->clear(); + auto coreList = cores.lock(); + if ((index < static_cast(coreList->size())) && (index >= 0)) { + (*coreList)[index]->valid = 0; + (*coreList)[index] = nullptr; + if (coreList->size() > 10) { + if (std::none_of(coreList->begin(), coreList->end(), [](const auto& core) { return static_cast(core); })) { + coreList->clear(); } } } @@ -1435,13 +1435,13 @@ void MasterObjectHolder::clearCore(int index) void MasterObjectHolder::clearFed(int index) { - auto fed = feds.lock(); - if ((index < static_cast(fed->size())) && (index >= 0)) { - (*fed)[index]->valid = 0; - (*fed)[index] = nullptr; - if (fed->size() > 10) { - if (std::none_of(fed->begin(), fed->end(), [](const auto& fd) { return static_cast(fd); })) { - fed->clear(); + auto fedList = feds.lock(); + if ((index < static_cast(fedList->size())) && (index >= 0)) { + (*fedList)[index]->valid = 0; + (*fedList)[index] = nullptr; + if (fedList->size() > 10) { + if (std::none_of(fedList->begin(), fedList->end(), [](const auto& federate) { return static_cast(federate); })) { + fedList->clear(); } } } @@ -1479,10 +1479,10 @@ void MasterObjectHolder::deleteAll() } { auto coreHandle = cores.lock(); - for (auto& cr : coreHandle) { - if ((cr) && (cr->coreptr)) { - cr->valid = 0; - cr->coreptr->disconnect(); + for (auto& core : coreHandle) { + if ((core) && (core->coreptr)) { + core->valid = 0; + core->coreptr->disconnect(); } } coreHandle->clear(); @@ -1502,16 +1502,16 @@ void MasterObjectHolder::deleteAll() const char* MasterObjectHolder::addErrorString(std::string_view newError) { - auto estring = errorStrings.lock(); - estring->emplace_back(newError); - auto& v = estring->back(); - return v.c_str(); + auto estrings = errorStrings.lock(); + estrings->emplace_back(newError); + auto& estring = estrings->back(); + return estring.c_str(); } std::shared_ptr getMasterHolder() { static auto instance = std::make_shared(); - static gmlc::concurrency::TripWireTrigger tripTriggerholder; + static const gmlc::concurrency::TripWireTrigger tripTriggerholder; return instance; } @@ -1519,8 +1519,8 @@ gmlc::concurrency::TripWireTrigger tripTrigger; void clearAllObjects() { - auto v = getMasterHolder(); - if (v) { - v->deleteAll(); + auto holder = getMasterHolder(); + if (holder) { + holder->deleteAll(); } } diff --git a/src/helics/shared_api_library/internal/api_objects.h b/src/helics/shared_api_library/internal/api_objects.h index f6ae3cbcbc..6db3f6372e 100644 --- a/src/helics/shared_api_library/internal/api_objects.h +++ b/src/helics/shared_api_library/internal/api_objects.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -212,7 +212,10 @@ std::unique_ptr getMessageUniquePtr(HelicsMessage message, Heli /** create a message object from a message pointer*/ HelicsMessage createAPIMessage(std::unique_ptr& mess); +/** add required information to SmallBuffer and return a HelicsDataBuffer object*/ HelicsDataBuffer createAPIDataBuffer(helics::SmallBuffer& buff); +/** get the small buffer point from a HelicsDataBuffer*/ +helics::SmallBuffer* getBuffer(HelicsDataBuffer data); std::shared_ptr getFedSharedPtr(HelicsFederate fed, HelicsError* err); std::shared_ptr getValueFedSharedPtr(HelicsFederate fed, HelicsError* err); diff --git a/tests/.clang-tidy b/tests/.clang-tidy index e1e71c4b29..6b03817a4d 100644 --- a/tests/.clang-tidy +++ b/tests/.clang-tidy @@ -50,6 +50,369 @@ WarningsAsErrors: " HeaderFilterRegex: "*test.*cpp" +AnalyzeTemporaryDtors: false CheckOptions: + - key: cert-dcl59-cpp.HeaderFileExtensions + value: h,hh,hpp,hxx + - key: cert-err61-cpp.CheckThrowTemporaries + value: "1" + - key: cert-oop11-cpp.IncludeStyle + value: llvm + - key: cert-oop11-cpp.UseCERTSemantics + value: "1" + - key: cppcoreguidelines-pro-bounds-constant-array-index.GslHeader + value: "" + - key: cppcoreguidelines-pro-bounds-constant-array-index.IncludeStyle + value: "0" + - key: cppcoreguidelines-pro-type-member-init.IgnoreArrays + value: "0" + - key: google-build-namespaces.HeaderFileExtensions + value: h,hh,hpp,hxx + - key: google-global-names-in-headers.HeaderFileExtensions + value: h - key: google-readability-braces-around-statements.ShortStatementLines - value: "3" + value: "1" + - key: google-readability-function-size.BranchThreshold + value: "4294967295" + - key: google-readability-function-size.LineThreshold + value: "4294967295" + - key: google-readability-function-size.StatementThreshold + value: "800" + - key: google-readability-namespace-comments.ShortNamespaceLines + value: "10" + - key: google-readability-namespace-comments.SpacesBeforeComments + value: "2" + - key: google-runtime-int.SignedTypePrefix + value: int + - key: google-runtime-int.TypeSuffix + value: "" + - key: google-runtime-int.UnsignedTypePrefix + value: uint + - key: llvm-namespace-comment.ShortNamespaceLines + value: "1" + - key: llvm-namespace-comment.SpacesBeforeComments + value: "1" + - key: misc-assert-side-effect.AssertMacros + value: assert + - key: misc-assert-side-effect.CheckFunctionCalls + value: "0" + - key: misc-dangling-handle.HandleClasses + value: "std::basic_string_view;std::experimental::basic_string_view" + - key: misc-definitions-in-headers.HeaderFileExtensions + value: ",h,hh,hpp,hxx" + - key: misc-definitions-in-headers.UseHeaderFileExtension + value: "1" + - key: misc-misplaced-widening-cast.CheckImplicitCasts + value: "1" + - key: misc-move-constructor-init.IncludeStyle + value: llvm + - key: misc-move-constructor-init.UseCERTSemantics + value: "0" + - key: misc-sizeof-expression.WarnOnSizeOfCompareToConstant + value: "1" + - key: misc-sizeof-expression.WarnOnSizeOfConstant + value: "1" + - key: misc-sizeof-expression.WarnOnSizeOfThis + value: "1" + - key: misc-string-constructor.LargeLengthThreshold + value: "8388608" + - key: misc-string-constructor.WarnOnLargeLength + value: "1" + - key: misc-suspicious-missing-comma.MaxConcatenatedTokens + value: "5" + - key: misc-suspicious-missing-comma.RatioThreshold + value: "0.200000" + - key: misc-suspicious-missing-comma.SizeThreshold + value: "5" + - key: misc-suspicious-string-compare.StringCompareLikeFunctions + value: "" + - key: misc-suspicious-string-compare.WarnOnImplicitComparison + value: "1" + - key: misc-suspicious-string-compare.WarnOnLogicalNotComparison + value: "0" + - key: misc-throw-by-value-catch-by-reference.CheckThrowTemporaries + value: "1" + - key: modernize-loop-convert.MaxCopySize + value: "16" + - key: modernize-loop-convert.MinConfidence + value: reasonable + - key: modernize-loop-convert.NamingStyle + value: CamelCase + - key: modernize-pass-by-value.IncludeStyle + value: llvm + - key: modernize-replace-auto-ptr.IncludeStyle + value: llvm + - key: modernize-use-nullptr.NullMacros + value: "NULL" + - key: performance-faster-string-find.StringLikeClasses + value: "std::basic_string" + - key: performance-for-range-copy.WarnOnAllAutoCopies + value: "0" + - key: readability-braces-around-statements.ShortStatementLines + value: "1" + - key: readability-function-size.BranchThreshold + value: "4294967295" + - key: readability-function-size.LineThreshold + value: "4294967295" + - key: readability-function-size.StatementThreshold + value: "800" + - key: readability-identifier-naming.AbstractClassCase + value: CamelCase + - key: readability-identifier-naming.AbstractClassPrefix + value: "" + - key: readability-identifier-naming.AbstractClassSuffix + value: "" + - key: readability-identifier-naming.ClassCase + value: CamelCase + - key: readability-identifier-naming.ClassConstantCase + value: aNy_CasE + - key: readability-identifier-naming.ClassConstantPrefix + value: "" + - key: readability-identifier-naming.ClassConstantSuffix + value: "" + - key: readability-identifier-naming.ClassMemberCase + value: aNy_CasE + - key: readability-identifier-naming.ClassMemberPrefix + value: "" + - key: readability-identifier-naming.ClassMemberSuffix + value: "" + - key: readability-identifier-naming.ClassMethodCase + value: camelBack + - key: readability-identifier-naming.ClassMethodPrefix + value: "" + - key: readability-identifier-naming.ClassMethodSuffix + value: "" + - key: readability-identifier-naming.ClassPrefix + value: "" + - key: readability-identifier-naming.ClassSuffix + value: "" + - key: readability-identifier-naming.ConstantCase + value: aNy_CasE + - key: readability-identifier-naming.ConstantMemberCase + value: aNy_CasE + - key: readability-identifier-naming.ConstantMemberPrefix + value: "" + - key: readability-identifier-naming.ConstantMemberSuffix + value: "" + - key: readability-identifier-naming.ConstantParameterCase + value: aNy_CasE + - key: readability-identifier-naming.ConstantParameterPrefix + value: "" + - key: readability-identifier-naming.ConstantParameterSuffix + value: "" + - key: readability-identifier-naming.ConstantPrefix + value: "" + - key: readability-identifier-naming.ConstantSuffix + value: "" + - key: readability-identifier-naming.ConstexprFunctionCase + value: aNy_CasE + - key: readability-identifier-naming.ConstexprFunctionPrefix + value: "" + - key: readability-identifier-naming.ConstexprFunctionSuffix + value: "" + - key: readability-identifier-naming.ConstexprMethodCase + value: aNy_CasE + - key: readability-identifier-naming.ConstexprMethodPrefix + value: "" + - key: readability-identifier-naming.ConstexprMethodSuffix + value: "" + - key: readability-identifier-naming.ConstexprVariableCase + value: aNy_CasE + - key: readability-identifier-naming.ConstexprVariablePrefix + value: "" + - key: readability-identifier-naming.ConstexprVariableSuffix + value: "" + - key: readability-identifier-naming.EnumCase + value: CamelCase + - key: readability-identifier-naming.EnumConstantCase + value: UPPER_CASE + - key: readability-identifier-naming.EnumConstantPrefix + value: "" + - key: readability-identifier-naming.EnumConstantSuffix + value: "" + - key: readability-identifier-naming.EnumPrefix + value: "" + - key: readability-identifier-naming.EnumSuffix + value: "" + - key: readability-identifier-naming.FunctionCase + value: camelBack + - key: readability-identifier-naming.FunctionPrefix + value: "" + - key: readability-identifier-naming.FunctionSuffix + value: "" + - key: readability-identifier-naming.GlobalConstantCase + value: aNy_CasE + - key: readability-identifier-naming.GlobalConstantPrefix + value: "" + - key: readability-identifier-naming.GlobalConstantSuffix + value: "" + - key: readability-identifier-naming.GlobalFunctionCase + value: aNy_CasE + - key: readability-identifier-naming.GlobalFunctionPrefix + value: "" + - key: readability-identifier-naming.GlobalFunctionSuffix + value: "" + - key: readability-identifier-naming.GlobalVariableCase + value: aNy_CasE + - key: readability-identifier-naming.GlobalVariablePrefix + value: "" + - key: readability-identifier-naming.GlobalVariableSuffix + value: "" + - key: readability-identifier-naming.IgnoreFailedSplit + value: "0" + - key: readability-identifier-naming.InlineNamespaceCase + value: aNy_CasE + - key: readability-identifier-naming.InlineNamespacePrefix + value: "" + - key: readability-identifier-naming.InlineNamespaceSuffix + value: "" + - key: readability-identifier-naming.LocalConstantCase + value: aNy_CasE + - key: readability-identifier-naming.LocalConstantPrefix + value: "" + - key: readability-identifier-naming.LocalConstantSuffix + value: "" + - key: readability-identifier-naming.LocalVariableCase + value: aNy_CasE + - key: readability-identifier-naming.LocalVariablePrefix + value: "" + - key: readability-identifier-naming.LocalVariableSuffix + value: "" + - key: readability-identifier-naming.MemberCase + value: aNy_CasE + - key: readability-identifier-naming.MemberPrefix + value: "" + - key: readability-identifier-naming.MemberSuffix + value: "" + - key: readability-identifier-naming.MethodCase + value: aNy_CasE + - key: readability-identifier-naming.MethodPrefix + value: "" + - key: readability-identifier-naming.MethodSuffix + value: "" + - key: readability-identifier-naming.NamespaceCase + value: lower_case + - key: readability-identifier-naming.NamespacePrefix + value: "" + - key: readability-identifier-naming.NamespaceSuffix + value: "" + - key: readability-identifier-naming.ParameterCase + value: aNy_CasE + - key: readability-identifier-naming.ParameterPackCase + value: aNy_CasE + - key: readability-identifier-naming.ParameterPackPrefix + value: "" + - key: readability-identifier-naming.ParameterPackSuffix + value: "" + - key: readability-identifier-naming.ParameterPrefix + value: "" + - key: readability-identifier-naming.ParameterSuffix + value: "" + - key: readability-identifier-naming.PrivateMemberCase + value: aNy_CasE + - key: readability-identifier-naming.PrivateMemberPrefix + value: "" + - key: readability-identifier-naming.PrivateMemberSuffix + value: "" + - key: readability-identifier-naming.PrivateMethodCase + value: aNy_CasE + - key: readability-identifier-naming.PrivateMethodPrefix + value: "" + - key: readability-identifier-naming.PrivateMethodSuffix + value: "" + - key: readability-identifier-naming.ProtectedMemberCase + value: aNy_CasE + - key: readability-identifier-naming.ProtectedMemberPrefix + value: "" + - key: readability-identifier-naming.ProtectedMemberSuffix + value: "" + - key: readability-identifier-naming.ProtectedMethodCase + value: aNy_CasE + - key: readability-identifier-naming.ProtectedMethodPrefix + value: "" + - key: readability-identifier-naming.ProtectedMethodSuffix + value: "" + - key: readability-identifier-naming.PublicMemberCase + value: aNy_CasE + - key: readability-identifier-naming.PublicMemberPrefix + value: "" + - key: readability-identifier-naming.PublicMemberSuffix + value: "" + - key: readability-identifier-naming.PublicMethodCase + value: aNy_CasE + - key: readability-identifier-naming.PublicMethodPrefix + value: "" + - key: readability-identifier-naming.PublicMethodSuffix + value: "" + - key: readability-identifier-naming.StaticConstantCase + value: aNy_CasE + - key: readability-identifier-naming.StaticConstantPrefix + value: "" + - key: readability-identifier-naming.StaticConstantSuffix + value: "" + - key: readability-identifier-naming.StaticVariableCase + value: aNy_CasE + - key: readability-identifier-naming.StaticVariablePrefix + value: "" + - key: readability-identifier-naming.StaticVariableSuffix + value: "" + - key: readability-identifier-naming.StructCase + value: aNy_CasE + - key: readability-identifier-naming.StructPrefix + value: "" + - key: readability-identifier-naming.StructSuffix + value: "" + - key: readability-identifier-naming.TemplateParameterCase + value: aNy_CasE + - key: readability-identifier-naming.TemplateParameterPrefix + value: "" + - key: readability-identifier-naming.TemplateParameterSuffix + value: "" + - key: readability-identifier-naming.TemplateTemplateParameterCase + value: aNy_CasE + - key: readability-identifier-naming.TemplateTemplateParameterPrefix + value: "" + - key: readability-identifier-naming.TemplateTemplateParameterSuffix + value: "" + - key: readability-identifier-naming.TypeTemplateParameterCase + value: aNy_CasE + - key: readability-identifier-naming.TypeTemplateParameterPrefix + value: "" + - key: readability-identifier-naming.TypeTemplateParameterSuffix + value: "" + - key: readability-identifier-naming.TypedefCase + value: aNy_CasE + - key: readability-identifier-naming.TypedefPrefix + value: "" + - key: readability-identifier-naming.TypedefSuffix + value: "" + - key: readability-identifier-naming.UnionCase + value: aNy_CasE + - key: readability-identifier-naming.UnionPrefix + value: "" + - key: readability-identifier-naming.UnionSuffix + value: "" + - key: readability-identifier-naming.ValueTemplateParameterCase + value: aNy_CasE + - key: readability-identifier-naming.ValueTemplateParameterPrefix + value: "" + - key: readability-identifier-naming.ValueTemplateParameterSuffix + value: "" + - key: readability-identifier-naming.VariableCase + value: aNy_CasE + - key: readability-identifier-naming.VariablePrefix + value: "" + - key: readability-identifier-naming.VariableSuffix + value: "" + - key: readability-identifier-naming.VirtualMethodCase + value: aNy_CasE + - key: readability-identifier-naming.VirtualMethodPrefix + value: "" + - key: readability-identifier-naming.VirtualMethodSuffix + value: "" + - key: readability-function-cognitive-complexity.Threshold + value: 100 + - key: readability-simplify-boolean-expr.ChainedConditionalAssignment + value: "0" + - key: readability-simplify-boolean-expr.ChainedConditionalReturn + value: "0" diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index c1c6797b20..27eb2293d5 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1,5 +1,5 @@ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Copyright (c) 2017-2023, Battelle Memorial Institute; Lawrence Livermore +# Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore # National Security, LLC; Alliance for Sustainable Energy, LLC. # See the top-level NOTICE for additional details. # All rights reserved. diff --git a/tests/helics/CMakeLists.txt b/tests/helics/CMakeLists.txt index 7db92ff980..07a2c511cf 100644 --- a/tests/helics/CMakeLists.txt +++ b/tests/helics/CMakeLists.txt @@ -1,5 +1,5 @@ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Copyright (c) 2017-2023, Battelle Memorial Institute; Lawrence Livermore +# Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore # National Security, LLC; Alliance for Sustainable Energy, LLC. # See the top-level NOTICE for additional details. # All rights reserved. diff --git a/tests/helics/application_api/CMakeLists.txt b/tests/helics/application_api/CMakeLists.txt index 7cae0f4b8f..17013b72f4 100644 --- a/tests/helics/application_api/CMakeLists.txt +++ b/tests/helics/application_api/CMakeLists.txt @@ -1,5 +1,5 @@ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Copyright (c) 2017-2023, Battelle Memorial Institute; Lawrence Livermore +# Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore # National Security, LLC; Alliance for Sustainable Energy, LLC. # See the top-level NOTICE for additional details. # All rights reserved. diff --git a/tests/helics/application_api/CallbackFederateTests.cpp b/tests/helics/application_api/CallbackFederateTests.cpp index 9a8cd66364..02410ded41 100644 --- a/tests/helics/application_api/CallbackFederateTests.cpp +++ b/tests/helics/application_api/CallbackFederateTests.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/tests/helics/application_api/CombinationFederateTests.cpp b/tests/helics/application_api/CombinationFederateTests.cpp index 705b4f5e5a..549b40efcc 100644 --- a/tests/helics/application_api/CombinationFederateTests.cpp +++ b/tests/helics/application_api/CombinationFederateTests.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -294,7 +294,8 @@ INSTANTIATE_TEST_SUITE_P(combofed_tests, testNamer); static constexpr const char* combo_config_files[] = {"example_combo_fed.json", - "example_combo_fed.toml"}; + "example_combo_fed.toml", + "folder with space/example_combo_fed.toml"}; class combofed_file_load_tests: public ::testing::TestWithParam, diff --git a/tests/helics/application_api/DynamicValueFederateTests.cpp b/tests/helics/application_api/DynamicValueFederateTests.cpp index 3b03effb55..e66a9ca23b 100644 --- a/tests/helics/application_api/DynamicValueFederateTests.cpp +++ b/tests/helics/application_api/DynamicValueFederateTests.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -29,10 +29,6 @@ SPDX-License-Identifier: BSD-3-Clause */ class dynFed: public ::testing::Test, public FederateTestFixture {}; -static const auto testNamer = [](const ::testing::TestParamInfo& parameter) { - return std::string(parameter.param); -}; - TEST_F(dynFed, initPubSubs) { SetupTest("test", 1, 1.0); diff --git a/tests/helics/application_api/EndpointLinkingTests.cpp b/tests/helics/application_api/EndpointLinkingTests.cpp index bf21073ad5..2534efc78a 100644 --- a/tests/helics/application_api/EndpointLinkingTests.cpp +++ b/tests/helics/application_api/EndpointLinkingTests.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -21,6 +21,7 @@ SPDX-License-Identifier: BSD-3-Clause #include #include +#include #include /** these test cases test out the message federates @@ -28,10 +29,6 @@ SPDX-License-Identifier: BSD-3-Clause class mfed_tests: public ::testing::Test, public FederateTestFixture {}; /** test simple creation and destruction*/ -static const auto testNamer = [](const ::testing::TestParamInfo& parameter) { - return std::string(parameter.param); -}; - TEST_F(mfed_tests, regex1) { SetupTest("test", 3, 1.0); @@ -491,3 +488,156 @@ TEST_F(mfed_tests, regex_combo_data_sink) mFed2->finalizeComplete(); mFed1->finalizeComplete(); } + +TEST_F(mfed_tests, endpoint_linking) +{ + SetupTest("testA", 1, 1.0); + auto mFed1 = GetFederateAs(0); + + auto& ept1 = mFed1->registerGlobalTargetedEndpoint("source_endpoint"); + auto& ept2 = mFed1->registerGlobalTargetedEndpoint("dest_endpoint"); + helics::CoreApp core(mFed1->getCorePointer()); + core->linkEndpoints("source_endpoint", "dest_endpoint"); + mFed1->enterExecutingMode(); + ept1.send("test message"); + mFed1->requestNextStep(); + EXPECT_TRUE(ept2.hasMessage()); + auto m = ept2.getMessage(); + EXPECT_EQ(m->to_string(), "test message"); + mFed1->finalize(); +} + +TEST_F(mfed_tests, endpoint_linking_dest_unknown) +{ + SetupTest("testA", 1, 1.0); + auto mFed1 = GetFederateAs(0); + helics::CoreApp core(mFed1->getCorePointer()); + auto& ept1 = mFed1->registerGlobalTargetedEndpoint("source_endpoint"); + core->linkEndpoints("source_endpoint", "dest_endpoint"); + auto& ept2 = mFed1->registerGlobalTargetedEndpoint("dest_endpoint"); + + mFed1->enterExecutingMode(); + ept1.send("test message"); + mFed1->requestNextStep(); + EXPECT_TRUE(ept2.hasMessage()); + auto m = ept2.getMessage(); + EXPECT_EQ(m->to_string(), "test message"); + mFed1->finalize(); +} + +TEST_F(mfed_tests, endpoint_linking_source_unknown) +{ + SetupTest("testA", 1, 1.0); + auto mFed1 = GetFederateAs(0); + helics::CoreApp core(mFed1->getCorePointer()); + auto& ept2 = mFed1->registerGlobalTargetedEndpoint("dest_endpoint"); + core->linkEndpoints("source_endpoint", "dest_endpoint"); + + auto& ept1 = mFed1->registerGlobalTargetedEndpoint("source_endpoint"); + mFed1->enterExecutingMode(); + ept1.send("test message"); + mFed1->requestNextStep(); + EXPECT_TRUE(ept2.hasMessage()); + auto m = ept2.getMessage(); + EXPECT_EQ(m->to_string(), "test message"); + mFed1->finalize(); +} + +TEST_F(mfed_tests, endpoint_linking_both_unknown) +{ + SetupTest("testA", 1, 1.0); + auto mFed1 = GetFederateAs(0); + helics::CoreApp core(mFed1->getCorePointer()); + + core->linkEndpoints("source_endpoint", "dest_endpoint"); + auto& ept2 = mFed1->registerGlobalTargetedEndpoint("dest_endpoint"); + + auto& ept1 = mFed1->registerGlobalTargetedEndpoint("source_endpoint"); + mFed1->enterExecutingMode(); + ept1.send("test message"); + mFed1->requestNextStep(); + EXPECT_TRUE(ept2.hasMessage()); + auto m = ept2.getMessage(); + EXPECT_EQ(m->to_string(), "test message"); + mFed1->finalize(); +} + +TEST_F(mfed_tests, endpoint_linking_source_alias) +{ + SetupTest("testA", 1, 1.0); + auto mFed1 = GetFederateAs(0); + helics::CoreApp core(mFed1->getCorePointer()); + + core->linkEndpoints("source", "dest_endpoint"); + auto& ept2 = mFed1->registerGlobalTargetedEndpoint("dest_endpoint"); + + auto& ept1 = mFed1->registerGlobalTargetedEndpoint("source_endpoint"); + core->addAlias("source_endpoint", "source"); + mFed1->enterExecutingMode(); + ept1.send("test message"); + mFed1->requestNextStep(); + EXPECT_TRUE(ept2.hasMessage()); + auto m = ept2.getMessage(); + EXPECT_EQ(m->to_string(), "test message"); + mFed1->finalize(); +} + +TEST_F(mfed_tests, endpoint_linking_dest_alias) +{ + SetupTest("testA", 1, 1.0); + auto mFed1 = GetFederateAs(0); + helics::CoreApp core(mFed1->getCorePointer()); + + core->linkEndpoints("source_endpoint", "dest"); + auto& ept2 = mFed1->registerGlobalTargetedEndpoint("dest_endpoint"); + + auto& ept1 = mFed1->registerGlobalTargetedEndpoint("source_endpoint"); + core->addAlias("dest_endpoint", "dest"); + mFed1->enterExecutingMode(); + ept1.send("test message"); + mFed1->requestNextStep(); + EXPECT_TRUE(ept2.hasMessage()); + auto m = ept2.getMessage(); + EXPECT_EQ(m->to_string(), "test message"); + mFed1->finalize(); +} + +class mfed_permutation_tests: public ::testing::TestWithParam, public FederateTestFixture {}; + +TEST_P(mfed_permutation_tests, endpoint_linking_order_permutations) +{ + SetupTest("testA", 1, 1.0); + auto mFed1 = GetFederateAs(0); + helics::CoreApp core(mFed1->getCorePointer()); + + std::vector> exList(5); + std::vector exOrder(5); + std::iota(exOrder.begin(), exOrder.end(), 0); + + int permutations = GetParam(); + for (int kk = 0; kk < permutations; ++kk) { + std::next_permutation(exOrder.begin(), exOrder.end()); + } + exList[0] = [&mFed1]() { mFed1->registerGlobalTargetedEndpoint("dest_endpoint"); }; + exList[1] = [&mFed1]() { mFed1->registerGlobalTargetedEndpoint("source_endpoint"); }; + exList[2] = [&core]() { core->addAlias("dest_endpoint", "dest"); }; + exList[3] = [&core]() { core->addAlias("source_endpoint", "source"); }; + exList[4] = [&core]() { core->linkEndpoints("source", "dest"); }; + + for (int ii = 0; ii < 5; ++ii) { + exList[exOrder[ii]](); + } + auto& ept2 = mFed1->getEndpoint("dest_endpoint"); + auto& ept1 = mFed1->getEndpoint("source_endpoint"); + mFed1->enterExecutingMode(); + ept1.send("test message"); + mFed1->requestNextStep(); + EXPECT_TRUE(ept2.hasMessage()); + auto m = ept2.getMessage(); + EXPECT_EQ(m->to_string(), "test message"); + mFed1->finalize(); +} + +INSTANTIATE_TEST_SUITE_P(OrderPermutations, + mfed_permutation_tests, + testing::Range(0, 5 * 4 * 3 * 2 * 1)); diff --git a/tests/helics/application_api/FederateInfoTests.cpp b/tests/helics/application_api/FederateInfoTests.cpp index 45175bb7a9..414846ebaa 100644 --- a/tests/helics/application_api/FederateInfoTests.cpp +++ b/tests/helics/application_api/FederateInfoTests.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. @@ -18,9 +18,9 @@ SPDX-License-Identifier: BSD-3-Clause TEST(federateInfo, constructor1) { - helics::FederateInfo f1("--coretype=test --name fi"); - EXPECT_EQ(f1.coreType, helics::CoreType::TEST); - EXPECT_EQ(f1.defName, "fi"); + helics::FederateInfo fedInfo("--coretype=test --name fi"); + EXPECT_EQ(fedInfo.coreType, helics::CoreType::TEST); + EXPECT_EQ(fedInfo.defName, "fi"); } TEST(federateInfo, constructor2) @@ -34,14 +34,14 @@ TEST(federateInfo, constructor2) "realtime,,source_only;autobroker"}; char* argv[7]; for (size_t ii = 0; ii < args.size(); ++ii) { - argv[ii] = &(args[ii][0]); + argv[ii] = args[ii].data(); } - helics::FederateInfo f1(7, argv); - EXPECT_EQ(f1.coreType, helics::CoreType::INPROC); - EXPECT_EQ(f1.defName, "f2"); - EXPECT_TRUE(f1.autobroker); - EXPECT_EQ(f1.flagProps.size(), 2U); + helics::FederateInfo fedInfo(7, argv); + EXPECT_EQ(fedInfo.coreType, helics::CoreType::INPROC); + EXPECT_EQ(fedInfo.defName, "f2"); + EXPECT_TRUE(fedInfo.autobroker); + EXPECT_EQ(fedInfo.flagProps.size(), 2U); } TEST(federateInfo, constructor_error) @@ -50,10 +50,10 @@ TEST(federateInfo, constructor_error) "constructor2", "--name", "f2", "--coretype", "inproc", "--brokerport=hippity_hopity"}; char* argv[6]; for (size_t ii = 0; ii < args.size(); ++ii) { - argv[ii] = &(args[ii][0]); + argv[ii] = args[ii].data(); } - EXPECT_THROW(helics::FederateInfo f1(6, argv), helics::InvalidParameter); + EXPECT_THROW(helics::FederateInfo fedInfo(6, argv), helics::InvalidParameter); } TEST(federateInfo, loadArgs1) @@ -62,45 +62,45 @@ TEST(federateInfo, loadArgs1) "constructor2", "--name", "f2", "--coretype", "zmq", "--flags", "realtime,source_only,17"}; char* argv[7]; for (size_t ii = 0; ii < args.size(); ++ii) { - argv[ii] = &(args[ii][0]); + argv[ii] = args[ii].data(); } - helics::FederateInfo f1; - f1.loadInfoFromArgs(7, argv); - EXPECT_EQ(f1.coreType, helics::CoreType::ZMQ); - EXPECT_EQ(f1.defName, "f2"); - EXPECT_EQ(f1.flagProps.size(), 3U); + helics::FederateInfo fedInfo; + fedInfo.loadInfoFromArgs(7, argv); + EXPECT_EQ(fedInfo.coreType, helics::CoreType::ZMQ); + EXPECT_EQ(fedInfo.defName, "f2"); + EXPECT_EQ(fedInfo.flagProps.size(), 3U); } TEST(federateInfo, constructor3) { - helics::FederateInfo f1{ + helics::FederateInfo fedInfo{ "--name f3 --coretype ipc --flags realtime;source_only,-buffer_data --port=5000"}; - EXPECT_EQ(f1.coreType, helics::CoreType::INTERPROCESS); - EXPECT_EQ(f1.defName, "f3"); - EXPECT_EQ(f1.flagProps.size(), 3U); - EXPECT_EQ(f1.brokerPort, 5000); + EXPECT_EQ(fedInfo.coreType, helics::CoreType::INTERPROCESS); + EXPECT_EQ(fedInfo.defName, "f3"); + EXPECT_EQ(fedInfo.flagProps.size(), 3U); + EXPECT_EQ(fedInfo.brokerPort, 5000); } TEST(federateInfo, loadArgs2) { - helics::FederateInfo f1; - f1.loadInfoFromArgs( + helics::FederateInfo fedInfo; + fedInfo.loadInfoFromArgs( "--name f3 --coretype ipc --flags realtime;source_only,-buffer_data --port=5000 --RT_tolerance 200ms"); - EXPECT_EQ(f1.coreType, helics::CoreType::INTERPROCESS); - EXPECT_EQ(f1.defName, "f3"); - EXPECT_EQ(f1.flagProps.size(), 3U); - EXPECT_EQ(f1.brokerPort, 5000); - EXPECT_EQ(f1.timeProps.size(), 1U); + EXPECT_EQ(fedInfo.coreType, helics::CoreType::INTERPROCESS); + EXPECT_EQ(fedInfo.defName, "f3"); + EXPECT_EQ(fedInfo.flagProps.size(), 3U); + EXPECT_EQ(fedInfo.brokerPort, 5000); + EXPECT_EQ(fedInfo.timeProps.size(), 1U); } TEST(federateInfo, loadArgs_error) { - helics::FederateInfo f1; + helics::FederateInfo fedInfo; EXPECT_NO_THROW( - f1.loadInfoFromArgs("--name f3 --coretype ipc --flags unrecognized --port=5000")); + fedInfo.loadInfoFromArgs("--name f3 --coretype ipc --flags unrecognized --port=5000")); - EXPECT_THROW(f1.loadInfoFromArgs("--name f3 --coretype ipc --brokerport=hippity_hopity"), + EXPECT_THROW(fedInfo.loadInfoFromArgs("--name f3 --coretype ipc --brokerport=hippity_hopity"), helics::InvalidParameter); } @@ -110,48 +110,48 @@ TEST(federateInfo, loadArgs_error2) "constructor2", "--name", "f2", "--coretype", "zmq", "--brokerport=hippity_hopity"}; char* argv[6]; for (size_t ii = 0; ii < args.size(); ++ii) { - argv[ii] = &(args[ii][0]); + argv[ii] = args[ii].data(); } - helics::FederateInfo f1; - EXPECT_THROW(f1.loadInfoFromArgs(6, argv), helics::InvalidParameter); + helics::FederateInfo fedInfo; + EXPECT_THROW(fedInfo.loadInfoFromArgs(6, argv), helics::InvalidParameter); } TEST(federateInfo, constructor4) { - helics::FederateInfo f1{ + helics::FederateInfo fedInfo{ "--log_level=no_print --brokerport=5000 --port=5005 --offset=5 --time_delta=45ms --max_iterations 10"}; - EXPECT_EQ(f1.brokerPort, 5000); - EXPECT_EQ(f1.localport, "5005"); - EXPECT_EQ(f1.intProps.size(), 2U); - EXPECT_EQ(f1.timeProps.size(), 2U); + EXPECT_EQ(fedInfo.brokerPort, 5000); + EXPECT_EQ(fedInfo.localport, "5005"); + EXPECT_EQ(fedInfo.intProps.size(), 2U); + EXPECT_EQ(fedInfo.timeProps.size(), 2U); } TEST(federateInfo, constructor5) { - helics::FederateInfo f1{ + helics::FederateInfo fedInfo{ "--input_delay 50ms --broker_init_string='--loglevel 3 --coretype=zmq'"}; - ASSERT_FALSE(f1.brokerInitString.empty()); - EXPECT_EQ(f1.brokerInitString.front(), ' '); - EXPECT_EQ(f1.timeProps.size(), 1U); + ASSERT_FALSE(fedInfo.brokerInitString.empty()); + EXPECT_EQ(fedInfo.brokerInitString.front(), ' '); + EXPECT_EQ(fedInfo.timeProps.size(), 1U); } TEST(federateInfo, constructor6) { - helics::FederateInfo f1{"--outputdelay=2 --separator=/ --rtlead=100ms --rtlag=50ms"}; - EXPECT_EQ(f1.timeProps.size(), 3U); - EXPECT_EQ(f1.separator, '/'); + helics::FederateInfo fedInfo{"--outputdelay=2 --separator=/ --rtlead=100ms --rtlag=50ms"}; + EXPECT_EQ(fedInfo.timeProps.size(), 3U); + EXPECT_EQ(fedInfo.separator, '/'); } TEST(federateInfo, constructor7) { - auto f1 = helics::loadFederateInfo("fedname7"); - EXPECT_EQ(f1.defName, "fedname7"); + auto fedInfo = helics::loadFederateInfo("fedname7"); + EXPECT_EQ(fedInfo.defName, "fedname7"); } TEST(federateInfo, constructor_fail) { - EXPECT_THROW(helics::FederateInfo f1{"--inputdelay=2 --separator=cbc"}, std::exception); + EXPECT_THROW(helics::FederateInfo fedInfo{"--inputdelay=2 --separator=cbc"}, std::exception); } TEST(federateInfo, property_index) @@ -187,39 +187,39 @@ TEST(federateInfo, loadinfoError) TEST(federateInfo, loadinfoPropsJson) { - auto f1 = helics::loadFederateInfo(R"({"separator":":"})"); - EXPECT_EQ(f1.separator, ':'); - f1 = helics::loadFederateInfo(R"({"core":"zmq"})"); - EXPECT_EQ(f1.coreType, helics::CoreType::ZMQ); - f1 = helics::loadFederateInfo(R"({"core":"fred"})"); - EXPECT_EQ(f1.coreName, "fred"); + auto fedInfo = helics::loadFederateInfo(R"({"separator":":"})"); + EXPECT_EQ(fedInfo.separator, ':'); + fedInfo = helics::loadFederateInfo(R"({"core":"zmq"})"); + EXPECT_EQ(fedInfo.coreType, helics::CoreType::ZMQ); + fedInfo = helics::loadFederateInfo(R"({"core":"fred"})"); + EXPECT_EQ(fedInfo.coreName, "fred"); EXPECT_THROW(helics::loadFederateInfo("{\"coreType\":\"fred\"}"), helics::InvalidIdentifier); EXPECT_THROW(helics::loadFederateInfo("{\"coretype\":\"fred\"}"), helics::InvalidIdentifier); EXPECT_THROW(helics::loadFederateInfo("{\"coretype\":\"fred\"}"), helics::InvalidIdentifier); - f1 = helics::loadFederateInfo(R"({"flags":"autobroker,source_only"})"); - EXPECT_EQ(f1.flagProps.size(), 1U); - EXPECT_TRUE(f1.autobroker); + fedInfo = helics::loadFederateInfo(R"({"flags":"autobroker,source_only"})"); + EXPECT_EQ(fedInfo.flagProps.size(), 1U); + EXPECT_TRUE(fedInfo.autobroker); - f1 = helics::loadFederateInfo("{\"port\":5000}"); - EXPECT_EQ(f1.brokerPort, 5000); - f1 = helics::loadFederateInfo(R"({"brokerport":5005,"port":5000})"); - EXPECT_EQ(f1.brokerPort, 5005); - EXPECT_EQ(f1.localport, "5000"); + fedInfo = helics::loadFederateInfo("{\"port\":5000}"); + EXPECT_EQ(fedInfo.brokerPort, 5000); + fedInfo = helics::loadFederateInfo(R"({"brokerport":5005,"port":5000})"); + EXPECT_EQ(fedInfo.brokerPort, 5005); + EXPECT_EQ(fedInfo.localport, "5000"); - f1 = helics::loadFederateInfo(R"({"localport":5005,"port":5000})"); - EXPECT_EQ(f1.brokerPort, 5000); - EXPECT_EQ(f1.localport, "5005"); + fedInfo = helics::loadFederateInfo(R"({"localport":5005,"port":5000})"); + EXPECT_EQ(fedInfo.brokerPort, 5000); + EXPECT_EQ(fedInfo.localport, "5005"); - f1 = helics::loadFederateInfo(R"({"loglevel":"timing"})"); - EXPECT_EQ(f1.intProps.size(), 1U); - EXPECT_EQ(f1.intProps[0].second, HELICS_LOG_LEVEL_TIMING); + fedInfo = helics::loadFederateInfo(R"({"loglevel":"timing"})"); + EXPECT_EQ(fedInfo.intProps.size(), 1U); + EXPECT_EQ(fedInfo.intProps[0].second, HELICS_LOG_LEVEL_TIMING); - f1 = helics::loadFederateInfo(R"({"loglevel":"summary"})"); - EXPECT_EQ(f1.intProps.size(), 1U); - EXPECT_EQ(f1.intProps[0].second, HELICS_LOG_LEVEL_SUMMARY); + fedInfo = helics::loadFederateInfo(R"({"loglevel":"summary"})"); + EXPECT_EQ(fedInfo.intProps.size(), 1U); + EXPECT_EQ(fedInfo.intProps[0].second, HELICS_LOG_LEVEL_SUMMARY); - EXPECT_EQ(f1.checkIntProperty(HELICS_PROPERTY_INT_LOG_LEVEL, HELICS_LOG_LEVEL_NO_PRINT), + EXPECT_EQ(fedInfo.checkIntProperty(HELICS_PROPERTY_INT_LOG_LEVEL, HELICS_LOG_LEVEL_NO_PRINT), HELICS_LOG_LEVEL_SUMMARY); EXPECT_THROW(helics::loadFederateInfo("{\"loglevel\":\"unknown\"}"), helics::InvalidIdentifier); @@ -227,61 +227,61 @@ TEST(federateInfo, loadinfoPropsJson) TEST(federateInfo, loadinfoPropsToml) { - auto f1 = helics::loadFederateInfo(R"("separator"=":")"); - EXPECT_EQ(f1.separator, ':'); - f1 = helics::loadFederateInfo(R"("core"="zmq")"); - EXPECT_EQ(f1.coreType, helics::CoreType::ZMQ); - f1 = helics::loadFederateInfo(R"("core"="fred")"); - EXPECT_EQ(f1.coreName, "fred"); + auto fedInfo = helics::loadFederateInfo(R"("separator"=":")"); + EXPECT_EQ(fedInfo.separator, ':'); + fedInfo = helics::loadFederateInfo(R"("core"="zmq")"); + EXPECT_EQ(fedInfo.coreType, helics::CoreType::ZMQ); + fedInfo = helics::loadFederateInfo(R"("core"="fred")"); + EXPECT_EQ(fedInfo.coreName, "fred"); EXPECT_THROW(helics::loadFederateInfo("\"coreType\"=\"fred\""), helics::InvalidIdentifier); EXPECT_THROW(helics::loadFederateInfo("\"coretype\"=\"fred\""), helics::InvalidIdentifier); EXPECT_THROW(helics::loadFederateInfo("\"coretype\"=\"fred\""), helics::InvalidIdentifier); - f1 = helics::loadFederateInfo(R"("coreType"="web")"); - EXPECT_EQ(f1.coreType, helics::CoreType::WEBSOCKET); + fedInfo = helics::loadFederateInfo(R"("coreType"="web")"); + EXPECT_EQ(fedInfo.coreType, helics::CoreType::WEBSOCKET); - f1 = helics::loadFederateInfo(R"("coretype"="UDP")"); - EXPECT_EQ(f1.coreType, helics::CoreType::UDP); + fedInfo = helics::loadFederateInfo(R"("coretype"="UDP")"); + EXPECT_EQ(fedInfo.coreType, helics::CoreType::UDP); - f1 = helics::loadFederateInfo(R"("flags"="autobroker,source_only")"); - EXPECT_EQ(f1.flagProps.size(), 1U); - EXPECT_TRUE(f1.autobroker); + fedInfo = helics::loadFederateInfo(R"("flags"="autobroker,source_only")"); + EXPECT_EQ(fedInfo.flagProps.size(), 1U); + EXPECT_TRUE(fedInfo.autobroker); - f1 = helics::loadFederateInfo("\"port\"=5000"); - EXPECT_EQ(f1.brokerPort, 5000); - f1 = helics::loadFederateInfo("\"brokerport\"=5005\n\"port\"=5000"); - EXPECT_EQ(f1.brokerPort, 5005); - EXPECT_EQ(f1.localport, "5000"); + fedInfo = helics::loadFederateInfo("\"port\"=5000"); + EXPECT_EQ(fedInfo.brokerPort, 5000); + fedInfo = helics::loadFederateInfo("\"brokerport\"=5005\n\"port\"=5000"); + EXPECT_EQ(fedInfo.brokerPort, 5005); + EXPECT_EQ(fedInfo.localport, "5000"); - f1 = helics::loadFederateInfo("\"localport\"=5005\n\"port\"=5000"); - EXPECT_EQ(f1.brokerPort, 5000); - EXPECT_EQ(f1.localport, "5005"); + fedInfo = helics::loadFederateInfo("\"localport\"=5005\n\"port\"=5000"); + EXPECT_EQ(fedInfo.brokerPort, 5000); + EXPECT_EQ(fedInfo.localport, "5005"); - f1 = helics::loadFederateInfo(R"("loglevel"="timing")"); - EXPECT_EQ(f1.intProps.size(), 1U); - EXPECT_EQ(f1.intProps[0].second, HELICS_LOG_LEVEL_TIMING); + fedInfo = helics::loadFederateInfo(R"("loglevel"="timing")"); + EXPECT_EQ(fedInfo.intProps.size(), 1U); + EXPECT_EQ(fedInfo.intProps[0].second, HELICS_LOG_LEVEL_TIMING); - f1 = helics::loadFederateInfo(R"("loglevel"="summary")"); - EXPECT_EQ(f1.intProps.size(), 1U); - EXPECT_EQ(f1.intProps[0].second, HELICS_LOG_LEVEL_SUMMARY); + fedInfo = helics::loadFederateInfo(R"("loglevel"="summary")"); + EXPECT_EQ(fedInfo.intProps.size(), 1U); + EXPECT_EQ(fedInfo.intProps[0].second, HELICS_LOG_LEVEL_SUMMARY); EXPECT_THROW(helics::loadFederateInfo("\"loglevel\"=\"unknown\""), helics::InvalidIdentifier); } TEST(federateInfo, initString) { - helics::FederateInfo fi; - fi.brokerPort = 6700; - fi.localport = "5000"; - fi.key = "broker_key"; - fi.broker = "broker2"; - fi.brokerInitString = "-f3"; - helics::FederateInfo f3(helics::generateFullCoreInitString(fi)); - - EXPECT_EQ(fi.brokerPort, f3.brokerPort); - EXPECT_EQ(fi.localport, f3.localport); - EXPECT_EQ(fi.key, f3.key); - EXPECT_EQ(fi.autobroker, f3.autobroker); - EXPECT_EQ(fi.broker, f3.broker); - - EXPECT_TRUE(f3.brokerInitString.find(fi.brokerInitString) != std::string::npos); + helics::FederateInfo fedInfo; + fedInfo.brokerPort = 6700; + fedInfo.localport = "5000"; + fedInfo.key = "broker_key"; + fedInfo.broker = "broker2"; + fedInfo.brokerInitString = "-f3"; + helics::FederateInfo fedInfo3(helics::generateFullCoreInitString(fedInfo)); + + EXPECT_EQ(fedInfo.brokerPort, fedInfo3.brokerPort); + EXPECT_EQ(fedInfo.localport, fedInfo3.localport); + EXPECT_EQ(fedInfo.key, fedInfo3.key); + EXPECT_EQ(fedInfo.autobroker, fedInfo3.autobroker); + EXPECT_EQ(fedInfo.broker, fedInfo3.broker); + + EXPECT_TRUE(fedInfo3.brokerInitString.find(fedInfo.brokerInitString) != std::string::npos); } diff --git a/tests/helics/application_api/FederateTests.cpp b/tests/helics/application_api/FederateTests.cpp index 6d0dede98d..cb6aab1488 100644 --- a/tests/helics/application_api/FederateTests.cpp +++ b/tests/helics/application_api/FederateTests.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -28,10 +28,10 @@ SPDX-License-Identifier: BSD-3-Clause TEST(federate, federate_initialize_tests) { - helics::FederateInfo fi(CORE_TYPE_TO_TEST); - fi.coreInitString = "--autobroker"; + helics::FederateInfo fedInfo(CORE_TYPE_TO_TEST); + fedInfo.coreInitString = "--autobroker"; - auto Fed = std::make_shared("test1", fi); + auto Fed = std::make_shared("test1", fedInfo); auto core = Fed->getCorePointer(); ASSERT_TRUE((core)); @@ -57,10 +57,10 @@ TEST(federate, federate_initialize_tests) TEST(federate, single_core_federate) { - helics::FederateInfo fi(CORE_TYPE_TO_TEST); - fi.coreInitString = "--autobroker"; - fi.setFlagOption(helics::defs::SINGLE_THREAD_FEDERATE); - auto fed = std::make_shared("test1", fi); + helics::FederateInfo fedInfo(CORE_TYPE_TO_TEST); + fedInfo.coreInitString = "--autobroker"; + fedInfo.setFlagOption(helics::defs::SINGLE_THREAD_FEDERATE); + auto fed = std::make_shared("test1", fedInfo); auto core = fed->getCorePointer(); ASSERT_TRUE((core)); @@ -80,9 +80,9 @@ TEST(federate, single_core_federate) TEST(federate, renamer) { - helics::FederateInfo fi(CORE_TYPE_TO_TEST); - fi.coreInitString = "--autobroker"; - auto fed = std::make_shared("test_${#}", fi); + helics::FederateInfo fedInfo(CORE_TYPE_TO_TEST); + fedInfo.coreInitString = "--autobroker"; + auto fed = std::make_shared("test_${#}", fedInfo); auto core = fed->getCorePointer(); ASSERT_TRUE((core)); @@ -92,24 +92,30 @@ TEST(federate, renamer) EXPECT_EQ(name, fed->getName()); EXPECT_EQ(name, "test_1"); - fi.coreInitString.clear(); - auto fed2 = std::make_shared("test_${#}", fi); + fedInfo.coreInitString.clear(); + auto fed2 = std::make_shared("test_${#}", fedInfo); EXPECT_EQ("test_2", fed2->getName()); + auto fed3 = std::make_shared("test_${#}", fed->getCorePointer(), fedInfo); + EXPECT_EQ("test_3", fed3->getName()); + fed->enterInitializingModeAsync(); + fed3->enterInitializingModeAsync(); fed2->enterInitializingMode(); fed->enterInitializingModeComplete(); + fed3->enterInitializingModeComplete(); fed = nullptr; // force the destructor fed2 = nullptr; + fed3 = nullptr; } TEST(federate_tests, federate_initialize_iterate) { - helics::FederateInfo fi(CORE_TYPE_TO_TEST); - fi.coreInitString = "--autobroker"; + helics::FederateInfo fedInfo(CORE_TYPE_TO_TEST); + fedInfo.coreInitString = "--autobroker"; - auto Fed = std::make_shared("test1", fi); + auto Fed = std::make_shared("test1", fedInfo); auto core = Fed->getCorePointer(); ASSERT_TRUE((core)); @@ -142,10 +148,10 @@ TEST(federate_tests, federate_initialize_json) { helics::BrokerApp brk(helics::CoreType::ZMQ); - helics::FederateInfo fi(helics::CoreType::ZMQ); - fi.coreInitString = "--json"; + helics::FederateInfo fedInfo(helics::CoreType::ZMQ); + fedInfo.coreInitString = "--json"; - auto Fed = std::make_shared("test1", fi); + auto Fed = std::make_shared("test1", fedInfo); auto core = Fed->getCorePointer(); ASSERT_TRUE((core)); @@ -167,10 +173,10 @@ TEST(federate_tests, federate_initialize_iteration_multiple) { helics::BrokerApp brk(helics::CoreType::ZMQ); - helics::FederateInfo fi(helics::CoreType::ZMQ); + helics::FederateInfo fedInfo(helics::CoreType::ZMQ); - auto Fed1 = std::make_shared("test1", fi); - auto Fed2 = std::make_shared("test2", fi); + auto Fed1 = std::make_shared("test1", fedInfo); + auto Fed2 = std::make_shared("test2", fedInfo); Fed1->enterInitializingModeAsync(); Fed2->enterInitializingModeIterative(); @@ -182,10 +188,10 @@ TEST(federate_tests, federate_initialize_iteration_multiple) EXPECT_TRUE(Fed2->getCurrentMode() == helics::Federate::Modes::PENDING_ITERATIVE_INIT || Fed2->getCurrentMode() == helics::Federate::Modes::STARTUP); std::this_thread::yield(); - int ii{0}; + int count{0}; while (!Fed2->isAsyncOperationCompleted()) { std::this_thread::sleep_for(std::chrono::milliseconds(50)); - if (++ii > 20) { + if (++count > 20) { break; } } @@ -206,10 +212,10 @@ TEST(federate_tests, federate_initialize_iteration_multiple) TEST(federate, federate_initialize_tests_env) { setEnvironmentVariable("HELICS_LOG_LEVEL", "connections"); - helics::FederateInfo fi(CORE_TYPE_TO_TEST); - fi.coreInitString = "--autobroker"; + helics::FederateInfo fedInfo(CORE_TYPE_TO_TEST); + fedInfo.coreInitString = "--autobroker"; - auto Fed = std::make_shared("test1", fi); + auto Fed = std::make_shared("test1", fedInfo); auto core = Fed->getCorePointer(); ASSERT_TRUE((core)); @@ -232,10 +238,10 @@ TEST(federate, federate_initialize_tests_env) TEST(federate, federate_initialize_tests_env2) { setEnvironmentVariable("HELICS_BROKER_LOG_LEVEL", std::to_string(HELICS_LOG_LEVEL_CONNECTIONS)); - helics::FederateInfo fi(CORE_TYPE_TO_TEST); - fi.coreInitString = "--autobroker"; + helics::FederateInfo fedInfo(CORE_TYPE_TO_TEST); + fedInfo.coreInitString = "--autobroker"; - auto Fed = std::make_shared("test1", fi); + auto Fed = std::make_shared("test1", fedInfo); auto core = Fed->getCorePointer(); ASSERT_TRUE((core)); @@ -256,10 +262,10 @@ TEST(federate, federate_initialize_tests_env2) */ TEST(federate, time_step_tests) { - helics::FederateInfo fi(CORE_TYPE_TO_TEST); - fi.coreInitString = "--autobroker"; + helics::FederateInfo fedInfo(CORE_TYPE_TO_TEST); + fedInfo.coreInitString = "--autobroker"; - auto Fed = std::make_shared("test1", fi); + auto Fed = std::make_shared("test1", fedInfo); EXPECT_TRUE(Fed->getCurrentMode() == helics::Federate::Modes::STARTUP); Fed->enterInitializingMode(); @@ -278,10 +284,10 @@ TEST(federate, time_step_tests) TEST(federate, dynamic_join) { - helics::FederateInfo fi(CORE_TYPE_TO_TEST); - fi.coreInitString = "--autobroker --broker_init_string='--dynamic --name=dyn_broker'"; + helics::FederateInfo fedInfo(CORE_TYPE_TO_TEST); + fedInfo.coreInitString = "--autobroker --broker_init_string='--dynamic --name=dyn_broker'"; - auto fed = std::make_shared("test1", fi); + auto fed = std::make_shared("test1", fedInfo); EXPECT_TRUE(fed->getCurrentMode() == helics::Federate::Modes::STARTUP); fed->enterInitializingMode(); @@ -293,10 +299,10 @@ TEST(federate, dynamic_join) res = fed->requestTime(2.0); EXPECT_EQ(res, 2.0); // now join a dynamic broker - fi.coreInitString.clear(); - fi.broker = "dyn_broker"; + fedInfo.coreInitString.clear(); + fedInfo.broker = "dyn_broker"; decltype(fed) fedDyn; - EXPECT_NO_THROW(fedDyn = std::make_shared("test_dyn", fi)); + EXPECT_NO_THROW(fedDyn = std::make_shared("test_dyn", fedInfo)); fedDyn->enterInitializingMode(); EXPECT_TRUE(fedDyn->getCurrentMode() == helics::Federate::Modes::INITIALIZING); @@ -317,11 +323,11 @@ TEST(federate, broker_disconnect_ci_skip) { auto brk = helics::BrokerFactory::create(CORE_TYPE_TO_TEST, "b1", "-f 1"); brk->connect(); - helics::FederateInfo fi(CORE_TYPE_TO_TEST); + helics::FederateInfo fedInfo(CORE_TYPE_TO_TEST); - fi.coreInitString = "--broker=b1 --tick=200 --timeout=1000"; + fedInfo.coreInitString = "--broker=b1 --tick=200 --timeout=1000"; - auto Fed = std::make_shared("test1", fi); + auto Fed = std::make_shared("test1", fedInfo); EXPECT_TRUE(Fed->getCurrentMode() == helics::Federate::Modes::STARTUP); Fed->enterInitializingMode(); @@ -347,10 +353,10 @@ TEST(federate, broker_disconnect_ci_skip) TEST(federate, index_groups) { - helics::FederateInfo fi(CORE_TYPE_TO_TEST); - fi.coreInitString = "--autobroker"; - fi.setProperty(HELICS_PROPERTY_INT_INDEX_GROUP, 3); - auto fed1 = std::make_shared("test1", fi); + helics::FederateInfo fedInfo(CORE_TYPE_TO_TEST); + fedInfo.coreInitString = "--autobroker"; + fedInfo.setProperty(HELICS_PROPERTY_INT_INDEX_GROUP, 3); + auto fed1 = std::make_shared("test1", fedInfo); helics::FederateInfo fi2(CORE_TYPE_TO_TEST); auto fed2 = std::make_shared("test2", fi2); @@ -371,19 +377,19 @@ TEST(federate, index_groups) // TODO(PT): make this work for all test types TEST(federate, bad_broker_error_zmq_ci_skip) { - helics::FederateInfo fi(helics::CoreType::ZMQ); - fi.coreInitString = "--broker=b1 --tick=200 --timeout=800 --networktimeout=400"; + helics::FederateInfo fedInfo(helics::CoreType::ZMQ); + fedInfo.coreInitString = "--broker=b1 --tick=200 --timeout=800 --networktimeout=400"; - EXPECT_THROW(auto fed = std::make_shared("test1", fi), + EXPECT_THROW(auto fed = std::make_shared("test1", fedInfo), helics::RegistrationFailure); } TEST(federate, timeout_error_zmq_ci_skip_nosan) { - helics::FederateInfo fi(helics::CoreType::ZMQ); - fi.coreInitString = "--tick=200 --timeout=800 --networktimeout=400"; + helics::FederateInfo fedInfo(helics::CoreType::ZMQ); + fedInfo.coreInitString = "--tick=200 --timeout=800 --networktimeout=400"; - EXPECT_THROW(auto fed = std::make_shared("test1", fi), + EXPECT_THROW(auto fed = std::make_shared("test1", fedInfo), helics::RegistrationFailure); } @@ -391,9 +397,9 @@ TEST(federate, timeout_abort_zmq_ci_skip_nosan_nocov) { std::future> fut; auto call = []() { - helics::FederateInfo fi(helics::CoreType::ZMQ); - fi.coreInitString = ""; - auto fed = std::make_shared("test1", fi); + helics::FederateInfo fedInfo(helics::CoreType::ZMQ); + fedInfo.coreInitString = ""; + auto fed = std::make_shared("test1", fedInfo); return fed; }; @@ -420,9 +426,9 @@ TEST(federate, timeout_abort_tcp_ci_skip_nosan_nocov) { std::future> fut; auto call = []() { - helics::FederateInfo fi(helics::CoreType::TCP); - fi.coreInitString = ""; - auto fed = std::make_shared("test1", fi); + helics::FederateInfo fedInfo(helics::CoreType::TCP); + fedInfo.coreInitString = ""; + auto fed = std::make_shared("test1", fedInfo); return fed; }; @@ -446,9 +452,9 @@ TEST(federate, timeout_abort_tcpss_ci_skip_nosan_nocov) { std::future> fut; auto call = []() { - helics::FederateInfo fi(helics::CoreType::TCP_SS); - fi.coreInitString = ""; - auto fed = std::make_shared("test1", fi); + helics::FederateInfo fedInfo(helics::CoreType::TCP_SS); + fedInfo.coreInitString = ""; + auto fed = std::make_shared("test1", fedInfo); return fed; }; @@ -474,9 +480,9 @@ TEST(federate, timeout_abort_udp_ci_skip_nosan_nocov) { std::future> fut; auto call = []() { - helics::FederateInfo fi(helics::CoreType::UDP); - fi.coreInitString = ""; - auto fed = std::make_shared("test1", fi); + helics::FederateInfo fedInfo(helics::CoreType::UDP); + fedInfo.coreInitString = ""; + auto fed = std::make_shared("test1", fedInfo); return fed; }; @@ -499,13 +505,13 @@ TEST(federate, timeout_abort_udp_ci_skip_nosan_nocov) TEST(federate, federate_multiple_federates) { - helics::FederateInfo fi(CORE_TYPE_TO_TEST); - fi.coreName = "core1-mult"; - fi.coreInitString = "-f 2 --autobroker"; + helics::FederateInfo fedInfo(CORE_TYPE_TO_TEST); + fedInfo.coreName = "core1-mult"; + fedInfo.coreInitString = "-f 2 --autobroker"; - auto Fed1 = std::make_shared("fed1", fi); + auto Fed1 = std::make_shared("fed1", fedInfo); - auto Fed2 = std::make_shared("fed2", fi); + auto Fed2 = std::make_shared("fed2", fedInfo); EXPECT_TRUE(Fed1->getCurrentMode() == helics::Federate::Modes::STARTUP); EXPECT_TRUE(Fed2->getCurrentMode() == helics::Federate::Modes::STARTUP); @@ -549,14 +555,14 @@ TEST(federate, federate_multiple_federates) /** the same as the previous test except with multiple cores and a single broker*/ TEST(federate, multiple_federates_multi_cores) { - helics::FederateInfo fi(CORE_TYPE_TO_TEST); - fi.coreName = "core_mc1"; - fi.coreInitString = "--autobroker --broker=brk1"; + helics::FederateInfo fedInfo(CORE_TYPE_TO_TEST); + fedInfo.coreName = "core_mc1"; + fedInfo.coreInitString = "--autobroker --broker=brk1"; - auto Fed1 = std::make_shared("fed1", fi); - fi.coreName = "core_mc2"; + auto Fed1 = std::make_shared("fed1", fedInfo); + fedInfo.coreName = "core_mc2"; - auto Fed2 = std::make_shared("fed2", fi); + auto Fed2 = std::make_shared("fed2", fedInfo); EXPECT_TRUE(Fed1->getCurrentMode() == helics::Federate::Modes::STARTUP); EXPECT_TRUE(Fed2->getCurrentMode() == helics::Federate::Modes::STARTUP); @@ -597,13 +603,13 @@ TEST(federate, multiple_federates_multi_cores) TEST(federate, multiple_federates_async_calls) { - helics::FederateInfo fi(CORE_TYPE_TO_TEST); - fi.coreName = "core_async"; - fi.coreInitString = "-f 2 --autobroker"; + helics::FederateInfo fedInfo(CORE_TYPE_TO_TEST); + fedInfo.coreName = "core_async"; + fedInfo.coreInitString = "-f 2 --autobroker"; - auto Fed1 = std::make_shared("fed1", fi); + auto Fed1 = std::make_shared("fed1", fedInfo); - auto Fed2 = std::make_shared("fed2", fi); + auto Fed2 = std::make_shared("fed2", fedInfo); EXPECT_TRUE(Fed1->getCurrentMode() == helics::Federate::Modes::STARTUP); EXPECT_TRUE(Fed2->getCurrentMode() == helics::Federate::Modes::STARTUP); @@ -614,11 +620,11 @@ TEST(federate, multiple_federates_async_calls) Fed2->enterInitializingMode(); EXPECT_NO_THROW(Fed2->enterInitializingMode()); - auto c1 = Fed1->getCorePointer(); - auto c2 = Fed2->getCorePointer(); - EXPECT_EQ(c1->getIdentifier(), c2->getIdentifier()); - c1.reset(); - c2.reset(); + auto core1 = Fed1->getCorePointer(); + auto core2 = Fed2->getCorePointer(); + EXPECT_EQ(core1->getIdentifier(), core2->getIdentifier()); + core1.reset(); + core2.reset(); Fed1->enterInitializingModeComplete(); @@ -655,24 +661,24 @@ TEST(federate, multiple_federates_async_calls) TEST(federate, missing_core) { - helics::FederateInfo fi(helics::CoreType::NULLCORE); - fi.coreName = "core_missing"; - fi.coreInitString = "-f 1"; + helics::FederateInfo fedInfo(helics::CoreType::NULLCORE); + fedInfo.coreName = "core_missing"; + fedInfo.coreInitString = "-f 1"; - EXPECT_THROW(auto Fed1 = std::make_shared("fed1", fi), + EXPECT_THROW(auto Fed1 = std::make_shared("fed1", fedInfo), helics::HelicsException); } TEST(federate, not_open) { - helics::FederateInfo fi(helics::CoreType::TEST); - fi.coreName = "core_full"; - fi.coreInitString = "-f 1 --autobroker"; + helics::FederateInfo fedInfo(helics::CoreType::TEST); + fedInfo.coreName = "core_full"; + fedInfo.coreInitString = "-f 1 --autobroker"; - auto Fed1 = std::make_shared("fed1", fi); + auto Fed1 = std::make_shared("fed1", fedInfo); Fed1->enterExecutingMode(); - EXPECT_THROW(auto fed2 = std::make_shared("fed2", fi), + EXPECT_THROW(auto fed2 = std::make_shared("fed2", fedInfo), helics::RegistrationFailure); Fed1->finalize(); } @@ -680,8 +686,8 @@ TEST(federate, not_open) TEST(federate, coreApp) { helics::CoreApp capp(helics::CoreType::TEST, "corename", "-f 1 --autobroker"); - helics::FederateInfo fi(helics::CoreType::TEST); - auto Fed1 = std::make_shared("fed1", capp, fi); + helics::FederateInfo fedInfo(helics::CoreType::TEST); + auto Fed1 = std::make_shared("fed1", capp, fedInfo); EXPECT_NO_THROW(Fed1->enterExecutingMode()); Fed1->finalize(); @@ -689,24 +695,24 @@ TEST(federate, coreApp) TEST(federate, core_ptr) { - helics::FederateInfo fi(helics::CoreType::TEST); - fi.coreName = "core_ptr"; - fi.coreInitString = "-f 1 --autobroker"; + helics::FederateInfo fedInfo(helics::CoreType::TEST); + fedInfo.coreName = "core_ptr"; + fedInfo.coreInitString = "-f 1 --autobroker"; - auto Fed1 = std::make_shared("fed1", nullptr, fi); + auto Fed1 = std::make_shared("fed1", nullptr, fedInfo); Fed1->enterExecutingMode(); - EXPECT_THROW(auto fed2 = std::make_shared("fed2", nullptr, fi), + EXPECT_THROW(auto fed2 = std::make_shared("fed2", nullptr, fedInfo), helics::RegistrationFailure); Fed1->finalize(); } TEST(federate, core_ptr_no_name) { - helics::FederateInfo fi(helics::CoreType::TEST); - fi.coreInitString = "-f 1 --autobroker"; + helics::FederateInfo fedInfo(helics::CoreType::TEST); + fedInfo.coreInitString = "-f 1 --autobroker"; - auto Fed1 = std::make_shared(std::string{}, nullptr, fi); + auto Fed1 = std::make_shared(std::string{}, nullptr, fedInfo); Fed1->enterExecutingMode(); Fed1->finalize(); } @@ -717,10 +723,10 @@ TEST(federate, from_string) "fed1", "--coretype=TEST --corename core_init --coreinitstring='-f 1 --autobroker'"); Fed1->enterExecutingMode(); - auto c1 = Fed1->getCorePointer(); - EXPECT_EQ(c1->getIdentifier(), "core_init"); + auto core = Fed1->getCorePointer(); + EXPECT_EQ(core->getIdentifier(), "core_init"); Fed1->finalize(); - c1.reset(); + core.reset(); } TEST(federate, from_file1) @@ -771,6 +777,15 @@ TEST(federate, from_file_invalid) EXPECT_THROW(Fed1 = std::make_shared(fstr2), std::exception); } +TEST(federate, from_file_invalid_translator) +{ + helics::BrokerFactory::terminateAllBrokers(); + helics::CoreFactory::terminateAllCores(); + auto fstr2 = std::string(TEST_DIR) + "invalid_translator_operation.json"; + std::shared_ptr Fed1; + EXPECT_THROW(Fed1 = std::make_shared(fstr2), std::exception); +} + TEST(federate, from_file5) { helics::BrokerFactory::terminateAllBrokers(); @@ -831,7 +846,7 @@ TEST(federate, from_file10) auto fstr2 = std::string(LONG_TEST_NAME); if (fstr2.size() < FILENAME_MAX) { - // this test would fail if the file name exceeeds the max filename length + // this test would fail if the file name exceeds the max filename length std::shared_ptr Fed1; EXPECT_NO_THROW(Fed1 = std::make_shared(fstr2)); if (Fed1) { @@ -854,11 +869,11 @@ TEST(federate, from_string2) TEST(federate, enterInit) { - helics::FederateInfo fi(helics::CoreType::TEST); - fi.coreName = "core_full_a"; - fi.coreInitString = "-f 1 --autobroker"; + helics::FederateInfo fedInfo(helics::CoreType::TEST); + fedInfo.coreName = "core_full_a"; + fedInfo.coreInitString = "-f 1 --autobroker"; - auto Fed1 = std::make_shared("fed1", fi); + auto Fed1 = std::make_shared("fed1", fedInfo); Fed1->enterInitializingModeAsync(); // make sure it doesn't error if called twice EXPECT_NO_THROW(Fed1->enterInitializingModeAsync()); @@ -872,11 +887,11 @@ TEST(federate, enterInit) TEST(federate, enterInitComplete) { - helics::FederateInfo fi(helics::CoreType::TEST); - fi.coreName = "core_full_b"; - fi.coreInitString = "-f 1 --autobroker"; + helics::FederateInfo fedInfo(helics::CoreType::TEST); + fedInfo.coreName = "core_full_b"; + fedInfo.coreInitString = "-f 1 --autobroker"; - auto Fed1 = std::make_shared("fed1", fi); + auto Fed1 = std::make_shared("fed1", fedInfo); // this should be the same as just calling enterInitializingMode EXPECT_NO_THROW(Fed1->enterInitializingModeComplete()); @@ -886,11 +901,11 @@ TEST(federate, enterInitComplete) TEST(federate, enterExec) { - helics::FederateInfo fi(helics::CoreType::TEST); - fi.coreName = "core_full_c"; - fi.coreInitString = "-f 1 --autobroker"; + helics::FederateInfo fedInfo(helics::CoreType::TEST); + fedInfo.coreName = "core_full_c"; + fedInfo.coreInitString = "-f 1 --autobroker"; - auto Fed1 = std::make_shared("fed1", fi); + auto Fed1 = std::make_shared("fed1", fedInfo); Fed1->enterInitializingModeAsync(); Fed1->setProperty(helics::defs::Properties::TIME_DELTA, helics::Time(1.0)); // make sure it doesn't error if called twice @@ -906,14 +921,14 @@ TEST(federate, enterExec) TEST(federate, enterExecAfterFinal) { - helics::FederateInfo fi(helics::CoreType::TEST); - fi.coreName = "core_full_ec"; - fi.coreInitString = "-f 1 --autobroker"; + helics::FederateInfo fedInfo(helics::CoreType::TEST); + fedInfo.coreName = "core_full_ec"; + fedInfo.coreInitString = "-f 1 --autobroker"; - auto Fed1 = std::make_shared("fed1", fi); + auto Fed1 = std::make_shared("fed1", fedInfo); Fed1->enterInitializingMode(); - auto cr = Fed1->getCorePointer(); - cr->disconnect(); + auto core = Fed1->getCorePointer(); + core->disconnect(); auto iterating = Fed1->enterExecutingMode(); EXPECT_EQ(iterating, helics::IterationResult::HALTED); @@ -923,14 +938,14 @@ TEST(federate, enterExecAfterFinal) TEST(federate, enterExecAfterFinalAsync) { - helics::FederateInfo fi(helics::CoreType::TEST); - fi.coreName = "core_full_eca"; - fi.coreInitString = "-f 1 --autobroker"; + helics::FederateInfo fedInfo(helics::CoreType::TEST); + fedInfo.coreName = "core_full_eca"; + fedInfo.coreInitString = "-f 1 --autobroker"; - auto Fed1 = std::make_shared("fed1", fi); + auto Fed1 = std::make_shared("fed1", fedInfo); Fed1->enterInitializingMode(); - auto cr = Fed1->getCorePointer(); - cr->disconnect(); + auto core = Fed1->getCorePointer(); + core->disconnect(); Fed1->enterExecutingModeAsync(); auto iterating = Fed1->enterExecutingModeComplete(); @@ -941,15 +956,15 @@ TEST(federate, enterExecAfterFinalAsync) TEST(federate, iterativeTimeRequestHalt) { - helics::FederateInfo fi(helics::CoreType::TEST); - fi.coreName = "core_full_eca1"; - fi.coreInitString = "-f 1 --autobroker"; + helics::FederateInfo fedInfo(helics::CoreType::TEST); + fedInfo.coreName = "core_full_eca1"; + fedInfo.coreInitString = "-f 1 --autobroker"; - auto Fed1 = std::make_shared("fed1", fi); + auto Fed1 = std::make_shared("fed1", fedInfo); Fed1->enterExecutingMode(); - auto cr = Fed1->getCorePointer(); - cr->disconnect(); + auto core = Fed1->getCorePointer(); + core->disconnect(); auto itTime = Fed1->requestTimeIterative(2.0, helics::IterationRequest::FORCE_ITERATION); EXPECT_EQ(itTime.state, helics::IterationResult::HALTED); @@ -960,15 +975,15 @@ TEST(federate, iterativeTimeRequestHalt) TEST(federate, iterativeTimeRequestAsyncHalt) { - helics::FederateInfo fi(helics::CoreType::TEST); - fi.coreName = "core_full_eca2"; - fi.coreInitString = "-f 1 --autobroker"; + helics::FederateInfo fedInfo(helics::CoreType::TEST); + fedInfo.coreName = "core_full_eca2"; + fedInfo.coreInitString = "-f 1 --autobroker"; - auto Fed1 = std::make_shared("fed1", fi); + auto Fed1 = std::make_shared("fed1", fedInfo); Fed1->enterExecutingMode(); - auto cr = Fed1->getCorePointer(); - cr->disconnect(); + auto core = Fed1->getCorePointer(); + core->disconnect(); Fed1->requestTimeIterativeAsync(2.0, helics::IterationRequest::FORCE_ITERATION); auto itTime = Fed1->requestTimeIterativeComplete(); @@ -980,11 +995,11 @@ TEST(federate, iterativeTimeRequestAsyncHalt) TEST(federate, enterExecAsync) { - helics::FederateInfo fi(helics::CoreType::TEST); - fi.coreName = "core_full_d"; - fi.coreInitString = "-f 1 --autobroker"; + helics::FederateInfo fedInfo(helics::CoreType::TEST); + fedInfo.coreName = "core_full_d"; + fedInfo.coreInitString = "-f 1 --autobroker"; - auto Fed1 = std::make_shared("fed1", fi); + auto Fed1 = std::make_shared("fed1", fedInfo); Fed1->enterExecutingModeAsync(); EXPECT_NO_THROW(Fed1->enterExecutingModeAsync()); @@ -993,11 +1008,11 @@ TEST(federate, enterExecAsync) TEST(federate, enterExecAsyncIterative) { - helics::FederateInfo fi(helics::CoreType::TEST); - fi.coreName = "core_full_e"; - fi.coreInitString = "-f 1 --autobroker"; + helics::FederateInfo fedInfo(helics::CoreType::TEST); + fedInfo.coreName = "core_full_e"; + fedInfo.coreInitString = "-f 1 --autobroker"; - auto Fed1 = std::make_shared("fed1", fi); + auto Fed1 = std::make_shared("fed1", fedInfo); Fed1->enterExecutingModeAsync(helics::IterationRequest::FORCE_ITERATION); EXPECT_NO_THROW(Fed1->enterExecutingModeAsync()); @@ -1011,11 +1026,11 @@ TEST(federate, enterExecAsyncIterative) TEST(federate, enterRequestTimeAsyncIterative) { - helics::FederateInfo fi(helics::CoreType::TEST); - fi.coreName = "core_full_e"; - fi.coreInitString = "-f 1 --autobroker"; + helics::FederateInfo fedInfo(helics::CoreType::TEST); + fedInfo.coreName = "core_full_e"; + fedInfo.coreInitString = "-f 1 --autobroker"; - auto Fed1 = std::make_shared("fed1", fi); + auto Fed1 = std::make_shared("fed1", fedInfo); Fed1->enterExecutingMode(); Fed1->requestTimeAsync(1.0); @@ -1045,27 +1060,27 @@ TEST(federate, enterRequestTimeAsyncIterative) TEST(federate, enterRequestTimeAsyncIterativeFinalize) { - helics::FederateInfo fi(helics::CoreType::TEST); - fi.coreName = "core_full_e2"; - fi.coreInitString = "-f 1 --autobroker"; + helics::FederateInfo fedInfo(helics::CoreType::TEST); + fedInfo.coreName = "core_full_e2"; + fedInfo.coreInitString = "-f 1 --autobroker"; - auto Fed1 = std::make_shared("fed1", fi); + auto Fed1 = std::make_shared("fed1", fedInfo); Fed1->enterExecutingMode(); Fed1->requestTimeIterativeAsync(1.0, helics::IterationRequest::FORCE_ITERATION); EXPECT_NO_THROW(Fed1->finalize()); // check time results after finalize - auto tm = Fed1->requestTime(3.0); - EXPECT_EQ(tm, helics::Time::maxVal()); + auto time = Fed1->requestTime(3.0); + EXPECT_EQ(time, helics::Time::maxVal()); } TEST(federate, enterRequestTimeAsyncFinalize) { - helics::FederateInfo fi(helics::CoreType::TEST); - fi.coreName = "core_full_e3"; - fi.coreInitString = "-f 1 --autobroker"; + helics::FederateInfo fedInfo(helics::CoreType::TEST); + fedInfo.coreName = "core_full_e3"; + fedInfo.coreInitString = "-f 1 --autobroker"; - auto Fed1 = std::make_shared("fed1", fi); + auto Fed1 = std::make_shared("fed1", fedInfo); Fed1->enterExecutingMode(); Fed1->requestTimeAsync(1.0); @@ -1075,11 +1090,11 @@ TEST(federate, enterRequestTimeAsyncFinalize) TEST(federate, enterRequestTimeAsyncFinalizeAsync) { - helics::FederateInfo fi(helics::CoreType::TEST); - fi.coreName = "core_full_e3a"; - fi.coreInitString = "-f 1 --autobroker"; + helics::FederateInfo fedInfo(helics::CoreType::TEST); + fedInfo.coreName = "core_full_e3a"; + fedInfo.coreInitString = "-f 1 --autobroker"; - auto Fed1 = std::make_shared("fed1", fi); + auto Fed1 = std::make_shared("fed1", fedInfo); Fed1->enterExecutingMode(); Fed1->requestTimeAsync(1.0); @@ -1090,11 +1105,11 @@ TEST(federate, enterRequestTimeAsyncFinalizeAsync) TEST(federate, enterEnterExecAsyncFinalize) { - helics::FederateInfo fi(helics::CoreType::TEST); - fi.coreName = "core_full_e4"; - fi.coreInitString = "-f 1 --autobroker"; + helics::FederateInfo fedInfo(helics::CoreType::TEST); + fedInfo.coreName = "core_full_e4"; + fedInfo.coreInitString = "-f 1 --autobroker"; - auto Fed1 = std::make_shared("fed1", fi); + auto Fed1 = std::make_shared("fed1", fedInfo); Fed1->enterInitializingMode(); Fed1->enterExecutingModeAsync(); EXPECT_NO_THROW(Fed1->finalize()); @@ -1103,11 +1118,11 @@ TEST(federate, enterEnterExecAsyncFinalize) TEST(federate, enterEnterInitAsyncFinalize) { - helics::FederateInfo fi(helics::CoreType::TEST); - fi.coreName = "core_full_e5"; - fi.coreInitString = "-f 1 --autobroker"; + helics::FederateInfo fedInfo(helics::CoreType::TEST); + fedInfo.coreName = "core_full_e5"; + fedInfo.coreInitString = "-f 1 --autobroker"; - auto Fed1 = std::make_shared("fed1", fi); + auto Fed1 = std::make_shared("fed1", fedInfo); Fed1->enterInitializingModeAsync(); EXPECT_NO_THROW(Fed1->finalize()); EXPECT_EQ(Fed1->getCurrentMode(), helics::Federate::Modes::FINALIZE); @@ -1115,11 +1130,11 @@ TEST(federate, enterEnterInitAsyncFinalize) TEST(federate, enterEnterExecAsyncFinalizeAsync) { - helics::FederateInfo fi(helics::CoreType::TEST); - fi.coreName = "core_full_e4a"; - fi.coreInitString = "-f 1 --autobroker"; + helics::FederateInfo fedInfo(helics::CoreType::TEST); + fedInfo.coreName = "core_full_e4a"; + fedInfo.coreInitString = "-f 1 --autobroker"; - auto Fed1 = std::make_shared("fed1", fi); + auto Fed1 = std::make_shared("fed1", fedInfo); Fed1->enterInitializingMode(); Fed1->enterExecutingModeAsync(); EXPECT_NO_THROW(Fed1->finalizeAsync()); @@ -1129,11 +1144,11 @@ TEST(federate, enterEnterExecAsyncFinalizeAsync) TEST(federate, enterEnterInitAsyncFinalizeAsync) { - helics::FederateInfo fi(helics::CoreType::TEST); - fi.coreName = "core_full_e5a"; - fi.coreInitString = "-f 1 --autobroker"; + helics::FederateInfo fedInfo(helics::CoreType::TEST); + fedInfo.coreName = "core_full_e5a"; + fedInfo.coreInitString = "-f 1 --autobroker"; - auto Fed1 = std::make_shared("fed1", fi); + auto Fed1 = std::make_shared("fed1", fedInfo); Fed1->enterInitializingModeAsync(); EXPECT_NO_THROW(Fed1->finalizeAsync()); Fed1->finalizeComplete(); @@ -1142,26 +1157,26 @@ TEST(federate, enterEnterInitAsyncFinalizeAsync) TEST(federate, enterExecPendingTimeIterative) { - helics::FederateInfo fi(helics::CoreType::TEST); - fi.coreName = "core_full_epa"; - fi.coreInitString = "-f 1 --autobroker"; + helics::FederateInfo fedInfo(helics::CoreType::TEST); + fedInfo.coreName = "core_full_epa"; + fedInfo.coreInitString = "-f 1 --autobroker"; - auto Fed1 = std::make_shared("fed1", fi); + auto Fed1 = std::make_shared("fed1", fedInfo); Fed1->enterExecutingMode(); Fed1->requestTimeIterativeAsync(2.0, helics::IterationRequest::FORCE_ITERATION); - auto it = Fed1->enterExecutingMode(); - EXPECT_EQ(it, helics::IterationResult::NEXT_STEP); + auto result = Fed1->enterExecutingMode(); + EXPECT_EQ(result, helics::IterationResult::NEXT_STEP); Fed1->finalizeComplete(); EXPECT_EQ(Fed1->getCurrentMode(), helics::Federate::Modes::FINALIZE); } TEST(federate, forceErrorExec) { - helics::FederateInfo fi(helics::CoreType::TEST); - fi.coreName = "core_full_fe"; - fi.coreInitString = "-f 1 --autobroker"; + helics::FederateInfo fedInfo(helics::CoreType::TEST); + fedInfo.coreName = "core_full_fe"; + fedInfo.coreInitString = "-f 1 --autobroker"; - auto Fed1 = std::make_shared("fed1", fi); + auto Fed1 = std::make_shared("fed1", fedInfo); Fed1->enterExecutingMode(); Fed1->localError(9827); @@ -1174,11 +1189,11 @@ TEST(federate, forceErrorExec) TEST(federate, forceErrorExecAsync) { - helics::FederateInfo fi(helics::CoreType::TEST); - fi.coreName = "core_full_fe1"; - fi.coreInitString = "-f 1 --autobroker"; + helics::FederateInfo fedInfo(helics::CoreType::TEST); + fedInfo.coreName = "core_full_fe1"; + fedInfo.coreInitString = "-f 1 --autobroker"; - auto Fed1 = std::make_shared("fed1", fi); + auto Fed1 = std::make_shared("fed1", fedInfo); Fed1->enterExecutingModeAsync(helics::IterationRequest::FORCE_ITERATION); Fed1->localError(9827); @@ -1191,11 +1206,11 @@ TEST(federate, forceErrorExecAsync) TEST(federate, forceErrorInitAsync) { - helics::FederateInfo fi(helics::CoreType::TEST); - fi.coreName = "core_full_fe2"; - fi.coreInitString = "-f 1 --autobroker"; + helics::FederateInfo fedInfo(helics::CoreType::TEST); + fedInfo.coreName = "core_full_fe2"; + fedInfo.coreInitString = "-f 1 --autobroker"; - auto Fed1 = std::make_shared("fed1", fi); + auto Fed1 = std::make_shared("fed1", fedInfo); Fed1->enterInitializingModeAsync(); Fed1->localError(9827); @@ -1208,11 +1223,11 @@ TEST(federate, forceErrorInitAsync) TEST(federate, forceErrorPendingTimeAsync) { - helics::FederateInfo fi(helics::CoreType::TEST); - fi.coreName = "core_full_fe3"; - fi.coreInitString = "-f 1 --autobroker"; + helics::FederateInfo fedInfo(helics::CoreType::TEST); + fedInfo.coreName = "core_full_fe3"; + fedInfo.coreInitString = "-f 1 --autobroker"; - auto Fed1 = std::make_shared("fed1", fi); + auto Fed1 = std::make_shared("fed1", fedInfo); Fed1->enterExecutingMode(); Fed1->requestTimeAsync(2.0); @@ -1225,11 +1240,11 @@ TEST(federate, forceErrorPendingTimeAsync) TEST(federate, federateGeneratedLocalError) { - helics::FederateInfo fi(helics::CoreType::TEST); - fi.coreName = "core_full_le"; - fi.coreInitString = "-f 1 --autobroker"; + helics::FederateInfo fedInfo(helics::CoreType::TEST); + fedInfo.coreName = "core_full_le"; + fedInfo.coreInitString = "-f 1 --autobroker"; - auto Fed1 = std::make_shared("fed1", fi); + auto Fed1 = std::make_shared("fed1", fedInfo); Fed1->enterExecutingMode(); Fed1->localError(9827, "user generated error"); @@ -1243,11 +1258,11 @@ TEST(federate, federateGeneratedLocalError) TEST(federate, federateGeneratedGlobalError) { - helics::FederateInfo fi(helics::CoreType::TEST); - fi.coreName = "core_full_ge"; - fi.coreInitString = "-f 1 --autobroker --error_timeout=0"; + helics::FederateInfo fedInfo(helics::CoreType::TEST); + fedInfo.coreName = "core_full_ge"; + fedInfo.coreInitString = "-f 1 --autobroker --error_timeout=0"; - auto Fed1 = std::make_shared("fed1", fi); + auto Fed1 = std::make_shared("fed1", fedInfo); Fed1->enterExecutingMode(); Fed1->requestTimeAsync(2.0); @@ -1263,11 +1278,11 @@ TEST(federate, federateGeneratedGlobalError) TEST(federate, federateGeneratedlocalErrorEscalation) { - helics::FederateInfo fi(helics::CoreType::TEST); - fi.coreName = "core_full_ge"; - fi.coreInitString = "-f 1 --autobroker --error_timeout=0"; + helics::FederateInfo fedInfo(helics::CoreType::TEST); + fedInfo.coreName = "core_full_ge"; + fedInfo.coreInitString = "-f 1 --autobroker --error_timeout=0"; - auto Fed1 = std::make_shared("fed1", fi); + auto Fed1 = std::make_shared("fed1", fedInfo); Fed1->setFlagOption(helics::defs::Flags::TERMINATE_ON_ERROR); Fed1->enterExecutingMode(); Fed1->requestTimeAsync(2.0); @@ -1283,23 +1298,23 @@ TEST(federate, federateGeneratedlocalErrorEscalation) TEST(federate, queryTest1) { - helics::FederateInfo fi(helics::CoreType::TEST); - fi.coreName = "core_q"; - fi.coreInitString = "-f 1 --autobroker"; + helics::FederateInfo fedInfo(helics::CoreType::TEST); + fedInfo.coreName = "core_q"; + fedInfo.coreInitString = "-f 1 --autobroker"; - auto Fed1 = std::make_shared("fed_q", fi); + auto Fed1 = std::make_shared("fed_q", fedInfo); Fed1->enterExecutingMode(); auto qres = Fed1->query("name"); EXPECT_EQ(qres, "\"fed_q\""); qres = Fed1->query("corename"); - auto cr = Fed1->getCorePointer(); - EXPECT_EQ(qres, std::string("\"") + cr->getIdentifier() + '"'); + auto core = Fed1->getCorePointer(); + EXPECT_EQ(qres, std::string("\"") + core->getIdentifier() + '"'); qres = Fed1->query("federate", "name"); EXPECT_EQ(qres, "\"fed_q\""); - cr.reset(); + core.reset(); Fed1->disconnect(); qres = Fed1->query("corename"); // core name should be empty after disconnect @@ -1318,11 +1333,11 @@ TEST(federate, queryTest1) TEST(federate, forceErrorPendingTimeIterativeAsync) { - helics::FederateInfo fi(helics::CoreType::TEST); - fi.coreName = "core_full_fe4"; - fi.coreInitString = "-f 1 --autobroker"; + helics::FederateInfo fedInfo(helics::CoreType::TEST); + fedInfo.coreName = "core_full_fe4"; + fedInfo.coreInitString = "-f 1 --autobroker"; - auto Fed1 = std::make_shared("fed1", fi); + auto Fed1 = std::make_shared("fed1", fedInfo); Fed1->enterExecutingMode(); Fed1->requestTimeIterativeAsync(2.0, helics::IterationRequest::NO_ITERATIONS); @@ -1335,11 +1350,11 @@ TEST(federate, forceErrorPendingTimeIterativeAsync) TEST(federate, forceErrorFinalizeAsync) { - helics::FederateInfo fi(helics::CoreType::TEST); - fi.coreName = "core_full_fe5"; - fi.coreInitString = "-f 1 --autobroker"; + helics::FederateInfo fedInfo(helics::CoreType::TEST); + fedInfo.coreName = "core_full_fe5"; + fedInfo.coreInitString = "-f 1 --autobroker"; - auto Fed1 = std::make_shared("fed1", fi); + auto Fed1 = std::make_shared("fed1", fedInfo); Fed1->enterExecutingMode(); Fed1->finalizeAsync(); @@ -1352,31 +1367,31 @@ TEST(federate, forceErrorFinalizeAsync) TEST(federate, error_after_disconnect) { - helics::FederateInfo fi(helics::CoreType::TEST); - fi.coreName = "core_full_g"; - fi.coreInitString = "-f 1 --autobroker"; + helics::FederateInfo fedInfo(helics::CoreType::TEST); + fedInfo.coreName = "core_full_g"; + fedInfo.coreInitString = "-f 1 --autobroker"; - auto Fed1 = std::make_shared("fed1", fi); - auto& f1 = Fed1->registerGlobalFilter("filt1", "type1", "type2"); + auto Fed1 = std::make_shared("fed1", fedInfo); + auto& filt1 = Fed1->registerGlobalFilter("filt1", "type1", "type2"); Fed1->enterExecutingMode(); Fed1->disconnect(); const auto& Fedref = *Fed1; - auto& fb = Fedref.getFilter(0); - auto& fb2 = Fedref.getFilter("filt1"); - auto& fb3 = Fedref.getFilter("notafilter"); - auto& fb4 = Fed1->getFilter("filt1"); - EXPECT_EQ(fb.getName(), f1.getName()); - EXPECT_EQ(fb2.getName(), f1.getName()); - EXPECT_EQ(fb4.getName(), f1.getName()); - EXPECT_FALSE(fb3.isValid()); + auto& filt1ref1 = Fedref.getFilter(0); + auto& filt1ref2 = Fedref.getFilter("filt1"); + auto& filt1ref3 = Fedref.getFilter("notafilter"); + auto& filt1ref4 = Fed1->getFilter("filt1"); + EXPECT_EQ(filt1ref1.getName(), filt1.getName()); + EXPECT_EQ(filt1ref2.getName(), filt1.getName()); + EXPECT_EQ(filt1ref4.getName(), filt1.getName()); + EXPECT_FALSE(filt1ref3.isValid()); EXPECT_NO_THROW(Fed1->setGlobal("global1", "global1")); - EXPECT_THROW(f1.addSourceTarget("ept"), helics::InvalidFunctionCall); + EXPECT_THROW(filt1.addSourceTarget("ept"), helics::InvalidFunctionCall); EXPECT_NO_THROW(Fed1->addDependency("otherFed")); - EXPECT_THROW(f1.addDestinationTarget("ept"), helics::InvalidFunctionCall); - EXPECT_NO_THROW(Fed1->setFilterOperator(f1, {})); + EXPECT_THROW(filt1.addDestinationTarget("ept"), helics::InvalidFunctionCall); + EXPECT_NO_THROW(Fed1->setFilterOperator(filt1, {})); EXPECT_THROW(Fed1->localError(99), helics::FederateError); EXPECT_THROW(Fed1->globalError(99), helics::FederateError); @@ -1386,22 +1401,22 @@ static constexpr const char* simple_global_files[] = {"example_globals1.json", "example_globals1.toml", "example_globals2.json"}; -class federate_global_files: public ::testing::TestWithParam {}; +class FederateGlobalFiles: public ::testing::TestWithParam {}; -TEST_P(federate_global_files, global_file_ci_skip) +TEST_P(FederateGlobalFiles, global_file_ci_skip) { auto brk = helics::BrokerFactory::create(helics::CoreType::TEST, "b1", "-f 2"); brk->connect(); auto testFile = std::string(TEST_DIR) + GetParam(); brk->makeConnections(testFile); - helics::FederateInfo fi(CORE_TYPE_TO_TEST); - fi.coreName = "core_global1"; - fi.coreInitString = "-f 2"; + helics::FederateInfo fedInfo(CORE_TYPE_TO_TEST); + fedInfo.coreName = "core_global1"; + fedInfo.coreInitString = "-f 2"; - auto Fed1 = std::make_shared("fed1", fi); + auto Fed1 = std::make_shared("fed1", fedInfo); - auto Fed2 = std::make_shared("fed2", fi); + auto Fed2 = std::make_shared("fed2", fedInfo); Fed1->enterInitializingModeAsync(); Fed2->enterInitializingMode(); @@ -1422,22 +1437,22 @@ TEST_P(federate_global_files, global_file_ci_skip) brk->waitForDisconnect(); } -TEST_P(federate_global_files, core_global_file_ci_skip) +TEST_P(FederateGlobalFiles, core_global_file_ci_skip) { auto brk = helics::BrokerFactory::create(helics::CoreType::TEST, "b1", "-f2"); brk->connect(); - helics::FederateInfo fi(CORE_TYPE_TO_TEST); - fi.coreName = "core_global3"; - fi.coreInitString = "-f 1"; + helics::FederateInfo fedInfo(CORE_TYPE_TO_TEST); + fedInfo.coreName = "core_global3"; + fedInfo.coreInitString = "-f 1"; - auto Fed1 = std::make_shared("fed1", fi); - fi.coreName = "core_global4"; - auto Fed2 = std::make_shared("fed2", fi); + auto Fed1 = std::make_shared("fed1", fedInfo); + fedInfo.coreName = "core_global4"; + auto Fed2 = std::make_shared("fed2", fedInfo); - auto cr = Fed1->getCorePointer(); + auto core = Fed1->getCorePointer(); auto testFile = std::string(TEST_DIR) + GetParam(); - cr->makeConnections(testFile); + core->makeConnections(testFile); Fed1->enterInitializingModeAsync(); Fed2->enterInitializingMode(); @@ -1447,7 +1462,7 @@ TEST_P(federate_global_files, core_global_file_ci_skip) EXPECT_EQ(str1, "this is a global1 value"); str1 = Fed2->query("global_value", "global1"); EXPECT_EQ(str1, "this is a global1 value"); - str1 = cr->query("global_value", "global1", HELICS_SEQUENCING_MODE_FAST); + str1 = core->query("global_value", "global1", HELICS_SEQUENCING_MODE_FAST); EXPECT_EQ(str1, "this is a global1 value"); str1 = brk->query("global_value", "global1"); EXPECT_EQ(str1, "this is a global1 value"); @@ -1456,7 +1471,7 @@ TEST_P(federate_global_files, core_global_file_ci_skip) EXPECT_EQ(str1, "this is another global value"); str1 = Fed2->query("global_value", "global2"); EXPECT_EQ(str1, "this is another global value"); - str1 = cr->query("global_value", "global2", HELICS_SEQUENCING_MODE_FAST); + str1 = core->query("global_value", "global2", HELICS_SEQUENCING_MODE_FAST); EXPECT_EQ(str1, "this is another global value"); str1 = brk->query("global_value", "global2"); EXPECT_EQ(str1, "this is another global value"); @@ -1468,8 +1483,8 @@ TEST_P(federate_global_files, core_global_file_ci_skip) EXPECT_NE(str3, "#invalid"); Fed1->finalize(); Fed2->finalize(); - cr = nullptr; + core = nullptr; brk->waitForDisconnect(); } -INSTANTIATE_TEST_SUITE_P(federate, federate_global_files, ::testing::ValuesIn(simple_global_files)); +INSTANTIATE_TEST_SUITE_P(federate, FederateGlobalFiles, ::testing::ValuesIn(simple_global_files)); diff --git a/tests/helics/application_api/FilterAdditionalTests.cpp b/tests/helics/application_api/FilterAdditionalTests.cpp index db1c5c8064..ff6a76b692 100644 --- a/tests/helics/application_api/FilterAdditionalTests.cpp +++ b/tests/helics/application_api/FilterAdditionalTests.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/tests/helics/application_api/FilterTests.cpp b/tests/helics/application_api/FilterTests.cpp index a01f057f5a..2f549d162b 100644 --- a/tests/helics/application_api/FilterTests.cpp +++ b/tests/helics/application_api/FilterTests.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/tests/helics/application_api/GrantTimeoutTests.cpp b/tests/helics/application_api/GrantTimeoutTests.cpp index 0ab33299fb..8ef44e31f8 100644 --- a/tests/helics/application_api/GrantTimeoutTests.cpp +++ b/tests/helics/application_api/GrantTimeoutTests.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/tests/helics/application_api/LoggingTests.cpp b/tests/helics/application_api/LoggingTests.cpp index b6a71a7af8..711377e5c9 100644 --- a/tests/helics/application_api/LoggingTests.cpp +++ b/tests/helics/application_api/LoggingTests.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/tests/helics/application_api/MessageFederateAdditionalTests.cpp b/tests/helics/application_api/MessageFederateAdditionalTests.cpp index d4624f8976..bb7322e374 100644 --- a/tests/helics/application_api/MessageFederateAdditionalTests.cpp +++ b/tests/helics/application_api/MessageFederateAdditionalTests.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -653,6 +653,20 @@ TEST(messageFederate, constructor4) mf1.finalize(); } +TEST(messageFederate, constructorWithSpaceInFilename) +{ + helics::MessageFederate mf1("fed1", + std::string(TEST_DIR) + "example message fed with space.json"); + + mf1.setProperty(HELICS_PROPERTY_INT_LOG_LEVEL, HELICS_LOG_LEVEL_ERROR); + + mf1.registerGlobalFilter("filt1"); + mf1.registerGlobalFilter("filt2"); + + EXPECT_NO_THROW(mf1.enterExecutingMode()); + mf1.finalize(); +} + TEST(messageFederate, constructor5) { helics::MessageFederate mf1("--coretype=test --autobroker --corename=mfc5 --name=fedmd"); diff --git a/tests/helics/application_api/MessageFederateKeyTests.cpp b/tests/helics/application_api/MessageFederateKeyTests.cpp index 8ceb34e98b..10760beee7 100644 --- a/tests/helics/application_api/MessageFederateKeyTests.cpp +++ b/tests/helics/application_api/MessageFederateKeyTests.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/tests/helics/application_api/MultiInputTests.cpp b/tests/helics/application_api/MultiInputTests.cpp index baeff046e6..09a796a09f 100644 --- a/tests/helics/application_api/MultiInputTests.cpp +++ b/tests/helics/application_api/MultiInputTests.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/tests/helics/application_api/PrimaryTypeConversionTests.cpp b/tests/helics/application_api/PrimaryTypeConversionTests.cpp index b3e543239a..08e4240dac 100644 --- a/tests/helics/application_api/PrimaryTypeConversionTests.cpp +++ b/tests/helics/application_api/PrimaryTypeConversionTests.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/tests/helics/application_api/TranslatorTests.cpp b/tests/helics/application_api/TranslatorTests.cpp index 4b405b6885..18fa6da80b 100644 --- a/tests/helics/application_api/TranslatorTests.cpp +++ b/tests/helics/application_api/TranslatorTests.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -30,10 +30,10 @@ SPDX-License-Identifier: BSD-3-Clause /** these test cases test out translator operations */ -class translator: public ::testing::Test, public FederateTestFixture {}; +class TranslatorFixture: public ::testing::Test, public FederateTestFixture {}; /** test registration of translators*/ -TEST_F(translator, translator_registration) +TEST_F(TranslatorFixture, translator_registration) { auto broker = AddBroker("test", 2); @@ -45,14 +45,14 @@ TEST_F(translator, translator_registration) auto fFed = GetFederateAs(0); auto mFed = GetFederateAs(1); - auto& t1 = mFed->registerGlobalTranslator("t1"); + auto& translator1 = mFed->registerGlobalTranslator("t1"); - auto& t2 = fFed->registerTranslator("t2"); + auto& translator2 = fFed->registerTranslator("t2"); - EXPECT_EQ(t1.getName(), "t1"); - EXPECT_EQ(t2.getName(), "filter0/t2"); + EXPECT_EQ(translator1.getName(), "t1"); + EXPECT_EQ(translator2.getName(), "filter0/t2"); - EXPECT_EQ(t1.getSourceTargets(), ""); + EXPECT_EQ(translator1.getSourceTargets(), ""); mFed->finalizeAsync(); fFed->finalize(); @@ -62,7 +62,7 @@ TEST_F(translator, translator_registration) FullDisconnect(); } -TEST_F(translator, translator_queries) +TEST_F(TranslatorFixture, translator_queries) { auto broker = AddBroker("test", 2); @@ -101,7 +101,7 @@ TEST_F(translator, translator_queries) FullDisconnect(); } -TEST_F(translator, translator_connections1) +TEST_F(TranslatorFixture, translator_connections1) { auto broker = AddBroker("test", 2); @@ -114,9 +114,9 @@ TEST_F(translator, translator_connections1) mFed1->registerGlobalTranslator("t1"); - auto& p2 = mFed2->registerPublication("p2", "any"); - p2.setOption(HELICS_HANDLE_OPTION_CONNECTION_REQUIRED); - p2.addDestinationTarget("t1"); + auto& pub2 = mFed2->registerPublication("p2", "any"); + pub2.setOption(HELICS_HANDLE_OPTION_CONNECTION_REQUIRED); + pub2.addDestinationTarget("t1"); mFed2->enterExecutingModeAsync(); mFed1->enterExecutingMode(); EXPECT_NO_THROW(mFed2->enterExecutingModeComplete()); @@ -130,7 +130,7 @@ TEST_F(translator, translator_connections1) FullDisconnect(); } -TEST_F(translator, translator_connections2) +TEST_F(TranslatorFixture, translator_connections2) { auto broker = AddBroker("test", 2); @@ -141,9 +141,9 @@ TEST_F(translator, translator_connections2) auto mFed1 = GetFederateAs(0); auto mFed2 = GetFederateAs(1); - auto& p2 = mFed2->registerPublication("p2", "any"); - p2.setOption(HELICS_HANDLE_OPTION_CONNECTION_REQUIRED); - p2.addDestinationTarget("t1"); + auto& pub2 = mFed2->registerPublication("p2", "any"); + pub2.setOption(HELICS_HANDLE_OPTION_CONNECTION_REQUIRED); + pub2.addDestinationTarget("t1"); std::this_thread::sleep_for(std::chrono::milliseconds(50)); mFed1->registerGlobalTranslator("t1"); mFed2->enterExecutingModeAsync(); @@ -159,7 +159,7 @@ TEST_F(translator, translator_connections2) FullDisconnect(); } -TEST_F(translator, translator_connections3_nosan) +TEST_F(TranslatorFixture, translator_connections3_nosan) { auto broker = AddBroker("test", 2); @@ -180,9 +180,9 @@ TEST_F(translator, translator_connections3_nosan) mFed2->getCorePointer()->setIntegerProperty(helics::gLocalCoreId, HELICS_PROPERTY_INT_LOG_LEVEL, HELICS_LOG_LEVEL_NO_PRINT); - auto& p2 = mFed2->registerPublication("p2", "any"); - p2.setOption(HELICS_HANDLE_OPTION_CONNECTION_REQUIRED); - p2.addDestinationTarget("t2"); + auto& pub2 = mFed2->registerPublication("p2", "any"); + pub2.setOption(HELICS_HANDLE_OPTION_CONNECTION_REQUIRED); + pub2.addDestinationTarget("t2"); std::this_thread::sleep_for(std::chrono::milliseconds(50)); mFed1->registerGlobalTranslator("t1"); mFed2->enterExecutingModeAsync(); @@ -198,7 +198,7 @@ TEST_F(translator, translator_connections3_nosan) FullDisconnect(); } -TEST_F(translator, translator_connections4) +TEST_F(TranslatorFixture, translator_connections4) { auto broker = AddBroker("test", 2); @@ -211,9 +211,9 @@ TEST_F(translator, translator_connections4) mFed1->registerGlobalTranslator("t1"); - auto& p2 = mFed2->registerInput("p2", "any"); - p2.setOption(HELICS_HANDLE_OPTION_CONNECTION_REQUIRED); - p2.addSourceTarget("t1"); + auto& pub2 = mFed2->registerInput("p2", "any"); + pub2.setOption(HELICS_HANDLE_OPTION_CONNECTION_REQUIRED); + pub2.addSourceTarget("t1"); mFed2->enterInitializingModeAsync(); mFed1->enterInitializingMode(); EXPECT_NO_THROW(mFed2->enterInitializingModeComplete()); @@ -227,7 +227,7 @@ TEST_F(translator, translator_connections4) FullDisconnect(); } -TEST_F(translator, translator_connections4_alias) +TEST_F(TranslatorFixture, translator_connections4_alias) { auto broker = AddBroker("test", 2); broker->addAlias("t1", "trans"); @@ -240,9 +240,9 @@ TEST_F(translator, translator_connections4_alias) mFed1->registerGlobalTranslator("t1"); - auto& p2 = mFed2->registerInput("p2", "any"); - p2.setOption(HELICS_HANDLE_OPTION_CONNECTION_REQUIRED); - p2.addSourceTarget("trans"); + auto& pub2 = mFed2->registerInput("p2", "any"); + pub2.setOption(HELICS_HANDLE_OPTION_CONNECTION_REQUIRED); + pub2.addSourceTarget("trans"); mFed2->enterInitializingModeAsync(); mFed1->enterInitializingMode(); EXPECT_NO_THROW(mFed2->enterInitializingModeComplete()); @@ -255,7 +255,7 @@ TEST_F(translator, translator_connections4_alias) FullDisconnect(); } -TEST_F(translator, translator_connections5) +TEST_F(TranslatorFixture, translator_connections5) { auto broker = AddBroker("test", 2); @@ -266,9 +266,9 @@ TEST_F(translator, translator_connections5) auto mFed1 = GetFederateAs(0); auto mFed2 = GetFederateAs(1); - auto& p2 = mFed2->registerInput("p2", "any"); - p2.setOption(HELICS_HANDLE_OPTION_CONNECTION_REQUIRED); - p2.addSourceTarget("t1"); + auto& pub2 = mFed2->registerInput("p2", "any"); + pub2.setOption(HELICS_HANDLE_OPTION_CONNECTION_REQUIRED); + pub2.addSourceTarget("t1"); std::this_thread::sleep_for(std::chrono::milliseconds(50)); mFed1->registerGlobalTranslator("t1"); mFed2->enterInitializingModeAsync(); @@ -284,7 +284,7 @@ TEST_F(translator, translator_connections5) FullDisconnect(); } -TEST_F(translator, translator_connections5_alias) +TEST_F(TranslatorFixture, translator_connections5_alias) { auto broker = AddBroker("test", 2); @@ -296,9 +296,9 @@ TEST_F(translator, translator_connections5_alias) auto mFed1 = GetFederateAs(0); auto mFed2 = GetFederateAs(1); - auto& p2 = mFed2->registerInput("p2", "any"); - p2.setOption(HELICS_HANDLE_OPTION_CONNECTION_REQUIRED); - p2.addSourceTarget("trans"); + auto& pub2 = mFed2->registerInput("p2", "any"); + pub2.setOption(HELICS_HANDLE_OPTION_CONNECTION_REQUIRED); + pub2.addSourceTarget("trans"); std::this_thread::sleep_for(std::chrono::milliseconds(50)); mFed1->registerGlobalTranslator("t1"); mFed2->enterInitializingModeAsync(); @@ -313,7 +313,7 @@ TEST_F(translator, translator_connections5_alias) FullDisconnect(); } -TEST_F(translator, translator_connections6_nosan) +TEST_F(TranslatorFixture, translator_connections6_nosan) { auto broker = AddBroker("test", 2); @@ -334,9 +334,9 @@ TEST_F(translator, translator_connections6_nosan) mFed2->getCorePointer()->setIntegerProperty(helics::gLocalCoreId, HELICS_PROPERTY_INT_LOG_LEVEL, HELICS_LOG_LEVEL_NO_PRINT); - auto& p2 = mFed2->registerInput("p2", "any"); - p2.setOption(HELICS_HANDLE_OPTION_CONNECTION_REQUIRED); - p2.addSourceTarget("t2"); + auto& pub2 = mFed2->registerInput("p2", "any"); + pub2.setOption(HELICS_HANDLE_OPTION_CONNECTION_REQUIRED); + pub2.addSourceTarget("t2"); std::this_thread::sleep_for(std::chrono::milliseconds(50)); mFed1->registerGlobalTranslator("t1"); mFed2->enterInitializingModeAsync(); @@ -352,7 +352,7 @@ TEST_F(translator, translator_connections6_nosan) FullDisconnect(); } -TEST_F(translator, translator_connections7) +TEST_F(TranslatorFixture, translator_connections7) { auto broker = AddBroker("test", 2); @@ -365,9 +365,9 @@ TEST_F(translator, translator_connections7) mFed1->registerGlobalTranslator("t1"); - auto& p2 = mFed2->registerTargetedEndpoint("p2", "any"); - p2.setOption(HELICS_HANDLE_OPTION_CONNECTION_REQUIRED); - p2.addSourceTarget("t1"); + auto& pub2 = mFed2->registerTargetedEndpoint("p2", "any"); + pub2.setOption(HELICS_HANDLE_OPTION_CONNECTION_REQUIRED); + pub2.addSourceTarget("t1"); mFed2->enterInitializingModeAsync(); mFed1->enterInitializingMode(); EXPECT_NO_THROW(mFed2->enterInitializingModeComplete()); @@ -381,7 +381,7 @@ TEST_F(translator, translator_connections7) FullDisconnect(); } -TEST_F(translator, translator_connections8) +TEST_F(TranslatorFixture, translator_connections8) { auto broker = AddBroker("test", 2); @@ -392,9 +392,9 @@ TEST_F(translator, translator_connections8) auto mFed1 = GetFederateAs(0); auto mFed2 = GetFederateAs(1); - auto& p2 = mFed2->registerTargetedEndpoint("p2", "any"); - p2.setOption(HELICS_HANDLE_OPTION_CONNECTION_REQUIRED); - p2.addSourceTarget("t1"); + auto& pub2 = mFed2->registerTargetedEndpoint("p2", "any"); + pub2.setOption(HELICS_HANDLE_OPTION_CONNECTION_REQUIRED); + pub2.addSourceTarget("t1"); std::this_thread::sleep_for(std::chrono::milliseconds(50)); mFed1->registerGlobalTranslator("t1"); mFed2->enterInitializingModeAsync(); @@ -410,7 +410,7 @@ TEST_F(translator, translator_connections8) FullDisconnect(); } -TEST_F(translator, translator_connections9_nosan) +TEST_F(TranslatorFixture, translator_connections9_nosan) { auto broker = AddBroker("test", 2); @@ -431,9 +431,9 @@ TEST_F(translator, translator_connections9_nosan) mFed2->getCorePointer()->setIntegerProperty(helics::gLocalCoreId, HELICS_PROPERTY_INT_LOG_LEVEL, HELICS_LOG_LEVEL_NO_PRINT); - auto& p2 = mFed2->registerTargetedEndpoint("p2", "any"); - p2.setOption(HELICS_HANDLE_OPTION_CONNECTION_REQUIRED); - p2.addSourceTarget("t2"); + auto& pub2 = mFed2->registerTargetedEndpoint("p2", "any"); + pub2.setOption(HELICS_HANDLE_OPTION_CONNECTION_REQUIRED); + pub2.addSourceTarget("t2"); std::this_thread::sleep_for(std::chrono::milliseconds(50)); mFed1->registerGlobalTranslator("t1"); mFed2->enterInitializingModeAsync(); @@ -449,7 +449,7 @@ TEST_F(translator, translator_connections9_nosan) FullDisconnect(); } -TEST_F(translator, translator_connections10) +TEST_F(TranslatorFixture, translator_connections10) { auto broker = AddBroker("test", 1); @@ -457,17 +457,17 @@ TEST_F(translator, translator_connections10) auto cFed1 = GetFederateAs(0); - auto& e1 = cFed1->registerGlobalTargetedEndpoint("e1", "any"); - auto& i1 = cFed1->registerGlobalInput("i1"); - auto& p1 = cFed1->registerGlobalPublication("p1"); - p1.setOption(HELICS_HANDLE_OPTION_CONNECTION_REQUIRED); - e1.setOption(HELICS_HANDLE_OPTION_CONNECTION_REQUIRED); - i1.setOption(HELICS_HANDLE_OPTION_CONNECTION_REQUIRED); + auto& endpoint1 = cFed1->registerGlobalTargetedEndpoint("e1", "any"); + auto& input1 = cFed1->registerGlobalInput("i1"); + auto& pub1 = cFed1->registerGlobalPublication("p1"); + pub1.setOption(HELICS_HANDLE_OPTION_CONNECTION_REQUIRED); + endpoint1.setOption(HELICS_HANDLE_OPTION_CONNECTION_REQUIRED); + input1.setOption(HELICS_HANDLE_OPTION_CONNECTION_REQUIRED); - e1.addSourceTarget("t1"); - p1.addDestinationTarget("t1"); - i1.addSourceTarget("t1"); - e1.addDestinationTarget("t1"); + endpoint1.addSourceTarget("t1"); + pub1.addDestinationTarget("t1"); + input1.addSourceTarget("t1"); + endpoint1.addDestinationTarget("t1"); cFed1->registerGlobalTranslator("t1"); @@ -478,7 +478,7 @@ TEST_F(translator, translator_connections10) FullDisconnect(); } -TEST_F(translator, translator_time_advance) +TEST_F(TranslatorFixture, translator_time_advance) { auto broker = AddBroker("test", 1); @@ -486,17 +486,17 @@ TEST_F(translator, translator_time_advance) auto cFed1 = GetFederateAs(0); - auto& e1 = cFed1->registerGlobalTargetedEndpoint("e1", "any"); - auto& i1 = cFed1->registerGlobalInput("i1"); - auto& p1 = cFed1->registerGlobalPublication("p1"); - p1.setOption(HELICS_HANDLE_OPTION_CONNECTION_REQUIRED); - e1.setOption(HELICS_HANDLE_OPTION_CONNECTION_REQUIRED); - i1.setOption(HELICS_HANDLE_OPTION_CONNECTION_REQUIRED); + auto& endpoint1 = cFed1->registerGlobalTargetedEndpoint("e1", "any"); + auto& input1 = cFed1->registerGlobalInput("i1"); + auto& pub1 = cFed1->registerGlobalPublication("p1"); + pub1.setOption(HELICS_HANDLE_OPTION_CONNECTION_REQUIRED); + endpoint1.setOption(HELICS_HANDLE_OPTION_CONNECTION_REQUIRED); + input1.setOption(HELICS_HANDLE_OPTION_CONNECTION_REQUIRED); - e1.addSourceTarget("t1"); - p1.addDestinationTarget("t1"); - i1.addSourceTarget("t1"); - e1.addDestinationTarget("t1"); + endpoint1.addSourceTarget("t1"); + pub1.addDestinationTarget("t1"); + input1.addSourceTarget("t1"); + endpoint1.addDestinationTarget("t1"); cFed1->registerGlobalTranslator("t1"); @@ -509,7 +509,7 @@ TEST_F(translator, translator_time_advance) FullDisconnect(); } -TEST_F(translator, translator_to_message) +TEST_F(TranslatorFixture, translator_to_message) { auto broker = AddBroker("test", 1); @@ -517,41 +517,41 @@ TEST_F(translator, translator_to_message) auto cFed1 = GetFederateAs(0); - auto& e1 = cFed1->registerGlobalTargetedEndpoint("e1", "any"); - auto& i1 = cFed1->registerGlobalInput("i1"); - auto& p1 = cFed1->registerGlobalPublication("p1"); - p1.setOption(HELICS_HANDLE_OPTION_CONNECTION_REQUIRED); - e1.setOption(HELICS_HANDLE_OPTION_CONNECTION_REQUIRED); - i1.setOption(HELICS_HANDLE_OPTION_CONNECTION_REQUIRED); + auto& endpoint1 = cFed1->registerGlobalTargetedEndpoint("e1", "any"); + auto& input1 = cFed1->registerGlobalInput("i1"); + auto& pub1 = cFed1->registerGlobalPublication("p1"); + pub1.setOption(HELICS_HANDLE_OPTION_CONNECTION_REQUIRED); + endpoint1.setOption(HELICS_HANDLE_OPTION_CONNECTION_REQUIRED); + input1.setOption(HELICS_HANDLE_OPTION_CONNECTION_REQUIRED); - e1.addSourceTarget("t1"); - p1.addDestinationTarget("t1"); - i1.addSourceTarget("t1"); - e1.addDestinationTarget("t1"); + endpoint1.addSourceTarget("t1"); + pub1.addDestinationTarget("t1"); + input1.addSourceTarget("t1"); + endpoint1.addDestinationTarget("t1"); cFed1->registerGlobalTranslator(helics::TranslatorTypes::JSON, "t1"); EXPECT_NO_THROW(cFed1->enterExecutingMode()); - p1.publish(20.7); + pub1.publish(20.7); auto tres = cFed1->requestTime(2.0); EXPECT_LT(tres, 2.0); - EXPECT_TRUE(e1.hasMessage()); - auto m = e1.getMessage(); + EXPECT_TRUE(endpoint1.hasMessage()); + auto message = endpoint1.getMessage(); cFed1->finalize(); - ASSERT_TRUE(m); + ASSERT_TRUE(message); - auto b = helics::fileops::loadJsonStr(m->data.to_string()); + auto json = helics::fileops::loadJsonStr(message->data.to_string()); - ASSERT_TRUE(b.isMember("value")); - ASSERT_TRUE(b.isMember("type")); - EXPECT_DOUBLE_EQ(b["value"].asDouble(), 20.7); - EXPECT_STREQ(b["type"].asCString(), "double"); + ASSERT_TRUE(json.isMember("value")); + ASSERT_TRUE(json.isMember("type")); + EXPECT_DOUBLE_EQ(json["value"].asDouble(), 20.7); + EXPECT_STREQ(json["type"].asCString(), "double"); FullDisconnect(); } -TEST_F(translator, translator_to_message_2fed) +TEST_F(TranslatorFixture, translator_to_message_2fed) { auto broker = AddBroker("test", 2); @@ -561,13 +561,13 @@ TEST_F(translator, translator_to_message_2fed) auto cFed1 = GetFederateAs(0); auto cFed2 = GetFederateAs(1); - auto& e1 = cFed2->registerGlobalTargetedEndpoint("e1", "any"); - auto& p1 = cFed1->registerGlobalPublication("p1"); - p1.setOption(HELICS_HANDLE_OPTION_CONNECTION_REQUIRED); - e1.setOption(HELICS_HANDLE_OPTION_CONNECTION_REQUIRED); + auto& endpoint1 = cFed2->registerGlobalTargetedEndpoint("e1", "any"); + auto& pub1 = cFed1->registerGlobalPublication("p1"); + pub1.setOption(HELICS_HANDLE_OPTION_CONNECTION_REQUIRED); + endpoint1.setOption(HELICS_HANDLE_OPTION_CONNECTION_REQUIRED); - e1.addSourceEndpoint("t1"); - p1.addDestinationTarget("t1"); + endpoint1.addSourceEndpoint("t1"); + pub1.addDestinationTarget("t1"); cFed1->registerGlobalTranslator(helics::TranslatorTypes::JSON, "t1"); @@ -575,28 +575,28 @@ TEST_F(translator, translator_to_message_2fed) cFed2->enterExecutingMode(); cFed1->enterExecutingModeComplete(); - p1.publish(20.7); + pub1.publish(20.7); auto tres = cFed1->requestTime(2.0); EXPECT_EQ(tres, 2.0); tres = cFed2->requestTime(3.0); EXPECT_EQ(tres, 1.0); - EXPECT_TRUE(e1.hasMessage()); - auto m = e1.getMessage(); + EXPECT_TRUE(endpoint1.hasMessage()); + auto message = endpoint1.getMessage(); cFed1->finalize(); cFed2->finalize(); - ASSERT_TRUE(m); + ASSERT_TRUE(message); - auto b = helics::fileops::loadJsonStr(m->data.to_string()); + auto json = helics::fileops::loadJsonStr(message->data.to_string()); - ASSERT_TRUE(b.isMember("value")); - ASSERT_TRUE(b.isMember("type")); - EXPECT_DOUBLE_EQ(b["value"].asDouble(), 20.7); - EXPECT_STREQ(b["type"].asCString(), "double"); + ASSERT_TRUE(json.isMember("value")); + ASSERT_TRUE(json.isMember("type")); + EXPECT_DOUBLE_EQ(json["value"].asDouble(), 20.7); + EXPECT_STREQ(json["type"].asCString(), "double"); FullDisconnect(); } -TEST_F(translator, translator_to_message_target_from_translator) +TEST_F(TranslatorFixture, translator_to_message_target_from_translator) { auto broker = AddBroker("test", 1); @@ -604,37 +604,37 @@ TEST_F(translator, translator_to_message_target_from_translator) auto cFed1 = GetFederateAs(0); - auto& e1 = cFed1->registerGlobalTargetedEndpoint("e1", "any"); - auto& p1 = cFed1->registerGlobalPublication("p1"); + auto& endpoint1 = cFed1->registerGlobalTargetedEndpoint("e1", "any"); + auto& pub1 = cFed1->registerGlobalPublication("p1"); - auto& t1 = cFed1->registerGlobalTranslator(helics::TranslatorTypes::JSON, "t1"); - t1.setOption(HELICS_HANDLE_OPTION_CONNECTION_REQUIRED); + auto& translator1 = cFed1->registerGlobalTranslator(helics::TranslatorTypes::JSON, "t1"); + translator1.setOption(HELICS_HANDLE_OPTION_CONNECTION_REQUIRED); - t1.addSourceEndpoint("e1"); - t1.addDestinationEndpoint("e1"); - t1.addPublication("p1"); + translator1.addSourceEndpoint("e1"); + translator1.addDestinationEndpoint("e1"); + translator1.addPublication("p1"); EXPECT_NO_THROW(cFed1->enterExecutingMode()); - p1.publish(20.7); + pub1.publish(20.7); auto tres = cFed1->requestTime(2.0); EXPECT_LT(tres, 2.0); - EXPECT_TRUE(e1.hasMessage()); - auto m = e1.getMessage(); + EXPECT_TRUE(endpoint1.hasMessage()); + auto message = endpoint1.getMessage(); cFed1->finalize(); - ASSERT_TRUE(m); + ASSERT_TRUE(message); - auto b = helics::fileops::loadJsonStr(m->data.to_string()); + auto json = helics::fileops::loadJsonStr(message->data.to_string()); - ASSERT_TRUE(b.isMember("value")); - ASSERT_TRUE(b.isMember("type")); - EXPECT_DOUBLE_EQ(b["value"].asDouble(), 20.7); - EXPECT_STREQ(b["type"].asCString(), "double"); + ASSERT_TRUE(json.isMember("value")); + ASSERT_TRUE(json.isMember("type")); + EXPECT_DOUBLE_EQ(json["value"].asDouble(), 20.7); + EXPECT_STREQ(json["type"].asCString(), "double"); FullDisconnect(); } -TEST_F(translator, translator_round_trip) +TEST_F(TranslatorFixture, translator_round_trip) { auto broker = AddBroker("test", 1); @@ -642,42 +642,42 @@ TEST_F(translator, translator_round_trip) auto cFed1 = GetFederateAs(0); - auto& e1 = cFed1->registerGlobalTargetedEndpoint("e1", "any"); - auto& i1 = cFed1->registerGlobalInput("i1"); - auto& p1 = cFed1->registerGlobalPublication("p1"); - p1.setOption(HELICS_HANDLE_OPTION_CONNECTION_REQUIRED); - e1.setOption(HELICS_HANDLE_OPTION_CONNECTION_REQUIRED); - i1.setOption(HELICS_HANDLE_OPTION_CONNECTION_REQUIRED); + auto& endpoint1 = cFed1->registerGlobalTargetedEndpoint("e1", "any"); + auto& input1 = cFed1->registerGlobalInput("i1"); + auto& pub1 = cFed1->registerGlobalPublication("p1"); + pub1.setOption(HELICS_HANDLE_OPTION_CONNECTION_REQUIRED); + endpoint1.setOption(HELICS_HANDLE_OPTION_CONNECTION_REQUIRED); + input1.setOption(HELICS_HANDLE_OPTION_CONNECTION_REQUIRED); - e1.addSourceEndpoint("t1"); - p1.addInputTarget("t1"); - i1.addPublication("t1"); - e1.addDestinationEndpoint("t1"); + endpoint1.addSourceEndpoint("t1"); + pub1.addInputTarget("t1"); + input1.addPublication("t1"); + endpoint1.addDestinationEndpoint("t1"); cFed1->registerGlobalTranslator(helics::TranslatorTypes::JSON, "t1"); EXPECT_NO_THROW(cFed1->enterExecutingMode()); - p1.publish(20.7); + pub1.publish(20.7); auto tres = cFed1->requestTime(2.0); EXPECT_LT(tres, 2.0); - EXPECT_TRUE(e1.hasMessage()); - auto m = e1.getMessage(); + EXPECT_TRUE(endpoint1.hasMessage()); + auto message = endpoint1.getMessage(); - ASSERT_TRUE(m); - m->dest.clear(); - e1.send(std::move(m)); + ASSERT_TRUE(message); + message->dest.clear(); + endpoint1.send(std::move(message)); auto tres2 = cFed1->requestTime(2.0); EXPECT_LT(tres2, 2.0); EXPECT_GT(tres2, tres); - EXPECT_FALSE(e1.hasMessage()); - EXPECT_TRUE(i1.isUpdated()); - EXPECT_DOUBLE_EQ(i1.getDouble(), 20.7); + EXPECT_FALSE(endpoint1.hasMessage()); + EXPECT_TRUE(input1.isUpdated()); + EXPECT_DOUBLE_EQ(input1.getDouble(), 20.7); cFed1->finalize(); FullDisconnect(); } -TEST_F(translator, translator_round_trip_target_from_translator) +TEST_F(TranslatorFixture, translator_round_trip_target_from_translator) { auto broker = AddBroker("test", 1); @@ -685,39 +685,39 @@ TEST_F(translator, translator_round_trip_target_from_translator) auto cFed1 = GetFederateAs(0); - auto& e1 = cFed1->registerGlobalTargetedEndpoint("e1", "any"); - auto& i1 = cFed1->registerGlobalInput("i1"); - auto& p1 = cFed1->registerGlobalPublication("p1"); + auto& endpoint1 = cFed1->registerGlobalTargetedEndpoint("e1", "any"); + auto& input1 = cFed1->registerGlobalInput("i1"); + auto& pub1 = cFed1->registerGlobalPublication("p1"); - auto& t1 = cFed1->registerGlobalTranslator(helics::TranslatorTypes::JSON, "t1"); - t1.setOption(HELICS_HANDLE_OPTION_CONNECTION_REQUIRED); - t1.addSourceEndpoint("e1"); - t1.addDestinationEndpoint("e1"); - t1.addPublication("p1"); - t1.addInputTarget("i1"); + auto& translator1 = cFed1->registerGlobalTranslator(helics::TranslatorTypes::JSON, "t1"); + translator1.setOption(HELICS_HANDLE_OPTION_CONNECTION_REQUIRED); + translator1.addSourceEndpoint("e1"); + translator1.addDestinationEndpoint("e1"); + translator1.addPublication("p1"); + translator1.addInputTarget("i1"); EXPECT_NO_THROW(cFed1->enterExecutingMode()); - p1.publish(20.7); + pub1.publish(20.7); auto tres = cFed1->requestTime(2.0); EXPECT_LT(tres, 2.0); - EXPECT_TRUE(e1.hasMessage()); - auto m = e1.getMessage(); + EXPECT_TRUE(endpoint1.hasMessage()); + auto message = endpoint1.getMessage(); - ASSERT_TRUE(m); - m->dest.clear(); - e1.send(std::move(m)); + ASSERT_TRUE(message); + message->dest.clear(); + endpoint1.send(std::move(message)); auto tres2 = cFed1->requestTime(2.0); EXPECT_LT(tres2, 2.0); EXPECT_GT(tres2, tres); - EXPECT_FALSE(e1.hasMessage()); - EXPECT_TRUE(i1.isUpdated()); - EXPECT_DOUBLE_EQ(i1.getDouble(), 20.7); + EXPECT_FALSE(endpoint1.hasMessage()); + EXPECT_TRUE(input1.isUpdated()); + EXPECT_DOUBLE_EQ(input1.getDouble(), 20.7); cFed1->finalize(); FullDisconnect(); } -TEST_F(translator, translator_to_multimessage) +TEST_F(TranslatorFixture, translator_to_multimessage) { auto broker = AddBroker("test", 1); @@ -725,55 +725,55 @@ TEST_F(translator, translator_to_multimessage) auto cFed1 = GetFederateAs(0); - auto& e1 = cFed1->registerGlobalTargetedEndpoint("e1", "any"); - auto& e2 = cFed1->registerGlobalTargetedEndpoint("e2", "any"); - auto& i1 = cFed1->registerGlobalInput("i1"); - auto& p1 = cFed1->registerGlobalPublication("p1"); - p1.setOption(HELICS_HANDLE_OPTION_CONNECTION_REQUIRED); - e1.setOption(HELICS_HANDLE_OPTION_CONNECTION_REQUIRED); - i1.setOption(HELICS_HANDLE_OPTION_CONNECTION_REQUIRED); + auto& endpoint1 = cFed1->registerGlobalTargetedEndpoint("e1", "any"); + auto& endpoint2 = cFed1->registerGlobalTargetedEndpoint("e2", "any"); + auto& input1 = cFed1->registerGlobalInput("i1"); + auto& pub1 = cFed1->registerGlobalPublication("p1"); + pub1.setOption(HELICS_HANDLE_OPTION_CONNECTION_REQUIRED); + endpoint1.setOption(HELICS_HANDLE_OPTION_CONNECTION_REQUIRED); + input1.setOption(HELICS_HANDLE_OPTION_CONNECTION_REQUIRED); - e1.addDestinationEndpoint("t1"); - p1.addInputTarget("t1"); - i1.addPublication("t1"); - e1.addSourceEndpoint("t1"); - e2.addSourceEndpoint("t1"); + endpoint1.addDestinationEndpoint("t1"); + pub1.addInputTarget("t1"); + input1.addPublication("t1"); + endpoint1.addSourceEndpoint("t1"); + endpoint2.addSourceEndpoint("t1"); cFed1->registerGlobalTranslator(helics::TranslatorTypes::JSON, "t1"); EXPECT_NO_THROW(cFed1->enterExecutingMode()); - p1.publish(20.7); + pub1.publish(20.7); auto tres = cFed1->requestTime(2.0); EXPECT_LT(tres, 2.0); - EXPECT_TRUE(e1.hasMessage()); - auto m = e1.getMessage(); + EXPECT_TRUE(endpoint1.hasMessage()); + auto message = endpoint1.getMessage(); - ASSERT_TRUE(m); + ASSERT_TRUE(message); - auto b = helics::fileops::loadJsonStr(m->data.to_string()); + auto json = helics::fileops::loadJsonStr(message->data.to_string()); - ASSERT_TRUE(b.isMember("value")); - ASSERT_TRUE(b.isMember("type")); - EXPECT_DOUBLE_EQ(b["value"].asDouble(), 20.7); - EXPECT_STREQ(b["type"].asCString(), "double"); + ASSERT_TRUE(json.isMember("value")); + ASSERT_TRUE(json.isMember("type")); + EXPECT_DOUBLE_EQ(json["value"].asDouble(), 20.7); + EXPECT_STREQ(json["type"].asCString(), "double"); - EXPECT_TRUE(e2.hasMessage()); - auto m2 = e2.getMessage(); + EXPECT_TRUE(endpoint2.hasMessage()); + auto message2 = endpoint2.getMessage(); cFed1->finalize(); - ASSERT_TRUE(m2); + ASSERT_TRUE(message2); - auto b2 = helics::fileops::loadJsonStr(m2->data.to_string()); + auto json2 = helics::fileops::loadJsonStr(message2->data.to_string()); - ASSERT_TRUE(b2.isMember("value")); - ASSERT_TRUE(b2.isMember("type")); - EXPECT_DOUBLE_EQ(b2["value"].asDouble(), 20.7); - EXPECT_STREQ(b2["type"].asCString(), "double"); + ASSERT_TRUE(json2.isMember("value")); + ASSERT_TRUE(json2.isMember("type")); + EXPECT_DOUBLE_EQ(json2["value"].asDouble(), 20.7); + EXPECT_STREQ(json2["type"].asCString(), "double"); FullDisconnect(); } -TEST_F(translator, translator_from_message) +TEST_F(TranslatorFixture, translator_from_message) { auto broker = AddBroker("test", 1); @@ -781,37 +781,37 @@ TEST_F(translator, translator_from_message) auto cFed1 = GetFederateAs(0); - auto& e1 = cFed1->registerGlobalTargetedEndpoint("e1", "any"); - auto& i1 = cFed1->registerGlobalInput("i1"); - auto& p1 = cFed1->registerGlobalPublication("p1"); - p1.setOption(HELICS_HANDLE_OPTION_CONNECTION_REQUIRED); - e1.setOption(HELICS_HANDLE_OPTION_CONNECTION_REQUIRED); - i1.setOption(HELICS_HANDLE_OPTION_CONNECTION_REQUIRED); + auto& endpoint1 = cFed1->registerGlobalTargetedEndpoint("e1", "any"); + auto& input1 = cFed1->registerGlobalInput("i1"); + auto& pub1 = cFed1->registerGlobalPublication("p1"); + pub1.setOption(HELICS_HANDLE_OPTION_CONNECTION_REQUIRED); + endpoint1.setOption(HELICS_HANDLE_OPTION_CONNECTION_REQUIRED); + input1.setOption(HELICS_HANDLE_OPTION_CONNECTION_REQUIRED); - e1.addSourceTarget("t1"); - p1.addDestinationTarget("t1"); - i1.addSourceTarget("t1"); - e1.addDestinationTarget("t1"); + endpoint1.addSourceTarget("t1"); + pub1.addDestinationTarget("t1"); + input1.addSourceTarget("t1"); + endpoint1.addDestinationTarget("t1"); cFed1->registerGlobalTranslator(helics::TranslatorTypes::JSON, "t1"); EXPECT_NO_THROW(cFed1->enterExecutingMode()); - auto sm = helics::typeConvert(helics::DataType::HELICS_JSON, 20.7); + auto json = helics::typeConvert(helics::DataType::HELICS_JSON, 20.7); std::string val; - helics::valueExtract(sm, helics::DataType::HELICS_JSON, val); - e1.send(val); + helics::valueExtract(json, helics::DataType::HELICS_JSON, val); + endpoint1.send(val); auto tres = cFed1->requestTime(2.0); EXPECT_LT(tres, 2.0); - EXPECT_TRUE(i1.isUpdated()); - EXPECT_DOUBLE_EQ(i1.getValue(), 20.7); + EXPECT_TRUE(input1.isUpdated()); + EXPECT_DOUBLE_EQ(input1.getValue(), 20.7); cFed1->finalize(); FullDisconnect(); } -TEST_F(translator, translator_from_message_2fed) +TEST_F(TranslatorFixture, translator_from_message_2fed) { auto broker = AddBroker("test", 2); @@ -820,14 +820,14 @@ TEST_F(translator, translator_from_message_2fed) auto cFed1 = GetFederateAs(0); auto cFed2 = GetFederateAs(1); - auto& e1 = cFed1->registerGlobalTargetedEndpoint("e1", "any"); - auto& i1 = cFed2->registerGlobalInput("i1"); + auto& endpoint1 = cFed1->registerGlobalTargetedEndpoint("e1", "any"); + auto& input1 = cFed2->registerGlobalInput("i1"); - e1.setOption(HELICS_HANDLE_OPTION_CONNECTION_REQUIRED); - i1.setOption(HELICS_HANDLE_OPTION_CONNECTION_REQUIRED); + endpoint1.setOption(HELICS_HANDLE_OPTION_CONNECTION_REQUIRED); + input1.setOption(HELICS_HANDLE_OPTION_CONNECTION_REQUIRED); - i1.addSourceTarget("t1"); - e1.addDestinationTarget("t1"); + input1.addSourceTarget("t1"); + endpoint1.addDestinationTarget("t1"); cFed1->registerGlobalTranslator(helics::TranslatorTypes::JSON, "t1"); @@ -835,25 +835,25 @@ TEST_F(translator, translator_from_message_2fed) EXPECT_NO_THROW(cFed1->enterExecutingMode()); cFed2->enterExecutingModeComplete(); - auto sm = helics::typeConvert(helics::DataType::HELICS_JSON, 20.7); - std::string val{sm.to_string()}; + auto data = helics::typeConvert(helics::DataType::HELICS_JSON, 20.7); + std::string val{data.to_string()}; - e1.send(val); + endpoint1.send(val); // there should be no dependencies here so it should grant immediately auto tres = cFed1->requestTime(3.0); EXPECT_EQ(tres, 3.0); tres = cFed2->requestTime(3.0); EXPECT_EQ(tres, 1.0); - EXPECT_TRUE(i1.isUpdated()); - EXPECT_DOUBLE_EQ(i1.getValue(), 20.7); + EXPECT_TRUE(input1.isUpdated()); + EXPECT_DOUBLE_EQ(input1.getValue(), 20.7); cFed1->finalize(); cFed2->finalize(); FullDisconnect(); } -TEST_F(translator, translator_multiinput) +TEST_F(TranslatorFixture, translator_multiinput) { auto broker = AddBroker("test", 1); @@ -861,35 +861,110 @@ TEST_F(translator, translator_multiinput) auto cFed1 = GetFederateAs(0); - auto& e1 = cFed1->registerGlobalTargetedEndpoint("e1", "any"); - auto& i1 = cFed1->registerGlobalInput("i1"); - auto& i2 = cFed1->registerGlobalInput("i2"); - auto& p1 = cFed1->registerGlobalPublication("p1"); - p1.setOption(HELICS_HANDLE_OPTION_CONNECTION_REQUIRED); - e1.setOption(HELICS_HANDLE_OPTION_CONNECTION_REQUIRED); - i1.setOption(HELICS_HANDLE_OPTION_CONNECTION_REQUIRED); + auto& endpoint1 = cFed1->registerGlobalTargetedEndpoint("e1", "any"); + auto& input1 = cFed1->registerGlobalInput("i1"); + auto& input2 = cFed1->registerGlobalInput("i2"); + auto& pub1 = cFed1->registerGlobalPublication("p1"); + pub1.setOption(HELICS_HANDLE_OPTION_CONNECTION_REQUIRED); + endpoint1.setOption(HELICS_HANDLE_OPTION_CONNECTION_REQUIRED); + input1.setOption(HELICS_HANDLE_OPTION_CONNECTION_REQUIRED); - e1.addSourceTarget("t1"); - p1.addDestinationTarget("t1"); - i1.addSourceTarget("t1"); - i2.addSourceTarget("t1"); - e1.addDestinationTarget("t1"); + endpoint1.addSourceTarget("t1"); + pub1.addDestinationTarget("t1"); + input1.addSourceTarget("t1"); + input2.addSourceTarget("t1"); + endpoint1.addDestinationTarget("t1"); cFed1->registerGlobalTranslator(helics::TranslatorTypes::JSON, "t1"); EXPECT_NO_THROW(cFed1->enterExecutingMode()); - auto sm = helics::typeConvert(helics::DataType::HELICS_JSON, 20.7); + auto data = helics::typeConvert(helics::DataType::HELICS_JSON, 20.7); std::string val; - helics::valueExtract(sm, helics::DataType::HELICS_JSON, val); - e1.send(val); + helics::valueExtract(data, helics::DataType::HELICS_JSON, val); + endpoint1.send(val); auto tres = cFed1->requestTime(2.0); EXPECT_LT(tres, 2.0); - EXPECT_TRUE(i1.isUpdated()); - EXPECT_DOUBLE_EQ(i1.getValue(), 20.7); + EXPECT_TRUE(input1.isUpdated()); + EXPECT_DOUBLE_EQ(input1.getValue(), 20.7); - EXPECT_TRUE(i2.isUpdated()); - EXPECT_DOUBLE_EQ(i2.getValue(), 20.7); + EXPECT_TRUE(input2.isUpdated()); + EXPECT_DOUBLE_EQ(input2.getValue(), 20.7); + cFed1->finalize(); + + FullDisconnect(); +} + +TEST_F(TranslatorFixture, translator_config) +{ + auto broker = AddBroker("test", 1); + + auto cFed1 = std::make_shared(std::string(TEST_DIR) + + "ControllerConfig.json"); + + EXPECT_NO_THROW(cFed1->enterExecutingMode()); + + EXPECT_EQ(cFed1->getTranslatorCount(), 5U); + EXPECT_EQ(cFed1->getInputCount(), 5U); + + auto& trans1 = cFed1->getTranslator(0); + + EXPECT_EQ(trans1.getName(), "EV_1_translator"); + + cFed1->query("broker", "global_flush"); + auto dflow = cFed1->query("broker", "data_flow_graph"); + auto fnd = dflow.find("EV_2_translator"); + EXPECT_NE(fnd, std::string::npos); + cFed1->finalize(); + + FullDisconnect(); +} + +TEST_F(TranslatorFixture, translator_config_json) +{ + auto broker = AddBroker("test", 1); + + auto cFed1 = std::make_shared(std::string(TEST_DIR) + + "example_translators.json"); + + EXPECT_NO_THROW(cFed1->enterExecutingMode()); + + EXPECT_EQ(cFed1->getTranslatorCount(), 5U); + EXPECT_EQ(cFed1->getInputCount(), 5U); + + auto& trans1 = cFed1->getTranslator(0); + + EXPECT_EQ(trans1.getName(), "EV_1_translator"); + + cFed1->query("broker", "global_flush"); + auto dflow = cFed1->query("broker", "data_flow_graph"); + auto fnd = dflow.find("EV_2_translator"); + EXPECT_NE(fnd, std::string::npos); + cFed1->finalize(); + + FullDisconnect(); +} + +TEST_F(TranslatorFixture, translator_config_toml) +{ + auto broker = AddBroker("test", 1); + + auto cFed1 = std::make_shared(std::string(TEST_DIR) + + "example_translators.toml"); + + EXPECT_NO_THROW(cFed1->enterExecutingMode()); + + EXPECT_EQ(cFed1->getTranslatorCount(), 5U); + EXPECT_EQ(cFed1->getInputCount(), 5U); + + auto& trans1 = cFed1->getTranslator(0); + + EXPECT_EQ(trans1.getName(), "EV_1_translator"); + + cFed1->query("broker", "global_flush"); + auto dflow = cFed1->query("broker", "data_flow_graph"); + auto fnd = dflow.find("EV_2_translator"); + EXPECT_NE(fnd, std::string::npos); cFed1->finalize(); FullDisconnect(); diff --git a/tests/helics/application_api/ValueConverterTests.cpp b/tests/helics/application_api/ValueConverterTests.cpp index c7cb80848b..5b38779e90 100644 --- a/tests/helics/application_api/ValueConverterTests.cpp +++ b/tests/helics/application_api/ValueConverterTests.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/tests/helics/application_api/ValueFederateAdditionalTests.cpp b/tests/helics/application_api/ValueFederateAdditionalTests.cpp index 29b385aebc..ddab5ddbd8 100644 --- a/tests/helics/application_api/ValueFederateAdditionalTests.cpp +++ b/tests/helics/application_api/ValueFederateAdditionalTests.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -645,6 +645,44 @@ TEST(valuefed_json_tests, file_loadb) helics::CoreFactory::terminateAllCores(); } +TEST(valuefed_json_tests, file_loadb_with_space) +{ + helics::ValueFederate vFed(std::string(TEST_DIR) + + "folder with space/example_value_fed_testb.json"); + + EXPECT_EQ(vFed.getName(), "valueFed2"); + + EXPECT_EQ(vFed.getInputCount(), 3); + EXPECT_EQ(vFed.getPublicationCount(), 2); + auto& id = vFed.getPublication("primary"); + + EXPECT_EQ(id.getName(), "valueFed2/pub2"); + + auto& id2 = vFed.getPublication("pub1"); + EXPECT_EQ(id2.getUnits(), "m"); + + EXPECT_EQ(id2.getTag("description"), "a test publication"); + EXPECT_EQ(std::stod(id2.getTag("period")), 0.5); + + auto& inp2 = vFed.getInput("ipt2"); + EXPECT_EQ(inp2.getTag("description"), "a test input"); + EXPECT_EQ(std::stod(inp2.getTag("period")), 0.7); + + EXPECT_EQ(vFed.getTag("description"), "fedb description"); + EXPECT_EQ(vFed.getTag("version"), "27"); + + auto& sub1 = vFed.getInput(0); + vFed.enterInitializingMode(); + + auto dv = sub1.getDouble(); + EXPECT_DOUBLE_EQ(dv, 9.33); + dv = inp2.getDouble(); + EXPECT_DOUBLE_EQ(dv, 3.67); + vFed.disconnect(); + helics::BrokerFactory::terminateAllBrokers(); + helics::CoreFactory::terminateAllCores(); +} + TEST(valuefederate, toml_file_loadb) { helics::ValueFederate vFed(std::string(TEST_DIR) + "example_value_fed_testb.toml"); diff --git a/tests/helics/application_api/ValueFederateDualTransfer.cpp b/tests/helics/application_api/ValueFederateDualTransfer.cpp index 13a6ead0d0..9f4ade0451 100644 --- a/tests/helics/application_api/ValueFederateDualTransfer.cpp +++ b/tests/helics/application_api/ValueFederateDualTransfer.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/tests/helics/application_api/ValueFederateKeyTests.cpp b/tests/helics/application_api/ValueFederateKeyTests.cpp index 4cf5037577..d5a2779d80 100644 --- a/tests/helics/application_api/ValueFederateKeyTests.cpp +++ b/tests/helics/application_api/ValueFederateKeyTests.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/tests/helics/application_api/ValueFederateSingleTransfer.cpp b/tests/helics/application_api/ValueFederateSingleTransfer.cpp index a810c55449..c4327aeed5 100644 --- a/tests/helics/application_api/ValueFederateSingleTransfer.cpp +++ b/tests/helics/application_api/ValueFederateSingleTransfer.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/tests/helics/application_api/ValueFederateTestTemplates.hpp b/tests/helics/application_api/ValueFederateTestTemplates.hpp index da9f1b6db7..9ae591c9c3 100644 --- a/tests/helics/application_api/ValueFederateTestTemplates.hpp +++ b/tests/helics/application_api/ValueFederateTestTemplates.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/tests/helics/application_api/applicationApiTests.cpp b/tests/helics/application_api/applicationApiTests.cpp index 28d1a992dc..5f940784ed 100644 --- a/tests/helics/application_api/applicationApiTests.cpp +++ b/tests/helics/application_api/applicationApiTests.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/tests/helics/application_api/data_viewTests.cpp b/tests/helics/application_api/data_viewTests.cpp index 2e778fd4f3..bfe2a432e7 100644 --- a/tests/helics/application_api/data_viewTests.cpp +++ b/tests/helics/application_api/data_viewTests.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/tests/helics/application_api/helicsTypeTests.cpp b/tests/helics/application_api/helicsTypeTests.cpp index e3a034752c..fb9169f43c 100644 --- a/tests/helics/application_api/helicsTypeTests.cpp +++ b/tests/helics/application_api/helicsTypeTests.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/tests/helics/application_api/subPubObjectTests.cpp b/tests/helics/application_api/subPubObjectTests.cpp index c3e3fa7e56..39ba21c1d9 100644 --- a/tests/helics/application_api/subPubObjectTests.cpp +++ b/tests/helics/application_api/subPubObjectTests.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/tests/helics/application_api/testFixtures.cpp b/tests/helics/application_api/testFixtures.cpp index 3777e8be9d..635bc1ddae 100644 --- a/tests/helics/application_api/testFixtures.cpp +++ b/tests/helics/application_api/testFixtures.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/tests/helics/application_api/testFixtures.hpp b/tests/helics/application_api/testFixtures.hpp index 255167707a..d01935101c 100644 --- a/tests/helics/application_api/testFixtures.hpp +++ b/tests/helics/application_api/testFixtures.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/tests/helics/application_api/testFixtures_shared.cpp b/tests/helics/application_api/testFixtures_shared.cpp index 8412721125..5a6b88ba07 100644 --- a/tests/helics/application_api/testFixtures_shared.cpp +++ b/tests/helics/application_api/testFixtures_shared.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/tests/helics/application_api/testFixtures_shared.hpp b/tests/helics/application_api/testFixtures_shared.hpp index 78c0ad24d3..7a7fd23058 100644 --- a/tests/helics/application_api/testFixtures_shared.hpp +++ b/tests/helics/application_api/testFixtures_shared.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/tests/helics/application_api/zmqSSTests.cpp b/tests/helics/application_api/zmqSSTests.cpp index 0043e34046..cc093eef20 100644 --- a/tests/helics/application_api/zmqSSTests.cpp +++ b/tests/helics/application_api/zmqSSTests.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/tests/helics/apps/BrokerAppTests.cpp b/tests/helics/apps/BrokerAppTests.cpp index 2002c32039..5dba8fac6f 100644 --- a/tests/helics/apps/BrokerAppTests.cpp +++ b/tests/helics/apps/BrokerAppTests.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/tests/helics/apps/BrokerServerTests.cpp b/tests/helics/apps/BrokerServerTests.cpp index 535673f7df..99f4419979 100644 --- a/tests/helics/apps/BrokerServerTests.cpp +++ b/tests/helics/apps/BrokerServerTests.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/tests/helics/apps/CMakeLists.txt b/tests/helics/apps/CMakeLists.txt index 9409b76d80..c9ff4aa191 100644 --- a/tests/helics/apps/CMakeLists.txt +++ b/tests/helics/apps/CMakeLists.txt @@ -1,5 +1,5 @@ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Copyright (c) 2017-2023, Battelle Memorial Institute; Lawrence Livermore +# Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore # National Security, LLC; Alliance for Sustainable Energy, LLC. # See the top-level NOTICE for additional details. # All rights reserved. @@ -24,6 +24,11 @@ set(helics_apps_test_sources BrokerAppTests.cpp MultiBrokerTests.cpp ProbeTests.cpp + ConnectorTests.cpp + ConnectorTests2.cpp + ConnectorFileTests.cpp + Connector2StageTests.cpp + ConnectorTagTests.cpp exeTestHelper.h ) diff --git a/tests/helics/apps/CloneTests.cpp b/tests/helics/apps/CloneTests.cpp index 1c9803796d..6d10a82725 100644 --- a/tests/helics/apps/CloneTests.cpp +++ b/tests/helics/apps/CloneTests.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -94,8 +94,6 @@ TEST(clone_tests, simple_clone_test_pub2) fi2.coreInitString = "--autobroker"; fi2.coreType = helics::CoreType::TEST; helics::apps::Player p1("p1", fi2); - p1.loadFile("pubtest2.json"); - p1.initialize(); EXPECT_EQ(p1.pointCount(), 3U); @@ -144,7 +142,6 @@ TEST(clone_tests, simple_clone_test_message) fi2.coreInitString = "--autobroker"; fi2.coreType = helics::CoreType::TEST; helics::apps::Player p1("p1", fi2); - p1.loadFile("eptsave.json"); p1.initialize(); @@ -222,7 +219,6 @@ TEST(clone_tests, simple_clone_test_combo) fi2.coreInitString = "--autobroker"; fi2.coreType = helics::CoreType::TEST; helics::apps::Player p1("p1", fi2); - p1.loadFile("combsave.json"); p1.initialize(); @@ -295,7 +291,6 @@ TEST(clone_tests, simple_clone_test_sub) fi2.coreInitString = "--autobroker"; fi2.coreType = helics::CoreType::TEST; helics::apps::Player p1("p1", fi2); - p1.loadFile("subtest.json"); p1.initialize(); diff --git a/tests/helics/apps/Connector2StageTests.cpp b/tests/helics/apps/Connector2StageTests.cpp new file mode 100644 index 0000000000..de1e040574 --- /dev/null +++ b/tests/helics/apps/Connector2StageTests.cpp @@ -0,0 +1,1306 @@ +/* +Copyright (c) 2017-2024, +Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable +Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. +SPDX-License-Identifier: BSD-3-Clause +*/ +#include "gtest/gtest.h" +#include +#ifndef DISABLE_SYSTEM_CALL_TESTS +# include "exeTestHelper.h" +#endif + +#include "helics/apps/BrokerApp.hpp" +#include "helics/apps/Connector.hpp" +#include "helics/apps/CoreApp.hpp" +#include "helics/common/JsonProcessingFunctions.hpp" + +#include +#include +#include + +static std::string newCoreName(std::string_view baseName) +{ + static std::atomic count = 1; + int value = ++count; + + return std::string(baseName) + std::to_string(value); +} + +class CheckFed { + public: + CheckFed(std::string_view name, const helics::FederateInfo& fedInfo): + vFed(std::make_shared(name, fedInfo)) + { + } + void initialize() + { + vFed->setQueryCallback( + [this](std::string_view query) { return generateQueryResponse(query); }); + vFed->enterInitializingModeIterative(); + // this must be done twice + vFed->enterInitializingModeIterative(); + bool hasCommand{true}; + while (hasCommand) { + auto cmd = vFed->getCommand(); + hasCommand = !cmd.first.empty(); + if (hasCommand) { + auto json = helics::fileops::loadJsonStr(cmd.first); + if (json.isMember("command")) { + if (json["command"] == "register_interfaces") { + receivedCommand = true; + if (json.isMember("publications")) { + for (const auto& pub : json["publications"]) { + const std::string pubName = pub.asString(); + if (std::find(potentialPubs.begin(), + potentialPubs.end(), + pubName) != potentialPubs.end()) { + vFed->registerGlobalPublication(pubName); + } + } + } + if (json.isMember("inputs")) { + for (const auto& input : json["inputs"]) { + const std::string inputName = input.asString(); + if (std::find(potentialInputs.begin(), + potentialInputs.end(), + inputName) != potentialInputs.end()) { + vFed->registerGlobalInput(inputName); + valueNames.push_back(inputName); + } + } + } + if (json.isMember("endpoints")) { + for (const auto& endpoint : json["endpoints"]) { + const std::string endpointName = endpoint.asString(); + if (std::find(potentialEndpoints.begin(), + potentialEndpoints.end(), + endpointName) != potentialEndpoints.end()) { + vFed->registerGlobalTargetedEndpoint(endpointName); + messageNames.push_back(endpointName); + } + } + } + } + } + } + } + values.resize(vFed->getInputCount()); + messages.resize(vFed->getEndpointCount()); + vFed->enterInitializingMode(); + } + + void executing() { vFed->enterExecutingMode(); } + + void run(helics::Time endTime) + { + helics::Time time = helics::timeZero; + + while (time < endTime) { + for (int ii = 0; ii < vFed->getPublicationCount(); ++ii) { + vFed->getPublication(ii).publish(time); + } + for (int ii = 0; ii < vFed->getInputCount(); ++ii) { + auto& ipt = vFed->getInput(ii); + if (ipt.isUpdated()) { + values[ii].push_back(ipt.getDouble()); + } + } + for (int ii = 0; ii < vFed->getEndpointCount(); ++ii) { + auto& ept = vFed->getEndpoint(ii); + while (ept.hasMessage()) { + messages[ii].emplace_back(ept.getMessage()->to_string()); + } + ept.send("message@" + std::to_string(static_cast(time))); + } + time = vFed->requestTime(endTime); + } + } + + void finalize() { vFed->finalize(); } + std::string generateQueryResponse(std::string_view query) + { + ResponseType type = responseType.load(); + + if (query == "potential_interfaces") { + Json::Value interfaces; + switch (type) { + case ResponseType::EVIL: { + Json::Value istruct = Json::objectValue; + istruct["key"] = "test"; + istruct["global"] = false; + istruct["target"] = "bullseye"; + + interfaces["inputs"].append(istruct); + interfaces["inputs"].append(istruct); + interfaces["publications"] = false; + interfaces["endpoints"] = "this should be fun"; + } break; + case ResponseType::LIST: { + if (!potentialInputs.empty()) { + interfaces["inputs"] = Json::arrayValue; + for (const auto& pInput : potentialInputs) { + interfaces["inputs"].append(pInput); + } + } + if (!potentialPubs.empty()) { + interfaces["publications"] = Json::arrayValue; + for (const auto& pPub : potentialPubs) { + interfaces["publications"].append(pPub); + } + } + if (!potentialEndpoints.empty()) { + interfaces["endpoints"] = Json::arrayValue; + for (const auto& pEpt : potentialEndpoints) { + interfaces["endpoints"].append(pEpt); + } + } + } break; + case ResponseType::STRUCTURE: { + if (!potentialInputs.empty()) { + interfaces["inputs"] = Json::arrayValue; + for (const auto& pInput : potentialInputs) { + Json::Value Obj = Json::objectValue; + Obj["key"] = pInput; + Obj["units"] = "V"; + interfaces["inputs"].append(Obj); + } + } + if (!potentialPubs.empty()) { + interfaces["publications"] = Json::arrayValue; + for (const auto& pPub : potentialPubs) { + Json::Value Obj = Json::objectValue; + Obj["key"] = pPub; + Obj["units"] = "V"; + interfaces["publications"].append(Obj); + } + } + if (!potentialEndpoints.empty()) { + interfaces["endpoints"] = Json::arrayValue; + for (const auto& pEpt : potentialEndpoints) { + Json::Value Obj = Json::objectValue; + Obj["key"] = pEpt; + Obj["type"] = "type1"; + interfaces["endpoints"].append(Obj); + } + } + } break; + } + return helics::fileops::generateJsonString(interfaces); + } + return std::string{}; + } + void addPotentialInputs(const std::vector& potInputs) + { + potentialInputs.insert(potentialInputs.end(), potInputs.begin(), potInputs.end()); + } + + void addPotentialPubs(const std::vector& potPubs) + { + potentialPubs.insert(potentialPubs.end(), potPubs.begin(), potPubs.end()); + } + + void addPotentialEndpoints(const std::vector& potEndpoints) + { + potentialEndpoints.insert(potentialEndpoints.end(), + potEndpoints.begin(), + potEndpoints.end()); + } + /** get the values array*/ + const auto& getValues(const std::string& input) const + { + static const std::vector emptyVals; + + for (int ii = 0; ii < valueNames.size(); ++ii) { + if (valueNames[ii] == input) { + return values[ii]; + } + } + return emptyVals; + } + /** get the values array*/ + const auto& getMessages(const std::string& endpoint) + { + static const std::vector emptyVals; + + for (int ii = 0; ii < messageNames.size(); ++ii) { + if (messageNames[ii] == endpoint) { + return messages[ii]; + } + } + return emptyVals; + } + + const auto& getValueNames() { return valueNames; } + const auto& getMessageNames() { return messageNames; } + bool hasReceivedCommand() const { return receivedCommand; } + + public: + enum class ResponseType { LIST, STRUCTURE, EVIL }; + std::atomic responseType{ResponseType::LIST}; + + private: + std::shared_ptr vFed; + std::vector potentialInputs; + std::vector potentialPubs; + std::vector potentialEndpoints; + std::vector valueNames; + std::vector> values; + std::vector> messages; + std::vector messageNames; + bool receivedCommand = true; +}; + +TEST(connector_2stage, simple_connector) +{ + helics::FederateInfo fedInfo(helics::CoreType::TEST); + using helics::apps::InterfaceDirection; + + fedInfo.coreName = newCoreName("core2stage"); + fedInfo.coreInitString = "-f2 --autobroker"; + fedInfo.setProperty(HELICS_PROPERTY_TIME_PERIOD, 1.0); + helics::apps::Connector conn1("connector1", fedInfo); + conn1.addConnection("inp1", "pub1", InterfaceDirection::FROM_TO); + + fedInfo.coreInitString = ""; + CheckFed cfed1("c1", fedInfo); + cfed1.addPotentialInputs({"inp1", "inp2"}); + cfed1.addPotentialPubs({"pub1", "pub3"}); + + auto fut = std::async(std::launch::async, [&conn1]() { conn1.run(); }); + cfed1.initialize(); + cfed1.executing(); + cfed1.run(5); + cfed1.finalize(); + fut.get(); + ASSERT_EQ(cfed1.getValueNames().size(), 1); + EXPECT_FALSE(cfed1.getValues("inp1").empty()); + EXPECT_EQ(conn1.madeConnections(), 1); +} + +TEST(connector_2stage, simple_connector_struct) +{ + helics::FederateInfo fedInfo(helics::CoreType::TEST); + using helics::apps::InterfaceDirection; + + fedInfo.coreName = newCoreName("core2stage"); + fedInfo.coreInitString = "-f2 --autobroker"; + fedInfo.setProperty(HELICS_PROPERTY_TIME_PERIOD, 1.0); + helics::apps::Connector conn1("connector1", fedInfo); + conn1.addConnection("inp1", "pub1", InterfaceDirection::FROM_TO); + + fedInfo.coreInitString = ""; + CheckFed cfed1("c1", fedInfo); + cfed1.addPotentialInputs({"inp1", "inp2"}); + cfed1.addPotentialPubs({"pub1", "pub3"}); + cfed1.responseType = CheckFed::ResponseType::STRUCTURE; + + auto fut = std::async(std::launch::async, [&conn1]() { conn1.run(); }); + cfed1.initialize(); + cfed1.executing(); + cfed1.run(5); + cfed1.finalize(); + fut.get(); + ASSERT_EQ(cfed1.getValueNames().size(), 1); + EXPECT_FALSE(cfed1.getValues("inp1").empty()); + EXPECT_EQ(conn1.madeConnections(), 1); +} + +TEST(connector_2stage, simple_endpoint_connector) +{ + helics::FederateInfo fedInfo(helics::CoreType::TEST); + using helics::apps::InterfaceDirection; + + fedInfo.coreName = newCoreName("core2stage"); + fedInfo.coreInitString = "-f2 --autobroker"; + fedInfo.setProperty(HELICS_PROPERTY_TIME_PERIOD, 1.0); + helics::apps::Connector conn1("connectore1", fedInfo); + conn1.addConnection("ept1", "ept2", InterfaceDirection::BIDIRECTIONAL); + + fedInfo.coreInitString = ""; + CheckFed cfed1("c1", fedInfo); + cfed1.addPotentialEndpoints({"ept1", "ept2"}); + + auto fut = std::async(std::launch::async, [&conn1]() { conn1.run(); }); + cfed1.initialize(); + cfed1.executing(); + cfed1.run(5); + cfed1.finalize(); + fut.get(); + ASSERT_EQ(cfed1.getMessageNames().size(), 2); + EXPECT_FALSE(cfed1.getMessages("ept1").empty()); + EXPECT_FALSE(cfed1.getMessages("ept2").empty()); + EXPECT_EQ(conn1.madeConnections(), 2); +} + +TEST(connector_2stage, simple_endpoint_connector_struct) +{ + helics::FederateInfo fedInfo(helics::CoreType::TEST); + using helics::apps::InterfaceDirection; + + fedInfo.coreName = newCoreName("core2stage"); + fedInfo.coreInitString = "-f2 --autobroker"; + fedInfo.setProperty(HELICS_PROPERTY_TIME_PERIOD, 1.0); + helics::apps::Connector conn1("connectore1", fedInfo); + conn1.addConnection("ept1", "ept2", InterfaceDirection::BIDIRECTIONAL); + + fedInfo.coreInitString = ""; + CheckFed cfed1("c1", fedInfo); + cfed1.addPotentialEndpoints({"ept1", "ept2"}); + cfed1.responseType = CheckFed::ResponseType::STRUCTURE; + auto fut = std::async(std::launch::async, [&conn1]() { conn1.run(); }); + cfed1.initialize(); + cfed1.executing(); + cfed1.run(5); + cfed1.finalize(); + fut.get(); + ASSERT_EQ(cfed1.getMessageNames().size(), 2); + EXPECT_FALSE(cfed1.getMessages("ept1").empty()); + EXPECT_FALSE(cfed1.getMessages("ept2").empty()); + EXPECT_EQ(conn1.madeConnections(), 2); +} + +TEST(connector_2stage, evil_federate) +{ + helics::FederateInfo fedInfo(helics::CoreType::TEST); + using helics::apps::InterfaceDirection; + + fedInfo.coreName = newCoreName("core2stage"); + fedInfo.coreInitString = "-f2 --autobroker"; + fedInfo.setProperty(HELICS_PROPERTY_TIME_PERIOD, 1.0); + helics::apps::Connector conn1("connectorevil1", fedInfo); + conn1.addConnection("ept1", "ept2", InterfaceDirection::BIDIRECTIONAL); + + fedInfo.coreInitString = ""; + CheckFed cfed1("c1", fedInfo); + cfed1.addPotentialEndpoints({"ept1", "ept2"}); + cfed1.responseType = CheckFed::ResponseType::EVIL; + auto fut = std::async(std::launch::async, [&conn1]() { conn1.run(); }); + cfed1.initialize(); + cfed1.executing(); + cfed1.run(5); + cfed1.finalize(); + EXPECT_NO_THROW(fut.get()); +} + +TEST(connector_2stage, simple_endpoint_connector_one_way) +{ + helics::FederateInfo fedInfo(helics::CoreType::TEST); + using helics::apps::InterfaceDirection; + + fedInfo.coreName = newCoreName("core2stage"); + fedInfo.coreInitString = "-f2 --autobroker"; + fedInfo.setProperty(HELICS_PROPERTY_TIME_PERIOD, 1.0); + helics::apps::Connector conn1("connectore1", fedInfo); + conn1.addConnection("ept1", "ept2", InterfaceDirection::FROM_TO); + + fedInfo.coreInitString = ""; + CheckFed cfed1("c1", fedInfo); + cfed1.addPotentialEndpoints({"ept1", "ept2"}); + + auto fut = std::async(std::launch::async, [&conn1]() { conn1.run(); }); + cfed1.initialize(); + cfed1.executing(); + cfed1.run(5); + cfed1.finalize(); + fut.get(); + ASSERT_EQ(cfed1.getMessageNames().size(), 2); + EXPECT_TRUE(cfed1.getMessages("ept1").empty()); + EXPECT_FALSE(cfed1.getMessages("ept2").empty()); + EXPECT_EQ(conn1.madeConnections(), 1); +} + +TEST(connector_2stage, no_connections) +{ + helics::FederateInfo fedInfo(helics::CoreType::TEST); + using helics::apps::InterfaceDirection; + + fedInfo.coreName = newCoreName("core2stage"); + fedInfo.coreInitString = "-f2 --autobroker"; + fedInfo.setProperty(HELICS_PROPERTY_TIME_PERIOD, 1.0); + helics::apps::Connector conn1("connectore1", fedInfo); + conn1.addConnection("ept1", "ept2", InterfaceDirection::FROM_TO); + + fedInfo.coreInitString = ""; + CheckFed cfed1("c1", fedInfo); + cfed1.addPotentialEndpoints({"ept10", "ept20"}); + + auto fut = std::async(std::launch::async, [&conn1]() { conn1.run(); }); + cfed1.initialize(); + cfed1.executing(); + cfed1.run(5); + cfed1.finalize(); + fut.get(); + ASSERT_EQ(cfed1.getMessageNames().size(), 0); + EXPECT_EQ(conn1.madeConnections(), 0); + EXPECT_TRUE(cfed1.hasReceivedCommand()); +} + +TEST(connector_2stage, simple_endpoint_connector_one_way_reverse) +{ + helics::FederateInfo fedInfo(helics::CoreType::TEST); + using helics::apps::InterfaceDirection; + + fedInfo.coreName = newCoreName("core2stage"); + fedInfo.coreInitString = "-f2 --autobroker"; + fedInfo.setProperty(HELICS_PROPERTY_TIME_PERIOD, 1.0); + helics::apps::Connector conn1("connectore3", fedInfo); + conn1.addConnection("ept1", "ept2", InterfaceDirection::TO_FROM); + + fedInfo.coreInitString = ""; + CheckFed cfed1("c1", fedInfo); + cfed1.addPotentialEndpoints({"ept1", "ept2"}); + + auto fut = std::async(std::launch::async, [&conn1]() { conn1.run(); }); + cfed1.initialize(); + cfed1.executing(); + cfed1.run(5); + cfed1.finalize(); + fut.get(); + ASSERT_EQ(cfed1.getMessageNames().size(), 2); + EXPECT_FALSE(cfed1.getMessages("ept1").empty()); + EXPECT_TRUE(cfed1.getMessages("ept2").empty()); + EXPECT_EQ(conn1.madeConnections(), 1); +} + +TEST(connector_2stage, three_fed) +{ + helics::FederateInfo fedInfo(helics::CoreType::TEST); + using helics::apps::InterfaceDirection; + + fedInfo.coreName = newCoreName("core2stage"); + fedInfo.coreInitString = "-f3 --autobroker"; + fedInfo.setProperty(HELICS_PROPERTY_TIME_PERIOD, 1.0); + helics::apps::Connector conn1("connector2", fedInfo); + conn1.addConnection("inp1", "pub1", InterfaceDirection::FROM_TO); + + fedInfo.coreInitString = ""; + CheckFed cfed1("c1", fedInfo); + cfed1.addPotentialInputs({"inp1", "inp2"}); + + helics::ValueFederate vFed2("v2", fedInfo); + auto& pub1 = vFed2.registerGlobalPublication("pub1"); + vFed2.enterExecutingModeAsync(); + + auto fut = std::async(std::launch::async, [&conn1]() { conn1.run(); }); + auto fut2 = std::async(std::launch::async, [&cfed1]() { + cfed1.initialize(); + cfed1.executing(); + cfed1.run(5); + cfed1.finalize(); + }); + vFed2.enterExecutingModeComplete(); + pub1.publish(1.0); + vFed2.requestTime(2.0); + pub1.publish(2.0); + vFed2.requestTime(3.0); + pub1.publish(3.0); + vFed2.disconnect(); + fut.get(); + fut2.get(); + ASSERT_EQ(cfed1.getValueNames().size(), 1); + EXPECT_EQ(cfed1.getValues("inp1").size(), 3); + EXPECT_EQ(conn1.madeConnections(), 1); +} + +TEST(connector_2stage, three_fed_endpoint) +{ + helics::FederateInfo fedInfo(helics::CoreType::TEST); + using helics::apps::InterfaceDirection; + + fedInfo.coreName = newCoreName("core2stage"); + fedInfo.coreInitString = "-f3 --autobroker"; + fedInfo.setProperty(HELICS_PROPERTY_TIME_PERIOD, 1.0); + helics::apps::Connector conn1("connectore5", fedInfo); + conn1.addConnection("ept1", "oept1", InterfaceDirection::TO_FROM); + + fedInfo.coreInitString = ""; + CheckFed cfed1("c1", fedInfo); + cfed1.addPotentialEndpoints({"ept1", "ept2", "ept3"}); + + helics::MessageFederate mFed2("m2", fedInfo); + auto& ept1 = mFed2.registerGlobalTargetedEndpoint("oept1"); + mFed2.enterExecutingModeAsync(); + + auto fut = std::async(std::launch::async, [&conn1]() { conn1.run(); }); + auto fut2 = std::async(std::launch::async, [&cfed1]() { + cfed1.initialize(); + cfed1.executing(); + cfed1.run(5); + cfed1.finalize(); + }); + mFed2.enterExecutingModeComplete(); + ept1.send("string1"); + mFed2.requestTime(2.0); + ept1.send("string2"); + mFed2.requestTime(3.0); + ept1.send("string3"); + mFed2.disconnect(); + fut.get(); + fut2.get(); + ASSERT_EQ(cfed1.getMessageNames().size(), 1); + EXPECT_EQ(cfed1.getMessages("ept1").size(), 3); + EXPECT_EQ(conn1.madeConnections(), 1); +} + +TEST(connector_2stage, three_fed_endpoint_bi) +{ + helics::FederateInfo fedInfo(helics::CoreType::TEST); + using helics::apps::InterfaceDirection; + + fedInfo.coreName = newCoreName("core2stage"); + fedInfo.coreInitString = "-f3 --autobroker"; + fedInfo.setProperty(HELICS_PROPERTY_TIME_PERIOD, 1.0); + helics::apps::Connector conn1("connectore6", fedInfo); + conn1.addConnection("ept1", "oept1", InterfaceDirection::BIDIRECTIONAL); + + fedInfo.coreInitString = ""; + CheckFed cfed1("c1", fedInfo); + cfed1.addPotentialEndpoints({"ept1", "ept2", "ept3"}); + + helics::MessageFederate mFed2("m2", fedInfo); + auto& ept1 = mFed2.registerGlobalTargetedEndpoint("oept1"); + mFed2.enterExecutingModeAsync(); + + auto fut = std::async(std::launch::async, [&conn1]() { conn1.run(); }); + auto fut2 = std::async(std::launch::async, [&cfed1]() { + cfed1.initialize(); + cfed1.executing(); + cfed1.run(5); + cfed1.finalize(); + }); + mFed2.enterExecutingModeComplete(); + ept1.send("string1"); + mFed2.requestTime(2.0); + ept1.send("string2"); + mFed2.requestTime(3.0); + ept1.send("string3"); + mFed2.disconnect(); + fut.get(); + fut2.get(); + ASSERT_EQ(cfed1.getMessageNames().size(), 1); + EXPECT_EQ(cfed1.getMessages("ept1").size(), 3); + EXPECT_EQ(conn1.madeConnections(), 2); +} + +TEST(connector_2stage, three_fed_reverse) +{ + helics::FederateInfo fedInfo(helics::CoreType::TEST); + using helics::apps::InterfaceDirection; + + fedInfo.coreName = newCoreName("core2stage"); + fedInfo.coreInitString = "-f3 --autobroker"; + fedInfo.setProperty(HELICS_PROPERTY_TIME_PERIOD, 1.0); + helics::apps::Connector conn1("connector3", fedInfo); + conn1.addConnection("pub1", "inp1", InterfaceDirection::FROM_TO); + + fedInfo.coreInitString = ""; + CheckFed cfed1("c1", fedInfo); + cfed1.addPotentialInputs({"inp1", "inp2"}); + + helics::ValueFederate vFed2("v2", fedInfo); + auto& pub1 = vFed2.registerGlobalPublication("pub1"); + vFed2.enterExecutingModeAsync(); + + auto fut = std::async(std::launch::async, [&conn1]() { conn1.run(); }); + auto fut2 = std::async(std::launch::async, [&cfed1]() { + cfed1.initialize(); + cfed1.executing(); + cfed1.run(5); + cfed1.finalize(); + }); + vFed2.enterExecutingModeComplete(); + pub1.publish(1.0); + vFed2.requestTime(2.0); + pub1.publish(2.0); + vFed2.requestTime(3.0); + pub1.publish(3.0); + vFed2.disconnect(); + fut.get(); + fut2.get(); + ASSERT_EQ(cfed1.getValueNames().size(), 1); + EXPECT_EQ(cfed1.getValues("inp1").size(), 3); + EXPECT_EQ(conn1.madeConnections(), 1); +} + +TEST(connector_2stage, three_fed_input) +{ + helics::FederateInfo fedInfo(helics::CoreType::TEST); + using helics::apps::InterfaceDirection; + + fedInfo.coreName = newCoreName("core2stage"); + fedInfo.coreInitString = "-f3 --autobroker"; + fedInfo.setProperty(HELICS_PROPERTY_TIME_PERIOD, 1.0); + helics::apps::Connector conn1("connector4", fedInfo); + conn1.addConnection("inp1", "publication1", InterfaceDirection::FROM_TO); + conn1.addConnection("publication1", "pub1", InterfaceDirection::FROM_TO); + fedInfo.coreInitString = ""; + CheckFed cfed1("c1", fedInfo); + cfed1.addPotentialPubs({"pub1", "pub2"}); + + helics::ValueFederate vFed2("v2", fedInfo); + auto& inp1 = vFed2.registerGlobalInput("inp1"); + vFed2.enterExecutingModeAsync(); + + auto fut = std::async(std::launch::async, [&conn1]() { conn1.run(); }); + auto fut2 = std::async(std::launch::async, [&cfed1]() { + cfed1.initialize(); + cfed1.executing(); + cfed1.run(5); + cfed1.finalize(); + }); + vFed2.enterExecutingModeComplete(); + std::vector data; + if (inp1.isUpdated()) { + data.push_back(inp1.getDouble()); + } + vFed2.requestTime(2.0); + if (inp1.isUpdated()) { + data.push_back(inp1.getDouble()); + } + vFed2.requestTime(3.0); + if (inp1.isUpdated()) { + data.push_back(inp1.getDouble()); + } + vFed2.disconnect(); + fut.get(); + fut2.get(); + EXPECT_GE(data.size(), 1); + EXPECT_EQ(conn1.madeConnections(), 1); +} + +TEST(connector_2stage, three_fed_input_regex) +{ + helics::FederateInfo fedInfo(helics::CoreType::TEST); + using helics::apps::InterfaceDirection; + + fedInfo.coreName = newCoreName("core2stage"); + fedInfo.coreInitString = "-f3 --autobroker"; + fedInfo.setProperty(HELICS_PROPERTY_TIME_PERIOD, 1.0); + helics::apps::Connector conn1("connector4", fedInfo); + conn1.addConnection("REGEX:Battery/EV(?.)_input_voltage", + "REGEX:Charger/EV(?.)_output_voltage", + InterfaceDirection::FROM_TO); + fedInfo.coreInitString = ""; + CheckFed cfed1("c1", fedInfo); + cfed1.addPotentialPubs({"Charger/EV1_output_voltage", "pub2"}); + + helics::ValueFederate vFed2("Battery", fedInfo); + auto& inp1 = vFed2.registerInput("EV1_input_voltage"); + vFed2.enterExecutingModeAsync(); + + auto fut = std::async(std::launch::async, [&conn1]() { conn1.run(); }); + auto fut2 = std::async(std::launch::async, [&cfed1]() { + cfed1.initialize(); + cfed1.executing(); + cfed1.run(5); + cfed1.finalize(); + }); + vFed2.enterExecutingModeComplete(); + std::vector data; + if (inp1.isUpdated()) { + data.push_back(inp1.getDouble()); + } + vFed2.requestTime(2.0); + if (inp1.isUpdated()) { + data.push_back(inp1.getDouble()); + } + vFed2.requestTime(3.0); + if (inp1.isUpdated()) { + data.push_back(inp1.getDouble()); + } + vFed2.disconnect(); + fut.get(); + fut2.get(); + EXPECT_GE(data.size(), 1); + EXPECT_EQ(conn1.madeConnections(), 1); +} + +TEST(connector_2stage, three_fed_input_alias) +{ + helics::FederateInfo fedInfo(helics::CoreType::TEST); + using helics::apps::InterfaceDirection; + + fedInfo.coreName = newCoreName("core2stage"); + fedInfo.coreInitString = "-f3 --autobroker"; + fedInfo.setProperty(HELICS_PROPERTY_TIME_PERIOD, 1.0); + helics::apps::Connector conn1("connector5", fedInfo); + conn1.addConnection("input1", "pub1", InterfaceDirection::FROM_TO); + fedInfo.coreInitString = ""; + CheckFed cfed1("c1", fedInfo); + cfed1.addPotentialPubs({"pub1", "pub2"}); + + helics::ValueFederate vFed2("v2", fedInfo); + auto& inp1 = vFed2.registerGlobalInput("inp1"); + inp1.addAlias("input1"); + vFed2.enterExecutingModeAsync(); + + auto fut = std::async(std::launch::async, [&conn1]() { conn1.run(); }); + auto fut2 = std::async(std::launch::async, [&cfed1]() { + cfed1.initialize(); + cfed1.executing(); + cfed1.run(5); + cfed1.finalize(); + }); + vFed2.enterExecutingModeComplete(); + std::vector data; + if (inp1.isUpdated()) { + data.push_back(inp1.getDouble()); + } + vFed2.requestTime(2.0); + if (inp1.isUpdated()) { + data.push_back(inp1.getDouble()); + } + vFed2.requestTime(3.0); + if (inp1.isUpdated()) { + data.push_back(inp1.getDouble()); + } + vFed2.disconnect(); + fut.get(); + fut2.get(); + EXPECT_GE(data.size(), 1); + EXPECT_EQ(conn1.madeConnections(), 1); +} + +TEST(connector_2stage, three_fed_alias_reverse) +{ + helics::FederateInfo fedInfo(helics::CoreType::TEST); + using helics::apps::InterfaceDirection; + + fedInfo.coreName = newCoreName("core2stage"); + fedInfo.coreInitString = "-f3 --autobroker"; + fedInfo.setProperty(HELICS_PROPERTY_TIME_PERIOD, 1.0); + helics::apps::Connector conn1("connector6", fedInfo); + conn1.addConnection("publication1", "inp1", InterfaceDirection::FROM_TO); + + fedInfo.coreInitString = ""; + CheckFed cfed1("c1", fedInfo); + cfed1.addPotentialInputs({"inp1", "inp2"}); + + helics::ValueFederate vFed2("v2", fedInfo); + auto& pub1 = vFed2.registerGlobalPublication("pub1"); + pub1.addAlias("publication1"); + vFed2.enterExecutingModeAsync(); + + auto fut = std::async(std::launch::async, [&conn1]() { conn1.run(); }); + auto fut2 = std::async(std::launch::async, [&cfed1]() { + cfed1.initialize(); + cfed1.executing(); + cfed1.run(5); + cfed1.finalize(); + }); + vFed2.enterExecutingModeComplete(); + pub1.publish(1.0); + vFed2.requestTime(2.0); + pub1.publish(2.0); + vFed2.requestTime(3.0); + pub1.publish(3.0); + vFed2.disconnect(); + fut.get(); + fut2.get(); + ASSERT_EQ(cfed1.getValueNames().size(), 1); + EXPECT_EQ(cfed1.getValues("inp1").size(), 3); + EXPECT_EQ(conn1.madeConnections(), 1); +} + +TEST(connector_2stage, three_fed_potential_alias) +{ + helics::FederateInfo fedInfo(helics::CoreType::TEST); + using helics::apps::InterfaceDirection; + + fedInfo.coreName = newCoreName("core2stage"); + fedInfo.coreInitString = "-f3 --autobroker"; + fedInfo.setProperty(HELICS_PROPERTY_TIME_PERIOD, 1.0); + helics::apps::Connector conn1("connector7", fedInfo); + conn1.addConnection("publication1", "input1", InterfaceDirection::FROM_TO); + + fedInfo.coreInitString = ""; + CheckFed cfed1("c1", fedInfo); + cfed1.addPotentialInputs({"inp1", "inp2"}); + + helics::ValueFederate vFed2("v2", fedInfo); + + helics::CoreApp core(vFed2.getCorePointer()); + core.addAlias("inp1", "input1"); + auto& pub1 = vFed2.registerGlobalPublication("pub1"); + pub1.addAlias("publication1"); + vFed2.enterExecutingModeAsync(); + + auto fut = std::async(std::launch::async, [&conn1]() { conn1.run(); }); + auto fut2 = std::async(std::launch::async, [&cfed1]() { + cfed1.initialize(); + cfed1.executing(); + cfed1.run(5); + cfed1.finalize(); + }); + vFed2.enterExecutingModeComplete(); + pub1.publish(1.0); + vFed2.requestTime(2.0); + pub1.publish(2.0); + vFed2.requestTime(3.0); + pub1.publish(3.0); + vFed2.disconnect(); + fut.get(); + fut2.get(); + ASSERT_EQ(cfed1.getValueNames().size(), 1); + EXPECT_EQ(cfed1.getValues("inp1").size(), 3); + EXPECT_EQ(conn1.madeConnections(), 1); +} + +TEST(connector_2stage, three_fed_potential_alias_reverse) +{ + helics::FederateInfo fedInfo(helics::CoreType::TEST); + using helics::apps::InterfaceDirection; + + fedInfo.coreName = newCoreName("core2stage"); + fedInfo.coreInitString = "-f3 --autobroker"; + fedInfo.setProperty(HELICS_PROPERTY_TIME_PERIOD, 1.0); + helics::apps::Connector conn1("connector8", fedInfo); + conn1.addConnection("input1", "publication1", InterfaceDirection::FROM_TO); + + fedInfo.coreInitString = ""; + CheckFed cfed1("c1", fedInfo); + cfed1.addPotentialInputs({"inp1", "inp2"}); + + helics::ValueFederate vFed2("v2", fedInfo); + + helics::CoreApp core(vFed2.getCorePointer()); + core.addAlias("inp1", "input1"); + auto& pub1 = vFed2.registerGlobalPublication("pub1"); + pub1.addAlias("publication1"); + vFed2.enterExecutingModeAsync(); + + auto fut = std::async(std::launch::async, [&conn1]() { conn1.run(); }); + auto fut2 = std::async(std::launch::async, [&cfed1]() { + cfed1.initialize(); + cfed1.executing(); + cfed1.run(5); + cfed1.finalize(); + }); + vFed2.enterExecutingModeComplete(); + pub1.publish(1.0); + vFed2.requestTime(2.0); + pub1.publish(2.0); + vFed2.requestTime(3.0); + pub1.publish(3.0); + vFed2.disconnect(); + fut.get(); + fut2.get(); + ASSERT_EQ(cfed1.getValueNames().size(), 1); + EXPECT_EQ(cfed1.getValues("inp1").size(), 3); + EXPECT_EQ(conn1.madeConnections(), 1); +} + +TEST(connector_2stage, three_fed_potential_cascade_alias_reverse) +{ + helics::FederateInfo fedInfo(helics::CoreType::TEST); + using helics::apps::InterfaceDirection; + + fedInfo.coreName = newCoreName("core2stage"); + fedInfo.coreInitString = "-f3 --autobroker"; + fedInfo.setProperty(HELICS_PROPERTY_TIME_PERIOD, 1.0); + helics::apps::Connector conn1("connector9", fedInfo); + conn1.addConnection("inputA", "publicationA", InterfaceDirection::FROM_TO); + + fedInfo.coreInitString = ""; + CheckFed cfed1("c1", fedInfo); + cfed1.addPotentialInputs({"inp1", "inp2"}); + + helics::ValueFederate vFed2("v2", fedInfo); + + helics::CoreApp core(vFed2.getCorePointer()); + core.addAlias("inp1", "input1"); + core.addAlias("publicationA", "publication1"); + core.addAlias("input1", "inputA"); + auto& pub1 = vFed2.registerGlobalPublication("pub1"); + pub1.addAlias("publication1"); + vFed2.enterExecutingModeAsync(); + + auto fut = std::async(std::launch::async, [&conn1]() { conn1.run(); }); + auto fut2 = std::async(std::launch::async, [&cfed1]() { + cfed1.initialize(); + cfed1.executing(); + cfed1.run(5); + cfed1.finalize(); + }); + vFed2.enterExecutingModeComplete(); + pub1.publish(1.0); + vFed2.requestTime(2.0); + pub1.publish(2.0); + vFed2.requestTime(3.0); + pub1.publish(3.0); + vFed2.disconnect(); + fut.get(); + fut2.get(); + ASSERT_EQ(cfed1.getValueNames().size(), 1); + EXPECT_EQ(cfed1.getValues("inp1").size(), 3); + EXPECT_EQ(conn1.madeConnections(), 1); +} + +TEST(connector_2stage, three_fed_alias_unmatched_connection) +{ + helics::FederateInfo fedInfo(helics::CoreType::TEST); + using helics::apps::InterfaceDirection; + + fedInfo.coreName = newCoreName("core2stage"); + fedInfo.coreInitString = "-f3 --autobroker"; + fedInfo.setProperty(HELICS_PROPERTY_TIME_PERIOD, 1.0); + helics::apps::Connector conn1("connector10", fedInfo); + + fedInfo.coreInitString = ""; + CheckFed cfed1("c1", fedInfo); + cfed1.addPotentialInputs({"inp1", "inp2"}); + + helics::ValueFederate vFed2("v2", fedInfo); + auto& pub1 = vFed2.registerGlobalPublication("pub1"); + pub1.addAlias("publication1"); + helics::CoreApp core(vFed2.getCorePointer()); + core.dataLink("publication1", "input1"); + core.addAlias("inp1", "input1"); + vFed2.enterExecutingModeAsync(); + + auto fut = std::async(std::launch::async, [&conn1]() { conn1.run(); }); + auto fut2 = std::async(std::launch::async, [&cfed1]() { + cfed1.initialize(); + cfed1.executing(); + cfed1.run(5); + cfed1.finalize(); + }); + vFed2.enterExecutingModeComplete(); + pub1.publish(1.0); + vFed2.requestTime(2.0); + pub1.publish(2.0); + vFed2.requestTime(3.0); + pub1.publish(3.0); + vFed2.disconnect(); + fut.get(); + fut2.get(); + ASSERT_EQ(cfed1.getValueNames().size(), 1); + EXPECT_EQ(cfed1.getValues("inp1").size(), 3); + // no connections through the connector made + EXPECT_EQ(conn1.madeConnections(), 0); +} + +TEST(connector_2stage, three_fed_unknown_pub_alias) +{ + helics::FederateInfo fedInfo(helics::CoreType::TEST); + using helics::apps::InterfaceDirection; + + fedInfo.coreName = newCoreName("core2stage"); + fedInfo.coreInitString = "-f3 --autobroker"; + fedInfo.setProperty(HELICS_PROPERTY_TIME_PERIOD, 1.0); + helics::apps::Connector conn1("connector11", fedInfo); + fedInfo.coreInitString = ""; + CheckFed cfed1("c1", fedInfo); + cfed1.addPotentialPubs({"pub1", "pub2"}); + + helics::ValueFederate vFed2("v2", fedInfo); + auto& inp1 = vFed2.registerGlobalInput("inp1"); + inp1.addAlias("input1"); + helics::CoreApp core(vFed2.getCorePointer()); + core.dataLink("publication1", "input1"); + core.addAlias("pub1", "publication1"); + + inp1.addAlias("input1"); + vFed2.enterExecutingModeAsync(); + + auto fut = std::async(std::launch::async, [&conn1]() { conn1.run(); }); + auto fut2 = std::async(std::launch::async, [&cfed1]() { + cfed1.initialize(); + cfed1.executing(); + cfed1.run(5); + cfed1.finalize(); + }); + vFed2.enterExecutingModeComplete(); + std::vector data; + if (inp1.isUpdated()) { + data.push_back(inp1.getDouble()); + } + vFed2.requestTime(2.0); + if (inp1.isUpdated()) { + data.push_back(inp1.getDouble()); + } + vFed2.requestTime(3.0); + if (inp1.isUpdated()) { + data.push_back(inp1.getDouble()); + } + vFed2.disconnect(); + fut.get(); + fut2.get(); + EXPECT_GE(data.size(), 1); + EXPECT_EQ(conn1.madeConnections(), 0); +} + +TEST(connector_2stage, three_fed_endpoint_bi_alias) +{ + helics::FederateInfo fedInfo(helics::CoreType::TEST); + using helics::apps::InterfaceDirection; + + fedInfo.coreName = newCoreName("core2stage"); + fedInfo.coreInitString = "-f3 --autobroker"; + fedInfo.setProperty(HELICS_PROPERTY_TIME_PERIOD, 1.0); + helics::apps::Connector conn1("connectore7", fedInfo); + conn1.addConnection("bigEndpoint", "origin", InterfaceDirection::BIDIRECTIONAL); + + fedInfo.coreInitString = ""; + CheckFed cfed1("c1", fedInfo); + cfed1.addPotentialEndpoints({"ept1", "ept2", "ept3"}); + + helics::MessageFederate mFed2("m2", fedInfo); + + helics::CoreApp core(mFed2.getCorePointer()); + auto& ept1 = mFed2.registerGlobalTargetedEndpoint("oept1"); + ept1.addAlias("origin"); + core.addAlias("ept1", "bigEndpoint"); + mFed2.enterExecutingModeAsync(); + + auto fut = std::async(std::launch::async, [&conn1]() { conn1.run(); }); + auto fut2 = std::async(std::launch::async, [&cfed1]() { + cfed1.initialize(); + cfed1.executing(); + cfed1.run(5); + cfed1.finalize(); + }); + mFed2.enterExecutingModeComplete(); + ept1.send("string1"); + mFed2.requestTime(2.0); + ept1.send("string2"); + mFed2.requestTime(3.0); + ept1.send("string3"); + mFed2.disconnect(); + fut.get(); + fut2.get(); + ASSERT_EQ(cfed1.getMessageNames().size(), 1); + EXPECT_EQ(cfed1.getMessages("ept1").size(), 3); + EXPECT_EQ(conn1.madeConnections(), 2); +} + +TEST(connector_2stage, three_fed_endpoint_dual_bi_alias) +{ + helics::FederateInfo fedInfo(helics::CoreType::TEST); + using helics::apps::InterfaceDirection; + + fedInfo.coreName = newCoreName("core2stage"); + fedInfo.coreInitString = "-f3 --autobroker"; + fedInfo.setProperty(HELICS_PROPERTY_TIME_PERIOD, 1.0); + helics::apps::Connector conn1("connectore8", fedInfo); + conn1.addConnection("bigEndpoint", "origin", InterfaceDirection::BIDIRECTIONAL); + conn1.addConnection("origin", "secondary", InterfaceDirection::BIDIRECTIONAL); + conn1.allowMultipleConnections(); + fedInfo.coreInitString = ""; + CheckFed cfed1("c1", fedInfo); + cfed1.addPotentialEndpoints({"ept1", "ept2", "ept3"}); + + helics::MessageFederate mFed2("m2", fedInfo); + + helics::CoreApp core(mFed2.getCorePointer()); + auto& ept1 = mFed2.registerGlobalTargetedEndpoint("oept1"); + ept1.addAlias("origin"); + core.addAlias("ept1", "bigEndpoint"); + core.addAlias("ept2", "secondary"); + mFed2.enterExecutingModeAsync(); + + auto fut = std::async(std::launch::async, [&conn1]() { conn1.run(); }); + auto fut2 = std::async(std::launch::async, [&cfed1]() { + cfed1.initialize(); + cfed1.executing(); + cfed1.run(5); + cfed1.finalize(); + }); + mFed2.enterExecutingModeComplete(); + ept1.send("string1"); + mFed2.requestTime(2.0); + ept1.send("string2"); + mFed2.requestTime(3.0); + ept1.send("string3"); + mFed2.disconnect(); + fut.get(); + fut2.get(); + ASSERT_EQ(cfed1.getMessageNames().size(), 2); + EXPECT_EQ(cfed1.getMessages("ept1").size(), 7); + EXPECT_EQ(conn1.madeConnections(), 6); +} + +TEST(connector_2stage, two_sided_broker_connection) +{ + helics::FederateInfo fedInfo(helics::CoreType::TEST); + using helics::apps::InterfaceDirection; + + fedInfo.coreName = newCoreName("core2stage"); + fedInfo.coreInitString = "-f2 --autobroker"; + fedInfo.setProperty(HELICS_PROPERTY_TIME_PERIOD, 1.0); + helics::apps::Connector conn1("connector1", fedInfo); + + fedInfo.coreInitString = ""; + CheckFed cfed1("c1", fedInfo); + cfed1.addPotentialInputs({"inp1", "inp2"}); + cfed1.addPotentialPubs({"pub1", "pub2", "pub3"}); + + helics::CoreApp core(fedInfo.coreName); + core.dataLink("pub1", "inp1"); + core.dataLink("pub2", "inp2"); + + auto fut = std::async(std::launch::async, [&conn1]() { conn1.run(); }); + cfed1.initialize(); + cfed1.executing(); + cfed1.run(5); + cfed1.finalize(); + fut.get(); + ASSERT_EQ(cfed1.getValueNames().size(), 2); + EXPECT_FALSE(cfed1.getValues("inp1").empty()); + EXPECT_FALSE(cfed1.getValues("inp2").empty()); + // not making any connections + EXPECT_EQ(conn1.madeConnections(), 0); +} + +TEST(connector_2stage, two_sided_broker_connection_alias) +{ + helics::FederateInfo fedInfo(helics::CoreType::TEST); + using helics::apps::InterfaceDirection; + + fedInfo.coreName = newCoreName("core2stage"); + fedInfo.coreInitString = "-f2 --autobroker"; + fedInfo.setProperty(HELICS_PROPERTY_TIME_PERIOD, 1.0); + helics::apps::Connector conn1("connector1", fedInfo); + + fedInfo.coreInitString = ""; + CheckFed cfed1("c1", fedInfo); + cfed1.addPotentialInputs({"inp1", "inp2"}); + cfed1.addPotentialPubs({"pub1", "pub2", "pub3"}); + + helics::CoreApp core(fedInfo.coreName); + core.addAlias("pub1", "publication1"); + core.addAlias("inp1", "input1"); + core.addAlias("pub2", "publication2"); + core.addAlias("inp2", "input2"); + core.dataLink("publication1", "input1"); + core.dataLink("publication2", "input2"); + + auto fut = std::async(std::launch::async, [&conn1]() { conn1.run(); }); + cfed1.initialize(); + cfed1.executing(); + cfed1.run(5); + cfed1.finalize(); + fut.get(); + ASSERT_EQ(cfed1.getValueNames().size(), 2); + EXPECT_FALSE(cfed1.getValues("inp1").empty()); + EXPECT_FALSE(cfed1.getValues("inp2").empty()); + // not making any connections + EXPECT_EQ(conn1.madeConnections(), 0); +} + +TEST(connector_2stage, two_sided_broker_connection_endpoints) +{ + helics::FederateInfo fedInfo(helics::CoreType::TEST); + using helics::apps::InterfaceDirection; + + fedInfo.coreName = newCoreName("core2stage"); + fedInfo.coreInitString = "-f2 --autobroker"; + fedInfo.setProperty(HELICS_PROPERTY_TIME_PERIOD, 1.0); + helics::apps::Connector conn1("connector1", fedInfo); + + fedInfo.coreInitString = ""; + CheckFed cfed1("c1", fedInfo); + cfed1.addPotentialEndpoints({"e1", "e2", "e3", "e4"}); + + helics::CoreApp core(fedInfo.coreName); + core.linkEndpoints("e1", "e2"); + core.linkEndpoints("e3", "e4"); + + auto fut = std::async(std::launch::async, [&conn1]() { conn1.run(); }); + cfed1.initialize(); + cfed1.executing(); + cfed1.run(5); + cfed1.finalize(); + fut.get(); + ASSERT_EQ(cfed1.getMessageNames().size(), 4); + EXPECT_TRUE(cfed1.getMessages("e1").empty()) << " endpoint " << cfed1.getMessageNames()[0]; + EXPECT_FALSE(cfed1.getMessages("e2").empty()) << " endpoint " << cfed1.getMessageNames()[1]; + EXPECT_TRUE(cfed1.getMessages("e3").empty()) << " endpoint " << cfed1.getMessageNames()[2]; + EXPECT_FALSE(cfed1.getMessages("e4").empty()) << " endpoint " << cfed1.getMessageNames()[3]; + // not making any connections + EXPECT_EQ(conn1.madeConnections(), 0); +} + +TEST(connector_2stage, two_sided_broker_connection_endpoints_alias) +{ + helics::FederateInfo fedInfo(helics::CoreType::TEST); + using helics::apps::InterfaceDirection; + + fedInfo.coreName = newCoreName("core2stage"); + fedInfo.coreInitString = "-f2 --autobroker"; + fedInfo.setProperty(HELICS_PROPERTY_TIME_PERIOD, 1.0); + helics::apps::Connector conn1("connector1", fedInfo); + + fedInfo.coreInitString = ""; + CheckFed cfed1("c1", fedInfo); + cfed1.addPotentialEndpoints({"e1", "e2", "e3", "e4"}); + + helics::CoreApp core(fedInfo.coreName); + core.linkEndpoints("end1", "end2"); + core.linkEndpoints("end3", "end4"); + core.addAlias("e1", "end1"); + core.addAlias("e2", "end2"); + core.addAlias("e3", "end3"); + core.addAlias("e4", "end4"); + + auto fut = std::async(std::launch::async, [&conn1]() { conn1.run(); }); + cfed1.initialize(); + cfed1.executing(); + cfed1.run(5); + cfed1.finalize(); + fut.get(); + ASSERT_EQ(cfed1.getMessageNames().size(), 4); + EXPECT_TRUE(cfed1.getMessages("e1").empty()); + EXPECT_FALSE(cfed1.getMessages("e2").empty()); + EXPECT_TRUE(cfed1.getMessages("e3").empty()); + EXPECT_FALSE(cfed1.getMessages("e4").empty()); + // not making any connections + EXPECT_EQ(conn1.madeConnections(), 0); +} + +TEST(connector_2stage, multiCheckFed) +{ + helics::FederateInfo fedInfo(helics::CoreType::TEST); + using helics::apps::InterfaceDirection; + + fedInfo.coreName = newCoreName("core2stage"); + fedInfo.coreInitString = "-f3 --autobroker"; + fedInfo.setProperty(HELICS_PROPERTY_TIME_PERIOD, 1.0); + helics::apps::Connector conn1("connector1", fedInfo); + conn1.addConnection("inp1", "pubA", InterfaceDirection::FROM_TO); + conn1.addConnection("inpA", "pub2", InterfaceDirection::FROM_TO); + fedInfo.coreInitString = ""; + CheckFed cfed1("c1", fedInfo); + cfed1.addPotentialInputs({"inp1", "inp2"}); + cfed1.addPotentialPubs({"pub1", "pub2"}); + CheckFed cfed2("c2", fedInfo); + cfed2.addPotentialInputs({"inpA", "inpB"}); + cfed2.addPotentialPubs({"pubA", "pubB", "pubC"}); + + helics::CoreApp core(fedInfo.coreName); + + auto fut = std::async(std::launch::async, [&conn1]() { conn1.run(); }); + + auto fut2 = std::async(std::launch::async, [&cfed2]() { + cfed2.initialize(); + cfed2.executing(); + cfed2.run(5); + cfed2.finalize(); + }); + + cfed1.initialize(); + cfed1.executing(); + cfed1.run(5); + cfed1.finalize(); + fut.get(); + ASSERT_EQ(cfed1.getValueNames().size(), 1); + EXPECT_FALSE(cfed1.getValues("inp1").empty()); + EXPECT_TRUE(cfed1.getValues("inp2").empty()); + + ASSERT_EQ(cfed2.getValueNames().size(), 1); + EXPECT_FALSE(cfed2.getValues("inpA").empty()); + EXPECT_TRUE(cfed2.getValues("inpB").empty()); + // not making any connections + EXPECT_EQ(conn1.madeConnections(), 2); +} diff --git a/tests/helics/apps/ConnectorFileTests.cpp b/tests/helics/apps/ConnectorFileTests.cpp new file mode 100644 index 0000000000..c722ad19a2 --- /dev/null +++ b/tests/helics/apps/ConnectorFileTests.cpp @@ -0,0 +1,233 @@ +/* +Copyright (c) 2017-2024, +Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable +Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. +SPDX-License-Identifier: BSD-3-Clause +*/ +#include "gtest/gtest.h" +#include +#ifndef DISABLE_SYSTEM_CALL_TESTS +# include "exeTestHelper.h" +#endif + +#include "helics/apps/BrokerApp.hpp" +#include "helics/apps/Connector.hpp" +#include "helics/apps/CoreApp.hpp" + +#include +#include +#include + +static constexpr std::string_view testdir = TEST_DIR "/connector/"; + +TEST(connector_file_tests, simple_connector) +{ + helics::FederateInfo fedInfo(helics::CoreType::TEST); + using helics::apps::InterfaceDirection; + + fedInfo.coreName = "ccoref1"; + fedInfo.coreInitString = "-f2 --autobroker"; + fedInfo.setProperty(HELICS_PROPERTY_TIME_PERIOD, 1.0); + helics::apps::Connector conn1("connector1", fedInfo); + conn1.loadFile(std::string(testdir) + "simple.txt"); + + helics::ValueFederate vfed("c1", fedInfo); + auto& pub1 = vfed.registerGlobalPublication("pub1"); + auto& inp1 = vfed.registerGlobalInput("inp1"); + + auto fut = std::async(std::launch::async, [&conn1]() { conn1.run(); }); + vfed.enterExecutingMode(); + const double testValue = 3452.562; + pub1.publish(testValue); + auto retTime = vfed.requestTime(5); + EXPECT_EQ(retTime, 1.0); + auto val = inp1.getDouble(); + EXPECT_EQ(val, testValue); + + vfed.finalize(); + fut.get(); + EXPECT_EQ(conn1.madeConnections(), 1); +} + +/* +TEST(connector_file_tests, simple_connector_cmd) +{ + helics::FederateInfo fedInfo(helics::CoreType::TEST); + using helics::apps::InterfaceDirection; + + fedInfo.coreName = "ccorefile1"; + fedInfo.coreInitString = "-f2 --autobroker"; + fedInfo.setProperty(HELICS_PROPERTY_TIME_PERIOD, 1.0); + helics::apps::Connector conn1("connector2", fmt::format("--corename={} --coretype=TEST +--coreinitstring='{}' --period=1.0 +--input={}simple.txt",fedInfo.coreName,fedInfo.coreInitString,testdir)); + + helics::ValueFederate vfed("c1", fedInfo); + auto& pub1 = vfed.registerGlobalPublication("pub1"); + auto& inp1 = vfed.registerGlobalInput("inp1"); + + auto fut = std::async(std::launch::async, [&conn1]() { conn1.run(); }); + vfed.enterExecutingMode(); + const double testValue = 3452.562; + pub1.publish(testValue); + auto retTime = vfed.requestTime(5); + EXPECT_EQ(retTime, 1.0); + auto val = inp1.getDouble(); + EXPECT_EQ(val, testValue); + + vfed.finalize(); + fut.get(); + EXPECT_EQ(conn1.madeConnections(), 1); +} + +*/ + +TEST(connector_file_tests, simple_connector_quotes) +{ + helics::FederateInfo fedInfo(helics::CoreType::TEST); + using helics::apps::InterfaceDirection; + + fedInfo.coreName = "ccoref1q"; + fedInfo.coreInitString = "-f2 --autobroker"; + fedInfo.setProperty(HELICS_PROPERTY_TIME_PERIOD, 1.0); + helics::apps::Connector conn1("connector1", fedInfo); + conn1.loadFile(std::string(testdir) + "simple-quotes.txt"); + + helics::ValueFederate vfed("c1", fedInfo); + auto& pub1 = vfed.registerGlobalPublication("pub1"); + auto& inp1 = vfed.registerGlobalInput("inp1"); + + auto fut = std::async(std::launch::async, [&conn1]() { conn1.run(); }); + vfed.enterExecutingMode(); + const double testValue = 3452.562; + pub1.publish(testValue); + auto retTime = vfed.requestTime(5); + EXPECT_EQ(retTime, 1.0); + auto val = inp1.getDouble(); + EXPECT_EQ(val, testValue); + + vfed.finalize(); + fut.get(); + EXPECT_EQ(conn1.madeConnections(), 1); +} + +TEST(connector_file_tests, simple_connector_reverse) +{ + helics::FederateInfo fedInfo(helics::CoreType::TEST); + using helics::apps::InterfaceDirection; + + fedInfo.coreName = "ccoref2"; + fedInfo.coreInitString = "-f2 --autobroker"; + fedInfo.setProperty(HELICS_PROPERTY_TIME_PERIOD, 1.0); + helics::apps::Connector conn1("connector1", fedInfo); + conn1.loadFile(std::string(testdir) + "simple.json"); + + helics::ValueFederate vfed("c1", fedInfo); + auto& pub1 = vfed.registerGlobalPublication("pub1"); + auto& inp1 = vfed.registerGlobalInput("inp1"); + + auto fut = std::async(std::launch::async, [&conn1]() { conn1.run(); }); + vfed.enterExecutingMode(); + const double testValue = 3452.562; + pub1.publish(testValue); + auto retTime = vfed.requestTime(5); + EXPECT_EQ(retTime, 1.0); + auto val = inp1.getDouble(); + EXPECT_EQ(val, testValue); + + vfed.finalize(); + fut.get(); +} + +TEST(connector_file_tests, connector_cascade) +{ + helics::FederateInfo fedInfo(helics::CoreType::TEST); + using helics::apps::InterfaceDirection; + + fedInfo.coreName = "ccoref3"; + fedInfo.coreInitString = "-f2 --autobroker"; + fedInfo.setProperty(HELICS_PROPERTY_TIME_PERIOD, 1.0); + helics::apps::Connector conn1("connector1", fedInfo); + conn1.loadFile(std::string(testdir) + "cascade.txt"); + + helics::ValueFederate vfed("c1", fedInfo); + auto& pub1 = vfed.registerGlobalPublication("pub1"); + auto& inp1 = vfed.registerGlobalInput("inp1"); + auto& inp2 = vfed.registerGlobalInput("inp2"); + + auto fut = std::async(std::launch::async, [&conn1]() { conn1.run(); }); + vfed.enterExecutingMode(); + const double testValue = 3452.562; + pub1.publish(testValue); + auto retTime = vfed.requestTime(5); + EXPECT_EQ(retTime, 1.0); + auto val = inp1.getDouble(); + EXPECT_EQ(val, testValue); + val = inp2.getDouble(); + EXPECT_EQ(val, testValue); + vfed.finalize(); + fut.get(); +} + +TEST(connector_file_tests, simple_connector_tags) +{ + helics::FederateInfo fedInfo(helics::CoreType::TEST); + using helics::apps::InterfaceDirection; + + fedInfo.coreName = "ccoref4"; + fedInfo.coreInitString = "-f2 --autobroker"; + fedInfo.setProperty(HELICS_PROPERTY_TIME_PERIOD, 1.0); + helics::apps::Connector conn1("connector1", fedInfo); + conn1.loadFile(std::string(testdir) + "simple_tags.txt"); + + helics::ValueFederate vfed("c1", fedInfo); + auto& pub1 = vfed.registerGlobalPublication("pub1"); + auto& inp1 = vfed.registerGlobalInput("inp1"); + auto& inp2 = vfed.registerGlobalInput("inp2"); + vfed.setGlobal("tag1", "true"); + auto fut = std::async(std::launch::async, [&conn1]() { conn1.run(); }); + vfed.enterExecutingMode(); + const double testValue = 3452.562; + pub1.publish(testValue); + auto retTime = vfed.requestTime(5); + EXPECT_EQ(retTime, 1.0); + auto val = inp1.getDouble(); + EXPECT_EQ(val, testValue); + val = inp2.getDouble(); + EXPECT_EQ(val, helics::invalidDouble); + vfed.finalize(); + fut.get(); + EXPECT_EQ(conn1.madeConnections(), 1); +} + +TEST(connector_file_tests, simple_connector_tags_alt) +{ + helics::FederateInfo fedInfo(helics::CoreType::TEST); + using helics::apps::InterfaceDirection; + + fedInfo.coreName = "ccoref5"; + fedInfo.coreInitString = "-f2 --autobroker"; + fedInfo.setProperty(HELICS_PROPERTY_TIME_PERIOD, 1.0); + helics::apps::Connector conn1("connector1", fedInfo); + conn1.loadFile(std::string(testdir) + "simple_tags.txt"); + + helics::ValueFederate vfed("c1", fedInfo); + auto& pub1 = vfed.registerGlobalPublication("pub1"); + auto& inp1 = vfed.registerGlobalInput("inp1"); + auto& inp2 = vfed.registerGlobalInput("inp2"); + vfed.setGlobal("tag2", "true"); + auto fut = std::async(std::launch::async, [&conn1]() { conn1.run(); }); + vfed.enterExecutingMode(); + const double testValue = 3452.562; + pub1.publish(testValue); + auto retTime = vfed.requestTime(5); + EXPECT_EQ(retTime, 1.0); + auto val = inp1.getDouble(); + EXPECT_EQ(val, helics::invalidDouble); + + val = inp2.getDouble(); + EXPECT_EQ(val, testValue); + vfed.finalize(); + fut.get(); + EXPECT_GE(conn1.madeConnections(), 1); +} diff --git a/tests/helics/apps/ConnectorTagTests.cpp b/tests/helics/apps/ConnectorTagTests.cpp new file mode 100644 index 0000000000..abad899c64 --- /dev/null +++ b/tests/helics/apps/ConnectorTagTests.cpp @@ -0,0 +1,300 @@ +/* +Copyright (c) 2017-2024, +Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable +Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. +SPDX-License-Identifier: BSD-3-Clause +*/ +#include "gtest/gtest.h" +#include +#ifndef DISABLE_SYSTEM_CALL_TESTS +# include "exeTestHelper.h" +#endif + +#include "helics/apps/BrokerApp.hpp" +#include "helics/apps/Connector.hpp" +#include "helics/apps/CoreApp.hpp" + +#include +#include + +static constexpr std::string_view testdir = TEST_DIR "/connector/"; + +TEST(connector_tags, no_match_tag) +{ + helics::FederateInfo fedInfo(helics::CoreType::TEST); + using helics::apps::InterfaceDirection; + + fedInfo.coreName = "ccoret1"; + fedInfo.coreInitString = "-f2 --autobroker"; + fedInfo.setProperty(HELICS_PROPERTY_TIME_PERIOD, 1.0); + helics::apps::Connector conn1("connector1", fedInfo); + conn1.addConnection("inp1", "pub1", InterfaceDirection::FROM_TO, {"tag1"}); + + helics::ValueFederate vfed("c1", fedInfo); + auto& pub1 = vfed.registerGlobalPublication("pub1"); + auto& inp1 = vfed.registerGlobalInput("inp1"); + + auto fut = std::async(std::launch::async, [&conn1]() { conn1.run(); }); + vfed.enterExecutingMode(); + const double testValue = 3452.562; + pub1.publish(testValue); + auto retTime = vfed.requestTime(5); + EXPECT_EQ(retTime, 5.0); + auto val = inp1.getDouble(); + EXPECT_EQ(val, helics::invalidDouble); + + vfed.finalize(); + fut.get(); + EXPECT_EQ(conn1.madeConnections(), 0); +} + +TEST(connector_tags, match_tag) +{ + helics::FederateInfo fedInfo(helics::CoreType::TEST); + using helics::apps::InterfaceDirection; + + fedInfo.coreName = "ccoret2"; + fedInfo.coreInitString = "-f2 --autobroker"; + fedInfo.setProperty(HELICS_PROPERTY_TIME_PERIOD, 1.0); + helics::apps::Connector conn1("connector1", fedInfo); + conn1.addConnection("inp1", "pub1", InterfaceDirection::FROM_TO, {"tag1"}); + + helics::ValueFederate vfed("c1", fedInfo); + vfed.setTag("tag1", "ON"); + auto& pub1 = vfed.registerGlobalPublication("pub1"); + auto& inp1 = vfed.registerGlobalInput("inp1"); + + auto fut = std::async(std::launch::async, [&conn1]() { conn1.run(); }); + vfed.enterExecutingMode(); + const double testValue = 3452.562; + pub1.publish(testValue); + auto retTime = vfed.requestTime(5); + EXPECT_EQ(retTime, 1.0); + auto val = inp1.getDouble(); + EXPECT_EQ(val, testValue); + + vfed.finalize(); + fut.get(); + EXPECT_EQ(conn1.madeConnections(), 1); +} + +TEST(connector_tags, match_tag2) +{ + helics::FederateInfo fedInfo(helics::CoreType::TEST); + using helics::apps::InterfaceDirection; + + fedInfo.coreName = "ccoret3"; + fedInfo.coreInitString = "-f2 --autobroker"; + fedInfo.setProperty(HELICS_PROPERTY_TIME_PERIOD, 1.0); + helics::apps::Connector conn1("connector1", fedInfo); + conn1.addConnection("inp1", "pub1", InterfaceDirection::FROM_TO, {"tag1", "tag2"}); + + helics::ValueFederate vfed("c1", fedInfo); + vfed.setTag("tag1", "ON"); + auto& pub1 = vfed.registerGlobalPublication("pub1"); + auto& inp1 = vfed.registerGlobalInput("inp1"); + + auto fut = std::async(std::launch::async, [&conn1]() { conn1.run(); }); + vfed.enterExecutingMode(); + const double testValue = 3452.562; + pub1.publish(testValue); + auto retTime = vfed.requestTime(5); + EXPECT_EQ(retTime, 1.0); + auto val = inp1.getDouble(); + EXPECT_EQ(val, testValue); + + vfed.finalize(); + fut.get(); + EXPECT_EQ(conn1.madeConnections(), 1); +} + +TEST(connector_tags, match_tag_core) +{ + helics::FederateInfo fedInfo(helics::CoreType::TEST); + using helics::apps::InterfaceDirection; + + fedInfo.coreName = "ccoret4"; + fedInfo.coreInitString = "-f2 --autobroker"; + fedInfo.setProperty(HELICS_PROPERTY_TIME_PERIOD, 1.0); + helics::apps::Connector conn1("connector1", fedInfo); + conn1.addConnection("inp1", "pub1", InterfaceDirection::FROM_TO, {"tag1", "tag2"}); + + helics::ValueFederate vfed("c1", fedInfo); + + auto& pub1 = vfed.registerGlobalPublication("pub1"); + auto& inp1 = vfed.registerGlobalInput("inp1"); + + helics::CoreApp core("ccoret4"); + core.setTag("tag2"); + auto fut = std::async(std::launch::async, [&conn1]() { conn1.run(); }); + vfed.enterExecutingMode(); + const double testValue = 3452.562; + pub1.publish(testValue); + auto retTime = vfed.requestTime(5); + EXPECT_EQ(retTime, 1.0); + auto val = inp1.getDouble(); + EXPECT_EQ(val, testValue); + + vfed.finalize(); + fut.get(); + EXPECT_EQ(conn1.madeConnections(), 1); +} + +TEST(connector_tags, match_tag_global) +{ + helics::FederateInfo fedInfo(helics::CoreType::TEST); + using helics::apps::InterfaceDirection; + + fedInfo.coreName = "ccoret5"; + fedInfo.coreInitString = "-f2 --autobroker"; + fedInfo.setProperty(HELICS_PROPERTY_TIME_PERIOD, 1.0); + helics::apps::Connector conn1("connector1", fedInfo); + conn1.addConnection("inp1", "pub1", InterfaceDirection::FROM_TO, {"tag1", "tag2"}); + + helics::ValueFederate vfed("c1", fedInfo); + + auto& pub1 = vfed.registerGlobalPublication("pub1"); + auto& inp1 = vfed.registerGlobalInput("inp1"); + + helics::CoreApp core("ccoret5"); + core.setGlobal("tag2"); + auto fut = std::async(std::launch::async, [&conn1]() { conn1.run(); }); + vfed.enterExecutingMode(); + const double testValue = 3452.562; + pub1.publish(testValue); + auto retTime = vfed.requestTime(5); + EXPECT_EQ(retTime, 1.0); + auto val = inp1.getDouble(); + EXPECT_EQ(val, testValue); + + vfed.finalize(); + fut.get(); + EXPECT_EQ(conn1.madeConnections(), 1); +} + +TEST(connector_tags, false_tag) +{ + helics::FederateInfo fedInfo(helics::CoreType::TEST); + using helics::apps::InterfaceDirection; + + fedInfo.coreName = "ccoret6"; + fedInfo.coreInitString = "-f2 --autobroker"; + fedInfo.setProperty(HELICS_PROPERTY_TIME_PERIOD, 1.0); + helics::apps::Connector conn1("connector1", fedInfo); + conn1.addConnection("inp1", "pub1", InterfaceDirection::FROM_TO, {"tag1"}); + + helics::ValueFederate vfed("c1", fedInfo); + vfed.setGlobal("tag1", "false"); + auto& pub1 = vfed.registerGlobalPublication("pub1"); + auto& inp1 = vfed.registerGlobalInput("inp1"); + + auto fut = std::async(std::launch::async, [&conn1]() { conn1.run(); }); + vfed.enterExecutingMode(); + const double testValue = 3452.562; + pub1.publish(testValue); + auto retTime = vfed.requestTime(5); + EXPECT_EQ(retTime, 5.0); + auto val = inp1.getDouble(); + EXPECT_EQ(val, helics::invalidDouble); + + vfed.finalize(); + fut.get(); + EXPECT_EQ(conn1.madeConnections(), 0); +} + +TEST(connector_tags, match_tag_tags) +{ + helics::FederateInfo fedInfo(helics::CoreType::TEST); + using helics::apps::InterfaceDirection; + + fedInfo.coreName = "ccoret7"; + fedInfo.coreInitString = "-f2 --autobroker"; + fedInfo.setProperty(HELICS_PROPERTY_TIME_PERIOD, 1.0); + helics::apps::Connector conn1("connector1", fedInfo); + conn1.addConnection("inp1", "pub1", InterfaceDirection::FROM_TO, {"tag1", "tag2"}); + + helics::ValueFederate vfed("c1", fedInfo); + + auto& pub1 = vfed.registerGlobalPublication("pub1"); + auto& inp1 = vfed.registerGlobalInput("inp1"); + + helics::CoreApp core("ccoret7"); + core.setGlobal("tags", "tag2,test,mode, single"); + auto fut = std::async(std::launch::async, [&conn1]() { conn1.run(); }); + vfed.enterExecutingMode(); + const double testValue = 3452.562; + pub1.publish(testValue); + auto retTime = vfed.requestTime(5); + EXPECT_EQ(retTime, 1.0); + auto val = inp1.getDouble(); + EXPECT_EQ(val, testValue); + + vfed.finalize(); + fut.get(); + EXPECT_EQ(conn1.madeConnections(), 1); +} + +TEST(connector_tags, match_tag_discriminate) +{ + helics::FederateInfo fedInfo(helics::CoreType::TEST); + using helics::apps::InterfaceDirection; + + fedInfo.coreName = "ccoret8"; + fedInfo.coreInitString = "-f2 --autobroker"; + fedInfo.setProperty(HELICS_PROPERTY_TIME_PERIOD, 1.0); + helics::apps::Connector conn1("connector1", fedInfo); + conn1.addConnection("inp1", "pub1", InterfaceDirection::FROM_TO, {"tag1"}); + conn1.addConnection("inp2", "pub1", InterfaceDirection::FROM_TO, {"tag2"}); + helics::ValueFederate vfed("c1", fedInfo); + vfed.setTag("tag2", "ON"); + auto& pub1 = vfed.registerGlobalPublication("pub1"); + auto& inp1 = vfed.registerGlobalInput("inp1"); + auto& inp2 = vfed.registerGlobalInput("inp2"); + auto fut = std::async(std::launch::async, [&conn1]() { conn1.run(); }); + vfed.enterExecutingMode(); + const double testValue = 3452.562; + pub1.publish(testValue); + auto retTime = vfed.requestTime(5); + EXPECT_EQ(retTime, 1.0); + auto val = inp1.getDouble(); + EXPECT_EQ(val, helics::invalidDouble); + val = inp2.getDouble(); + EXPECT_EQ(val, testValue); + + vfed.finalize(); + fut.get(); + EXPECT_EQ(conn1.madeConnections(), 1); +} + +TEST(connector_tags, match_tag_discriminate2) +{ + helics::FederateInfo fedInfo(helics::CoreType::TEST); + using helics::apps::InterfaceDirection; + + fedInfo.coreName = "ccoret9"; + fedInfo.coreInitString = "-f2 --autobroker"; + fedInfo.setProperty(HELICS_PROPERTY_TIME_PERIOD, 1.0); + helics::apps::Connector conn1("connector1", fedInfo); + conn1.addConnection("inp1", "pub1", InterfaceDirection::FROM_TO, {"tag1"}); + conn1.addConnection("inp2", "pub1", InterfaceDirection::FROM_TO, {"tag2"}); + helics::ValueFederate vfed("c1", fedInfo); + vfed.setTag("tag1", "ON"); + auto& pub1 = vfed.registerGlobalPublication("pub1"); + auto& inp1 = vfed.registerGlobalInput("inp1"); + auto& inp2 = vfed.registerGlobalInput("inp2"); + auto fut = std::async(std::launch::async, [&conn1]() { conn1.run(); }); + vfed.enterExecutingMode(); + const double testValue = 3452.562; + pub1.publish(testValue); + auto retTime = vfed.requestTime(5); + EXPECT_EQ(retTime, 1.0); + auto val = inp1.getDouble(); + EXPECT_EQ(val, testValue); + + val = inp2.getDouble(); + EXPECT_EQ(val, helics::invalidDouble); + + vfed.finalize(); + fut.get(); + EXPECT_EQ(conn1.madeConnections(), 1); +} diff --git a/tests/helics/apps/ConnectorTests.cpp b/tests/helics/apps/ConnectorTests.cpp new file mode 100644 index 0000000000..53c982334e --- /dev/null +++ b/tests/helics/apps/ConnectorTests.cpp @@ -0,0 +1,449 @@ +/* +Copyright (c) 2017-2024, +Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable +Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. +SPDX-License-Identifier: BSD-3-Clause +*/ +#include "gtest/gtest.h" +#include +#ifndef DISABLE_SYSTEM_CALL_TESTS +# include "exeTestHelper.h" +#endif + +#include "helics/apps/BrokerApp.hpp" +#include "helics/apps/Connector.hpp" +#include "helics/apps/CoreApp.hpp" + +#include +#include + +TEST(connector_tests, simple_connector) +{ + helics::FederateInfo fedInfo(helics::CoreType::TEST); + using helics::apps::InterfaceDirection; + + fedInfo.coreName = "ccore1"; + fedInfo.coreInitString = "-f2 --autobroker"; + fedInfo.setProperty(HELICS_PROPERTY_TIME_PERIOD, 1.0); + helics::apps::Connector conn1("connector1", fedInfo); + conn1.addConnection("inp1", "pub1", InterfaceDirection::FROM_TO); + + helics::ValueFederate vfed("c1", fedInfo); + auto& pub1 = vfed.registerGlobalPublication("pub1"); + auto& inp1 = vfed.registerGlobalInput("inp1"); + + auto fut = std::async(std::launch::async, [&conn1]() { conn1.run(); }); + vfed.enterExecutingMode(); + const double testValue = 3452.562; + pub1.publish(testValue); + auto retTime = vfed.requestTime(5); + EXPECT_EQ(retTime, 1.0); + auto val = inp1.getDouble(); + EXPECT_EQ(val, testValue); + + vfed.finalize(); + fut.get(); + EXPECT_EQ(conn1.madeConnections(), 1); +} + +TEST(connector_tests, simple_connector_reverse) +{ + helics::FederateInfo fedInfo(helics::CoreType::TEST); + using helics::apps::InterfaceDirection; + + fedInfo.coreName = "ccore2"; + fedInfo.coreInitString = "-f2 --autobroker"; + fedInfo.setProperty(HELICS_PROPERTY_TIME_PERIOD, 1.0); + helics::apps::Connector conn1("connector1", fedInfo); + conn1.addConnection("pub1", "inp1", InterfaceDirection::FROM_TO); + + helics::ValueFederate vfed("c1", fedInfo); + auto& pub1 = vfed.registerGlobalPublication("pub1"); + auto& inp1 = vfed.registerGlobalInput("inp1"); + + auto fut = std::async(std::launch::async, [&conn1]() { conn1.run(); }); + vfed.enterExecutingMode(); + const double testValue = 3452.562; + pub1.publish(testValue); + auto retTime = vfed.requestTime(5); + EXPECT_EQ(retTime, 1.0); + auto val = inp1.getDouble(); + EXPECT_EQ(val, testValue); + + vfed.finalize(); + fut.get(); +} + +TEST(connector_tests, connector_multiple) +{ + helics::FederateInfo fedInfo(helics::CoreType::TEST); + using helics::apps::InterfaceDirection; + + fedInfo.coreName = "ccore3"; + fedInfo.coreInitString = "-f2 --autobroker"; + fedInfo.setProperty(HELICS_PROPERTY_TIME_PERIOD, 1.0); + helics::apps::Connector conn1("connector1", fedInfo); + conn1.addConnection("inp1", "pub1", InterfaceDirection::FROM_TO); + conn1.addConnection("inp1", "pubA", InterfaceDirection::FROM_TO); + conn1.addConnection("inp2", "pub1", InterfaceDirection::FROM_TO); + conn1.addConnection("inp2", "pubA", InterfaceDirection::FROM_TO); + + helics::ValueFederate vfed("c1", fedInfo); + auto& pub1 = vfed.registerGlobalPublication("pub1"); + auto& inp1 = vfed.registerGlobalInput("inp1"); + auto& inp2 = vfed.registerGlobalInput("inp2"); + + auto fut = std::async(std::launch::async, [&conn1]() { conn1.run(); }); + vfed.enterExecutingMode(); + const double testValue = 3452.562; + pub1.publish(testValue); + auto retTime = vfed.requestTime(5); + EXPECT_EQ(retTime, 1.0); + auto val = inp1.getDouble(); + EXPECT_EQ(val, testValue); + val = inp2.getDouble(); + EXPECT_EQ(val, testValue); + vfed.finalize(); + fut.get(); +} + +TEST(connector_tests, connector_cascade) +{ + helics::FederateInfo fedInfo(helics::CoreType::TEST); + using helics::apps::InterfaceDirection; + + fedInfo.coreName = "ccore4"; + fedInfo.coreInitString = "-f2 --autobroker"; + fedInfo.setProperty(HELICS_PROPERTY_TIME_PERIOD, 1.0); + helics::apps::Connector conn1("connector1", fedInfo); + conn1.addConnection("inp1", "intermediate1", InterfaceDirection::FROM_TO); + conn1.addConnection("intermediate1", "intermediate1", InterfaceDirection::BIDIRECTIONAL); + conn1.addConnection("intermediate1", "intermediate2", InterfaceDirection::FROM_TO); + conn1.addConnection("intermediate2", "intermediate3", InterfaceDirection::FROM_TO); + conn1.addConnection("intermediate3", "pub1", InterfaceDirection::BIDIRECTIONAL); + conn1.addConnection("inp2", "intermediate2", InterfaceDirection::FROM_TO); + + helics::ValueFederate vfed("c1", fedInfo); + auto& pub1 = vfed.registerGlobalPublication("pub1"); + auto& inp1 = vfed.registerGlobalInput("inp1"); + auto& inp2 = vfed.registerGlobalInput("inp2"); + + auto fut = std::async(std::launch::async, [&conn1]() { conn1.run(); }); + vfed.enterExecutingMode(); + const double testValue = 3452.562; + pub1.publish(testValue); + auto retTime = vfed.requestTime(5); + EXPECT_EQ(retTime, 1.0); + auto val = inp1.getDouble(); + EXPECT_EQ(val, testValue); + val = inp2.getDouble(); + EXPECT_EQ(val, testValue); + vfed.finalize(); + fut.get(); +} + +TEST(connector_tests, endpoint_connector) +{ + helics::FederateInfo fedInfo(helics::CoreType::TEST); + using helics::apps::InterfaceDirection; + + fedInfo.coreName = "ccore5"; + fedInfo.coreInitString = "-f2 --autobroker"; + fedInfo.setProperty(HELICS_PROPERTY_TIME_PERIOD, 1.0); + helics::apps::Connector conn1("connector1", fedInfo); + conn1.addConnection("ept1", "ept12", InterfaceDirection::FROM_TO); + + helics::MessageFederate vfed("c1", fedInfo); + auto& ept1 = vfed.registerGlobalTargetedEndpoint("ept1"); + auto& ept12 = vfed.registerGlobalTargetedEndpoint("ept12"); + + auto fut = std::async(std::launch::async, [&conn1]() { conn1.run(); }); + vfed.enterExecutingMode(); + constexpr std::string_view testValue = "this is a test string"; + ept1.send(testValue); + auto retTime = vfed.requestTime(5); + EXPECT_EQ(retTime, 1.0); + EXPECT_TRUE(ept12.hasMessage()); + auto message = ept12.getMessage(); + EXPECT_EQ(message->to_string(), testValue); + vfed.finalize(); + fut.get(); +} + +TEST(connector_tests, endpoint_connector_no_connection) +{ + helics::FederateInfo fedInfo(helics::CoreType::TEST); + using helics::apps::InterfaceDirection; + + fedInfo.coreName = "ccore6"; + fedInfo.coreInitString = "-f2 --autobroker"; + fedInfo.setProperty(HELICS_PROPERTY_TIME_PERIOD, 1.0); + helics::apps::Connector conn1("connector1", fedInfo); + conn1.addConnection("ept1", "ept12", InterfaceDirection::FROM_TO); + + helics::MessageFederate vfed("c1", fedInfo); + auto& ept1 = vfed.registerGlobalTargetedEndpoint("ept1"); + auto& ept12 = vfed.registerGlobalTargetedEndpoint("ept12"); + + auto fut = std::async(std::launch::async, [&conn1]() { conn1.run(); }); + vfed.enterExecutingMode(); + constexpr std::string_view testValue = "this is a test string"; + ept12.send(testValue); + auto retTime = vfed.requestTime(5); + EXPECT_EQ(retTime, 5.0); + EXPECT_FALSE(ept1.hasMessage()); + + vfed.finalize(); + fut.get(); +} + +TEST(connector_tests, endpoint_connector_bidirectional) +{ + helics::FederateInfo fedInfo(helics::CoreType::TEST); + using helics::apps::InterfaceDirection; + + fedInfo.coreName = "ccore7"; + fedInfo.coreInitString = "-f2 --autobroker"; + fedInfo.setProperty(HELICS_PROPERTY_TIME_PERIOD, 1.0); + helics::apps::Connector conn1("connector1", fedInfo); + conn1.addConnection("ept1", "ept12", InterfaceDirection::BIDIRECTIONAL); + + helics::MessageFederate vfed("c1", fedInfo); + auto& ept1 = vfed.registerGlobalTargetedEndpoint("ept1"); + auto& ept12 = vfed.registerGlobalTargetedEndpoint("ept12"); + + auto fut = std::async(std::launch::async, [&conn1]() { conn1.run(); }); + vfed.enterExecutingMode(); + constexpr std::string_view testValue1 = "this is a test string1"; + constexpr std::string_view testValue2 = "this is a test string2"; + ept1.send(testValue1); + ept12.send(testValue2); + auto retTime = vfed.requestTime(5); + EXPECT_EQ(retTime, 1.0); + EXPECT_TRUE(ept1.hasMessage()); + EXPECT_TRUE(ept12.hasMessage()); + auto message = ept12.getMessage(); + EXPECT_EQ(message->to_string(), testValue1); + + message = ept1.getMessage(); + EXPECT_EQ(message->to_string(), testValue2); + vfed.finalize(); + fut.get(); +} + +TEST(connector_tests, simple_connector_alias) +{ + helics::FederateInfo fedInfo(helics::CoreType::TEST); + using helics::apps::InterfaceDirection; + + fedInfo.coreName = "ccore8"; + fedInfo.coreInitString = "-f2 --autobroker"; + fedInfo.setProperty(HELICS_PROPERTY_TIME_PERIOD, 1.0); + helics::apps::Connector conn1("connector1", fedInfo); + conn1.addConnection("inp1", "publication1", InterfaceDirection::FROM_TO); + + helics::ValueFederate vfed("c1", fedInfo); + auto& pub1 = vfed.registerGlobalPublication("pub1"); + pub1.addAlias("publication1"); + auto& inp1 = vfed.registerGlobalInput("inp1"); + + auto fut = std::async(std::launch::async, [&conn1]() { conn1.run(); }); + vfed.enterExecutingMode(); + const double testValue = 3452.562; + pub1.publish(testValue); + auto retTime = vfed.requestTime(5); + EXPECT_EQ(retTime, 1.0); + auto val = inp1.getDouble(); + EXPECT_EQ(val, testValue); + + vfed.finalize(); + fut.get(); +} + +TEST(connector_tests, simple_connector_alias_reverse) +{ + helics::FederateInfo fedInfo(helics::CoreType::TEST); + using helics::apps::InterfaceDirection; + + fedInfo.coreName = "ccore9"; + fedInfo.coreInitString = "-f2 --autobroker"; + fedInfo.setProperty(HELICS_PROPERTY_TIME_PERIOD, 1.0); + helics::apps::Connector conn1("connector1", fedInfo); + conn1.addConnection("pub1", "input1", InterfaceDirection::FROM_TO); + + helics::ValueFederate vfed("c1", fedInfo); + auto& pub1 = vfed.registerGlobalPublication("pub1"); + + auto& inp1 = vfed.registerGlobalInput("inp1"); + inp1.addAlias("input1"); + auto fut = std::async(std::launch::async, [&conn1]() { conn1.run(); }); + vfed.enterExecutingMode(); + const double testValue = 3452.562; + pub1.publish(testValue); + auto retTime = vfed.requestTime(5); + EXPECT_EQ(retTime, 1.0); + auto val = inp1.getDouble(); + EXPECT_EQ(val, testValue); + + vfed.finalize(); + fut.get(); +} + +TEST(connector_tests, dual_alias) +{ + helics::FederateInfo fedInfo(helics::CoreType::TEST); + using helics::apps::InterfaceDirection; + + fedInfo.coreName = "ccore10"; + fedInfo.coreInitString = "-f2 --autobroker"; + fedInfo.setProperty(HELICS_PROPERTY_TIME_PERIOD, 1.0); + helics::apps::Connector conn1("connector1", fedInfo); + conn1.addConnection("input1", "publication1", InterfaceDirection::FROM_TO); + + helics::ValueFederate vfed("c1", fedInfo); + auto& pub1 = vfed.registerGlobalPublication("pub1"); + pub1.addAlias("publication1"); + auto& inp1 = vfed.registerGlobalInput("inp1"); + inp1.addAlias("input1"); + + auto fut = std::async(std::launch::async, [&conn1]() { conn1.run(); }); + vfed.enterExecutingMode(); + const double testValue = 3452.562; + pub1.publish(testValue); + auto retTime = vfed.requestTime(5); + EXPECT_EQ(retTime, 1.0); + auto val = inp1.getDouble(); + EXPECT_EQ(val, testValue); + + vfed.finalize(); + fut.get(); +} + +TEST(connector_tests, dual_alias_reverse) +{ + helics::FederateInfo fedInfo(helics::CoreType::TEST); + using helics::apps::InterfaceDirection; + + fedInfo.coreName = "ccore11"; + fedInfo.coreInitString = "-f2 --autobroker"; + fedInfo.setProperty(HELICS_PROPERTY_TIME_PERIOD, 1.0); + helics::apps::Connector conn1("connector1", fedInfo); + conn1.addConnection("publication1", "input1", InterfaceDirection::FROM_TO); + + helics::ValueFederate vfed("c1", fedInfo); + auto& pub1 = vfed.registerGlobalPublication("pub1"); + pub1.addAlias("publication1"); + auto& inp1 = vfed.registerGlobalInput("inp1"); + inp1.addAlias("input1"); + auto fut = std::async(std::launch::async, [&conn1]() { conn1.run(); }); + vfed.enterExecutingMode(); + const double testValue = 3452.562; + pub1.publish(testValue); + auto retTime = vfed.requestTime(5); + EXPECT_EQ(retTime, 1.0); + auto val = inp1.getDouble(); + EXPECT_EQ(val, testValue); + + vfed.finalize(); + fut.get(); +} + +TEST(connector_tests, cascade_dual_alias) +{ + helics::FederateInfo fedInfo(helics::CoreType::TEST); + using helics::apps::InterfaceDirection; + + fedInfo.coreName = "ccore12"; + fedInfo.coreInitString = "-f2 --autobroker"; + fedInfo.setProperty(HELICS_PROPERTY_TIME_PERIOD, 1.0); + helics::apps::Connector conn1("connector1", fedInfo); + conn1.addConnection("inputA", "publicationA", InterfaceDirection::FROM_TO); + + helics::ValueFederate vfed("c1", fedInfo); + auto& pub1 = vfed.registerGlobalPublication("pub1"); + pub1.addAlias("publication1"); + helics::CoreApp core(vfed.getCorePointer()); + core.addAlias("publication1", "pubsbb"); + core.addAlias("pubsbb", "publicationA"); + auto& inp1 = vfed.registerGlobalInput("inp1"); + inp1.addAlias("input1"); + core.addAlias("input1", "inpsbb"); + core.addAlias("inpsbb", "inputA"); + + auto fut = std::async(std::launch::async, [&conn1]() { conn1.run(); }); + vfed.enterExecutingMode(); + const double testValue = 3452.562; + pub1.publish(testValue); + auto retTime = vfed.requestTime(5); + EXPECT_EQ(retTime, 1.0); + auto val = inp1.getDouble(); + EXPECT_EQ(val, testValue); + + vfed.finalize(); + fut.get(); +} + +TEST(connector_tests, cascade_dual_alias_intermediary) +{ + helics::FederateInfo fedInfo(helics::CoreType::TEST); + using helics::apps::InterfaceDirection; + + fedInfo.coreName = "ccore13"; + fedInfo.coreInitString = "-f2 --autobroker"; + fedInfo.setProperty(HELICS_PROPERTY_TIME_PERIOD, 1.0); + helics::apps::Connector conn1("connector1", fedInfo); + conn1.addConnection("publicationA", "inputC", InterfaceDirection::FROM_TO); + conn1.addConnection("inputC", "inputE", InterfaceDirection::FROM_TO); + conn1.addConnection("inputE", "inputA", InterfaceDirection::FROM_TO); + helics::ValueFederate vfed("c1", fedInfo); + auto& pub1 = vfed.registerGlobalPublication("pub1"); + pub1.addAlias("publication1"); + helics::CoreApp core(vfed.getCorePointer()); + core.addAlias("publication1", "pubsbb"); + core.addAlias("pubsbb", "publicationA"); + auto& inp1 = vfed.registerGlobalInput("inp1"); + inp1.addAlias("input1"); + inp1.addAlias("input1"); + core.addAlias("input1", "inpsbb"); + core.addAlias("inpsbb", "inputA"); + auto fut = std::async(std::launch::async, [&conn1]() { conn1.run(); }); + vfed.enterExecutingMode(); + const double testValue = 3452.562; + pub1.publish(testValue); + auto retTime = vfed.requestTime(5); + EXPECT_EQ(retTime, 1.0); + auto val = inp1.getDouble(); + EXPECT_EQ(val, testValue); + + vfed.finalize(); + fut.get(); +} + +TEST(connector_tests, endpoint_connector_alias1) +{ + helics::FederateInfo fedInfo(helics::CoreType::TEST); + using helics::apps::InterfaceDirection; + + fedInfo.coreName = "ccore14"; + fedInfo.coreInitString = "-f2 --autobroker"; + fedInfo.setProperty(HELICS_PROPERTY_TIME_PERIOD, 1.0); + helics::apps::Connector conn1("connector1", fedInfo); + conn1.addConnection("eptA", "eptB", InterfaceDirection::FROM_TO); + + helics::MessageFederate vfed("c1", fedInfo); + auto& ept1 = vfed.registerGlobalTargetedEndpoint("ept1"); + ept1.addAlias("eptA"); + auto& ept12 = vfed.registerGlobalTargetedEndpoint("ept12"); + ept12.addAlias("eptB"); + auto fut = std::async(std::launch::async, [&conn1]() { conn1.run(); }); + vfed.enterExecutingMode(); + constexpr std::string_view testValue = "this is a test string"; + ept1.send(testValue); + auto retTime = vfed.requestTime(5); + EXPECT_EQ(retTime, 1.0); + EXPECT_TRUE(ept12.hasMessage()); + auto message = ept12.getMessage(); + EXPECT_EQ(message->to_string(), testValue); + vfed.finalize(); + fut.get(); +} diff --git a/tests/helics/apps/ConnectorTests2.cpp b/tests/helics/apps/ConnectorTests2.cpp new file mode 100644 index 0000000000..529a54a662 --- /dev/null +++ b/tests/helics/apps/ConnectorTests2.cpp @@ -0,0 +1,280 @@ +/* +Copyright (c) 2017-2024, +Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable +Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. +SPDX-License-Identifier: BSD-3-Clause +*/ +#include "gtest/gtest.h" +#include +#ifndef DISABLE_SYSTEM_CALL_TESTS +# include "exeTestHelper.h" +#endif + +#include "helics/ValueFederates.hpp" +#include "helics/apps/BrokerApp.hpp" +#include "helics/apps/Connector.hpp" +#include "helics/apps/CoreApp.hpp" + +#include +#include + +class MultibrokerFixture: public ::testing::Test { + public: + MultibrokerFixture(): brokerA(helics::CoreType::TEST, "-f7") + { + //** setup brokers and cores*/ + + subBroker1 = helics::BrokerApp(helics::CoreType::TEST, + std::string("--broker=") + brokerA.getIdentifier()); + subBroker2 = helics::BrokerApp(helics::CoreType::TEST, + std::string("--broker=") + brokerA.getIdentifier()); + + subsubBroker2 = helics::BrokerApp(helics::CoreType::TEST, + std::string("--broker=") + subBroker2.getIdentifier()); + + coreA = helics::CoreApp(helics::CoreType::TEST, + std::string("--broker=") + brokerA.getIdentifier()); + core_sub1 = helics::CoreApp(helics::CoreType::TEST, + std::string("--broker=") + subBroker1.getIdentifier()); + core_sub1B = helics::CoreApp(helics::CoreType::TEST, + std::string("--broker=") + subBroker1.getIdentifier()); + + core_sub2 = helics::CoreApp(helics::CoreType::TEST, + std::string("--broker=") + subBroker2.getIdentifier()); + + core_subsub1 = helics::CoreApp(helics::CoreType::TEST, + std::string("--broker=") + subsubBroker2.getIdentifier()); + /** setup the federates*/ + + fedInfo.setProperty(HELICS_PROPERTY_TIME_PERIOD, 1.0); + + fedA = std::make_shared("fedA", coreA, fedInfo); + fedA->registerGlobalInput("inputA"); + fedA->registerGlobalPublication("pubD"); + + fedSubA = std::make_shared("fedSubA", core_sub1, fedInfo); + + fedSubA->registerGlobalInput("inputB"); + fedSubA->registerGlobalPublication("pubF"); + + fedSubA2 = std::make_shared("fedSubA2", core_sub1, fedInfo); + fedSubA2->registerGlobalInput("inputC"); + fedSubA2->registerGlobalPublication("pubA"); + + fedSubA2b = std::make_shared("fedSubA2b", core_sub1B, fedInfo); + + fedSubA2b->registerGlobalInput("inputD"); + fedSubA2b->registerGlobalPublication("pubE"); + + fedSubB = std::make_shared("fedSubB", core_sub2, fedInfo); + fedSubB->registerGlobalInput("inputE"); + fedSubB->registerGlobalPublication("pubB"); + fedSubSub1 = std::make_shared("fedSubSub1", core_subsub1, fedInfo); + fedSubSub1->registerGlobalInput("inputF"); + fedSubSub1->registerGlobalPublication("pubC"); + + conn1 = std::make_shared("connector1", coreA, fedInfo); + } + + void SetUp() + { + // code here will execute just before the test ensues + } + + void TearDown() { helics::cleanupHelicsLibrary(); } + + void launchThreads() + { + threads.resize(7); + threads[0] = std::thread([this]() { + fedA->enterExecutingMode(); + fedA->finalize(); + }); + + threads[1] = std::thread([this]() { + fedSubA->enterExecutingMode(); + fedSubA->finalize(); + }); + threads[2] = std::thread([this]() { + fedSubA2->enterExecutingMode(); + fedSubA2->finalize(); + }); + threads[3] = std::thread([this]() { + fedSubA2b->enterExecutingMode(); + fedSubA2b->finalize(); + }); + threads[4] = std::thread([this]() { + fedSubB->enterExecutingMode(); + fedSubB->finalize(); + }); + threads[5] = std::thread([this]() { + fedSubSub1->enterExecutingMode(); + fedSubSub1->finalize(); + }); + threads[6] = std::thread([this]() { conn1->run(); }); + } + + void closeThreads() + { + threads[6].join(); + + threads[0].join(); + threads[1].join(); + threads[2].join(); + threads[3].join(); + threads[4].join(); + threads[5].join(); + } + + ~MultibrokerFixture() {} + + helics::BrokerApp brokerA; + helics::BrokerApp subBroker1; + helics::BrokerApp subBroker2; + helics::BrokerApp subsubBroker2; + helics::CoreApp coreA; + helics::CoreApp core_sub1; + helics::CoreApp core_sub1B; + helics::CoreApp core_sub2; + helics::CoreApp core_subsub1; + std::shared_ptr fedA; + std::shared_ptr fedSubA; + std::shared_ptr fedSubA2; + std::shared_ptr fedSubA2b; + std::shared_ptr fedSubB; + std::shared_ptr fedSubSub1; + helics::FederateInfo fedInfo; + std::shared_ptr conn1; + std::vector threads; +}; + +TEST_F(MultibrokerFixture, multibroker_connector) +{ + using helics::apps::InterfaceDirection; + + conn1->addConnection("pubA", "inputA", InterfaceDirection::FROM_TO); + conn1->addConnection("pubB", "inputB", InterfaceDirection::FROM_TO); + conn1->addConnection("pubC", "inputC", InterfaceDirection::FROM_TO); + conn1->addConnection("pubD", "inputD", InterfaceDirection::FROM_TO); + conn1->addConnection("pubE", "inputE", InterfaceDirection::FROM_TO); + conn1->addConnection("pubF", "inputF", InterfaceDirection::FROM_TO); + + launchThreads(); + closeThreads(); + + EXPECT_EQ(conn1->madeConnections(), 6); +} + +TEST_F(MultibrokerFixture, multibroker_connector_aliases) +{ + using helics::apps::InterfaceDirection; + + conn1->addConnection("publicationA", "inpA", InterfaceDirection::FROM_TO); + conn1->addConnection("publicationB", "inpB", InterfaceDirection::FROM_TO); + conn1->addConnection("publicationC", "inpC", InterfaceDirection::FROM_TO); + conn1->addConnection("publicationD", "inpD", InterfaceDirection::FROM_TO); + conn1->addConnection("publicationE", "inpE", InterfaceDirection::FROM_TO); + conn1->addConnection("publicationF", "inpF", InterfaceDirection::FROM_TO); + + brokerA.addAlias("publicationA", "pubA"); + brokerA.addAlias("publicationB", "pubB"); + brokerA.addAlias("publicationC", "pubC"); + brokerA.addAlias("publicationD", "pubD"); + brokerA.addAlias("publicationE", "pubE"); + brokerA.addAlias("publicationF", "pubF"); + + brokerA.addAlias("inputA", "inpA"); + brokerA.addAlias("inputB", "inpB"); + brokerA.addAlias("inputC", "inpC"); + brokerA.addAlias("inputD", "inpD"); + brokerA.addAlias("inputE", "inpE"); + brokerA.addAlias("inputF", "inpF"); + + launchThreads(); + closeThreads(); + + EXPECT_EQ(conn1->madeConnections(), 6); +} + +TEST_F(MultibrokerFixture, multibroker_connector_regex) +{ + using helics::apps::InterfaceDirection; + + conn1->addConnection("REGEX:publication(?.)", + "REGEX:inp(?.)", + InterfaceDirection::FROM_TO); + + brokerA.addAlias("publicationA", "pubA"); + brokerA.addAlias("publicationB", "pubB"); + brokerA.addAlias("publicationC", "pubC"); + brokerA.addAlias("publicationD", "pubD"); + brokerA.addAlias("publicationE", "pubE"); + brokerA.addAlias("publicationF", "pubF"); + + brokerA.addAlias("inputA", "inpA"); + brokerA.addAlias("inputB", "inpB"); + brokerA.addAlias("inputC", "inpC"); + brokerA.addAlias("inputD", "inpD"); + brokerA.addAlias("inputE", "inpE"); + brokerA.addAlias("inputF", "inpF"); + launchThreads(); + closeThreads(); + + EXPECT_EQ(conn1->madeConnections(), 6); +} + +TEST_F(MultibrokerFixture, multibroker_connector_regex2) +{ + using helics::apps::InterfaceDirection; + conn1->addConnection("REGEX:(?.)publication(?.)", + "REGEX:inp(?.)(?.)", + InterfaceDirection::FROM_TO); + + brokerA.addAlias("pubA", "Apublication1"); + brokerA.addAlias("pubB", "Bpublication2"); + brokerA.addAlias("pubC", "Cpublication3"); + brokerA.addAlias("pubD", "Dpublication4"); + brokerA.addAlias("pubE", "Epublication5"); + brokerA.addAlias("pubF", "Fpublication6"); + + brokerA.addAlias("inputA", "inp1A"); + brokerA.addAlias("inputB", "inp2B"); + brokerA.addAlias("inputC", "inp3C"); + brokerA.addAlias("inputD", "inp4D"); + brokerA.addAlias("inputE", "inp5E"); + brokerA.addAlias("inputF", "inp6F"); + + launchThreads(); + closeThreads(); + + EXPECT_EQ(conn1->madeConnections(), 6); +} + +TEST_F(MultibrokerFixture, multibroker_connector_regex_default_tag) +{ + using helics::apps::InterfaceDirection; + + conn1->addConnection("REGEX:publication(?.)", + "REGEX:inp(?.)", + InterfaceDirection::FROM_TO, + {"default"}); + + brokerA.addAlias("publicationA", "pubA"); + brokerA.addAlias("publicationB", "pubB"); + brokerA.addAlias("publicationC", "pubC"); + brokerA.addAlias("publicationD", "pubD"); + brokerA.addAlias("publicationE", "pubE"); + brokerA.addAlias("publicationF", "pubF"); + + brokerA.addAlias("inputA", "inpA"); + brokerA.addAlias("inputB", "inpB"); + brokerA.addAlias("inputC", "inpC"); + brokerA.addAlias("inputD", "inpD"); + brokerA.addAlias("inputE", "inpE"); + brokerA.addAlias("inputF", "inpF"); + + launchThreads(); + closeThreads(); + + EXPECT_EQ(conn1->madeConnections(), 6); +} diff --git a/tests/helics/apps/CoreAppTests.cpp b/tests/helics/apps/CoreAppTests.cpp index 0ba18bf833..aeb7075d63 100644 --- a/tests/helics/apps/CoreAppTests.cpp +++ b/tests/helics/apps/CoreAppTests.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/tests/helics/apps/EchoTests.cpp b/tests/helics/apps/EchoTests.cpp index b6b52bac0d..f5323d9dd6 100644 --- a/tests/helics/apps/EchoTests.cpp +++ b/tests/helics/apps/EchoTests.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/tests/helics/apps/MultiBrokerTests.cpp b/tests/helics/apps/MultiBrokerTests.cpp index bcea535c2b..26f37a2165 100644 --- a/tests/helics/apps/MultiBrokerTests.cpp +++ b/tests/helics/apps/MultiBrokerTests.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/tests/helics/apps/PlayerTests.cpp b/tests/helics/apps/PlayerTests.cpp index ae32622918..8586572456 100644 --- a/tests/helics/apps/PlayerTests.cpp +++ b/tests/helics/apps/PlayerTests.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -16,20 +16,20 @@ SPDX-License-Identifier: BSD-3-Clause #include #include -TEST(player_tests, simple_player_test) +TEST(player_tests, simple_player) { - helics::FederateInfo fi(helics::CoreType::TEST); + helics::FederateInfo fedInfo(helics::CoreType::TEST); - fi.coreName = "pcore1"; - fi.coreInitString = "-f2 --autobroker"; - helics::apps::Player play1("player1", fi); + fedInfo.coreName = "pcore1"; + fedInfo.coreInitString = "-f2 --autobroker"; + helics::apps::Player play1("player1", fedInfo); play1.addPublication("pub1", helics::DataType::HELICS_DOUBLE); play1.addPoint(1.0, "pub1", 0.5); play1.addPoint(2.0, "pub1", 0.7); play1.addPoint(3.0, "pub1", 0.8); - helics::ValueFederate vfed("block1", fi); + helics::ValueFederate vfed("block1", fedInfo); auto& sub1 = vfed.registerSubscription("pub1"); auto fut = std::async(std::launch::async, [&play1]() { play1.run(); }); vfed.enterExecutingMode(); @@ -54,19 +54,19 @@ TEST(player_tests, simple_player_test) fut.get(); } -TEST(player_tests, simple_player_test_diff_inputs) +TEST(player_tests, simple_player_diff_inputs) { - helics::FederateInfo fi(helics::CoreType::TEST); - fi.coreName = "pcore2"; - fi.coreInitString = "-f 2 --autobroker"; - helics::apps::Player play1("player1", fi); + helics::FederateInfo fedInfo(helics::CoreType::TEST); + fedInfo.coreName = "pcore2"; + fedInfo.coreInitString = "-f 2 --autobroker"; + helics::apps::Player play1("player1", fedInfo); play1.addPublication("pub1", helics::DataType::HELICS_DOUBLE); play1.addPoint(1.0, "pub1", "v[3.0,4.0]"); play1.addPoint(2.0, "pub1", "0.7"); play1.addPoint(3.0, "pub1", std::complex(0.0, 0.8)); play1.addPoint(4.0, "pub1", "c[3.0+0j, 0.0-4.0j]"); - helics::ValueFederate vfed("block1", fi); + helics::ValueFederate vfed("block1", fedInfo); auto& sub1 = vfed.registerSubscription("pub1"); auto fut = std::async(std::launch::async, [&play1]() { play1.run(); }); vfed.enterExecutingMode(); @@ -96,19 +96,19 @@ TEST(player_tests, simple_player_test_diff_inputs) fut.get(); } -TEST(player_tests, simple_player_test_iterative) +TEST(player_tests, simple_player_iterative) { - helics::FederateInfo fi(helics::CoreType::TEST); - fi.coreName = "pcore3"; - fi.coreInitString = "-f 2 --autobroker"; - helics::apps::Player play1("player1", fi); + helics::FederateInfo fedInfo(helics::CoreType::TEST); + fedInfo.coreName = "pcore3"; + fedInfo.coreInitString = "-f 2 --autobroker"; + helics::apps::Player play1("player1", fedInfo); play1.addPublication("pub1", helics::DataType::HELICS_DOUBLE); play1.addPoint(1.0, 0, "pub1", 0.5); play1.addPoint(1.0, 1, "pub1", 0.7); play1.addPoint(1.0, 2, "pub1", 0.8); - helics::ValueFederate vfed("block1", fi); + helics::ValueFederate vfed("block1", fedInfo); auto& sub1 = vfed.registerSubscription("pub1"); auto fut = std::async(std::launch::async, [&play1]() { play1.run(); }); vfed.enterExecutingMode(); @@ -137,12 +137,12 @@ TEST(player_tests, simple_player_test_iterative) fut.get(); } -TEST(player_tests, simple_player_test2) +TEST(player_tests, simple_player2) { - helics::FederateInfo fi(helics::CoreType::TEST); - fi.coreName = "pcore4"; - fi.coreInitString = "-f 2 --autobroker"; - helics::apps::Player play1("player1", fi); + helics::FederateInfo fedInfo(helics::CoreType::TEST); + fedInfo.coreName = "pcore4"; + fedInfo.coreInitString = "-f 2 --autobroker"; + helics::apps::Player play1("player1", fedInfo); play1.addPublication("pub1"); play1.addPoint(1.0, "pub1", 0.5); @@ -154,7 +154,7 @@ TEST(player_tests, simple_player_test2) play1.addPoint(2.0, "pub2", 0.6); play1.addPoint(3.0, "pub2", 0.9); - helics::ValueFederate vfed("block1", fi); + helics::ValueFederate vfed("block1", fedInfo); auto& sub1 = vfed.registerSubscription("pub1"); auto& sub2 = vfed.registerSubscription("pub2"); auto fut = std::async(std::launch::async, [&play1]() { play1.run(); }); @@ -196,18 +196,18 @@ static constexpr const char* simple_files[] = {"example1.player", class player_file_tests: public ::testing::TestWithParam {}; -TEST_P(player_file_tests, test_files) +TEST_P(player_file_tests, files) { static char indx = 'a'; - helics::FederateInfo fi(helics::CoreType::TEST); - fi.coreName = std::string("pcore5") + GetParam(); - fi.coreName.push_back(indx++); - fi.coreInitString = "-f 2 --autobroker"; - helics::apps::Player play1("player1", fi); + helics::FederateInfo fedInfo(helics::CoreType::TEST); + fedInfo.coreName = std::string("pcore5") + GetParam(); + fedInfo.coreName.push_back(indx++); + fedInfo.coreInitString = "-f 2 --autobroker"; + helics::apps::Player play1("player1", fedInfo); play1.loadFile(std::string(TEST_DIR) + GetParam()); - helics::ValueFederate vfed("block1", fi); + helics::ValueFederate vfed("block1", fedInfo); auto& sub1 = vfed.registerSubscription("pub1"); auto& sub2 = vfed.registerSubscription("pub2"); auto fut = std::async(std::launch::async, [&play1]() { play1.run(); }); @@ -244,14 +244,14 @@ TEST_P(player_file_tests, test_files) TEST(player_tests, bigfile) { - helics::FederateInfo fi(helics::CoreType::TEST); - fi.coreName = "pcorebig"; - fi.coreInitString = "-f 2 --autobroker"; - helics::apps::Player play1("player1", fi); + helics::FederateInfo fedInfo(helics::CoreType::TEST); + fedInfo.coreName = "pcorebig"; + fedInfo.coreInitString = "-f 2 --autobroker"; + helics::apps::Player play1("player1", fedInfo); play1.loadFile(std::string(TEST_DIR) + "bigtest.txt"); - fi.setProperty(HELICS_PROPERTY_TIME_PERIOD, 60.0); - helics::ValueFederate vfed("charger", fi); + fedInfo.setProperty(HELICS_PROPERTY_TIME_PERIOD, 60.0); + helics::ValueFederate vfed("charger", fedInfo); auto& sub1 = vfed.registerSubscription("Battery/EV1_current"); auto& sub2 = vfed.registerSubscription("Battery/EV2_current"); auto& sub3 = vfed.registerSubscription("Battery/EV3_current"); @@ -298,18 +298,63 @@ TEST(player_tests, bigfile) fut.get(); } +TEST(player_tests, testfile) +{ + helics::FederateInfo fedInfo(helics::CoreType::TEST); + fedInfo.coreName = "pcoretest"; + fedInfo.coreInitString = "-f 2 --autobroker"; + helics::apps::Player play1("player1", fedInfo); + + play1.loadFile(std::string(TEST_DIR) + "oorder.txt"); + helics::ValueFederate vfed("receiver", fedInfo); + vfed.registerSubscription("player1/G"); + vfed.registerSubscription("player1/T"); + vfed.registerSubscription("player1/Fc"); + vfed.registerSubscription("player1/Ud"); + vfed.registerSubscription("player1/Rg"); + vfed.registerSubscription("player1/ctl"); + + std::vector> results; + results.resize(6); + + auto fut = std::async(std::launch::async, [&play1]() { play1.runTo(8.0); }); + vfed.enterExecutingMode(); + // helics::Time maxTime = 60.0 * 60.0 * 24.0 * 7.0; + auto retTime = vfed.requestTime(8.0); + + while (retTime <= 7.0) { + for (int ii = 0; ii < 6; ++ii) { + auto& inp = vfed.getInput(ii); + if (inp.isUpdated()) { + results[ii].push_back(inp.getDouble()); + } + } + retTime = vfed.requestTime(7.0); + } + + vfed.finalize(); + fut.get(); + EXPECT_GE(results[0].size(), 120); + EXPECT_EQ(results[1].size(), 2); + EXPECT_EQ(results[2].size(), 2); + EXPECT_EQ(results[3].size(), 2); + EXPECT_EQ(results[4].size(), 2); + EXPECT_EQ(results[5].size(), 2); + EXPECT_EQ(results[2][1], 63.0); +} + TEST(player_tests, simple_player_mlinecomment) { static char indx = 'a'; - helics::FederateInfo fi(helics::CoreType::TEST); - fi.coreName = "pcore6-mline"; - fi.coreName.push_back(indx++); - fi.coreInitString = " -f 2 --autobroker"; - helics::apps::Player play1("player1", fi); + helics::FederateInfo fedInfo(helics::CoreType::TEST); + fedInfo.coreName = "pcore6-mline"; + fedInfo.coreName.push_back(indx++); + fedInfo.coreInitString = " -f 2 --autobroker"; + helics::apps::Player play1("player1", fedInfo); play1.loadFile(std::string(TEST_DIR) + "/example_comments.player"); EXPECT_EQ(play1.pointCount(), 7U); - helics::ValueFederate vfed("block1", fi); + helics::ValueFederate vfed("block1", fedInfo); auto& sub1 = vfed.registerSubscription("pub1"); auto& sub2 = vfed.registerSubscription("pub2"); auto fut = std::async(std::launch::async, [&play1]() { play1.run(); }); @@ -354,7 +399,7 @@ TEST_P(player_file_tests, test_files_cmd) std::string exampleFile = std::string(TEST_DIR) + GetParam(); std::vector args{ - "", "--name=player", "--broker=ipc_broker", "--coretype=ipc", exampleFile}; + "", "--name=player", "--broker=ipc_broker", "--coretype=ipc", "--input=" + exampleFile}; char* argv[5]; argv[0] = &(args[0][0]); argv[1] = &(args[1][0]); @@ -364,10 +409,10 @@ TEST_P(player_file_tests, test_files_cmd) helics::apps::Player play1(5, argv); - helics::FederateInfo fi(helics::CoreType::IPC); - fi.coreInitString = "--broker=ipc_broker"; + helics::FederateInfo fedInfo(helics::CoreType::IPC); + fedInfo.coreInitString = "--broker=ipc_broker"; - helics::ValueFederate vfed("obj", fi); + helics::ValueFederate vfed("obj", fedInfo); auto& sub1 = vfed.registerSubscription("pub1"); auto& sub2 = vfed.registerSubscription("pub2"); auto fut = std::async(std::launch::async, [&play1]() { play1.run(); }); @@ -422,12 +467,13 @@ TEST_P(player_file_tests, test_files_exe) ASSERT_TRUE(brokerExe.isActive()); auto res = brokerExe.runAsync("-f 2 --coretype=zmq --name=zmq_broker"); std::string exampleFile = std::string(TEST_DIR) + GetParam(); - auto res2 = playerExe.runCaptureOutputAsync("--name=player --coretype=zmq " + exampleFile); + auto res2 = + playerExe.runCaptureOutputAsync("--name=player --coretype=zmq --input=" + exampleFile); - helics::FederateInfo fi(helics::CoreType::ZMQ); - fi.coreInitString = ""; + helics::FederateInfo fedInfo(helics::CoreType::ZMQ); + fedInfo.coreInitString = ""; - helics::ValueFederate vfed("fed", fi); + helics::ValueFederate vfed("fed", fedInfo); auto& sub1 = vfed.registerSubscription("pub1"); auto& sub2 = vfed.registerSubscription("pub2"); vfed.enterExecutingMode(); @@ -470,13 +516,13 @@ INSTANTIATE_TEST_SUITE_P(player_tests, player_file_tests, ::testing::ValuesIn(si TEST(player_tests, simple_player_testjson) { - helics::FederateInfo fi(helics::CoreType::TEST); - fi.coreName = "pcore7"; - fi.coreInitString = "-f 2 --autobroker"; - helics::apps::Player play1("player1", fi); + helics::FederateInfo fedInfo(helics::CoreType::TEST); + fedInfo.coreName = "pcore7"; + fedInfo.coreInitString = "-f 2 --autobroker"; + helics::apps::Player play1("player1", fedInfo); play1.loadFile(std::string(TEST_DIR) + "/example6.json"); - helics::ValueFederate vfed("block1", fi); + helics::ValueFederate vfed("block1", fedInfo); auto& sub1 = vfed.registerSubscription("pub1"); auto& sub2 = vfed.registerSubscription("pub2"); auto fut = std::async(std::launch::async, [&play1]() { play1.run(); }); @@ -511,12 +557,12 @@ TEST(player_tests, simple_player_testjson) TEST(player_tests, player_test_message) { - helics::FederateInfo fi(helics::CoreType::TEST); - fi.coreName = "pcore8"; - fi.coreInitString = "-f 2 --autobroker"; - helics::apps::Player play1("player1", fi); + helics::FederateInfo fedInfo(helics::CoreType::TEST); + fedInfo.coreName = "pcore8"; + fedInfo.coreInitString = "-f 2 --autobroker"; + helics::apps::Player play1("player1", fedInfo); - helics::MessageFederate mfed("block1", fi); + helics::MessageFederate mfed("block1", fedInfo); helics::Endpoint e1(helics::InterfaceVisibility::GLOBAL, &mfed, "dest"); play1.addMessage(1.0, "src", "dest", "this is a message"); @@ -539,12 +585,12 @@ TEST(player_tests, player_test_message) TEST(player_tests, player_test_message2) { - helics::FederateInfo fi(helics::CoreType::TEST); - fi.coreName = "pcore9"; - fi.coreInitString = "-f 2 --autobroker"; - helics::apps::Player play1("player1", fi); + helics::FederateInfo fedInfo(helics::CoreType::TEST); + fedInfo.coreName = "pcore9"; + fedInfo.coreInitString = "-f 2 --autobroker"; + helics::apps::Player play1("player1", fedInfo); - helics::MessageFederate mfed("block1", fi); + helics::MessageFederate mfed("block1", fedInfo); helics::Endpoint e1(helics::InterfaceVisibility::GLOBAL, &mfed, "dest"); play1.addMessage(1.0, "src", "dest", "this is a test message"); @@ -589,12 +635,12 @@ TEST(player_tests, player_test_message2) TEST(player_tests, player_test_message3) { - helics::FederateInfo fi(helics::CoreType::TEST); - fi.coreName = "pcore10"; - fi.coreInitString = "-f 2 --autobroker"; - helics::apps::Player play1("player1", fi); + helics::FederateInfo fedInfo(helics::CoreType::TEST); + fedInfo.coreName = "pcore10"; + fedInfo.coreInitString = "-f 2 --autobroker"; + helics::apps::Player play1("player1", fedInfo); - helics::MessageFederate mfed("block1", fi); + helics::MessageFederate mfed("block1", fedInfo); helics::Endpoint e1(helics::InterfaceVisibility::GLOBAL, &mfed, "dest"); play1.addMessage(1.0, "src", "dest", "this is a test message"); @@ -647,13 +693,13 @@ class player_message_file_tests: public ::testing::TestWithParam {} TEST_P(player_message_file_tests, message_test_files) { static char indx = 'a'; - helics::FederateInfo fi(helics::CoreType::TEST); - fi.coreName = std::string("pcore11") + GetParam(); - fi.coreName.push_back(indx++); - fi.coreInitString = "-f 2 --autobroker"; - helics::apps::Player play1("player1", fi); + helics::FederateInfo fedInfo(helics::CoreType::TEST); + fedInfo.coreName = std::string("pcore11") + GetParam(); + fedInfo.coreName.push_back(indx++); + fedInfo.coreInitString = "-f 2 --autobroker"; + helics::apps::Player play1("player1", fedInfo); - helics::MessageFederate mfed("block1", fi); + helics::MessageFederate mfed("block1", fedInfo); helics::Endpoint e1(helics::InterfaceVisibility::GLOBAL, &mfed, "dest"); play1.loadFile(std::string(TEST_DIR) + GetParam()); auto fut = std::async(std::launch::async, [&play1]() { play1.run(); }); diff --git a/tests/helics/apps/ProbeTests.cpp b/tests/helics/apps/ProbeTests.cpp index 76a4a227f3..0750fc3b64 100644 --- a/tests/helics/apps/ProbeTests.cpp +++ b/tests/helics/apps/ProbeTests.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/tests/helics/apps/RecorderTests.cpp b/tests/helics/apps/RecorderTests.cpp index 12b6d251cb..370e6e0884 100644 --- a/tests/helics/apps/RecorderTests.cpp +++ b/tests/helics/apps/RecorderTests.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -282,7 +282,7 @@ TEST_P(recorder_message_file_tests, test_message_files_cmd) std::string exampleFile = std::string(TEST_DIR) + GetParam(); std::vector args{ - "", "--name=rec", "--broker=ipc_broker", "--coretype=ipc", exampleFile}; + "", "--name=rec", "--broker=ipc_broker", "--coretype=ipc", "--input=" + exampleFile}; char* argv[5]; argv[0] = &(args[0][0]); argv[1] = &(args[1][0]); diff --git a/tests/helics/apps/SourceTests.cpp b/tests/helics/apps/SourceTests.cpp index 11a1c620ea..0c8b168fcf 100644 --- a/tests/helics/apps/SourceTests.cpp +++ b/tests/helics/apps/SourceTests.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/tests/helics/apps/TracerTests.cpp b/tests/helics/apps/TracerTests.cpp index 8a204611de..47c6708a00 100644 --- a/tests/helics/apps/TracerTests.cpp +++ b/tests/helics/apps/TracerTests.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -23,7 +23,7 @@ SPDX-License-Identifier: BSD-3-Clause using namespace std::literals::chrono_literals; -TEST(tracer_tests, simple_tracer_test) +TEST(tracer_tests, simple_tracer) { std::atomic lastVal{-1e49}; std::atomic lastTime{0.0}; @@ -72,7 +72,7 @@ TEST(tracer_tests, simple_tracer_test) trace1.finalize(); } -TEST(tracer_tests, tracer_test_message) +TEST(tracer_tests, tracer_message) { gmlc::libguarded::guarded> mguard; std::atomic lastTime{0.0}; @@ -146,7 +146,7 @@ static constexpr const char* simple_files[] = {"example1.recorder", class tracer_file_tests: public ::testing::TestWithParam {}; -TEST_P(tracer_file_tests, simple_tracer_test_files) +TEST_P(tracer_file_tests, simple_tracer_files) { static char indx = 'a'; helics::FederateInfo fi(helics::CoreType::TEST); @@ -207,7 +207,7 @@ static constexpr const char* simple_message_files[] = {"example4.recorder", class tracer_message_file_tests: public ::testing::TestWithParam {}; -TEST_P(tracer_message_file_tests, test_message_files) +TEST_P(tracer_message_file_tests, message_files) { static char indx = 'a'; helics::FederateInfo fi(helics::CoreType::TEST); @@ -272,12 +272,12 @@ TEST_P(tracer_message_file_tests, test_message_files) } #ifdef HELICS_ENABLE_IPC_CORE -TEST_P(tracer_message_file_tests, test_message_files_cmd) +TEST_P(tracer_message_file_tests, message_files_cmd) { std::this_thread::sleep_for(300ms); helics::apps::BrokerApp brk(helics::CoreType::IPC, "ipc_broker", "-f 2"); std::string exampleFile = std::string(TEST_DIR) + GetParam(); - std::vector args{"", "--name=rec", "--coretype=ipc", exampleFile}; + std::vector args{"", "--name=rec", "--coretype=ipc", "--input=" + exampleFile}; char* argv[4]; argv[0] = &(args[0][0]); @@ -342,7 +342,7 @@ INSTANTIATE_TEST_SUITE_P(tracer_tests, tracer_message_file_tests, ::testing::ValuesIn(simple_message_files)); -TEST(tracer_tests, tracer_test_destendpoint_clone) +TEST(tracer_tests, tracer_destendpoint_clone) { gmlc::libguarded::guarded> mguard; std::atomic lastTime{0.0}; @@ -490,7 +490,7 @@ TEST(tracer_tests, srcendpoint_clone) } } -TEST(tracer_tests, tracer_test_endpoint_clone) +TEST(tracer_tests, tracer_endpoint_clone) { gmlc::libguarded::guarded> mguard; std::atomic lastTime{0.0}; @@ -576,7 +576,7 @@ static constexpr const char* simple_clone_test_files[] = {"clone_example1.txt", class tracer_clone_file_tests: public ::testing::TestWithParam {}; -TEST_P(tracer_clone_file_tests, simple_clone_test_file) +TEST_P(tracer_clone_file_tests, simple_clone_file) { static char indx = 'a'; gmlc::libguarded::guarded> mguard; @@ -667,13 +667,14 @@ INSTANTIATE_TEST_SUITE_P(tracer_tests, // TODO(PT): I think the EXE tests need to be moved to a different structure. The EXE runner // doesn't always work right for some reason -TEST_P(tracer_message_file_tests, test_message_files_exe) +TEST_P(tracer_message_file_tests, message_files_exe) { std::this_thread::sleep_for(300ms); helics::apps::BrokerApp brk(helics::CoreType::ZMQ, "z_broker", "-f 2"); std::string exampleFile = std::string(TEST_DIR) + GetParam(); - std::string cmdArg("--name=tracer --coretype=zmq --stop=4s --print --skiplog " + exampleFile); + std::string cmdArg("--name=tracer --coretype=zmq --stop=4s --print --skiplog --input=" + + exampleFile); exeTestRunner tracerExe(HELICS_INSTALL_LOC, HELICS_BUILD_LOC, "helics_app"); ASSERT_TRUE(tracerExe.isActive()); auto out = tracerExe.runCaptureOutputAsync(std::string("tracer " + cmdArg)); diff --git a/tests/helics/apps/combo_tests.cpp b/tests/helics/apps/combo_tests.cpp index 6f4b3ddb77..3f8a14d6b7 100644 --- a/tests/helics/apps/combo_tests.cpp +++ b/tests/helics/apps/combo_tests.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/tests/helics/apps/helics_apps_tests.cpp b/tests/helics/apps/helics_apps_tests.cpp index dd407a9d78..ce4f813176 100644 --- a/tests/helics/apps/helics_apps_tests.cpp +++ b/tests/helics/apps/helics_apps_tests.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/tests/helics/apps/multi_player_tests.cpp b/tests/helics/apps/multi_player_tests.cpp index 80582c816b..fb7e37dfdf 100644 --- a/tests/helics/apps/multi_player_tests.cpp +++ b/tests/helics/apps/multi_player_tests.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/tests/helics/apps/multi_tests.cpp b/tests/helics/apps/multi_tests.cpp index 80582c816b..fb7e37dfdf 100644 --- a/tests/helics/apps/multi_tests.cpp +++ b/tests/helics/apps/multi_tests.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/tests/helics/apps/test_files/connector/cascade.txt b/tests/helics/apps/test_files/connector/cascade.txt new file mode 100644 index 0000000000..bfe4c44875 --- /dev/null +++ b/tests/helics/apps/test_files/connector/cascade.txt @@ -0,0 +1,9 @@ +#comment line for cascade file test +# second comment line +inp1 intermediate1 +intermediate1 intermediate1 bi +intermediate1 intermediate2 from_to +intermediate2 intermediate3 from_to +#comment line in the middle +intermediate3 pub1 bi +inp2 intermediate2 from_to diff --git a/tests/helics/apps/test_files/connector/simple-quotes.txt b/tests/helics/apps/test_files/connector/simple-quotes.txt new file mode 100644 index 0000000000..cd856a55b3 --- /dev/null +++ b/tests/helics/apps/test_files/connector/simple-quotes.txt @@ -0,0 +1,2 @@ +#comment line for simple file test +"inp1", "pub1", "from_to" diff --git a/tests/helics/apps/test_files/connector/simple.json b/tests/helics/apps/test_files/connector/simple.json new file mode 100644 index 0000000000..47bf227bc6 --- /dev/null +++ b/tests/helics/apps/test_files/connector/simple.json @@ -0,0 +1,3 @@ +{ + "connections": [["inp1", "pub1", "TO_FROM"]] +} diff --git a/tests/helics/apps/test_files/connector/simple.txt b/tests/helics/apps/test_files/connector/simple.txt new file mode 100644 index 0000000000..6edb88ce4a --- /dev/null +++ b/tests/helics/apps/test_files/connector/simple.txt @@ -0,0 +1,2 @@ +#comment line for simple file test +inp1 pub1 from_to diff --git a/tests/helics/apps/test_files/connector/simple_tags.txt b/tests/helics/apps/test_files/connector/simple_tags.txt new file mode 100644 index 0000000000..06dc97a960 --- /dev/null +++ b/tests/helics/apps/test_files/connector/simple_tags.txt @@ -0,0 +1,3 @@ +#comment line for simple file test +inp1 pub1 from_to tag1 +inp2 pub1 tag2 tag3 diff --git a/tests/helics/apps/test_files/oorder.txt b/tests/helics/apps/test_files/oorder.txt new file mode 100644 index 0000000000..3da78df3bc --- /dev/null +++ b/tests/helics/apps/test_files/oorder.txt @@ -0,0 +1,137 @@ +#second topic type(d,s,i,c) value +# from https://github.com/pnnl/pecblocks/blob/master/examples/helics/test/helics_player.txt +!local=true +# ramp the changes in G +-1.000 G d 0.0 + 0.101 G d 10.0 + 0.102 G d 20.0 + 0.103 G d 30.0 + 0.104 G d 40.0 + 0.105 G d 50.0 + 0.106 G d 60.0 + 0.107 G d 70.0 + 0.108 G d 80.0 + 0.109 G d 90.0 + 0.110 G d 100.0 + 0.111 G d 110.0 + 0.112 G d 120.0 + 0.113 G d 130.0 + 0.114 G d 140.0 + 0.115 G d 150.0 + 0.116 G d 160.0 + 0.117 G d 170.0 + 0.118 G d 180.0 + 0.119 G d 190.0 + 0.120 G d 200.0 + 0.121 G d 210.0 + 0.122 G d 220.0 + 0.123 G d 230.0 + 0.124 G d 240.0 + 0.125 G d 250.0 + 0.126 G d 260.0 + 0.127 G d 270.0 + 0.128 G d 280.0 + 0.129 G d 290.0 + 0.130 G d 300.0 + 0.131 G d 310.0 + 0.132 G d 320.0 + 0.133 G d 330.0 + 0.134 G d 340.0 + 0.135 G d 350.0 + 0.136 G d 360.0 + 0.137 G d 370.0 + 0.138 G d 380.0 + 0.139 G d 390.0 + 0.140 G d 400.0 + 0.141 G d 410.0 + 0.142 G d 420.0 + 0.143 G d 430.0 + 0.144 G d 440.0 + 0.145 G d 450.0 + 0.146 G d 460.0 + 0.147 G d 470.0 + 0.148 G d 480.0 + 0.149 G d 490.0 + 0.150 G d 500.0 + 0.151 G d 510.0 + 0.152 G d 520.0 + 0.153 G d 530.0 + 0.154 G d 540.0 + 0.155 G d 550.0 + 0.156 G d 560.0 + 0.157 G d 570.0 + 0.158 G d 580.0 + 0.159 G d 590.0 + 0.160 G d 600.0 + 0.161 G d 610.0 + 0.162 G d 620.0 + 0.163 G d 630.0 + 0.164 G d 640.0 + 0.165 G d 650.0 + 0.166 G d 660.0 + 0.167 G d 670.0 + 0.168 G d 680.0 + 0.169 G d 690.0 + 0.170 G d 700.0 + 0.171 G d 710.0 + 0.172 G d 720.0 + 0.173 G d 730.0 + 0.174 G d 740.0 + 0.175 G d 750.0 + 0.176 G d 760.0 + 0.177 G d 770.0 + 0.178 G d 780.0 + 0.179 G d 790.0 + 0.180 G d 800.0 + 0.181 G d 810.0 + 0.182 G d 820.0 + 0.183 G d 830.0 + 0.184 G d 840.0 + 0.185 G d 850.0 + 0.186 G d 860.0 + 0.187 G d 870.0 + 0.188 G d 880.0 + 0.189 G d 890.0 + 0.190 G d 900.0 + 0.191 G d 910.0 + 0.192 G d 920.0 + 0.193 G d 930.0 + 0.194 G d 940.0 + 0.195 G d 950.0 +# ramp the G disturbance down to 825 + 2.401 G d 945.0 + 2.402 G d 940.0 + 2.403 G d 935.0 + 2.404 G d 930.0 + 2.405 G d 925.0 + 2.406 G d 920.0 + 2.407 G d 915.0 + 2.408 G d 910.0 + 2.409 G d 905.0 + 2.410 G d 900.0 + 2.411 G d 895.0 + 2.412 G d 890.0 + 2.413 G d 885.0 + 2.414 G d 880.0 + 2.415 G d 875.0 + 2.416 G d 870.0 + 2.417 G d 865.0 + 2.418 G d 860.0 + 2.419 G d 855.0 + 2.420 G d 850.0 + 2.421 G d 845.0 + 2.422 G d 840.0 + 2.423 G d 835.0 + 2.424 G d 830.0 + 2.425 G d 825.0 +# the other changes can be abrupt +-1.000 T d 5.0 + 3.450 T d 35.0 +-1.000 Fc d 60.0 + 4.450 Fc d 63.0 +-1.000 Ud d 1.00 + 5.450 Ud d 0.92 +-1.000 Rg d 4.25 + 6.450 Rg d 6.25 +-1.000 ctl d 0.0 + 2.000 ctl d 1.0 diff --git a/tests/helics/common/CMakeLists.txt b/tests/helics/common/CMakeLists.txt index 7063e90253..d3b5a4976b 100644 --- a/tests/helics/common/CMakeLists.txt +++ b/tests/helics/common/CMakeLists.txt @@ -1,5 +1,5 @@ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Copyright (c) 2017-2023, Battelle Memorial Institute; Lawrence Livermore +# Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore # National Security, LLC; Alliance for Sustainable Energy, LLC. # See the top-level NOTICE for additional details. # All rights reserved. diff --git a/tests/helics/common/JsonGenerationTests.cpp b/tests/helics/common/JsonGenerationTests.cpp index 8a8397aa88..b1e632adb4 100644 --- a/tests/helics/common/JsonGenerationTests.cpp +++ b/tests/helics/common/JsonGenerationTests.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/tests/helics/common/SmallBufferTests.cpp b/tests/helics/common/SmallBufferTests.cpp index 220807fd7d..2d8604ff39 100644 --- a/tests/helics/common/SmallBufferTests.cpp +++ b/tests/helics/common/SmallBufferTests.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -16,281 +16,290 @@ using namespace helics; TEST(small_buffer_tests, empty) { - SmallBuffer sb; - EXPECT_EQ(sb.size(), 0U); - EXPECT_TRUE(sb.empty()); - EXPECT_EQ(sb.begin(), sb.end()); + SmallBuffer buffer; + EXPECT_EQ(buffer.size(), 0U); + EXPECT_TRUE(buffer.empty()); + EXPECT_EQ(buffer.begin(), buffer.end()); } TEST(small_buffer_tests, resize) { - SmallBuffer sb; - sb.resize(35); - EXPECT_EQ(sb.size(), 35U); - sb.resize(135121); - EXPECT_EQ(sb.size(), 135121U); - sb.resize(1541); - EXPECT_EQ(sb.size(), 1541U); + SmallBuffer buffer; + buffer.resize(35); + EXPECT_EQ(buffer.size(), 35U); + buffer.resize(135121); + EXPECT_EQ(buffer.size(), 135121U); + buffer.resize(1541); + EXPECT_EQ(buffer.size(), 1541U); } TEST(small_buffer_tests, resize_assign) { - SmallBuffer sb; - sb.resize(37, std::byte{34}); - EXPECT_EQ(sb.size(), 37U); - for (auto be : sb) { - EXPECT_EQ(be, std::byte{34}); + SmallBuffer buffer; + buffer.resize(37, std::byte{34}); + EXPECT_EQ(buffer.size(), 37U); + for (auto bufferElement : buffer) { + EXPECT_EQ(bufferElement, std::byte{34}); } - sb.resize(182, std::byte{36}); - EXPECT_EQ(sb.size(), 182U); - for (std::size_t ii = 0; ii < sb.size(); ++ii) { + buffer.resize(182, std::byte{36}); + EXPECT_EQ(buffer.size(), 182U); + for (std::size_t ii = 0; ii < buffer.size(); ++ii) { if (ii < 37) { - EXPECT_EQ(sb[ii], std::byte{34}); + EXPECT_EQ(buffer[ii], std::byte{34}); } else { - EXPECT_EQ(sb[ii], std::byte{36}); + EXPECT_EQ(buffer[ii], std::byte{36}); } } } TEST(small_buffer_tests, index_assign) { - SmallBuffer sb; - sb.resize(45); - sb[23] = std::byte{5}; - EXPECT_EQ(sb[23], std::byte{5}); + SmallBuffer buffer; + buffer.resize(45); + buffer[23] = std::byte{5}; + EXPECT_EQ(buffer[23], std::byte{5}); - sb[23] = std::byte{17}; - EXPECT_EQ(sb[23], std::byte{17}); - EXPECT_NE(sb[24], std::byte{17}); + buffer[23] = std::byte{17}; + EXPECT_EQ(buffer[23], std::byte{17}); + EXPECT_NE(buffer[24], std::byte{17}); } TEST(small_buffer_tests, at) { - SmallBuffer sb; - sb.resize(45); - sb.at(23) = std::byte{5}; - EXPECT_EQ(sb[23], std::byte{5}); - EXPECT_EQ(sb.at(23), std::byte{5}); + SmallBuffer buffer; + buffer.resize(45); + buffer.at(23) = std::byte{5}; + EXPECT_EQ(buffer[23], std::byte{5}); + EXPECT_EQ(buffer.at(23), std::byte{5}); - EXPECT_THROW(sb.at(56), std::out_of_range); + EXPECT_THROW(buffer.at(56), std::out_of_range); - sb.at(14) = std::byte{7}; - const SmallBuffer& sb2 = sb; + buffer.at(14) = std::byte{7}; + const SmallBuffer& buffer2 = buffer; - EXPECT_EQ(sb2.at(14), std::byte{7}); - EXPECT_EQ(sb2[14], std::byte{7}); + EXPECT_EQ(buffer2.at(14), std::byte{7}); + EXPECT_EQ(buffer2[14], std::byte{7}); } TEST(small_buffer_tests, string_construct) { - SmallBuffer sb("test string 1"); - EXPECT_EQ(sb.to_string(), "test string 1"); + SmallBuffer buffer("test string 1"); + EXPECT_EQ(buffer.to_string(), "test string 1"); } TEST(small_buffer_tests, string_construct2) { - SmallBuffer sb("test111111", 5); - EXPECT_EQ(sb.to_string(), "test1"); + SmallBuffer buffer("test111111", 5); + EXPECT_EQ(buffer.to_string(), "test1"); } TEST(small_buffer_tests, string_assign) { - SmallBuffer sb; - sb = "this is a test string"; - auto ts = sb.to_string(); + SmallBuffer buffer; + buffer = "this is a test string"; + auto ts = buffer.to_string(); EXPECT_EQ(ts, "this is a test string"); } TEST(small_buffer_tests, string_assign2) { - SmallBuffer sb; + SmallBuffer buffer; std::string testStr = "this is a test 2"; - sb = testStr; - auto ts = sb.to_string(); + buffer = testStr; + auto ts = buffer.to_string(); EXPECT_EQ(ts, testStr); } TEST(small_buffer_tests, capacity) { - SmallBuffer sb; - sb.reserve(450); - EXPECT_GE(sb.capacity(), 450U); - sb.reserve(12514); - EXPECT_GE(sb.capacity(), 12514U); - sb.reserve(400); - EXPECT_GE(sb.capacity(), 12514U); + SmallBuffer buffer; + buffer.reserve(450); + EXPECT_GE(buffer.capacity(), 450U); + buffer.reserve(12514); + EXPECT_GE(buffer.capacity(), 12514U); + buffer.reserve(400); + EXPECT_GE(buffer.capacity(), 12514U); } TEST(small_buffer_tests, equality) { - SmallBuffer sb1("string test 1"); - SmallBuffer sb2("string test 2"); - EXPECT_FALSE(sb1 == sb2); - EXPECT_TRUE(sb1 != sb2); - SmallBuffer sb3("string test 1"); - EXPECT_EQ(sb1, sb3); - EXPECT_NE(sb2, sb3); + SmallBuffer buffer1("string test 1"); + SmallBuffer buffer2("string test 2"); + EXPECT_FALSE(buffer1 == buffer2); + EXPECT_TRUE(buffer1 != buffer2); + SmallBuffer buffer3("string test 1"); + EXPECT_EQ(buffer1, buffer3); + EXPECT_NE(buffer2, buffer3); } TEST(small_buffer_tests, iterators) { const char* tstring = "string test 1"; - SmallBuffer sb1(tstring, 9); + SmallBuffer buffer1(tstring, 9); - std::string b2(reinterpret_cast(sb1.begin()), - reinterpret_cast(sb1.end())); - EXPECT_EQ(b2.size(), 9U); + std::string string2(reinterpret_cast(buffer1.begin()), + reinterpret_cast(buffer1.end())); + EXPECT_EQ(string2.size(), 9U); - const SmallBuffer& sb2 = sb1; - std::string b3(reinterpret_cast(sb2.begin()), - reinterpret_cast(sb2.end())); - EXPECT_EQ(b3.size(), 9U); + const SmallBuffer& buffer2 = buffer1; + std::string string3(reinterpret_cast(buffer2.begin()), + reinterpret_cast(buffer2.end())); + EXPECT_EQ(string3.size(), 9U); // first 9 elements of the string - EXPECT_EQ(b3, "string te"); + EXPECT_EQ(string3, "string te"); } TEST(small_buffer_tests, copy_constructor) { - SmallBuffer sb1(std::string(400, 'a')); - EXPECT_EQ(sb1[234], std::byte{'a'}); - SmallBuffer sb2(sb1); + SmallBuffer buffer1(std::string(400, 'a')); + EXPECT_EQ(buffer1[234], std::byte{'a'}); + SmallBuffer buffer2(buffer1); - EXPECT_EQ(sb1, sb2); - EXPECT_EQ(sb2[219], std::byte{'a'}); + EXPECT_EQ(buffer1, buffer2); + EXPECT_EQ(buffer2[219], std::byte{'a'}); } TEST(small_buffer_tests, copy_constructor2) { - SmallBuffer sb1(std::string(16, 'a')); - EXPECT_EQ(sb1[13], std::byte{'a'}); - SmallBuffer sb2(sb1); + SmallBuffer buffer1(std::string(16, 'a')); + EXPECT_EQ(buffer1[13], std::byte{'a'}); + SmallBuffer buffer2(buffer1); - EXPECT_EQ(sb1, sb2); - EXPECT_EQ(sb2[11], std::byte{'a'}); + EXPECT_EQ(buffer1, buffer2); + EXPECT_EQ(buffer2[11], std::byte{'a'}); } TEST(small_buffer_tests, copy_assign) { - SmallBuffer sb1(std::string(400, 'a')); - EXPECT_EQ(sb1[234], std::byte{'a'}); - SmallBuffer sb2; - EXPECT_TRUE(sb2.empty()); - sb2 = sb1; - EXPECT_EQ(sb1, sb2); - EXPECT_EQ(sb2[219], std::byte{'a'}); + SmallBuffer buffer1(std::string(400, 'a')); + EXPECT_EQ(buffer1[234], std::byte{'a'}); + SmallBuffer buffer2; + EXPECT_TRUE(buffer2.empty()); + buffer2 = buffer1; + EXPECT_EQ(buffer1, buffer2); + EXPECT_EQ(buffer2[219], std::byte{'a'}); } TEST(small_buffer_tests, copy_assign2) { - SmallBuffer sb1(std::string(16, 'a')); - EXPECT_EQ(sb1[13], std::byte{'a'}); - SmallBuffer sb2; - EXPECT_TRUE(sb2.empty()); - sb2 = sb1; - EXPECT_EQ(sb1, sb2); - EXPECT_EQ(sb2[11], std::byte{'a'}); + SmallBuffer buffer1(std::string(16, 'a')); + EXPECT_EQ(buffer1[13], std::byte{'a'}); + SmallBuffer buffer2; + EXPECT_TRUE(buffer2.empty()); + buffer2 = buffer1; + EXPECT_EQ(buffer1, buffer2); + EXPECT_EQ(buffer2[11], std::byte{'a'}); } TEST(small_buffer_tests, copy_assign_full) { - SmallBuffer sb1(std::string(400, 'a')); - EXPECT_EQ(sb1[234], std::byte{'a'}); - SmallBuffer sb2(std::string(36223, 'b')); - EXPECT_EQ(sb2.size(), 36223U); - sb2 = sb1; - EXPECT_EQ(sb1, sb2); - EXPECT_EQ(sb2[219], std::byte{'a'}); + SmallBuffer buffer1(std::string(400, 'a')); + EXPECT_EQ(buffer1[234], std::byte{'a'}); + SmallBuffer buffer2(std::string(36223, 'b')); + EXPECT_EQ(buffer2.size(), 36223U); + buffer2 = buffer1; + EXPECT_EQ(buffer1, buffer2); + EXPECT_EQ(buffer2[219], std::byte{'a'}); } TEST(small_buffer_tests, copy_assign_full2) { - SmallBuffer sb1(std::string(16, 'a')); - EXPECT_EQ(sb1[13], std::byte{'a'}); - SmallBuffer sb2(std::string(36223, 'b')); - EXPECT_EQ(sb2.size(), 36223U); - sb2 = sb1; - EXPECT_EQ(sb1, sb2); - EXPECT_EQ(sb2[11], std::byte{'a'}); + SmallBuffer buffer1(std::string(16, 'a')); + EXPECT_EQ(buffer1[13], std::byte{'a'}); + SmallBuffer buffer2(std::string(36223, 'b')); + EXPECT_EQ(buffer2.size(), 36223U); + buffer2 = buffer1; + EXPECT_EQ(buffer1, buffer2); + EXPECT_EQ(buffer2[11], std::byte{'a'}); } TEST(small_buffer_tests, move_constructor) { - SmallBuffer sb1(std::string(400, 'a')); - EXPECT_EQ(sb1[234], std::byte{'a'}); - SmallBuffer sb2(std::move(sb1)); + SmallBuffer buffer1(std::string(400, 'a')); + EXPECT_EQ(buffer1[234], std::byte{'a'}); + SmallBuffer buffer2(std::move(buffer1)); - EXPECT_EQ(sb2[219], std::byte{'a'}); + EXPECT_EQ(buffer2[219], std::byte{'a'}); } TEST(small_buffer_tests, move_assign) { - SmallBuffer sb1(std::string(400, 'a')); - EXPECT_EQ(sb1[234], std::byte{'a'}); - SmallBuffer sb2; - EXPECT_TRUE(sb2.empty()); - sb2 = std::move(sb1); - EXPECT_EQ(sb2[219], std::byte{'a'}); - EXPECT_EQ(sb2.size(), 400U); + SmallBuffer buffer1(std::string(400, 'a')); + EXPECT_EQ(buffer1[234], std::byte{'a'}); + SmallBuffer buffer2; + EXPECT_TRUE(buffer2.empty()); + buffer2 = std::move(buffer1); + EXPECT_EQ(buffer2[219], std::byte{'a'}); + EXPECT_EQ(buffer2.size(), 400U); } TEST(small_buffer_tests, move_assign2) { - SmallBuffer sb1(std::string(16, 'a')); - EXPECT_EQ(sb1[13], std::byte{'a'}); - SmallBuffer sb2; - EXPECT_TRUE(sb2.empty()); - sb2 = std::move(sb1); - EXPECT_EQ(sb2[11], std::byte{'a'}); + SmallBuffer buffer1(std::string(16, 'a')); + EXPECT_EQ(buffer1[13], std::byte{'a'}); + SmallBuffer buffer2; + EXPECT_TRUE(buffer2.empty()); + buffer2 = std::move(buffer1); + EXPECT_EQ(buffer2[11], std::byte{'a'}); } TEST(small_buffer_tests, move_assign_full) { - SmallBuffer sb1(std::string(400, 'a')); - EXPECT_EQ(sb1[234], std::byte{'a'}); - SmallBuffer sb2(std::string(36223, 'b')); - EXPECT_EQ(sb2.size(), 36223U); - sb2 = std::move(sb1); - EXPECT_EQ(sb2[219], std::byte{'a'}); + SmallBuffer buffer1(std::string(400, 'a')); + EXPECT_EQ(buffer1[234], std::byte{'a'}); + SmallBuffer buffer2(std::string(36223, 'b')); + EXPECT_EQ(buffer2.size(), 36223U); + buffer2 = std::move(buffer1); + EXPECT_EQ(buffer2[219], std::byte{'a'}); } TEST(small_buffer_tests, move_assign_full2) { - SmallBuffer sb1(std::string(16, 'a')); - EXPECT_EQ(sb1[13], std::byte{'a'}); - SmallBuffer sb2(std::string(36223, 'b')); - EXPECT_EQ(sb2.size(), 36223U); - sb2 = std::move(sb1); - EXPECT_EQ(sb2[11], std::byte{'a'}); + SmallBuffer buffer1(std::string(16, 'a')); + EXPECT_EQ(buffer1[13], std::byte{'a'}); + SmallBuffer buffer2(std::string(36223, 'b')); + EXPECT_EQ(buffer2.size(), 36223U); + buffer2 = std::move(buffer1); + EXPECT_EQ(buffer2[11], std::byte{'a'}); } TEST(small_buffer_tests, move_assign_self) { - SmallBuffer sb1(std::string(36214, 'e')); - EXPECT_EQ(sb1.size(), 36214U); + SmallBuffer buffer1(std::string(36214, 'e')); + EXPECT_EQ(buffer1.size(), 36214U); // this is testing self move so ignore the warning about #if defined(__clang__) # pragma clang diagnostic push # pragma clang diagnostic ignored "-Wself-move" #endif - sb1 = std::move(sb1); + +#if defined(__GNUC__) && (__GNUC__ >= 13) +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wself-move" +#endif + buffer1 = std::move(buffer1); + +#if defined(__GNUC__) && (__GNUC__ >= 13) +# pragma GCC diagnostic pop +#endif #if defined(__clang__) # pragma clang diagnostic pop #endif - EXPECT_EQ(sb1[11], std::byte{'e'}); // NOLINT + EXPECT_EQ(buffer1[11], std::byte{'e'}); // NOLINT } TEST(small_buffer_tests, buffer_transfer) { - SmallBuffer sb1; + SmallBuffer buffer1; auto* buffer = new std::byte[5000]; - sb1.moveAssign(buffer, 4567, 5000); - EXPECT_EQ(sb1.size(), 4567U); - EXPECT_EQ(sb1.capacity(), 5000U); - sb1[27] = std::byte{15}; + buffer1.moveAssign(buffer, 4567, 5000); + EXPECT_EQ(buffer1.size(), 4567U); + EXPECT_EQ(buffer1.capacity(), 5000U); + buffer1[27] = std::byte{15}; EXPECT_EQ(buffer[27], std::byte{15}); // the SMallbuffer should take care of deletion @@ -298,13 +307,13 @@ TEST(small_buffer_tests, buffer_transfer) TEST(small_buffer_tests, buffer_transfer_full) { - SmallBuffer sb1(std::string(2354, 'b')); + SmallBuffer buffer1(std::string(2354, 'b')); auto* buffer = new std::byte[5000]; - sb1.moveAssign(buffer, 4567, 5000); - EXPECT_EQ(sb1.size(), 4567U); - EXPECT_EQ(sb1.capacity(), 5000U); - sb1[27] = std::byte{15}; + buffer1.moveAssign(buffer, 4567, 5000); + EXPECT_EQ(buffer1.size(), 4567U); + EXPECT_EQ(buffer1.capacity(), 5000U); + buffer1[27] = std::byte{15}; EXPECT_EQ(buffer[27], std::byte{15}); // the SMallbuffer should take care of deletion @@ -312,28 +321,28 @@ TEST(small_buffer_tests, buffer_transfer_full) TEST(small_buffer_tests, buffer_transfer_self_assign) { - SmallBuffer sb1(std::string(2354, 'b')); + SmallBuffer buffer1(std::string(2354, 'b')); - sb1.moveAssign(sb1.data(), 2314, 2354); - EXPECT_EQ(sb1.size(), 2314U); - EXPECT_GE(sb1.capacity(), 2354U); - sb1[27] = std::byte{15}; + buffer1.moveAssign(buffer1.data(), 2314, 2354); + EXPECT_EQ(buffer1.size(), 2314U); + EXPECT_GE(buffer1.capacity(), 2354U); + buffer1[27] = std::byte{15}; - EXPECT_EQ(sb1[27], std::byte{15}); - EXPECT_EQ(sb1[20], std::byte{'b'}); + EXPECT_EQ(buffer1[27], std::byte{15}); + EXPECT_EQ(buffer1[20], std::byte{'b'}); // the SMallbuffer should take care of deletion } TEST(small_buffer_tests, buffer_borrow) { - SmallBuffer sb1; + SmallBuffer buffer1; std::vector buffer; buffer.resize(5000); - sb1.spanAssign(buffer.data(), 4567, 5000); - EXPECT_EQ(sb1.size(), 4567U); - EXPECT_EQ(sb1.capacity(), 5000U); - sb1[27] = std::byte{15}; + buffer1.spanAssign(buffer.data(), 4567, 5000); + EXPECT_EQ(buffer1.size(), 4567U); + EXPECT_EQ(buffer1.capacity(), 5000U); + buffer1[27] = std::byte{15}; EXPECT_EQ(buffer[27], std::byte{15}); // the Smallbuffer should not delete the object @@ -341,14 +350,14 @@ TEST(small_buffer_tests, buffer_borrow) TEST(small_buffer_tests, buffer_borrow_full) { - SmallBuffer sb1(std::string(2354, 'b')); + SmallBuffer buffer1(std::string(2354, 'b')); std::vector buffer; buffer.resize(5000); - sb1.spanAssign(buffer.data(), 4567, 5000); - EXPECT_EQ(sb1.size(), 4567U); - EXPECT_EQ(sb1.capacity(), 5000U); - sb1[27] = std::byte{15}; + buffer1.spanAssign(buffer.data(), 4567, 5000); + EXPECT_EQ(buffer1.size(), 4567U); + EXPECT_EQ(buffer1.capacity(), 5000U); + buffer1[27] = std::byte{15}; EXPECT_EQ(buffer[27], std::byte{15}); // the Smallbuffer should not delete the object @@ -356,169 +365,169 @@ TEST(small_buffer_tests, buffer_borrow_full) TEST(small_buffer_tests, buffer_borrow_locked) { - SmallBuffer sb1(std::string(2354, 'b')); + SmallBuffer buffer1(std::string(2354, 'b')); std::vector buffer; buffer.resize(5000); - sb1.spanAssign(buffer.data(), 4567, 5000); - sb1.lock(); - EXPECT_TRUE(sb1.isLocked()); - EXPECT_EQ(sb1.size(), 4567U); - EXPECT_EQ(sb1.capacity(), 5000U); - EXPECT_THROW(sb1.resize(5025), std::bad_alloc); - sb1.lock(false); - EXPECT_FALSE(sb1.isLocked()); - EXPECT_NO_THROW(sb1.resize(5025)); + buffer1.spanAssign(buffer.data(), 4567, 5000); + buffer1.lock(); + EXPECT_TRUE(buffer1.isLocked()); + EXPECT_EQ(buffer1.size(), 4567U); + EXPECT_EQ(buffer1.capacity(), 5000U); + EXPECT_THROW(buffer1.resize(5025), std::bad_alloc); + buffer1.lock(false); + EXPECT_FALSE(buffer1.isLocked()); + EXPECT_NO_THROW(buffer1.resize(5025)); } TEST(small_buffer_tests, buffer_borrow_self_assign) { - SmallBuffer sb1(std::string(2354, 'b')); + SmallBuffer buffer1(std::string(2354, 'b')); - sb1.spanAssign(sb1.data(), 1986, 2000); - EXPECT_EQ(sb1.size(), 1986U); - EXPECT_GE(sb1.capacity(), 2000U); - sb1[27] = std::byte{15}; + buffer1.spanAssign(buffer1.data(), 1986, 2000); + EXPECT_EQ(buffer1.size(), 1986U); + EXPECT_GE(buffer1.capacity(), 2000U); + buffer1[27] = std::byte{15}; - EXPECT_EQ(sb1[27], std::byte{15}); - EXPECT_EQ(sb1[20], std::byte{'b'}); + EXPECT_EQ(buffer1[27], std::byte{15}); + EXPECT_EQ(buffer1[20], std::byte{'b'}); // this should trigger self assignment detection } TEST(small_buffer_tests, assign) { - SmallBuffer sb1; - std::string t1(3634, 'g'); - sb1.assign(t1.data(), t1.data() + t1.size()); - EXPECT_EQ(t1.size(), sb1.size()); - EXPECT_EQ(sb1[3333], std::byte{'g'}); + SmallBuffer buffer1; + std::string string1(3634, 'g'); + buffer1.assign(string1.data(), string1.data() + string1.size()); + EXPECT_EQ(string1.size(), buffer1.size()); + EXPECT_EQ(buffer1[3333], std::byte{'g'}); - sb1.assign(t1.data(), t1.data()); - EXPECT_EQ(sb1.size(), 0U); + buffer1.assign(string1.data(), string1.data()); + EXPECT_EQ(buffer1.size(), 0U); } TEST(small_buffer_tests, assign_size) { - SmallBuffer sb1; - std::string t1(3615, 'q'); - sb1.assign(t1.data(), t1.size()); - EXPECT_EQ(t1.size(), sb1.size()); - EXPECT_EQ(sb1[3333], std::byte{'q'}); + SmallBuffer buffer1; + std::string string1(3615, 'q'); + buffer1.assign(string1.data(), string1.size()); + EXPECT_EQ(string1.size(), buffer1.size()); + EXPECT_EQ(buffer1[3333], std::byte{'q'}); } TEST(small_buffer_tests, assign_invalid) { - SmallBuffer sb1; - std::string t1; - sb1.assign(t1.data(), t1.data() + t1.size()); - EXPECT_EQ(t1.size(), sb1.size()); + SmallBuffer buffer1; + std::string string1; + buffer1.assign(string1.data(), string1.data() + string1.size()); + EXPECT_EQ(string1.size(), buffer1.size()); - EXPECT_THROW(sb1.assign(t1.data(), t1.data() - 45), std::invalid_argument); + EXPECT_THROW(buffer1.assign(string1.data(), string1.data() - 45), std::invalid_argument); } TEST(small_buffer_tests, append) { - SmallBuffer sb1; - std::string t1(3634, 'g'); - std::string t2(1516, 'k'); - sb1.append(t1.data(), t1.data() + t1.size()); - sb1.append(t2.data(), t2.data() + t2.size()); - EXPECT_EQ(t1.size() + t2.size(), sb1.size()); - EXPECT_EQ(sb1[3333], std::byte{'g'}); - EXPECT_EQ(sb1[3634], std::byte{'k'}); + SmallBuffer buffer1; + std::string string1(3634, 'g'); + std::string string2(1516, 'k'); + buffer1.append(string1.data(), string1.data() + string1.size()); + buffer1.append(string2.data(), string2.data() + string2.size()); + EXPECT_EQ(string1.size() + string2.size(), buffer1.size()); + EXPECT_EQ(buffer1[3333], std::byte{'g'}); + EXPECT_EQ(buffer1[3634], std::byte{'k'}); } TEST(small_buffer_tests, append_size) { - SmallBuffer sb1; - std::string t1(3634, 'r'); - std::string t2(1516, 't'); - sb1.append(t1.data(), t1.size()); - sb1.append(t2.data(), t2.size()); - EXPECT_EQ(t1.size() + t2.size(), sb1.size()); - EXPECT_EQ(sb1[3333], std::byte{'r'}); - EXPECT_EQ(sb1[3634], std::byte{'t'}); + SmallBuffer buffer1; + std::string string1(3634, 'r'); + std::string string2(1516, 't'); + buffer1.append(string1.data(), string1.size()); + buffer1.append(string2.data(), string2.size()); + EXPECT_EQ(string1.size() + string2.size(), buffer1.size()); + EXPECT_EQ(buffer1[3333], std::byte{'r'}); + EXPECT_EQ(buffer1[3634], std::byte{'t'}); } TEST(small_buffer_tests, append_invalid) { - SmallBuffer sb1; - std::string t1; - sb1.append(t1.data(), t1.data() + t1.size()); - EXPECT_EQ(t1.size(), sb1.size()); + SmallBuffer buffer1; + std::string string1; + buffer1.append(string1.data(), string1.data() + string1.size()); + EXPECT_EQ(string1.size(), buffer1.size()); - EXPECT_THROW(sb1.append(t1.data(), t1.data() - 45), std::invalid_argument); + EXPECT_THROW(buffer1.append(string1.data(), string1.data() - 45), std::invalid_argument); } TEST(small_buffer_tests, swap1) { constexpr std::string_view testString("this is a test"); - SmallBuffer sb1; - SmallBuffer sb2(testString); - sb1.swap(sb2); - EXPECT_TRUE(sb2.empty()); - EXPECT_EQ(sb1.to_string(), testString); + SmallBuffer buffer1; + SmallBuffer buffer2(testString); + buffer1.swap(buffer2); + EXPECT_TRUE(buffer2.empty()); + EXPECT_EQ(buffer1.to_string(), testString); } TEST(small_buffer_tests, swap2) { const std::string testString(21514, 'c'); - SmallBuffer sb1; - SmallBuffer sb2(testString); - sb1.swap(sb2); - EXPECT_TRUE(sb2.empty()); - EXPECT_EQ(sb1.to_string(), testString); + SmallBuffer buffer1; + SmallBuffer buffer2(testString); + buffer1.swap(buffer2); + EXPECT_TRUE(buffer2.empty()); + EXPECT_EQ(buffer1.to_string(), testString); } TEST(small_buffer_tests, swap3) { const std::string testString1(21514, 'c'); const std::string testString2(3453, 'e'); - SmallBuffer sb1(testString1); - SmallBuffer sb2(testString2); - sb1.swap(sb2); - EXPECT_EQ(sb2.to_string(), testString1); - EXPECT_EQ(sb1.to_string(), testString2); + SmallBuffer buffer1(testString1); + SmallBuffer buffer2(testString2); + buffer1.swap(buffer2); + EXPECT_EQ(buffer2.to_string(), testString1); + EXPECT_EQ(buffer1.to_string(), testString2); } TEST(small_buffer_tests, swap4) { const std::string testString(21514, 'c'); - SmallBuffer sb1; - SmallBuffer sb2(testString); - sb2.swap(sb1); - EXPECT_TRUE(sb2.empty()); - EXPECT_EQ(sb1.to_string(), testString); + SmallBuffer buffer1; + SmallBuffer buffer2(testString); + buffer2.swap(buffer1); + EXPECT_TRUE(buffer2.empty()); + EXPECT_EQ(buffer1.to_string(), testString); } TEST(small_buffer_tests, swap5) { const std::string testString(21514, 'c'); - SmallBuffer sb1; + SmallBuffer buffer1; std::vector buffer; buffer.resize(5000); - sb1.spanAssign(buffer.data(), 4567, 5000); + buffer1.spanAssign(buffer.data(), 4567, 5000); - SmallBuffer sb2(testString); - sb2.swap(sb1); - EXPECT_EQ(sb2.size(), 4567U); - EXPECT_EQ(sb1.to_string(), testString); + SmallBuffer buffer2(testString); + buffer2.swap(buffer1); + EXPECT_EQ(buffer2.size(), 4567U); + EXPECT_EQ(buffer1.to_string(), testString); } TEST(small_buffer_tests, release) { - auto* sb1 = new SmallBuffer(std::string(1562268, 'f')); + auto* buffer1 = new SmallBuffer(std::string(1562268, 'f')); - EXPECT_EQ(sb1->size(), 1562268U); - (*sb1)[57515] = std::byte{'q'}; + EXPECT_EQ(buffer1->size(), 1562268U); + (*buffer1)[57515] = std::byte{'q'}; - auto* buffer = sb1->release(); + auto* buffer = buffer1->release(); ASSERT_FALSE(buffer == nullptr); buffer[13] = std::byte{'r'}; EXPECT_EQ(buffer[57515], std::byte{'q'}); EXPECT_EQ(buffer[13], std::byte{'r'}); - delete sb1; + delete buffer1; EXPECT_EQ(buffer[57515], std::byte{'q'}); EXPECT_EQ(buffer[13], std::byte{'r'}); delete[] buffer; diff --git a/tests/helics/common/TimeTests.cpp b/tests/helics/common/TimeTests.cpp index cf3af6e3cf..5c2a90e9ec 100644 --- a/tests/helics/common/TimeTests.cpp +++ b/tests/helics/common/TimeTests.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/tests/helics/core/ActionMessage-tests.cpp b/tests/helics/core/ActionMessage-tests.cpp index 0b182cba9c..b57f710ecd 100644 --- a/tests/helics/core/ActionMessage-tests.cpp +++ b/tests/helics/core/ActionMessage-tests.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/tests/helics/core/BrokerClassTests.cpp b/tests/helics/core/BrokerClassTests.cpp index 7f1b33e4d2..3d9fbbf047 100644 --- a/tests/helics/core/BrokerClassTests.cpp +++ b/tests/helics/core/BrokerClassTests.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/tests/helics/core/CMakeLists.txt b/tests/helics/core/CMakeLists.txt index 3901df068f..f06bbc22c7 100644 --- a/tests/helics/core/CMakeLists.txt +++ b/tests/helics/core/CMakeLists.txt @@ -1,5 +1,5 @@ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Copyright (c) 2017-2023, Battelle Memorial Institute; Lawrence Livermore +# Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore # National Security, LLC; Alliance for Sustainable Energy, LLC. # See the top-level NOTICE for additional details. # All rights reserved. diff --git a/tests/helics/core/CoreConfigureTests.cpp b/tests/helics/core/CoreConfigureTests.cpp index 44f147d8c9..0ba1a3e258 100644 --- a/tests/helics/core/CoreConfigureTests.cpp +++ b/tests/helics/core/CoreConfigureTests.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/tests/helics/core/CoreFactory-tests.cpp b/tests/helics/core/CoreFactory-tests.cpp index 502cce8b02..3ac07241e9 100644 --- a/tests/helics/core/CoreFactory-tests.cpp +++ b/tests/helics/core/CoreFactory-tests.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -15,7 +15,7 @@ SPDX-License-Identifier: BSD-3-Clause #include "gtest/gtest.h" #include -static const bool ld = helics::loadCores(); +static const bool loaded = helics::loadCores(); #ifdef HELICS_ENABLE_ZMQ_CORE TEST(CoreFactory, ZmqCore) @@ -40,10 +40,10 @@ TEST(CoreFactory, ZmqCore) TEST(CoreFactory,MpiCore) { EXPECT_EQ (helics::core::isCoreTypeAvailable (helics::CoreType::MPI), true); - auto core = helics::CoreFactory::create (helics::CoreType::MPI, ""); - ASSERT_TRUE (core != nullptr); - helics::CoreFactory::unregisterCore (core->getIdentifier ()); - core = nullptr; + auto coretype = helics::CoreFactory::create (helics::CoreType::MPI, ""); + ASSERT_TRUE (coretype != nullptr); + helics::CoreFactory::unregisterCore (coretype->getIdentifier ()); + coretype = nullptr; } #else TEST(CoreFactory,MpiCore) @@ -159,24 +159,24 @@ TEST(core, core_log_command_failures) TEST(CoreFactory, availableCores) { - auto ac = helics::CoreFactory::getAvailableCoreTypes(); - for (const auto& ct : ac) { - EXPECT_TRUE(helics::core::isCoreTypeAvailable(helics::core::coreTypeFromString(ct))); + auto availableCores = helics::CoreFactory::getAvailableCoreTypes(); + for (const auto& coretype : availableCores) { + EXPECT_TRUE(helics::core::isCoreTypeAvailable(helics::core::coreTypeFromString(coretype))); } } TEST(core, systemInfo) { - auto eVers = helics::systemInfo(); + auto eVers = helics::core::systemInfo(); - auto jv = helics::fileops::loadJsonStr(eVers); - EXPECT_FALSE(jv.isNull()); + auto json = helics::fileops::loadJsonStr(eVers); + EXPECT_FALSE(json.isNull()); - EXPECT_FALSE(jv["version"].isNull()); + EXPECT_FALSE(json["version"].isNull()); - ASSERT_FALSE(jv["cores"].isNull()); - for (const auto& cr : jv["cores"]) { - auto cname = cr.asString(); + ASSERT_FALSE(json["cores"].isNull()); + for (const auto& coretype : json["cores"]) { + auto cname = coretype.asString(); EXPECT_TRUE(helics::core::isCoreTypeAvailable(helics::core::coreTypeFromString(cname))); } } diff --git a/tests/helics/core/CoreOperationsTests.cpp b/tests/helics/core/CoreOperationsTests.cpp index 5527945cce..d8f3b9a0cb 100644 --- a/tests/helics/core/CoreOperationsTests.cpp +++ b/tests/helics/core/CoreOperationsTests.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/tests/helics/core/FederateState-tests.cpp b/tests/helics/core/FederateState-tests.cpp index 81dcb7fae0..e37f568eae 100644 --- a/tests/helics/core/FederateState-tests.cpp +++ b/tests/helics/core/FederateState-tests.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/tests/helics/core/FilterFederateTests.cpp b/tests/helics/core/FilterFederateTests.cpp index 9d77c84e98..f4086fa578 100644 --- a/tests/helics/core/FilterFederateTests.cpp +++ b/tests/helics/core/FilterFederateTests.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/tests/helics/core/ForwardingTimeCoordinatorTests.cpp b/tests/helics/core/ForwardingTimeCoordinatorTests.cpp index 322634c610..43cd90a0c1 100644 --- a/tests/helics/core/ForwardingTimeCoordinatorTests.cpp +++ b/tests/helics/core/ForwardingTimeCoordinatorTests.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/tests/helics/core/HandleManagerTests.cpp b/tests/helics/core/HandleManagerTests.cpp index b3fbcf8dfd..a4ff556c30 100644 --- a/tests/helics/core/HandleManagerTests.cpp +++ b/tests/helics/core/HandleManagerTests.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/tests/helics/core/InfoClass-tests.cpp b/tests/helics/core/InfoClass-tests.cpp index 64156aa165..91bbf98a3c 100644 --- a/tests/helics/core/InfoClass-tests.cpp +++ b/tests/helics/core/InfoClass-tests.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/tests/helics/core/MessageTimerTests.cpp b/tests/helics/core/MessageTimerTests.cpp index ef5b1a5fe8..63ab752ef2 100644 --- a/tests/helics/core/MessageTimerTests.cpp +++ b/tests/helics/core/MessageTimerTests.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/tests/helics/core/TimeCoordinatorTests.cpp b/tests/helics/core/TimeCoordinatorTests.cpp index 119bd8b319..e602dbc232 100644 --- a/tests/helics/core/TimeCoordinatorTests.cpp +++ b/tests/helics/core/TimeCoordinatorTests.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/tests/helics/core/TimeDependenciesTests.cpp b/tests/helics/core/TimeDependenciesTests.cpp index 4fdfa137cf..7772090bd1 100644 --- a/tests/helics/core/TimeDependenciesTests.cpp +++ b/tests/helics/core/TimeDependenciesTests.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/tests/helics/core/core-tests.cpp b/tests/helics/core/core-tests.cpp index 1d9d079e4d..642c7068a2 100644 --- a/tests/helics/core/core-tests.cpp +++ b/tests/helics/core/core-tests.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/tests/helics/coreTypeLists.hpp b/tests/helics/coreTypeLists.hpp index 4a17092f55..91b3b6b37b 100644 --- a/tests/helics/coreTypeLists.hpp +++ b/tests/helics/coreTypeLists.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/tests/helics/find_package_tests/CMakeLists.txt b/tests/helics/find_package_tests/CMakeLists.txt index 9b6e86c722..d1c0510dba 100644 --- a/tests/helics/find_package_tests/CMakeLists.txt +++ b/tests/helics/find_package_tests/CMakeLists.txt @@ -1,5 +1,5 @@ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Copyright (c) 2017-2023, Battelle Memorial Institute; Lawrence Livermore +# Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore # National Security, LLC; Alliance for Sustainable Energy, LLC. # See the top-level NOTICE for additional details. # All rights reserved. diff --git a/tests/helics/network/CMakeLists.txt b/tests/helics/network/CMakeLists.txt index dc3c8fb4df..bff4726b24 100644 --- a/tests/helics/network/CMakeLists.txt +++ b/tests/helics/network/CMakeLists.txt @@ -1,5 +1,5 @@ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Copyright (c) 2017-2023, Battelle Memorial Institute; Lawrence Livermore +# Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore # National Security, LLC; Alliance for Sustainable Energy, LLC. # See the top-level NOTICE for additional details. # All rights reserved. diff --git a/tests/helics/network/TestCore-tests.cpp b/tests/helics/network/TestCore-tests.cpp index 12a109a653..f51c4e330d 100644 --- a/tests/helics/network/TestCore-tests.cpp +++ b/tests/helics/network/TestCore-tests.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/tests/helics/network/network-tests.cpp b/tests/helics/network/network-tests.cpp index d4318e4ef4..e2170cdb23 100644 --- a/tests/helics/network/network-tests.cpp +++ b/tests/helics/network/network-tests.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/tests/helics/network/networkInfoTests.cpp b/tests/helics/network/networkInfoTests.cpp index 06cf196c43..a3842ebd5e 100644 --- a/tests/helics/network/networkInfoTests.cpp +++ b/tests/helics/network/networkInfoTests.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/tests/helics/package_config_tests/CMakeLists.txt b/tests/helics/package_config_tests/CMakeLists.txt index dc8c2e9aea..81fe387ea6 100644 --- a/tests/helics/package_config_tests/CMakeLists.txt +++ b/tests/helics/package_config_tests/CMakeLists.txt @@ -1,5 +1,5 @@ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Copyright (c) 2017-2023, Battelle Memorial Institute; Lawrence Livermore +# Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore # National Security, LLC; Alliance for Sustainable Energy, LLC. # See the top-level NOTICE for additional details. # All rights reserved. diff --git a/tests/helics/sequencing_tests/CMakeLists.txt b/tests/helics/sequencing_tests/CMakeLists.txt index 73f80005c7..d650326123 100644 --- a/tests/helics/sequencing_tests/CMakeLists.txt +++ b/tests/helics/sequencing_tests/CMakeLists.txt @@ -1,5 +1,5 @@ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Copyright (c) 2017-2023, Battelle Memorial Institute; Lawrence Livermore +# Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore # National Security, LLC; Alliance for Sustainable Energy, LLC. # See the top-level NOTICE for additional details. # All rights reserved. diff --git a/tests/helics/sequencing_tests/Sequencing1.cpp b/tests/helics/sequencing_tests/Sequencing1.cpp index e0c7dd065b..3d5e0527d7 100644 --- a/tests/helics/sequencing_tests/Sequencing1.cpp +++ b/tests/helics/sequencing_tests/Sequencing1.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/tests/helics/sequencing_tests/Sequencing2.cpp b/tests/helics/sequencing_tests/Sequencing2.cpp index b725ad915d..a7b6fd2b5c 100644 --- a/tests/helics/sequencing_tests/Sequencing2.cpp +++ b/tests/helics/sequencing_tests/Sequencing2.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/tests/helics/sequencing_tests/sequencing-tests.cpp b/tests/helics/sequencing_tests/sequencing-tests.cpp index 28d1a992dc..5f940784ed 100644 --- a/tests/helics/sequencing_tests/sequencing-tests.cpp +++ b/tests/helics/sequencing_tests/sequencing-tests.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/tests/helics/sequencing_tests/sequencingHelpers.cpp b/tests/helics/sequencing_tests/sequencingHelpers.cpp index 58b4cbf8b0..a0ee09f024 100644 --- a/tests/helics/sequencing_tests/sequencingHelpers.cpp +++ b/tests/helics/sequencing_tests/sequencingHelpers.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/tests/helics/sequencing_tests/sequencingHelpers.hpp b/tests/helics/sequencing_tests/sequencingHelpers.hpp index f7f5d7f6bc..6a55a81e33 100644 --- a/tests/helics/sequencing_tests/sequencingHelpers.hpp +++ b/tests/helics/sequencing_tests/sequencingHelpers.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/tests/helics/shared_library/CMakeLists.txt b/tests/helics/shared_library/CMakeLists.txt index 085da23813..4ee53763cf 100644 --- a/tests/helics/shared_library/CMakeLists.txt +++ b/tests/helics/shared_library/CMakeLists.txt @@ -1,5 +1,5 @@ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Copyright (c) 2017-2023, Battelle Memorial Institute; Lawrence Livermore +# Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore # National Security, LLC; Alliance for Sustainable Energy, LLC. # See the top-level NOTICE for additional details. # All rights reserved. diff --git a/tests/helics/shared_library/CallbackFederateTests.cpp b/tests/helics/shared_library/CallbackFederateTests.cpp index 90a3de559a..59a9ee3541 100644 --- a/tests/helics/shared_library/CallbackFederateTests.cpp +++ b/tests/helics/shared_library/CallbackFederateTests.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/tests/helics/shared_library/DataAPITests.cpp b/tests/helics/shared_library/DataAPITests.cpp index fd29d83f70..2b165430f2 100644 --- a/tests/helics/shared_library/DataAPITests.cpp +++ b/tests/helics/shared_library/DataAPITests.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -49,7 +49,7 @@ TEST(data, toFromInt) auto buff = helicsCreateDataBuffer(500); int64_t v1 = 35; - auto cnt = helicsIntegerToBytes(v1, buff); + auto cnt = helicsDataBufferFillFromInteger(buff, v1); EXPECT_EQ(helicsDataBufferType(buff), HELICS_DATA_TYPE_INT); EXPECT_GT(cnt, 0); int64_t v2 = helicsDataBufferToInteger(buff); @@ -62,7 +62,7 @@ TEST(data, toFromDouble) auto buff = helicsCreateDataBuffer(500); double v1 = 35.7; - auto cnt = helicsDoubleToBytes(v1, buff); + auto cnt = helicsDataBufferFillFromDouble(buff, v1); EXPECT_EQ(helicsDataBufferType(buff), HELICS_DATA_TYPE_DOUBLE); EXPECT_GT(cnt, 0); double v2 = helicsDataBufferToDouble(buff); @@ -75,7 +75,7 @@ TEST(data, toFromChar) auto buff = helicsCreateDataBuffer(500); char v1 = 'q'; - auto cnt = helicsCharToBytes(v1, buff); + auto cnt = helicsDataBufferFillFromChar(buff, v1); EXPECT_GT(cnt, 0); double v2 = helicsDataBufferToChar(buff); EXPECT_EQ(v1, v2); @@ -87,7 +87,7 @@ TEST(data, toFromTime) auto buff = helicsCreateDataBuffer(500); HelicsTime v1 = 12.77; - auto cnt = helicsTimeToBytes(v1, buff); + auto cnt = helicsDataBufferFillFromTime(buff, v1); EXPECT_GT(cnt, 0); HelicsTime v2 = helicsDataBufferToTime(buff); EXPECT_EQ(v1, v2); @@ -99,7 +99,7 @@ TEST(data, toFromString) auto buff = helicsCreateDataBuffer(500); std::string v1 = "this is an interesting string"; - auto cnt = helicsStringToBytes(v1.c_str(), buff); + auto cnt = helicsDataBufferFillFromString(buff, v1.c_str()); EXPECT_GT(cnt, 0); std::string v2; v2.resize(100); @@ -126,7 +126,7 @@ TEST(data, toFromRawString) std::string v1 = "this is an interesting"; v1.push_back('\0'); v1.append(" string "); - auto cnt = helicsRawStringToBytes(v1.c_str(), static_cast(v1.size()), buff); + auto cnt = helicsDataBufferFillFromRawString(buff, v1.c_str(), static_cast(v1.size())); EXPECT_GT(cnt, 0); std::string v2; v2.resize(100); @@ -144,7 +144,7 @@ TEST(data, toFromVector) auto buff = helicsCreateDataBuffer(500); std::vector v1{34.7, -99.99999, 0, 43.7e231, std::nan("0")}; - auto cnt = helicsVectorToBytes(v1.data(), static_cast(v1.size()), buff); + auto cnt = helicsDataBufferFillFromVector(buff, v1.data(), static_cast(v1.size())); EXPECT_GT(cnt, 0); std::vector v2; v2.resize(5); @@ -177,9 +177,9 @@ TEST(data, toFromComplexVector) cv{0, 0}, cv{43.7e231, -19.3e-88}, cv{std::nan("0"), 0}}; - auto cnt = helicsComplexVectorToBytes(reinterpret_cast(v1.data()), - static_cast(v1.size()), - buff); + auto cnt = helicsDataBufferFillFromComplexVector(buff, + reinterpret_cast(v1.data()), + static_cast(v1.size())); EXPECT_GT(cnt, 0); std::vector v2; v2.resize(10); @@ -209,7 +209,7 @@ TEST(data, toFromNamedPoint) { auto buff = helicsCreateDataBuffer(500); - auto cnt = helicsNamedPointToBytes("string_thing", 45.7, buff); + auto cnt = helicsDataBufferFillFromNamedPoint(buff, "string_thing", 45.7); EXPECT_GT(cnt, 0); std::string v2name; double v2val; @@ -228,7 +228,7 @@ TEST(data, converter) auto buff = helicsCreateDataBuffer(500); double v1 = 35.7; - auto cnt = helicsDoubleToBytes(v1, buff); + auto cnt = helicsDataBufferFillFromDouble(buff, v1); EXPECT_EQ(helicsDataBufferType(buff), HELICS_DATA_TYPE_DOUBLE); EXPECT_GT(cnt, 0); bool res = helicsDataBufferConvertToType(buff, HELICS_DATA_TYPE_INT) != HELICS_FALSE; @@ -245,7 +245,7 @@ TEST(data, clone) auto buff = helicsCreateDataBuffer(500); double v1 = 35.7; - auto cnt = helicsDoubleToBytes(v1, buff); + auto cnt = helicsDataBufferFillFromDouble(buff, v1); EXPECT_EQ(helicsDataBufferType(buff), HELICS_DATA_TYPE_DOUBLE); EXPECT_GT(cnt, 0); auto newbuff = helicsDataBufferClone(buff); diff --git a/tests/helics/shared_library/FilterTests.cpp b/tests/helics/shared_library/FilterTests.cpp index e56ca2d508..e6b91e2782 100644 --- a/tests/helics/shared_library/FilterTests.cpp +++ b/tests/helics/shared_library/FilterTests.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/tests/helics/shared_library/MultiInputTests.cpp b/tests/helics/shared_library/MultiInputTests.cpp index 32b88ccbe5..e7aa1f01bf 100644 --- a/tests/helics/shared_library/MultiInputTests.cpp +++ b/tests/helics/shared_library/MultiInputTests.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/tests/helics/shared_library/PropertyIndexTests.cpp b/tests/helics/shared_library/PropertyIndexTests.cpp index 7283344ca0..0813f164ab 100644 --- a/tests/helics/shared_library/PropertyIndexTests.cpp +++ b/tests/helics/shared_library/PropertyIndexTests.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/tests/helics/shared_library/QueryTests.cpp b/tests/helics/shared_library/QueryTests.cpp index f59ef2d3aa..1f87e664f7 100644 --- a/tests/helics/shared_library/QueryTests.cpp +++ b/tests/helics/shared_library/QueryTests.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -10,11 +10,11 @@ SPDX-License-Identifier: BSD-3-Clause #include -class query_tests: public ::testing::TestWithParam, public FederateTestFixture {}; +class QueryTests: public ::testing::TestWithParam, public FederateTestFixture {}; -class query_test_single: public ::testing::Test, public FederateTestFixture {}; +class QueryTestSingle: public ::testing::Test, public FederateTestFixture {}; /** test simple creation and destruction*/ -TEST_P(query_tests, publication_queries) +TEST_P(QueryTests, publication_queries) { SetupTest(helicsCreateValueFederate, GetParam(), 2); auto vFed1 = GetFederateAt(0); @@ -31,36 +31,36 @@ TEST_P(query_tests, publication_queries) auto core = helicsFederateGetCore(vFed1, &err); - auto q1 = helicsCreateQuery("fed0", "publications"); + auto query1 = helicsCreateQuery("fed0", "publications"); - CE(std::string res(helicsQueryCoreExecute(q1, core, &err))); + CE(std::string res(helicsQueryCoreExecute(query1, core, &err))); EXPECT_EQ(res, "[\"pub1\",\"fed0/pub2\"]"); - helicsQueryFree(q1); - q1 = helicsCreateQuery(nullptr, "publications"); - CE(helicsQuerySetOrdering(q1, 1, &err)); - CE(std::string res2 = helicsQueryExecute(q1, vFed2, &err)); + helicsQueryFree(query1); + query1 = helicsCreateQuery(nullptr, "publications"); + CE(helicsQuerySetOrdering(query1, 1, &err)); + CE(std::string res2 = helicsQueryExecute(query1, vFed2, &err)); EXPECT_EQ(res2, "[\"fed1/pub3\"]"); - helicsQueryFree(q1); + helicsQueryFree(query1); - q1 = helicsCreateQuery("fed1", "isinit"); + query1 = helicsCreateQuery("fed1", "isinit"); - CE(res = helicsQueryExecute(q1, vFed1, &err)); + CE(res = helicsQueryExecute(query1, vFed1, &err)); EXPECT_EQ(res, "true"); - helicsQueryFree(q1); + helicsQueryFree(query1); - q1 = helicsCreateQuery("fed1", "publications"); - CE(res = helicsQueryExecute(q1, vFed1, &err)); + query1 = helicsCreateQuery("fed1", "publications"); + CE(res = helicsQueryExecute(query1, vFed1, &err)); EXPECT_EQ(res, "[\"fed1/pub3\"]"); - helicsQueryFree(q1); + helicsQueryFree(query1); helicsCoreFree(core); CE(helicsFederateFinalizeAsync(vFed1, &err)); CE(helicsFederateFinalize(vFed2, &err)); CE(helicsFederateFinalizeComplete(vFed1, &err)); } -TEST_P(query_tests, broker_queries) +TEST_P(QueryTests, broker_queries) { SetupTest(helicsCreateValueFederate, GetParam(), 2); auto vFed1 = GetFederateAt(0); @@ -68,8 +68,8 @@ TEST_P(query_tests, broker_queries) CE(auto core = helicsFederateGetCore(vFed1, &err)); - auto q1 = helicsCreateQuery("root", "federates"); - std::string res = helicsQueryCoreExecute(q1, core, nullptr); + auto query1 = helicsCreateQuery("root", "federates"); + std::string res = helicsQueryCoreExecute(query1, core, nullptr); std::string str("[\""); str.append(helicsFederateGetName(vFed1)); str.append("\",\""); @@ -78,16 +78,16 @@ TEST_P(query_tests, broker_queries) EXPECT_EQ(res, str); - CE(std::string res2 = helicsQueryExecute(q1, vFed1, &err)); + CE(std::string res2 = helicsQueryExecute(query1, vFed1, &err)); EXPECT_EQ(res2, str); CE(helicsFederateEnterInitializingModeAsync(vFed1, &err)); CE(helicsFederateEnterInitializingMode(vFed2, &err)); CE(helicsFederateEnterInitializingModeComplete(vFed1, &err)); // expected to be false since it isn't associated with a asynchronous query - auto qcomplete = helicsQueryIsCompleted(q1); + auto qcomplete = helicsQueryIsCompleted(query1); EXPECT_EQ(qcomplete, HELICS_FALSE); - helicsQueryFree(q1); + helicsQueryFree(query1); helicsCoreFree(core); CE(helicsFederateFinalizeAsync(vFed1, &err)); CE(helicsFederateFinalize(vFed2, &err)); @@ -96,35 +96,35 @@ TEST_P(query_tests, broker_queries) static void queryTest(const char* query, int stringSize, HelicsQueryBuffer buffer, void* /*unused*/) { - std::string q(query, stringSize); - if (q == "abc") { - static const char* aret = "AAAA"; + std::string_view qstring(query, stringSize); + if (qstring == "abc") { + static constexpr const char* aret = "AAAA"; helicsQueryBufferFill(buffer, aret, 4, nullptr); } else { - static const char* bret = "BBBB"; + static constexpr const char* bret = "BBBB"; helicsQueryBufferFill(buffer, bret, 4, nullptr); } } -TEST_F(query_test_single, queries_callback_test) +TEST_F(QueryTestSingle, queries_callback_test) { SetupTest(helicsCreateValueFederate, "test", 1); auto vFed1 = GetFederateAt(0); helicsFederateSetQueryCallback(vFed1, queryTest, nullptr, nullptr); - auto q1 = helicsCreateQuery(helicsFederateGetName(vFed1), "abc"); + auto query1 = helicsCreateQuery(helicsFederateGetName(vFed1), "abc"); - auto res = helicsQueryExecute(q1, vFed1, nullptr); + auto res = helicsQueryExecute(query1, vFed1, nullptr); EXPECT_STREQ(res, "AAAA"); - helicsQueryFree(q1); - q1 = helicsCreateQuery(helicsFederateGetName(vFed1), "bca"); - res = helicsQueryExecute(q1, vFed1, nullptr); + helicsQueryFree(query1); + query1 = helicsCreateQuery(helicsFederateGetName(vFed1), "bca"); + res = helicsQueryExecute(query1, vFed1, nullptr); EXPECT_STREQ(res, "BBBB"); - helicsQueryFree(q1); + helicsQueryFree(query1); helicsFederateEnterExecutingMode(vFed1, nullptr); helicsFederateFinalize(vFed1, nullptr); } -INSTANTIATE_TEST_SUITE_P(query_tests, query_tests, ::testing::ValuesIn(CoreTypes)); +INSTANTIATE_TEST_SUITE_P(QueryTests, QueryTests, ::testing::ValuesIn(CoreTypes)); diff --git a/tests/helics/shared_library/QueryTests_cpp.cpp b/tests/helics/shared_library/QueryTests_cpp.cpp index d91d3321b9..054561ff7c 100644 --- a/tests/helics/shared_library/QueryTests_cpp.cpp +++ b/tests/helics/shared_library/QueryTests_cpp.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -12,9 +12,9 @@ SPDX-License-Identifier: BSD-3-Clause #include -struct query_tests: public FederateTestFixture_cpp, public ::testing::Test {}; +struct QueryTests: public FederateTestFixture_cpp, public ::testing::Test {}; -TEST_F(query_tests, exists) +TEST_F(QueryTests, exists) { SetupTest("test_2", 2, 1.0); auto mFed1 = GetFederateAs(0); @@ -87,7 +87,7 @@ TEST_F(query_tests, exists) core1.waitForDisconnect(); } -TEST_F(query_tests, callback) +TEST_F(QueryTests, callback) { SetupTest("test_2", 2, 1.0); auto mFed1 = GetFederateAs(0); diff --git a/tests/helics/shared_library/SystemTests.cpp b/tests/helics/shared_library/SystemTests.cpp index 1393a2ec44..d5039f9a1d 100644 --- a/tests/helics/shared_library/SystemTests.cpp +++ b/tests/helics/shared_library/SystemTests.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -41,7 +41,7 @@ TEST(other_tests, broker_global_value) TEST(other_tests, broker_global_value_errors_nosan_ci_skip) { auto err = helicsErrorInitialize(); - auto brk = helicsCreateBroker("test", "gbroker", "--root", &err); + auto brk = helicsCreateBroker("test", "gbroker2", "--root", &err); auto q = helicsCreateQuery("global_value", "testglobal"); auto res = helicsQueryBrokerExecute(nullptr, brk, &err); EXPECT_NE(err.error_code, 0); @@ -313,13 +313,13 @@ TEST(other_tests, federate_add_dependency) TEST(other_tests, core_creation) { auto err = helicsErrorInitialize(); - auto brk = helicsCreateBroker("test", "gbrokerc", "--root", &err); + auto brk = helicsCreateBroker("test", "gbrokercn", "--root", &err); const char* argv[4]; argv[0] = ""; argv[1] = "--name=gcore"; argv[2] = "--timeout=2000"; - argv[3] = "--broker=gbrokerc"; + argv[3] = "--broker=gbrokercn"; auto cr = helicsCreateCoreFromArgs("test", nullptr, 4, argv, &err); EXPECT_EQ(err.error_code, 0); @@ -340,7 +340,7 @@ TEST(other_tests, core_creation_error_nosan) argv[0] = ""; argv[1] = "--name=gcore2"; argv[2] = "--log_level=what_logs?"; - argv[3] = "--broker=gbrokerc"; + argv[3] = "--broker=gbrokercm2"; auto cr2 = helicsCreateCoreFromArgs("test", nullptr, 4, argv, &err); EXPECT_NE(err.error_code, 0); @@ -355,13 +355,13 @@ TEST(other_tests, broker_creation) const char* argv[4]; argv[0] = ""; - argv[1] = "--name=gbrokerc"; + argv[1] = "--name=gbrokercm3"; argv[2] = "--timeout=2000"; argv[3] = "--root"; auto brk = helicsCreateBrokerFromArgs("test", nullptr, 4, argv, &err); EXPECT_EQ(err.error_code, 0); - EXPECT_STREQ(helicsBrokerGetIdentifier(brk), "gbrokerc"); + EXPECT_STREQ(helicsBrokerGetIdentifier(brk), "gbrokercm3"); helicsBrokerDisconnect(brk, &err); } @@ -373,7 +373,7 @@ TEST(other_tests, broker_creation_nosan) const char* argv[4]; argv[0] = ""; - argv[1] = "--name=gbrokerc2"; + argv[1] = "--name=gbrokerAC1"; argv[2] = "--log_level=what_logs?"; argv[3] = "--root"; @@ -388,7 +388,9 @@ TEST(federate_tests, federateGeneratedLocalError_nosan) auto fi = helicsCreateFederateInfo(); helicsFederateInfoSetCoreType(fi, HELICS_CORE_TYPE_TEST, nullptr); helicsFederateInfoSetCoreName(fi, "core_full_le", nullptr); - helicsFederateInfoSetCoreInitString(fi, "-f 1 --autobroker --error_timeout=0", nullptr); + helicsFederateInfoSetCoreInitString(fi, + "-f 1 --autobroker --broker=flebroker1 --error_timeout=0", + nullptr); auto fed1 = helicsCreateValueFederate("fed1", fi, nullptr); helicsFederateInfoFree(fi); @@ -412,7 +414,9 @@ TEST(federate, federateGeneratedGlobalError_nosan) auto fi = helicsCreateFederateInfo(); helicsFederateInfoSetCoreType(fi, HELICS_CORE_TYPE_TEST, nullptr); helicsFederateInfoSetCoreName(fi, "core_full_ge", nullptr); - helicsFederateInfoSetCoreInitString(fi, "-f 1 --autobroker --error_timeout=0", nullptr); + helicsFederateInfoSetCoreInitString(fi, + "-f 1 --autobroker --broker=fgebroker2 --error_timeout=0", + nullptr); auto fed1 = helicsCreateValueFederate("fed1", fi, nullptr); helicsFederateInfoFree(fi); @@ -556,7 +560,9 @@ TEST(federate, federateNoProtection) auto fi = helicsCreateFederateInfo(); helicsFederateInfoSetCoreType(fi, HELICS_CORE_TYPE_TEST, nullptr); helicsFederateInfoSetCoreName(fi, "core_protect", nullptr); - helicsFederateInfoSetCoreInitString(fi, "-f 1 --autobroker --error_timeout=0", nullptr); + helicsFederateInfoSetCoreInitString(fi, + "-f 1 --autobroker --broker=npbroker1 --error_timeout=0", + nullptr); auto fed1 = helicsCreateValueFederate("fed1", fi, nullptr); @@ -580,7 +586,9 @@ TEST(federate, federateProtection) auto fi = helicsCreateFederateInfo(); helicsFederateInfoSetCoreType(fi, HELICS_CORE_TYPE_TEST, nullptr); helicsFederateInfoSetCoreName(fi, "core_protect", nullptr); - helicsFederateInfoSetCoreInitString(fi, "-f 1 --autobroker --error_timeout=0", nullptr); + helicsFederateInfoSetCoreInitString(fi, + "-f 1 --autobroker --broker=npbroker2 --error_timeout=0", + nullptr); auto fed1 = helicsCreateValueFederate("fed1", fi, nullptr); helicsFederateInfoFree(fi); diff --git a/tests/helics/shared_library/TimingTests.cpp b/tests/helics/shared_library/TimingTests.cpp index be4ce46f2e..da75b9ffa9 100644 --- a/tests/helics/shared_library/TimingTests.cpp +++ b/tests/helics/shared_library/TimingTests.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/tests/helics/shared_library/TranslatorTests.cpp b/tests/helics/shared_library/TranslatorTests.cpp index 5df6db44bd..eb5dc31245 100644 --- a/tests/helics/shared_library/TranslatorTests.cpp +++ b/tests/helics/shared_library/TranslatorTests.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -335,7 +335,7 @@ void toVC(HelicsMessage message, HelicsDataBuffer value, void* /*userData*/) const auto* str = helicsMessageGetString(message); char* ptr{nullptr}; double v = strtod(str, &ptr) + 9.0; - helicsDoubleToBytes(v, value); + helicsDataBufferFillFromDouble(value, v); } TEST_F(translator, custom_translator) diff --git a/tests/helics/shared_library/badInputTests.cpp b/tests/helics/shared_library/badInputTests.cpp index 95c5a09b43..701ea1b819 100644 --- a/tests/helics/shared_library/badInputTests.cpp +++ b/tests/helics/shared_library/badInputTests.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/tests/helics/shared_library/comboConfigTests.cpp b/tests/helics/shared_library/comboConfigTests.cpp index f043cec6b6..c6848668e7 100644 --- a/tests/helics/shared_library/comboConfigTests.cpp +++ b/tests/helics/shared_library/comboConfigTests.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/tests/helics/shared_library/commandInterfaceTests.cpp b/tests/helics/shared_library/commandInterfaceTests.cpp index 60830a03be..238b6cc0a5 100644 --- a/tests/helics/shared_library/commandInterfaceTests.cpp +++ b/tests/helics/shared_library/commandInterfaceTests.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/tests/helics/shared_library/cppshared-library-tests.cpp b/tests/helics/shared_library/cppshared-library-tests.cpp index 559f701029..b1ee56fc72 100644 --- a/tests/helics/shared_library/cppshared-library-tests.cpp +++ b/tests/helics/shared_library/cppshared-library-tests.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/tests/helics/shared_library/cpptestFixtures.cpp b/tests/helics/shared_library/cpptestFixtures.cpp index 497964bb40..00465b2413 100644 --- a/tests/helics/shared_library/cpptestFixtures.cpp +++ b/tests/helics/shared_library/cpptestFixtures.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, Battelle Memorial Institute +Copyright (c) 2017-2024, Battelle Memorial Institute All rights reserved. This software was co-developed by Pacific Northwest National Laboratory, operated by the Battelle diff --git a/tests/helics/shared_library/cpptestFixtures.hpp b/tests/helics/shared_library/cpptestFixtures.hpp index f3add41eeb..8d18fd8446 100644 --- a/tests/helics/shared_library/cpptestFixtures.hpp +++ b/tests/helics/shared_library/cpptestFixtures.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/tests/helics/shared_library/ctestFixtures.cpp b/tests/helics/shared_library/ctestFixtures.cpp index fd427bed2a..8f1defd1bf 100644 --- a/tests/helics/shared_library/ctestFixtures.cpp +++ b/tests/helics/shared_library/ctestFixtures.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/tests/helics/shared_library/ctestFixtures.hpp b/tests/helics/shared_library/ctestFixtures.hpp index 4c06daf8ef..6ecc6bbd3e 100644 --- a/tests/helics/shared_library/ctestFixtures.hpp +++ b/tests/helics/shared_library/ctestFixtures.hpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/tests/helics/shared_library/evilInputTests.cpp b/tests/helics/shared_library/evilInputTests.cpp index 324689c066..825d975f93 100644 --- a/tests/helics/shared_library/evilInputTests.cpp +++ b/tests/helics/shared_library/evilInputTests.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/tests/helics/shared_library/iterationTests.cpp b/tests/helics/shared_library/iterationTests.cpp index ac1b0b1362..dac709b1fe 100644 --- a/tests/helics/shared_library/iterationTests.cpp +++ b/tests/helics/shared_library/iterationTests.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/tests/helics/shared_library/loggingTests.cpp b/tests/helics/shared_library/loggingTests.cpp index c7709026c4..58f90aadd2 100644 --- a/tests/helics/shared_library/loggingTests.cpp +++ b/tests/helics/shared_library/loggingTests.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -18,24 +18,28 @@ SPDX-License-Identifier: BSD-3-Clause #include "helics/helics.h" using logblocktype = gmlc::libguarded::guarded>>; + TEST(logging_tests, check_log_message) { - auto fi = helicsCreateFederateInfo(); + helicsCleanupLibrary(); + std::cout << "log test starting\n"; + auto fedInfo = helicsCreateFederateInfo(); auto err = helicsErrorInitialize(); - helicsFederateInfoSetCoreType(fi, HELICS_CORE_TYPE_TEST, &err); - helicsFederateInfoSetCoreInitString(fi, "--autobroker", &err); - helicsFederateInfoSetIntegerProperty(fi, + helicsFederateInfoSetCoreType(fedInfo, HELICS_CORE_TYPE_TEST, &err); + helicsFederateInfoSetCoreName(fedInfo, "clogcore", &err); + helicsFederateInfoSetCoreInitString(fedInfo, "--autobroker --broker=clogbroker", &err); + helicsFederateInfoSetIntegerProperty(fedInfo, HELICS_PROPERTY_INT_LOG_LEVEL, HELICS_LOG_LEVEL_TIMING, &err); - auto fed = helicsCreateValueFederate("test1", fi, &err); - + auto fed = helicsCreateValueFederate("test1", fedInfo, &err); + std::cout << "log test created\n"; logblocktype mlog; auto logg = [](int level, const char* /*unused*/, const char* message, void* udata) { - auto* mp = reinterpret_cast(udata); - mp->lock()->emplace_back(level, message); + auto* messageLock = reinterpret_cast(udata); + messageLock->lock()->emplace_back(level, message); }; helicsFederateSetLoggingCallback(fed, logg, &mlog, &err); @@ -48,42 +52,45 @@ TEST(logging_tests, check_log_message) helicsFederateRequestNextStep(fed, &err); helicsFederateFinalize(fed, &err); std::this_thread::sleep_for(std::chrono::milliseconds(200)); + std::cout << "finalized federate\n"; EXPECT_EQ(err.error_code, 0); auto llock = mlog.lock(); bool found = false; - for (auto& m : llock) { - if (m.second.find("MEXAGE") != std::string::npos) { + for (auto& message : *llock) { + if (message.second.find("MEXAGE") != std::string::npos) { found = true; } } EXPECT_TRUE(found); if (!found) { - for (auto& m : llock) { - std::cout << "message (" << m.first << ") ::" << m.second << std::endl; + for (auto& message : *llock) { + std::cout << "message (" << message.first << ") ::" << message.second << std::endl; } } + llock.unlock(); helicsFederateFree(fed); - helicsFederateInfoFree(fi); + helicsFederateInfoFree(fedInfo); } TEST(logging_tests, check_log_message_levels) { - auto fi = helicsCreateFederateInfo(); + auto fedInfo = helicsCreateFederateInfo(); auto err = helicsErrorInitialize(); - helicsFederateInfoSetCoreType(fi, HELICS_CORE_TYPE_TEST, &err); - helicsFederateInfoSetCoreInitString(fi, "--autobroker", &err); - helicsFederateInfoSetIntegerProperty(fi, + helicsFederateInfoSetCoreType(fedInfo, HELICS_CORE_TYPE_TEST, &err); + helicsFederateInfoSetCoreInitString(fedInfo, "--autobroker --broker=clogbrokerlevel", &err); + helicsFederateInfoSetCoreName(fedInfo, "clogcorelevels", &err); + helicsFederateInfoSetIntegerProperty(fedInfo, HELICS_PROPERTY_INT_LOG_LEVEL, HELICS_LOG_LEVEL_TIMING, &err); - auto fed = helicsCreateValueFederate("test1", fi, &err); + auto fed = helicsCreateValueFederate("test1", fedInfo, &err); logblocktype mlog; auto logg = [](int level, const char* /*unused*/, const char* message, void* udata) { - auto* mp = reinterpret_cast(udata); - mp->lock()->emplace_back(level, message); + auto* messageLock = reinterpret_cast(udata); + messageLock->lock()->emplace_back(level, message); }; helicsFederateSetLoggingCallback(fed, nullptr, &mlog, &err); @@ -101,39 +108,40 @@ TEST(logging_tests, check_log_message_levels) auto llock = mlog.lock(); bool found_low = false; bool found_high = false; - for (auto& m : llock) { - if (m.second.find("MEXAGE1") != std::string::npos) { + for (auto& message : *llock) { + if (message.second.find("MEXAGE1") != std::string::npos) { found_low = true; } - if (m.second.find("MEXAGE2") != std::string::npos) { + if (message.second.find("MEXAGE2") != std::string::npos) { found_high = true; } } EXPECT_TRUE(found_low); EXPECT_FALSE(found_high); - + llock.unlock(); helicsFederateFree(fed); - helicsFederateInfoFree(fi); + helicsFederateInfoFree(fedInfo); } TEST(logging_tests, check_log_message_levels_high) { - auto fi = helicsCreateFederateInfo(); + auto fedInfo = helicsCreateFederateInfo(); auto err = helicsErrorInitialize(); - helicsFederateInfoSetCoreType(fi, HELICS_CORE_TYPE_TEST, &err); - helicsFederateInfoSetCoreInitString(fi, "--autobroker", &err); - helicsFederateInfoSetIntegerProperty(fi, + helicsFederateInfoSetCoreType(fedInfo, HELICS_CORE_TYPE_TEST, &err); + helicsFederateInfoSetCoreInitString(fedInfo, "--autobroker --broker=clogbrokerhigh", &err); + helicsFederateInfoSetCoreName(fedInfo, "clogcorehigh", &err); + helicsFederateInfoSetIntegerProperty(fedInfo, HELICS_PROPERTY_INT_LOG_LEVEL, HELICS_LOG_LEVEL_TRACE + 6, &err); - auto fed = helicsCreateValueFederate("test1", fi, &err); + auto fed = helicsCreateValueFederate("test1", fedInfo, &err); logblocktype mlog; auto logg = [](int level, const char* /*unused*/, const char* message, void* udata) { - auto* mp = reinterpret_cast(udata); - mp->lock()->emplace_back(level, message); + auto* messageLock = reinterpret_cast(udata); + messageLock->lock()->emplace_back(level, message); }; helicsFederateSetLoggingCallback(fed, logg, &mlog, &err); @@ -146,34 +154,37 @@ TEST(logging_tests, check_log_message_levels_high) helicsFederateRequestNextStep(fed, &err); helicsFederateFinalize(fed, &err); EXPECT_EQ(err.error_code, 0); - - auto llock = mlog.lock(); bool found_low = false; bool found_high = false; - for (auto& m : llock) { - if (m.second.find("MEXAGE1") != std::string::npos) { + auto llock = mlog.lock(); + for (auto& message : *llock) { + if (message.second.find("MEXAGE1") != std::string::npos) { found_low = true; } - if (m.second.find("MEXAGE2") != std::string::npos) { + if (message.second.find("MEXAGE2") != std::string::npos) { found_high = true; } } + llock.unlock(); EXPECT_TRUE(found_low && found_high); helicsFederateFree(fed); - helicsFederateInfoFree(fi); + helicsFederateInfoFree(fedInfo); } TEST(logging_tests, core_logging) { - auto core = helicsCreateCore("inproc", "ctype", "--autobroker --log_level=trace", nullptr); + auto core = helicsCreateCore("inproc", + "ctype", + "--autobroker --log_level=trace --broker=ncorelogging", + nullptr); helicsCoreSetLoggingCallback(core, nullptr, nullptr, nullptr); logblocktype mlog; auto logg = [](int level, const char* /*unused*/, const char* message, void* udata) { - auto* mp = reinterpret_cast(udata); - mp->lock()->emplace_back(level, message); + auto* messageLock = reinterpret_cast(udata); + messageLock->lock()->emplace_back(level, message); }; auto err = helicsErrorInitialize(); helicsCoreSetLoggingCallback(core, logg, &mlog, &err); @@ -192,8 +203,8 @@ TEST(logging_tests, broker_logging) logblocktype mlog; auto logg = [](int level, const char* /*unused*/, const char* message, void* udata) { - auto* mp = reinterpret_cast(udata); - mp->lock()->emplace_back(level, message); + auto* messageLock = reinterpret_cast(udata); + messageLock->lock()->emplace_back(level, message); }; auto err = helicsErrorInitialize(); helicsBrokerSetLoggingCallback(broker, logg, &mlog, &err); @@ -226,7 +237,10 @@ TEST(logging_tests, core_logging_file) if (std::filesystem::exists(lfile)) { std::filesystem::remove(lfile); } - auto core = helicsCreateCore("inproc", "clog", "--autobroker --log_level=trace", nullptr); + auto core = helicsCreateCore("inproc", + "clog", + "--autobroker --log_level=trace --broker=clogfile", + nullptr); auto err = helicsErrorInitialize(); helicsCoreSetLogFile(core, lfile.c_str(), &err); @@ -242,12 +256,15 @@ TEST(logging_tests, fed_logging_file) if (std::filesystem::exists(lfile)) { std::filesystem::remove(lfile); } - auto core = helicsCreateCore("inproc", "clogf", "--autobroker --log_level=trace", nullptr); + auto core = helicsCreateCore("inproc", + "clogf", + "--autobroker --log_level=trace --broker=clogfbroker", + nullptr); auto err = helicsErrorInitialize(); - auto fi = helicsCreateFederateInfo(); - helicsFederateInfoSetCoreName(fi, "clogf", nullptr); - auto fed = helicsCreateValueFederate("f1", fi, nullptr); + auto fedInfo = helicsCreateFederateInfo(); + helicsFederateInfoSetCoreName(fedInfo, "clogf", nullptr); + auto fed = helicsCreateValueFederate("f1", fedInfo, nullptr); helicsFederateSetLogFile(fed, lfile.c_str(), nullptr); helicsCoreSetLogFile(core, lfile.c_str(), &err); @@ -255,7 +272,7 @@ TEST(logging_tests, fed_logging_file) helicsFederateFinalize(fed, &err); helicsFederateSetLogFile(fed, "emptyfile.txt", nullptr); - helicsFederateInfoFree(fi); + helicsFederateInfoFree(fedInfo); helicsCloseLibrary(); ASSERT_TRUE(std::filesystem::exists(lfile)); std::filesystem::remove(lfile); diff --git a/tests/helics/shared_library/miscApiTests.cpp b/tests/helics/shared_library/miscApiTests.cpp index fe15ce5dab..1e13a7bdee 100644 --- a/tests/helics/shared_library/miscApiTests.cpp +++ b/tests/helics/shared_library/miscApiTests.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/tests/helics/shared_library/shared-library-tests.cpp b/tests/helics/shared_library/shared-library-tests.cpp index 559f701029..b1ee56fc72 100644 --- a/tests/helics/shared_library/shared-library-tests.cpp +++ b/tests/helics/shared_library/shared-library-tests.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/tests/helics/shared_library/test-combo-federate_cpp.cpp b/tests/helics/shared_library/test-combo-federate_cpp.cpp index c4f329dcde..1fe66be4c4 100644 --- a/tests/helics/shared_library/test-combo-federate_cpp.cpp +++ b/tests/helics/shared_library/test-combo-federate_cpp.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/tests/helics/shared_library/test-message-federate.cpp b/tests/helics/shared_library/test-message-federate.cpp index a708af42a8..1e326c7438 100644 --- a/tests/helics/shared_library/test-message-federate.cpp +++ b/tests/helics/shared_library/test-message-federate.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -164,7 +164,7 @@ TEST_P(mfed_simple_type_tests, send_receive_mobj) EXPECT_TRUE(mFed1State == HelicsFederateState::HELICS_STATE_FINALIZE); } -TEST_F(mfed_tests, message_object_tests) +TEST_F(mfed_tests, message_object) { SetupTest(helicsCreateMessageFederate, "test", 1); auto mFed1 = GetFederateAt(0); @@ -368,6 +368,7 @@ TEST(message_object, test1_nosan) auto brk = helicsCreateBroker("test", "brk1", "", nullptr); auto fi = helicsCreateFederateInfo(); + helicsFederateInfoSetBroker(fi, "brk1", nullptr); helicsFederateInfoSetCoreType(fi, HELICS_CORE_TYPE_TEST, nullptr); auto fed = helicsCreateMessageFederate("fed1", fi, nullptr); @@ -454,13 +455,16 @@ TEST(message_object, test1_nosan) TEST(message_object, copy) { - auto brk = helicsCreateBroker("test", "brk1", "", nullptr); + helicsCleanupLibrary(); + auto brk = helicsCreateBroker("test", "brk_mcpy", "", nullptr); - auto fi = helicsCreateFederateInfo(); - helicsFederateInfoSetCoreType(fi, HELICS_CORE_TYPE_TEST, nullptr); - auto fed = helicsCreateMessageFederate("fed1", fi, nullptr); + auto fedInfo = helicsCreateFederateInfo(); + helicsFederateInfoSetCoreType(fedInfo, HELICS_CORE_TYPE_TEST, nullptr); + helicsFederateInfoSetBroker(fedInfo, "brk_mcpy", nullptr); + helicsFederateInfoLoadFromString(fedInfo, "--force_new_core", nullptr); + auto fed = helicsCreateMessageFederate("fed1", fedInfo, nullptr); - helicsFederateInfoFree(fi); + helicsFederateInfoFree(fedInfo); auto m1 = helicsFederateCreateMessage(fed, nullptr); EXPECT_NE(m1, nullptr); @@ -518,3 +522,46 @@ TEST(message_object, copy) helicsFederateFinalize(fed, nullptr); helicsBrokerDisconnect(brk, nullptr); } + +TEST(message_object, dataBuffer) +{ + auto brk = helicsCreateBroker("test", "brk_db", "", nullptr); + + auto fedInfo = helicsCreateFederateInfo(); + helicsFederateInfoSetCoreType(fedInfo, HELICS_CORE_TYPE_TEST, nullptr); + + helicsFederateInfoSetBroker(fedInfo, "brk_db", nullptr); + helicsFederateInfoLoadFromString(fedInfo, "--force_new_core", nullptr); + + auto fed = helicsCreateMessageFederate("fed1", fedInfo, nullptr); + helicsFederateInfoFree(fedInfo); + auto m1 = helicsFederateCreateMessage(fed, nullptr); + EXPECT_NE(m1, nullptr); + + auto m2 = helicsFederateCreateMessage(fed, nullptr); + EXPECT_NE(m2, nullptr); + + helicsMessageSetString(m1, "raw data", nullptr); + + auto err = helicsErrorInitialize(); + + EXPECT_EQ(helicsDataBufferIsValid(m1), HELICS_TRUE); + + char data[20]; + int actSize{10}; + + EXPECT_EQ(helicsDataBufferSize(m1), 8); + helicsDataBufferToRawString(m1, data, 20, &actSize); + EXPECT_EQ(actSize, 8); + EXPECT_EQ(std::string(data, data + actSize), "raw data"); + + helicsMessageClear(m2, &err); + // test the connection between the buffer and message + EXPECT_EQ(helicsDataBufferSize(m2), 0); + EXPECT_EQ(helicsMessageIsValid(m2), HELICS_FALSE); + EXPECT_EQ(helicsDataBufferIsValid(m2), HELICS_TRUE); + + helicsFederateEnterExecutingMode(fed, nullptr); + helicsFederateFinalize(fed, nullptr); + helicsBrokerDisconnect(brk, nullptr); +} diff --git a/tests/helics/shared_library/test-message-federate_cpp.cpp b/tests/helics/shared_library/test-message-federate_cpp.cpp index 70ced2dc1b..79e5bc693d 100644 --- a/tests/helics/shared_library/test-message-federate_cpp.cpp +++ b/tests/helics/shared_library/test-message-federate_cpp.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -332,3 +332,84 @@ TEST_F(mfed_tests, message_create_from_ept_after) auto mFed1State = mFed1->getCurrentMode(); EXPECT_TRUE(mFed1State == HelicsFederateState::HELICS_STATE_FINALIZE); } + +TEST_F(mfed_tests, dataBuffer) +{ + SetupTest("test", 1, 1.0); + auto mFed1 = GetFederateAs(0); + + auto m1 = helicscpp::Message(*mFed1); + + auto m2 = helicscpp::Message(*mFed1); + m1.data("raw data"); + + EXPECT_EQ(m1.size(), 8); + EXPECT_TRUE(m1.isValid()); + EXPECT_STREQ(m1.c_str(), "raw data"); + + // test the connection between the buffer and message + EXPECT_EQ(m2.size(), 0); + EXPECT_FALSE(m2.isValid()); + auto buffer = m2.dataBuffer(); + + EXPECT_TRUE(buffer.isValid()); + + mFed1->enterExecutingMode(); + mFed1->finalize(); +} + +TEST(dataBuffer, buffer) +{ + helicscpp::DataBuffer buf1(345); + EXPECT_GE(buf1.capacity(), 345); + EXPECT_TRUE(buf1.reserve(1024)); + EXPECT_GE(buf1.capacity(), 1024); + EXPECT_FALSE(buf1.reserve(-456)); + std::string str1("this is a long string that I want to put in a buffer"); + const char* str2 = "this is another string, that is fairly long that I want to put in a buffer"; + buf1.fill(str1); + // +1 is to account for newline stringSize is the size required to hold the string + EXPECT_EQ(buf1.stringSize(), str1.size() + 1); + EXPECT_EQ(buf1.toString(), str1); + buf1.fill(str2); + EXPECT_EQ(buf1.toString(), str2); + + EXPECT_EQ(buf1.type(), HELICS_DATA_TYPE_STRING); + + auto buf2 = buf1.clone(); + EXPECT_EQ(buf1.toString(), buf2.toString()); + + double tValue = 45.626525; + buf2.fill(tValue); + EXPECT_EQ(buf2.type(), HELICS_DATA_TYPE_DOUBLE); + + buf2.convertToType(HELICS_DATA_TYPE_NAMED_POINT); + + EXPECT_EQ(buf2.type(), HELICS_DATA_TYPE_NAMED_POINT); + + buf2.convertToType(HELICS_DATA_TYPE_VECTOR); + EXPECT_EQ(buf2.vectorSize(), 1); + + EXPECT_EQ(buf2.toDouble(), tValue); +} + +TEST(dataBuffer, bufferMemory) +{ + std::string v1; + v1.resize(1024, '\0'); + helicscpp::DataBuffer buf1(v1.data(), 0, static_cast(v1.size())); + EXPECT_EQ(buf1.capacity(), v1.size()); + EXPECT_EQ(buf1.size(), 0); + buf1.fill(std::vector{34.673, 19.1514, 1e-45}); + helicscpp::DataBuffer buf2(v1.data(), + static_cast(buf1.size()), + static_cast(v1.capacity())); + + EXPECT_EQ(buf2.type(), HELICS_DATA_TYPE_VECTOR); + + EXPECT_FALSE(buf1.reserve(2048)); + buf2.convertToType(HELICS_DATA_TYPE_STRING); + // checking linkage here + EXPECT_EQ(buf2.type(), HELICS_DATA_TYPE_STRING); + EXPECT_EQ(buf1.type(), HELICS_DATA_TYPE_STRING); +} diff --git a/tests/helics/shared_library/test-value-federate1.cpp b/tests/helics/shared_library/test-value-federate1.cpp index 7e83fb7e9a..659858100f 100644 --- a/tests/helics/shared_library/test-value-federate1.cpp +++ b/tests/helics/shared_library/test-value-federate1.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -1184,3 +1184,58 @@ TEST_P(vfed_simple_type_tests, test_info_field) INSTANTIATE_TEST_SUITE_P(vfed_tests, vfed_simple_type_tests, ::testing::ValuesIn(CoreTypes_simple)); INSTANTIATE_TEST_SUITE_P(vfed_tests, vfed_type_tests, ::testing::ValuesIn(CoreTypes)); + +TEST_F(vfed_single_tests, buffer_tests) +{ + HelicsTime gtime; + double val1 = 0; + double* val = &val1; + const double testValue1{4.565}; + const double testValue2{-2624.262}; + SetupTest(helicsCreateValueFederate, "test", 1, 1.0); + auto vFed = GetFederateAt(0); + // register the publications + auto pubid = + helicsFederateRegisterGlobalPublication(vFed, "pub1", HELICS_DATA_TYPE_DOUBLE, "", nullptr); + auto subid = helicsFederateRegisterSubscription(vFed, "pub1", "", nullptr); + + CE(helicsFederateEnterExecutingMode(vFed, &err)); + + // publish string1 at time=0.0; + CE(helicsPublicationPublishDouble(pubid, testValue1, &err)); + + CE(gtime = helicsFederateRequestTime(vFed, 1.0, &err)); + EXPECT_EQ(gtime, 1.0); + + // get the value + CE(*val = helicsInputGetDouble(subid, &err)); + // make sure the string is what we expect + EXPECT_EQ(*val, testValue1); + + // publish a second value + auto buf1 = helicsCreateDataBuffer(20); + helicsDataBufferFillFromDouble(buf1, testValue2); + + CE(helicsPublicationPublishDataBuffer(pubid, buf1, &err)); + + helicsDataBufferFree(buf1); + // make sure the value is still what we expect + CE(*val = helicsInputGetDouble(subid, &err)); + EXPECT_EQ(*val, testValue1); + + auto buffer = helicsInputGetDataBuffer(subid, nullptr); + EXPECT_EQ(helicsDataBufferIsValid(buffer), HELICS_TRUE); + EXPECT_EQ(helicsDataBufferType(buffer), HELICS_DATA_TYPE_DOUBLE); + EXPECT_EQ(helicsDataBufferToDouble(buffer), testValue1); + + helicsDataBufferFree(buffer); + // advance time + CE(gtime = helicsFederateRequestTime(vFed, 2.0, &err)); + // make sure the value was updated + EXPECT_EQ(gtime, 2.0); + + CE(*val = helicsInputGetDouble(subid, &err)); + EXPECT_EQ(*val, testValue2); + + CE(helicsFederateFinalize(vFed, &err)); +} diff --git a/tests/helics/shared_library/test-value-federate2.cpp b/tests/helics/shared_library/test-value-federate2.cpp index 2a857b4a36..8805c9d5af 100644 --- a/tests/helics/shared_library/test-value-federate2.cpp +++ b/tests/helics/shared_library/test-value-federate2.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. */ @@ -152,6 +152,23 @@ TEST_F(vfed2_tests, file_load) helicsFederateFree(vFed); } +TEST_F(vfed2_tests, file_load_with_space) +{ + HelicsFederate vFed; + // fi = helicsCreateFederateInfo(); + // path of the JSON file is hardcoded for now + vFed = helicsCreateValueFederateFromConfig(TEST_DIR "/folder with space/example_value_fed.json", + &err); + EXPECT_EQ(err.error_code, HELICS_OK); + ASSERT_FALSE(vFed == nullptr); + const char* s = helicsFederateGetName(vFed); + EXPECT_STREQ(s, "valueFed"); + EXPECT_EQ(helicsFederateGetInputCount(vFed), 3); + EXPECT_EQ(helicsFederateGetPublicationCount(vFed), 2); + CE(helicsFederateFinalize(vFed, &err)); + helicsFederateFree(vFed); +} + TEST(valuefederate, fedAlias) { auto fi = helicsCreateFederateInfo(); diff --git a/tests/helics/shared_library/test-value-federate2_cpp.cpp b/tests/helics/shared_library/test-value-federate2_cpp.cpp index 9078c1cbdb..436b83954f 100644 --- a/tests/helics/shared_library/test-value-federate2_cpp.cpp +++ b/tests/helics/shared_library/test-value-federate2_cpp.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -16,9 +16,9 @@ static const auto testNamer = [](const ::testing::TestParamInfo& pa return std::string(parameter.param); }; -struct vfed_tests: public FederateTestFixture_cpp, public ::testing::Test {}; +struct VfedTests: public FederateTestFixture_cpp, public ::testing::Test {}; -class vfed_type_tests: +class VFedTypeTests: public ::testing::TestWithParam, public FederateTestFixture_cpp {}; @@ -26,11 +26,11 @@ class vfed_type_tests: /** test block send and receive*/ -TEST_P(vfed_type_tests, test_block_send_receive) +TEST_P(VFedTypeTests, test_block_send_receive) { HelicsTime gtime; - std::string s(500, ';'); - int len = static_cast(s.size()); + std::string value(500, ';'); + int len = static_cast(value.size()); SCOPED_TRACE("calling setup"); SetupTest(GetParam(), 1); SCOPED_TRACE("calling get federate"); @@ -48,7 +48,7 @@ TEST_P(vfed_type_tests, test_block_send_receive) SCOPED_TRACE("set Delta"); vFed1->enterExecutingMode(); SCOPED_TRACE("publish"); - pubid3.publish(s); + pubid3.publish(value); SCOPED_TRACE("reqtime"); gtime = vFed1->requestTime(1.0); EXPECT_EQ(gtime, 1.0); @@ -71,7 +71,7 @@ TEST_P(vfed_type_tests, test_block_send_receive) vFed1->finalize(); } -TEST_P(vfed_type_tests, test_async_calls) +TEST_P(VFedTypeTests, test_async_calls) { HelicsTime gtime; HelicsTime f1time; @@ -105,17 +105,17 @@ TEST_P(vfed_type_tests, test_async_calls) gtime = vFed1->getCurrentTime(); EXPECT_EQ(gtime, 1.0); // get the value - auto s = subid.getString(); + auto value = subid.getString(); // make sure the string is what we expect - EXPECT_EQ(s, "string1"); + EXPECT_EQ(value, "string1"); // publish a second string pubid.publish("string2"); // make sure the value is still what we expect - s = subid.getString(); - EXPECT_EQ(s, "string1"); + value = subid.getString(); + EXPECT_EQ(value, "string1"); // advance time vFed1->requestTimeAsync(2.0); @@ -127,24 +127,24 @@ TEST_P(vfed_type_tests, test_async_calls) EXPECT_EQ(gtime, 2.0); // make sure the value was updated - s = subid.getString(); - EXPECT_EQ(s, "string2"); + value = subid.getString(); + EXPECT_EQ(value, "string2"); vFed1->finalize(); vFed2->finalize(); } // -INSTANTIATE_TEST_SUITE_P(vfed_tests, vfed_type_tests, ::testing::ValuesIn(CoreTypes), testNamer); +INSTANTIATE_TEST_SUITE_P(VfedTests, VFedTypeTests, ::testing::ValuesIn(CoreTypes), testNamer); // -TEST_F(vfed_tests, test_file_load) +TEST_F(VfedTests, test_file_load) { // fi = helicsCreateFederateInfo(); // path of the JSON file is hardcoded for now helicscpp::ValueFederate vFed(TEST_DIR "/example_value_fed.json"); ASSERT_TRUE(vFed.baseObject() != nullptr); - std::string s = vFed.getName(); - EXPECT_EQ(s, "valueFed"); + std::string fedName = vFed.getName(); + EXPECT_EQ(fedName, "valueFed"); EXPECT_EQ(vFed.getInputCount(), 3); EXPECT_EQ(vFed.getPublicationCount(), 2); // helicscpp::ValueFederate vFed(std::string(TEST_DIR) + @@ -152,31 +152,81 @@ TEST_F(vfed_tests, test_file_load) vFed.finalize(); } -TEST_F(vfed_tests, test_json_register_publish) +TEST_F(VfedTests, json_register_publish) { SetupTest("test", 1); auto vFed = GetFederateAs(0); vFed->setSeparator('/'); vFed->registerFromPublicationJSON(std::string(TEST_DIR) + "example_pub_input1.json"); - auto s1 = vFed->registerSubscription("fed0/pub1"); - auto s2 = vFed->registerSubscription("fed0/pub2"); - auto s3 = vFed->registerSubscription("fed0/group1/pubA"); - auto s4 = vFed->registerSubscription("fed0/group1/pubB"); + auto sub1 = vFed->registerSubscription("fed0/pub1"); + auto sub2 = vFed->registerSubscription("fed0/pub2"); + auto sub3 = vFed->registerSubscription("fed0/group1/pubA"); + auto sub4 = vFed->registerSubscription("fed0/group1/pubB"); vFed->enterExecutingMode(); vFed->publishJSON(std::string(TEST_DIR) + "example_pub_input1.json"); vFed->requestTime(1.0); - EXPECT_EQ(s1.getDouble(), 99.9); - EXPECT_EQ(s2.getString(), "things"); - EXPECT_EQ(s3.getDouble(), 45.7); - EXPECT_EQ(s4.getString(), "count"); + EXPECT_EQ(sub1.getDouble(), 99.9); + EXPECT_EQ(sub2.getString(), "things"); + EXPECT_EQ(sub3.getDouble(), 45.7); + EXPECT_EQ(sub4.getString(), "count"); vFed->publishJSON(std::string(TEST_DIR) + "example_pub_input2.json"); vFed->requestTime(2.0); - EXPECT_EQ(s1.getDouble(), 88.2); - EXPECT_EQ(s2.getString(), "items"); - EXPECT_EQ(s3.getDouble(), 15.0); - EXPECT_EQ(s4.getString(), "count2"); + EXPECT_EQ(sub1.getDouble(), 88.2); + EXPECT_EQ(sub2.getString(), "items"); + EXPECT_EQ(sub3.getDouble(), 15.0); + EXPECT_EQ(sub4.getString(), "count2"); + + vFed->finalize(); +} + +TEST_F(VfedTests, data_buffer) +{ + HelicsTime gtime; + double val1 = 0; + const double testValue1{4.565}; + const double testValue2{-2624.262}; + SetupTest("test", 1, 1.0); + auto vFed = GetFederateAs(0); + // register the publications + auto pubid = vFed->registerGlobalPublication("pub1", HELICS_DATA_TYPE_DOUBLE, ""); + auto subid = vFed->registerSubscription("pub1", ""); + + vFed->enterExecutingMode(); + + pubid.publish(testValue1); + + gtime = vFed->requestTime(1.0); + EXPECT_EQ(gtime, 1.0); + + // get the value + val1 = subid.getDouble(); + // make sure the string is what we expect + EXPECT_EQ(val1, testValue1); + { + // publish a second value + helicscpp::DataBuffer buf1(20); + buf1.fill(testValue2); + pubid.publish(buf1); + } + val1 = subid.getDouble(); + + EXPECT_EQ(val1, testValue1); + + { + auto buffer = subid.getDataBuffer(); + EXPECT_TRUE(buffer.isValid()); + EXPECT_EQ(buffer.type(), HELICS_DATA_TYPE_DOUBLE); + EXPECT_EQ(buffer.toDouble(), testValue1); + } + // advance time + gtime = vFed->requestTime(2.0); + // make sure the value was updated + EXPECT_EQ(gtime, 2.0); + + val1 = subid.getDouble(); + EXPECT_EQ(val1, testValue2); vFed->finalize(); } diff --git a/tests/helics/shared_library/timingTests_cpp.cpp b/tests/helics/shared_library/timingTests_cpp.cpp index f7dff34202..b000d1dad1 100644 --- a/tests/helics/shared_library/timingTests_cpp.cpp +++ b/tests/helics/shared_library/timingTests_cpp.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/tests/helics/system_tests/CMakeLists.txt b/tests/helics/system_tests/CMakeLists.txt index 2cd3352fd4..88a03b8e52 100644 --- a/tests/helics/system_tests/CMakeLists.txt +++ b/tests/helics/system_tests/CMakeLists.txt @@ -1,5 +1,5 @@ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Copyright (c) 2017-2023, Battelle Memorial Institute; Lawrence Livermore +# Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore # National Security, LLC; Alliance for Sustainable Energy, LLC. # See the top-level NOTICE for additional details. # All rights reserved. diff --git a/tests/helics/system_tests/ErrorTests.cpp b/tests/helics/system_tests/ErrorTests.cpp index 00a809a00c..e08f06977d 100644 --- a/tests/helics/system_tests/ErrorTests.cpp +++ b/tests/helics/system_tests/ErrorTests.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/tests/helics/system_tests/QueryTests.cpp b/tests/helics/system_tests/QueryTests.cpp index 29414b5755..77c4c47689 100644 --- a/tests/helics/system_tests/QueryTests.cpp +++ b/tests/helics/system_tests/QueryTests.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/tests/helics/system_tests/TimingTests.cpp b/tests/helics/system_tests/TimingTests.cpp index ff66ce1db9..9abe368a20 100644 --- a/tests/helics/system_tests/TimingTests.cpp +++ b/tests/helics/system_tests/TimingTests.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/tests/helics/system_tests/TimingTests2.cpp b/tests/helics/system_tests/TimingTests2.cpp index 896426a128..08b3984707 100644 --- a/tests/helics/system_tests/TimingTests2.cpp +++ b/tests/helics/system_tests/TimingTests2.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/tests/helics/system_tests/brokerTimeoutTests.cpp b/tests/helics/system_tests/brokerTimeoutTests.cpp index 190153e780..36fb3602b1 100644 --- a/tests/helics/system_tests/brokerTimeoutTests.cpp +++ b/tests/helics/system_tests/brokerTimeoutTests.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/tests/helics/system_tests/commandInterfaceTests.cpp b/tests/helics/system_tests/commandInterfaceTests.cpp index 1cf1bf75d7..c4d7fac1f4 100644 --- a/tests/helics/system_tests/commandInterfaceTests.cpp +++ b/tests/helics/system_tests/commandInterfaceTests.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/tests/helics/system_tests/dynamicFederationTests.cpp b/tests/helics/system_tests/dynamicFederationTests.cpp index 3ac0ec0129..13a519136c 100644 --- a/tests/helics/system_tests/dynamicFederationTests.cpp +++ b/tests/helics/system_tests/dynamicFederationTests.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/tests/helics/system_tests/federateRealTimeTests.cpp b/tests/helics/system_tests/federateRealTimeTests.cpp index 6330f11151..a1b0308df9 100644 --- a/tests/helics/system_tests/federateRealTimeTests.cpp +++ b/tests/helics/system_tests/federateRealTimeTests.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. diff --git a/tests/helics/system_tests/flagTests.cpp b/tests/helics/system_tests/flagTests.cpp index 8d6f30b374..05d7ecb649 100644 --- a/tests/helics/system_tests/flagTests.cpp +++ b/tests/helics/system_tests/flagTests.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/tests/helics/system_tests/heat-transfer-tests.cpp b/tests/helics/system_tests/heat-transfer-tests.cpp index 6afaad09cb..fa2487fab8 100644 --- a/tests/helics/system_tests/heat-transfer-tests.cpp +++ b/tests/helics/system_tests/heat-transfer-tests.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause @@ -12,8 +12,7 @@ SPDX-License-Identifier: BSD-3-Clause #include #include -using helics::operator"" _t; -helics::Time tend = 3600.0_t; // simulation end time +helics::Time tend = 3600.0; // simulation end time /** class implementing a single heat transfer block*/ class HeatUnitBlock { @@ -72,7 +71,7 @@ class HeatUnitBlock { void mainLoop() { - auto cTime = 0.0_t; + auto cTime = helics::timeZero; while (cTime < tend) { auto T0 = sub[0]->getValue(); diff --git a/tests/helics/system_tests/helics_system_tests.cpp b/tests/helics/system_tests/helics_system_tests.cpp index 1d9d079e4d..642c7068a2 100644 --- a/tests/helics/system_tests/helics_system_tests.cpp +++ b/tests/helics/system_tests/helics_system_tests.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/tests/helics/system_tests/iterationTests.cpp b/tests/helics/system_tests/iterationTests.cpp index d77532130a..631d7bf5fe 100644 --- a/tests/helics/system_tests/iterationTests.cpp +++ b/tests/helics/system_tests/iterationTests.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/tests/helics/system_tests/networkTests.cpp b/tests/helics/system_tests/networkTests.cpp index bff85f17f5..5b9de14d8e 100644 --- a/tests/helics/system_tests/networkTests.cpp +++ b/tests/helics/system_tests/networkTests.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/tests/helics/system_tests/profilingTests.cpp b/tests/helics/system_tests/profilingTests.cpp index c18cbe6a42..fbe8e11f64 100644 --- a/tests/helics/system_tests/profilingTests.cpp +++ b/tests/helics/system_tests/profilingTests.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/tests/helics/system_tests/updateTests.cpp b/tests/helics/system_tests/updateTests.cpp index c3464f42fa..156c54478d 100644 --- a/tests/helics/system_tests/updateTests.cpp +++ b/tests/helics/system_tests/updateTests.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/tests/helics/test_files/ControllerConfig.json b/tests/helics/test_files/ControllerConfig.json new file mode 100644 index 0000000000..9262207506 --- /dev/null +++ b/tests/helics/test_files/ControllerConfig.json @@ -0,0 +1,100 @@ +{ + "name": "Controller", + "core_name": "controller_core", + "log_level": "warning", + "core_type": "test", + "time_delta": 1, + "uninterruptible": false, + "terminate_on_error": true, + "translators": [ + { + "name": "EV_1_translator", + "type": "json", + "global": true, + "info": "", + "source_endpoint": "Charger/EV1.soc", + "destination_input": "Controller/EV1.soc" + }, + { + "name": "EV_2_translator", + "type": "json", + "global": true, + "info": "", + "source_endpoint": "Charger/EV2.soc", + "destination_input": "Controller/EV2.soc" + }, + { + "name": "EV_3_translator", + "type": "json", + "global": true, + "info": "", + "source_endpoint": "Charger/EV3.soc", + "destination_input": "Controller/EV3.soc" + }, + { + "name": "EV_4_translator", + "type": "json", + "global": true, + "info": "", + "source_endpoint": "Charger/EV4.soc", + "destination_input": "Controller/EV4.soc" + }, + { + "name": "EV_5_translator", + "type": "json", + "global": true, + "info": "", + "source_endpoint": "Charger/EV5.soc", + "destination_input": "Controller/EV5.soc" + } + ], + "inputs": [ + { + "key": "Controller/EV1.soc", + "type": "double", + "global": true + }, + { + "key": "Controller/EV2.soc", + "type": "double", + "global": true + }, + { + "key": "Controller/EV3.soc", + "type": "double", + "global": true + }, + { + "key": "Controller/EV4.soc", + "type": "double", + "global": true + }, + { + "key": "Controller/EV5.soc", + "type": "double", + "global": true + } + ], + "endpoints": [ + { + "name": "Charger/EV1.soc", + "global": true + }, + { + "name": "Charger/EV2.soc", + "global": true + }, + { + "name": "Charger/EV3.soc", + "global": true + }, + { + "name": "Charger/EV4.soc", + "global": true + }, + { + "name": "Charger/EV5.soc", + "global": true + } + ] +} diff --git a/tests/helics/test_files/example message fed with space.json b/tests/helics/test_files/example message fed with space.json new file mode 100644 index 0000000000..e81199789b --- /dev/null +++ b/tests/helics/test_files/example message fed with space.json @@ -0,0 +1,44 @@ +//this should be a valid json file (except comments are not recognized in standard JSON) +{ + //example json configuration file for a message federate all arguments are optional + "name": "messageFed", // the name of the federate + //possible flags + "observer": false, // indicator that the federate does not send anything + "rollback": false, // indicator that the federate can use rollback -NOTE: not used at present + "only_update_on_change": false, //indicator that the federate should only indicate updated values on change + "only_transmit_on_change": false, //indicator that the federate should only publish if the value changed + "source_only": false, //indicator that the federate is only a source and is not expected to receive anything + "uninterruptible": false, //indicator that the federate should only return requested times + "coretype": "test", //the type of the core "test","zmq","udp","ipc","tcp","mpi" + "corename": "mcname", //this matters most for ipc and test cores, can be empty + "coreinitstring": "--autobroker", // the initialization string for the core in the form of a command line arguments + "max_iterations": 10, //the maximum number of iterations for a time step + "period": 1.0, //the period with which federate may return time + "log_level": "error", // set the log level to error only + "offset": 0.0, // the offset shift in the period + "time_delta": 0.0, // the minimum time between subsequent return times + "output_delay": 0, //the propagation delay for federates to send data + "input_delay": 0, //the input delay for external data to propagate to federates + + //endpoints used in the federate + "endpoints": [ + { + "name": "ept1", // the name of the publication + "type": "genmessage", // the type associated with a endpoint endpoint types have limited usefulness at present (optional) + "global": true, //set to true to make the key global (default is false in which case the publication is prepended with the federate name) + "flags": ["connection_optional", "-connection_required"] + }, + { + "name": "ept2", // the name of the publication + "type": "message2", // the type associated with a endpoint (optional) + //the fact that there is no global value creates a local endpoint with global name messageFed/ept2 + "knownDestinations": "ept1", //this value can be an array of strings or just a single one it names key paths + //knownDestinations can be used to optimize the communication pathways inside of HELICS + //the message will be raw data so it would have to be translated to be useful. this can also be a json array to subscribe to multiple publications + "connection_required": true, + "connection_optional": true, + "sourceFilters": "filt1", + "destFilters": "filt2" + } + ] +} diff --git a/tests/helics/test_files/example_translators.json b/tests/helics/test_files/example_translators.json new file mode 100644 index 0000000000..4c7027ef18 --- /dev/null +++ b/tests/helics/test_files/example_translators.json @@ -0,0 +1,83 @@ +{ + "name": "transtest_json", + "core_type": "test", + "time_delta": 1, + "terminate_on_error": true, + "defaultglobal": true, + "translators": [ + { + "name": "EV_1_translator", + "type": "json", + "info": "", + "source_endpoint": "Charger/EV1.soc", + "destination_input": "Controller/EV1.soc" + }, + { + "name": "EV_2_translator", + "type": "json", + "info": "", + "source_endpoint": "Charger/EV2.soc", + "destination_input": "Controller/EV2.soc" + }, + { + "name": "EV_3_translator", + "type": "binary", + "info": "", + "source_endpoint": "Charger/EV3.soc", + "destination_input": "Controller/EV3.soc" + }, + { + "name": "EV_4_translator", + "type": "json", + "info": "", + "source_endpoint": "Charger/EV4.soc", + "destination_input": "Controller/EV4.soc" + }, + { + "name": "EV_5_translator", + "type": "json", + "info": "", + "source_endpoint": "Charger/EV5.soc", + "destination_input": "Controller/EV5.soc" + } + ], + "inputs": [ + { + "key": "Controller/EV1.soc", + "type": "double" + }, + { + "key": "Controller/EV2.soc", + "type": "double" + }, + { + "key": "Controller/EV3.soc", + "type": "double" + }, + { + "key": "Controller/EV4.soc", + "type": "double" + }, + { + "key": "Controller/EV5.soc", + "type": "double" + } + ], + "endpoints": [ + { + "name": "Charger/EV1.soc" + }, + { + "name": "Charger/EV2.soc" + }, + { + "name": "Charger/EV3.soc" + }, + { + "name": "Charger/EV4.soc" + }, + { + "name": "Charger/EV5.soc" + } + ] +} diff --git a/tests/helics/test_files/example_translators.toml b/tests/helics/test_files/example_translators.toml new file mode 100644 index 0000000000..a078be757d --- /dev/null +++ b/tests/helics/test_files/example_translators.toml @@ -0,0 +1,61 @@ +# configuration test for toml +name="transtest_toml" +core_type="test" +time_delta= 1 +terminate_on_error= true +defaultglobal=true +[[translators]] + "name"= "EV_1_translator" + "type"= "json" + "info"= "" + "source_endpoint"= "Charger/EV1.soc" + "destination_input"= "Controller/EV1.soc" +[[translators]] + "name"="EV_2_translator" + "type"= "json" + "info"= "" + "source_endpoint"= "Charger/EV2.soc" + "destination_input"= "Controller/EV2.soc" +[[translators]] + "name"= "EV_3_translator" + "type"= "binary" + "info"= "" + "source_endpoint"= "Charger/EV3.soc" + "destination_input"= "Controller/EV3.soc" +[[translators]] + "name"= "EV_4_translator" + "type"= "json" + "info"= "" + "source_endpoint"= "Charger/EV4.soc" + "destination_input"= "Controller/EV4.soc" +[[translators]] + "name"= "EV_5_translator" + "type"= "json" + "info"= "" + "source_endpoint"= "Charger/EV5.soc" + "destination_input"= "Controller/EV5.soc" +[[inputs]] + "key"="Controller/EV1.soc" + "type"="double" +[[inputs]] + "key"="Controller/EV2.soc" + "type"="double" +[[inputs]] + "key"="Controller/EV3.soc" + "type"= "double" +[[inputs]] + "key"="Controller/EV4.soc" + "type"="double" +[[inputs]] + "key"="Controller/EV5.soc" + "type"="double" +[[endpoints]] + "name"="Charger/EV1.soc" +[[endpoints]] + "name"="Charger/EV2.soc" +[[endpoints]] + "name"="Charger/EV3.soc" +[[endpoints]] + "name"="Charger/EV4.soc" +[[endpoints]] + "name"="Charger/EV5.soc" diff --git a/tests/helics/test_files/folder with space/example_combo_fed.toml b/tests/helics/test_files/folder with space/example_combo_fed.toml new file mode 100644 index 0000000000..0fab8e86ff --- /dev/null +++ b/tests/helics/test_files/folder with space/example_combo_fed.toml @@ -0,0 +1,68 @@ +#this should be a valid json file (except comments are not recognized in standard JSON) +#example json configuration file for a message federate all arguments are optional +name="comboFed" # the name of the federate +#possible flags +observer=false # indicator that the federate does not send anything +rollback= false # indicator that the federate can use rollback -NOTE= not used at present +only_update_on_change=false #indicator that the federate should only indicate updated values on change +only_transmit_on_change=false #indicator that the federate should only publish if the value changed +source_only=false #indicator that the federate is only a source and is not expected to receive anything +uninterruptible=false #indicator that the federate should only return requested times +coretype="test" #the type of the core "test","zmq","udp","ipc","tcp","mpi" +corename="the name of the core" #this matters most for ipc and test cores, can be empty +coreinitstring="--federates 1 --autobroker" # the initialization string for the core in the form of a command line arguments +max_iterations=10 #the maximum number of iterations for a time step +period= 1.0 #the period with which federate may return time +offset= 0.0 # the offset shift in the period +time_delta=0.0 # the minimum time between subsequent return times +output_delay=0 #the propagation delay for federates to send data +input_delay=0 #the input delay for external data to propagate to federates + +#endpoints used in the federate +[[endpoints]] + +name="ept1" # the name of the publication + type="genmessage" # the type associated with a endpoint endpoint types have limited usefulness at present (optional) + global=true #set to true to make the key global (default is false in which case the publication is prepended with the federate name) +[[endpoints]] +name="ept2" # the name of the publication + type="message2" # the type associated with a endpoint (optional) + #the fact that there is no global value creates a local endpoint with global name comboFed/ept2 + + knownDestinations="ept1" #this value can be an array of strings or just a single one it names key paths + #knownDestinations can be used to optimize the communication pathways inside of HELICS + subscriptions="pub1" #subscribe an endpoint to a particular publication this means that an endpoint will get a message whenever anything is published to that particular key + #the message will be raw data so it would have to be translated to be useful. this can also be a json array to subscribe to multiple publications + +#Publications used in the federate +[[publications]] + +"key"="pub1" # the name of the publication + "type"="double" # the type associated with a publication (optional) + "unit"="m" # the units associated with a publication (optional) + "global"=true #set to true to make the key global (default is false in which case the publication is prepended with the federate name) + +[[publications]] +name="pub2" # the name of the publication (can be key or name) + type="double" # the type associated with a publication (optional) + info='{"field1":45,"field2":99}' #literal info field + #no global=true implies this will have the federate name prepended like comboFed/pub2 + +#subscriptions used in the federate +[[subscriptions]] + +key="pub1" # the key of the publication + type="double" # the type associated with a publication (optional) + connection_required=true #set to true to make helics issue a warning if the publication is not found + +[[subscriptions]] +key="comboFed/pub2" # the name of the publication to subscribe to +alias="pubshortcut" #a naming shortcut for the publication for later retrieval + +[[subscriptions]] + +key="dpub" # the key of the publication + type="double" # the type associated with a publication (optional) + connection_required=true #set to true to make helics issue a warning if the publication is not found + + aliases=[["comboFed/pub2","dpub"]] diff --git a/tests/helics/test_files/folder with space/example_value_fed.json b/tests/helics/test_files/folder with space/example_value_fed.json new file mode 100644 index 0000000000..4a559cecc6 --- /dev/null +++ b/tests/helics/test_files/folder with space/example_value_fed.json @@ -0,0 +1,65 @@ +//this should be a valid json file (except comments are not recognized in standard JSON) +{ + //example json configuration file for a value federate all arguments are optional + "name": "valueFed", // the name of the federate + //possible flags + "observer": false, // indicator that the federate does not send anything + "rollback": false, // indicator that the federate can use rollback -NOTE: not used at present + "only_update_on_change": false, //indicator that the federate should only indicate updated values on change + "only_transmit_on_change": false, //indicator that the federate should only publish if the value changed + "source_only": false, //indicator that the federate is only a source and is not expected to receive anything + "uninterruptible": false, //indicator that the federate should only return requested times + "coretype": "test", //the type of the core "test","zmq","udp","ipc","tcp","mpi" + "corename": "the name of the core", //this matters most for ipc and inproc cores, can be empty + "coreinitstring": "--autobroker", // the initialization string for the core in the form of a command line arguments + "max_iterations": 10, //the maximum number of iterations for a time step + "period": 1.0, //the period with which federate may return time + "offset": 0.0, // the offset shift in the period + "time_delta": 0.0, // the minimum time between subsequent return times + "output_delay": 0, //the propagation delay for federates to send data + "input_delay": 0, //the input delay for external data to propagate to federates + "log_level": "summary", //specify the log level (either a number or string) + + //Publications used in the federate + "publications": [ + { + "key": "pub1", // the name of the publication + "type": "double", // the type associated with a publication (optional) + "units": "m", // the units associated with a publication (optional) + "global": true, //set to true to make the key global (default is false in which case the publication is prepended with the federate name) + "info": "this is an information string for use by the application" + }, + { + "key": "pub2", // the name of the publication + "type": "double" // the type associated with a publication (optional) + //no global:true implies this will have the federate name prepended like valueFed/pub2 + } + ], + //subscriptions used in the federate + "subscriptions": [ + { + "key": "pub1", // the key of the publication + "connection_required": true //set to true to make helics issue a warning if the publication is not found + }, + { + "key": "fedName/pub2", // the name of the publication to subscribe to + "alias": "pubshortcut", //a naming shortcut for the publication for later retrieval + "info": "this is an information string for use by the application" + } + ], + + "inputs": [ + { + "key": "ipt2", + "type": "double", + "connection_required": true, + "target": "pub1" + } + //specify an input with a target multiple targets could be specified like "targets":["pub1","pub2","pub3"] + ], + + "globals": [ + ["global1", "this is a global1 value"], + ["global2", "this is another global value"] + ] +} diff --git a/tests/helics/test_files/folder with space/example_value_fed_testb.json b/tests/helics/test_files/folder with space/example_value_fed_testb.json new file mode 100644 index 0000000000..3725d8d4b9 --- /dev/null +++ b/tests/helics/test_files/folder with space/example_value_fed_testb.json @@ -0,0 +1,85 @@ +//this should be a valid json file (except comments are not recognized in standard JSON) +{ + //example json configuration file for a value federate all arguments are optional + "name": "valueFed2", // the name of the federate + //possible flags + "observer": false, // indicator that the federate does not send anything + "rollback": false, // indicator that the federate can use rollback -NOTE: not used at present + "only_update_on_change": false, //indicator that the federate should only indicate updated values on change + "only_transmit_on_change": false, //indicator that the federate should only publish if the value changed + "source_only": false, //indicator that the federate is only a source and is not expected to receive anything + "uninterruptible": false, //indicator that the federate should only return requested times + "coretype": "test", //the type of the core "test","zmq","udp","ipc","tcp","mpi" + "corename": "testb_core", //this matters most for ipc and inproc cores, can be empty + "coreinitstring": "--autobroker", // the initialization string for the core in the form of a command line arguments + "max_iterations": 10, //the maximum number of iterations for a time step + "period": 1.0, //the period with which federate may return time + "offset": 0.0, // the offset shift in the period + "time_delta": 0.0, // the minimum time between subsequent return times + "output_delay": 0, //the propagation delay for federates to send data + "input_delay": 0, //the input delay for external data to propagate to federates + "log_level": "warning", //specify the log level + + //Publications used in the federate + "publications": [ + { + "key": "pub1", // the name of the publication + "type": "double", // the type associated with a publication (optional) + "unit": "m", // the units associated with a publication (optional) + "global": true, //set to true to make the key global (default is false in which case the publication is prepended with the federate name) + "info": "this is an information string for use by the application", + "flags": ["connection_required", "-connection_optional"], + "tags": { + "period": 0.5, + "description": "a test publication" + } + }, + { + "key": "pub2", // the name of the publication + "type": "double", // the type associated with a publication (optional) + //no global:true implies this will have the federate name prepended like valueFed/pub2 + "alias": "primary" + } + ], + //subscriptions used in the federate + "subscriptions": [ + { + "key": "pub1", // the key of the publication + "connection_required": true, //set to true to make helics issue a warning if the publication is not found + "tolerance": 0.3, + "default": "9.33" + }, + { + "key": "fedName/pub2", // the name of the publication to subscribe to + "alias": "pubshortcut", //a naming shortcut for the publication for later retrieval + "info": "this is an information string for use by the application", + "connection_optional": true //the subscription is optional + } + ], + + "inputs": [ + { + "key": "ipt2", + "type": "double", + "connection_required": true, + "target": "pub1", + "global": true, + "default": 3.67, + "tags": [ + { "name": "period", "value": "0.7" }, + { "name": "description", "value": "a test input" } + ] + } + //specify an input with a target multiple targets could be specified like "targets":["pub1","pub2","pub3"] + ], + + "globals": [ + ["global1", "this is a global1 value"], + ["global2", "this is another global value"] + ], + // add some tags about the federate + "tags": { + "description": "fedb description", + "version": 27 + } +} diff --git a/tests/helics/test_files/invalid_translator_operation.json b/tests/helics/test_files/invalid_translator_operation.json new file mode 100644 index 0000000000..27012af852 --- /dev/null +++ b/tests/helics/test_files/invalid_translator_operation.json @@ -0,0 +1,58 @@ +//this should be a valid json file (except comments are not recognized in standard JSON) +{ + //example json configuration file for a message federate that also creates some filters + "name": "transFed", // the name of the federate + //possible flags + "observer": false, // indicator that the federate does not send anything + "rollback": false, // indicator that the federate can use rollback -NOTE: not used at present + "only_update_on_change": false, //indicator that the federate should only indicate updated values on change + "only_transmit_on_change": false, //indicator that the federate should only publish if the value changed + "source_only": false, //indicator that the federate is only a source and is not expected to receive anything + "uninterruptible": false, //indicator that the federate should only return requested times + "coretype": "test", //the type of the core "test","zmq","udp","ipc","tcp","mpi" + "corename": "the name of the core", //this matters most for ipc and test cores, can be empty + "coreinit": "--autobroker", // the initialization string for the core in the form of a command line arguments + "max_iterations": 10, //the maximum number of iterations for a time step + "period": 1.0, //the period with which federate may return time + "offset": 0.0, // the offset shift in the period + "time_delta": 0.0, // the minimum time between subsequent return times + "output_delay": 0, //the propagation delay for federates to send data + "input_delay": 0, //the input delay for external data to propagate to federates + + //endpoints used in the federate not really necessary to define endpoints for a filer + "endpoints": [ + { + "name": "ept1", // the name of the endpoint + "type": "genmessage", // the type associated with a endpoint endpoint types have limited usefulness at present (optional) + "global": true //set to true to make the key global (default is false in which case the endpoint is prepended with the federate name) + }, + { + "name": "ept2", // the name of the endpoint + "type": "message2", // the type associated with a endpoint (optional) + //the fact that there is no global value creates a local endpoint with global name transFed/ept2 + "knownDestinations": "ept1", //this value can be an array of strings or just a single one it names key paths + //knownDestinations can be used to optimize the communication pathways inside of HELICS + "subscriptions": "fed2/sub1" //subscribe an endpoint to a particular publication this means that an endpoint will get a message whenever anything is published to that particular key + //the message will be raw data so it would have to be translated to be useful. this can also be a json array to subscribe to multiple publications + } + ], + "translators": [ + { + "name": "tname", //translators can have names (optional) + "sourcetarget": "ept1", // source target for the translator + "type": "reroute3", //this should produce a warning + "info": "this is an information string for use by the application", + //additional properties for translators are specified in a property array or object if there is just a single one + "properties": { + "name": "delay", //the time delay for translation + "value": 0.2 //times default to seconds though units can also be specified "200 ms" or similar + } + }, + { + "name": "trans2", //translators can have names (optional) + "sourcetargets": ["filterFed/ept2"], //this is a key field specifying the source targets can be an array + //"dest":["dest targets"], // field specifying destination targets + "type": "json" //currently valid types are "json","binary","custom" + } + ] +} diff --git a/tests/helics/test_files/unusual_filters.toml b/tests/helics/test_files/unusual_filters.toml index b33b31c057..8790e9f05b 100644 --- a/tests/helics/test_files/unusual_filters.toml +++ b/tests/helics/test_files/unusual_filters.toml @@ -20,7 +20,7 @@ input_delay=0 #the input delay for external data to propagate to federates strict_config_checking=false # this file is odd so let it be flexible and only produce warnings separator=":" # set the character separator for local interfaces -#endpoints used in the federate not really necessary to define endpoints for a filer +#endpoints used in the federate not really necessary to define endpoints for a filter [[endpoints]] name="ept1" # the name of the endpoint type="genmessage" # the type associated with a endpoint endpoint types have limited usefulness at present (optional) diff --git a/tests/helics/webserver/CMakeLists.txt b/tests/helics/webserver/CMakeLists.txt index a860cf0bb1..08ce037c57 100644 --- a/tests/helics/webserver/CMakeLists.txt +++ b/tests/helics/webserver/CMakeLists.txt @@ -1,5 +1,5 @@ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Copyright (c) 2017-2023, Battelle Memorial Institute; Lawrence Livermore +# Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore # National Security, LLC; Alliance for Sustainable Energy, LLC. # See the top-level NOTICE for additional details. # All rights reserved. diff --git a/tests/helics/webserver/helics_webserver_tests.cpp b/tests/helics/webserver/helics_webserver_tests.cpp index 1d9d079e4d..642c7068a2 100644 --- a/tests/helics/webserver/helics_webserver_tests.cpp +++ b/tests/helics/webserver/helics_webserver_tests.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/tests/helics/webserver/webServerHttpTests.cpp b/tests/helics/webserver/webServerHttpTests.cpp index 9a64433401..773dff0b47 100644 --- a/tests/helics/webserver/webServerHttpTests.cpp +++ b/tests/helics/webserver/webServerHttpTests.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/tests/helics/webserver/webServerWebSocketTests.cpp b/tests/helics/webserver/webServerWebSocketTests.cpp index 988c97310b..81664a3d57 100644 --- a/tests/helics/webserver/webServerWebSocketTests.cpp +++ b/tests/helics/webserver/webServerWebSocketTests.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2023, +Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable Energy, LLC. See the top-level NOTICE for additional details. All rights reserved. SPDX-License-Identifier: BSD-3-Clause diff --git a/tests/java/CMakeLists.txt b/tests/java/CMakeLists.txt index 26bf4b46e1..237e606a01 100644 --- a/tests/java/CMakeLists.txt +++ b/tests/java/CMakeLists.txt @@ -1,5 +1,5 @@ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Copyright (c) 2017-2023, Battelle Memorial Institute; Lawrence Livermore +# Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore # National Security, LLC; Alliance for Sustainable Energy, LLC. # See the top-level NOTICE for additional details. # All rights reserved. diff --git a/tests/octave/CMakeLists.txt b/tests/octave/CMakeLists.txt index 4a1de20899..2d32120182 100644 --- a/tests/octave/CMakeLists.txt +++ b/tests/octave/CMakeLists.txt @@ -1,5 +1,5 @@ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Copyright (c) 2017-2023, Battelle Memorial Institute; Lawrence Livermore +# Copyright (c) 2017-2024, Battelle Memorial Institute; Lawrence Livermore # National Security, LLC; Alliance for Sustainable Energy, LLC. # See the top-level NOTICE for additional details. # All rights reserved. diff --git a/vcpkg.json b/vcpkg.json index d8dc027741..339ad34ba1 100644 --- a/vcpkg.json +++ b/vcpkg.json @@ -1,6 +1,6 @@ { "name": "helics", - "version-string": "3.4.0", + "version-string": "3.5.0", "description": "Hierarchical Engine for Large-scale Infrastructure Co-Simulation (HELICS)", "homepage": "https://helics.org/", "default-features": ["zeromq", "ipc", "webserver", "encryption"],