From 057a34d93f41a15ec919c2c1eb77d3d355c17e14 Mon Sep 17 00:00:00 2001 From: Alan Garny Date: Tue, 14 Apr 2026 18:38:52 +1200 Subject: [PATCH 1/5] New version. --- VERSION.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION.txt b/VERSION.txt index cf25f11db..121861f9f 100644 --- a/VERSION.txt +++ b/VERSION.txt @@ -1 +1 @@ -0.20260409.1 +0.20260416.0 From 4de7a5e672d08ff1a0b7ca0cb5ea007497fa2f1f Mon Sep 17 00:00:00 2001 From: Alan Garny Date: Tue, 14 Apr 2026 18:42:07 +1200 Subject: [PATCH 2/5] macOS: support macOS 14 and later. Only support the three most recent versions of macOS. --- .github/workflows/cd.yml | 4 ++-- CMakeLists.txt | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml index e5684ce79..1e4518bc6 100644 --- a/.github/workflows/cd.yml +++ b/.github/workflows/cd.yml @@ -168,10 +168,10 @@ jobs: env: CIBW_ARCHS: auto64 CIBW_BUILD: 'cp312-* cp313-* cp314-*' - CIBW_ENVIRONMENT_MACOS: MACOSX_DEPLOYMENT_TARGET=13.0 + CIBW_ENVIRONMENT_MACOS: MACOSX_DEPLOYMENT_TARGET=14.0 # Note #1: the value of CIBW_ENVIRONMENT_MACOS must be in sync with that of MACOS_DEPLOYMENT_TARGET in # CMakelists.txt. - # Note #2: for some reasons, we need to specify the minor version, hence using 13.0 rather than 13. + # Note #2: for some reasons, we need to specify the minor version, hence using 14.0 rather than 14. CIBW_MANYLINUX_X86_64_IMAGE: manylinux_2_34 CIBW_MANYLINUX_AARCH64_IMAGE: manylinux_2_34 CIBW_SKIP: '*musllinux*' diff --git a/CMakeLists.txt b/CMakeLists.txt index aa0052a83..4963c07db 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -56,12 +56,12 @@ if(EMSCRIPTEN) add_subdirectory(src) else() - # On macOS, deploy on macOS 13 and later. + # On macOS, deploy on macOS 14 and later. # Note: the value of MACOS_DEPLOYMENT_TARGET must be in sync with that of CIBW_ENVIRONMENT_MACOS in # .github/workflows/cd.yml. if(APPLE) - set(MACOS_DEPLOYMENT_TARGET 13) + set(MACOS_DEPLOYMENT_TARGET 14) if("${CMAKE_OSX_DEPLOYMENT_TARGET}" STREQUAL "") set(CMAKE_OSX_DEPLOYMENT_TARGET ${MACOS_DEPLOYMENT_TARGET}) From a1e7d4edcbdcb819830776053d17189d5d238e6b Mon Sep 17 00:00:00 2001 From: Alan Garny Date: Tue, 14 Apr 2026 20:14:23 +1200 Subject: [PATCH 3/5] GitHub Actions: use Ubuntu 24.04. So that we can get access to `std::format()`. --- .github/workflows/buildThirdPartyLibrary.yml | 4 +-- .github/workflows/cd.yml | 16 ++++++------ .github/workflows/ci.yml | 26 ++++++++++---------- 3 files changed, 23 insertions(+), 23 deletions(-) diff --git a/.github/workflows/buildThirdPartyLibrary.yml b/.github/workflows/buildThirdPartyLibrary.yml index 55f93fcbb..8fd666c04 100644 --- a/.github/workflows/buildThirdPartyLibrary.yml +++ b/.github/workflows/buildThirdPartyLibrary.yml @@ -36,10 +36,10 @@ jobs: arch: amd64_arm64 build_type: Debug - name: 'Linux (Intel)' - os: ubuntu-22.04 + os: ubuntu-24.04 build_type: Release - name: 'Linux (ARM)' - os: ubuntu-22.04-arm + os: ubuntu-24.04-arm build_type: Release - name: 'macOS (Intel)' os: macos-15-intel diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml index 1e4518bc6..6c09f157f 100644 --- a/.github/workflows/cd.yml +++ b/.github/workflows/cd.yml @@ -48,19 +48,19 @@ jobs: build_type: Debug shared_libs: ON - name: 'Linux static library (Intel)' - os: ubuntu-22.04 + os: ubuntu-24.04 build_type: Release shared_libs: OFF - name: 'Linux shared library (Intel)' - os: ubuntu-22.04 + os: ubuntu-24.04 build_type: Release shared_libs: ON - name: 'Linux static library (ARM)' - os: ubuntu-22.04-arm + os: ubuntu-24.04-arm build_type: Release shared_libs: OFF - name: 'Linux shared library (ARM)' - os: ubuntu-22.04-arm + os: ubuntu-24.04-arm build_type: Release shared_libs: ON - name: 'macOS static library (Intel)' @@ -137,9 +137,9 @@ jobs: os: windows-11-arm arch: amd64_arm64 - name: 'Linux Python wheels (Intel)' - os: ubuntu-22.04 + os: ubuntu-24.04 - name: 'Linux Python wheels (ARM)' - os: ubuntu-22.04-arm + os: ubuntu-24.04-arm - name: 'macOS Python wheels (Intel)' os: macos-15-intel - name: 'macOS Python wheels (ARM)' @@ -188,7 +188,7 @@ jobs: python_pypi: needs: [python_wheels] name: Publish to PyPI - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 environment: pypi if: ${{ startsWith(github.ref, 'refs/tags/v') }} steps: @@ -202,7 +202,7 @@ jobs: uses: pypa/gh-action-pypi-publish@release/v1 webassembly: name: WebAssembly - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 env: BUILDCACHE_ACCURACY: STRICT BUILDCACHE_COMPRESS_FORMAT: ZSTD diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ecdbad144..6c91bda57 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -72,7 +72,7 @@ jobs: install_uninstall_and_package: ON copy_dll: ON - name: 'Linux static library (Intel)' - os: ubuntu-22.04 + os: ubuntu-24.04 build_type: Release code_analysis: OFF code_coverage: OFF @@ -86,7 +86,7 @@ jobs: install_uninstall_and_package: ON use_install_prefix: ON - name: 'Linux shared library (Intel)' - os: ubuntu-22.04 + os: ubuntu-24.04 build_type: Release code_analysis: OFF code_coverage: OFF @@ -100,7 +100,7 @@ jobs: install_uninstall_and_package: ON use_install_prefix: ON - name: 'Linux static library (ARM)' - os: ubuntu-22.04-arm + os: ubuntu-24.04-arm build_type: Release code_analysis: OFF code_coverage: OFF @@ -114,7 +114,7 @@ jobs: install_uninstall_and_package: ON use_install_prefix: ON - name: 'Linux shared library (ARM)' - os: ubuntu-22.04-arm + os: ubuntu-24.04-arm build_type: Release code_analysis: OFF code_coverage: OFF @@ -184,7 +184,7 @@ jobs: install_uninstall_and_package: ON use_install_prefix: ON - name: 'JavaScript bindings' - os: ubuntu-22.04 + os: ubuntu-24.04 build_type: Release code_analysis: OFF code_coverage: OFF @@ -210,7 +210,7 @@ jobs: target: python_unit_testing pip_install_test_and_uninstall: ON - name: 'Linux Python bindings' - os: ubuntu-22.04 + os: ubuntu-24.04 build_type: Release code_analysis: OFF code_coverage: OFF @@ -238,7 +238,7 @@ jobs: pip_install_prerequisites: sudo uv pip install --system cmake scikit-build pip_install_test_and_uninstall: ON - name: 'Code formatting' - os: ubuntu-22.04 + os: ubuntu-24.04 build_type: Release code_analysis: OFF code_coverage: OFF @@ -251,7 +251,7 @@ jobs: context: PATH=$GITHUB_WORKSPACE:$PATH target: check_code_formatting - name: 'JavaScript code formatting' - os: ubuntu-22.04 + os: ubuntu-24.04 build_type: Release code_analysis: OFF code_coverage: OFF @@ -263,7 +263,7 @@ jobs: unit_testing: OFF target: javascript_check_code_formatting - name: 'Python code formatting' - os: ubuntu-22.04 + os: ubuntu-24.04 build_type: Release code_analysis: OFF code_coverage: OFF @@ -275,7 +275,7 @@ jobs: unit_testing: OFF target: python_check_code_formatting - name: 'Code analysis' - os: ubuntu-22.04 + os: ubuntu-24.04 build_type: Release code_analysis: ON code_coverage: OFF @@ -300,7 +300,7 @@ jobs: context: PATH=/opt/homebrew/opt/llvm@20/bin:$PATH CC=/opt/homebrew/opt/llvm@20/bin/clang CXX=/opt/homebrew/opt/llvm@20/bin/clang++ target: code_coverage - name: 'Memory checks' - os: ubuntu-22.04 + os: ubuntu-24.04 build_type: Debug code_analysis: OFF code_coverage: OFF @@ -312,7 +312,7 @@ jobs: unit_testing: ON target: memory_checks - name: 'Documentation' - os: ubuntu-22.04 + os: ubuntu-24.04 build_type: Release code_analysis: OFF code_coverage: OFF @@ -487,7 +487,7 @@ jobs: run: uv pip uninstall --system libopencor spell_check: name: Spell check - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 steps: - name: Set the timezone to New Zealand uses: szenius/set-timezone@v2.0 From edf4e9966ee46345baed7d7c9482f46accb9b044 Mon Sep 17 00:00:00 2001 From: Alan Garny Date: Tue, 14 Apr 2026 20:03:28 +1200 Subject: [PATCH 4/5] libCellML: upgraded to commit 6c970b7. --- cmake/packages.cmake | 2 +- src/3rdparty/libCellML/CMakeLists.txt | 20 ++++++++++---------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/cmake/packages.cmake b/cmake/packages.cmake index 4ba604e7a..a5843ab55 100644 --- a/cmake/packages.cmake +++ b/cmake/packages.cmake @@ -193,7 +193,7 @@ function(retrieve_package PACKAGE_NAME PACKAGE_VERSION PACKAGE_REPOSITORY RELEAS set(PACKAGE_URL "https://github.com/opencor/${PACKAGE_REPOSITORY}/releases/download/${RELEASE_TAG}/${PACKAGE_FILE}") if("${PACKAGE_NAME}" STREQUAL "libCellML") - set(PACKAGE_URL "https://github.com/agarny/${PACKAGE_REPOSITORY}/releases/download/8cfa98e/${PACKAGE_FILE}") + set(PACKAGE_URL "https://github.com/agarny/${PACKAGE_REPOSITORY}/releases/download/6c970b7/${PACKAGE_FILE}") endif() set(ATTEMPT 1) diff --git a/src/3rdparty/libCellML/CMakeLists.txt b/src/3rdparty/libCellML/CMakeLists.txt index cbfb4c7df..cf6f489d0 100644 --- a/src/3rdparty/libCellML/CMakeLists.txt +++ b/src/3rdparty/libCellML/CMakeLists.txt @@ -34,49 +34,49 @@ if(LIBOPENCOR_PREBUILT_LIBCELLML) if(EMSCRIPTEN) retrieve_package(${PACKAGE_NAME} ${PACKAGE_VERSION} ${PACKAGE_REPOSITORY} ${RELEASE_TAG} - 45feae9508ee694b27f813b43ede20b29521d1d5) + 5cb4721d595594e82506c2b100642f34a7426e67) else() if(WIN32) if(RELEASE_MODE) if(INTEL_MODE) retrieve_package(${PACKAGE_NAME} ${PACKAGE_VERSION} ${PACKAGE_REPOSITORY} ${RELEASE_TAG} - 52a5e21ec7c83526853175cfc996631bebbbc22d) + 727b7dc43a9f125965105d340be0d5da3b0ca107) else() retrieve_package(${PACKAGE_NAME} ${PACKAGE_VERSION} ${PACKAGE_REPOSITORY} ${RELEASE_TAG} - 17a4405f8ce5dec66cd18eb881335a882de36e70) + 8efb6f27fb2487cae75e4f2001058e987084e520) endif() else() if(INTEL_MODE) retrieve_package(${PACKAGE_NAME} ${PACKAGE_VERSION} ${PACKAGE_REPOSITORY} ${RELEASE_TAG} - 49da1cc047be6caace7e011e71aa28acf11f77b0) + e65148844e68d800f6542a1aaf9e1803f8abb10f) else() retrieve_package(${PACKAGE_NAME} ${PACKAGE_VERSION} ${PACKAGE_REPOSITORY} ${RELEASE_TAG} - eea3705a481e9b703d544b5bb8c438d2cc25c0bb) + 89a0a89adba941858aa269e0ee1ca88f385c01e3) endif() endif() elseif(APPLE) if(INTEL_MODE) retrieve_package(${PACKAGE_NAME} ${PACKAGE_VERSION} ${PACKAGE_REPOSITORY} ${RELEASE_TAG} - 4abb7649dd9410bdc8ee466b28fbab33d12cadbe) + a825eaa30456ae131d146174b4575d247173a603) else() retrieve_package(${PACKAGE_NAME} ${PACKAGE_VERSION} ${PACKAGE_REPOSITORY} ${RELEASE_TAG} - 2a49cdf98ecb277b32976bf7db1c4831d408bb8d) + 8afff08fe254df1e1599a8b2aae5c1061de06728) endif() else() if(INTEL_MODE) retrieve_package(${PACKAGE_NAME} ${PACKAGE_VERSION} ${PACKAGE_REPOSITORY} ${RELEASE_TAG} - 6253f25c88f6e88d316a8c9b04e0096aaeb387b1) + a6972bf4124a2fd24bc4323383e1f4af5a0e1a05) else() retrieve_package(${PACKAGE_NAME} ${PACKAGE_VERSION} ${PACKAGE_REPOSITORY} ${RELEASE_TAG} - bc9b411b9863cea950186edead96b8ef739fc6a1) + e973eabfc82f250fe1f4512f43d16091e61146fc) endif() endif() endif() @@ -86,7 +86,7 @@ elseif(NOT ONLY_BUILD_JAVASCRIPT_THIRD_PARTY_LIBRARIES) build_package(${PACKAGE_NAME} URL # https://github.com/opencor/${PACKAGE_REPOSITORY}/archive/refs/tags/${RELEASE_TAG}.tar.gz - https://github.com/agarny/${PACKAGE_REPOSITORY}/archive/refs/tags/8cfa98e.tar.gz + https://github.com/agarny/${PACKAGE_REPOSITORY}/archive/refs/tags/6c970b7.tar.gz DOWNLOAD_NO_PROGRESS ON CMAKE_ARGS -DBINDINGS_PYTHON=OFF From a01670cdd92bcc42bf1aee76c0c1dd2429f3186b Mon Sep 17 00:00:00 2001 From: Alan Garny Date: Wed, 15 Apr 2026 16:55:22 +1200 Subject: [PATCH 5/5] Improvements to the overall speed and memory use of libOpenCOR. --- .codespellexclude | 1 + src/CMakeLists.txt | 6 + src/api/libopencor/file.h | 18 +- src/api/libopencor/issue.h | 4 +- src/api/libopencor/logger.h | 12 +- src/api/libopencor/sedbase.h | 2 +- src/api/libopencor/sedchange.h | 2 +- src/api/libopencor/sedchangeattribute.h | 6 +- src/api/libopencor/seddocument.h | 12 +- src/api/libopencor/sedinstance.h | 4 +- src/api/libopencor/sedinstancetask.h | 48 +- src/api/libopencor/sedmodel.h | 6 +- src/api/libopencor/sedsimulation.h | 4 +- src/api/libopencor/sedtask.h | 4 +- src/api/libopencor/solver.h | 4 +- src/api/libopencor/version.h | 14 +- src/bindings/javascript/file.cpp | 2 +- src/file/file.cpp | 66 +-- src/file/file_p.h | 19 +- src/file/filemanager.cpp | 8 +- src/logger/issue.cpp | 45 +- src/logger/issue_p.h | 5 +- src/logger/logger.cpp | 40 +- src/logger/logger_p.h | 12 +- src/misc/compiler.cpp | 79 +++- src/misc/utils.cpp | 56 ++- src/misc/utils.h | 6 +- src/sed/sedbase.cpp | 4 +- src/sed/sedbase_p.h | 2 +- src/sed/sedchange.cpp | 4 +- src/sed/sedchange_p.h | 2 +- src/sed/sedchangeattribute.cpp | 68 ++- src/sed/sedchangeattribute_p.h | 6 +- src/sed/seddocument.cpp | 55 ++- src/sed/seddocument_p.h | 12 +- src/sed/sedinstance.cpp | 16 +- src/sed/sedinstance_p.h | 4 +- src/sed/sedinstancetask.cpp | 418 ++++++++++++------ src/sed/sedinstancetask_p.h | 54 ++- src/sed/sedmodel.cpp | 16 +- src/sed/sedmodel_p.h | 6 +- src/sed/sedsimulation.cpp | 33 +- src/sed/sedsimulation_p.h | 4 +- src/sed/sedtask.cpp | 27 +- src/sed/sedtask_p.h | 4 +- src/solver/solver.cpp | 8 +- src/solver/solver_p.h | 4 +- src/solver/solvercvode.cpp | 253 ++++++++++- src/solver/solverkinsol.cpp | 115 ++++- src/solver/solverodefixedstep.cpp | 44 +- src/support/cellml/cellmlfile.cpp | 6 +- src/support/cellml/cellmlfileruntime.cpp | 61 ++- src/support/combine/combinearchive.cpp | 51 ++- src/support/combine/combinearchive.h | 10 +- src/support/combine/combinearchive_p.h | 11 +- src/support/sedml/sedmlfile.cpp | 68 ++- src/version.cpp | 42 +- tests/api/file/basictests.cpp | 4 +- tests/api/file/coveragetests.cpp | 2 +- tests/api/sed/coveragetests.cpp | 8 +- tests/api/sed/instancetests.cpp | 14 +- tests/api/sed/serialisetests.cpp | 54 +-- tests/api/solver/coveragetests.cpp | 2 +- tests/api/solver/cvodetests.cpp | 76 ++-- tests/api/solver/forwardeulertests.cpp | 4 +- .../api/solver/fourthorderrungekuttatests.cpp | 4 +- tests/api/solver/heuntests.cpp | 4 +- tests/api/solver/kinsoltests.cpp | 36 +- tests/api/solver/odemodel.cpp | 4 +- .../api/solver/secondorderrungekuttatests.cpp | 4 +- tests/install/src/main.cpp | 4 +- tests/misc/failingsimulationtests.cpp | 2 +- tests/utils.cpp | 2 +- 73 files changed, 1445 insertions(+), 672 deletions(-) diff --git a/.codespellexclude b/.codespellexclude index 0bc6464b6..0f7b3ac5e 100644 --- a/.codespellexclude +++ b/.codespellexclude @@ -7,3 +7,4 @@ mErrors.clear(); if (pIndex >= mErrors.size()) { return mErrors[pIndex]; + mErrors.push_back(std::move(issue)); diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 2ec2fe08e..e53e2cc43 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -45,6 +45,12 @@ if(BUILDING_USING_MSVC) endif() endif() +# Prefer maximum optimisation for native non-MSVC release builds. + +if(RELEASE_MODE AND NOT BUILDING_USING_MSVC) + replace_compiler_flag("-O2" "-O3") +endif() + # Build our different third-party libraries. add_subdirectory(3rdparty) diff --git a/src/api/libopencor/file.h b/src/api/libopencor/file.h index d0758c5f0..0e5731d4f 100644 --- a/src/api/libopencor/file.h +++ b/src/api/libopencor/file.h @@ -119,7 +119,7 @@ class LIBOPENCOR_EXPORT File: public Logger * @return The file name, as a @c std::string, of this file. */ - std::string fileName() const; + const std::string &fileName() const; /** * @brief Get the URL of this file. @@ -132,7 +132,7 @@ class LIBOPENCOR_EXPORT File: public Logger * @return The URL, as a @c std::string, of this file. */ - std::string url() const; + const std::string &url() const; /** * @brief Get the path of this file. @@ -145,7 +145,7 @@ class LIBOPENCOR_EXPORT File: public Logger * @return The path, as a @c std::string, of this file. */ - std::string path() const; + const std::string &path() const; /** * @brief Get the contents of this file. @@ -155,7 +155,7 @@ class LIBOPENCOR_EXPORT File: public Logger * @return The contents, as an @ref UnsignedChars, of this file. */ - UnsignedChars contents(); + const UnsignedChars &contents(); /** * @brief Set the contents of this file. @@ -195,7 +195,7 @@ class LIBOPENCOR_EXPORT File: public Logger * @return The child file names, as a @ref Strings. */ - Strings childFileNames() const; + const Strings &childFileNames() const; /** * @brief Return the child files. @@ -205,7 +205,7 @@ class LIBOPENCOR_EXPORT File: public Logger * @return The child files, as a @ref FilePtrs. */ - FilePtrs childFiles() const; + const FilePtrs &childFiles() const; /** * @brief Return a child file. @@ -217,7 +217,7 @@ class LIBOPENCOR_EXPORT File: public Logger * @return The file, as a @ref FilePtr, if it is a child file of this file, @c nullptr otherwise. */ - FilePtr childFile(size_t pIndex) const; + const FilePtr &childFile(size_t pIndex) const; /** * @brief Return a child file. @@ -230,9 +230,9 @@ class LIBOPENCOR_EXPORT File: public Logger */ #ifdef __EMSCRIPTEN__ - FilePtr childFileFromFileName(const std::string &pFileName) const; + const FilePtr &childFileFromFileName(const std::string &pFileName) const; #else - FilePtr childFile(const std::string &pFileName) const; + const FilePtr &childFile(const std::string &pFileName) const; #endif private: diff --git a/src/api/libopencor/issue.h b/src/api/libopencor/issue.h index 5f6ce8253..84152c7dd 100644 --- a/src/api/libopencor/issue.h +++ b/src/api/libopencor/issue.h @@ -76,7 +76,7 @@ class LIBOPENCOR_EXPORT Issue * @return The type of this issue as a @c std::string. */ - std::string typeAsString() const; + const std::string &typeAsString() const; /** * @brief Get the description of this issue. @@ -86,7 +86,7 @@ class LIBOPENCOR_EXPORT Issue * @return The @c std::string description of this issue. */ - std::string description() const; + const std::string &description() const; private: class Impl; /**< Forward declaration of the implementation class, @private. */ diff --git a/src/api/libopencor/logger.h b/src/api/libopencor/logger.h index 4025d52fc..5ec526f7a 100644 --- a/src/api/libopencor/logger.h +++ b/src/api/libopencor/logger.h @@ -73,7 +73,7 @@ class LIBOPENCOR_EXPORT Logger * @return The issues, as an @ref IssuePtrs. */ - IssuePtrs issues() const; + const IssuePtrs &issues() const; /** * @brief Return an issue. @@ -85,7 +85,7 @@ class LIBOPENCOR_EXPORT Logger * @return The issue, as an @ref IssuePtr, if the index is valid, @c nullptr otherwise. */ - IssuePtr issue(size_t pIndex) const; + const IssuePtr &issue(size_t pIndex) const; /** * @brief Return whether there are some errors. @@ -115,7 +115,7 @@ class LIBOPENCOR_EXPORT Logger * @return The errors, as a @ref IssuePtrs of type @ref Issue::Type::ERROR. */ - IssuePtrs errors() const; + const IssuePtrs &errors() const; /** * @brief Return an error. @@ -127,7 +127,7 @@ class LIBOPENCOR_EXPORT Logger * @return The error, as an @ref IssuePtr, if the index is valid, @c nullptr otherwise. */ - IssuePtr error(size_t pIndex) const; + const IssuePtr &error(size_t pIndex) const; /** * @brief Return whether there are some warnings. @@ -157,7 +157,7 @@ class LIBOPENCOR_EXPORT Logger * @return The warnings, as a @ref IssuePtrs of type @ref Issue::Type::WARNING. */ - IssuePtrs warnings() const; + const IssuePtrs &warnings() const; /** * @brief Return a warning. @@ -169,7 +169,7 @@ class LIBOPENCOR_EXPORT Logger * @return The warning, as an @ref IssuePtr, if the index is valid, @c nullptr otherwise. */ - IssuePtr warning(size_t pIndex) const; + const IssuePtr &warning(size_t pIndex) const; protected: class Impl; /**< Forward declaration of the implementation class, @private. */ diff --git a/src/api/libopencor/sedbase.h b/src/api/libopencor/sedbase.h index 7b3f1c86f..213a60604 100644 --- a/src/api/libopencor/sedbase.h +++ b/src/api/libopencor/sedbase.h @@ -49,7 +49,7 @@ class LIBOPENCOR_EXPORT SedBase: public Logger * @return The id as a @c std::string. */ - std::string id() const; + const std::string &id() const; /** * @brief Set the id. diff --git a/src/api/libopencor/sedchange.h b/src/api/libopencor/sedchange.h index c2421a033..62f7a62ad 100644 --- a/src/api/libopencor/sedchange.h +++ b/src/api/libopencor/sedchange.h @@ -49,7 +49,7 @@ class LIBOPENCOR_EXPORT SedChange: public SedBase * @return The target as a @c std::string. */ - std::string target() const; + const std::string &target() const; protected: class Impl; /**< Forward declaration of the implementation class, @private. */ diff --git a/src/api/libopencor/sedchangeattribute.h b/src/api/libopencor/sedchangeattribute.h index 7c6c98eff..79e7fa20d 100644 --- a/src/api/libopencor/sedchangeattribute.h +++ b/src/api/libopencor/sedchangeattribute.h @@ -71,7 +71,7 @@ class LIBOPENCOR_EXPORT SedChangeAttribute: public SedChange * @return The name of the component as a @c std::string. */ - std::string componentName() const; + const std::string &componentName() const; /** * @brief Set the name of the component. @@ -91,7 +91,7 @@ class LIBOPENCOR_EXPORT SedChangeAttribute: public SedChange * @return The name of the variable as a @c std::string. */ - std::string variableName() const; + const std::string &variableName() const; /** * @brief Set the name of the variable. @@ -111,7 +111,7 @@ class LIBOPENCOR_EXPORT SedChangeAttribute: public SedChange * @return The new value as a @c std::string. */ - std::string newValue() const; + const std::string &newValue() const; /** * @brief Set the new value. diff --git a/src/api/libopencor/seddocument.h b/src/api/libopencor/seddocument.h index 128fcb96b..ed61021f6 100644 --- a/src/api/libopencor/seddocument.h +++ b/src/api/libopencor/seddocument.h @@ -118,7 +118,7 @@ class LIBOPENCOR_EXPORT SedDocument: public Logger * @return The models, as a @ref SedModelPtrs. */ - SedModelPtrs models() const; + const SedModelPtrs &models() const; /** * @brief Return the model at the given index. @@ -130,7 +130,7 @@ class LIBOPENCOR_EXPORT SedDocument: public Logger * @return The model as a @ref SedModelPtr, if the index is valid, @c nullptr otherwise. */ - SedModelPtr model(size_t pIndex) const; + const SedModelPtr &model(size_t pIndex) const; /** * @brief Add the model to this simulation experiment description. @@ -193,7 +193,7 @@ class LIBOPENCOR_EXPORT SedDocument: public Logger * @return The simulations, as a @ref SedSimulationPtrs. */ - SedSimulationPtrs simulations() const; + const SedSimulationPtrs &simulations() const; /** * @brief Return the simulation at the given index. @@ -205,7 +205,7 @@ class LIBOPENCOR_EXPORT SedDocument: public Logger * @return The simulation as a @ref SedSimulationPtr, if the index is valid, @c nullptr otherwise. */ - SedSimulationPtr simulation(size_t pIndex) const; + const SedSimulationPtr &simulation(size_t pIndex) const; /** * @brief Add the simulation to this simulation experiment description. @@ -268,7 +268,7 @@ class LIBOPENCOR_EXPORT SedDocument: public Logger * @return The tasks, as a @ref SedAbstractTaskPtrs. */ - SedAbstractTaskPtrs tasks() const; + const SedAbstractTaskPtrs &tasks() const; /** * @brief Return the task at the given index. @@ -280,7 +280,7 @@ class LIBOPENCOR_EXPORT SedDocument: public Logger * @return The task as a @ref SedAbstractTaskPtr, if the index is valid, @c nullptr otherwise. */ - SedAbstractTaskPtr task(size_t pIndex) const; + const SedAbstractTaskPtr &task(size_t pIndex) const; /** * @brief Add the task to this simulation experiment description. diff --git a/src/api/libopencor/sedinstance.h b/src/api/libopencor/sedinstance.h index 9343aee75..9eb311627 100644 --- a/src/api/libopencor/sedinstance.h +++ b/src/api/libopencor/sedinstance.h @@ -81,7 +81,7 @@ class LIBOPENCOR_EXPORT SedInstance: public Logger * @return The tasks, as a @ref SedInstanceTaskPtrs. */ - SedInstanceTaskPtrs tasks() const; + const SedInstanceTaskPtrs &tasks() const; /** * @brief Return the task at the given index. @@ -93,7 +93,7 @@ class LIBOPENCOR_EXPORT SedInstance: public Logger * @return The task as a @ref SedInstanceTaskPtr, if the index is valid, @c nullptr otherwise. */ - SedInstanceTaskPtr task(size_t pIndex) const; + const SedInstanceTaskPtr &task(size_t pIndex) const; private: class Impl; /**< Forward declaration of the implementation class, @private. */ diff --git a/src/api/libopencor/sedinstancetask.h b/src/api/libopencor/sedinstancetask.h index 47e4b3c6f..6671aaa98 100644 --- a/src/api/libopencor/sedinstancetask.h +++ b/src/api/libopencor/sedinstancetask.h @@ -54,10 +54,10 @@ class LIBOPENCOR_EXPORT SedInstanceTask: public Logger * @return The values of the variable of integration. */ - Doubles voi() const; + const Doubles &voi() const; #ifdef __EMSCRIPTEN__ - emscripten::val voiAsArray() const; + const emscripten::val &voiAsArray() const; #endif /** @@ -68,7 +68,7 @@ class LIBOPENCOR_EXPORT SedInstanceTask: public Logger * @return The name of the variable of integration. */ - std::string voiName() const; + const std::string &voiName() const; /** * @brief Get the unit of the variable of integration. @@ -78,7 +78,7 @@ class LIBOPENCOR_EXPORT SedInstanceTask: public Logger * @return The unit of the variable of integration. */ - std::string voiUnit() const; + const std::string &voiUnit() const; /** * @brief Get the number of states. @@ -100,10 +100,10 @@ class LIBOPENCOR_EXPORT SedInstanceTask: public Logger * @return The values of the state, as a @ref Doubles, if the index is valid, an empty vector otherwise. */ - Doubles state(size_t pIndex) const; + const Doubles &state(size_t pIndex) const; #ifdef __EMSCRIPTEN__ - emscripten::val stateAsArray(size_t pIndex) const; + const emscripten::val &stateAsArray(size_t pIndex) const; #endif /** @@ -116,7 +116,7 @@ class LIBOPENCOR_EXPORT SedInstanceTask: public Logger * @return The name of the state, as a @c std::string, if the index is valid, an empty string otherwise. */ - std::string stateName(size_t pIndex) const; + const std::string &stateName(size_t pIndex) const; /** * @brief Get the unit of the state. @@ -128,7 +128,7 @@ class LIBOPENCOR_EXPORT SedInstanceTask: public Logger * @return The unit of the state, as a @c std::string, if the index is valid, an empty vector otherwise. */ - std::string stateUnit(size_t pIndex) const; + const std::string &stateUnit(size_t pIndex) const; /** * @brief Get the number of rates. @@ -150,10 +150,10 @@ class LIBOPENCOR_EXPORT SedInstanceTask: public Logger * @return The values of the rate, as a @ref Doubles, if the index is valid, an empty vector otherwise. */ - Doubles rate(size_t pIndex) const; + const Doubles &rate(size_t pIndex) const; #ifdef __EMSCRIPTEN__ - emscripten::val rateAsArray(size_t pIndex) const; + const emscripten::val &rateAsArray(size_t pIndex) const; #endif /** @@ -166,7 +166,7 @@ class LIBOPENCOR_EXPORT SedInstanceTask: public Logger * @return The name of the rate, as a @c std::string, if the index is valid, an empty string otherwise. */ - std::string rateName(size_t pIndex) const; + const std::string &rateName(size_t pIndex) const; /** * @brief Get the unit of the rate. @@ -178,7 +178,7 @@ class LIBOPENCOR_EXPORT SedInstanceTask: public Logger * @return The unit of the rate, as a @c std::string, if the index is valid, an empty string otherwise. */ - std::string rateUnit(size_t pIndex) const; + const std::string &rateUnit(size_t pIndex) const; /** * @brief Get the number of constants. @@ -200,10 +200,10 @@ class LIBOPENCOR_EXPORT SedInstanceTask: public Logger * @return The values of the constant, as a @ref Doubles, if the index is valid, an empty vector otherwise. */ - Doubles constant(size_t pIndex) const; + const Doubles &constant(size_t pIndex) const; #ifdef __EMSCRIPTEN__ - emscripten::val constantAsArray(size_t pIndex) const; + const emscripten::val &constantAsArray(size_t pIndex) const; #endif /** @@ -216,7 +216,7 @@ class LIBOPENCOR_EXPORT SedInstanceTask: public Logger * @return The name of the constant, as a @c std::string, if the index is valid, an empty string otherwise. */ - std::string constantName(size_t pIndex) const; + const std::string &constantName(size_t pIndex) const; /** * @brief Get the unit of the constant. @@ -228,7 +228,7 @@ class LIBOPENCOR_EXPORT SedInstanceTask: public Logger * @return The unit of the constant, as a @c std::string, if the index is valid, an empty string otherwise. */ - std::string constantUnit(size_t pIndex) const; + const std::string &constantUnit(size_t pIndex) const; /** * @brief Get the number of computed constants. @@ -250,10 +250,10 @@ class LIBOPENCOR_EXPORT SedInstanceTask: public Logger * @return The values of the computed constant, as a @ref Doubles, if the index is valid, an empty vector otherwise. */ - Doubles computedConstant(size_t pIndex) const; + const Doubles &computedConstant(size_t pIndex) const; #ifdef __EMSCRIPTEN__ - emscripten::val computedConstantAsArray(size_t pIndex) const; + const emscripten::val &computedConstantAsArray(size_t pIndex) const; #endif /** @@ -266,7 +266,7 @@ class LIBOPENCOR_EXPORT SedInstanceTask: public Logger * @return The name of the computed constant, as a @c std::string, if the index is valid, an empty string otherwise. */ - std::string computedConstantName(size_t pIndex) const; + const std::string &computedConstantName(size_t pIndex) const; /** * @brief Get the unit of the computed constant. @@ -278,7 +278,7 @@ class LIBOPENCOR_EXPORT SedInstanceTask: public Logger * @return The unit of the computed constant, as a @c std::string, if the index is valid, an empty string otherwise. */ - std::string computedConstantUnit(size_t pIndex) const; + const std::string &computedConstantUnit(size_t pIndex) const; /** * @brief Get the number of algebraic variables. @@ -300,10 +300,10 @@ class LIBOPENCOR_EXPORT SedInstanceTask: public Logger * @return The values of the algebraic variable, as a @c Doubles, if the index is valid, an empty vector otherwise. */ - Doubles algebraicVariable(size_t pIndex) const; + const Doubles &algebraicVariable(size_t pIndex) const; #ifdef __EMSCRIPTEN__ - emscripten::val algebraicVariableAsArray(size_t pIndex) const; + const emscripten::val &algebraicVariableAsArray(size_t pIndex) const; #endif /** @@ -317,7 +317,7 @@ class LIBOPENCOR_EXPORT SedInstanceTask: public Logger * otherwise. */ - std::string algebraicVariableName(size_t pIndex) const; + const std::string &algebraicVariableName(size_t pIndex) const; /** * @brief Get the unit of the algebraic variable. @@ -330,7 +330,7 @@ class LIBOPENCOR_EXPORT SedInstanceTask: public Logger * otherwise. */ - std::string algebraicVariableUnit(size_t pIndex) const; + const std::string &algebraicVariableUnit(size_t pIndex) const; private: class Impl; /**< Forward declaration of the implementation class, @private. */ diff --git a/src/api/libopencor/sedmodel.h b/src/api/libopencor/sedmodel.h index b5ebda12f..d5e362afc 100644 --- a/src/api/libopencor/sedmodel.h +++ b/src/api/libopencor/sedmodel.h @@ -74,7 +74,7 @@ class LIBOPENCOR_EXPORT SedModel: public SedBase * @return The file, as a smart pointer to a @ref File object. */ - FilePtr file() const; + const FilePtr &file() const; /** * @brief Return whether there are some changes. @@ -104,7 +104,7 @@ class LIBOPENCOR_EXPORT SedModel: public SedBase * @return The changes, as a @ref SedChangePtrs. */ - SedChangePtrs changes() const; + const SedChangePtrs &changes() const; /** * @brief Return the change at the given index. @@ -116,7 +116,7 @@ class LIBOPENCOR_EXPORT SedModel: public SedBase * @return The change as a @ref SedChangePtr, if the index is valid, @c nullptr otherwise. */ - SedChangePtr change(size_t pIndex) const; + const SedChangePtr &change(size_t pIndex) const; /** * @brief Add the change to this model. diff --git a/src/api/libopencor/sedsimulation.h b/src/api/libopencor/sedsimulation.h index dd1692d01..1b8dc81ed 100644 --- a/src/api/libopencor/sedsimulation.h +++ b/src/api/libopencor/sedsimulation.h @@ -50,7 +50,7 @@ class LIBOPENCOR_EXPORT SedSimulation: public SedBase * @return The ODE solver for this simulation. */ - SolverOdePtr odeSolver() const; + const SolverOdePtr &odeSolver() const; /** * @brief Set the ODE solver for this simulation. @@ -70,7 +70,7 @@ class LIBOPENCOR_EXPORT SedSimulation: public SedBase * @return The NLA solver for this simulation. */ - SolverNlaPtr nlaSolver() const; + const SolverNlaPtr &nlaSolver() const; /** * @brief Set the NLA solver for this simulation. diff --git a/src/api/libopencor/sedtask.h b/src/api/libopencor/sedtask.h index ffef663fc..9d6de8eb8 100644 --- a/src/api/libopencor/sedtask.h +++ b/src/api/libopencor/sedtask.h @@ -71,7 +71,7 @@ class LIBOPENCOR_EXPORT SedTask: public SedAbstractTask * @return The model, as a @ref SedModelPtr, used by this task. */ - SedModelPtr model() const; + const SedModelPtr &model() const; /** * @brief Set the model to be used by this task. @@ -91,7 +91,7 @@ class LIBOPENCOR_EXPORT SedTask: public SedAbstractTask * @return The simulation, as a @ref SedSimulationPtr, used by this task. */ - SedSimulationPtr simulation() const; + const SedSimulationPtr &simulation() const; /** * @brief Set the simulation to be used by this task. diff --git a/src/api/libopencor/solver.h b/src/api/libopencor/solver.h index 2a8efda65..793848763 100644 --- a/src/api/libopencor/solver.h +++ b/src/api/libopencor/solver.h @@ -73,7 +73,7 @@ class LIBOPENCOR_EXPORT Solver: public Logger * @return The (KiSAO) id, as a @c std::string, of the solver. */ - std::string id() const; + const std::string &id() const; /** * @brief Get the name of the solver. @@ -83,7 +83,7 @@ class LIBOPENCOR_EXPORT Solver: public Logger * @return The name, as a @c std::string, of the solver. */ - std::string name() const; + const std::string &name() const; protected: class Impl; /**< Forward declaration of the implementation class, @private. */ diff --git a/src/api/libopencor/version.h b/src/api/libopencor/version.h index 83a5ddb51..4dde8283d 100644 --- a/src/api/libopencor/version.h +++ b/src/api/libopencor/version.h @@ -40,7 +40,7 @@ uint64_t LIBOPENCOR_EXPORT version(); * @return A string that represents the version of libOpenCOR. */ -std::string LIBOPENCOR_EXPORT versionString(); +const std::string LIBOPENCOR_EXPORT &versionString(); /** * Return the version of Clang as a number. @@ -58,7 +58,7 @@ unsigned int LIBOPENCOR_EXPORT clangVersion(); * @return A string that represents the version of Clang. */ -std::string LIBOPENCOR_EXPORT clangVersionString(); +const std::string LIBOPENCOR_EXPORT &clangVersionString(); /** * Return the version of libCellML as a number. @@ -76,7 +76,7 @@ unsigned int LIBOPENCOR_EXPORT libcellmlVersion(); * @return A string that represents the version of libCellML. */ -std::string LIBOPENCOR_EXPORT libcellmlVersionString(); +const std::string LIBOPENCOR_EXPORT &libcellmlVersionString(); /** * Return the version of libCOMBINE as a number. @@ -94,7 +94,7 @@ unsigned int LIBOPENCOR_EXPORT libcombineVersion(); * @return A string that represents the version of libCOMBINE. */ -std::string LIBOPENCOR_EXPORT libcombineVersionString(); +const std::string LIBOPENCOR_EXPORT &libcombineVersionString(); #ifndef __EMSCRIPTEN__ /** @@ -113,7 +113,7 @@ unsigned int LIBOPENCOR_EXPORT libcurlVersion(); * @return A string that represents the version of libcurl. */ -std::string LIBOPENCOR_EXPORT libcurlVersionString(); +const std::string LIBOPENCOR_EXPORT &libcurlVersionString(); #endif /** @@ -132,7 +132,7 @@ unsigned int LIBOPENCOR_EXPORT libsedmlVersion(); * @return A string that represents the version of libSEDML. */ -std::string LIBOPENCOR_EXPORT libsedmlVersionString(); +const std::string LIBOPENCOR_EXPORT &libsedmlVersionString(); /** * Return the version of LLVM as a number. @@ -150,7 +150,7 @@ unsigned int LIBOPENCOR_EXPORT llvmVersion(); * @return A string that represents the version of LLVM. */ -std::string LIBOPENCOR_EXPORT llvmVersionString(); +const std::string LIBOPENCOR_EXPORT &llvmVersionString(); /** * Return the version of SUNDIALS as a number. diff --git a/src/bindings/javascript/file.cpp b/src/bindings/javascript/file.cpp index 2ea382f5f..737c9cc2e 100644 --- a/src/bindings/javascript/file.cpp +++ b/src/bindings/javascript/file.cpp @@ -33,7 +33,7 @@ void fileApi() .property("url", &libOpenCOR::File::url) .property("path", &libOpenCOR::File::path) .function("contents", emscripten::optional_override([](const libOpenCOR::FilePtr &pThis) { - auto contents {pThis->contents()}; + const auto &contents {pThis->contents()}; auto size = contents.size(); if (size == 0) { diff --git a/src/file/file.cpp b/src/file/file.cpp index 5884af219..a00f4084e 100644 --- a/src/file/file.cpp +++ b/src/file/file.cpp @@ -62,6 +62,8 @@ File::Impl::Impl(const std::string &pFileNameOrUrl, bool pRetrieveContents) mFilePath = stringToPath("/some/path/file"); } #endif + + mFileName = pathToString(mFilePath); } File::Impl::~Impl() @@ -127,22 +129,22 @@ File::Type File::Impl::type() const return mType; } -std::string File::Impl::fileName() const +const std::string &File::Impl::fileName() const { - return pathToString(mFilePath); + return mFileName; } -std::string File::Impl::url() const +const std::string &File::Impl::url() const { return mUrl; } -std::string File::Impl::path() const +const std::string &File::Impl::path() const { - return mUrl.empty() ? fileName() : mUrl; + return mUrl.empty() ? mFileName : mUrl; } -UnsignedChars File::Impl::contents() +const UnsignedChars &File::Impl::contents() { #ifndef __EMSCRIPTEN__ // Retrieve the contents of the file, if needed. @@ -181,48 +183,56 @@ size_t File::Impl::childFileCount() const return 0; } -Strings File::Impl::childFileNames() const +const Strings &File::Impl::childFileNames() const { + static const Strings NO_STRINGS; + if (mType == Type::COMBINE_ARCHIVE) { return mCombineArchive->fileNames(); } - return {}; + return NO_STRINGS; } -FilePtrs File::Impl::childFiles() const +const FilePtrs &File::Impl::childFiles() const { + static const FilePtrs NO_FILE_PTRS; + if (mType == Type::COMBINE_ARCHIVE) { return mCombineArchive->files(); } - return {}; + return NO_FILE_PTRS; } -FilePtr File::Impl::childFile(size_t pIndex) const +const FilePtr &File::Impl::childFile(size_t pIndex) const { + static const FilePtr NO_FILE_PTR; + if (mType == Type::COMBINE_ARCHIVE) { if (pIndex >= mCombineArchive->fileCount()) { - return {}; + return NO_FILE_PTR; } return mCombineArchive->file(pIndex); } - return {}; + return NO_FILE_PTR; } #ifdef __EMSCRIPTEN__ -FilePtr File::Impl::childFileFromFileName(const std::string &pFileName) const +const FilePtr &File::Impl::childFileFromFileName(const std::string &pFileName) const #else -FilePtr File::Impl::childFile(const std::string &pFileName) const +const FilePtr &File::Impl::childFile(const std::string &pFileName) const #endif { + static const FilePtr NO_FILE_PTR; + if (mType == Type::COMBINE_ARCHIVE) { return mCombineArchive->file(pFileName); } - return {}; + return NO_FILE_PTR; } File::File(const std::string &pFileNameOrUrl, bool pRetrieveContents) @@ -258,11 +268,11 @@ FilePtr File::create(const std::string &pFileNameOrUrl, bool pRetrieveContents) // Check whether the given file name or URL is already managed and if so then return it otherwise create, manage, // and return a new file object. - auto fileManager {FileManager::instance()}; + auto &fileManager {FileManager::instance()}; #ifdef __EMSCRIPTEN__ - auto file {fileManager.fileFromFileNameOrUrl(pFileNameOrUrl)}; + const auto &file {fileManager.fileFromFileNameOrUrl(pFileNameOrUrl)}; #else - auto file {fileManager.file(pFileNameOrUrl)}; + const auto &file {fileManager.file(pFileNameOrUrl)}; #endif if (file != nullptr) { @@ -287,22 +297,22 @@ File::Type File::type() const return pimpl()->type(); } -std::string File::fileName() const +const std::string &File::fileName() const { return pimpl()->fileName(); } -std::string File::url() const +const std::string &File::url() const { return pimpl()->url(); } -std::string File::path() const +const std::string &File::path() const { return pimpl()->path(); } -UnsignedChars File::contents() +const UnsignedChars &File::contents() { return pimpl()->contents(); } @@ -324,25 +334,25 @@ size_t File::childFileCount() const return pimpl()->childFileCount(); } -Strings File::childFileNames() const +const Strings &File::childFileNames() const { return pimpl()->childFileNames(); } -FilePtrs File::childFiles() const +const FilePtrs &File::childFiles() const { return pimpl()->childFiles(); } -FilePtr File::childFile(size_t pIndex) const +const FilePtr &File::childFile(size_t pIndex) const { return pimpl()->childFile(pIndex); } #ifdef __EMSCRIPTEN__ -FilePtr File::childFileFromFileName(const std::string &pFileName) const +const FilePtr &File::childFileFromFileName(const std::string &pFileName) const #else -FilePtr File::childFile(const std::string &pFileName) const +const FilePtr &File::childFile(const std::string &pFileName) const #endif { #ifdef __EMSCRIPTEN__ diff --git a/src/file/file_p.h b/src/file/file_p.h index dbfd69665..9dd0bdae7 100644 --- a/src/file/file_p.h +++ b/src/file/file_p.h @@ -34,6 +34,7 @@ class File::Impl: public Logger::Impl Type mType {Type::UNKNOWN_FILE}; std::filesystem::path mFilePath; + std::string mFileName; std::string mUrl; bool mTypeChecked {false}; @@ -52,22 +53,22 @@ class File::Impl: public Logger::Impl void checkType(const FilePtr &pOwner, bool pResetType = false); Type type() const; - std::string fileName() const; - std::string url() const; - std::string path() const; + const std::string &fileName() const; + const std::string &url() const; + const std::string &path() const; - UnsignedChars contents(); + const UnsignedChars &contents(); void setContents(const UnsignedChars &pContents); bool hasChildFiles() const; size_t childFileCount() const; - Strings childFileNames() const; - FilePtrs childFiles() const; - FilePtr childFile(size_t pIndex) const; + const Strings &childFileNames() const; + const FilePtrs &childFiles() const; + const FilePtr &childFile(size_t pIndex) const; #ifdef __EMSCRIPTEN__ - FilePtr childFileFromFileName(const std::string &pFileName) const; + const FilePtr &childFileFromFileName(const std::string &pFileName) const; #else - FilePtr childFile(const std::string &pFileName) const; + const FilePtr &childFile(const std::string &pFileName) const; #endif }; diff --git a/src/file/filemanager.cpp b/src/file/filemanager.cpp index 8a3c45d43..67a44e2d9 100644 --- a/src/file/filemanager.cpp +++ b/src/file/filemanager.cpp @@ -95,8 +95,10 @@ FilePtrs FileManager::Impl::files() const FilePtr FileManager::Impl::file(size_t pIndex) const { + static const FilePtr NO_FILE_PTR; + if (pIndex >= mFiles.size()) { - return {}; + return NO_FILE_PTR; } return mFiles[pIndex]->shared_from_this(); @@ -108,6 +110,8 @@ FilePtr FileManager::Impl::fileFromFileNameOrUrl(const std::string &pFileNameOrU FilePtr FileManager::Impl::file(const std::string &pFileNameOrUrl) const #endif { + static const FilePtr NO_FILE_PTR; + #if __clang_major__ < 16 auto [tIsLocalFile, tFileNameOrUrl] {retrieveFileInfo(pFileNameOrUrl)}; auto isLocalFile {tIsLocalFile}; @@ -125,7 +129,7 @@ FilePtr FileManager::Impl::file(const std::string &pFileNameOrUrl) const return (*res)->shared_from_this(); } - return {}; + return NO_FILE_PTR; } FileManager &FileManager::instance() diff --git a/src/logger/issue.cpp b/src/logger/issue.cpp index c7349e05a..70dc3916a 100644 --- a/src/logger/issue.cpp +++ b/src/logger/issue.cpp @@ -23,6 +23,24 @@ Issue::Impl::Impl(Type pType, const std::string &pDescription, const std::string , mDescription(pDescription) , mContext(pContext) { + // Check whether we have some context to add to the description. + + if (!mContext.empty()) { + mDescriptionWithContext.reserve(mContext.size() + 2 + mDescription.size()); // NOLINT + + mDescriptionWithContext.insert(0, mDescription); + +#ifndef CODE_COVERAGE_ENABLED + if (std::isupper(mDescriptionWithContext[0]) != 0) { +#endif + mDescriptionWithContext[0] = static_cast(std::tolower(mDescriptionWithContext[0])); +#ifndef CODE_COVERAGE_ENABLED + } +#endif + + mDescriptionWithContext.insert(0, ": "); + mDescriptionWithContext.insert(0, mContext); + } } Issue::Type Issue::Impl::type() const @@ -30,27 +48,18 @@ Issue::Type Issue::Impl::type() const return mType; } -std::string Issue::Impl::typeAsString() const +const std::string &Issue::Impl::typeAsString() const { - return (mType == Type::ERROR) ? "Error" : "Warning"; + static const std::string ERROR_STRING {"Error"}; + static const std::string WARNING_STRING {"Warning"}; + + return (mType == Type::ERROR) ? ERROR_STRING : WARNING_STRING; } -std::string Issue::Impl::description() const +const std::string &Issue::Impl::description() const { - // Check whether we have some context to add to the description. - if (!mContext.empty()) { - auto description {mDescription}; - -#ifndef CODE_COVERAGE_ENABLED - if (std::isupper(description[0]) != 0) { -#endif - description[0] = static_cast(std::tolower(description[0])); -#ifndef CODE_COVERAGE_ENABLED - } -#endif - - return mContext + ": " + description; + return mDescriptionWithContext; } return mDescription; @@ -71,12 +80,12 @@ Issue::Type Issue::type() const return mPimpl->type(); } -std::string Issue::typeAsString() const +const std::string &Issue::typeAsString() const { return mPimpl->typeAsString(); } -std::string Issue::description() const +const std::string &Issue::description() const { return mPimpl->description(); } diff --git a/src/logger/issue_p.h b/src/logger/issue_p.h index 524a1ab8b..f2d8ca65c 100644 --- a/src/logger/issue_p.h +++ b/src/logger/issue_p.h @@ -26,12 +26,13 @@ class Issue::Impl Type mType; std::string mDescription; std::string mContext; + std::string mDescriptionWithContext; explicit Impl(Type pType, const std::string &pDescription, const std::string &pContext); Type type() const; - std::string typeAsString() const; - std::string description() const; + const std::string &typeAsString() const; + const std::string &description() const; }; } // namespace libOpenCOR diff --git a/src/logger/logger.cpp b/src/logger/logger.cpp index 1edbf56a6..415a38650 100644 --- a/src/logger/logger.cpp +++ b/src/logger/logger.cpp @@ -29,15 +29,17 @@ size_t Logger::Impl::issueCount() const return mIssues.size(); } -IssuePtrs Logger::Impl::issues() const +const IssuePtrs &Logger::Impl::issues() const { return mIssues; } -IssuePtr Logger::Impl::issue(size_t pIndex) const +const IssuePtr &Logger::Impl::issue(size_t pIndex) const { + static const IssuePtr NO_ISSUE_PTR; + if (pIndex >= mIssues.size()) { - return {}; + return NO_ISSUE_PTR; } return mIssues[pIndex]; @@ -53,15 +55,17 @@ size_t Logger::Impl::errorCount() const return mErrors.size(); } -IssuePtrs Logger::Impl::errors() const +const IssuePtrs &Logger::Impl::errors() const { return mErrors; } -IssuePtr Logger::Impl::error(size_t pIndex) const +const IssuePtr &Logger::Impl::error(size_t pIndex) const { + static const IssuePtr NO_ISSUE_PTR; + if (pIndex >= mErrors.size()) { - return {}; + return NO_ISSUE_PTR; } return mErrors[pIndex]; @@ -77,15 +81,17 @@ size_t Logger::Impl::warningCount() const return mWarnings.size(); } -IssuePtrs Logger::Impl::warnings() const +const IssuePtrs &Logger::Impl::warnings() const { return mWarnings; } -IssuePtr Logger::Impl::warning(size_t pIndex) const +const IssuePtr &Logger::Impl::warning(size_t pIndex) const { + static const IssuePtr NO_ISSUE_PTR; + if (pIndex >= mWarnings.size()) { - return {}; + return NO_ISSUE_PTR; } return mWarnings[pIndex]; @@ -116,9 +122,9 @@ void Logger::Impl::addIssue(Issue::Type pType, const std::string &pDescription, mIssues.push_back(issue); if (pType == Issue::Type::ERROR) { - mErrors.push_back(issue); + mErrors.push_back(std::move(issue)); } else { - mWarnings.push_back(issue); + mWarnings.push_back(std::move(issue)); } } @@ -155,12 +161,12 @@ size_t Logger::issueCount() const return mPimpl->issueCount(); } -IssuePtrs Logger::issues() const +const IssuePtrs &Logger::issues() const { return mPimpl->issues(); } -IssuePtr Logger::issue(size_t pIndex) const +const IssuePtr &Logger::issue(size_t pIndex) const { return mPimpl->issue(pIndex); } @@ -175,12 +181,12 @@ size_t Logger::errorCount() const return mPimpl->errorCount(); } -IssuePtrs Logger::errors() const +const IssuePtrs &Logger::errors() const { return mPimpl->errors(); } -IssuePtr Logger::error(size_t pIndex) const +const IssuePtr &Logger::error(size_t pIndex) const { return mPimpl->error(pIndex); } @@ -195,12 +201,12 @@ size_t Logger::warningCount() const return mPimpl->warningCount(); } -IssuePtrs Logger::warnings() const +const IssuePtrs &Logger::warnings() const { return mPimpl->warnings(); } -IssuePtr Logger::warning(size_t pIndex) const +const IssuePtr &Logger::warning(size_t pIndex) const { return mPimpl->warning(pIndex); } diff --git a/src/logger/logger_p.h b/src/logger/logger_p.h index 6c3076f72..4b46a3a07 100644 --- a/src/logger/logger_p.h +++ b/src/logger/logger_p.h @@ -36,18 +36,18 @@ class Logger::Impl bool hasIssues() const; size_t issueCount() const; - IssuePtrs issues() const; - IssuePtr issue(size_t pIndex) const; + const IssuePtrs &issues() const; + const IssuePtr &issue(size_t pIndex) const; bool hasErrors() const; size_t errorCount() const; - IssuePtrs errors() const; - IssuePtr error(size_t pIndex) const; + const IssuePtrs &errors() const; + const IssuePtr &error(size_t pIndex) const; bool hasWarnings() const; size_t warningCount() const; - IssuePtrs warnings() const; - IssuePtr warning(size_t pIndex) const; + const IssuePtrs &warnings() const; + const IssuePtr &warning(size_t pIndex) const; void addIssues(const LoggerPtr &pLogger, const std::string &pContext); void addIssues(const libcellml::LoggerPtr &pLogger, const std::string &pContext); diff --git a/src/misc/compiler.cpp b/src/misc/compiler.cpp index fd2cff5d1..503ecd6b4 100644 --- a/src/misc/compiler.cpp +++ b/src/misc/compiler.cpp @@ -55,7 +55,15 @@ std::string llvmClangError(llvm::Error pError) res[0] = static_cast(toupper(res[0])); - return res.insert(0, " (").append(")"); + std::string wrappedError; + + wrappedError.reserve(res.size() + 3); // NOLINT + + wrappedError += " ("; + wrappedError += res; + wrappedError += ")"; + + return wrappedError; } #endif @@ -131,7 +139,16 @@ bool Compiler::Impl::compile(const std::string &pCode) static constexpr auto CLANG {"clang"}; if (strcmp(command.getCreator().getName(), CLANG) != 0) { - addError(std::string("The command name must be 'clang' while it is '").append(command.getCreator().getName()).append("'.")); + const std::string commandName(command.getCreator().getName()); + std::string error; + + error.reserve(commandName.size() + 47); // NOLINT + + error += "The command name must be 'clang' while it is '"; + error += commandName; + error += "'."; + + addError(error); return false; } @@ -178,7 +195,7 @@ bool Compiler::Impl::compile(const std::string &pCode) // Map our code to a memory buffer. - auto code {R"(// Arithmetic operators. + std::string code {R"(// Arithmetic operators. extern double pow(double, double); extern double sqrt(double); @@ -212,7 +229,9 @@ extern double atanh(double); #define INFINITY (__builtin_inf()) #define NAN (__builtin_nan("")) -)" + pCode}; +)"}; + + code += pCode; compilerInstance->getInvocation().getPreprocessorOpts().addRemappedFile(DUMMY_FILE_NAME, llvm::MemoryBuffer::getMemBuffer(code).release()); @@ -254,11 +273,13 @@ extern double atanh(double); error[error.size() - 1] = ' '; } - error += line.substr(notePos + NOTE_LENGTH) + ":"; + error += line.substr(notePos + NOTE_LENGTH); + error += ":"; } else if (line.find(DUMMY_FILE_NAME) != std::string::npos) { break; } else { - error += "\n" + line; + error += "\n"; + error += line; hasErrorDetails = true; } @@ -298,7 +319,17 @@ extern double atanh(double); if (target == nullptr) { error[0] = static_cast(tolower(error[0])); - addError(std::string("the target (").append(module->getTargetTriple()).append(") could not be found: ").append(error)); + const auto targetTriple {module->getTargetTriple()}; + std::string targetError; + + targetError.reserve(targetTriple.size() + error.size() + 32); // NOLINT + + targetError += "the target ("; + targetError += targetTriple; + targetError += ") could not be found: "; + targetError += error; + + addError(targetError); return false; } @@ -348,7 +379,16 @@ extern double atanh(double); # ifndef CODE_COVERAGE_ENABLED if (!lljit) { - addError(std::string("An ORC-based JIT could not be created").append(llvmClangError(lljit.takeError())).append(".")); + auto llvmError {llvmClangError(lljit.takeError())}; + std::string error; + + error.reserve(37 + llvmError.size()); // NOLINT + + error += "An ORC-based JIT could not be created"; + error += llvmError; + error += "."; + + addError(error); return false; } @@ -362,7 +402,16 @@ extern double atanh(double); # ifndef CODE_COVERAGE_ENABLED if (!dynamicLibrarySearchGenerator) { - addError(std::string("The dynamic library search generator could not be created").append(llvmClangError(dynamicLibrarySearchGenerator.takeError())).append(".")); + auto llvmError {llvmClangError(dynamicLibrarySearchGenerator.takeError())}; + std::string error; + + error.reserve(56 + llvmError.size()); // NOLINT + + error += "The dynamic library search generator could not be created"; + error += llvmError; + error += "."; + + addError(error); return false; } @@ -403,7 +452,15 @@ bool Compiler::Impl::addFunction(const std::string &pName, void *pFunction) # ifndef CODE_COVERAGE_ENABLED if (!res) { - addError(std::string("The ").append(pName).append("() function could not be added to the compiler.")); + std::string error; + + error.reserve(pName.size() + 48); // NOLINT + + error += "The "; + error += pName; + error += "() function could not be added to the compiler."; + + addError(error); } # endif @@ -421,7 +478,7 @@ void *Compiler::Impl::function(const std::string &pName) const return reinterpret_cast(symbol->getValue()); // NOLINT } - return {}; + return nullptr; } #endif diff --git a/src/misc/utils.cpp b/src/misc/utils.cpp index 232336a92..499d70d51 100644 --- a/src/misc/utils.cpp +++ b/src/misc/utils.cpp @@ -30,6 +30,7 @@ limitations under the License. #include #include +#include #include #include #include @@ -58,7 +59,7 @@ void printIssues(const LoggerPtr &pLogger, const std::string &pHeader) std::cout << "---[" << pHeader << "]\n"; } - for (auto &issue : pLogger->issues()) { + for (const auto &issue : pLogger->issues()) { std::cout << ((issue->type() == Issue::Type::ERROR) ? "ERROR" : "WARNING") << ": " << issue->description() << "\n"; } @@ -157,16 +158,29 @@ bool fuzzyCompare(double pNb1, double pNb2) std::string encodeUrl(const std::string &pUrl) { - std::ostringstream res; + static constexpr std::string_view URL_SAFE_CHARACTERS {"!#$&'()*+,-./:;=?@_~"}; + static constexpr std::string_view HEX_DIGITS {"0123456789ABCDEF"}; + static constexpr unsigned int HEX_HIGH_NIBBLE_SHIFT {4U}; + static constexpr unsigned int HEX_LOW_NIBBLE_MASK {0x0FU}; + + std::string res; + + res.reserve(pUrl.size() * 3); // NOLINT + + for (const auto urlChar : pUrl) { + const auto unsignedChar {static_cast(urlChar)}; + const auto encodedChar {static_cast(unsignedChar)}; - for (const char c : pUrl) { - if ((isalnum(c) != 0) || (std::string("!#$&'()*+,-./:;=?@_~").find(c) != std::string::npos)) { - res << c; + if ((isalnum(unsignedChar) != 0) || (URL_SAFE_CHARACTERS.find(urlChar) != std::string::npos)) { + res += urlChar; } else { - res << '%' << std::uppercase << std::hex << std::setw(2) << std::setfill('0') << static_cast(static_cast(c)); + res += '%'; + res += HEX_DIGITS[encodedChar >> HEX_HIGH_NIBBLE_SHIFT]; + res += HEX_DIGITS[encodedChar & HEX_LOW_NIBBLE_MASK]; } } - return res.str(); + + return res; } std::string decodeUrl(const std::string &pUrl) @@ -463,12 +477,14 @@ size_t curlWriteFunction(char *pData, size_t pSize, size_t pDataSize, void *pUse std::tuple downloadFile(const std::string &pUrl) { + static const std::tuple NO_TUPLE {false, std::filesystem::path()}; + auto filePath {uniqueFilePath()}; std::ofstream file(filePath, std::ios_base::binary); # ifndef CODE_COVERAGE_ENABLED if (!file.is_open()) { - return {}; + return NO_TUPLE; } # endif @@ -504,23 +520,27 @@ std::tuple downloadFile(const std::string &pUrl) std::filesystem::remove(filePath); - return {}; + return NO_TUPLE; } UnsignedChars fileContents(const std::filesystem::path &pFilePath) { + static const UnsignedChars NO_UNSIGNED_CHARS; + // Retrieve and return the contents of the given file. std::ifstream file(pFilePath, std::ios_base::binary); if (!file.is_open()) { - return {}; + return NO_UNSIGNED_CHARS; } const auto fileSize {std::filesystem::file_size(pFilePath)}; - UnsignedChars contents(fileSize); + UnsignedChars contents; - file.read(reinterpret_cast(&contents[0]), static_cast(fileSize)); // NOLINT + contents.resize(fileSize); + + file.read(reinterpret_cast(contents.data()), static_cast(fileSize)); // NOLINT return contents; } @@ -578,20 +598,12 @@ int toInt(const std::string &pString) std::string toString(int pNumber) { - std::ostringstream res; - - res << pNumber; - - return res.str(); + return std::format("{}", pNumber); } std::string toString(size_t pNumber) { - std::ostringstream res; - - res << pNumber; - - return res.str(); + return std::format("{}", pNumber); } bool isDouble(const std::string &pString) diff --git a/src/misc/utils.h b/src/misc/utils.h index 7b9513862..a83c12515 100644 --- a/src/misc/utils.h +++ b/src/misc/utils.h @@ -40,10 +40,10 @@ limitations under the License. namespace libOpenCOR { -static const std::string LIBOPENCOR_NAMESPACE {"https://opencor.ws/libopencor"}; +static constexpr auto LIBOPENCOR_NAMESPACE {"https://opencor.ws/libopencor"}; -static const auto INF {std::numeric_limits::infinity()}; -static const auto NAN {std::numeric_limits::quiet_NaN()}; +static constexpr auto INF {std::numeric_limits::infinity()}; +static constexpr auto NAN {std::numeric_limits::quiet_NaN()}; using StringStringMap = std::map; diff --git a/src/sed/sedbase.cpp b/src/sed/sedbase.cpp index ffdb0adbf..e3d30e129 100644 --- a/src/sed/sedbase.cpp +++ b/src/sed/sedbase.cpp @@ -25,7 +25,7 @@ SedBase::Impl::Impl(const std::string &pId) { } -std::string SedBase::Impl::id() const +const std::string &SedBase::Impl::id() const { return mId; } @@ -55,7 +55,7 @@ const SedBase::Impl *SedBase::pimpl() const return static_cast(Logger::mPimpl); } -std::string SedBase::id() const +const std::string &SedBase::id() const { return pimpl()->id(); } diff --git a/src/sed/sedbase_p.h b/src/sed/sedbase_p.h index 631eaba55..c0e925729 100644 --- a/src/sed/sedbase_p.h +++ b/src/sed/sedbase_p.h @@ -33,7 +33,7 @@ class SedBase::Impl: public Logger::Impl explicit Impl(const std::string &pId = {}); - std::string id() const; + const std::string &id() const; void setId(const std::string &pId); virtual void serialise(xmlNodePtr pNode) const; diff --git a/src/sed/sedchange.cpp b/src/sed/sedchange.cpp index ec685c673..5cf6f0406 100644 --- a/src/sed/sedchange.cpp +++ b/src/sed/sedchange.cpp @@ -25,7 +25,7 @@ SedChange::Impl::Impl(const std::string &pTarget) { } -std::string SedChange::Impl::target() const +const std::string &SedChange::Impl::target() const { return mTarget; } @@ -60,7 +60,7 @@ const SedChange::Impl *SedChange::pimpl() const return static_cast(SedBase::pimpl()); } -std::string SedChange::target() const +const std::string &SedChange::target() const { return pimpl()->target(); } diff --git a/src/sed/sedchange_p.h b/src/sed/sedchange_p.h index f06ba63ac..caa39c3aa 100644 --- a/src/sed/sedchange_p.h +++ b/src/sed/sedchange_p.h @@ -29,7 +29,7 @@ class SedChange::Impl: public SedBase::Impl explicit Impl(const std::string &pTarget = {}); - std::string target() const; + const std::string &target() const; virtual void setTarget(const std::string &pTarget) = 0; void serialise(xmlNodePtr pNode) const override; diff --git a/src/sed/sedchangeattribute.cpp b/src/sed/sedchangeattribute.cpp index add084469..aa37e0b71 100644 --- a/src/sed/sedchangeattribute.cpp +++ b/src/sed/sedchangeattribute.cpp @@ -40,7 +40,7 @@ void SedChangeAttribute::Impl::updateTarget() setTarget("/cellml:model/cellml:component[@name='" + mComponentName + "']/cellml:variable[@name='" + mVariableName + "']"); } -std::string SedChangeAttribute::Impl::componentName() const +const std::string &SedChangeAttribute::Impl::componentName() const { return mComponentName; } @@ -52,7 +52,7 @@ void SedChangeAttribute::Impl::setComponentName(const std::string &pComponentNam updateTarget(); } -std::string SedChangeAttribute::Impl::variableName() const +const std::string &SedChangeAttribute::Impl::variableName() const { return mVariableName; } @@ -64,7 +64,7 @@ void SedChangeAttribute::Impl::setVariableName(const std::string &pVariableName) updateTarget(); } -std::string SedChangeAttribute::Impl::newValue() const +const std::string &SedChangeAttribute::Impl::newValue() const { return mNewValue; } @@ -88,21 +88,43 @@ void SedChangeAttribute::Impl::serialise(xmlNodePtr pNode) const void SedChangeAttribute::Impl::apply(const SedInstanceTaskPtr &pInstanceTask, const libcellml::AnalyserModelPtr &pAnalyserModel) { + auto addCannotChangeWarning = [&](const std::string &pVariableName, + const std::string &pComponentName, + const char *pVariableType) { + std::string warning; + + warning.reserve(pVariableName.size() + pComponentName.size() + 120); // NOLINT + + warning += "The "; + warning += pVariableType; + warning += " '"; + warning += pVariableName; + warning += "' in component '"; + warning += pComponentName; + warning += "' cannot be changed. Only state variables and constants can be changed."; + + addWarning(warning); + }; + auto *instanceTaskPimpl {pInstanceTask->pimpl()}; auto changeName {name(mComponentName, mVariableName)}; + const auto stateCount = instanceTaskPimpl->stateCount(); + const auto constantCount = instanceTaskPimpl->constantCount(); + const auto computedConstantCount = instanceTaskPimpl->computedConstantCount(); + const auto algebraicVariableCount = instanceTaskPimpl->algebraicVariableCount(); if (instanceTaskPimpl->voiName() == changeName) { auto voiVariable {pAnalyserModel->voi()->variable()}; auto voiComponent {owningComponent(voiVariable)}; - addWarning(std::string("The variable of integration '").append(voiVariable->name()).append("' in component '").append(voiComponent->name()).append("' cannot be changed. Only state variables and constants can be changed.")); + addCannotChangeWarning(voiVariable->name(), voiComponent->name(), "variable of integration"); return; } auto isParameterSet {false}; - for (size_t i {0}; i < pAnalyserModel->stateCount(); ++i) { + for (size_t i {0}; i < stateCount; ++i) { if (instanceTaskPimpl->stateName(i) == changeName) { instanceTaskPimpl->mStates[i] = toDouble(newValue()); // NOLINT @@ -113,7 +135,7 @@ void SedChangeAttribute::Impl::apply(const SedInstanceTaskPtr &pInstanceTask, } if (!isParameterSet) { - for (size_t i {0}; i < pAnalyserModel->constantCount(); ++i) { + for (size_t i {0}; i < constantCount; ++i) { if (instanceTaskPimpl->constantName(i) == changeName) { instanceTaskPimpl->mConstants[i] = toDouble(newValue()); // NOLINT @@ -125,12 +147,14 @@ void SedChangeAttribute::Impl::apply(const SedInstanceTaskPtr &pInstanceTask, } if (!isParameterSet) { - for (size_t i {0}; i < pAnalyserModel->computedConstantCount(); ++i) { + const auto &computedConstants = pAnalyserModel->computedConstants(); + + for (size_t i {0}; i < computedConstantCount; ++i) { if (instanceTaskPimpl->computedConstantName(i) == changeName) { - auto computedConstantVariable {pAnalyserModel->computedConstants()[i]->variable()}; + auto computedConstantVariable {computedConstants[i]->variable()}; auto computedConstantComponent {owningComponent(computedConstantVariable)}; - addWarning(std::string("The computed constant '").append(computedConstantVariable->name()).append("' in component '").append(computedConstantComponent->name()).append("' cannot be changed. Only state variables and constants can be changed.")); + addCannotChangeWarning(computedConstantVariable->name(), computedConstantComponent->name(), "computed constant"); isParameterSet = true; @@ -140,12 +164,14 @@ void SedChangeAttribute::Impl::apply(const SedInstanceTaskPtr &pInstanceTask, } if (!isParameterSet) { - for (size_t i {0}; i < pAnalyserModel->algebraicVariableCount(); ++i) { + const auto &algebraicVariables = pAnalyserModel->algebraicVariables(); + + for (size_t i {0}; i < algebraicVariableCount; ++i) { if (instanceTaskPimpl->algebraicVariableName(i) == changeName) { - auto algebraicVariable {pAnalyserModel->algebraicVariables()[i]->variable()}; + auto algebraicVariable {algebraicVariables[i]->variable()}; auto algebraicComponent {owningComponent(algebraicVariable)}; - addWarning(std::string("The algebraic variable '").append(algebraicVariable->name()).append("' in component '").append(algebraicComponent->name()).append("' cannot be changed. Only state variables and constants can be changed.")); + addCannotChangeWarning(algebraicVariable->name(), algebraicComponent->name(), "algebraic variable"); isParameterSet = true; @@ -155,7 +181,17 @@ void SedChangeAttribute::Impl::apply(const SedInstanceTaskPtr &pInstanceTask, } if (!isParameterSet) { - addWarning(std::string("The variable '").append(mVariableName).append("' in component '").append(mComponentName).append("' could not be found and therefore could not be changed.")); + std::string warning; + + warning.reserve(mVariableName.size() + mComponentName.size() + 72); // NOLINT + + warning += "The variable '"; + warning += mVariableName; + warning += "' in component '"; + warning += mComponentName; + warning += "' could not be found and therefore could not be changed."; + + addWarning(warning); } } @@ -186,7 +222,7 @@ SedChangeAttributePtr SedChangeAttribute::create(const std::string &pComponent, return SedChangeAttributePtr(new SedChangeAttribute(pComponent, pVariable, pNewValue)); } -std::string SedChangeAttribute::componentName() const +const std::string &SedChangeAttribute::componentName() const { return pimpl()->componentName(); } @@ -196,7 +232,7 @@ void SedChangeAttribute::setComponentName(const std::string &pComponentName) pimpl()->setComponentName(pComponentName); } -std::string SedChangeAttribute::variableName() const +const std::string &SedChangeAttribute::variableName() const { return pimpl()->variableName(); } @@ -206,7 +242,7 @@ void SedChangeAttribute::setVariableName(const std::string &pVariableName) pimpl()->setVariableName(pVariableName); } -std::string SedChangeAttribute::newValue() const +const std::string &SedChangeAttribute::newValue() const { return pimpl()->newValue(); } diff --git a/src/sed/sedchangeattribute_p.h b/src/sed/sedchangeattribute_p.h index da9c84004..afa8e1ff6 100644 --- a/src/sed/sedchangeattribute_p.h +++ b/src/sed/sedchangeattribute_p.h @@ -35,13 +35,13 @@ class SedChangeAttribute::Impl: public SedChange::Impl void setTarget(const std::string &pTarget) override; void updateTarget(); - std::string componentName() const; + const std::string &componentName() const; void setComponentName(const std::string &pComponentName); - std::string variableName() const; + const std::string &variableName() const; void setVariableName(const std::string &pVariableName); - std::string newValue() const; + const std::string &newValue() const; void setNewValue(const std::string &pNewValue); void serialise(xmlNodePtr pNode) const override; diff --git a/src/sed/seddocument.cpp b/src/sed/seddocument.cpp index 99688e87c..a0054f03b 100644 --- a/src/sed/seddocument.cpp +++ b/src/sed/seddocument.cpp @@ -24,6 +24,7 @@ limitations under the License. #include "utils.h" #include +#include #include namespace libOpenCOR { @@ -31,18 +32,10 @@ namespace libOpenCOR { std::string SedDocument::Impl::uniqueId(const std::string &pPrefix) { size_t counter {0}; - std::stringstream stream; - - stream << pPrefix << ++counter; - - auto res {stream.str()}; + auto res {pPrefix + std::format("{}", ++counter)}; while (mIds.contains(res)) { - stream.str({}); - - stream << pPrefix << ++counter; - - res = stream.str(); + res = pPrefix + std::format("{}", ++counter); } mIds.insert(res); @@ -96,7 +89,7 @@ void SedDocument::Impl::initialiseFromSedmlFile(const SedDocumentPtr &pOwner, co void SedDocument::Impl::initialiseFromCombineArchive(const SedDocumentPtr &pOwner, const FilePtr &pFile) { - auto masterFile {pFile->pimpl()->mCombineArchive->masterFile()}; + const auto &masterFile {pFile->pimpl()->mCombineArchive->masterFile()}; if (masterFile == nullptr) { addError("A simulation experiment description cannot be created using a COMBINE archive with no master file."); @@ -116,8 +109,8 @@ void SedDocument::Impl::initialiseFromCombineArchive(const SedDocumentPtr &pOwne void SedDocument::Impl::serialise(xmlNodePtr pNode) const { xmlNewProp(pNode, toConstXmlCharPtr("xmlns"), toConstXmlCharPtr(mXmlns)); - xmlNewProp(pNode, toConstXmlCharPtr("level"), toConstXmlCharPtr(std::to_string(mLevel))); - xmlNewProp(pNode, toConstXmlCharPtr("version"), toConstXmlCharPtr(std::to_string(mVersion))); + xmlNewProp(pNode, toConstXmlCharPtr("level"), toConstXmlCharPtr(std::format("{}", mLevel))); + xmlNewProp(pNode, toConstXmlCharPtr("version"), toConstXmlCharPtr(std::format("{}", mVersion))); } std::string SedDocument::Impl::serialise(const std::string &pBasePath) const @@ -251,15 +244,17 @@ size_t SedDocument::Impl::modelCount() const return mModels.size(); } -SedModelPtrs SedDocument::Impl::models() const +const SedModelPtrs &SedDocument::Impl::models() const { return mModels; } -SedModelPtr SedDocument::Impl::model(size_t pIndex) const +const SedModelPtr &SedDocument::Impl::model(size_t pIndex) const { + static const SedModelPtr NO_SED_MODEL_PTR; + if (pIndex >= mModels.size()) { - return {}; + return NO_SED_MODEL_PTR; } return mModels[pIndex]; @@ -323,15 +318,17 @@ size_t SedDocument::Impl::simulationCount() const return mSimulations.size(); } -SedSimulationPtrs SedDocument::Impl::simulations() const +const SedSimulationPtrs &SedDocument::Impl::simulations() const { return mSimulations; } -SedSimulationPtr SedDocument::Impl::simulation(size_t pIndex) const +const SedSimulationPtr &SedDocument::Impl::simulation(size_t pIndex) const { + static const SedSimulationPtr NO_SED_SIMULATION_PTR; + if (pIndex >= mSimulations.size()) { - return {}; + return NO_SED_SIMULATION_PTR; } return mSimulations[pIndex]; @@ -395,15 +392,17 @@ size_t SedDocument::Impl::taskCount() const return mTasks.size(); } -SedAbstractTaskPtrs SedDocument::Impl::tasks() const +const SedAbstractTaskPtrs &SedDocument::Impl::tasks() const { return mTasks; } -SedAbstractTaskPtr SedDocument::Impl::task(size_t pIndex) const +const SedAbstractTaskPtr &SedDocument::Impl::task(size_t pIndex) const { + static const SedAbstractTaskPtr NO_SED_ABSTRACT_TASK_PTR; + if (pIndex >= mTasks.size()) { - return {}; + return NO_SED_ABSTRACT_TASK_PTR; } return mTasks[pIndex]; @@ -513,12 +512,12 @@ size_t SedDocument::modelCount() const return pimpl()->modelCount(); } -SedModelPtrs SedDocument::models() const +const SedModelPtrs &SedDocument::models() const { return pimpl()->models(); } -SedModelPtr SedDocument::model(size_t pIndex) const +const SedModelPtr &SedDocument::model(size_t pIndex) const { return pimpl()->model(pIndex); } @@ -548,12 +547,12 @@ size_t SedDocument::simulationCount() const return pimpl()->simulationCount(); } -SedSimulationPtrs SedDocument::simulations() const +const SedSimulationPtrs &SedDocument::simulations() const { return pimpl()->simulations(); } -SedSimulationPtr SedDocument::simulation(size_t pIndex) const +const SedSimulationPtr &SedDocument::simulation(size_t pIndex) const { return pimpl()->simulation(pIndex); } @@ -583,12 +582,12 @@ size_t SedDocument::taskCount() const return pimpl()->taskCount(); } -SedAbstractTaskPtrs SedDocument::tasks() const +const SedAbstractTaskPtrs &SedDocument::tasks() const { return pimpl()->tasks(); } -SedAbstractTaskPtr SedDocument::task(size_t pIndex) const +const SedAbstractTaskPtr &SedDocument::task(size_t pIndex) const { return pimpl()->task(pIndex); } diff --git a/src/sed/seddocument_p.h b/src/sed/seddocument_p.h index fe8b355fb..52a6dc35c 100644 --- a/src/sed/seddocument_p.h +++ b/src/sed/seddocument_p.h @@ -54,24 +54,24 @@ class SedDocument::Impl: public Logger::Impl bool hasModels() const; size_t modelCount() const; - SedModelPtrs models() const; - SedModelPtr model(size_t pIndex) const; + const SedModelPtrs &models() const; + const SedModelPtr &model(size_t pIndex) const; bool addModel(const SedModelPtr &pModel); bool removeModel(const SedModelPtr &pModel); bool removeAllModels(); bool hasSimulations() const; size_t simulationCount() const; - SedSimulationPtrs simulations() const; - SedSimulationPtr simulation(size_t pIndex) const; + const SedSimulationPtrs &simulations() const; + const SedSimulationPtr &simulation(size_t pIndex) const; bool addSimulation(const SedSimulationPtr &pSimulation); bool removeSimulation(const SedSimulationPtr &pSimulation); bool removeAllSimulations(); bool hasTasks() const; size_t taskCount() const; - SedAbstractTaskPtrs tasks() const; - SedAbstractTaskPtr task(size_t pIndex) const; + const SedAbstractTaskPtrs &tasks() const; + const SedAbstractTaskPtr &task(size_t pIndex) const; bool addTask(const SedAbstractTaskPtr &pTask); bool removeTask(const SedAbstractTaskPtr &pTask); bool removeAllTasks(); diff --git a/src/sed/sedinstance.cpp b/src/sed/sedinstance.cpp index 3e792f361..fbefad02c 100644 --- a/src/sed/sedinstance.cpp +++ b/src/sed/sedinstance.cpp @@ -37,7 +37,7 @@ SedInstance::Impl::Impl(const SedDocumentPtr &pDocument) if (pDocument->hasTasks()) { // Make sure that all the tasks are valid. - auto tasks {pDocument->tasks()}; + const auto &tasks {pDocument->tasks()}; auto tasksValid {true}; for (const auto &task : tasks) { @@ -57,6 +57,8 @@ SedInstance::Impl::Impl(const SedDocumentPtr &pDocument) // Create an instance of all the tasks, if they are all valid. if (tasksValid) { + mTasks.reserve(tasks.size()); + for (const auto &task : tasks) { auto taskInstance {SedInstanceTask::Impl::create(task)}; @@ -115,15 +117,17 @@ size_t SedInstance::Impl::taskCount() const return mTasks.size(); } -SedInstanceTaskPtrs SedInstance::Impl::tasks() const +const SedInstanceTaskPtrs &SedInstance::Impl::tasks() const { return mTasks; } -SedInstanceTaskPtr SedInstance::Impl::task(size_t pIndex) const +const SedInstanceTaskPtr &SedInstance::Impl::task(size_t pIndex) const { + static const SedInstanceTaskPtr NO_SED_INSTANCE_TASK_PTR; + if (pIndex >= mTasks.size()) { - return {}; + return NO_SED_INSTANCE_TASK_PTR; } return mTasks[pIndex]; @@ -164,12 +168,12 @@ size_t SedInstance::taskCount() const return pimpl()->taskCount(); } -SedInstanceTaskPtrs SedInstance::tasks() const +const SedInstanceTaskPtrs &SedInstance::tasks() const { return pimpl()->tasks(); } -SedInstanceTaskPtr SedInstance::task(size_t pIndex) const +const SedInstanceTaskPtr &SedInstance::task(size_t pIndex) const { return pimpl()->task(pIndex); } diff --git a/src/sed/sedinstance_p.h b/src/sed/sedinstance_p.h index 7260ac1ea..6b4b9c04f 100644 --- a/src/sed/sedinstance_p.h +++ b/src/sed/sedinstance_p.h @@ -36,8 +36,8 @@ class SedInstance::Impl: public Logger::Impl bool hasTasks() const; size_t taskCount() const; - SedInstanceTaskPtrs tasks() const; - SedInstanceTaskPtr task(size_t pIndex) const; + const SedInstanceTaskPtrs &tasks() const; + const SedInstanceTaskPtr &task(size_t pIndex) const; }; } // namespace libOpenCOR diff --git a/src/sed/sedinstancetask.cpp b/src/sed/sedinstancetask.cpp index be2fb3db4..f7d643157 100644 --- a/src/sed/sedinstancetask.cpp +++ b/src/sed/sedinstancetask.cpp @@ -83,9 +83,10 @@ SedInstanceTask::Impl::Impl(const SedAbstractTaskPtr &pTask) mDifferentialModel = (cellmlFileType == libcellml::AnalyserModel::Type::ODE) || (cellmlFileType == libcellml::AnalyserModel::Type::DAE); mSimulation = task->pimpl()->mSimulation; + mSedUniformTimeCourse = mDifferentialModel ? std::dynamic_pointer_cast(mSimulation) : nullptr; - auto odeSolver {mSimulation->odeSolver()}; - auto nlaSolver {mSimulation->nlaSolver()}; + const auto &odeSolver {mSimulation->odeSolver()}; + const auto &nlaSolver {mSimulation->nlaSolver()}; mOdeSolver = (odeSolver != nullptr) ? std::dynamic_pointer_cast(odeSolver->pimpl()->duplicate()) : nullptr; mNlaSolver = (nlaSolver != nullptr) ? std::dynamic_pointer_cast(nlaSolver->pimpl()->duplicate()) : nullptr; @@ -102,50 +103,123 @@ SedInstanceTask::Impl::Impl(const SedAbstractTaskPtr &pTask) // Create our various arrays. mAnalyserModel = cellmlFile->analyserModel(); + mStateCount = mAnalyserModel->stateCount(); + mConstantCount = mAnalyserModel->constantCount(); + mComputedConstantCount = mAnalyserModel->computedConstantCount(); + mAlgebraicVariableCount = mAnalyserModel->algebraicVariableCount(); if (mDifferentialModel) { - mStateDoubles.resize(mAnalyserModel->stateCount(), NAN); - mRateDoubles.resize(mAnalyserModel->stateCount(), NAN); + mStateDoubles.resize(mStateCount, NAN); + mRateDoubles.resize(mStateCount, NAN); mStates = mStateDoubles.data(); mRates = mRateDoubles.data(); - mResults.states.resize(mAnalyserModel->stateCount(), {}); - mResults.rates.resize(mAnalyserModel->stateCount(), {}); + mResults.states.resize(mStateCount, {}); + mResults.rates.resize(mStateCount, {}); } - mConstantDoubles.resize(mAnalyserModel->constantCount(), NAN); - mComputedConstantDoubles.resize(mAnalyserModel->computedConstantCount(), NAN); - mAlgebraicDoubles.resize(mAnalyserModel->algebraicVariableCount(), NAN); + mConstantDoubles.resize(mConstantCount, NAN); + mComputedConstantDoubles.resize(mComputedConstantCount, NAN); + mAlgebraicDoubles.resize(mAlgebraicVariableCount, NAN); mConstants = mConstantDoubles.data(); mComputedConstants = mComputedConstantDoubles.data(); mAlgebraicVariables = mAlgebraicDoubles.data(); - mResults.constants.resize(mAnalyserModel->constantCount(), {}); - mResults.computedConstants.resize(mAnalyserModel->computedConstantCount(), {}); - mResults.algebraic.resize(mAnalyserModel->algebraicVariableCount(), {}); + mResults.constants.resize(mConstantCount, {}); + mResults.computedConstants.resize(mComputedConstantCount, {}); + mResults.algebraic.resize(mAlgebraicVariableCount, {}); + + // Retrieve our various strings. + + if (mDifferentialModel) { + auto variable = mAnalyserModel->voi()->variable(); + + mVoiName = name(variable); + mVoiUnit = variable->units()->name(); + + const auto stateCount = mStateCount; + + mStateNames.resize(stateCount); + mStateUnits.resize(stateCount); + + mRateNames.resize(stateCount); + mRateUnits.resize(stateCount); + + const auto &states = mAnalyserModel->states(); + + for (size_t i {0}; i < stateCount; ++i) { + mStateNames[i] = name(states[i]->variable()); + mStateUnits[i] = states[i]->variable()->units()->name(); + + mRateNames[i] = mStateNames[i] + "'"; + mRateUnits[i] = mStateUnits[i] + "/" + mVoiUnit; + } + } + + const auto constantCount = mConstantCount; + + mConstantNames.resize(constantCount); + mConstantUnits.resize(constantCount); + + const auto &constants = mAnalyserModel->constants(); + + for (size_t i {0}; i < constantCount; ++i) { + mConstantNames[i] = name(constants[i]->variable()); + mConstantUnits[i] = constants[i]->variable()->units()->name(); + } + + const auto computedConstantCount = mComputedConstantCount; + + mComputedConstantNames.resize(computedConstantCount); + mComputedConstantUnits.resize(computedConstantCount); + + const auto &computedConstants = mAnalyserModel->computedConstants(); + + for (size_t i {0}; i < computedConstantCount; ++i) { + mComputedConstantNames[i] = name(computedConstants[i]->variable()); + mComputedConstantUnits[i] = computedConstants[i]->variable()->units()->name(); + } + + const auto algebraicVariableCount = mAlgebraicVariableCount; + + mAlgebraicVariableNames.resize(algebraicVariableCount); + mAlgebraicVariableUnits.resize(algebraicVariableCount); + + const auto &algebraicVariables = mAnalyserModel->algebraicVariables(); + + for (size_t i {0}; i < algebraicVariableCount; ++i) { + mAlgebraicVariableNames[i] = name(algebraicVariables[i]->variable()); + mAlgebraicVariableUnits[i] = algebraicVariables[i]->variable()->units()->name(); + } } void SedInstanceTask::Impl::trackResults(size_t pIndex) { mResults.voi[pIndex] = mVoi; - for (size_t i {0}; i < mAnalyserModel->stateCount(); ++i) { - mResults.states[i][pIndex] = mStates[i]; // NOLINT - mResults.rates[i][pIndex] = mRates[i]; // NOLINT + auto &states = mResults.states; + auto &rates = mResults.rates; + auto &constants = mResults.constants; + auto &computedConstants = mResults.computedConstants; + auto &algebraic = mResults.algebraic; + + for (size_t i {0}; i < mStateCount; ++i) { + states[i][pIndex] = mStates[i]; // NOLINT + rates[i][pIndex] = mRates[i]; // NOLINT } - for (size_t i {0}; i < mAnalyserModel->constantCount(); ++i) { - mResults.constants[i][pIndex] = mConstants[i]; // NOLINT + for (size_t i {0}; i < mConstantCount; ++i) { + constants[i][pIndex] = mConstants[i]; // NOLINT } - for (size_t i {0}; i < mAnalyserModel->computedConstantCount(); ++i) { - mResults.computedConstants[i][pIndex] = mComputedConstants[i]; // NOLINT + for (size_t i {0}; i < mComputedConstantCount; ++i) { + computedConstants[i][pIndex] = mComputedConstants[i]; // NOLINT } - for (size_t i {0}; i < mAnalyserModel->algebraicVariableCount(); ++i) { - mResults.algebraic[i][pIndex] = mAlgebraicVariables[i]; // NOLINT + for (size_t i {0}; i < mAlgebraicVariableCount; ++i) { + algebraic[i][pIndex] = mAlgebraicVariables[i]; // NOLINT } } @@ -171,8 +245,6 @@ void SedInstanceTask::Impl::initialise() // variables, compute computed constants, rates, and variables, while for an algebraic/NLA model we need to // initialise our variables and compute computed constants and variables. - mSedUniformTimeCourse = mDifferentialModel ? std::dynamic_pointer_cast(mSimulation) : nullptr; - if (mSedUniformTimeCourse != nullptr) { mVoi = mSedUniformTimeCourse->pimpl()->mOutputStartTime; @@ -222,9 +294,7 @@ void SedInstanceTask::Impl::initialise() // Initialise the ODE solver, if needed. if (mDifferentialModel) { - if (!mOdeSolver->pimpl()->initialise(mVoi, mAnalyserModel->stateCount(), mStates, mRates, - mConstants, mComputedConstants, mAlgebraicVariables, - mRuntime)) { + if (!mOdeSolver->pimpl()->initialise(mVoi, mStateCount, mStates, mRates, mConstants, mComputedConstants, mAlgebraicVariables, mRuntime)) { addIssues(mOdeSolver, mOdeSolver->name()); return; @@ -248,24 +318,25 @@ double SedInstanceTask::Impl::run() if (mDifferentialModel) { // Initialise our results structure. - auto resultsSize {static_cast(mSedUniformTimeCourse->pimpl()->mNumberOfSteps) + 1}; + const auto *sedUniformTimeCoursePimpl {mSedUniformTimeCourse->pimpl()}; + const auto resultsSize {static_cast(sedUniformTimeCoursePimpl->mNumberOfSteps) + 1}; mResults.voi.resize(resultsSize, NAN); - for (size_t i {0}; i < mAnalyserModel->stateCount(); ++i) { + for (size_t i {0}; i < mStateCount; ++i) { mResults.states[i].resize(resultsSize, NAN); mResults.rates[i].resize(resultsSize, NAN); } - for (size_t i {0}; i < mAnalyserModel->constantCount(); ++i) { + for (size_t i {0}; i < mConstantCount; ++i) { mResults.constants[i].resize(resultsSize, NAN); } - for (size_t i {0}; i < mAnalyserModel->computedConstantCount(); ++i) { + for (size_t i {0}; i < mComputedConstantCount; ++i) { mResults.computedConstants[i].resize(resultsSize, NAN); } - for (size_t i {0}; i < mAnalyserModel->algebraicVariableCount(); ++i) { + for (size_t i {0}; i < mAlgebraicVariableCount; ++i) { mResults.algebraic[i].resize(resultsSize, NAN); } @@ -277,24 +348,27 @@ double SedInstanceTask::Impl::run() // Compute the differential model. - auto voiStart {mVoi}; - auto voiEnd {mSedUniformTimeCourse->pimpl()->mOutputEndTime}; - auto voiInterval {(voiEnd - mVoi) / mSedUniformTimeCourse->pimpl()->mNumberOfSteps}; + auto *odeSolverPimpl {mOdeSolver->pimpl()}; + const auto voiStart {mVoi}; + const auto voiEnd {sedUniformTimeCoursePimpl->mOutputEndTime}; + const auto voiInterval {(voiEnd - mVoi) / sedUniformTimeCoursePimpl->mNumberOfSteps}; size_t voiCounter {0}; +#ifndef __EMSCRIPTEN__ + const auto computeVariablesForDifferentialModel = mRuntime->computeVariablesForDifferentialModel(); +#endif + while (!fuzzyCompare(mVoi, voiEnd)) { - if (!mOdeSolver->pimpl()->solve(mVoi, std::min(voiStart + static_cast(++voiCounter) * voiInterval, voiEnd))) { + if (!odeSolverPimpl->solve(mVoi, std::min(voiStart + static_cast(++voiCounter) * voiInterval, voiEnd))) { addIssues(mOdeSolver, mOdeSolver->name()); return 0.0; } #ifdef __EMSCRIPTEN__ - mRuntime->computeVariablesForDifferentialModel(mVoi, mStates, mRates, - mConstants, mComputedConstants, mAlgebraicVariables); + mRuntime->computeVariablesForDifferentialModel(mVoi, mStates, mRates, mConstants, mComputedConstants, mAlgebraicVariables); #else - mRuntime->computeVariablesForDifferentialModel()(mVoi, mStates, mRates, - mConstants, mComputedConstants, mAlgebraicVariables); + computeVariablesForDifferentialModel(mVoi, mStates, mRates, mConstants, mComputedConstants, mAlgebraicVariables); #endif //---GRY--- WE NEED TO CHECK FOR POSSIBLE NLA ISSUES, BUT FOR CODE COVERAGE WE NEED A MODEL THAT WOULD @@ -314,16 +388,16 @@ double SedInstanceTask::Impl::run() } else { // Track our results. - for (size_t i {0}; i < mAnalyserModel->constantCount(); ++i) { - mResults.constants[i].resize(1, mConstants[i]); // NOLINT + for (size_t i {0}; i < mConstantCount; ++i) { + mResults.constants[i].assign(1, mConstants[i]); // NOLINT } - for (size_t i {0}; i < mAnalyserModel->computedConstantCount(); ++i) { - mResults.computedConstants[i].resize(1, mComputedConstants[i]); // NOLINT + for (size_t i {0}; i < mComputedConstantCount; ++i) { + mResults.computedConstants[i].assign(1, mComputedConstants[i]); // NOLINT } - for (size_t i {0}; i < mAnalyserModel->algebraicVariableCount(); ++i) { - mResults.algebraic[i].resize(1, mAlgebraicVariables[i]); // NOLINT + for (size_t i {0}; i < mAlgebraicVariableCount; ++i) { + mResults.algebraic[i].assign(1, mAlgebraicVariables[i]); // NOLINT } } @@ -332,63 +406,75 @@ double SedInstanceTask::Impl::run() return std::chrono::duration(std::chrono::high_resolution_clock::now() - startTime).count(); } -Doubles SedInstanceTask::Impl::voi() const +const Doubles &SedInstanceTask::Impl::voi() const { + static const Doubles NO_DOUBLES; + if (mDifferentialModel) { return mResults.voi; } - return {}; + return NO_DOUBLES; } -std::string SedInstanceTask::Impl::voiName() const +const std::string &SedInstanceTask::Impl::voiName() const { + static const std::string NO_STRING; + if (mDifferentialModel) { - return name(mAnalyserModel->voi()->variable()); + return mVoiName; } - return {}; + return NO_STRING; } -std::string SedInstanceTask::Impl::voiUnit() const +const std::string &SedInstanceTask::Impl::voiUnit() const { + static const std::string NO_STRING; + if (mDifferentialModel) { - return mAnalyserModel->voi()->variable()->units()->name(); + return mVoiUnit; } - return {}; + return NO_STRING; } size_t SedInstanceTask::Impl::stateCount() const { - return mAnalyserModel->stateCount(); + return mStateCount; } -Doubles SedInstanceTask::Impl::state(size_t pIndex) const +const Doubles &SedInstanceTask::Impl::state(size_t pIndex) const { - if (!mDifferentialModel || (pIndex >= mAnalyserModel->stateCount())) { - return {}; + static const Doubles NO_DOUBLES; + + if (!mDifferentialModel || (pIndex >= mStateCount)) { + return NO_DOUBLES; } return mResults.states[pIndex]; } -std::string SedInstanceTask::Impl::stateName(size_t pIndex) const +const std::string &SedInstanceTask::Impl::stateName(size_t pIndex) const { - if (!mDifferentialModel || (pIndex >= mAnalyserModel->stateCount())) { - return {}; + static const std::string NO_STRING; + + if (!mDifferentialModel || (pIndex >= mStateCount)) { + return NO_STRING; } - return name(mAnalyserModel->states()[pIndex]->variable()); + return mStateNames[pIndex]; } -std::string SedInstanceTask::Impl::stateUnit(size_t pIndex) const +const std::string &SedInstanceTask::Impl::stateUnit(size_t pIndex) const { - if (!mDifferentialModel || (pIndex >= mAnalyserModel->stateCount())) { - return {}; + static const std::string NO_STRING; + + if (!mDifferentialModel || (pIndex >= mStateCount)) { + return NO_STRING; } - return mAnalyserModel->states()[pIndex]->variable()->units()->name(); + return mStateUnits[pIndex]; } size_t SedInstanceTask::Impl::rateCount() const @@ -396,127 +482,151 @@ size_t SedInstanceTask::Impl::rateCount() const return stateCount(); } -Doubles SedInstanceTask::Impl::rate(size_t pIndex) const +const Doubles &SedInstanceTask::Impl::rate(size_t pIndex) const { - if (!mDifferentialModel || (pIndex >= mAnalyserModel->stateCount())) { - return {}; + static const Doubles NO_DOUBLES; + + if (!mDifferentialModel || (pIndex >= mStateCount)) { + return NO_DOUBLES; } return mResults.rates[pIndex]; } -std::string SedInstanceTask::Impl::rateName(size_t pIndex) const +const std::string &SedInstanceTask::Impl::rateName(size_t pIndex) const { - if (!mDifferentialModel || (pIndex >= mAnalyserModel->stateCount())) { - return {}; + static const std::string NO_STRING; + + if (!mDifferentialModel || (pIndex >= mStateCount)) { + return NO_STRING; } - return name(mAnalyserModel->states()[pIndex]->variable()) + "'"; + return mRateNames[pIndex]; } -std::string SedInstanceTask::Impl::rateUnit(size_t pIndex) const +const std::string &SedInstanceTask::Impl::rateUnit(size_t pIndex) const { - if (!mDifferentialModel || (pIndex >= mAnalyserModel->stateCount())) { - return {}; + static const std::string NO_STRING; + + if (!mDifferentialModel || (pIndex >= mStateCount)) { + return NO_STRING; } - return mAnalyserModel->states()[pIndex]->variable()->units()->name() + "/" + voiUnit(); + return mRateUnits[pIndex]; } size_t SedInstanceTask::Impl::constantCount() const { - return mAnalyserModel->constantCount(); + return mConstantCount; } -Doubles SedInstanceTask::Impl::constant(size_t pIndex) const +const Doubles &SedInstanceTask::Impl::constant(size_t pIndex) const { - if (pIndex >= mAnalyserModel->constantCount()) { - return {}; + static const Doubles NO_DOUBLES; + + if (pIndex >= mConstantCount) { + return NO_DOUBLES; } return mResults.constants[pIndex]; } -std::string SedInstanceTask::Impl::constantName(size_t pIndex) const +const std::string &SedInstanceTask::Impl::constantName(size_t pIndex) const { - if (pIndex >= mAnalyserModel->constantCount()) { - return {}; + static const std::string NO_STRING; + + if (pIndex >= mConstantCount) { + return NO_STRING; } - return name(mAnalyserModel->constants()[pIndex]->variable()); + return mConstantNames[pIndex]; } -std::string SedInstanceTask::Impl::constantUnit(size_t pIndex) const +const std::string &SedInstanceTask::Impl::constantUnit(size_t pIndex) const { - if (pIndex >= mAnalyserModel->constantCount()) { - return {}; + static const std::string NO_STRING; + + if (pIndex >= mConstantCount) { + return NO_STRING; } - return mAnalyserModel->constants()[pIndex]->variable()->units()->name(); + return mConstantUnits[pIndex]; } size_t SedInstanceTask::Impl::computedConstantCount() const { - return mAnalyserModel->computedConstantCount(); + return mComputedConstantCount; } -Doubles SedInstanceTask::Impl::computedConstant(size_t pIndex) const +const Doubles &SedInstanceTask::Impl::computedConstant(size_t pIndex) const { - if (pIndex >= mAnalyserModel->computedConstantCount()) { - return {}; + static const Doubles NO_DOUBLES; + + if (pIndex >= mComputedConstantCount) { + return NO_DOUBLES; } return mResults.computedConstants[pIndex]; } -std::string SedInstanceTask::Impl::computedConstantName(size_t pIndex) const +const std::string &SedInstanceTask::Impl::computedConstantName(size_t pIndex) const { - if (pIndex >= mAnalyserModel->computedConstantCount()) { - return {}; + static const std::string NO_STRING; + + if (pIndex >= mComputedConstantCount) { + return NO_STRING; } - return name(mAnalyserModel->computedConstants()[pIndex]->variable()); + return mComputedConstantNames[pIndex]; } -std::string SedInstanceTask::Impl::computedConstantUnit(size_t pIndex) const +const std::string &SedInstanceTask::Impl::computedConstantUnit(size_t pIndex) const { - if (pIndex >= mAnalyserModel->computedConstantCount()) { - return {}; + static const std::string NO_STRING; + + if (pIndex >= mComputedConstantCount) { + return NO_STRING; } - return mAnalyserModel->computedConstants()[pIndex]->variable()->units()->name(); + return mComputedConstantUnits[pIndex]; } size_t SedInstanceTask::Impl::algebraicVariableCount() const { - return mAnalyserModel->algebraicVariableCount(); + return mAlgebraicVariableCount; } -Doubles SedInstanceTask::Impl::algebraicVariable(size_t pIndex) const +const Doubles &SedInstanceTask::Impl::algebraicVariable(size_t pIndex) const { - if (pIndex >= mAnalyserModel->algebraicVariableCount()) { - return {}; + static const Doubles NO_DOUBLES; + + if (pIndex >= mAlgebraicVariableCount) { + return NO_DOUBLES; } return mResults.algebraic[pIndex]; } -std::string SedInstanceTask::Impl::algebraicVariableName(size_t pIndex) const +const std::string &SedInstanceTask::Impl::algebraicVariableName(size_t pIndex) const { - if (pIndex >= mAnalyserModel->algebraicVariableCount()) { - return {}; + static const std::string NO_STRING; + + if (pIndex >= mAlgebraicVariableCount) { + return NO_STRING; } - return name(mAnalyserModel->algebraicVariables()[pIndex]->variable()); + return mAlgebraicVariableNames[pIndex]; } -std::string SedInstanceTask::Impl::algebraicVariableUnit(size_t pIndex) const +const std::string &SedInstanceTask::Impl::algebraicVariableUnit(size_t pIndex) const { - if (pIndex >= mAnalyserModel->algebraicVariableCount()) { - return {}; + static const std::string NO_STRING; + + if (pIndex >= mAlgebraicVariableCount) { + return NO_STRING; } - return mAnalyserModel->algebraicVariables()[pIndex]->variable()->units()->name(); + return mAlgebraicVariableUnits[pIndex]; } SedInstanceTask::SedInstanceTask(const SedAbstractTaskPtr &pTask) @@ -539,24 +649,28 @@ const SedInstanceTask::Impl *SedInstanceTask::pimpl() const return static_cast(Logger::mPimpl); } -Doubles SedInstanceTask::voi() const +const Doubles &SedInstanceTask::voi() const { return pimpl()->voi(); } #ifdef __EMSCRIPTEN__ -emscripten::val SedInstanceTask::voiAsArray() const +const emscripten::val &SedInstanceTask::voiAsArray() const { - return toFloat64Array(voi()); + static thread_local emscripten::val res {emscripten::val::undefined()}; + + res = toFloat64Array(voi()); + + return res; } #endif -std::string SedInstanceTask::voiName() const +const std::string &SedInstanceTask::voiName() const { return pimpl()->voiName(); } -std::string SedInstanceTask::voiUnit() const +const std::string &SedInstanceTask::voiUnit() const { return pimpl()->voiUnit(); } @@ -566,24 +680,28 @@ size_t SedInstanceTask::stateCount() const return pimpl()->stateCount(); } -Doubles SedInstanceTask::state(size_t pIndex) const +const Doubles &SedInstanceTask::state(size_t pIndex) const { return pimpl()->state(pIndex); } #ifdef __EMSCRIPTEN__ -emscripten::val SedInstanceTask::stateAsArray(size_t pIndex) const +const emscripten::val &SedInstanceTask::stateAsArray(size_t pIndex) const { - return toFloat64Array(state(pIndex)); + static thread_local emscripten::val res {emscripten::val::undefined()}; + + res = toFloat64Array(state(pIndex)); + + return res; } #endif -std::string SedInstanceTask::stateName(size_t pIndex) const +const std::string &SedInstanceTask::stateName(size_t pIndex) const { return pimpl()->stateName(pIndex); } -std::string SedInstanceTask::stateUnit(size_t pIndex) const +const std::string &SedInstanceTask::stateUnit(size_t pIndex) const { return pimpl()->stateUnit(pIndex); } @@ -593,24 +711,28 @@ size_t SedInstanceTask::rateCount() const return pimpl()->rateCount(); } -Doubles SedInstanceTask::rate(size_t pIndex) const +const Doubles &SedInstanceTask::rate(size_t pIndex) const { return pimpl()->rate(pIndex); } #ifdef __EMSCRIPTEN__ -emscripten::val SedInstanceTask::rateAsArray(size_t pIndex) const +const emscripten::val &SedInstanceTask::rateAsArray(size_t pIndex) const { - return toFloat64Array(rate(pIndex)); + static thread_local emscripten::val res {emscripten::val::undefined()}; + + res = toFloat64Array(rate(pIndex)); + + return res; } #endif -std::string SedInstanceTask::rateName(size_t pIndex) const +const std::string &SedInstanceTask::rateName(size_t pIndex) const { return pimpl()->rateName(pIndex); } -std::string SedInstanceTask::rateUnit(size_t pIndex) const +const std::string &SedInstanceTask::rateUnit(size_t pIndex) const { return pimpl()->rateUnit(pIndex); } @@ -620,24 +742,28 @@ size_t SedInstanceTask::constantCount() const return pimpl()->constantCount(); } -Doubles SedInstanceTask::constant(size_t pIndex) const +const Doubles &SedInstanceTask::constant(size_t pIndex) const { return pimpl()->constant(pIndex); } #ifdef __EMSCRIPTEN__ -emscripten::val SedInstanceTask::constantAsArray(size_t pIndex) const +const emscripten::val &SedInstanceTask::constantAsArray(size_t pIndex) const { - return toFloat64Array(constant(pIndex)); + static thread_local emscripten::val res {emscripten::val::undefined()}; + + res = toFloat64Array(constant(pIndex)); + + return res; } #endif -std::string SedInstanceTask::constantName(size_t pIndex) const +const std::string &SedInstanceTask::constantName(size_t pIndex) const { return pimpl()->constantName(pIndex); } -std::string SedInstanceTask::constantUnit(size_t pIndex) const +const std::string &SedInstanceTask::constantUnit(size_t pIndex) const { return pimpl()->constantUnit(pIndex); } @@ -647,24 +773,28 @@ size_t SedInstanceTask::computedConstantCount() const return pimpl()->computedConstantCount(); } -Doubles SedInstanceTask::computedConstant(size_t pIndex) const +const Doubles &SedInstanceTask::computedConstant(size_t pIndex) const { return pimpl()->computedConstant(pIndex); } #ifdef __EMSCRIPTEN__ -emscripten::val SedInstanceTask::computedConstantAsArray(size_t pIndex) const +const emscripten::val &SedInstanceTask::computedConstantAsArray(size_t pIndex) const { - return toFloat64Array(computedConstant(pIndex)); + static thread_local emscripten::val res {emscripten::val::undefined()}; + + res = toFloat64Array(computedConstant(pIndex)); + + return res; } #endif -std::string SedInstanceTask::computedConstantName(size_t pIndex) const +const std::string &SedInstanceTask::computedConstantName(size_t pIndex) const { return pimpl()->computedConstantName(pIndex); } -std::string SedInstanceTask::computedConstantUnit(size_t pIndex) const +const std::string &SedInstanceTask::computedConstantUnit(size_t pIndex) const { return pimpl()->computedConstantUnit(pIndex); } @@ -674,24 +804,28 @@ size_t SedInstanceTask::algebraicVariableCount() const return pimpl()->algebraicVariableCount(); } -Doubles SedInstanceTask::algebraicVariable(size_t pIndex) const +const Doubles &SedInstanceTask::algebraicVariable(size_t pIndex) const { return pimpl()->algebraicVariable(pIndex); } #ifdef __EMSCRIPTEN__ -emscripten::val SedInstanceTask::algebraicVariableAsArray(size_t pIndex) const +const emscripten::val &SedInstanceTask::algebraicVariableAsArray(size_t pIndex) const { - return toFloat64Array(algebraicVariable(pIndex)); + static thread_local emscripten::val res {emscripten::val::undefined()}; + + res = toFloat64Array(algebraicVariable(pIndex)); + + return res; } #endif -std::string SedInstanceTask::algebraicVariableName(size_t pIndex) const +const std::string &SedInstanceTask::algebraicVariableName(size_t pIndex) const { return pimpl()->algebraicVariableName(pIndex); } -std::string SedInstanceTask::algebraicVariableUnit(size_t pIndex) const +const std::string &SedInstanceTask::algebraicVariableUnit(size_t pIndex) const { return pimpl()->algebraicVariableUnit(pIndex); } diff --git a/src/sed/sedinstancetask_p.h b/src/sed/sedinstancetask_p.h index 7ee992ba0..1567e46e9 100644 --- a/src/sed/sedinstancetask_p.h +++ b/src/sed/sedinstancetask_p.h @@ -50,6 +50,11 @@ class SedInstanceTask::Impl: public Logger::Impl SolverOdePtr mOdeSolver; SolverNlaPtr mNlaSolver; + size_t mStateCount {0}; + size_t mConstantCount {0}; + size_t mComputedConstantCount {0}; + size_t mAlgebraicVariableCount {0}; + double mVoi {0.0}; double *mStates {nullptr}; double *mRates {nullptr}; @@ -65,6 +70,19 @@ class SedInstanceTask::Impl: public Logger::Impl SedInstanceTaskResults mResults; + std::string mVoiName; + std::string mVoiUnit; + Strings mStateNames; + Strings mStateUnits; + Strings mRateNames; + Strings mRateUnits; + Strings mConstantNames; + Strings mConstantUnits; + Strings mComputedConstantNames; + Strings mComputedConstantUnits; + Strings mAlgebraicVariableNames; + Strings mAlgebraicVariableUnits; + static SedInstanceTaskPtr create(const SedAbstractTaskPtr &pTask); explicit Impl(const SedAbstractTaskPtr &pTask); @@ -75,34 +93,34 @@ class SedInstanceTask::Impl: public Logger::Impl void initialise(); double run(); - Doubles voi() const; - std::string voiName() const; - std::string voiUnit() const; + const Doubles &voi() const; + const std::string &voiName() const; + const std::string &voiUnit() const; size_t stateCount() const; - Doubles state(size_t pIndex) const; - std::string stateName(size_t pIndex) const; - std::string stateUnit(size_t pIndex) const; + const Doubles &state(size_t pIndex) const; + const std::string &stateName(size_t pIndex) const; + const std::string &stateUnit(size_t pIndex) const; size_t rateCount() const; - Doubles rate(size_t pIndex) const; - std::string rateName(size_t pIndex) const; - std::string rateUnit(size_t pIndex) const; + const Doubles &rate(size_t pIndex) const; + const std::string &rateName(size_t pIndex) const; + const std::string &rateUnit(size_t pIndex) const; size_t constantCount() const; - Doubles constant(size_t pIndex) const; - std::string constantName(size_t pIndex) const; - std::string constantUnit(size_t pIndex) const; + const Doubles &constant(size_t pIndex) const; + const std::string &constantName(size_t pIndex) const; + const std::string &constantUnit(size_t pIndex) const; size_t computedConstantCount() const; - Doubles computedConstant(size_t pIndex) const; - std::string computedConstantName(size_t pIndex) const; - std::string computedConstantUnit(size_t pIndex) const; + const Doubles &computedConstant(size_t pIndex) const; + const std::string &computedConstantName(size_t pIndex) const; + const std::string &computedConstantUnit(size_t pIndex) const; size_t algebraicVariableCount() const; - Doubles algebraicVariable(size_t pIndex) const; - std::string algebraicVariableName(size_t pIndex) const; - std::string algebraicVariableUnit(size_t pIndex) const; + const Doubles &algebraicVariable(size_t pIndex) const; + const std::string &algebraicVariableName(size_t pIndex) const; + const std::string &algebraicVariableUnit(size_t pIndex) const; }; } // namespace libOpenCOR diff --git a/src/sed/sedmodel.cpp b/src/sed/sedmodel.cpp index 565478afb..d90dbe7e7 100644 --- a/src/sed/sedmodel.cpp +++ b/src/sed/sedmodel.cpp @@ -33,7 +33,7 @@ SedModel::Impl::Impl(const SedDocumentPtr &pDocument, const FilePtr &pFile) { } -FilePtr SedModel::Impl::file() const +const FilePtr &SedModel::Impl::file() const { return mFile; } @@ -80,15 +80,17 @@ size_t SedModel::Impl::changeCount() const return mChanges.size(); } -SedChangePtrs SedModel::Impl::changes() const +const SedChangePtrs &SedModel::Impl::changes() const { return mChanges; } -SedChangePtr SedModel::Impl::change(size_t pIndex) const +const SedChangePtr &SedModel::Impl::change(size_t pIndex) const { + static const SedChangePtr NO_SED_CHANGE_PTR; + if (pIndex >= mChanges.size()) { - return {}; + return NO_SED_CHANGE_PTR; } return mChanges[pIndex]; @@ -204,7 +206,7 @@ SedModelPtr SedModel::create(const SedDocumentPtr &pDocument, const FilePtr &pFi return SedModelPtr {new SedModel {pDocument, pFile}}; } -FilePtr SedModel::file() const +const FilePtr &SedModel::file() const { return pimpl()->file(); } @@ -219,12 +221,12 @@ size_t SedModel::changeCount() const return pimpl()->changeCount(); } -SedChangePtrs SedModel::changes() const +const SedChangePtrs &SedModel::changes() const { return pimpl()->changes(); } -SedChangePtr SedModel::change(size_t pIndex) const +const SedChangePtr &SedModel::change(size_t pIndex) const { return pimpl()->change(pIndex); } diff --git a/src/sed/sedmodel_p.h b/src/sed/sedmodel_p.h index bd2ea09d3..70cb6ec7c 100644 --- a/src/sed/sedmodel_p.h +++ b/src/sed/sedmodel_p.h @@ -32,14 +32,14 @@ class SedModel::Impl: public SedBase::Impl explicit Impl(const SedDocumentPtr &pDocument, const FilePtr &pFile); - FilePtr file() const; + const FilePtr &file() const; bool isValid(); bool hasChanges() const; size_t changeCount() const; - SedChangePtrs changes() const; - SedChangePtr change(size_t pIndex) const; + const SedChangePtrs &changes() const; + const SedChangePtr &change(size_t pIndex) const; bool addChange(const SedChangePtr &pChange); bool removeChange(const SedChangePtr &pChange); bool removeAllChanges(); diff --git a/src/sed/sedsimulation.cpp b/src/sed/sedsimulation.cpp index 7a45906f2..b970e9864 100644 --- a/src/sed/sedsimulation.cpp +++ b/src/sed/sedsimulation.cpp @@ -33,25 +33,42 @@ SedSimulation::Impl::Impl(const SedDocumentPtr &pDocument) bool SedSimulation::Impl::isValid(const SedModelPtr &pModel) { auto modelType {pModel->pimpl()->mFile->pimpl()->mCellmlFile->type()}; + const auto &modelId = pModel->pimpl()->mId; + + auto addMissingSolverError = [&](const char *pSolverType) { + std::string error; + + error.reserve(mId.size() + modelId.size() + 96); // NOLINT + + error += "Simulation '"; + error += mId; + error += "' is to be used with model '"; + error += modelId; + error += "' which requires an "; + error += pSolverType; + error += " solver but none is provided."; + + addError(error); + }; if ((modelType == libcellml::AnalyserModel::Type::ODE) && (mOdeSolver == nullptr)) { - addError(std::string("Simulation '").append(mId).append("' is to be used with model '").append(pModel->pimpl()->mId).append("' which requires an ODE solver but none is provided.")); + addMissingSolverError("ODE"); } else if ((modelType == libcellml::AnalyserModel::Type::NLA) && (mNlaSolver == nullptr)) { - addError(std::string("Simulation '").append(mId).append("' is to be used with model '").append(pModel->pimpl()->mId).append("' which requires an NLA solver but none is provided.")); + addMissingSolverError("NLA"); } else if (modelType == libcellml::AnalyserModel::Type::DAE) { if (mOdeSolver == nullptr) { - addError(std::string("Simulation '").append(mId).append("' is to be used with model '").append(pModel->pimpl()->mId).append("' which requires an ODE solver but none is provided.")); + addMissingSolverError("ODE"); } if (mNlaSolver == nullptr) { - addError(std::string("Simulation '").append(mId).append("' is to be used with model '").append(pModel->pimpl()->mId).append("' which requires an NLA solver but none is provided.")); + addMissingSolverError("NLA"); } } return !hasErrors(); } -SolverOdePtr SedSimulation::Impl::odeSolver() const +const SolverOdePtr &SedSimulation::Impl::odeSolver() const { return mOdeSolver; } @@ -61,7 +78,7 @@ void SedSimulation::Impl::setOdeSolver(const SolverOdePtr &pOdeSolver) mOdeSolver = pOdeSolver; } -SolverNlaPtr SedSimulation::Impl::nlaSolver() const +const SolverNlaPtr &SedSimulation::Impl::nlaSolver() const { return mNlaSolver; } @@ -101,7 +118,7 @@ const SedSimulation::Impl *SedSimulation::pimpl() const return static_cast(SedBase::pimpl()); } -SolverOdePtr SedSimulation::odeSolver() const +const SolverOdePtr &SedSimulation::odeSolver() const { return pimpl()->odeSolver(); } @@ -111,7 +128,7 @@ void SedSimulation::setOdeSolver(const SolverOdePtr &pOdeSolver) pimpl()->setOdeSolver(pOdeSolver); } -SolverNlaPtr SedSimulation::nlaSolver() const +const SolverNlaPtr &SedSimulation::nlaSolver() const { return pimpl()->nlaSolver(); } diff --git a/src/sed/sedsimulation_p.h b/src/sed/sedsimulation_p.h index eac2e6114..a357dab58 100644 --- a/src/sed/sedsimulation_p.h +++ b/src/sed/sedsimulation_p.h @@ -32,10 +32,10 @@ class SedSimulation::Impl: public SedBase::Impl bool isValid(const SedModelPtr &pModel); - SolverOdePtr odeSolver() const; + const SolverOdePtr &odeSolver() const; void setOdeSolver(const SolverOdePtr &pOdeSolver); - SolverNlaPtr nlaSolver() const; + const SolverNlaPtr &nlaSolver() const; void setNlaSolver(const SolverNlaPtr &pNlaSolver); void serialise(xmlNodePtr pNode) const override; diff --git a/src/sed/sedtask.cpp b/src/sed/sedtask.cpp index 9a71d5ba4..f36b17fa9 100644 --- a/src/sed/sedtask.cpp +++ b/src/sed/sedtask.cpp @@ -33,14 +33,27 @@ SedTask::Impl::Impl(const SedDocumentPtr &pDocument, const SedModelPtr &pModel, bool SedTask::Impl::isValid() { + auto addTaskError = [&](const char *pMessage) { + std::string error; + + error.reserve(mId.size() + 32 + std::string(pMessage).size()); // NOLINT + + error += "Task '"; + error += mId; + error += "' "; + error += pMessage; + + addError(error); + }; + // Make sure that we have both a model and a simulation. if (mModel == nullptr) { - addError(std::string("Task '").append(mId).append("' requires a model.")); + addTaskError("requires a model."); } if (mSimulation == nullptr) { - addError(std::string("Task '").append(mId).append("' requires a simulation.")); + addTaskError("requires a simulation."); } if (hasIssues()) { @@ -50,7 +63,7 @@ bool SedTask::Impl::isValid() // Make sure that the model is of CellML type. if (mModel->pimpl()->mFile->type() != File::Type::CELLML_FILE) { - addError(std::string("Task '").append(mId).append("' requires a model of CellML type.")); + addTaskError("requires a model of CellML type."); return false; } @@ -70,7 +83,7 @@ bool SedTask::Impl::isValid() return !hasIssues(); } -SedModelPtr SedTask::Impl::model() const +const SedModelPtr &SedTask::Impl::model() const { return mModel; } @@ -80,7 +93,7 @@ void SedTask::Impl::setModel(const SedModelPtr &pModel) mModel = pModel; } -SedSimulationPtr SedTask::Impl::simulation() const +const SedSimulationPtr &SedTask::Impl::simulation() const { return mSimulation; } @@ -133,7 +146,7 @@ SedTaskPtr SedTask::create(const SedDocumentPtr &pDocument, const SedModelPtr &p return SedTaskPtr {new SedTask {pDocument, pModel, pSimulation}}; } -SedModelPtr SedTask::model() const +const SedModelPtr &SedTask::model() const { return pimpl()->model(); } @@ -143,7 +156,7 @@ void SedTask::setModel(const SedModelPtr &pModel) pimpl()->setModel(pModel); } -SedSimulationPtr SedTask::simulation() const +const SedSimulationPtr &SedTask::simulation() const { return pimpl()->simulation(); } diff --git a/src/sed/sedtask_p.h b/src/sed/sedtask_p.h index 11f0722a9..577a7278c 100644 --- a/src/sed/sedtask_p.h +++ b/src/sed/sedtask_p.h @@ -32,10 +32,10 @@ class SedTask::Impl: public SedAbstractTask::Impl bool isValid() override; - SedModelPtr model() const; + const SedModelPtr &model() const; void setModel(const SedModelPtr &pModel); - SedSimulationPtr simulation() const; + const SedSimulationPtr &simulation() const; void setSimulation(const SedSimulationPtr &pSimulation); void serialise(xmlNodePtr pNode) const override; diff --git a/src/solver/solver.cpp b/src/solver/solver.cpp index a363f0620..370443799 100644 --- a/src/solver/solver.cpp +++ b/src/solver/solver.cpp @@ -24,12 +24,12 @@ Solver::Impl::Impl(const std::string &pId, const std::string &pName) { } -std::string Solver::Impl::id() const +const std::string &Solver::Impl::id() const { return mId; } -std::string Solver::Impl::name() const +const std::string &Solver::Impl::name() const { return mName; } @@ -79,12 +79,12 @@ const Solver::Impl *Solver::pimpl() const return static_cast(Logger::mPimpl); } -std::string Solver::id() const +const std::string &Solver::id() const { return pimpl()->id(); } -std::string Solver::name() const +const std::string &Solver::name() const { return pimpl()->name(); } diff --git a/src/solver/solver_p.h b/src/solver/solver_p.h index 95b8e82bd..f70c39515 100644 --- a/src/solver/solver_p.h +++ b/src/solver/solver_p.h @@ -44,8 +44,8 @@ class Solver::Impl: public Logger::Impl virtual void populate(libsedml::SedAlgorithm *pAlgorithm) = 0; - std::string id() const; - std::string name() const; + const std::string &id() const; + const std::string &name() const; void serialise(xmlNodePtr pNode, bool pNlaAlgorithm = false) const; diff --git a/src/solver/solvercvode.cpp b/src/solver/solvercvode.cpp index 5ed0cb63a..f72940c1f 100644 --- a/src/solver/solvercvode.cpp +++ b/src/solver/solvercvode.cpp @@ -133,16 +133,41 @@ SolverCvode::Impl::~Impl() void SolverCvode::Impl::populate(libsedml::SedAlgorithm *pAlgorithm) { + auto addUnknownParameterWarning = [&](const std::string &pKisaoId) { + std::string warning; + + warning.reserve(pKisaoId.size() + 49); // NOLINT + + warning += "The parameter '"; + warning += pKisaoId; + warning += "' is not recognised. It will be ignored."; + + addWarning(warning); + }; + for (unsigned int i {0}; i < pAlgorithm->getNumAlgorithmParameters(); ++i) { auto *algorithmParameter {pAlgorithm->getAlgorithmParameter(i)}; - auto kisaoId {algorithmParameter->getKisaoID()}; + const auto &kisaoId {algorithmParameter->getKisaoID()}; auto value {algorithmParameter->getValue()}; if (kisaoId == "KISAO:0000467") { mMaximumStep = toDouble(value); if ((mMaximumStep < 0.0) || std::isnan(mMaximumStep)) { - addWarning(std::string("The maximum step ('").append(kisaoId).append("') cannot be equal to '").append(value).append("'. It must be greater or equal to 0. A maximum step of ").append(toString(DEFAULT_MAXIMUM_STEP)).append(" will be used instead.")); + const auto defaultMaximumStep {toString(DEFAULT_MAXIMUM_STEP)}; + std::string warning; + + warning.reserve(kisaoId.size() + value.size() + defaultMaximumStep.size() + 98); // NOLINT + + warning += "The maximum step ('"; + warning += kisaoId; + warning += "') cannot be equal to '"; + warning += value; + warning += "'. It must be greater or equal to 0. A maximum step of "; + warning += defaultMaximumStep; + warning += " will be used instead."; + + addWarning(warning); mMaximumStep = DEFAULT_MAXIMUM_STEP; } @@ -150,13 +175,39 @@ void SolverCvode::Impl::populate(libsedml::SedAlgorithm *pAlgorithm) mMaximumNumberOfSteps = toInt(value); if (!isInt(value) || (mMaximumNumberOfSteps <= 0)) { - addWarning(std::string("The maximum number of steps ('").append(kisaoId).append("') cannot be equal to '").append(value).append("'. It must be greater than 0. A maximum number of steps of ").append(toString(DEFAULT_MAXIMUM_NUMBER_OF_STEPS)).append(" will be used instead.")); + const auto defaultMaximumNumberOfSteps {toString(DEFAULT_MAXIMUM_NUMBER_OF_STEPS)}; + std::string warning; + + warning.reserve(kisaoId.size() + value.size() + defaultMaximumNumberOfSteps.size() + 123); // NOLINT + + warning += "The maximum number of steps ('"; + warning += kisaoId; + warning += "') cannot be equal to '"; + warning += value; + warning += "'. It must be greater than 0. A maximum number of steps of "; + warning += defaultMaximumNumberOfSteps; + warning += " will be used instead."; + + addWarning(warning); mMaximumNumberOfSteps = DEFAULT_MAXIMUM_NUMBER_OF_STEPS; } } else if (kisaoId == "KISAO:0000475") { if ((value != "BDF") && (value != "Adams-Moulton")) { - addWarning(std::string("The integration method ('").append(kisaoId).append("') cannot be equal to '").append(value).append("'. It must be equal to 'BDF' or 'Adams-Moulton'. A ").append(toString(DEFAULT_INTEGRATION_METHOD)).append(" integration method will be used instead.")); + const auto defaultIntegrationMethod {toString(DEFAULT_INTEGRATION_METHOD)}; + std::string warning; + + warning.reserve(kisaoId.size() + value.size() + defaultIntegrationMethod.size() + 116); // NOLINT + + warning += "The integration method ('"; + warning += kisaoId; + warning += "') cannot be equal to '"; + warning += value; + warning += "'. It must be equal to 'BDF' or 'Adams-Moulton'. A "; + warning += defaultIntegrationMethod; + warning += " integration method will be used instead."; + + addWarning(warning); value = toString(DEFAULT_INTEGRATION_METHOD); } @@ -166,7 +217,20 @@ void SolverCvode::Impl::populate(libsedml::SedAlgorithm *pAlgorithm) SolverCvode::IntegrationMethod::ADAMS_MOULTON; } else if (kisaoId == "KISAO:0000476") { if ((value != "Functional") && (value != "Newton")) { - addWarning(std::string("The iteration type ('").append(kisaoId).append("') cannot be equal to '").append(value).append("'. It must be equal to 'Functional' or 'Newton'. A ").append(toString(DEFAULT_ITERATION_TYPE)).append(" iteration type will be used instead.")); + const auto defaultIterationType {toString(DEFAULT_ITERATION_TYPE)}; + std::string warning; + + warning.reserve(kisaoId.size() + value.size() + defaultIterationType.size() + 112); // NOLINT + + warning += "The iteration type ('"; + warning += kisaoId; + warning += "') cannot be equal to '"; + warning += value; + warning += "'. It must be equal to 'Functional' or 'Newton'. A "; + warning += defaultIterationType; + warning += " iteration type will be used instead."; + + addWarning(warning); value = toString(DEFAULT_ITERATION_TYPE); } @@ -176,7 +240,20 @@ void SolverCvode::Impl::populate(libsedml::SedAlgorithm *pAlgorithm) SolverCvode::IterationType::NEWTON; } else if (kisaoId == "KISAO:0000477") { if ((value != "Dense") && (value != "Banded") && (value != "Diagonal") && (value != "GMRES") && (value != "BiCGStab") && (value != "TFQMR")) { - addWarning(std::string("The linear solver ('").append(kisaoId).append("') cannot be equal to '").append(value).append("'. It must be equal to 'Dense', 'Banded', 'Diagonal', 'GMRES', 'BiCGStab', or 'TFQMR'. A ").append(toString(DEFAULT_LINEAR_SOLVER)).append(" linear solver will be used instead.")); + const auto defaultLinearSolver {toString(DEFAULT_LINEAR_SOLVER)}; + std::string warning; + + warning.reserve(kisaoId.size() + value.size() + defaultLinearSolver.size() + 157); // NOLINT + + warning += "The linear solver ('"; + warning += kisaoId; + warning += "') cannot be equal to '"; + warning += value; + warning += "'. It must be equal to 'Dense', 'Banded', 'Diagonal', 'GMRES', 'BiCGStab', or 'TFQMR'. A "; + warning += defaultLinearSolver; + warning += " linear solver will be used instead."; + + addWarning(warning); value = toString(DEFAULT_LINEAR_SOLVER); } @@ -194,7 +271,20 @@ void SolverCvode::Impl::populate(libsedml::SedAlgorithm *pAlgorithm) SolverCvode::LinearSolver::TFQMR; } else if (kisaoId == "KISAO:0000478") { if ((value != "No") && (value != "Banded")) { - addWarning(std::string("The preconditioner ('").append(kisaoId).append("') cannot be equal to '").append(value).append("'. It must be equal to 'No' or 'Banded'. A ").append(toString(DEFAULT_PRECONDITIONER)).append(" preconditioner will be used instead.")); + const auto defaultPreconditioner {toString(DEFAULT_PRECONDITIONER)}; + std::string warning; + + warning.reserve(kisaoId.size() + value.size() + defaultPreconditioner.size() + 108); // NOLINT + + warning += "The preconditioner ('"; + warning += kisaoId; + warning += "') cannot be equal to '"; + warning += value; + warning += "'. It must be equal to 'No' or 'Banded'. A "; + warning += defaultPreconditioner; + warning += " preconditioner will be used instead."; + + addWarning(warning); value = toString(DEFAULT_PRECONDITIONER); } @@ -206,7 +296,20 @@ void SolverCvode::Impl::populate(libsedml::SedAlgorithm *pAlgorithm) mUpperHalfBandwidth = toInt(value); if (!isInt(value) || (mUpperHalfBandwidth < 0)) { - addWarning(std::string("The upper half-bandwidth ('").append(kisaoId).append("') cannot be equal to '").append(value).append("'. It must be greater or equal to 0. An upper half-bandwidth of ").append(toString(DEFAULT_UPPER_HALF_BANDWIDTH)).append(" will be used instead.")); + const auto defaultUpperHalfBandwidth {toString(DEFAULT_UPPER_HALF_BANDWIDTH)}; + std::string warning; + + warning.reserve(kisaoId.size() + value.size() + defaultUpperHalfBandwidth.size() + 113); // NOLINT + + warning += "The upper half-bandwidth ('"; + warning += kisaoId; + warning += "') cannot be equal to '"; + warning += value; + warning += "'. It must be greater or equal to 0. An upper half-bandwidth of "; + warning += defaultUpperHalfBandwidth; + warning += " will be used instead."; + + addWarning(warning); mUpperHalfBandwidth = DEFAULT_UPPER_HALF_BANDWIDTH; } @@ -214,7 +317,20 @@ void SolverCvode::Impl::populate(libsedml::SedAlgorithm *pAlgorithm) mLowerHalfBandwidth = toInt(value); if (!isInt(value) || (mLowerHalfBandwidth < 0)) { - addWarning(std::string("The lower half-bandwidth ('").append(kisaoId).append("') cannot be equal to '").append(value).append("'. It must be greater or equal to 0. A lower half-bandwidth of ").append(toString(DEFAULT_LOWER_HALF_BANDWIDTH)).append(" will be used instead.")); + const auto defaultLowerHalfBandwidth {toString(DEFAULT_LOWER_HALF_BANDWIDTH)}; + std::string warning; + + warning.reserve(kisaoId.size() + value.size() + defaultLowerHalfBandwidth.size() + 112); // NOLINT + + warning += "The lower half-bandwidth ('"; + warning += kisaoId; + warning += "') cannot be equal to '"; + warning += value; + warning += "'. It must be greater or equal to 0. A lower half-bandwidth of "; + warning += defaultLowerHalfBandwidth; + warning += " will be used instead."; + + addWarning(warning); mLowerHalfBandwidth = DEFAULT_LOWER_HALF_BANDWIDTH; } @@ -222,7 +338,20 @@ void SolverCvode::Impl::populate(libsedml::SedAlgorithm *pAlgorithm) mRelativeTolerance = toDouble(value); if ((mRelativeTolerance < 0.0) || std::isnan(mRelativeTolerance)) { - addWarning(std::string("The relative tolerance ('").append(kisaoId).append("') cannot be equal to '").append(value).append("'. It must be greater or equal to 0. A relative tolerance of ").append(toString(DEFAULT_RELATIVE_TOLERANCE)).append(" will be used instead.")); + const auto defaultRelativeTolerance {toString(DEFAULT_RELATIVE_TOLERANCE)}; + std::string warning; + + warning.reserve(kisaoId.size() + value.size() + defaultRelativeTolerance.size() + 112); // NOLINT + + warning += "The relative tolerance ('"; + warning += kisaoId; + warning += "') cannot be equal to '"; + warning += value; + warning += "'. It must be greater or equal to 0. A relative tolerance of "; + warning += defaultRelativeTolerance; + warning += " will be used instead."; + + addWarning(warning); mRelativeTolerance = DEFAULT_RELATIVE_TOLERANCE; } @@ -230,20 +359,46 @@ void SolverCvode::Impl::populate(libsedml::SedAlgorithm *pAlgorithm) mAbsoluteTolerance = toDouble(value); if ((mAbsoluteTolerance < 0.0) || std::isnan(mAbsoluteTolerance)) { - addWarning(std::string("The absolute tolerance ('").append(kisaoId).append("') cannot be equal to '").append(value).append("'. It must be greater or equal to 0. An absolute tolerance of ").append(toString(DEFAULT_ABSOLUTE_TOLERANCE)).append(" will be used instead.")); + const auto defaultAbsoluteTolerance {toString(DEFAULT_ABSOLUTE_TOLERANCE)}; + std::string warning; + + warning.reserve(kisaoId.size() + value.size() + defaultAbsoluteTolerance.size() + 113); // NOLINT + + warning += "The absolute tolerance ('"; + warning += kisaoId; + warning += "') cannot be equal to '"; + warning += value; + warning += "'. It must be greater or equal to 0. An absolute tolerance of "; + warning += defaultAbsoluteTolerance; + warning += " will be used instead."; + + addWarning(warning); mAbsoluteTolerance = DEFAULT_ABSOLUTE_TOLERANCE; } } else if (kisaoId == "KISAO:0000481") { if ((value != "true") && (value != "false")) { - addWarning(std::string("The interpolate solution parameter ('").append(kisaoId).append("') cannot be equal to '").append(value).append("'. It must be equal to 'true' or 'false'. A value of ").append(toString(DEFAULT_INTERPOLATE_SOLUTION)).append(" will be used instead.")); + const auto defaultInterpolateSolution {toString(DEFAULT_INTERPOLATE_SOLUTION)}; + std::string warning; + + warning.reserve(kisaoId.size() + value.size() + defaultInterpolateSolution.size() + 121); // NOLINT + + warning += "The interpolate solution parameter ('"; + warning += kisaoId; + warning += "') cannot be equal to '"; + warning += value; + warning += "'. It must be equal to 'true' or 'false'. A value of "; + warning += defaultInterpolateSolution; + warning += " will be used instead."; + + addWarning(warning); value = toString(DEFAULT_INTERPOLATE_SOLUTION); } mInterpolateSolution = toBool(value); } else { - addWarning(std::string("The parameter '").append(kisaoId).append("' is not recognised. It will be ignored.")); + addUnknownParameterWarning(kisaoId); } } } @@ -319,11 +474,29 @@ bool SolverCvode::Impl::initialise(double pVoi, size_t pSize, double *pStates, d // Check the solver's properties. if (mMaximumStep < 0.0) { - addError(std::string("The maximum step cannot be equal to ").append(toString(mMaximumStep)).append(". It must be greater or equal to 0.")); + const auto maximumStep {toString(mMaximumStep)}; + std::string error; + + error.reserve(maximumStep.size() + 61); // NOLINT + + error += "The maximum step cannot be equal to "; + error += maximumStep; + error += ". It must be greater or equal to 0."; + + addError(error); } if (mMaximumNumberOfSteps <= 0) { - addError(std::string("The maximum number of steps cannot be equal to ").append(toString(mMaximumNumberOfSteps)).append(". It must be greater than 0.")); + const auto maximumNumberOfSteps {toString(mMaximumNumberOfSteps)}; + std::string error; + + error.reserve(maximumNumberOfSteps.size() + 67); // NOLINT + + error += "The maximum number of steps cannot be equal to "; + error += maximumNumberOfSteps; + error += ". It must be greater than 0."; + + addError(error); } if (mIterationType == IterationType::NEWTON) { @@ -349,21 +522,63 @@ bool SolverCvode::Impl::initialise(double pVoi, size_t pSize, double *pStates, d if (needUpperAndLowerHalfBandwidths) { if ((mUpperHalfBandwidth < 0) || std::cmp_greater_equal(mUpperHalfBandwidth, pSize)) { - addError(std::string("The upper half-bandwidth cannot be equal to ").append(toString(mUpperHalfBandwidth)).append(". It must be between 0 and ").append(toString(pSize - 1)).append(".")); + const auto upperHalfBandwidth {toString(mUpperHalfBandwidth)}; + const auto maximumUpperHalfBandwidth {toString(pSize - 1)}; + std::string error; + + error.reserve(upperHalfBandwidth.size() + maximumUpperHalfBandwidth.size() + 62); // NOLINT + + error += "The upper half-bandwidth cannot be equal to "; + error += upperHalfBandwidth; + error += ". It must be between 0 and "; + error += maximumUpperHalfBandwidth; + error += "."; + + addError(error); } if ((mLowerHalfBandwidth < 0) || std::cmp_greater_equal(mLowerHalfBandwidth, pSize)) { - addError(std::string("The lower half-bandwidth cannot be equal to ").append(toString(mLowerHalfBandwidth)).append(". It must be between 0 and ").append(toString(pSize - 1)).append(".")); + const auto lowerHalfBandwidth {toString(mLowerHalfBandwidth)}; + const auto maximumLowerHalfBandwidth {toString(pSize - 1)}; + std::string error; + + error.reserve(lowerHalfBandwidth.size() + maximumLowerHalfBandwidth.size() + 62); // NOLINT + + error += "The lower half-bandwidth cannot be equal to "; + error += lowerHalfBandwidth; + error += ". It must be between 0 and "; + error += maximumLowerHalfBandwidth; + error += "."; + + addError(error); } } } if (mRelativeTolerance < 0.0) { - addError(std::string("The relative tolerance cannot be equal to ").append(toString(mRelativeTolerance)).append(". It must be greater or equal to 0.")); + const auto relativeTolerance {toString(mRelativeTolerance)}; + std::string error; + + error.reserve(relativeTolerance.size() + 66); // NOLINT + + error += "The relative tolerance cannot be equal to "; + error += relativeTolerance; + error += ". It must be greater or equal to 0."; + + addError(error); } if (mAbsoluteTolerance < 0.0) { - addError(std::string("The absolute tolerance cannot be equal to ").append(toString(mAbsoluteTolerance)).append(". It must be greater or equal to 0.")); + const auto absoluteTolerance {toString(mAbsoluteTolerance)}; + std::string error; + + error.reserve(absoluteTolerance.size() + 66); // NOLINT + + error += "The absolute tolerance cannot be equal to "; + error += absoluteTolerance; + error += ". It must be greater or equal to 0."; + + addError(error); } // Check whether we got some errors. diff --git a/src/solver/solverkinsol.cpp b/src/solver/solverkinsol.cpp index 83427b8b5..e3f08a4d8 100644 --- a/src/solver/solverkinsol.cpp +++ b/src/solver/solverkinsol.cpp @@ -127,22 +127,60 @@ SolverKinsol::Impl::Impl() void SolverKinsol::Impl::populate(libsedml::SedAlgorithm *pAlgorithm) { + auto addUnknownParameterWarning = [&](const std::string &pKisaoId) { + std::string warning; + + warning.reserve(pKisaoId.size() + 49); // NOLINT + + warning += "The parameter '"; + warning += pKisaoId; + warning += "' is not recognised. It will be ignored."; + + addWarning(warning); + }; + for (unsigned int i {0}; i < pAlgorithm->getNumAlgorithmParameters(); ++i) { auto *algorithmParameter {pAlgorithm->getAlgorithmParameter(i)}; - auto kisaoId {algorithmParameter->getKisaoID()}; + const auto &kisaoId {algorithmParameter->getKisaoID()}; auto value {algorithmParameter->getValue()}; if (kisaoId == "KISAO:0000486") { mMaximumNumberOfIterations = toInt(value); if (!isInt(value) || (mMaximumNumberOfIterations <= 0)) { - addWarning(std::string("The maximum number of iterations ('").append(kisaoId).append("') cannot be equal to '").append(value).append("'. It must be greater than 0. A maximum number of iterations of ").append(toString(DEFAULT_MAXIMUM_NUMBER_OF_ITERATIONS)).append(" will be used instead.")); + const auto defaultIterations {toString(DEFAULT_MAXIMUM_NUMBER_OF_ITERATIONS)}; + std::string warning; + + warning.reserve(kisaoId.size() + value.size() + defaultIterations.size() + 130); // NOLINT + + warning += "The maximum number of iterations ('"; + warning += kisaoId; + warning += "') cannot be equal to '"; + warning += value; + warning += "'. It must be greater than 0. A maximum number of iterations of "; + warning += defaultIterations; + warning += " will be used instead."; + + addWarning(warning); mMaximumNumberOfIterations = DEFAULT_MAXIMUM_NUMBER_OF_ITERATIONS; } } else if (kisaoId == "KISAO:0000477") { if ((value != "Dense") && (value != "Banded") && (value != "GMRES") && (value != "BiCGStab") && (value != "TFQMR")) { - addWarning(std::string("The linear solver ('").append(kisaoId).append("') cannot be equal to '").append(value).append("'. It must be equal to 'Dense', 'Banded', 'GMRES', 'BiCGStab', or 'TFQMR'. A ").append(toString(DEFAULT_LINEAR_SOLVER)).append(" linear solver will be used instead.")); + const auto defaultLinearSolver {toString(DEFAULT_LINEAR_SOLVER)}; + std::string warning; + + warning.reserve(kisaoId.size() + value.size() + defaultLinearSolver.size() + 146); // NOLINT + + warning += "The linear solver ('"; + warning += kisaoId; + warning += "') cannot be equal to '"; + warning += value; + warning += "'. It must be equal to 'Dense', 'Banded', 'GMRES', 'BiCGStab', or 'TFQMR'. A "; + warning += defaultLinearSolver; + warning += " linear solver will be used instead."; + + addWarning(warning); value = toString(DEFAULT_LINEAR_SOLVER); } @@ -160,7 +198,20 @@ void SolverKinsol::Impl::populate(libsedml::SedAlgorithm *pAlgorithm) mUpperHalfBandwidth = toInt(value); if (!isInt(value) || (mUpperHalfBandwidth < 0)) { - addWarning(std::string("The upper half-bandwidth ('").append(kisaoId).append("') cannot be equal to '").append(value).append("'. It must be greater or equal to 0. An upper half-bandwidth of ").append(toString(DEFAULT_UPPER_HALF_BANDWIDTH)).append(" will be used instead.")); + const auto defaultUpperHalfBandwidth {toString(DEFAULT_UPPER_HALF_BANDWIDTH)}; + std::string warning; + + warning.reserve(kisaoId.size() + value.size() + defaultUpperHalfBandwidth.size() + 113); // NOLINT + + warning += "The upper half-bandwidth ('"; + warning += kisaoId; + warning += "') cannot be equal to '"; + warning += value; + warning += "'. It must be greater or equal to 0. An upper half-bandwidth of "; + warning += defaultUpperHalfBandwidth; + warning += " will be used instead."; + + addWarning(warning); mUpperHalfBandwidth = DEFAULT_UPPER_HALF_BANDWIDTH; } @@ -168,12 +219,25 @@ void SolverKinsol::Impl::populate(libsedml::SedAlgorithm *pAlgorithm) mLowerHalfBandwidth = toInt(value); if (!isInt(value) || (mLowerHalfBandwidth < 0)) { - addWarning(std::string("The lower half-bandwidth ('").append(kisaoId).append("') cannot be equal to '").append(value).append("'. It must be greater or equal to 0. A lower half-bandwidth of ").append(toString(DEFAULT_LOWER_HALF_BANDWIDTH)).append(" will be used instead.")); + const auto defaultLowerHalfBandwidth {toString(DEFAULT_LOWER_HALF_BANDWIDTH)}; + std::string warning; + + warning.reserve(kisaoId.size() + value.size() + defaultLowerHalfBandwidth.size() + 112); // NOLINT + + warning += "The lower half-bandwidth ('"; + warning += kisaoId; + warning += "') cannot be equal to '"; + warning += value; + warning += "'. It must be greater or equal to 0. A lower half-bandwidth of "; + warning += defaultLowerHalfBandwidth; + warning += " will be used instead."; + + addWarning(warning); mLowerHalfBandwidth = DEFAULT_LOWER_HALF_BANDWIDTH; } } else { - addWarning(std::string("The parameter '").append(kisaoId).append("' is not recognised. It will be ignored.")); + addUnknownParameterWarning(kisaoId); } } } @@ -255,7 +319,16 @@ bool SolverKinsol::Impl::solve(ComputeObjectiveFunction pComputeObjectiveFunctio // solver's properties are all valid. if (mMaximumNumberOfIterations <= 0) { - addError(std::string("The maximum number of iterations cannot be equal to ").append(toString(mMaximumNumberOfIterations)).append(". It must be greater than 0.")); + const auto maximumNumberOfIterations {toString(mMaximumNumberOfIterations)}; + std::string error; + + error.reserve(maximumNumberOfIterations.size() + 72); // NOLINT + + error += "The maximum number of iterations cannot be equal to "; + error += maximumNumberOfIterations; + error += ". It must be greater than 0."; + + addError(error); } bool needUpperAndLowerHalfBandwidths = false; @@ -268,11 +341,35 @@ bool SolverKinsol::Impl::solve(ComputeObjectiveFunction pComputeObjectiveFunctio if (needUpperAndLowerHalfBandwidths) { if ((mUpperHalfBandwidth < 0) || std::cmp_greater_equal(mUpperHalfBandwidth, pN)) { - addError(std::string("The upper half-bandwidth cannot be equal to ").append(toString(mUpperHalfBandwidth)).append(". It must be between 0 and ").append(toString(pN - 1)).append(".")); + const auto upperHalfBandwidth {toString(mUpperHalfBandwidth)}; + const auto maximumUpperHalfBandwidth {toString(pN - 1)}; + std::string error; + + error.reserve(upperHalfBandwidth.size() + maximumUpperHalfBandwidth.size() + 62); // NOLINT + + error += "The upper half-bandwidth cannot be equal to "; + error += upperHalfBandwidth; + error += ". It must be between 0 and "; + error += maximumUpperHalfBandwidth; + error += "."; + + addError(error); } if ((mLowerHalfBandwidth < 0) || std::cmp_greater_equal(mLowerHalfBandwidth, pN)) { - addError(std::string("The lower half-bandwidth cannot be equal to ").append(toString(mLowerHalfBandwidth)).append(". It must be between 0 and ").append(toString(pN - 1)).append(".")); + const auto lowerHalfBandwidth {toString(mLowerHalfBandwidth)}; + const auto maximumLowerHalfBandwidth {toString(pN - 1)}; + std::string error; + + error.reserve(lowerHalfBandwidth.size() + maximumLowerHalfBandwidth.size() + 62); // NOLINT + + error += "The lower half-bandwidth cannot be equal to "; + error += lowerHalfBandwidth; + error += ". It must be between 0 and "; + error += maximumLowerHalfBandwidth; + error += "."; + + addError(error); } } diff --git a/src/solver/solverodefixedstep.cpp b/src/solver/solverodefixedstep.cpp index 6013bcb33..309592b85 100644 --- a/src/solver/solverodefixedstep.cpp +++ b/src/solver/solverodefixedstep.cpp @@ -31,21 +31,46 @@ SolverOdeFixedStep::Impl::Impl(const std::string &pId, const std::string &pName) void SolverOdeFixedStep::Impl::populate(libsedml::SedAlgorithm *pAlgorithm) { + auto addUnknownParameterWarning = [&](const std::string &pKisaoId) { + std::string warning; + + warning.reserve(pKisaoId.size() + 49); // NOLINT + + warning += "The parameter '"; + warning += pKisaoId; + warning += "' is not recognised. It will be ignored."; + + addWarning(warning); + }; + for (unsigned int i {0}; i < pAlgorithm->getNumAlgorithmParameters(); ++i) { auto *algorithmParameter {pAlgorithm->getAlgorithmParameter(i)}; - auto kisaoId {algorithmParameter->getKisaoID()}; - auto value {algorithmParameter->getValue()}; + const auto &kisaoId {algorithmParameter->getKisaoID()}; + const auto &value {algorithmParameter->getValue()}; if (kisaoId == "KISAO:0000483") { mStep = toDouble(value); if ((mStep <= 0.0) || std::isnan(mStep)) { - addWarning(std::string("The step ('").append(kisaoId).append("') cannot be equal to '").append(value).append("'. It must be greater or equal to 0. A step of ").append(toString(DEFAULT_STEP)).append(" will be used instead.")); + const auto defaultStep {toString(DEFAULT_STEP)}; + std::string warning; + + warning.reserve(kisaoId.size() + value.size() + defaultStep.size() + 85); // NOLINT + + warning += "The step ('"; + warning += kisaoId; + warning += "') cannot be equal to '"; + warning += value; + warning += "'. It must be greater or equal to 0. A step of "; + warning += defaultStep; + warning += " will be used instead."; + + addWarning(warning); mStep = DEFAULT_STEP; } } else { - addWarning(std::string("The parameter '").append(kisaoId).append("' is not recognised. It will be ignored.")); + addUnknownParameterWarning(kisaoId); } } } @@ -81,7 +106,16 @@ bool SolverOdeFixedStep::Impl::initialise(double pVoi, size_t pSize, double *pSt // Check the solver's properties. if (mStep <= 0.0) { - addError(std::string("The step cannot be equal to ").append(toString(mStep)).append(". It must be greater than 0.")); + const auto stepAsString {toString(mStep)}; + std::string error; + + error.reserve(stepAsString.size() + 45); // NOLINT + + error += "The step cannot be equal to "; + error += stepAsString; + error += ". It must be greater than 0."; + + addError(error); return false; } diff --git a/src/support/cellml/cellmlfile.cpp b/src/support/cellml/cellmlfile.cpp index edb5978c8..f2415e6f4 100644 --- a/src/support/cellml/cellmlfile.cpp +++ b/src/support/cellml/cellmlfile.cpp @@ -139,6 +139,8 @@ const CellmlFile::Impl *CellmlFile::pimpl() const CellmlFilePtr CellmlFile::create(const FilePtr &pFile) { + static const CellmlFilePtr NO_CELLML_FILE_PTR; + // Check whether the file is a CellML file and if so then return its CellmlFile object. if (pFile->pimpl()->type() == File::Type::CELLML_FILE) { @@ -149,7 +151,7 @@ CellmlFilePtr CellmlFile::create(const FilePtr &pFile) // file contents again. if (pFile->pimpl()->mTypeChecked) { - return {}; + return NO_CELLML_FILE_PTR; } // Try to parse the file contents as a CellML file, be it a CellML 1.x or a CellML 2.0 file. @@ -161,7 +163,7 @@ CellmlFilePtr CellmlFile::create(const FilePtr &pFile) return CellmlFilePtr {new CellmlFile {pFile, model, false}}; } - return {}; + return NO_CELLML_FILE_PTR; } void CellmlFile::populateDocument(const SedDocumentPtr &pDocument) diff --git a/src/support/cellml/cellmlfileruntime.cpp b/src/support/cellml/cellmlfileruntime.cpp index c72969178..8ee469891 100644 --- a/src/support/cellml/cellmlfileruntime.cpp +++ b/src/support/cellml/cellmlfileruntime.cpp @@ -19,6 +19,9 @@ limitations under the License. #include "cellmlfile.h" +#include +#include + namespace libOpenCOR { #ifdef __EMSCRIPTEN__ @@ -28,7 +31,15 @@ namespace { std::string exportJavaScriptName(const std::string &pName) { - return std::string("__attribute__((export_name(\"").append(pName).append("\")))\n"); + std::string exportName; + + exportName.reserve(pName.size() + 31); // NOLINT + + exportName += "__attribute__((export_name(\""; + exportName += pName; + exportName += "\")))\n"; + + return exportName; } intptr_t instantiateWebAssemblyModule(const UnsignedChars &pWasmModule, bool pDifferentialModel, bool pIsOdeModel, @@ -258,13 +269,26 @@ CellmlFileRuntime::Impl::Impl(const CellmlFilePtr &pCellmlFile, const SolverNlaP // Export our various methods. + auto prependExportName = [](const std::string &pName, const std::string &pCode) { + auto exportName {exportJavaScriptName(pName)}; + std::string res; + + res.reserve(exportName.size() + pCode.size()); + + res += exportName; + res += pCode; + + return res; + }; + generatorProfile->setImplementationInitialiseArraysMethodString(differentialModel, - exportJavaScriptName("initialiseArrays").append(generatorProfile->implementationInitialiseArraysMethodString(differentialModel))); - generatorProfile->setImplementationComputeComputedConstantsMethodString(differentialModel, exportJavaScriptName("computeComputedConstants").append(generatorProfile->implementationComputeComputedConstantsMethodString(differentialModel))); + prependExportName("initialiseArrays", generatorProfile->implementationInitialiseArraysMethodString(differentialModel))); + generatorProfile->setImplementationComputeComputedConstantsMethodString(differentialModel, + prependExportName("computeComputedConstants", generatorProfile->implementationComputeComputedConstantsMethodString(differentialModel))); generatorProfile->setImplementationComputeRatesMethodString(WITH_EXTERNAL_VARIABLES, - exportJavaScriptName("computeRates").append(generatorProfile->implementationComputeRatesMethodString(WITH_EXTERNAL_VARIABLES))); + prependExportName("computeRates", generatorProfile->implementationComputeRatesMethodString(WITH_EXTERNAL_VARIABLES))); generatorProfile->setImplementationComputeVariablesMethodString(differentialModel, WITH_EXTERNAL_VARIABLES, - exportJavaScriptName("computeVariables").append(generatorProfile->implementationComputeVariablesMethodString(differentialModel, WITH_EXTERNAL_VARIABLES))); + prependExportName("computeVariables", generatorProfile->implementationComputeVariablesMethodString(differentialModel, WITH_EXTERNAL_VARIABLES))); #endif if (pNlaSolver != nullptr) { @@ -284,7 +308,7 @@ extern void free(void *ptr); extern void nlaSolve(uintptr_t nlaSolverAddress, size_t objectiveFunctionIndex, uintptr_t u, size_t n, uintptr_t data); )"); generatorProfile->setNlaSolveCallString(differentialModel, WITH_EXTERNAL_VARIABLES, - std::string("nlaSolve(").append(mNlaSolverAddress).append(", [INDEX], (uintptr_t) u, [SIZE], (uintptr_t) rfi);\n")); + "nlaSolve(" + mNlaSolverAddress + ", [INDEX], (uintptr_t) u, [SIZE], (uintptr_t) rfi);\n"); #else # ifdef BUILDING_USING_MSVC generatorProfile->setExternNlaSolveMethodString(R"(typedef unsigned long long uintptr_t; @@ -302,7 +326,7 @@ extern void nlaSolve(uintptr_t nlaSolverAddress, void (*objectiveFunction)(doubl )"); # endif generatorProfile->setNlaSolveCallString(differentialModel, WITH_EXTERNAL_VARIABLES, - std::string("nlaSolve(").append(mNlaSolverAddress).append(", objectiveFunction[INDEX], u, [SIZE], &rfi);\n")); + "nlaSolve(" + mNlaSolverAddress + ", objectiveFunction[INDEX], u, [SIZE], &rfi);\n"); #endif } @@ -312,19 +336,22 @@ extern void nlaSolve(uintptr_t nlaSolverAddress, void (*objectiveFunction)(doubl auto implementationCode {generator->implementationCode(pCellmlFile->analyserModel(), generatorProfile)}; if (pNlaSolver != nullptr) { - std::vector handledNlaSystemIndices; + std::unordered_set handledNlaSystemIndices; + const auto &analyserEquations = pCellmlFile->analyserModel()->analyserEquations(); + + handledNlaSystemIndices.reserve(analyserEquations.size()); - for (const auto &analyserEquation : pCellmlFile->analyserModel()->analyserEquations()) { + for (const auto &analyserEquation : analyserEquations) { if (analyserEquation->type() == libcellml::AnalyserEquation::Type::NLA) { auto nlaSystemIndex {analyserEquation->nlaSystemIndex()}; - if (std::find(handledNlaSystemIndices.begin(), handledNlaSystemIndices.end(), nlaSystemIndex) == handledNlaSystemIndices.end()) { - auto objectiveFunctionName {std::string("objectiveFunction").append(std::to_string(nlaSystemIndex))}; + if (!handledNlaSystemIndices.contains(nlaSystemIndex)) { + auto objectiveFunctionName {"objectiveFunction" + std::format("{}", nlaSystemIndex)}; implementationCode.insert(implementationCode.find("void " + objectiveFunctionName), exportJavaScriptName(objectiveFunctionName)); - handledNlaSystemIndices.push_back(nlaSystemIndex); + handledNlaSystemIndices.insert(nlaSystemIndex); } } } @@ -359,7 +386,7 @@ extern void nlaSolve(uintptr_t nlaSolverAddress, void (*objectiveFunction)(doubl free(errorMessagePtr); - addError(std::string("The WebAssembly module could not be instantiated (").append(jsErrorMessage).append(").")); + addError("The WebAssembly module could not be instantiated (" + jsErrorMessage + ")."); return; } @@ -411,7 +438,9 @@ extern void nlaSolve(uintptr_t nlaSolverAddress, void (*objectiveFunction)(doubl || (mComputeComputedConstantsForDifferentialModel == nullptr) || (mComputeRates == nullptr) || (mComputeVariablesForDifferentialModel == nullptr)) { - addError(std::string("The functions needed to compute the ").append((cellmlFileType == libcellml::AnalyserModel::Type::ODE) ? "ODE" : "DAE").append(" model could not be retrieved.")); + addError(std::string("The functions needed to compute the ") + + ((cellmlFileType == libcellml::AnalyserModel::Type::ODE) ? "ODE" : "DAE") + + " model could not be retrieved."); } # endif } else { @@ -423,7 +452,9 @@ extern void nlaSolve(uintptr_t nlaSolverAddress, void (*objectiveFunction)(doubl if ((mInitialiseArraysForAlgebraicModel == nullptr) || (mComputeComputedConstantsForAlgebraicModel == nullptr) || (mComputeVariablesForAlgebraicModel == nullptr)) { - addError(std::string("The functions needed to compute the ").append((cellmlFileType == libcellml::AnalyserModel::Type::ALGEBRAIC) ? "algebraic" : "NLA").append(" model could not be retrieved.")); + addError(std::string("The functions needed to compute the ") + + ((cellmlFileType == libcellml::AnalyserModel::Type::ALGEBRAIC) ? "algebraic" : "NLA") + + " model could not be retrieved."); } # endif } diff --git a/src/support/combine/combinearchive.cpp b/src/support/combine/combinearchive.cpp index f847d3796..3f33fbec9 100644 --- a/src/support/combine/combinearchive.cpp +++ b/src/support/combine/combinearchive.cpp @@ -34,6 +34,11 @@ CombineArchive::Impl::Impl(const FilePtr &pFile, libcombine::CombineArchive *pAr { // Extract all the files contained in the COMBINE archive. + auto fileCount {static_cast(mArchive->getNumEntries())}; + + mFiles.reserve(fileCount); + mFileNames.reserve(fileCount); + for (int i {0}; i < mArchive->getNumEntries(); ++i) { const auto *entry {mArchive->getEntry(i)}; auto location {entry->getLocation()}; @@ -41,8 +46,8 @@ CombineArchive::Impl::Impl(const FilePtr &pFile, libcombine::CombineArchive *pAr file->setContents(mArchive->extractEntryToBuffer(location)); - mFiles.push_back(file); // So that the files (besides the master file) don't get automatically deleted when we - // get out of scope. + mFiles.push_back(file); + mFileNames.push_back(location); if (entry->getMaster()) { mMasterFile = file; @@ -55,7 +60,7 @@ CombineArchive::Impl::~Impl() delete mArchive; } -FilePtr CombineArchive::Impl::masterFile() const +const FilePtr &CombineArchive::Impl::masterFile() const { return mMasterFile; } @@ -70,40 +75,38 @@ size_t CombineArchive::Impl::fileCount() const return mFiles.size(); } -Strings CombineArchive::Impl::fileNames() const +const Strings &CombineArchive::Impl::fileNames() const { - Strings res; - - for (const auto &file : mFiles) { - res.push_back(file->fileName().substr(mArchiveLocationSize)); - } - - return res; + return mFileNames; } -FilePtrs CombineArchive::Impl::files() const +const FilePtrs &CombineArchive::Impl::files() const { return mFiles; } -FilePtr CombineArchive::Impl::file(size_t pIndex) const +const FilePtr &CombineArchive::Impl::file(size_t pIndex) const { + static const FilePtr NO_FILE_PTR; + if (pIndex >= mFiles.size()) { - return {}; + return NO_FILE_PTR; } return mFiles[pIndex]; } -FilePtr CombineArchive::Impl::file(const std::string &pFileName) const +const FilePtr &CombineArchive::Impl::file(const std::string &pFileName) const { + static const FilePtr NO_FILE_PTR; + for (const auto &file : mFiles) { if (file->fileName() == mArchiveLocation + pFileName) { return file; } } - return {}; + return NO_FILE_PTR; } CombineArchive::CombineArchive(const FilePtr &pFile, libcombine::CombineArchive *pArchive, UnsignedChars &&pArchiveContents) @@ -128,6 +131,8 @@ const CombineArchive::Impl *CombineArchive::pimpl() const CombineArchivePtr CombineArchive::create(const FilePtr &pFile) { + static const CombineArchivePtr NO_COMBINE_ARCHIVE_PTR; + // Check whether the file is a COMBINE archive and if so then return its CombineArchive object. if (pFile->pimpl()->type() == File::Type::COMBINE_ARCHIVE) { @@ -138,7 +143,7 @@ CombineArchivePtr CombineArchive::create(const FilePtr &pFile) // file contents again. if (pFile->pimpl()->mTypeChecked) { - return {}; + return NO_COMBINE_ARCHIVE_PTR; } // Try to retrieve a COMBINE archive. @@ -165,10 +170,10 @@ CombineArchivePtr CombineArchive::create(const FilePtr &pFile) // CombineArchive::Impl object. } - return {}; + return NO_COMBINE_ARCHIVE_PTR; } -FilePtr CombineArchive::masterFile() const +const FilePtr &CombineArchive::masterFile() const { return pimpl()->masterFile(); } @@ -183,22 +188,22 @@ size_t CombineArchive::fileCount() const return pimpl()->fileCount(); } -Strings CombineArchive::fileNames() const +const Strings &CombineArchive::fileNames() const { return pimpl()->fileNames(); } -FilePtrs CombineArchive::files() const +const FilePtrs &CombineArchive::files() const { return pimpl()->files(); } -FilePtr CombineArchive::file(size_t pIndex) const +const FilePtr &CombineArchive::file(size_t pIndex) const { return pimpl()->file(pIndex); } -FilePtr CombineArchive::file(const std::string &pFileName) const +const FilePtr &CombineArchive::file(const std::string &pFileName) const { return pimpl()->file(pFileName); } diff --git a/src/support/combine/combinearchive.h b/src/support/combine/combinearchive.h index 64286de0c..7c1cc09c1 100644 --- a/src/support/combine/combinearchive.h +++ b/src/support/combine/combinearchive.h @@ -43,14 +43,14 @@ class LIBOPENCOR_UNIT_TESTING_EXPORT CombineArchive: public Logger static CombineArchivePtr create(const FilePtr &pFile); - FilePtr masterFile() const; + const FilePtr &masterFile() const; bool hasFiles() const; size_t fileCount() const; - Strings fileNames() const; - FilePtrs files() const; - FilePtr file(size_t pIndex) const; - FilePtr file(const std::string &pFileName) const; + const Strings &fileNames() const; + const FilePtrs &files() const; + const FilePtr &file(size_t pIndex) const; + const FilePtr &file(const std::string &pFileName) const; private: class Impl; diff --git a/src/support/combine/combinearchive_p.h b/src/support/combine/combinearchive_p.h index c627bd9b8..e9ff1cb6b 100644 --- a/src/support/combine/combinearchive_p.h +++ b/src/support/combine/combinearchive_p.h @@ -30,18 +30,19 @@ class CombineArchive::Impl: public Logger::Impl std::string mArchiveLocation; size_t mArchiveLocationSize; std::vector mFiles; + std::vector mFileNames; FilePtr mMasterFile; explicit Impl(const FilePtr &pFile, libcombine::CombineArchive *pArchive, UnsignedChars &&pArchiveContents); ~Impl() override; - FilePtr masterFile() const; + const FilePtr &masterFile() const; bool hasFiles() const; size_t fileCount() const; - Strings fileNames() const; - FilePtrs files() const; - FilePtr file(size_t pIndex) const; - FilePtr file(const std::string &pFileName) const; + const Strings &fileNames() const; + const FilePtrs &files() const; + const FilePtr &file(size_t pIndex) const; + const FilePtr &file(const std::string &pFileName) const; }; } // namespace libOpenCOR diff --git a/src/support/sedml/sedmlfile.cpp b/src/support/sedml/sedmlfile.cpp index 2c65b5394..e83cfb279 100644 --- a/src/support/sedml/sedmlfile.cpp +++ b/src/support/sedml/sedmlfile.cpp @@ -73,7 +73,7 @@ void SedmlFile::Impl::populateDocument(const SedDocumentPtr &pDocument) removeAllIssues(); - auto fileManager {FileManager::instance()}; + auto &fileManager {FileManager::instance()}; for (unsigned int i {0}; i < mDocument->getNumModels(); ++i) { auto source {mDocument->getModel(i)->getSource()}; @@ -82,16 +82,24 @@ void SedmlFile::Impl::populateDocument(const SedDocumentPtr &pDocument) mLocation + fileNameOrUrl : fileNameOrUrl}; #ifdef __EMSCRIPTEN__ - auto file {fileManager.fileFromFileNameOrUrl(modelSource)}; + const auto &file {fileManager.fileFromFileNameOrUrl(modelSource)}; #else - auto file {fileManager.file(modelSource)}; + const auto &file {fileManager.file(modelSource)}; #endif SedModelPtr model; if (file != nullptr) { model = SedModel::create(pDocument, file); } else { - addWarning(std::string("The model '").append(source).append("' could not be found in the file manager. It has been automatically added to it.")); + std::string warning; + + warning.reserve(source.size() + 80); // NOLINT + + warning += "The model '"; + warning += source; + warning += "' could not be found in the file manager. It has been automatically added to it."; + + addWarning(warning); model = SedModel::create(pDocument, File::create(modelSource)); } @@ -142,13 +150,30 @@ void SedmlFile::Impl::populateDocument(const SedDocumentPtr &pDocument) if (componentName.empty() || variableName.empty()) { canAddChange = false; - addError(std::string("The component and variable names could not be retrieved for the change of type 'changeAttribute' and of target '").append(changeAttribute->getTarget()).append("'.")); + const std::string targetString(changeAttribute->getTarget()); + std::string error; + + error.reserve(targetString.size() + 111); // NOLINT + + error += "The component and variable names could not be retrieved for the change of type 'changeAttribute' and of target '"; + error += targetString; + error += "'."; + + addError(error); } if (!isDouble(newValue)) { canAddChange = false; - addError(std::string("The new value '").append(newValue).append("' for the change of type 'changeAttribute' is not a valid double value.")); + std::string error; + + error.reserve(newValue.size() + 70); // NOLINT + + error += "The new value '"; + error += newValue; + error += "' for the change of type 'changeAttribute' is not a valid double value."; + + addError(error); } if (canAddChange) { @@ -156,7 +181,16 @@ void SedmlFile::Impl::populateDocument(const SedDocumentPtr &pDocument) changeAttribute->getNewValue())); } } else { - addWarning(std::string("Only changes of type 'changeAttribute' are currently supported. The change of type '").append(change->getElementName()).append("' has been ignored.")); + const std::string changeElementName(change->getElementName()); + std::string warning; + + warning.reserve(changeElementName.size() + 92); // NOLINT + + warning += "Only changes of type 'changeAttribute' are currently supported. The change of type '"; + warning += changeElementName; + warning += "' has been ignored."; + + addWarning(warning); } } @@ -199,7 +233,7 @@ void SedmlFile::Impl::populateDocument(const SedDocumentPtr &pDocument) // Populate the simulation's algorithm. auto *sedAlgorithm {sedSimulation->getAlgorithm()}; - auto kisaoId {sedAlgorithm->getKisaoID()}; + const auto &kisaoId {sedAlgorithm->getKisaoID()}; SolverOdePtr odeSolver {nullptr}; SolverNlaPtr nlaSolver {nullptr}; @@ -216,7 +250,15 @@ void SedmlFile::Impl::populateDocument(const SedDocumentPtr &pDocument) } else if (kisaoId == "KISAO:0000381") { odeSolver = SolverSecondOrderRungeKutta::create(); } else { - addWarning(std::string("The solver '").append(kisaoId).append("' is not recognised. The CVODE solver will be used instead.")); + std::string warning; + + warning.reserve(kisaoId.size() + 63); // NOLINT + + warning += "The solver '"; + warning += kisaoId; + warning += "' is not recognised. The CVODE solver will be used instead."; + + addWarning(warning); odeSolver = SolverCvode::create(); } @@ -246,7 +288,7 @@ void SedmlFile::Impl::populateDocument(const SedDocumentPtr &pDocument) #else if ((mDocument->getNumModels() == 1) && (mDocument->getNumSimulations() == 1)) { #endif - pDocument->addTask(SedTask::create(pDocument, pDocument->models()[0], pDocument->simulations()[0])); + pDocument->addTask(SedTask::create(pDocument, pDocument->model(0), pDocument->simulation(0))); } } @@ -274,6 +316,8 @@ const SedmlFile::Impl *SedmlFile::pimpl() const SedmlFilePtr SedmlFile::create(const FilePtr &pFile) { + static const SedmlFilePtr NO_SEDML_FILE_PTR; + // Check whether the file is a SED-ML file and if so then return its SedmlFile object. if (pFile->pimpl()->type() == File::Type::SEDML_FILE) { @@ -284,7 +328,7 @@ SedmlFilePtr SedmlFile::create(const FilePtr &pFile) // file contents again. if (pFile->pimpl()->mTypeChecked) { - return {}; + return NO_SEDML_FILE_PTR; } // Try to retrieve a SED-ML document. @@ -305,7 +349,7 @@ SedmlFilePtr SedmlFile::create(const FilePtr &pFile) delete document; - return {}; + return NO_SEDML_FILE_PTR; } void SedmlFile::populateDocument(const SedDocumentPtr &pDocument) diff --git a/src/version.cpp b/src/version.cpp index 03ab86593..3c4c0561f 100644 --- a/src/version.cpp +++ b/src/version.cpp @@ -75,9 +75,11 @@ uint64_t version() return LIBOPENCOR_VERSION; } -std::string versionString() +const std::string &versionString() { - return LIBOPENCOR_VERSION_STRING; + static const std::string res {LIBOPENCOR_VERSION_STRING}; + + return res; } unsigned int clangVersion() @@ -87,9 +89,11 @@ unsigned int clangVersion() + PATCH_10 * firstDigit(CLANG_VERSION_PATCHLEVEL) + PATCH_01 * secondDigit(CLANG_VERSION_PATCHLEVEL); } -std::string clangVersionString() +const std::string &clangVersionString() { - return CLANG_VERSION_STRING; + static const std::string res {CLANG_VERSION_STRING}; + + return res; } unsigned int libcellmlVersion() @@ -97,9 +101,11 @@ unsigned int libcellmlVersion() return libcellml::version(); } -std::string libcellmlVersionString() +const std::string &libcellmlVersionString() { - return libcellml::versionString(); + static const std::string res {libcellml::versionString()}; + + return res; } unsigned int libcombineVersion() @@ -107,9 +113,11 @@ unsigned int libcombineVersion() return static_cast(libcombine::getLibCombineVersion()); } -std::string libcombineVersionString() +const std::string &libcombineVersionString() { - return libcombine::getLibCombineDottedVersion(); + static const std::string res {libcombine::getLibCombineDottedVersion()}; + + return res; } #ifndef __EMSCRIPTEN__ @@ -118,9 +126,11 @@ unsigned int libcurlVersion() return LIBCURL_VERSION_NUM; } -std::string libcurlVersionString() +const std::string &libcurlVersionString() { - return LIBCURL_VERSION; + static const std::string res {LIBCURL_VERSION}; + + return res; } #endif @@ -129,9 +139,11 @@ unsigned int libsedmlVersion() return static_cast(libsedml::getLibSEDMLVersion()); } -std::string libsedmlVersionString() +const std::string &libsedmlVersionString() { - return libsedml::getLibSEDMLDottedVersion(); + static const std::string res {libsedml::getLibSEDMLDottedVersion()}; + + return res; } unsigned int llvmVersion() @@ -141,9 +153,11 @@ unsigned int llvmVersion() + PATCH_10 * firstDigit(LLVM_VERSION_PATCH) + PATCH_01 * secondDigit(LLVM_VERSION_PATCH); } -std::string llvmVersionString() +const std::string &llvmVersionString() { - return LLVM_VERSION_STRING; + static const std::string res {LLVM_VERSION_STRING}; + + return res; } unsigned int sundialsVersion() diff --git a/tests/api/file/basictests.cpp b/tests/api/file/basictests.cpp index 79108e1d6..dbc66c17a 100644 --- a/tests/api/file/basictests.cpp +++ b/tests/api/file/basictests.cpp @@ -161,7 +161,7 @@ TEST(BasicFileTest, remoteVirtualFile) TEST(BasicFileTest, fileManager) { - auto fileManager {libOpenCOR::FileManager::instance()}; + auto &fileManager {libOpenCOR::FileManager::instance()}; EXPECT_FALSE(fileManager.hasFiles()); EXPECT_EQ(fileManager.fileCount(), 0); @@ -170,7 +170,7 @@ TEST(BasicFileTest, fileManager) EXPECT_EQ(fileManager.file(libOpenCOR::LOCAL_FILE), nullptr); auto localFile {libOpenCOR::File::create(libOpenCOR::LOCAL_FILE)}; - auto sameFileManager {libOpenCOR::FileManager::instance()}; + auto &sameFileManager {libOpenCOR::FileManager::instance()}; EXPECT_TRUE(sameFileManager.hasFiles()); EXPECT_EQ(sameFileManager.fileCount(), 1); diff --git a/tests/api/file/coveragetests.cpp b/tests/api/file/coveragetests.cpp index 6700b8015..c4a915fc5 100644 --- a/tests/api/file/coveragetests.cpp +++ b/tests/api/file/coveragetests.cpp @@ -82,7 +82,7 @@ TEST(CoverageFileTest, doNotRetrieveContents) TEST(CoverageFileTest, unmanageFileWithChildren) { auto file = libOpenCOR::File::create(libOpenCOR::resourcePath(libOpenCOR::COMBINE_2_ARCHIVE)); - auto fileManager = libOpenCOR::FileManager::instance(); + auto &fileManager = libOpenCOR::FileManager::instance(); EXPECT_EQ(fileManager.fileCount(), 3); diff --git a/tests/api/sed/coveragetests.cpp b/tests/api/sed/coveragetests.cpp index ecc00078f..5fc272a64 100644 --- a/tests/api/sed/coveragetests.cpp +++ b/tests/api/sed/coveragetests.cpp @@ -420,13 +420,13 @@ TEST(CoverageSedTest, sedInstanceAndSedInstanceTaskDifferentialModel) auto file {libOpenCOR::File::create(libOpenCOR::resourcePath("api/solver/ode.cellml"))}; auto document {libOpenCOR::SedDocument::create(file)}; - auto solver {std::dynamic_pointer_cast(document->simulations()[0]->odeSolver())}; + const auto &solver {std::dynamic_pointer_cast(document->simulations()[0]->odeSolver())}; solver->setLinearSolver(libOpenCOR::SolverCvode::LinearSolver::BANDED); solver->setUpperHalfBandwidth(UPPER_HALF_BANDWIDTH); auto instance {document->instantiate()}; - auto instanceTask {instance->tasks()[0]}; + const auto &instanceTask {instance->tasks()[0]}; EXPECT_EQ(instance->hasTasks(), true); EXPECT_EQ(instance->taskCount(), 1); @@ -488,7 +488,7 @@ TEST(CoverageSedTest, sedInstanceAndSedInstanceTaskNonDifferentialModel) auto document {libOpenCOR::SedDocument::create(file)}; auto instance {document->instantiate()}; - auto instanceTask {instance->tasks()[0]}; + const auto &instanceTask {instance->tasks()[0]}; EXPECT_EQ(instanceTask->voi(), NoDoubles); EXPECT_EQ(instanceTask->voiName(), ""); @@ -562,7 +562,7 @@ TEST(CoverageSedTest, math) auto file {libOpenCOR::File::create(libOpenCOR::resourcePath("api/sed/math.cellml"))}; auto document {libOpenCOR::SedDocument::create(file)}; auto instance {document->instantiate()}; - auto instanceTask {instance->tasks()[0]}; + const auto &instanceTask {instance->tasks()[0]}; EXPECT_EQ(instanceTask->constantCount(), 0); EXPECT_EQ(instanceTask->computedConstantCount(), 37); diff --git a/tests/api/sed/instancetests.cpp b/tests/api/sed/instancetests.cpp index 721d11573..630a8ca2a 100644 --- a/tests/api/sed/instancetests.cpp +++ b/tests/api/sed/instancetests.cpp @@ -116,11 +116,11 @@ TEST(InstanceSedTest, odeModel) auto file {libOpenCOR::File::create(libOpenCOR::resourcePath(libOpenCOR::CELLML_2_FILE))}; auto document {libOpenCOR::SedDocument::create(file)}; - auto simulation {std::dynamic_pointer_cast(document->simulations()[0])}; + const auto &simulation {std::dynamic_pointer_cast(document->simulations()[0])}; static const auto NOK_MAXIMUM_NUMBER_OF_STEPS {10}; - auto cvode {std::dynamic_pointer_cast(simulation->odeSolver())}; + const auto &cvode {std::dynamic_pointer_cast(simulation->odeSolver())}; cvode->setMaximumNumberOfSteps(NOK_MAXIMUM_NUMBER_OF_STEPS); @@ -167,8 +167,8 @@ TEST(InstanceSedTest, nlaModel) auto file {libOpenCOR::File::create(libOpenCOR::resourcePath("api/sed/nla.cellml"))}; auto document {libOpenCOR::SedDocument::create(file)}; - auto simulation {std::dynamic_pointer_cast(document->simulations()[0])}; - auto kinsol {std::dynamic_pointer_cast(simulation->nlaSolver())}; + const auto &simulation {std::dynamic_pointer_cast(document->simulations()[0])}; + const auto &kinsol {std::dynamic_pointer_cast(simulation->nlaSolver())}; kinsol->setLinearSolver(libOpenCOR::SolverKinsol::LinearSolver::BANDED); kinsol->setUpperHalfBandwidth(-1); @@ -208,8 +208,8 @@ TEST(InstanceSedTest, daeModel) auto file {libOpenCOR::File::create(libOpenCOR::resourcePath("api/sed/dae.cellml"))}; auto document {libOpenCOR::SedDocument::create(file)}; - auto simulation {std::dynamic_pointer_cast(document->simulations()[0])}; - auto kinsol {std::dynamic_pointer_cast(simulation->nlaSolver())}; + const auto &simulation {std::dynamic_pointer_cast(document->simulations()[0])}; + const auto &kinsol {std::dynamic_pointer_cast(simulation->nlaSolver())}; kinsol->setLinearSolver(libOpenCOR::SolverKinsol::LinearSolver::BANDED); kinsol->setUpperHalfBandwidth(-1); @@ -240,7 +240,7 @@ TEST(InstanceSedTest, daeModelWithNoOdeOrNlaSolver) auto file {libOpenCOR::File::create(libOpenCOR::resourcePath("api/sed/dae.cellml"))}; auto document {libOpenCOR::SedDocument::create(file)}; - auto simulation {document->simulations()[0]}; + const auto &simulation {document->simulations()[0]}; simulation->setOdeSolver(nullptr); simulation->setNlaSolver(nullptr); diff --git a/tests/api/sed/serialisetests.cpp b/tests/api/sed/serialisetests.cpp index 38763eec0..733057727 100644 --- a/tests/api/sed/serialisetests.cpp +++ b/tests/api/sed/serialisetests.cpp @@ -330,7 +330,7 @@ TEST(SerialiseSedTest, fixedStepOdeSolver) auto file {libOpenCOR::File::create(libOpenCOR::resourcePath(libOpenCOR::CELLML_2_FILE))}; auto document {libOpenCOR::SedDocument::create(file)}; - auto simulation {document->simulations()[0]}; + const auto &simulation {document->simulations()[0]}; simulation->setOdeSolver(libOpenCOR::SolverForwardEuler::create()); @@ -341,8 +341,8 @@ TEST(SerialiseSedTest, cvodeSolverWithAdamsMoultonInterationMethod) { auto file {libOpenCOR::File::create(libOpenCOR::resourcePath(libOpenCOR::CELLML_2_FILE))}; auto document {libOpenCOR::SedDocument::create(file)}; - auto simulation {document->simulations()[0]}; - auto solver {std::dynamic_pointer_cast(simulation->odeSolver())}; + const auto &simulation {document->simulations()[0]}; + const auto &solver {std::dynamic_pointer_cast(simulation->odeSolver())}; solver->setIntegrationMethod(libOpenCOR::SolverCvode::IntegrationMethod::ADAMS_MOULTON); @@ -353,8 +353,8 @@ TEST(SerialiseSedTest, cvodeSolverWithFunctionalIterationType) { auto file {libOpenCOR::File::create(libOpenCOR::resourcePath(libOpenCOR::CELLML_2_FILE))}; auto document {libOpenCOR::SedDocument::create(file)}; - auto simulation {document->simulations()[0]}; - auto solver {std::dynamic_pointer_cast(simulation->odeSolver())}; + const auto &simulation {document->simulations()[0]}; + const auto &solver {std::dynamic_pointer_cast(simulation->odeSolver())}; solver->setIterationType(libOpenCOR::SolverCvode::IterationType::FUNCTIONAL); @@ -365,8 +365,8 @@ TEST(SerialiseSedTest, cvodeSolverWithBandedLinearSolver) { auto file {libOpenCOR::File::create(libOpenCOR::resourcePath(libOpenCOR::CELLML_2_FILE))}; auto document {libOpenCOR::SedDocument::create(file)}; - auto simulation {document->simulations()[0]}; - auto solver {std::dynamic_pointer_cast(simulation->odeSolver())}; + const auto &simulation {document->simulations()[0]}; + const auto &solver {std::dynamic_pointer_cast(simulation->odeSolver())}; solver->setLinearSolver(libOpenCOR::SolverCvode::LinearSolver::BANDED); @@ -377,8 +377,8 @@ TEST(SerialiseSedTest, cvodeSolverWithDiagonalLinearSolver) { auto file {libOpenCOR::File::create(libOpenCOR::resourcePath(libOpenCOR::CELLML_2_FILE))}; auto document {libOpenCOR::SedDocument::create(file)}; - auto simulation {document->simulations()[0]}; - auto solver {std::dynamic_pointer_cast(simulation->odeSolver())}; + const auto &simulation {document->simulations()[0]}; + const auto &solver {std::dynamic_pointer_cast(simulation->odeSolver())}; solver->setLinearSolver(libOpenCOR::SolverCvode::LinearSolver::DIAGONAL); @@ -389,8 +389,8 @@ TEST(SerialiseSedTest, cvodeSolverWithGmresLinearSolver) { auto file {libOpenCOR::File::create(libOpenCOR::resourcePath(libOpenCOR::CELLML_2_FILE))}; auto document {libOpenCOR::SedDocument::create(file)}; - auto simulation {document->simulations()[0]}; - auto solver {std::dynamic_pointer_cast(simulation->odeSolver())}; + const auto &simulation {document->simulations()[0]}; + const auto &solver {std::dynamic_pointer_cast(simulation->odeSolver())}; solver->setLinearSolver(libOpenCOR::SolverCvode::LinearSolver::GMRES); @@ -401,8 +401,8 @@ TEST(SerialiseSedTest, cvodeSolverWithBicgstabLinearSolver) { auto file {libOpenCOR::File::create(libOpenCOR::resourcePath(libOpenCOR::CELLML_2_FILE))}; auto document {libOpenCOR::SedDocument::create(file)}; - auto simulation {document->simulations()[0]}; - auto solver {std::dynamic_pointer_cast(simulation->odeSolver())}; + const auto &simulation {document->simulations()[0]}; + const auto &solver {std::dynamic_pointer_cast(simulation->odeSolver())}; solver->setLinearSolver(libOpenCOR::SolverCvode::LinearSolver::BICGSTAB); @@ -413,8 +413,8 @@ TEST(SerialiseSedTest, cvodeSolverWithTfqmrLinearSolver) { auto file {libOpenCOR::File::create(libOpenCOR::resourcePath(libOpenCOR::CELLML_2_FILE))}; auto document {libOpenCOR::SedDocument::create(file)}; - auto simulation {document->simulations()[0]}; - auto solver {std::dynamic_pointer_cast(simulation->odeSolver())}; + const auto &simulation {document->simulations()[0]}; + const auto &solver {std::dynamic_pointer_cast(simulation->odeSolver())}; solver->setLinearSolver(libOpenCOR::SolverCvode::LinearSolver::TFQMR); @@ -425,8 +425,8 @@ TEST(SerialiseSedTest, cvodeSolverWithNoPreconditioner) { auto file {libOpenCOR::File::create(libOpenCOR::resourcePath(libOpenCOR::CELLML_2_FILE))}; auto document {libOpenCOR::SedDocument::create(file)}; - auto simulation {document->simulations()[0]}; - auto solver {std::dynamic_pointer_cast(simulation->odeSolver())}; + const auto &simulation {document->simulations()[0]}; + const auto &solver {std::dynamic_pointer_cast(simulation->odeSolver())}; solver->setPreconditioner(libOpenCOR::SolverCvode::Preconditioner::NO); @@ -437,8 +437,8 @@ TEST(SerialiseSedTest, cvodeSolverWithNoInterpolateSolution) { auto file {libOpenCOR::File::create(libOpenCOR::resourcePath(libOpenCOR::CELLML_2_FILE))}; auto document {libOpenCOR::SedDocument::create(file)}; - auto simulation {document->simulations()[0]}; - auto solver {std::dynamic_pointer_cast(simulation->odeSolver())}; + const auto &simulation {document->simulations()[0]}; + const auto &solver {std::dynamic_pointer_cast(simulation->odeSolver())}; solver->setInterpolateSolution(false); @@ -449,8 +449,8 @@ TEST(SerialiseSedTest, kinsolWithBandedLinearSolver) { auto file {libOpenCOR::File::create(libOpenCOR::resourcePath("api/sed/nla.cellml"))}; auto document {libOpenCOR::SedDocument::create(file)}; - auto simulation {document->simulations()[0]}; - auto solver {std::dynamic_pointer_cast(simulation->nlaSolver())}; + const auto &simulation {document->simulations()[0]}; + const auto &solver {std::dynamic_pointer_cast(simulation->nlaSolver())}; solver->setLinearSolver(libOpenCOR::SolverKinsol::LinearSolver::BANDED); @@ -461,8 +461,8 @@ TEST(SerialiseSedTest, kinsolWithGmresLinearSolver) { auto file {libOpenCOR::File::create(libOpenCOR::resourcePath("api/sed/nla.cellml"))}; auto document {libOpenCOR::SedDocument::create(file)}; - auto simulation {document->simulations()[0]}; - auto solver {std::dynamic_pointer_cast(simulation->nlaSolver())}; + const auto &simulation {document->simulations()[0]}; + const auto &solver {std::dynamic_pointer_cast(simulation->nlaSolver())}; solver->setLinearSolver(libOpenCOR::SolverKinsol::LinearSolver::GMRES); @@ -473,8 +473,8 @@ TEST(SerialiseSedTest, kinsolWithBicgstabLinearSolver) { auto file {libOpenCOR::File::create(libOpenCOR::resourcePath("api/sed/nla.cellml"))}; auto document {libOpenCOR::SedDocument::create(file)}; - auto simulation {document->simulations()[0]}; - auto solver {std::dynamic_pointer_cast(simulation->nlaSolver())}; + const auto &simulation {document->simulations()[0]}; + const auto &solver {std::dynamic_pointer_cast(simulation->nlaSolver())}; solver->setLinearSolver(libOpenCOR::SolverKinsol::LinearSolver::BICGSTAB); @@ -485,8 +485,8 @@ TEST(SerialiseSedTest, kinsolWithTfmqrLinearSolver) { auto file {libOpenCOR::File::create(libOpenCOR::resourcePath("api/sed/nla.cellml"))}; auto document {libOpenCOR::SedDocument::create(file)}; - auto simulation {document->simulations()[0]}; - auto solver {std::dynamic_pointer_cast(simulation->nlaSolver())}; + const auto &simulation {document->simulations()[0]}; + const auto &solver {std::dynamic_pointer_cast(simulation->nlaSolver())}; solver->setLinearSolver(libOpenCOR::SolverKinsol::LinearSolver::TFQMR); diff --git a/tests/api/solver/coveragetests.cpp b/tests/api/solver/coveragetests.cpp index 01bd034f1..eba4368c0 100644 --- a/tests/api/solver/coveragetests.cpp +++ b/tests/api/solver/coveragetests.cpp @@ -69,7 +69,7 @@ TEST(CoverageSolverTest, algebraicChanges) static const auto ABS_TOL {1e-05}; - auto instanceTask {instance->tasks()[0]}; + const auto &instanceTask {instance->tasks()[0]}; EXPECT_EQ(instanceTask->stateCount(), 0); EXPECT_EQ(instanceTask->rateCount(), 0); diff --git a/tests/api/solver/cvodetests.cpp b/tests/api/solver/cvodetests.cpp index a2257367a..84164e7e5 100644 --- a/tests/api/solver/cvodetests.cpp +++ b/tests/api/solver/cvodetests.cpp @@ -25,8 +25,8 @@ TEST(CvodeSolverTest, maximumStepValueWithInvalidNumber) auto file {libOpenCOR::File::create(libOpenCOR::resourcePath("api/solver/ode.cellml"))}; auto document {libOpenCOR::SedDocument::create(file)}; - auto simulation {std::dynamic_pointer_cast(document->simulations()[0])}; - auto solver {std::dynamic_pointer_cast(simulation->odeSolver())}; + const auto &simulation {std::dynamic_pointer_cast(document->simulations()[0])}; + const auto &solver {std::dynamic_pointer_cast(simulation->odeSolver())}; solver->setMaximumStep(RELATIVE_TOLERANCE); @@ -44,8 +44,8 @@ TEST(CvodeSolverTest, maximumNumberOfStepsValueWithInvalidNumber) auto file {libOpenCOR::File::create(libOpenCOR::resourcePath("api/solver/ode.cellml"))}; auto document {libOpenCOR::SedDocument::create(file)}; - auto simulation {std::dynamic_pointer_cast(document->simulations()[0])}; - auto solver {std::dynamic_pointer_cast(simulation->odeSolver())}; + const auto &simulation {std::dynamic_pointer_cast(document->simulations()[0])}; + const auto &solver {std::dynamic_pointer_cast(simulation->odeSolver())}; solver->setMaximumNumberOfSteps(MAXIMUM_NUMBER_OF_STEPS); @@ -63,8 +63,8 @@ TEST(CvodeSolverTest, bandedLinearSolverAndUpperHalfBandwidthValueWithNumberTooS auto file {libOpenCOR::File::create(libOpenCOR::resourcePath("api/solver/ode.cellml"))}; auto document {libOpenCOR::SedDocument::create(file)}; - auto simulation {std::dynamic_pointer_cast(document->simulations()[0])}; - auto solver {std::dynamic_pointer_cast(simulation->odeSolver())}; + const auto &simulation {std::dynamic_pointer_cast(document->simulations()[0])}; + const auto &solver {std::dynamic_pointer_cast(simulation->odeSolver())}; solver->setLinearSolver(libOpenCOR::SolverCvode::LinearSolver::BANDED); solver->setUpperHalfBandwidth(UPPER_HALF_BANDWIDTH); @@ -83,8 +83,8 @@ TEST(CvodeSolverTest, bandedLinearSolverAndUpperHalfBandwidthValueWithNumberTooB auto file {libOpenCOR::File::create(libOpenCOR::resourcePath("api/solver/ode.cellml"))}; auto document {libOpenCOR::SedDocument::create(file)}; - auto simulation {std::dynamic_pointer_cast(document->simulations()[0])}; - auto solver {std::dynamic_pointer_cast(simulation->odeSolver())}; + const auto &simulation {std::dynamic_pointer_cast(document->simulations()[0])}; + const auto &solver {std::dynamic_pointer_cast(simulation->odeSolver())}; solver->setLinearSolver(libOpenCOR::SolverCvode::LinearSolver::BANDED); solver->setUpperHalfBandwidth(UPPER_HALF_BANDWIDTH); @@ -103,8 +103,8 @@ TEST(CvodeSolverTest, bandedLinearSolverAndLowerHalfBandwidthValueWithNumberTooS auto file {libOpenCOR::File::create(libOpenCOR::resourcePath("api/solver/ode.cellml"))}; auto document {libOpenCOR::SedDocument::create(file)}; - auto simulation {std::dynamic_pointer_cast(document->simulations()[0])}; - auto solver {std::dynamic_pointer_cast(simulation->odeSolver())}; + const auto &simulation {std::dynamic_pointer_cast(document->simulations()[0])}; + const auto &solver {std::dynamic_pointer_cast(simulation->odeSolver())}; solver->setLinearSolver(libOpenCOR::SolverCvode::LinearSolver::BANDED); solver->setLowerHalfBandwidth(LOWER_HALF_BANDWIDTH); @@ -123,8 +123,8 @@ TEST(CvodeSolverTest, bandedLinearSolverAndLowerHalfBandwidthValueWithNumberTooB auto file {libOpenCOR::File::create(libOpenCOR::resourcePath("api/solver/ode.cellml"))}; auto document {libOpenCOR::SedDocument::create(file)}; - auto simulation {std::dynamic_pointer_cast(document->simulations()[0])}; - auto solver {std::dynamic_pointer_cast(simulation->odeSolver())}; + const auto &simulation {std::dynamic_pointer_cast(document->simulations()[0])}; + const auto &solver {std::dynamic_pointer_cast(simulation->odeSolver())}; solver->setLinearSolver(libOpenCOR::SolverCvode::LinearSolver::BANDED); solver->setLowerHalfBandwidth(LOWER_HALF_BANDWIDTH); @@ -143,8 +143,8 @@ TEST(CvodeSolverTest, relativeToleranceValueWithInvalidNumber) auto file {libOpenCOR::File::create(libOpenCOR::resourcePath("api/solver/ode.cellml"))}; auto document {libOpenCOR::SedDocument::create(file)}; - auto simulation {std::dynamic_pointer_cast(document->simulations()[0])}; - auto solver {std::dynamic_pointer_cast(simulation->odeSolver())}; + const auto &simulation {std::dynamic_pointer_cast(document->simulations()[0])}; + const auto &solver {std::dynamic_pointer_cast(simulation->odeSolver())}; solver->setRelativeTolerance(RELATIVE_TOLERANCE); @@ -162,8 +162,8 @@ TEST(CvodeSolverTest, absoluteToleranceValueWithInvalidNumber) auto file {libOpenCOR::File::create(libOpenCOR::resourcePath("api/solver/ode.cellml"))}; auto document {libOpenCOR::SedDocument::create(file)}; - auto simulation {std::dynamic_pointer_cast(document->simulations()[0])}; - auto solver {std::dynamic_pointer_cast(simulation->odeSolver())}; + const auto &simulation {std::dynamic_pointer_cast(document->simulations()[0])}; + const auto &solver {std::dynamic_pointer_cast(simulation->odeSolver())}; solver->setAbsoluteTolerance(ABSOLUTE_TOLERANCE); @@ -211,8 +211,8 @@ TEST(CvodeSolverTest, solveWithoutInterpolateSolution) auto file {libOpenCOR::File::create(libOpenCOR::resourcePath("api/solver/ode.cellml"))}; auto document {libOpenCOR::SedDocument::create(file)}; - auto simulation {std::dynamic_pointer_cast(document->simulations()[0])}; - auto solver {std::dynamic_pointer_cast(simulation->odeSolver())}; + const auto &simulation {std::dynamic_pointer_cast(document->simulations()[0])}; + const auto &solver {std::dynamic_pointer_cast(simulation->odeSolver())}; solver->setInterpolateSolution(false); @@ -239,8 +239,8 @@ TEST(CvodeSolverTest, solveWithAdamsMoultonIntegrationMethod) auto file {libOpenCOR::File::create(libOpenCOR::resourcePath("api/solver/ode.cellml"))}; auto document {libOpenCOR::SedDocument::create(file)}; - auto simulation {std::dynamic_pointer_cast(document->simulations()[0])}; - auto solver {std::dynamic_pointer_cast(simulation->odeSolver())}; + const auto &simulation {std::dynamic_pointer_cast(document->simulations()[0])}; + const auto &solver {std::dynamic_pointer_cast(simulation->odeSolver())}; solver->setIntegrationMethod(libOpenCOR::SolverCvode::IntegrationMethod::ADAMS_MOULTON); @@ -267,8 +267,8 @@ TEST(CvodeSolverTest, solveWithFunctionalIterationType) auto file {libOpenCOR::File::create(libOpenCOR::resourcePath("api/solver/ode.cellml"))}; auto document {libOpenCOR::SedDocument::create(file)}; - auto simulation {std::dynamic_pointer_cast(document->simulations()[0])}; - auto solver {std::dynamic_pointer_cast(simulation->odeSolver())}; + const auto &simulation {std::dynamic_pointer_cast(document->simulations()[0])}; + const auto &solver {std::dynamic_pointer_cast(simulation->odeSolver())}; solver->setIterationType(libOpenCOR::SolverCvode::IterationType::FUNCTIONAL); @@ -295,8 +295,8 @@ TEST(CvodeSolverTest, solveWithBandedLinearSolver) auto file {libOpenCOR::File::create(libOpenCOR::resourcePath("api/solver/ode.cellml"))}; auto document {libOpenCOR::SedDocument::create(file)}; - auto simulation {std::dynamic_pointer_cast(document->simulations()[0])}; - auto solver {std::dynamic_pointer_cast(simulation->odeSolver())}; + const auto &simulation {std::dynamic_pointer_cast(document->simulations()[0])}; + const auto &solver {std::dynamic_pointer_cast(simulation->odeSolver())}; solver->setLinearSolver(libOpenCOR::SolverCvode::LinearSolver::BANDED); @@ -323,8 +323,8 @@ TEST(CvodeSolverTest, solveWithDiagonalLinearSolver) auto file {libOpenCOR::File::create(libOpenCOR::resourcePath("api/solver/ode.cellml"))}; auto document {libOpenCOR::SedDocument::create(file)}; - auto simulation {std::dynamic_pointer_cast(document->simulations()[0])}; - auto solver {std::dynamic_pointer_cast(simulation->odeSolver())}; + const auto &simulation {std::dynamic_pointer_cast(document->simulations()[0])}; + const auto &solver {std::dynamic_pointer_cast(simulation->odeSolver())}; solver->setLinearSolver(libOpenCOR::SolverCvode::LinearSolver::DIAGONAL); @@ -351,8 +351,8 @@ TEST(CvodeSolverTest, solveWithGmresLinearSolver) auto file {libOpenCOR::File::create(libOpenCOR::resourcePath("api/solver/ode.cellml"))}; auto document {libOpenCOR::SedDocument::create(file)}; - auto simulation {std::dynamic_pointer_cast(document->simulations()[0])}; - auto solver {std::dynamic_pointer_cast(simulation->odeSolver())}; + const auto &simulation {std::dynamic_pointer_cast(document->simulations()[0])}; + const auto &solver {std::dynamic_pointer_cast(simulation->odeSolver())}; solver->setLinearSolver(libOpenCOR::SolverCvode::LinearSolver::GMRES); @@ -379,8 +379,8 @@ TEST(CvodeSolverTest, solveWithBicgstabLinearSolver) auto file {libOpenCOR::File::create(libOpenCOR::resourcePath("api/solver/ode.cellml"))}; auto document {libOpenCOR::SedDocument::create(file)}; - auto simulation {std::dynamic_pointer_cast(document->simulations()[0])}; - auto solver {std::dynamic_pointer_cast(simulation->odeSolver())}; + const auto &simulation {std::dynamic_pointer_cast(document->simulations()[0])}; + const auto &solver {std::dynamic_pointer_cast(simulation->odeSolver())}; solver->setLinearSolver(libOpenCOR::SolverCvode::LinearSolver::BICGSTAB); @@ -407,8 +407,8 @@ TEST(CvodeSolverTest, solveWithTfqmrLinearSolver) auto file {libOpenCOR::File::create(libOpenCOR::resourcePath("api/solver/ode.cellml"))}; auto document {libOpenCOR::SedDocument::create(file)}; - auto simulation {std::dynamic_pointer_cast(document->simulations()[0])}; - auto solver {std::dynamic_pointer_cast(simulation->odeSolver())}; + const auto &simulation {std::dynamic_pointer_cast(document->simulations()[0])}; + const auto &solver {std::dynamic_pointer_cast(simulation->odeSolver())}; solver->setLinearSolver(libOpenCOR::SolverCvode::LinearSolver::TFQMR); @@ -435,8 +435,8 @@ TEST(CvodeSolverTest, solveWithGmresLinearSolverAndNoPreconditioner) auto file {libOpenCOR::File::create(libOpenCOR::resourcePath("api/solver/ode.cellml"))}; auto document {libOpenCOR::SedDocument::create(file)}; - auto simulation {std::dynamic_pointer_cast(document->simulations()[0])}; - auto solver {std::dynamic_pointer_cast(simulation->odeSolver())}; + const auto &simulation {std::dynamic_pointer_cast(document->simulations()[0])}; + const auto &solver {std::dynamic_pointer_cast(simulation->odeSolver())}; solver->setLinearSolver(libOpenCOR::SolverCvode::LinearSolver::GMRES); solver->setPreconditioner(libOpenCOR::SolverCvode::Preconditioner::NO); @@ -464,8 +464,8 @@ TEST(CvodeSolverTest, solveWithBicgstabLinearSolverAndNoPreconditioner) auto file {libOpenCOR::File::create(libOpenCOR::resourcePath("api/solver/ode.cellml"))}; auto document {libOpenCOR::SedDocument::create(file)}; - auto simulation {std::dynamic_pointer_cast(document->simulations()[0])}; - auto solver {std::dynamic_pointer_cast(simulation->odeSolver())}; + const auto &simulation {std::dynamic_pointer_cast(document->simulations()[0])}; + const auto &solver {std::dynamic_pointer_cast(simulation->odeSolver())}; solver->setLinearSolver(libOpenCOR::SolverCvode::LinearSolver::BICGSTAB); solver->setPreconditioner(libOpenCOR::SolverCvode::Preconditioner::NO); @@ -493,8 +493,8 @@ TEST(CvodeSolverTest, solveWithTfqmrLinearSolverAndNoPreconditioner) auto file {libOpenCOR::File::create(libOpenCOR::resourcePath("api/solver/ode.cellml"))}; auto document {libOpenCOR::SedDocument::create(file)}; - auto simulation {std::dynamic_pointer_cast(document->simulations()[0])}; - auto solver {std::dynamic_pointer_cast(simulation->odeSolver())}; + const auto &simulation {std::dynamic_pointer_cast(document->simulations()[0])}; + const auto &solver {std::dynamic_pointer_cast(simulation->odeSolver())}; solver->setLinearSolver(libOpenCOR::SolverCvode::LinearSolver::TFQMR); solver->setPreconditioner(libOpenCOR::SolverCvode::Preconditioner::NO); diff --git a/tests/api/solver/forwardeulertests.cpp b/tests/api/solver/forwardeulertests.cpp index 9af6c719d..029551564 100644 --- a/tests/api/solver/forwardeulertests.cpp +++ b/tests/api/solver/forwardeulertests.cpp @@ -25,7 +25,7 @@ TEST(ForwardEulerSolverTest, stepValueWithInvalidNumber) auto file {libOpenCOR::File::create(libOpenCOR::resourcePath("api/solver/ode.cellml"))}; auto document {libOpenCOR::SedDocument::create(file)}; - auto simulation {std::dynamic_pointer_cast(document->simulations()[0])}; + const auto &simulation {std::dynamic_pointer_cast(document->simulations()[0])}; auto solver {libOpenCOR::SolverForwardEuler::create()}; solver->setStep(STEP); @@ -53,7 +53,7 @@ TEST(ForwardEulerSolverTest, solve) auto file {libOpenCOR::File::create(libOpenCOR::resourcePath("api/solver/ode.cellml"))}; auto document {libOpenCOR::SedDocument::create(file)}; - auto simulation {std::dynamic_pointer_cast(document->simulations()[0])}; + const auto &simulation {std::dynamic_pointer_cast(document->simulations()[0])}; auto solver {libOpenCOR::SolverForwardEuler::create()}; solver->setStep(STEP); diff --git a/tests/api/solver/fourthorderrungekuttatests.cpp b/tests/api/solver/fourthorderrungekuttatests.cpp index c013ae630..1a2045393 100644 --- a/tests/api/solver/fourthorderrungekuttatests.cpp +++ b/tests/api/solver/fourthorderrungekuttatests.cpp @@ -25,7 +25,7 @@ TEST(FourthOrderRungeKuttaSolverTest, stepValueWithInvalidNumber) auto file {libOpenCOR::File::create(libOpenCOR::resourcePath("api/solver/ode.cellml"))}; auto document {libOpenCOR::SedDocument::create(file)}; - auto simulation {std::dynamic_pointer_cast(document->simulations()[0])}; + const auto &simulation {std::dynamic_pointer_cast(document->simulations()[0])}; auto solver {libOpenCOR::SolverFourthOrderRungeKutta::create()}; solver->setStep(STEP); @@ -53,7 +53,7 @@ TEST(FourthOrderRungeKuttaSolverTest, solve) auto file {libOpenCOR::File::create(libOpenCOR::resourcePath("api/solver/ode.cellml"))}; auto document {libOpenCOR::SedDocument::create(file)}; - auto simulation {std::dynamic_pointer_cast(document->simulations()[0])}; + const auto &simulation {std::dynamic_pointer_cast(document->simulations()[0])}; auto solver {libOpenCOR::SolverFourthOrderRungeKutta::create()}; solver->setStep(STEP); diff --git a/tests/api/solver/heuntests.cpp b/tests/api/solver/heuntests.cpp index 60354b928..5b72857cf 100644 --- a/tests/api/solver/heuntests.cpp +++ b/tests/api/solver/heuntests.cpp @@ -25,7 +25,7 @@ TEST(HeunSolverTest, stepValueWithInvalidNumber) auto file {libOpenCOR::File::create(libOpenCOR::resourcePath("api/solver/ode.cellml"))}; auto document {libOpenCOR::SedDocument::create(file)}; - auto simulation {std::dynamic_pointer_cast(document->simulations()[0])}; + const auto &simulation {std::dynamic_pointer_cast(document->simulations()[0])}; auto solver {libOpenCOR::SolverHeun::create()}; solver->setStep(STEP); @@ -53,7 +53,7 @@ TEST(HeunSolverTest, solve) auto file {libOpenCOR::File::create(libOpenCOR::resourcePath("api/solver/ode.cellml"))}; auto document {libOpenCOR::SedDocument::create(file)}; - auto simulation {std::dynamic_pointer_cast(document->simulations()[0])}; + const auto &simulation {std::dynamic_pointer_cast(document->simulations()[0])}; auto solver {libOpenCOR::SolverHeun::create()}; solver->setStep(STEP); diff --git a/tests/api/solver/kinsoltests.cpp b/tests/api/solver/kinsoltests.cpp index a56010b3c..3df2db418 100644 --- a/tests/api/solver/kinsoltests.cpp +++ b/tests/api/solver/kinsoltests.cpp @@ -26,8 +26,8 @@ TEST(KinsolSolverTest, maximumNumberOfIterationsValueWithInvalidNumber) auto file {libOpenCOR::File::create(libOpenCOR::resourcePath("api/solver/nla1.cellml"))}; auto document {libOpenCOR::SedDocument::create(file)}; - auto simulation {std::dynamic_pointer_cast(document->simulations()[0])}; - auto solver {std::dynamic_pointer_cast(simulation->nlaSolver())}; + const auto &simulation {std::dynamic_pointer_cast(document->simulations()[0])}; + const auto &solver {std::dynamic_pointer_cast(simulation->nlaSolver())}; solver->setMaximumNumberOfIterations(0); @@ -44,8 +44,8 @@ TEST(KinsolSolverTest, bandedLinearSolverAndUpperHalfBandwidthValueWithNumberToo auto file {libOpenCOR::File::create(libOpenCOR::resourcePath("api/solver/nla2.cellml"))}; auto document {libOpenCOR::SedDocument::create(file)}; - auto simulation {std::dynamic_pointer_cast(document->simulations()[0])}; - auto solver {std::dynamic_pointer_cast(simulation->nlaSolver())}; + const auto &simulation {std::dynamic_pointer_cast(document->simulations()[0])}; + const auto &solver {std::dynamic_pointer_cast(simulation->nlaSolver())}; solver->setLinearSolver(libOpenCOR::SolverKinsol::LinearSolver::BANDED); solver->setUpperHalfBandwidth(-1); @@ -63,8 +63,8 @@ TEST(KinsolSolverTest, bandedLinearSolverAndUpperHalfBandwidthValueWithNumberToo auto file {libOpenCOR::File::create(libOpenCOR::resourcePath("api/solver/nla1.cellml"))}; auto document {libOpenCOR::SedDocument::create(file)}; - auto simulation {std::dynamic_pointer_cast(document->simulations()[0])}; - auto solver {std::dynamic_pointer_cast(simulation->nlaSolver())}; + const auto &simulation {std::dynamic_pointer_cast(document->simulations()[0])}; + const auto &solver {std::dynamic_pointer_cast(simulation->nlaSolver())}; solver->setLinearSolver(libOpenCOR::SolverKinsol::LinearSolver::BANDED); solver->setUpperHalfBandwidth(1); @@ -82,8 +82,8 @@ TEST(KinsolSolverTest, bandedLinearSolverAndLowerHalfBandwidthValueWithNumberToo auto file {libOpenCOR::File::create(libOpenCOR::resourcePath("api/solver/nla2.cellml"))}; auto document {libOpenCOR::SedDocument::create(file)}; - auto simulation {std::dynamic_pointer_cast(document->simulations()[0])}; - auto solver {std::dynamic_pointer_cast(simulation->nlaSolver())}; + const auto &simulation {std::dynamic_pointer_cast(document->simulations()[0])}; + const auto &solver {std::dynamic_pointer_cast(simulation->nlaSolver())}; solver->setLinearSolver(libOpenCOR::SolverKinsol::LinearSolver::BANDED); solver->setLowerHalfBandwidth(-1); @@ -101,8 +101,8 @@ TEST(KinsolSolverTest, bandedLinearSolverAndLowerHalfBandwidthValueWithNumberToo auto file {libOpenCOR::File::create(libOpenCOR::resourcePath("api/solver/nla1.cellml"))}; auto document {libOpenCOR::SedDocument::create(file)}; - auto simulation {std::dynamic_pointer_cast(document->simulations()[0])}; - auto solver {std::dynamic_pointer_cast(simulation->nlaSolver())}; + const auto &simulation {std::dynamic_pointer_cast(document->simulations()[0])}; + const auto &solver {std::dynamic_pointer_cast(simulation->nlaSolver())}; solver->setLinearSolver(libOpenCOR::SolverKinsol::LinearSolver::BANDED); solver->setLowerHalfBandwidth(1); @@ -158,8 +158,8 @@ TEST(KinsolSolverTest, solveWithBandedLinearSolver) { auto file {libOpenCOR::File::create(libOpenCOR::resourcePath("api/solver/nla2.cellml"))}; auto document {libOpenCOR::SedDocument::create(file)}; - auto simulation {std::dynamic_pointer_cast(document->simulations()[0])}; - auto solver {std::dynamic_pointer_cast(simulation->nlaSolver())}; + const auto &simulation {std::dynamic_pointer_cast(document->simulations()[0])}; + const auto &solver {std::dynamic_pointer_cast(simulation->nlaSolver())}; solver->setLinearSolver(libOpenCOR::SolverKinsol::LinearSolver::BANDED); solver->setUpperHalfBandwidth(2); @@ -176,8 +176,8 @@ TEST(KinsolSolverTest, solveWithGmresLinearSolver) { auto file {libOpenCOR::File::create(libOpenCOR::resourcePath("api/solver/nla1.cellml"))}; auto document {libOpenCOR::SedDocument::create(file)}; - auto simulation {std::dynamic_pointer_cast(document->simulations()[0])}; - auto solver {std::dynamic_pointer_cast(simulation->nlaSolver())}; + const auto &simulation {std::dynamic_pointer_cast(document->simulations()[0])}; + const auto &solver {std::dynamic_pointer_cast(simulation->nlaSolver())}; solver->setLinearSolver(libOpenCOR::SolverKinsol::LinearSolver::GMRES); @@ -192,8 +192,8 @@ TEST(KinsolSolverTest, solveWithBicgstabLinearSolver) { auto file {libOpenCOR::File::create(libOpenCOR::resourcePath("api/solver/nla2.cellml"))}; auto document {libOpenCOR::SedDocument::create(file)}; - auto simulation {std::dynamic_pointer_cast(document->simulations()[0])}; - auto solver {std::dynamic_pointer_cast(simulation->nlaSolver())}; + const auto &simulation {std::dynamic_pointer_cast(document->simulations()[0])}; + const auto &solver {std::dynamic_pointer_cast(simulation->nlaSolver())}; solver->setLinearSolver(libOpenCOR::SolverKinsol::LinearSolver::BICGSTAB); @@ -208,8 +208,8 @@ TEST(KinsolSolverTest, solveWithTfqmrLinearSolver) { auto file {libOpenCOR::File::create(libOpenCOR::resourcePath("api/solver/nla1.cellml"))}; auto document {libOpenCOR::SedDocument::create(file)}; - auto simulation {std::dynamic_pointer_cast(document->simulations()[0])}; - auto solver {std::dynamic_pointer_cast(simulation->nlaSolver())}; + const auto &simulation {std::dynamic_pointer_cast(document->simulations()[0])}; + const auto &solver {std::dynamic_pointer_cast(simulation->nlaSolver())}; solver->setLinearSolver(libOpenCOR::SolverKinsol::LinearSolver::TFQMR); diff --git a/tests/api/solver/odemodel.cpp b/tests/api/solver/odemodel.cpp index 33dba869b..c077a3cc6 100644 --- a/tests/api/solver/odemodel.cpp +++ b/tests/api/solver/odemodel.cpp @@ -28,7 +28,7 @@ void run(const libOpenCOR::SedDocumentPtr &pDocument, static const auto OUTPUT_END_TIME {50.0}; static const auto NUMBER_OF_STEPS {50000}; - auto simulation {std::dynamic_pointer_cast(pDocument->simulations()[0])}; + const auto &simulation {std::dynamic_pointer_cast(pDocument->simulations()[0])}; simulation->setOutputEndTime(OUTPUT_END_TIME); simulation->setNumberOfSteps(NUMBER_OF_STEPS); @@ -37,7 +37,7 @@ void run(const libOpenCOR::SedDocumentPtr &pDocument, instance->run(); - auto instanceTask {instance->tasks()[0]}; + const auto &instanceTask {instance->tasks()[0]}; EXPECT_EQ_VALUES(instanceTask, 13000, pStateValues, pStateAbsTols, diff --git a/tests/api/solver/secondorderrungekuttatests.cpp b/tests/api/solver/secondorderrungekuttatests.cpp index 936518fe3..2334ca3b5 100644 --- a/tests/api/solver/secondorderrungekuttatests.cpp +++ b/tests/api/solver/secondorderrungekuttatests.cpp @@ -25,7 +25,7 @@ TEST(SecondOrderRungeKuttaSolverTest, stepValueWithInvalidNumber) auto file {libOpenCOR::File::create(libOpenCOR::resourcePath("api/solver/ode.cellml"))}; auto document {libOpenCOR::SedDocument::create(file)}; - auto simulation {std::dynamic_pointer_cast(document->simulations()[0])}; + const auto &simulation {std::dynamic_pointer_cast(document->simulations()[0])}; auto solver {libOpenCOR::SolverSecondOrderRungeKutta::create()}; solver->setStep(STEP); @@ -53,7 +53,7 @@ TEST(SecondOrderRungeKuttaSolverTest, solve) auto file {libOpenCOR::File::create(libOpenCOR::resourcePath("api/solver/ode.cellml"))}; auto document {libOpenCOR::SedDocument::create(file)}; - auto simulation {std::dynamic_pointer_cast(document->simulations()[0])}; + const auto &simulation {std::dynamic_pointer_cast(document->simulations()[0])}; auto solver {libOpenCOR::SolverSecondOrderRungeKutta::create()}; solver->setStep(STEP); diff --git a/tests/install/src/main.cpp b/tests/install/src/main.cpp index 416904947..b44c00b49 100644 --- a/tests/install/src/main.cpp +++ b/tests/install/src/main.cpp @@ -14,7 +14,7 @@ int main() auto file {libOpenCOR::File::create("https://raw.githubusercontent.com/opencor/libopencor/master/tests/res/cellml_2.omex")}; auto document {libOpenCOR::SedDocument::create(file)}; - auto simulation {std::dynamic_pointer_cast(document->simulations()[0])}; + const auto &simulation {std::dynamic_pointer_cast(document->simulations()[0])}; simulation->setOutputEndTime(5.0); simulation->setNumberOfSteps(500); @@ -23,7 +23,7 @@ int main() instance->run(); - auto instanceTask {instance->tasks()[0]}; + const auto &instanceTask {instance->tasks()[0]}; std::cout << "\n"; std::cout << "---[ File information ]---\n"; diff --git a/tests/misc/failingsimulationtests.cpp b/tests/misc/failingsimulationtests.cpp index 82b8f8c7c..f910830b9 100644 --- a/tests/misc/failingsimulationtests.cpp +++ b/tests/misc/failingsimulationtests.cpp @@ -31,7 +31,7 @@ TEST(FailingSimulationTest, basic) // Set the value of `membrane.test` to zero and rerun the simulation. - auto model = document->model(0); + const auto &model {document->model(0)}; model->addChange(libOpenCOR::SedChangeAttribute::create("membrane", "test", "0.0")); diff --git a/tests/utils.cpp b/tests/utils.cpp index e6a9055d1..99720a6ef 100644 --- a/tests/utils.cpp +++ b/tests/utils.cpp @@ -28,7 +28,7 @@ namespace libOpenCOR { void expectEqualIssues(const LoggerPtr &pLogger, const ExpectedIssues &pExpectedIssues) { - auto issues {pLogger->issues()}; + const auto &issues {pLogger->issues()}; EXPECT_EQ(issues.size(), pExpectedIssues.size());