From a059adbc2f909c795e47dcc42cdb809b1212a110 Mon Sep 17 00:00:00 2001 From: Kyle Shores Date: Thu, 14 May 2026 14:17:10 -0500 Subject: [PATCH 01/10] Optionally use std::format Introduces a CMake option `MECH_CONFIG_USE_FMT` (default OFF) to use the {fmt} library instead of `std::format`. A shim header (`format_compat.hpp`) aliases fmt or std into `mc_fmt` so call sites are unchanged. Packaging conditionally installs fmt when built from source and emits `find_dependency(fmt)` when found via the system. fmt headers are exposed with PUBLIC linkage since they appear in the public `format_compat.hpp` header. CI tests both `MECH_CONFIG_USE_FMT=OFF` and `ON` via a matrix dimension across Mac, Ubuntu, and Windows workflows. Adds a `MECH_CONFIG_COMPILE_WARNING_AS_ERROR` option (default OFF) that passes `/WX` on MSVC and `-Werror` elsewhere. Enabled in all CI workflows and Dockerfiles. Fixes the clang-cl warnings this exposed: removes unused `status` variables in `v0/parser.cpp` and `v1/mechanism_parsers.cpp`, drops unused `phase_optional` return values in the development model validators, and removes redundant `std::move()` on temporaries returned by `GetComments()` (pessimizing-move). Co-Authored-By: Claude Sonnet 4.6 --- .github/workflows/mac.yml | 9 +++--- .github/workflows/ubuntu.yml | 24 +++------------ .github/workflows/windows.yml | 29 ++++++------------- CMakeLists.txt | 2 ++ cmake/dependencies.cmake | 16 ++++++++++ cmake/mechanism_configurationConfig.cmake.in | 6 ++++ docker/Dockerfile | 1 + docker/Dockerfile.coverage | 1 + .../error_location.hpp | 24 ++++++++++++--- .../mechanism_configuration/format_compat.hpp | 13 +++++++++ packaging/CMakeLists.txt | 13 ++++++++- src/CMakeLists.txt | 17 +++++++++-- src/development/mechanism.cpp | 8 ++--- src/development/models/validators/gas.cpp | 2 +- src/development/models/validators/modal.cpp | 4 +-- .../validators/aqueous_equilibrium.cpp | 2 +- .../reactions/validators/arrhenius.cpp | 4 +-- .../reactions/validators/branched.cpp | 2 +- .../validators/condensed_phase_arrhenius.cpp | 4 +-- .../validators/condensed_phase_photolysis.cpp | 4 +-- .../reactions/validators/emission.cpp | 2 +- .../reactions/validators/first_order_loss.cpp | 4 +-- .../reactions/validators/henrys_law.cpp | 4 +-- .../validators/lambda_rate_constant.cpp | 2 +- .../reactions/validators/photolysis.cpp | 4 +-- .../validators/simpol_phase_transfer.cpp | 10 +++---- .../reactions/validators/surface.cpp | 4 +-- .../reactions/validators/taylor_series.cpp | 4 +-- .../reactions/validators/user_defined.cpp | 2 +- .../reactions/validators/wet_deposition.cpp | 2 +- src/development/type_parsers.cpp | 6 ++-- src/development/type_validators.cpp | 18 ++++++------ src/development/utils.cpp | 10 +++---- src/parser.cpp | 10 +++---- src/v0/parser.cpp | 3 -- src/v1/mechanism_parsers.cpp | 1 - src/validate_schema.cpp | 8 ++--- 37 files changed, 164 insertions(+), 115 deletions(-) create mode 100644 include/mechanism_configuration/format_compat.hpp diff --git a/.github/workflows/mac.yml b/.github/workflows/mac.yml index be116974..dd99519d 100644 --- a/.github/workflows/mac.yml +++ b/.github/workflows/mac.yml @@ -1,6 +1,6 @@ name: Mac -on: +on: push: branches: - main @@ -19,6 +19,7 @@ jobs: matrix: xcode: ['16.4'] build_type: [Release] + use_fmt: [OFF, ON] compiler: - { cpp: g++-13, c: gcc-13 } - { cpp: g++-14, c: gcc-14 } @@ -36,8 +37,8 @@ jobs: with: xcode-version: ${{ matrix.xcode }} - - name: Run Cmake - run: cmake -S . -B build -D CMAKE_BUILD_TYPE=${{ matrix.build_type }} + - name: Run Cmake + run: cmake -S . -B build -D CMAKE_BUILD_TYPE=${{ matrix.build_type }} -D MECH_CONFIG_USE_FMT=${{ matrix.use_fmt }} -D MECH_CONFIG_COMPILE_WARNING_AS_ERROR=ON - name: Build run: cmake --build build --parallel 10 @@ -45,4 +46,4 @@ jobs: - name: Run tests run: | cd build - ctest -C ${{ matrix.build_type }} --rerun-failed --output-on-failure --verbose \ No newline at end of file + ctest -C ${{ matrix.build_type }} --rerun-failed --output-on-failure --verbose diff --git a/.github/workflows/ubuntu.yml b/.github/workflows/ubuntu.yml index d974e307..39c09daa 100644 --- a/.github/workflows/ubuntu.yml +++ b/.github/workflows/ubuntu.yml @@ -1,12 +1,12 @@ name: Ubuntu -on: +on: push: branches: - main pull_request: workflow_dispatch: - + concurrency: group: ${{ github.workflow }}-${{ github.ref || github.run_id }} cancel-in-progress: true @@ -22,6 +22,7 @@ jobs: - { cpp: g++-14, c: gcc-14 } - { cpp: clang++, c: clang } build_type: [Release] + use_fmt: [OFF, ON] env: CC: ${{ matrix.compiler.c }} CXX: ${{ matrix.compiler.cpp }} @@ -29,25 +30,8 @@ jobs: - name: Checkout code uses: actions/checkout@v4 - - name: Install GCC 13 if needed - if: matrix.compiler.cpp == 'clang++' - run: | - sudo apt update - sudo apt install -y gcc-13 g++-13 - - name: Configure CMake - run: | - if [[ "${{ matrix.compiler.cpp }}" == "clang++" ]]; then - cmake -S . -B build \ - -D CMAKE_BUILD_TYPE=${{ matrix.build_type }} \ - -D CMAKE_CXX_STANDARD=20 \ - -D CMAKE_CXX_COMPILER=${CXX} \ - -D CMAKE_EXE_LINKER_FLAGS="-stdlib=libstdc++" \ - -D CMAKE_CXX_FLAGS="--gcc-toolchain=/usr" - else - cmake -S . -B build -D CMAKE_BUILD_TYPE=${{ matrix.build_type }} \ - -D CMAKE_CXX_STANDARD=20 - fi + run: cmake -S . -B build -D CMAKE_BUILD_TYPE=${{ matrix.build_type }} -D MECH_CONFIG_USE_FMT=${{ matrix.use_fmt }} -D MECH_CONFIG_COMPILE_WARNING_AS_ERROR=ON - name: Build run: cmake --build build --config ${{ matrix.build_type }} --parallel 10 diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index b2f5d173..fd380730 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -1,6 +1,6 @@ name: Windows -on: +on: push: branches: - main @@ -19,28 +19,15 @@ jobs: matrix: build_type: [Release, Debug] architecture: [Win32, x64] + use_fmt: [OFF, ON] steps: - name: Checkout code uses: actions/checkout@v4 - - name: Setup Python - if: matrix.architecture == 'Win32' - uses: actions/setup-python@v5 - with: - python-version: '3.9' - architecture: 'x86' - - - name: Setup Python - if: matrix.architecture == 'x64' - uses: actions/setup-python@v5 - with: - python-version: '3.9' - architecture: 'x64' - - name: Run Cmake - run: cmake -S . -B build -A ${{ matrix.architecture }} -D CMAKE_BUILD_TYPE=${{ matrix.build_type }} -DCMAKE_POLICY_VERSION_MINIMUM="3.5" - + run: cmake -S . -B build -A ${{ matrix.architecture }} -D CMAKE_BUILD_TYPE=${{ matrix.build_type }} -D MECH_CONFIG_USE_FMT=${{ matrix.use_fmt }} -D MECH_CONFIG_COMPILE_WARNING_AS_ERROR=ON + - name: Build run: cmake --build build --config ${{ matrix.build_type }} --parallel 10 @@ -51,11 +38,12 @@ jobs: msys2: runs-on: windows-latest - continue-on-error: true + continue-on-error: true strategy: fail-fast: false matrix: build_type: [Debug, Release] + use_fmt: [OFF, ON] steps: - name: Checkout code @@ -81,7 +69,8 @@ jobs: run: | cmake -S . -B build -G "MinGW Makefiles" \ -D CMAKE_BUILD_TYPE=${{ matrix.build_type }} \ - -D CMAKE_POLICY_VERSION_MINIMUM=3.5 + -D MECH_CONFIG_USE_FMT=${{ matrix.use_fmt }} \ + -D MECH_CONFIG_COMPILE_WARNING_AS_ERROR=ON - name: Build the project shell: msys2 {0} @@ -90,4 +79,4 @@ jobs: - name: Run tests shell: msys2 {0} run: ctest --rerun-failed --output-on-failure . --verbose - working-directory: build \ No newline at end of file + working-directory: build diff --git a/CMakeLists.txt b/CMakeLists.txt index eb2ba39f..a9452d22 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -27,6 +27,8 @@ set(CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH};${PROJECT_SOURCE_DIR}/cmake") option(MECH_CONFIG_ENABLE_TESTS "Build the tests" ON) option(MECH_CONFIG_BUILD_SHARED_LIBS "Build shared libraries" OFF) option(MECH_CONFIG_ENABLE_COVERAGE "Enable code coverage output" OFF) +option(MECH_CONFIG_USE_FMT "Use {fmt} library instead of std::format" OFF) +option(MECH_CONFIG_COMPILE_WARNING_AS_ERROR "Treat compiler warnings as errors for mechanism configuration targets" OFF) set(MECH_CONFIG_INSTALL_INCLUDE_DIR ${CMAKE_INSTALL_INCLUDEDIR}) set(MECH_CONFIG_LIB_DIR ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}) diff --git a/cmake/dependencies.cmake b/cmake/dependencies.cmake index 9269eb1d..3fabc44f 100644 --- a/cmake/dependencies.cmake +++ b/cmake/dependencies.cmake @@ -27,6 +27,22 @@ if(PROJECT_IS_TOP_LEVEL AND MECH_CONFIG_ENABLE_TESTS) FetchContent_MakeAvailable(googletest) endif() +################################################################################ +# fmt + +if(MECH_CONFIG_USE_FMT) + set_git_default(FMT_GIT_REPOSITORY https://github.com/fmtlib/fmt.git) + set_git_default(FMT_GIT_TAG 12.1.0) + + FetchContent_Declare(fmt + GIT_REPOSITORY ${FMT_GIT_REPOSITORY} + GIT_TAG ${FMT_GIT_TAG} + FIND_PACKAGE_ARGS NAMES fmt + ) + + FetchContent_MakeAvailable(fmt) +endif() + ################################################################################ # yaml-cpp diff --git a/cmake/mechanism_configurationConfig.cmake.in b/cmake/mechanism_configurationConfig.cmake.in index 3cc6a433..96dc49c1 100644 --- a/cmake/mechanism_configurationConfig.cmake.in +++ b/cmake/mechanism_configurationConfig.cmake.in @@ -1,5 +1,11 @@ @PACKAGE_INIT@ +include(CMakeFindDependencyMacro) + +if(@MECH_CONFIG_FMT_FIND_DEPENDENCY@) + find_dependency(fmt) +endif() + include("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@_Exports.cmake") check_required_components("@PROJECT_NAME@") \ No newline at end of file diff --git a/docker/Dockerfile b/docker/Dockerfile index 8ec0ce3b..832392bf 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -18,6 +18,7 @@ RUN mkdir /build \ && cd /build \ && cmake \ -D CMAKE_BUILD_TYPE=debug \ + -D MECH_CONFIG_COMPILE_WARNING_AS_ERROR=ON \ ../mechanism_configuration \ && make install -j 8 diff --git a/docker/Dockerfile.coverage b/docker/Dockerfile.coverage index bce71cac..83e10bba 100644 --- a/docker/Dockerfile.coverage +++ b/docker/Dockerfile.coverage @@ -19,6 +19,7 @@ RUN mkdir /build \ && cmake \ -D CMAKE_BUILD_TYPE=debug \ -D MECH_CONFIG_ENABLE_COVERAGE:BOOL=TRUE \ + -D MECH_CONFIG_COMPILE_WARNING_AS_ERROR=ON \ ../mechanism_configuration \ && make install -j 8 diff --git a/include/mechanism_configuration/error_location.hpp b/include/mechanism_configuration/error_location.hpp index cd684469..cf04b53b 100644 --- a/include/mechanism_configuration/error_location.hpp +++ b/include/mechanism_configuration/error_location.hpp @@ -4,7 +4,7 @@ #pragma once -#include +#include #include namespace mechanism_configuration @@ -24,16 +24,32 @@ namespace mechanism_configuration }; } // namespace mechanism_configuration -template<> +#ifdef MECH_CONFIG_USE_FMT +template <> +struct fmt::formatter +{ + constexpr auto parse(fmt::format_parse_context& ctx) const + { + return ctx.begin(); + } + template + auto format(const mechanism_configuration::ErrorLocation& loc, FormatContext& ctx) const + { + return fmt::format_to(ctx.out(), "{}:{}", loc.line, loc.column); + } +}; +#else +template <> struct std::formatter { constexpr auto parse(std::format_parse_context& ctx) const { return ctx.begin(); } - template + template auto format(const mechanism_configuration::ErrorLocation& loc, FormatContext& ctx) const { return std::format_to(ctx.out(), "{}:{}", loc.line, loc.column); } -}; \ No newline at end of file +}; +#endif \ No newline at end of file diff --git a/include/mechanism_configuration/format_compat.hpp b/include/mechanism_configuration/format_compat.hpp new file mode 100644 index 00000000..38532114 --- /dev/null +++ b/include/mechanism_configuration/format_compat.hpp @@ -0,0 +1,13 @@ +// Copyright (C) 2023–2026 University Corporation for Atmospheric Research +// University of Illinois at Urbana-Champaign +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#ifdef MECH_CONFIG_USE_FMT +# include +namespace mc_fmt = fmt; +#else +# include +namespace mc_fmt = std; +#endif diff --git a/packaging/CMakeLists.txt b/packaging/CMakeLists.txt index b3169bab..ed311f4f 100644 --- a/packaging/CMakeLists.txt +++ b/packaging/CMakeLists.txt @@ -2,11 +2,22 @@ include(CMakePackageConfigHelpers) include(GNUInstallDirs) set(INSTALL_PREFIX "mechanism_configuration-${PROJECT_VERSION}" ) +set(MECH_CONFIG_OPTIONAL_INSTALL_TARGETS "") +set(MECH_CONFIG_FMT_FIND_DEPENDENCY OFF) +if(MECH_CONFIG_USE_FMT) + if(fmt_POPULATED) + list(APPEND MECH_CONFIG_OPTIONAL_INSTALL_TARGETS fmt) + else() + set(MECH_CONFIG_FMT_FIND_DEPENDENCY ON) + endif() +endif() + install( TARGETS mechanism_configuration yaml-cpp - EXPORT + ${MECH_CONFIG_OPTIONAL_INSTALL_TARGETS} + EXPORT mechanism_configuration_Exports LIBRARY DESTINATION ${INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR} diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 94ab851a..8a686138 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -12,6 +12,11 @@ add_library(musica::mechanism_configuration ALIAS mechanism_configuration) target_compile_features(mechanism_configuration PUBLIC cxx_std_20) +if(MECH_CONFIG_USE_FMT) + target_compile_definitions(mechanism_configuration PUBLIC MECH_CONFIG_USE_FMT) + target_link_libraries(mechanism_configuration PUBLIC fmt::fmt) +endif() + set_target_properties(mechanism_configuration PROPERTIES ARCHIVE_OUTPUT_DIRECTORY ${MECH_CONFIG_LIB_DIR} LIBRARY_OUTPUT_DIRECTORY ${MECH_CONFIG_LIB_DIR} @@ -37,11 +42,19 @@ add_subdirectory(v0) add_subdirectory(v1) add_subdirectory(development) -target_link_libraries(mechanism_configuration - PUBLIC +target_link_libraries(mechanism_configuration + PUBLIC yaml-cpp::yaml-cpp ) +if(MECH_CONFIG_COMPILE_WARNING_AS_ERROR) + if(MSVC) + target_compile_options(mechanism_configuration PRIVATE /WX) + else() + target_compile_options(mechanism_configuration PRIVATE -Werror) + endif() +endif() + if (APPLE) # set the rpath for the shared library set_target_properties(mechanism_configuration PROPERTIES diff --git a/src/development/mechanism.cpp b/src/development/mechanism.cpp index 2645066a..fc7e2f42 100644 --- a/src/development/mechanism.cpp +++ b/src/development/mechanism.cpp @@ -12,7 +12,7 @@ #include -#include +#include namespace mechanism_configuration { @@ -24,7 +24,7 @@ namespace mechanism_configuration if (!std::filesystem::exists(config_path) || !std::filesystem::is_regular_file(config_path)) { throw std::runtime_error( - std::format("Configuration file '{}' does not exist or is not a regular file.", config_path.string())); + mc_fmt::format("Configuration file '{}' does not exist or is not a regular file.", config_path.string())); } SetConfigPath(config_path.string()); @@ -35,7 +35,7 @@ namespace mechanism_configuration } catch (const YAML::Exception& e) { - throw std::runtime_error(std::format("Failed to parse '{}': {}", config_path.string(), e.what())); + throw std::runtime_error(mc_fmt::format("Failed to parse '{}': {}", config_path.string(), e.what())); } } @@ -68,7 +68,7 @@ namespace mechanism_configuration { ErrorLocation error_location{ object[validation::version].Mark().line, object[validation::version].Mark().column }; - std::string message = std::format( + std::string message = mc_fmt::format( "{} error: The version must be '{}' but the invalid version number '{}' found.", error_location, MAJOR_VERSION, diff --git a/src/development/models/validators/gas.cpp b/src/development/models/validators/gas.cpp index a9962496..c9da44e8 100644 --- a/src/development/models/validators/gas.cpp +++ b/src/development/models/validators/gas.cpp @@ -27,7 +27,7 @@ namespace mechanism_configuration return errors; } - auto phase_optional = CheckPhaseExists(object, validation::phase, existing_phases, errors); + CheckPhaseExists(object, validation::phase, existing_phases, errors); return errors; } diff --git a/src/development/models/validators/modal.cpp b/src/development/models/validators/modal.cpp index 7f683d23..dfbadd24 100644 --- a/src/development/models/validators/modal.cpp +++ b/src/development/models/validators/modal.cpp @@ -39,7 +39,7 @@ namespace mechanism_configuration const auto& node = object[validation::modes]; ErrorLocation error_location{ node.Mark().line, node.Mark().column }; - std::string message = std::format( + std::string message = mc_fmt::format( "{} error: Expected 'modes' to be a sequence, but found a different type in the '{}' model.", error_location, object[validation::type].as()); @@ -58,7 +58,7 @@ namespace mechanism_configuration continue; } - auto phase_optional = CheckPhaseExists( + CheckPhaseExists( mode_object, validation::phase, existing_phases, diff --git a/src/development/reactions/validators/aqueous_equilibrium.cpp b/src/development/reactions/validators/aqueous_equilibrium.cpp index 1939af06..b4169c91 100644 --- a/src/development/reactions/validators/aqueous_equilibrium.cpp +++ b/src/development/reactions/validators/aqueous_equilibrium.cpp @@ -10,7 +10,7 @@ #include #include -#include +#include namespace mechanism_configuration { diff --git a/src/development/reactions/validators/arrhenius.cpp b/src/development/reactions/validators/arrhenius.cpp index c6a23d41..c49ebdc4 100644 --- a/src/development/reactions/validators/arrhenius.cpp +++ b/src/development/reactions/validators/arrhenius.cpp @@ -11,7 +11,7 @@ #include #include -#include +#include namespace mechanism_configuration { @@ -66,7 +66,7 @@ namespace mechanism_configuration const auto& node = object[validation::Ea]; ErrorLocation error_location{ node.Mark().line, node.Mark().column }; - std::string message = std::format( + std::string message = mc_fmt::format( "{} error: Mutually exclusive option of 'Ea' and 'C' found in '{}' reaction.", error_location, object[validation::type].as()); diff --git a/src/development/reactions/validators/branched.cpp b/src/development/reactions/validators/branched.cpp index 9b549199..ca2649ca 100644 --- a/src/development/reactions/validators/branched.cpp +++ b/src/development/reactions/validators/branched.cpp @@ -10,7 +10,7 @@ #include #include -#include +#include namespace mechanism_configuration { diff --git a/src/development/reactions/validators/condensed_phase_arrhenius.cpp b/src/development/reactions/validators/condensed_phase_arrhenius.cpp index bcf57837..586ffaf9 100644 --- a/src/development/reactions/validators/condensed_phase_arrhenius.cpp +++ b/src/development/reactions/validators/condensed_phase_arrhenius.cpp @@ -11,7 +11,7 @@ #include #include -#include +#include namespace mechanism_configuration { @@ -66,7 +66,7 @@ namespace mechanism_configuration const auto& node = object[validation::Ea]; ErrorLocation error_location{ node.Mark().line, node.Mark().column }; - std::string message = std::format( + std::string message = mc_fmt::format( "{} error: Mutually exclusive option of 'Ea' and 'C' found in '{}' reaction.", error_location, object[validation::type].as()); diff --git a/src/development/reactions/validators/condensed_phase_photolysis.cpp b/src/development/reactions/validators/condensed_phase_photolysis.cpp index 863427b3..c6db4d94 100644 --- a/src/development/reactions/validators/condensed_phase_photolysis.cpp +++ b/src/development/reactions/validators/condensed_phase_photolysis.cpp @@ -10,7 +10,7 @@ #include #include -#include +#include namespace mechanism_configuration { @@ -79,7 +79,7 @@ namespace mechanism_configuration const auto& node = object[validation::reactants]; ErrorLocation error_location{ node.Mark().line, node.Mark().column }; - std::string message = std::format( + std::string message = mc_fmt::format( "{} error: '{}' reaction requires one reactant, but {} were provided.", error_location, object[validation::type].as(), diff --git a/src/development/reactions/validators/emission.cpp b/src/development/reactions/validators/emission.cpp index 1b8620f2..3fcf3b58 100644 --- a/src/development/reactions/validators/emission.cpp +++ b/src/development/reactions/validators/emission.cpp @@ -10,7 +10,7 @@ #include #include -#include +#include namespace mechanism_configuration { diff --git a/src/development/reactions/validators/first_order_loss.cpp b/src/development/reactions/validators/first_order_loss.cpp index 35f3b00a..3eccd499 100644 --- a/src/development/reactions/validators/first_order_loss.cpp +++ b/src/development/reactions/validators/first_order_loss.cpp @@ -10,7 +10,7 @@ #include #include -#include +#include namespace mechanism_configuration { @@ -67,7 +67,7 @@ namespace mechanism_configuration const auto& node = object[validation::reactants]; ErrorLocation error_location{ node.Mark().line, node.Mark().column }; - std::string message = std::format( + std::string message = mc_fmt::format( "{} error: '{}' reaction requires one reactant, but {} were provided.", error_location, object[validation::type].as(), diff --git a/src/development/reactions/validators/henrys_law.cpp b/src/development/reactions/validators/henrys_law.cpp index 3a88ea75..eacdcbc4 100644 --- a/src/development/reactions/validators/henrys_law.cpp +++ b/src/development/reactions/validators/henrys_law.cpp @@ -10,7 +10,7 @@ #include #include -#include +#include namespace mechanism_configuration { @@ -91,7 +91,7 @@ namespace mechanism_configuration const auto& node = object[validation::particle][validation::solvent]; ErrorLocation error_location{ node.Mark().line, node.Mark().column }; - std::string message = std::format( + std::string message = mc_fmt::format( "{} error: '{}' reaction requires one solute, but {} were provided.", error_location, object[validation::type].as(), diff --git a/src/development/reactions/validators/lambda_rate_constant.cpp b/src/development/reactions/validators/lambda_rate_constant.cpp index 76604a29..90702769 100644 --- a/src/development/reactions/validators/lambda_rate_constant.cpp +++ b/src/development/reactions/validators/lambda_rate_constant.cpp @@ -10,7 +10,7 @@ #include #include -#include +#include namespace mechanism_configuration { diff --git a/src/development/reactions/validators/photolysis.cpp b/src/development/reactions/validators/photolysis.cpp index 3652c673..37c54e5a 100644 --- a/src/development/reactions/validators/photolysis.cpp +++ b/src/development/reactions/validators/photolysis.cpp @@ -10,7 +10,7 @@ #include #include -#include +#include namespace mechanism_configuration { @@ -79,7 +79,7 @@ namespace mechanism_configuration const auto& node = object[validation::reactants]; ErrorLocation error_location{ node.Mark().line, node.Mark().column }; - std::string message = std::format( + std::string message = mc_fmt::format( "{} error: '{}' reaction requires one reactant, but {} were provided.", error_location, object[validation::type].as(), diff --git a/src/development/reactions/validators/simpol_phase_transfer.cpp b/src/development/reactions/validators/simpol_phase_transfer.cpp index efe165c2..13b37d34 100644 --- a/src/development/reactions/validators/simpol_phase_transfer.cpp +++ b/src/development/reactions/validators/simpol_phase_transfer.cpp @@ -10,7 +10,7 @@ #include #include -#include +#include namespace mechanism_configuration { @@ -78,10 +78,10 @@ namespace mechanism_configuration } else { - issue = std::format("requires {} parameters, but {} were provided", NUM_PARAMS, object[validation::B].size()); + issue = mc_fmt::format("requires {} parameters, but {} were provided", NUM_PARAMS, object[validation::B].size()); } - std::string message = std::format( + std::string message = mc_fmt::format( "{} error: '{}' reaction parameter 'B' {}.", error_location, object[validation::type].as(), issue); errors.push_back({ ConfigParseStatus::InvalidParameterNumber, message }); @@ -102,7 +102,7 @@ namespace mechanism_configuration const auto& node = object[validation::gas_phase_species]; ErrorLocation error_location{ node.Mark().line, node.Mark().column }; - std::string message = std::format( + std::string message = mc_fmt::format( "{} error: '{}' reaction requires one gas phase, but {} were provided.", error_location, object[validation::type].as(), @@ -133,7 +133,7 @@ namespace mechanism_configuration const auto& node = object[validation::condensed_phase_species]; ErrorLocation error_location{ node.Mark().line, node.Mark().column }; - std::string message = std::format( + std::string message = mc_fmt::format( "{} error: '{}' reaction requires one condensed phase, but {} were provided.", error_location, object[validation::type].as(), diff --git a/src/development/reactions/validators/surface.cpp b/src/development/reactions/validators/surface.cpp index 1dcd5918..f00ea48b 100644 --- a/src/development/reactions/validators/surface.cpp +++ b/src/development/reactions/validators/surface.cpp @@ -10,7 +10,7 @@ #include #include -#include +#include namespace mechanism_configuration { @@ -81,7 +81,7 @@ namespace mechanism_configuration const auto& node = object[validation::gas_phase_species]; ErrorLocation error_location{ node.Mark().line, node.Mark().column }; - std::string message = std::format( + std::string message = mc_fmt::format( "{} error: '{}' reaction requires one reactant, but {} were provided.", error_location, object[validation::type].as(), diff --git a/src/development/reactions/validators/taylor_series.cpp b/src/development/reactions/validators/taylor_series.cpp index 1277b5c0..6db1318b 100644 --- a/src/development/reactions/validators/taylor_series.cpp +++ b/src/development/reactions/validators/taylor_series.cpp @@ -10,7 +10,7 @@ #include #include -#include +#include namespace mechanism_configuration { @@ -67,7 +67,7 @@ namespace mechanism_configuration const auto& node = object[validation::Ea]; ErrorLocation error_location{ node.Mark().line, node.Mark().column }; - std::string message = std::format( + std::string message = mc_fmt::format( "{} error: Mutually exclusive option of 'Ea' and 'C' found in '{}' reaction.", error_location, object[validation::type].as()); diff --git a/src/development/reactions/validators/user_defined.cpp b/src/development/reactions/validators/user_defined.cpp index c5811880..1eb297a8 100644 --- a/src/development/reactions/validators/user_defined.cpp +++ b/src/development/reactions/validators/user_defined.cpp @@ -10,7 +10,7 @@ #include #include -#include +#include namespace mechanism_configuration { diff --git a/src/development/reactions/validators/wet_deposition.cpp b/src/development/reactions/validators/wet_deposition.cpp index d1a20106..243ad918 100644 --- a/src/development/reactions/validators/wet_deposition.cpp +++ b/src/development/reactions/validators/wet_deposition.cpp @@ -10,7 +10,7 @@ #include #include -#include +#include namespace mechanism_configuration { diff --git a/src/development/type_parsers.cpp b/src/development/type_parsers.cpp index 679d9462..8da245df 100644 --- a/src/development/type_parsers.cpp +++ b/src/development/type_parsers.cpp @@ -46,7 +46,7 @@ namespace mechanism_configuration if (object[validation::is_third_body]) species.is_third_body = object[validation::is_third_body].as(); - species.unknown_properties = std::move(GetComments(object)); + species.unknown_properties = GetComments(object); all_species.push_back(species); } @@ -72,13 +72,13 @@ namespace mechanism_configuration { phase_species.diffusion_coefficient = spec[validation::diffusion_coefficient].as(); } - phase_species.unknown_properties = std::move(GetComments(spec)); + phase_species.unknown_properties = GetComments(spec); species.emplace_back(phase_species); } phase.species = species; - phase.unknown_properties = std::move(GetComments(object)); + phase.unknown_properties = GetComments(object); all_phases.emplace_back(phase); } diff --git a/src/development/type_validators.cpp b/src/development/type_validators.cpp index dcdc6756..966f1637 100644 --- a/src/development/type_validators.cpp +++ b/src/development/type_validators.cpp @@ -11,7 +11,7 @@ #include #include -#include +#include #include #include @@ -70,7 +70,7 @@ namespace mechanism_configuration const auto& object = duplicate.nodes[i]; ErrorLocation error_location{ object.Mark().line, object.Mark().column }; - std::string message = std::format( + std::string message = mc_fmt::format( "{} error: Duplicate species name '{}' found ({} of {}).", error_location, duplicate.name, i + 1, total); errors.push_back({ ConfigParseStatus::DuplicateSpeciesDetected, message }); @@ -145,7 +145,7 @@ namespace mechanism_configuration const auto& duplicate_obj = duplicate.nodes[i]; ErrorLocation error_location{ duplicate_obj.Mark().line, duplicate_obj.Mark().column }; - std::string message = std::format( + std::string message = mc_fmt::format( "{} error: Duplicate species name '{}' found ({} of {}).", error_location, duplicate.name, i + 1, total); errors.push_back({ ConfigParseStatus::DuplicateSpeciesInPhaseDetected, message }); @@ -162,7 +162,7 @@ namespace mechanism_configuration ErrorLocation error_location{ node.Mark().line, node.Mark().column }; std::string message = - std::format("{} error: Unknown species name '{}' found in '{}' phase.", error_location, name, phase.name); + mc_fmt::format("{} error: Unknown species name '{}' found in '{}' phase.", error_location, name, phase.name); errors.push_back({ ConfigParseStatus::PhaseRequiresUnknownSpecies, message }); } @@ -183,7 +183,7 @@ namespace mechanism_configuration const auto& duplicate_object = duplicate.nodes[i]; ErrorLocation error_location{ duplicate_object.Mark().line, duplicate_object.Mark().column }; - std::string message = std::format( + std::string message = mc_fmt::format( "{} error: Duplicate phase name '{}' found ({} of {})", error_location, duplicate.name, i + 1, total); errors.push_back({ ConfigParseStatus::DuplicatePhasesDetected, message }); @@ -262,7 +262,7 @@ namespace mechanism_configuration if (!object[validation::type]) { ErrorLocation error_location{ object.Mark().line, object.Mark().column }; - std::string message = std::format("{} error: Missing 'type' object in reaction.", error_location); + std::string message = mc_fmt::format("{} error: Missing 'type' object in reaction.", error_location); errors.push_back({ ConfigParseStatus::RequiredKeyNotFound, message }); is_valid = false; continue; @@ -276,7 +276,7 @@ namespace mechanism_configuration const auto& node = object[validation::type]; ErrorLocation error_location{ node.Mark().line, node.Mark().column }; - std::string message = std::format("{} error: Unknown reaction type '{}' found.", error_location, type); + std::string message = mc_fmt::format("{} error: Unknown reaction type '{}' found.", error_location, type); errors.push_back({ ConfigParseStatus::UnknownType, message }); is_valid = false; @@ -315,7 +315,7 @@ namespace mechanism_configuration if (!object[validation::type]) { ErrorLocation error_location{ object.Mark().line, object.Mark().column }; - std::string message = std::format("{} error: Missing 'type' object in model.", error_location); + std::string message = mc_fmt::format("{} error: Missing 'type' object in model.", error_location); errors.push_back({ ConfigParseStatus::RequiredKeyNotFound, message }); is_valid = false; continue; @@ -329,7 +329,7 @@ namespace mechanism_configuration const auto& node = object[validation::type]; ErrorLocation error_location{ node.Mark().line, node.Mark().column }; - std::string message = std::format("{} error: Unknown model type '{}' found.", error_location, type); + std::string message = mc_fmt::format("{} error: Unknown model type '{}' found.", error_location, type); errors.push_back({ ConfigParseStatus::UnknownType, message }); is_valid = false; diff --git a/src/development/utils.cpp b/src/development/utils.cpp index 5b8fd94e..0b2fdcbe 100644 --- a/src/development/utils.cpp +++ b/src/development/utils.cpp @@ -7,7 +7,7 @@ #include #include -#include +#include #include #include #include @@ -89,7 +89,7 @@ namespace mechanism_configuration { ErrorLocation error_location{ node.Mark().line, node.Mark().column }; - std::string message = std::format( + std::string message = mc_fmt::format( "{} error: Unknown species name '{}' found in '{}'.", error_location, name, @@ -123,7 +123,7 @@ namespace mechanism_configuration { ErrorLocation error_location{ object.Mark().line, object.Mark().column }; - std::string message = std::format( + std::string message = mc_fmt::format( "{} error: Invalid phase key '{}'. This phase was not found in the object of type '{}'.", error_location, phase_key, @@ -146,7 +146,7 @@ namespace mechanism_configuration ErrorLocation error_location{ phase_node.Mark().line, phase_node.Mark().column }; std::string message = - std::format("{} error: Unknown phase name '{}' found in '{}'.", error_location, phase_name, type); + mc_fmt::format("{} error: Unknown phase name '{}' found in '{}'.", error_location, phase_name, type); errors.push_back({ parser_status, message }); return std::nullopt; @@ -174,7 +174,7 @@ namespace mechanism_configuration { ErrorLocation error_location{ node.Mark().line, node.Mark().column }; - std::string message = std::format( + std::string message = mc_fmt::format( "{} error: {}-phase species '{}' is used in '{}' but is not defined in the '{}' phase.", error_location, phase.name, diff --git a/src/parser.cpp b/src/parser.cpp index 5115f29e..35822b04 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -14,7 +14,7 @@ #include #include -#include +#include #include #include @@ -28,7 +28,7 @@ namespace mechanism_configuration if (!std::filesystem::exists(config_path)) { info.errors.push_back( - { ConfigParseStatus::FileNotFound, std::format("Configuration file '{}' does not exist.", config_path.string()) }); + { ConfigParseStatus::FileNotFound, mc_fmt::format("Configuration file '{}' does not exist.", config_path.string()) }); return info; } @@ -40,14 +40,14 @@ namespace mechanism_configuration catch (const YAML::Exception& e) { info.errors.push_back( - { ConfigParseStatus::UnexpectedError, std::format("Failed to parse '{}': {}", config_path.string(), e.what()) }); + { ConfigParseStatus::UnexpectedError, mc_fmt::format("Failed to parse '{}': {}", config_path.string(), e.what()) }); return info; } if (!object[development::validation::version]) { info.errors.push_back({ ConfigParseStatus::MissingVersionField, - std::format("The version field was not found in '{}'.", config_path.string()) }); + mc_fmt::format("The version field was not found in '{}'.", config_path.string()) }); return info; } @@ -142,7 +142,7 @@ namespace mechanism_configuration } else { - std::string message = std::format( + std::string message = mc_fmt::format( "error: The supported versions are '{}', '{}' but the invalid version number '{}' was found: '{}'.", DEV_VERSION, V1_VERSION, diff --git a/src/v0/parser.cpp b/src/v0/parser.cpp index 5db83f7f..33e77c9c 100644 --- a/src/v0/parser.cpp +++ b/src/v0/parser.cpp @@ -43,7 +43,6 @@ namespace mechanism_configuration Errors ParseMechanism(const ParserMap& parsers, std::unique_ptr& mechanism, const YAML::Node& object) { - ConfigParseStatus status = ConfigParseStatus::Success; std::vector required = { validation::NAME, validation::REACTIONS, validation::TYPE }; Errors errors; @@ -120,8 +119,6 @@ namespace mechanism_configuration ParserResult Parser::Parse(const std::filesystem::path& config_path) { - ConfigParseStatus status; - ParserResult result; result.mechanism = std::make_unique(); diff --git a/src/v1/mechanism_parsers.cpp b/src/v1/mechanism_parsers.cpp index 3a2481b3..d04b22ee 100644 --- a/src/v1/mechanism_parsers.cpp +++ b/src/v1/mechanism_parsers.cpp @@ -94,7 +94,6 @@ namespace mechanism_configuration const std::vector existing_species) { Errors errors; - ConfigParseStatus status = ConfigParseStatus::Success; std::vector all_phases; std::vector> phase_node_pairs; diff --git a/src/validate_schema.cpp b/src/validate_schema.cpp index 9bb5b421..08cc4223 100644 --- a/src/validate_schema.cpp +++ b/src/validate_schema.cpp @@ -5,7 +5,7 @@ #include #include -#include +#include #include namespace mechanism_configuration @@ -20,7 +20,7 @@ namespace mechanism_configuration if (!object || object.IsNull()) { - std::string message = std::format("{} error: Object is null.", error_location); + std::string message = mc_fmt::format("{} error: Object is null.", error_location); errors.push_back({ ConfigParseStatus::EmptyObject, message }); return errors; @@ -51,7 +51,7 @@ namespace mechanism_configuration for (const auto& key : missing_keys) { - std::string message = std::format("{} error: Required key '{}' is missing.", error_location, key); + std::string message = mc_fmt::format("{} error: Required key '{}' is missing.", error_location, key); errors.push_back({ ConfigParseStatus::RequiredKeyNotFound, message }); } @@ -77,7 +77,7 @@ namespace mechanism_configuration { if (key.find("__") == std::string::npos) { - std::string message = std::format("{} error: Non-standard key '{}' found.", error_location, key); + std::string message = mc_fmt::format("{} error: Non-standard key '{}' found.", error_location, key); errors.push_back({ ConfigParseStatus::InvalidKey, message }); } } From f3203c482e4b8c7be3614a75330885a9f23e0451 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 15 May 2026 10:09:34 -0500 Subject: [PATCH 02/10] Auto-format code using Clang-Format (#264) Co-authored-by: GitHub Actions --- include/mechanism_configuration/error_location.hpp | 9 +++++---- src/development/mechanism.cpp | 3 +-- .../reactions/validators/aqueous_equilibrium.cpp | 3 +-- src/development/reactions/validators/arrhenius.cpp | 3 +-- src/development/reactions/validators/branched.cpp | 3 +-- .../reactions/validators/condensed_phase_arrhenius.cpp | 3 +-- .../validators/condensed_phase_photolysis.cpp | 3 +-- src/development/reactions/validators/emission.cpp | 3 +-- .../reactions/validators/first_order_loss.cpp | 3 +-- src/development/reactions/validators/henrys_law.cpp | 3 +-- .../reactions/validators/lambda_rate_constant.cpp | 3 +-- src/development/reactions/validators/photolysis.cpp | 3 +-- .../reactions/validators/simpol_phase_transfer.cpp | 3 +-- src/development/reactions/validators/surface.cpp | 3 +-- src/development/reactions/validators/taylor_series.cpp | 3 +-- src/development/reactions/validators/user_defined.cpp | 3 +-- .../reactions/validators/wet_deposition.cpp | 3 +-- src/development/type_validators.cpp | 2 +- src/development/utils.cpp | 2 +- src/parser.cpp | 10 +++++----- src/validate_schema.cpp | 2 +- 21 files changed, 29 insertions(+), 44 deletions(-) diff --git a/include/mechanism_configuration/error_location.hpp b/include/mechanism_configuration/error_location.hpp index cf04b53b..7d4edf48 100644 --- a/include/mechanism_configuration/error_location.hpp +++ b/include/mechanism_configuration/error_location.hpp @@ -5,6 +5,7 @@ #pragma once #include + #include namespace mechanism_configuration @@ -25,28 +26,28 @@ namespace mechanism_configuration } // namespace mechanism_configuration #ifdef MECH_CONFIG_USE_FMT -template <> +template<> struct fmt::formatter { constexpr auto parse(fmt::format_parse_context& ctx) const { return ctx.begin(); } - template + template auto format(const mechanism_configuration::ErrorLocation& loc, FormatContext& ctx) const { return fmt::format_to(ctx.out(), "{}:{}", loc.line, loc.column); } }; #else -template <> +template<> struct std::formatter { constexpr auto parse(std::format_parse_context& ctx) const { return ctx.begin(); } - template + template auto format(const mechanism_configuration::ErrorLocation& loc, FormatContext& ctx) const { return std::format_to(ctx.out(), "{}:{}", loc.line, loc.column); diff --git a/src/development/mechanism.cpp b/src/development/mechanism.cpp index fc7e2f42..4627bdac 100644 --- a/src/development/mechanism.cpp +++ b/src/development/mechanism.cpp @@ -8,12 +8,11 @@ #include #include #include +#include #include #include -#include - namespace mechanism_configuration { namespace development diff --git a/src/development/reactions/validators/aqueous_equilibrium.cpp b/src/development/reactions/validators/aqueous_equilibrium.cpp index b4169c91..ddb14d77 100644 --- a/src/development/reactions/validators/aqueous_equilibrium.cpp +++ b/src/development/reactions/validators/aqueous_equilibrium.cpp @@ -8,9 +8,8 @@ #include #include #include -#include - #include +#include namespace mechanism_configuration { diff --git a/src/development/reactions/validators/arrhenius.cpp b/src/development/reactions/validators/arrhenius.cpp index c49ebdc4..43ebbdba 100644 --- a/src/development/reactions/validators/arrhenius.cpp +++ b/src/development/reactions/validators/arrhenius.cpp @@ -9,9 +9,8 @@ #include #include #include -#include - #include +#include namespace mechanism_configuration { diff --git a/src/development/reactions/validators/branched.cpp b/src/development/reactions/validators/branched.cpp index ca2649ca..5c1783d2 100644 --- a/src/development/reactions/validators/branched.cpp +++ b/src/development/reactions/validators/branched.cpp @@ -8,9 +8,8 @@ #include #include #include -#include - #include +#include namespace mechanism_configuration { diff --git a/src/development/reactions/validators/condensed_phase_arrhenius.cpp b/src/development/reactions/validators/condensed_phase_arrhenius.cpp index 586ffaf9..c1f11e3d 100644 --- a/src/development/reactions/validators/condensed_phase_arrhenius.cpp +++ b/src/development/reactions/validators/condensed_phase_arrhenius.cpp @@ -9,9 +9,8 @@ #include #include #include -#include - #include +#include namespace mechanism_configuration { diff --git a/src/development/reactions/validators/condensed_phase_photolysis.cpp b/src/development/reactions/validators/condensed_phase_photolysis.cpp index c6db4d94..6469fb6f 100644 --- a/src/development/reactions/validators/condensed_phase_photolysis.cpp +++ b/src/development/reactions/validators/condensed_phase_photolysis.cpp @@ -8,9 +8,8 @@ #include #include #include -#include - #include +#include namespace mechanism_configuration { diff --git a/src/development/reactions/validators/emission.cpp b/src/development/reactions/validators/emission.cpp index 3fcf3b58..5bd8aa17 100644 --- a/src/development/reactions/validators/emission.cpp +++ b/src/development/reactions/validators/emission.cpp @@ -8,9 +8,8 @@ #include #include #include -#include - #include +#include namespace mechanism_configuration { diff --git a/src/development/reactions/validators/first_order_loss.cpp b/src/development/reactions/validators/first_order_loss.cpp index 3eccd499..5adf1b48 100644 --- a/src/development/reactions/validators/first_order_loss.cpp +++ b/src/development/reactions/validators/first_order_loss.cpp @@ -8,9 +8,8 @@ #include #include #include -#include - #include +#include namespace mechanism_configuration { diff --git a/src/development/reactions/validators/henrys_law.cpp b/src/development/reactions/validators/henrys_law.cpp index eacdcbc4..c9839d12 100644 --- a/src/development/reactions/validators/henrys_law.cpp +++ b/src/development/reactions/validators/henrys_law.cpp @@ -8,9 +8,8 @@ #include #include #include -#include - #include +#include namespace mechanism_configuration { diff --git a/src/development/reactions/validators/lambda_rate_constant.cpp b/src/development/reactions/validators/lambda_rate_constant.cpp index 90702769..ea8e82f6 100644 --- a/src/development/reactions/validators/lambda_rate_constant.cpp +++ b/src/development/reactions/validators/lambda_rate_constant.cpp @@ -8,9 +8,8 @@ #include #include #include -#include - #include +#include namespace mechanism_configuration { diff --git a/src/development/reactions/validators/photolysis.cpp b/src/development/reactions/validators/photolysis.cpp index 37c54e5a..df45bfd0 100644 --- a/src/development/reactions/validators/photolysis.cpp +++ b/src/development/reactions/validators/photolysis.cpp @@ -8,9 +8,8 @@ #include #include #include -#include - #include +#include namespace mechanism_configuration { diff --git a/src/development/reactions/validators/simpol_phase_transfer.cpp b/src/development/reactions/validators/simpol_phase_transfer.cpp index 13b37d34..f4d8cc65 100644 --- a/src/development/reactions/validators/simpol_phase_transfer.cpp +++ b/src/development/reactions/validators/simpol_phase_transfer.cpp @@ -8,9 +8,8 @@ #include #include #include -#include - #include +#include namespace mechanism_configuration { diff --git a/src/development/reactions/validators/surface.cpp b/src/development/reactions/validators/surface.cpp index f00ea48b..1342133d 100644 --- a/src/development/reactions/validators/surface.cpp +++ b/src/development/reactions/validators/surface.cpp @@ -8,9 +8,8 @@ #include #include #include -#include - #include +#include namespace mechanism_configuration { diff --git a/src/development/reactions/validators/taylor_series.cpp b/src/development/reactions/validators/taylor_series.cpp index 6db1318b..76f3c5ec 100644 --- a/src/development/reactions/validators/taylor_series.cpp +++ b/src/development/reactions/validators/taylor_series.cpp @@ -8,9 +8,8 @@ #include #include #include -#include - #include +#include namespace mechanism_configuration { diff --git a/src/development/reactions/validators/user_defined.cpp b/src/development/reactions/validators/user_defined.cpp index 1eb297a8..622c9238 100644 --- a/src/development/reactions/validators/user_defined.cpp +++ b/src/development/reactions/validators/user_defined.cpp @@ -8,9 +8,8 @@ #include #include #include -#include - #include +#include namespace mechanism_configuration { diff --git a/src/development/reactions/validators/wet_deposition.cpp b/src/development/reactions/validators/wet_deposition.cpp index 243ad918..fce3a603 100644 --- a/src/development/reactions/validators/wet_deposition.cpp +++ b/src/development/reactions/validators/wet_deposition.cpp @@ -8,9 +8,8 @@ #include #include #include -#include - #include +#include namespace mechanism_configuration { diff --git a/src/development/type_validators.cpp b/src/development/type_validators.cpp index 966f1637..47104142 100644 --- a/src/development/type_validators.cpp +++ b/src/development/type_validators.cpp @@ -9,9 +9,9 @@ #include #include #include +#include #include -#include #include #include diff --git a/src/development/utils.cpp b/src/development/utils.cpp index 0b2fdcbe..82d077b4 100644 --- a/src/development/utils.cpp +++ b/src/development/utils.cpp @@ -5,9 +5,9 @@ #include #include #include +#include #include -#include #include #include #include diff --git a/src/parser.cpp b/src/parser.cpp index 35822b04..e20f1bac 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -14,7 +15,6 @@ #include #include -#include #include #include @@ -27,8 +27,8 @@ namespace mechanism_configuration if (!std::filesystem::exists(config_path)) { - info.errors.push_back( - { ConfigParseStatus::FileNotFound, mc_fmt::format("Configuration file '{}' does not exist.", config_path.string()) }); + info.errors.push_back({ ConfigParseStatus::FileNotFound, + mc_fmt::format("Configuration file '{}' does not exist.", config_path.string()) }); return info; } @@ -39,8 +39,8 @@ namespace mechanism_configuration } catch (const YAML::Exception& e) { - info.errors.push_back( - { ConfigParseStatus::UnexpectedError, mc_fmt::format("Failed to parse '{}': {}", config_path.string(), e.what()) }); + info.errors.push_back({ ConfigParseStatus::UnexpectedError, + mc_fmt::format("Failed to parse '{}': {}", config_path.string(), e.what()) }); return info; } diff --git a/src/validate_schema.cpp b/src/validate_schema.cpp index 08cc4223..64f17cd1 100644 --- a/src/validate_schema.cpp +++ b/src/validate_schema.cpp @@ -3,9 +3,9 @@ // SPDX-License-Identifier: Apache-2.0 #include +#include #include -#include #include namespace mechanism_configuration From 0356ec366c3c202c3f8139e317a4241dac36a65b Mon Sep 17 00:00:00 2001 From: Kyle Shores Date: Tue, 19 May 2026 14:30:05 -0500 Subject: [PATCH 03/10] Fix fmt PIC without polluting global BUILD_SHARED_LIBS (#265) Setting BUILD_SHARED_LIBS globally with FORCE causes all subsequent FetchContent dependencies (e.g. TUV-x) to also build as shared, which breaks their builds if their objects lack -fPIC. Instead, set POSITION_INDEPENDENT_CODE on the fmt target directly after fetch so fmt's static library is PIC-safe when linked into a shared mechanism_configuration, without side effects on other dependencies. Co-authored-by: Claude Sonnet 4.6 --- cmake/dependencies.cmake | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/cmake/dependencies.cmake b/cmake/dependencies.cmake index 3fabc44f..5445ba5d 100644 --- a/cmake/dependencies.cmake +++ b/cmake/dependencies.cmake @@ -41,6 +41,10 @@ if(MECH_CONFIG_USE_FMT) ) FetchContent_MakeAvailable(fmt) + + if(fmt_POPULATED AND MECH_CONFIG_BUILD_SHARED_LIBS) + set_target_properties(fmt PROPERTIES POSITION_INDEPENDENT_CODE ON) + endif() endif() ################################################################################ @@ -58,4 +62,4 @@ FetchContent_Declare(yaml-cpp set(YAML_CPP_BUILD_TOOLS OFF CACHE BOOL "" FORCE) set(YAML_BUILD_SHARED_LIBS ${MECH_CONFIG_BUILD_SHARED_LIBS} CACHE BOOL "" FORCE) -FetchContent_MakeAvailable(yaml-cpp) \ No newline at end of file +FetchContent_MakeAvailable(yaml-cpp) From 10fc4d7c2dab8cc3bdccee9e425c34c65643c2f9 Mon Sep 17 00:00:00 2001 From: Kyle Shores Date: Wed, 17 Jun 2026 16:23:03 -0600 Subject: [PATCH 04/10] Restructure mechanism parser (`std::expected`, separation of public/private headers) and support in-code mechanisms (#276) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * refactoring v1 * v0 refactor * development * Accept `name` or `species name` for reaction components (v1 alias) Add an `exactly_one_of` group to ValidateSchema so a schema can require exactly one of a set of keys, then use it to let reaction components reference their species with either the canonical `name` or the legacy `species name` alias (used by v1 config files): exactly one, error if both or neither. - ValidateSchema: defaulted `exactly_one_of` param. None present -> RequiredKeyNotFound; more than one -> MutuallyExclusiveOption. Group members count as allowed keys (never flagged invalid). - validation.hpp: add `species_name = "species name"`. - ValidateReactantsOrProducts requires exactly one of {name, species name}. - New GetReactionComponentName() helper; route the component-name reads across all reaction validators and the parser through it. - Tests + fixtures: AcceptsSpeciesNameAlias, RejectsBothNameAndSpeciesName. Prep for consolidating development -> v1 (issue #269): keeps community v1 files (which use `species name`) parseable by the development engine. Also adds planning docs: PLAN-consolidate-v1.md, TODO-name-species_name-alias.md. Co-Authored-By: Claude Opus 4.8 (1M context) * Rename development engine to v1; delete the old combined v1 parser Consolidate onto a single v1 engine (issue #269). The two-phase Validate()/Parse() "development" engine becomes the canonical v1 implementation; the old combined v1 parser is removed. - Delete old src/v1 combined parser (parser.cpp, mechanism_parsers.cpp, utils.cpp, reactions/*_parser.cpp) and its headers (parser.hpp, mechanism_parsers.hpp, reaction_parsers.hpp, validation.hpp, utils.hpp). - git mv src/development/* -> src/v1/* and include/.../development/* -> include/.../v1/* (sources, headers, reactions/{parsers,validators} tree, CMakeLists), preserving history. - Sweep namespace development -> v1 and mechanism_configuration/development/ includes -> v1/. Old v1::validation (with its own species_name) is gone; the engine now resolves unqualified validation:: to the shared top-level namespace. - Drop add_subdirectory(development) from src/CMakeLists.txt; remove the emptied development dirs and a dead, unreferenced reaction_types.hpp stub. Library builds. Tests are not yet migrated (Stage 4): test/unit/v1 still calls the old API and test/unit/development references the gone namespace. Co-Authored-By: Claude Opus 4.8 (1M context) * Wire top-level parse() dispatch (file + string) Replace the throwing stub with a real version dispatch returning std::expected: - directory input or a missing version field -> v0 parser - major 0 -> v0, major 1 -> v1 engine (FileToYaml -> Validate -> Parse) - unsupported versions -> InvalidVersion Add parse(const std::string&) for in-memory v1+ documents. Remove the dead f() and commented-out dispatch; re-enable the v0 include; fix parse.hpp (drop the duplicated declaration, add the string overload). validate(const Mechanism&) (the in-code path, Option 2) and test migration are still pending. Co-Authored-By: Claude Opus 4.8 (1M context) * Stage 4: unify v1 tests on the engine; add file-list config support Engine / parse(): - Engine now accepts major version 1 (MAJOR_VERSION 1, not 2), since the renamed engine IS the v1 parser. - Add v1::Parser::ResolveFileConfig(): ports the multi-file "{ files: [...] }" logic from PR #256 to the unified engine. species/phases/reactions sections may be split across files (v1.1+); they are merged into one inline node, then validated/parsed normally. Inline sections pass through unchanged. Structural checks (missing 'files' key, non-array/object section, minor-version >= 1) and file-load errors are reported with the config path prefix. - parse() v1 case now goes ResolveFileConfig -> Validate -> Parse. - Drop the parse(const std::string&) content overload: it hijacked parse(std::string path). parse(filesystem::path) accepts strings implicitly. Tests: - development fixtures renumbered 2.0.0 -> 1.0.0; development test sources swept development:: -> v1::, includes development/ -> v1/. - v1 community tests migrated from v1::Parser::Parse(path) to top-level parse(). Status: file-list mechanism verified (its structural sub-tests pass). Remaining 14 failures are a single separate gap: community v1 lists phase species as bare strings ([A, B, C]) but the engine expects objects ([{name: A}]). Tracked next. Co-Authored-By: Claude Opus 4.8 (1M context) * Accept bare-string phase species in the v1 engine (restore v1 behavior) The old v1 phase parser accepted a phase's species as either bare strings (`species: [A, B]`) or objects (`species: [{name: A, ...}]`). The development engine only handled the object form and threw on scalars. Restore the dual handling in both ParsePhases (parse) and ValidatePhases (validate): a scalar is shorthand for the species name; a map carries name + optional properties. Valid v1 reaction/phase configs now parse. Remaining v1 test failures are a separate matter (stale error-count expectations + a few validator key-set gaps such as FIRST_ORDER_LOSS dropping `products`). Co-Authored-By: Claude Opus 4.8 (1M context) * Restore v1 leniency in the engine: optional/scalar components, FOL products, surface condensed_phase Reconcile the engine's per-reaction validators/parsers with v1 community files: - Reaction components may be bare strings (e.g. `gas-phase species: A`), not just objects. GetReactionComponentName handles scalars; ParseReactionComponents only reads coefficient/comments on the object form (scalar -> name only). - first_order_loss: restore `products` (optional key + parse it, guarded since optional). The type already had the field; old v1 allowed it. - surface: `condensed_phase` is optional, not required (community surface files omit it). Validator only verifies the phase when present; parser reads it when present. No more segfaults. Remaining v1 failures are stale test expectations (the engine reports richer errors than old v1), to be updated next per decision. Co-Authored-By: Claude Opus 4.8 (1M context) * Drop the 6 CAMP-only reactions from v1; delete development tests These reactions are supported by CAMP (v0) and aren't used by the ODE solver, so remove them from the v1 engine (re-addable later atop the canonical types): aqueous_equilibrium, condensed_phase_arrhenius, condensed_phase_photolysis, henrys_law, simpol_phase_transfer, wet_deposition. - Delete their parser + validator sources and CMake entries. - Remove their IReactionParser classes + registry entries from reaction_parsers.hpp. - Remove their type structs + Reactions members from types.hpp (species-level henrys_law_constant_* properties are unrelated and kept). - Delete all development tests (they had been swept onto the v1 engine during the rename and were the only coverage for these now-removed reactions). Unused validation:: keys for the dropped reactions are left in place (harmless). Co-Authored-By: Claude Opus 4.8 (1M context) * Update v1 test expectations to the engine's error reporting; fix file-list version-check ordering - v1 community tests: update error-count expectations to the engine's richer reporting (unknown species -> ReactionRequiresUnknownSpecies + RequestedSpeciesNotRegisteredInPhase; duplicates report one error per occurrence). Drop branched's stale third bad-component assertion. - ResolveFileConfig: check the file-list minor-version requirement BEFORE loading referenced files and return early, instead of also emitting file-not-found errors for a config already known to be invalid (matches old v1). Suite now 25/26. The lone remaining failure (file_configs TwoPhasesSets) is a semantic-policy question: a gas-phase reaction produces a species defined only in the aqueous phase, which the engine's phase-membership check rejects. Co-Authored-By: Claude Opus 4.8 (1M context) * Exempt reaction products from the phase-membership check A reaction's products may legitimately reference species defined in another phase (e.g. a gas-phase reaction producing an aqueous species), so only reactants are required to belong to the reaction's phase. Reactants stay phase-checked; products are still required to be known species (unknown-species check unchanged). - All reaction validators build a reactants-only list for CheckSpeciesPresenceInPhase; products go only into the unknown-species check. emission (products only) drops the phase check entirely; first_order_loss already checked reactants only. - Realign v1 test error-count expectations accordingly. Full suite green: 26/26. Co-Authored-By: Claude Opus 4.8 (1M context) * Add version-agnostic validate(const Mechanism&) Semantic validation belongs to the canonical Mechanism, not to a specific parser version. Add a top-level validate(const Mechanism&) -> Errors that checks the mechanism's semantic invariants on the struct, independent of how it was produced (parsed from any version, or built in code): - unique species names; unique phase names; unique species within a phase - phase species exist in the species list - reaction species exist; reactants are registered in the reaction's phase (products may reference any phase) This is the in-code validation path from issue #269's "ideas" (in-code mechanism -> validate). New unit tests cover an in-code mechanism directly. Note: additive. parse() still uses v1's YAML-level (line-numbered) validation; routing parse() through validate(Mechanism) and removing v1's duplicated semantic checks is a follow-up. Co-Authored-By: Claude Opus 4.8 (1M context) * Refactor validate() onto a single semantics checker over a located intermediate Introduce semantics::Input (species/phases/reactions as name + optional ErrorLocation) and ValidateSemantics(Input) as the single place the semantic rules live. validate(const Mechanism&) now builds a location-free Input and calls it. Errors carry line:col whenever a source location is supplied — which lets the parse path reuse the same checker with locations next, instead of duplicating the rules in v1. Co-Authored-By: Claude Opus 4.8 (1M context) * Add v1 BuildSemanticInput (YAML -> located semantics::Input) Extracts species/phase/reaction species references from a fully-resolved v1 YAML node, each carrying its source ErrorLocation, into the version-neutral semantics::Input. This lets the parse path feed the single ValidateSemantics checker with line:col (the YAML counterpart to validate(Mechanism)'s location-free build). Not yet wired into Parser::Validate — that wiring + removing v1's own semantic checks is the next step. Co-Authored-By: Claude Opus 4.8 (1M context) * Route parse() semantic validation through ValidateSemantics; strip v1's copy v1's parsers now own only deserialization + structural (schema/cardinality/ mutually-exclusive) validation. All semantic checks (unknown species, phase membership, duplicates, unknown phase) are performed once by the version-neutral ValidateSemantics: - Parser::Validate runs the structural validators, then calls ValidateSemantics(BuildSemanticInput(object)) so parse-time semantic errors keep line:col. - The 12 reaction validators drop their species/phase/duplicate checks (keeping ValidateSchema, ValidateReactantsOrProducts, cardinality, Ea-vs-C). - ValidateSpecies / ValidatePhases reduced to structural schema checks. Semantic rules now exist in exactly one place and apply to the canonical Mechanism (parsed or in-code). The old per-component semantic helpers in v1/utils are now unused (left in place; can be removed in a follow-up). Suite: 27/27. Co-Authored-By: Claude Opus 4.8 (1M context) * Modernize integration tests to the parse()/validate() API Rewrite the integration tests onto the current public API: - test_parser: use top-level parse() for version dispatch (v0 fallback, v1, missing file, unsupported version, v0 directory). Drop the v2/development case. - test_v0_parser: v0::Parser::Parse still returns expected; update to the canonical Mechanism + .error(). - test_v1_parser: files via parse(); in-memory YAML/JSON via the v1 engine (Validate + Parse(node)), since v1::Parser no longer has Parse(path)/ ParseFromString/ParseFromNode. - test_v1_read_from_file_configs: multi-file configs via parse(). - Drop the stale development_parser CMake entry (source no longer exists). Known: examples/v1/full_configuration.{json,yaml} is semantically invalid under the engine's checks (undeclared foo/bar/baz; third-body M used outside the gas phase), so the two full-configuration tests fail pending an example-data decision. Co-Authored-By: Claude Opus 4.8 (1M context) * Fix examples/v1/full_configuration to be semantically valid The full-configuration example tripped the engine's semantic checks: - third-body species M was used as a TROE reactant but absent from the gas phase -> add M to the gas phase species list - the TERNARY_CHEMICAL_ACTIVATION reaction referenced undeclared species foo/bar/baz -> use declared species (A/B/C) Species count is unchanged (M was already declared), so the integration test assertions are unaffected. Full suite green: 31/31. Co-Authored-By: Claude Opus 4.8 (1M context) * Remove dead semantic helpers from v1/utils After semantic validation moved to the version-neutral ValidateSemantics, these v1/utils helpers had no remaining callers: FindUnknownObjectsByName, CheckSpeciesPresenceInPhase, CheckPhaseExists, ReportUnknownSpecies, FindDuplicateObjectsByName, GetSpeciesNames, and the NodeInfo/DuplicateEntryInfo structs. Remove them. v1/utils now holds only the parser-support helpers still in use: AsSequence, AppendFilePath, GetComments, GetReactionComponentName. Full suite green: 31/31. Co-Authored-By: Claude Opus 4.8 (1M context) * Tidy v1 type_validators: structural-only docs, drop dead ValidateParticles - Rewrite the docstrings to reflect that these are structural (schema) checks only; semantic invariants moved to ValidateSemantics. - Remove ValidateParticles (header + definition): its only callers were the Henry's-law/SIMPOL validators, which were dropped with the CAMP-only reactions. Suite green: 31/31. Co-Authored-By: Claude Opus 4.8 (1M context) * Rename validation.hpp -> validation_keys.hpp The header holds the schema key-name constants (the `validation::` namespace), not validation logic. Renaming disambiguates the three similarly-named headers: - validation_keys.hpp : the key strings - validate_schema.hpp : structural/schema checking - validate.hpp : semantic validation (ValidateSemantics / validate) The `validation` namespace name is unchanged; only the file + its include sites (7) are updated. v0/validation.hpp is unrelated and untouched. Suite green: 31/31. Co-Authored-By: Claude Opus 4.8 (1M context) * docs: add README usage example (parse a file or validate an in-code mechanism) A single, compile-checked example showing the two entry points around the canonical Mechanism: parse() a YAML/JSON file (version auto-dispatched, returning std::expected), and build a Mechanism in code then validate() it with the same semantic checks the parser uses. Co-Authored-By: Claude Opus 4.8 (1M context) * private headers * Flatten v1 detail headers to nested namespace; fix ::v typo Collapse the v1 private headers to the joined `mechanism_configuration::v1` namespace form and normalize include ordering. Fixes a typo in type_validators.hpp (`::v`) that broke compilation. Co-Authored-By: Claude Opus 4.8 (1M context) * docs: document lambda_rate_constant, add it to examples; drop planning notes - Add docs/source/v1/reactions/lambda_rate_constant.rst and wire it into the v1 reactions index/toctree (it was the only v1 engine reaction undocumented). - Add a LAMBDA_RATE_CONSTANT reaction to examples/v1/full_configuration.{yaml,json} so the example exercises every v1 reaction type (both parse cleanly). - Remove the scratch planning docs PLAN-consolidate-v1.md and TODO-name-species_name-alias.md from the repo root. Co-Authored-By: Claude Opus 4.8 (1M context) * Release 2.0.0: bump version and add docs changelog Bump project version 1.1.2 -> 2.0.0 to reflect the breaking C++ API changes on this branch (std::expected parse()/validate(), canonical Mechanism, the public/private header split with a single umbrella header, and removed v1 reactions). The v0/v1 config file formats are unchanged. Add docs/source/changelog.rst (modeled on music-box's changelog) covering the API changes, header reorganization, removed reactions, and a migration example, and wire it into the docs toctree. Update the docs |project_version|. Co-Authored-By: Claude Opus 4.8 (1M context) * ci: fix Ubuntu workflow matrix exclude indentation `exclude` was nested under `strategy` instead of `strategy.matrix`, which is an invalid workflow definition — GitHub Actions rejected it at startup, so the Ubuntu job failed in 0s on every push. Re-indent `exclude` under `matrix`. Co-Authored-By: Claude Opus 4.8 (1M context) * Fix Linux clang and MSVC CI builds Two separate stdlib/include issues that GCC papered over via transitive includes but Linux clang and MSVC did not: - MSVC: errors.hpp defines PrintTo(..., std::ostream*) and streams a string into it, but never included , leaving std::basic_ostream an incomplete type (C2027 in 's operator<<). Add . - Linux clang: clang-18 paired with libstdc++ (gcc-13/14) does not expose std::expected at any -std flag (reproduced in ubuntu:24.04). Build the Ubuntu clang job against libc++ (-stdlib=libc++ + libc++-dev), which provides std::expected and std::format. Verified: full repo builds clean with clang-18 + libc++ for both fmt OFF and ON under -Werror, 31/31 tests. Co-Authored-By: Claude Opus 4.8 (1M context) * Rename structural checks Validate -> CheckSchema; reserve validate() for semantics The word "validate" was overloaded: the public semantic validate(const Mechanism&) / ValidateSemantics shared the name with the v1 structural YAML checks, making it hard to see what the real validation is. Reserve "validate" for semantics and name the structural layer "CheckSchema": - Parser::Validate -> Parser::CheckSchema - IReactionParser::Validate -> CheckSchema (+ all 12 reaction overrides) - ValidateSpecies/Phases/Reactions/ReactantsOrProducts -> CheckSpeciesSchema/CheckPhasesSchema/ CheckReactionsSchema/CheckReactantsOrProductsSchema - ValidateSchema primitive -> CheckSchema - detail/validate_schema.{hpp,cpp} -> detail/check_schema.{hpp,cpp} (+ src/check_schema.cpp) In-member primitive calls are qualified (mechanism_configuration::CheckSchema) to avoid the member name hiding the free function. Fix the stale validator docstrings that claimed to "ensure all referenced species and phases exist" (that moved to ValidateSemantics) and mark the now-unused existing_species/existing_phases params. validate()/ValidateSemantics and the validators/ + type_validators.* names are unchanged. Build clean (gcc-14 -Werror), 31/31 tests pass. Co-Authored-By: Claude Opus 4.8 (1M context) * Tidy v1 schema checkers: drop dead is_valid, rename validation_errors The reaction validators carried an is_valid flag that was either never read (arrhenius) or only gated a trailing `return errors;` that the function reached anyway. Where it did guard a later check (first_order_loss/surface/photolysis cardinality, and CheckReactionsSchema's per-reaction loop), it was equivalent to `!errors.empty()` at that point, so the flag is replaced by that check. Also rename the reused local `validation_errors` -> `schema_errors`, matching the CheckSchema naming and avoiding the "validation" overload (reserved for the semantic validate()/ValidateSemantics). No behavior change. Build clean, 31/31 tests pass. Co-Authored-By: Claude Opus 4.8 (1M context) * Rename type_validators -> type_schema, reactions/validators/ -> reactions/schema/ These hold structural schema checks (CheckSpeciesSchema, XxxParser::CheckSchema, etc.), not semantic validation, so "validators" was misleading. Rename to match the CheckSchema naming and pair cleanly with the sibling reactions/parsers/. Co-Authored-By: Claude Opus 4.8 (1M context) * Flatten reactions/{parsers,schema}/ into one file per reaction Each reaction was one IReactionParser subclass (e.g. ArrheniusParser) whose two methods, CheckSchema and Parse, were split across reactions/schema/X.cpp and reactions/parsers/X.cpp with near-identical include blocks. Splitting one class across two files/dirs cost cohesion for no real benefit. Merge each pair into a single src/v1/reactions/X.cpp holding the whole parser (CheckSchema then Parse), drop the parsers/ and schema/ subdirectories, and list the 12 sources directly in reactions/CMakeLists.txt. (taylor_series needed , previously only pulled in on the parser side.) No behavior change. Build clean (gcc-14 -Werror), 31/31 tests pass. Co-Authored-By: Claude Opus 4.8 (1M context) * v1::Parser::Parse owns validation; return std::expected, hide CheckSchema Parse(node) now runs CheckSchema (structure + semantics) itself and returns std::expected, so callers can't build from an unvalidated node or forget to validate. CheckSchema and the construction step (Build) are now private. The top-level parse() v1 branch collapses to ResolveFileConfig -> Parse, and the string-parsing test helper to a single Parse call. No behavior change. Build clean (gcc-14 -Werror), 31/31 tests pass. Co-Authored-By: Claude Opus 4.8 (1M context) * v1::Parser::Parse: add path/string/node overloads; mirror v0 in parse() Parsing a v1 file no longer requires calling ResolveFileConfig by hand. Parse is now overloaded: - Parse(filesystem::path) -> resolve file-list sections, validate, build - Parse(std::string) -> treat as a YAML/JSON document, validate, build - Parse(YAML::Node, bool) -> validate + build a loaded node ResolveFileConfig, CheckSchema, Build, and the config-path setters are now private; the dead FileToYaml is removed. The top-level parse() v1 branch collapses to `return v1::Parser{}.Parse(config_path);`, matching v0. Exception safety moved into Parse(node) (the shared path), so value-conversion throws surface as Errors rather than escaping. No behavior change. Build clean (gcc-14 -Werror), 31/31 tests pass. Co-Authored-By: Claude Opus 4.8 (1M context) * docs: use a static Apache-2.0 license badge; fix LICENSE link to main The github/license shields.io badge is dynamic (hits the GitHub API) and intermittently fails with "Unable to select next GitHub token from pool", rendering broken. Switch to a static Apache-2.0 badge that never calls the API, and point the link at blob/main/LICENSE (the default branch) instead of master. Co-Authored-By: Claude Opus 4.8 (1M context) * Drop read_from_config_file flag from v1::Parser The boolean only told CheckSchema whether to reset config_path_ (the file-path prefix for error messages) — a flag argument that callers had to reason about. Each Parse overload already knows its context, so it now sets config_path_ itself (ResolveFileConfig for files; empty for string/node) and delegates to a private flag-free ValidateAndBuild(node) that runs CheckSchema + Build. CheckSchema and Parse(node) lose the bool. No behavior change. Build clean, 31/31 tests pass. Co-Authored-By: Claude Opus 4.8 (1M context) * test: fix stale version_mismatch comment The comment claimed version "1.3.0" / "minor != 1", but the config is "1.0.0" and the gate is `minor < 1` (file-list requires v1.1+). Correct the comment to match the config and logic. Co-Authored-By: Claude Opus 4.8 (1M context) * Hoist semantic validation out of CheckSchema into ValidateAndBuild CheckSchema also ran ValidateSemantics, so its name undersold what it did and re-overloaded "validate" in the structural layer. Move the semantic pass up into ValidateAndBuild, which now reads as an explicit three-phase pipeline: structural (CheckSchema) -> semantic (ValidateSemantics, gated on clean structure) -> Build. CheckSchema is now schema-only, matching its name. No behavior change. Build clean, 31/31 tests pass. Co-Authored-By: Claude Opus 4.8 (1M context) * Rename validation key-vocabulary to keys The validation:: namespaces were just dictionaries of YAML key-name strings, used by parsing and construction as much as by checking (e.g. Build reads object[validation::gas_phase]) — so "validation" misdescribed them. Rename mechanism_configuration::validation -> keys and v0::validation -> v0::keys (validation_keys.hpp -> keys.hpp, v0/validation.hpp -> v0/keys.hpp), and validation:: -> keys:: throughout (~600 refs). "validation" is now reserved for actual semantic validation. No behavior change. Build clean (gcc-14 -Werror), 31/31 tests pass. Co-Authored-By: Claude Opus 4.8 (1M context) * Move the v1 key vocabulary under v1 (keys -> v1::keys) detail/keys.hpp held the v1 keys but lived at the detail root, asymmetric with v0's detail/v0/keys.hpp. Its only cross-version use was parse()'s version dispatch reading the "version" field. Move it to detail/v1/keys.hpp as mechanism_configuration::v1::keys (v1 call sites are inside namespace v1, so keys:: still resolves with no change), and have the version-agnostic dispatcher in parse() read the literal "version" instead of depending on a version's keys. Now each version owns its key vocabulary: v0::keys and v1::keys. No behavior change. Build clean (gcc-14 -Werror), 31/31 tests pass. Co-Authored-By: Claude Opus 4.8 (1M context) * Prefix the unsupported-version error with the config file path The "Unsupported version number" error was the one parse() error without a file path. We only reach that branch after reading the version out of the file, so it always names a real document — prefix it (path: message) like the other errors, so it points at the offending file. Co-Authored-By: Claude Opus 4.8 (1M context) * Include line:col in the unsupported-version error GetVersion now also returns the source location of the `version` field (absent for directories / version-less docs). parse()'s default branch uses it to format the error as path:line:col error: ... , matching the located v1 errors, instead of just the file path. Co-Authored-By: Claude Opus 4.8 (1M context) * adding readme example parsing * update to camelcase * remove old aqueous and henrys law configs * update the copyright header * rearrage the types * replace phase location with location --------- Co-authored-by: Claude Opus 4.8 (1M context) Co-authored-by: Jiwon Gim --- .github/workflows/ubuntu.yml | 18 +- CMakeLists.txt | 2 +- README.md | 69 ++- cmake/test_util.cmake | 4 + docs/source/changelog.rst | 102 +++ docs/source/index.rst | 3 +- docs/source/v1/reactions/index.rst | 2 + .../v1/reactions/lambda_rate_constant.rst | 76 +++ examples/development/full_configuration.json | 586 ------------------ examples/development/full_configuration.yaml | 358 ----------- examples/v1/full_configuration.json | 27 +- examples/v1/full_configuration.yaml | 19 +- .../development/mechanism.hpp | 76 --- .../development/model_parsers.hpp | 72 --- .../development/model_types.hpp | 57 -- .../development/reaction_parsers.hpp | 273 -------- .../development/reaction_types.hpp | 402 ------------ .../development/type_parsers.hpp | 63 -- .../development/type_validators.hpp | 66 -- .../development/types.hpp | 78 --- .../development/utils.hpp | 155 ----- .../development/validation.hpp | 218 ------- .../error_location.hpp | 56 -- include/mechanism_configuration/errors.hpp | 87 ++- include/mechanism_configuration/mechanism.hpp | 29 +- .../mechanism_configuration.hpp | 13 + include/mechanism_configuration/parse.hpp | 20 + .../mechanism_configuration/parse_status.hpp | 49 -- include/mechanism_configuration/parser.hpp | 36 -- .../mechanism_configuration/parser_result.hpp | 39 -- include/mechanism_configuration/types.hpp | 329 ++++++++++ include/mechanism_configuration/v0/parser.hpp | 33 - .../v0/parser_types.hpp | 38 -- include/mechanism_configuration/v0/types.hpp | 208 ------- .../mechanism_configuration/v0/validation.hpp | 67 -- .../mechanism_configuration/v1/mechanism.hpp | 36 -- .../v1/mechanism_parsers.hpp | 38 -- include/mechanism_configuration/v1/parser.hpp | 46 -- .../v1/reaction_parsers.hpp | 239 ------- .../v1/reaction_types.hpp | 291 --------- include/mechanism_configuration/v1/types.hpp | 58 -- include/mechanism_configuration/v1/utils.hpp | 103 --- .../mechanism_configuration/v1/validation.hpp | 140 ----- include/mechanism_configuration/validate.hpp | 63 ++ .../validate_schema.hpp | 21 - include/mechanism_configuration/version.hpp | 12 +- src/CMakeLists.txt | 12 +- src/{validate_schema.cpp => check_schema.cpp} | 59 +- src/detail/check_schema.hpp | 30 + .../detail}/constants.hpp | 0 .../detail}/conversions.hpp | 2 +- src/detail/v0/keys.hpp | 61 ++ src/detail/v0/parser.hpp | 31 + src/detail/v0/parser_types.hpp | 34 + src/detail/v1/keys.hpp | 179 ++++++ src/detail/v1/parser.hpp | 73 +++ src/detail/v1/reaction_parsers.hpp | 195 ++++++ src/detail/v1/type_parsers.hpp | 51 ++ src/detail/v1/type_schema.hpp | 46 ++ src/detail/v1/utils.hpp | 36 ++ src/development/CMakeLists.txt | 10 - src/development/mechanism.cpp | 140 ----- src/development/models/CMakeLists.txt | 2 - src/development/models/parsers/CMakeLists.txt | 5 - src/development/models/parsers/gas.cpp | 32 - src/development/models/parsers/modal.cpp | 42 -- .../models/validators/CMakeLists.txt | 5 - src/development/models/validators/gas.cpp | 36 -- src/development/models/validators/modal.cpp | 74 --- src/development/reactions/CMakeLists.txt | 2 - .../reactions/parsers/CMakeLists.txt | 21 - .../reactions/parsers/aqueous_equilibrium.cpp | 42 -- .../reactions/parsers/arrhenius.cpp | 63 -- .../reactions/parsers/branched.cpp | 49 -- .../parsers/condensed_phase_arrhenius.cpp | 57 -- .../parsers/condensed_phase_photolysis.cpp | 36 -- .../reactions/parsers/emission.cpp | 35 -- .../reactions/parsers/first_order_loss.cpp | 35 -- .../reactions/parsers/henrys_law.cpp | 49 -- .../parsers/lambda_rate_constant.cpp | 34 - .../reactions/parsers/photolysis.cpp | 36 -- .../parsers/simpol_phase_transfer.cpp | 38 -- src/development/reactions/parsers/surface.cpp | 37 -- .../reactions/parsers/taylor_series.cpp | 66 -- .../parsers/ternary_chemical_activation.cpp | 64 -- src/development/reactions/parsers/troe.cpp | 64 -- .../reactions/parsers/tunneling.cpp | 44 -- .../reactions/parsers/user_defined.cpp | 38 -- .../reactions/parsers/wet_deposition.cpp | 35 -- .../reactions/validators/CMakeLists.txt | 21 - .../validators/aqueous_equilibrium.cpp | 105 ---- .../reactions/validators/arrhenius.cpp | 117 ---- .../reactions/validators/branched.cpp | 120 ---- .../validators/condensed_phase_arrhenius.cpp | 117 ---- .../validators/condensed_phase_photolysis.cpp | 119 ---- .../reactions/validators/emission.cpp | 86 --- .../reactions/validators/first_order_loss.cpp | 100 --- .../reactions/validators/henrys_law.cpp | 151 ----- .../validators/lambda_rate_constant.cpp | 101 --- .../reactions/validators/photolysis.cpp | 119 ---- .../validators/simpol_phase_transfer.cpp | 174 ------ .../reactions/validators/surface.cpp | 125 ---- .../reactions/validators/taylor_series.cpp | 118 ---- .../ternary_chemical_activation.cpp | 102 --- src/development/reactions/validators/troe.cpp | 102 --- .../reactions/validators/tunneling.cpp | 101 --- .../reactions/validators/user_defined.cpp | 102 --- .../reactions/validators/wet_deposition.cpp | 52 -- src/development/type_parsers.cpp | 155 ----- src/development/type_validators.cpp | 358 ----------- src/development/utils.cpp | 191 ------ src/errors.cpp | 40 ++ src/parse.cpp | 93 +++ src/parse_status.cpp | 42 -- src/parser.cpp | 157 ----- src/v0/arrhenius_parser.cpp | 139 ++--- src/v0/branched_parser.cpp | 107 ++-- src/v0/emission_parser.cpp | 65 +- src/v0/first_order_loss_parser.cpp | 65 +- src/v0/parser.cpp | 240 +++---- src/v0/photolysis_parser.cpp | 79 +-- src/v0/species_parser.cpp | 175 +++--- src/v0/surface_parser.cpp | 79 +-- src/v0/ternary_chemical_activation_parser.cpp | 147 ++--- src/v0/troe_parser.cpp | 147 ++--- src/v0/tunneling_parser.cpp | 101 +-- src/v0/user_defined_reaction_parser.cpp | 71 +-- src/v1/CMakeLists.txt | 3 +- src/v1/mechanism_parsers.cpp | 312 ---------- src/v1/parser.cpp | 471 ++++++++------ src/v1/reactions/CMakeLists.txt | 24 +- src/v1/reactions/arrhenius.cpp | 124 ++++ src/v1/reactions/arrhenius_parser.cpp | 139 ----- src/v1/reactions/branched.cpp | 109 ++++ src/v1/reactions/branched_parser.cpp | 122 ---- src/v1/reactions/emission.cpp | 75 +++ src/v1/reactions/emission_parser.cpp | 102 --- src/v1/reactions/first_order_loss.cpp | 105 ++++ src/v1/reactions/first_order_loss_parser.cpp | 117 ---- src/v1/reactions/lambda_parser.cpp | 111 ---- src/v1/reactions/lambda_rate_constant.cpp | 81 +++ src/v1/reactions/photolysis.cpp | 114 ++++ src/v1/reactions/photolysis_parser.cpp | 118 ---- src/v1/reactions/surface.cpp | 120 ++++ src/v1/reactions/surface_parser.cpp | 111 ---- src/v1/reactions/taylor_series.cpp | 130 ++++ src/v1/reactions/taylor_series_parser.cpp | 149 ----- .../reactions/ternary_chemical_activation.cpp | 113 ++++ .../ternary_chemical_activation_parser.cpp | 102 --- src/v1/reactions/troe.cpp | 113 ++++ src/v1/reactions/troe_parser.cpp | 141 ----- src/v1/reactions/tunneling.cpp | 92 +++ src/v1/reactions/tunneling_parser.cpp | 119 ---- src/v1/reactions/user_defined.cpp | 86 +++ src/v1/reactions/user_defined_parser.cpp | 111 ---- src/v1/type_parsers.cpp | 151 +++++ src/v1/type_schema.cpp | 156 +++++ src/v1/utils.cpp | 54 +- src/validate.cpp | 181 ++++++ src/version.hpp.in | 4 + test/integration/CMakeLists.txt | 30 +- test/integration/test_development_parser.cpp | 100 --- test/integration/test_parser.cpp | 131 ++-- test/integration/test_v0_parser.cpp | 48 +- test/integration/test_v1_parser.cpp | 249 +++----- .../test_v1_read_from_file_configs.cpp | 35 +- test/unit/CMakeLists.txt | 3 +- test/unit/development/CMakeLists.txt | 16 - .../gas/gas_phase_not_found_in_phases.json | 89 --- .../gas/gas_phase_not_found_in_phases.yaml | 47 -- .../models/gas/missing_phase.json | 88 --- .../models/gas/missing_phase.yaml | 46 -- .../models/gas/valid.json | 89 --- .../models/gas/valid.yaml | 48 -- .../models/modal/missing_modal_variable.json | 184 ------ .../models/modal/missing_modal_variable.yaml | 116 ---- .../models/modal/missing_modes.json | 88 --- .../models/modal/missing_modes.yaml | 46 -- .../modal/mode_phase_not_found_in_phases.json | 103 --- .../modal/mode_phase_not_found_in_phases.yaml | 57 -- .../models/modal/valid.json | 200 ------ .../models/modal/valid.yaml | 122 ---- .../phases/duplicate_phases.json | 48 -- .../phases/duplicate_phases.yaml | 24 - .../phases/duplicate_species_in_phase.json | 32 - .../phases/duplicate_species_in_phase.yaml | 16 - .../phases/invalid_key.json | 30 - .../phases/invalid_key.yaml | 16 - .../phases/invalid_species_object.json | 23 - .../phases/invalid_species_object.yaml | 11 - .../phases/missing_required_key.json | 11 - .../phases/missing_required_key.yaml | 6 - .../phases/phase_species_properties.json | 36 -- .../phases/phase_species_properties.yaml | 18 - .../phases/unknown_species.json | 30 - .../phases/unknown_species.yaml | 16 - .../phases/valid_phases.json | 42 -- .../phases/valid_phases.yaml | 24 - .../bad_reaction_component.json | 61 -- .../bad_reaction_component.yaml | 27 - .../aqueous_equilibrium/missing_phase.json | 43 -- .../aqueous_equilibrium/missing_phase.yaml | 21 - .../aqueous_equilibrium/unknown_species.json | 49 -- .../aqueous_equilibrium/unknown_species.yaml | 23 - .../reactions/aqueous_equilibrium/valid.json | 87 --- .../reactions/aqueous_equilibrium/valid.yaml | 43 -- .../arrhenius/bad_reaction_component.json | 41 -- .../arrhenius/bad_reaction_component.yaml | 17 - .../reactions/arrhenius/missing_phase.json | 32 - .../reactions/arrhenius/missing_phase.yaml | 14 - .../arrhenius/mutually_exclusive.json | 43 -- .../arrhenius/mutually_exclusive.yaml | 19 - .../reactions/arrhenius/unknown_species.json | 42 -- .../reactions/arrhenius/unknown_species.yaml | 18 - .../reactions/arrhenius/valid.json | 101 --- .../reactions/arrhenius/valid.yaml | 53 -- .../branched/bad_reaction_component.json | 65 -- .../branched/bad_reaction_component.yaml | 32 - .../reactions/branched/missing_phase.json | 50 -- .../reactions/branched/missing_phase.yaml | 27 - .../reactions/branched/unknown_species.json | 59 -- .../reactions/branched/unknown_species.yaml | 30 - .../reactions/branched/valid.json | 65 -- .../reactions/branched/valid.yaml | 32 - .../bad_reaction_component.json | 47 -- .../bad_reaction_component.yaml | 19 - .../missing_phase.json | 35 -- .../missing_phase.yaml | 15 - .../mutually_exclusive.json | 49 -- .../mutually_exclusive.yaml | 21 - .../species_not_in_aqueous_phase.json | 104 ---- .../species_not_in_aqueous_phase.yaml | 54 -- .../unknown_species.json | 47 -- .../unknown_species.yaml | 19 - .../condensed_phase_arrhenius/valid.json | 107 ---- .../condensed_phase_arrhenius/valid.yaml | 55 -- .../bad_reaction_component.json | 55 -- .../bad_reaction_component.yaml | 23 - .../missing_phase.json | 37 -- .../missing_phase.yaml | 17 - .../more_than_one_reactant.json | 57 -- .../more_than_one_reactant.yaml | 23 - .../species_not_in_aqueous_phase.json | 56 -- .../species_not_in_aqueous_phase.yaml | 24 - .../unknown_species.json | 43 -- .../unknown_species.yaml | 19 - .../condensed_phase_photolysis/valid.json | 74 --- .../condensed_phase_photolysis/valid.yaml | 34 - .../emission/bad_reaction_component.json | 36 -- .../emission/bad_reaction_component.yaml | 15 - .../reactions/emission/missing_phase.json | 27 - .../reactions/emission/missing_phase.yaml | 12 - .../reactions/emission/unknown_species.json | 36 -- .../reactions/emission/unknown_species.yaml | 15 - .../reactions/emission/valid.json | 69 --- .../reactions/emission/valid.yaml | 30 - .../bad_reaction_component.json | 36 -- .../bad_reaction_component.yaml | 15 - .../first_order_loss/missing_phase.json | 27 - .../first_order_loss/missing_phase.yaml | 12 - .../first_order_loss/too_many_reactants.json | 47 -- .../first_order_loss/too_many_reactants.yaml | 20 - .../first_order_loss/unknown_species.json | 36 -- .../first_order_loss/unknown_species.yaml | 15 - .../reactions/first_order_loss/valid.json | 56 -- .../reactions/first_order_loss/valid.yaml | 26 - ...lvent_species_not_registered_in_phase.json | 72 --- ...lvent_species_not_registered_in_phase.yaml | 32 - .../species_not_found_in_gas_phase.json | 64 -- .../species_not_found_in_gas_phase.yaml | 28 - .../species_not_in_aqueous_phase.json | 66 -- .../species_not_in_aqueous_phase.yaml | 30 - .../reactions/henrys_law/unknown_species.json | 64 -- .../reactions/henrys_law/unknown_species.yaml | 29 - .../reactions/henrys_law/valid.json | 102 --- .../reactions/henrys_law/valid.yaml | 52 -- .../photolysis/bad_reaction_component.json | 43 -- .../photolysis/bad_reaction_component.yaml | 19 - .../reactions/photolysis/missing_phase.json | 34 - .../reactions/photolysis/missing_phase.yaml | 16 - .../photolysis/more_than_one_reactant.json | 84 --- .../photolysis/more_than_one_reactant.yaml | 37 -- .../reactions/photolysis/unknown_species.json | 43 -- .../reactions/photolysis/unknown_species.yaml | 19 - .../reactions/photolysis/valid.json | 82 --- .../reactions/photolysis/valid.yaml | 37 -- .../missing_aqueous_phase.json | 48 -- .../missing_aqueous_phase.yaml | 25 - ...queous_phase_species_in_aqueous_phase.json | 56 -- ...queous_phase_species_in_aqueous_phase.yaml | 28 - .../missing_gas_phase.json | 48 -- .../missing_gas_phase.yaml | 25 - ...issing_gas_phase_species_in_gas_phase.json | 56 -- ...issing_gas_phase_species_in_gas_phase.yaml | 28 - .../unknown_species.json | 56 -- .../unknown_species.yaml | 28 - .../simpol_phase_transfer/valid.json | 80 --- .../simpol_phase_transfer/valid.yaml | 43 -- .../surface/bad_reaction_component.json | 58 -- .../surface/bad_reaction_component.yaml | 27 - .../surface/missing_condensed_phase.json | 53 -- .../surface/missing_condensed_phase.yaml | 23 - .../reactions/surface/missing_gas_phase.json | 50 -- .../reactions/surface/missing_gas_phase.yaml | 22 - .../reactions/surface/unknown_species.json | 60 -- .../reactions/surface/unknown_species.yaml | 27 - .../reactions/surface/valid.json | 91 --- .../reactions/surface/valid.yaml | 47 -- .../taylor_series/bad_reaction_component.json | 41 -- .../taylor_series/bad_reaction_component.yaml | 17 - .../taylor_series/missing_phase.json | 32 - .../taylor_series/missing_phase.yaml | 14 - .../taylor_series/mutually_exclusive.json | 43 -- .../taylor_series/mutually_exclusive.yaml | 19 - .../taylor_series/unknown_species.json | 41 -- .../taylor_series/unknown_species.yaml | 17 - .../reactions/taylor_series/valid.json | 109 ---- .../reactions/taylor_series/valid.yaml | 59 -- .../contains_nonstandard_key.json | 127 ---- .../contains_nonstandard_key.yaml | 68 -- .../missing_products.json | 53 -- .../missing_products.yaml | 23 - .../missing_reactants.json | 53 -- .../missing_reactants.yaml | 23 - .../unknown_species.json | 97 --- .../unknown_species.yaml | 52 -- .../ternary_chemical_activation/valid.json | 97 --- .../ternary_chemical_activation/valid.yaml | 50 -- .../troe/bad_reaction_component.json | 41 -- .../troe/bad_reaction_component.yaml | 17 - .../reactions/troe/missing_phase.json | 32 - .../reactions/troe/missing_phase.yaml | 14 - .../reactions/troe/unknown_species.json | 42 -- .../reactions/troe/unknown_species.yaml | 18 - .../reactions/troe/valid.json | 79 --- .../reactions/troe/valid.yaml | 40 -- .../tunneling/bad_reaction_component.json | 41 -- .../tunneling/bad_reaction_component.yaml | 17 - .../reactions/tunneling/missing_phase.json | 36 -- .../reactions/tunneling/missing_phase.yaml | 18 - .../reactions/tunneling/unknown_species.json | 42 -- .../reactions/tunneling/unknown_species.yaml | 18 - .../reactions/tunneling/valid.json | 73 --- .../reactions/tunneling/valid.yaml | 35 -- .../user_defined/bad_reaction_component.json | 44 -- .../user_defined/bad_reaction_component.yaml | 20 - .../reactions/user_defined/missing_phase.json | 34 - .../reactions/user_defined/missing_phase.yaml | 16 - .../user_defined/unknown_species.json | 43 -- .../user_defined/unknown_species.yaml | 19 - .../reactions/user_defined/valid.json | 86 --- .../reactions/user_defined/valid.yaml | 39 -- .../wet_deposition/missing_phase.json | 23 - .../wet_deposition/missing_phase.yaml | 11 - .../reactions/wet_deposition/valid.json | 45 -- .../reactions/wet_deposition/valid.yaml | 21 - .../species/duplicate_species.json | 29 - .../species/duplicate_species.yaml | 12 - .../species/invalid_key.json | 12 - .../species/invalid_key.yaml | 7 - .../species/missing_required_key.json | 11 - .../species/missing_required_key.yaml | 6 - .../species/valid_species.json | 32 - .../species/valid_species.yaml | 23 - test/unit/development/models/CMakeLists.txt | 5 - .../models/test_parse_gas_model.cpp | 76 --- .../development/models/test_parse_modal.cpp | 114 ---- .../unit/development/reactions/CMakeLists.txt | 20 - .../test_parse_aqueous_equilibrium.cpp | 166 ----- .../reactions/test_parse_arrhenius.cpp | 211 ------- .../reactions/test_parse_branched.cpp | 193 ------ .../test_parse_condensed_phase_arrhenius.cpp | 235 ------- .../test_parse_condensed_phase_photolysis.cpp | 205 ------ .../reactions/test_parse_emission.cpp | 147 ----- .../reactions/test_parse_first_order_loss.cpp | 174 ------ .../reactions/test_parse_henrys_law.cpp | 360 ----------- .../reactions/test_parse_photolysis.cpp | 180 ------ .../test_parse_simpol_phase_transfer.cpp | 356 ----------- .../reactions/test_parse_surface.cpp | 190 ------ .../reactions/test_parse_taylor_series.cpp | 217 ------- ...test_parse_ternary_chemical_activation.cpp | 211 ------- .../development/reactions/test_parse_troe.cpp | 185 ------ .../reactions/test_parse_tunneling.cpp | 166 ----- .../reactions/test_parse_user_defined.cpp | 164 ----- .../reactions/test_parse_wet_deposition.cpp | 159 ----- test/unit/development/test_parse_phases.cpp | 501 --------------- test/unit/development/test_parse_species.cpp | 262 -------- test/unit/test_validate.cpp | 123 ++++ test/unit/v0/test_arrhenius_config.cpp | 88 +-- test/unit/v0/test_branched_config.cpp | 114 ++-- test/unit/v0/test_emission_config.cpp | 38 +- test/unit/v0/test_first_order_loss_config.cpp | 38 +- test/unit/v0/test_photolysis_config.cpp | 70 ++- test/unit/v0/test_species_config.cpp | 12 +- test/unit/v0/test_surface_config.cpp | 66 +- ...est_ternary_chemical_activation_config.cpp | 82 +-- test/unit/v0/test_troe_config.cpp | 82 +-- test/unit/v0/test_tunneling_config.cpp | 68 +- test/unit/v0/test_user_defined_config.cpp | 70 ++- .../test_parse_from_file_configs.cpp | 67 +- .../v1/reactions/test_parse_arrhenius.cpp | 75 ++- .../unit/v1/reactions/test_parse_branched.cpp | 57 +- .../unit/v1/reactions/test_parse_emission.cpp | 52 +- .../reactions/test_parse_first_order_loss.cpp | 88 ++- .../test_parse_lambda_rate_constant.cpp | 50 +- .../v1/reactions/test_parse_photolysis.cpp | 71 +-- test/unit/v1/reactions/test_parse_surface.cpp | 60 +- .../v1/reactions/test_parse_taylor_series.cpp | 75 ++- ...test_parse_ternary_chemical_activation.cpp | 82 +-- test/unit/v1/reactions/test_parse_troe.cpp | 58 +- .../v1/reactions/test_parse_tunneling.cpp | 58 +- .../v1/reactions/test_parse_user_defined.cpp | 54 +- test/unit/v1/test_parse_phases.cpp | 86 ++- test/unit/v1/test_parse_species.cpp | 52 +- .../bad_reaction_component.json | 53 -- .../bad_reaction_component.yaml | 27 - .../aqueous_equilibrium/missing_phase.json | 43 -- .../aqueous_equilibrium/missing_phase.yaml | 21 - .../aqueous_equilibrium/unknown_species.json | 45 -- .../aqueous_equilibrium/unknown_species.yaml | 23 - .../reactions/aqueous_equilibrium/valid.json | 79 --- .../reactions/aqueous_equilibrium/valid.yaml | 43 -- .../reactions/henrys_law/missing_phase.json | 31 - .../reactions/henrys_law/missing_phase.yaml | 19 - ...lvent_species_not_registered_in_phase.json | 50 -- ...lvent_species_not_registered_in_phase.yaml | 29 - .../species_not_found_in_gas_phase.json | 44 -- .../species_not_found_in_gas_phase.yaml | 25 - .../species_not_in_aqueous_phase.json | 50 -- .../species_not_in_aqueous_phase.yaml | 27 - .../reactions/henrys_law/unknown_species.json | 44 -- .../reactions/henrys_law/unknown_species.yaml | 25 - .../reactions/henrys_law/valid.json | 71 --- .../reactions/henrys_law/valid.yaml | 40 -- 434 files changed, 5751 insertions(+), 25730 deletions(-) create mode 100644 docs/source/changelog.rst create mode 100644 docs/source/v1/reactions/lambda_rate_constant.rst delete mode 100644 examples/development/full_configuration.json delete mode 100644 examples/development/full_configuration.yaml delete mode 100644 include/mechanism_configuration/development/mechanism.hpp delete mode 100644 include/mechanism_configuration/development/model_parsers.hpp delete mode 100644 include/mechanism_configuration/development/model_types.hpp delete mode 100644 include/mechanism_configuration/development/reaction_parsers.hpp delete mode 100644 include/mechanism_configuration/development/reaction_types.hpp delete mode 100644 include/mechanism_configuration/development/type_parsers.hpp delete mode 100644 include/mechanism_configuration/development/type_validators.hpp delete mode 100644 include/mechanism_configuration/development/types.hpp delete mode 100644 include/mechanism_configuration/development/utils.hpp delete mode 100644 include/mechanism_configuration/development/validation.hpp delete mode 100644 include/mechanism_configuration/error_location.hpp create mode 100644 include/mechanism_configuration/mechanism_configuration.hpp create mode 100644 include/mechanism_configuration/parse.hpp delete mode 100644 include/mechanism_configuration/parse_status.hpp delete mode 100644 include/mechanism_configuration/parser.hpp delete mode 100644 include/mechanism_configuration/parser_result.hpp create mode 100644 include/mechanism_configuration/types.hpp delete mode 100644 include/mechanism_configuration/v0/parser.hpp delete mode 100644 include/mechanism_configuration/v0/parser_types.hpp delete mode 100644 include/mechanism_configuration/v0/types.hpp delete mode 100644 include/mechanism_configuration/v0/validation.hpp delete mode 100644 include/mechanism_configuration/v1/mechanism.hpp delete mode 100644 include/mechanism_configuration/v1/mechanism_parsers.hpp delete mode 100644 include/mechanism_configuration/v1/parser.hpp delete mode 100644 include/mechanism_configuration/v1/reaction_parsers.hpp delete mode 100644 include/mechanism_configuration/v1/reaction_types.hpp delete mode 100644 include/mechanism_configuration/v1/types.hpp delete mode 100644 include/mechanism_configuration/v1/utils.hpp delete mode 100644 include/mechanism_configuration/v1/validation.hpp create mode 100644 include/mechanism_configuration/validate.hpp delete mode 100644 include/mechanism_configuration/validate_schema.hpp rename src/{validate_schema.cpp => check_schema.cpp} (53%) create mode 100644 src/detail/check_schema.hpp rename {include/mechanism_configuration => src/detail}/constants.hpp (100%) rename {include/mechanism_configuration => src/detail}/conversions.hpp (89%) create mode 100644 src/detail/v0/keys.hpp create mode 100644 src/detail/v0/parser.hpp create mode 100644 src/detail/v0/parser_types.hpp create mode 100644 src/detail/v1/keys.hpp create mode 100644 src/detail/v1/parser.hpp create mode 100644 src/detail/v1/reaction_parsers.hpp create mode 100644 src/detail/v1/type_parsers.hpp create mode 100644 src/detail/v1/type_schema.hpp create mode 100644 src/detail/v1/utils.hpp delete mode 100644 src/development/CMakeLists.txt delete mode 100644 src/development/mechanism.cpp delete mode 100644 src/development/models/CMakeLists.txt delete mode 100644 src/development/models/parsers/CMakeLists.txt delete mode 100644 src/development/models/parsers/gas.cpp delete mode 100644 src/development/models/parsers/modal.cpp delete mode 100644 src/development/models/validators/CMakeLists.txt delete mode 100644 src/development/models/validators/gas.cpp delete mode 100644 src/development/models/validators/modal.cpp delete mode 100644 src/development/reactions/CMakeLists.txt delete mode 100644 src/development/reactions/parsers/CMakeLists.txt delete mode 100644 src/development/reactions/parsers/aqueous_equilibrium.cpp delete mode 100644 src/development/reactions/parsers/arrhenius.cpp delete mode 100644 src/development/reactions/parsers/branched.cpp delete mode 100644 src/development/reactions/parsers/condensed_phase_arrhenius.cpp delete mode 100644 src/development/reactions/parsers/condensed_phase_photolysis.cpp delete mode 100644 src/development/reactions/parsers/emission.cpp delete mode 100644 src/development/reactions/parsers/first_order_loss.cpp delete mode 100644 src/development/reactions/parsers/henrys_law.cpp delete mode 100644 src/development/reactions/parsers/lambda_rate_constant.cpp delete mode 100644 src/development/reactions/parsers/photolysis.cpp delete mode 100644 src/development/reactions/parsers/simpol_phase_transfer.cpp delete mode 100644 src/development/reactions/parsers/surface.cpp delete mode 100644 src/development/reactions/parsers/taylor_series.cpp delete mode 100644 src/development/reactions/parsers/ternary_chemical_activation.cpp delete mode 100644 src/development/reactions/parsers/troe.cpp delete mode 100644 src/development/reactions/parsers/tunneling.cpp delete mode 100644 src/development/reactions/parsers/user_defined.cpp delete mode 100644 src/development/reactions/parsers/wet_deposition.cpp delete mode 100644 src/development/reactions/validators/CMakeLists.txt delete mode 100644 src/development/reactions/validators/aqueous_equilibrium.cpp delete mode 100644 src/development/reactions/validators/arrhenius.cpp delete mode 100644 src/development/reactions/validators/branched.cpp delete mode 100644 src/development/reactions/validators/condensed_phase_arrhenius.cpp delete mode 100644 src/development/reactions/validators/condensed_phase_photolysis.cpp delete mode 100644 src/development/reactions/validators/emission.cpp delete mode 100644 src/development/reactions/validators/first_order_loss.cpp delete mode 100644 src/development/reactions/validators/henrys_law.cpp delete mode 100644 src/development/reactions/validators/lambda_rate_constant.cpp delete mode 100644 src/development/reactions/validators/photolysis.cpp delete mode 100644 src/development/reactions/validators/simpol_phase_transfer.cpp delete mode 100644 src/development/reactions/validators/surface.cpp delete mode 100644 src/development/reactions/validators/taylor_series.cpp delete mode 100644 src/development/reactions/validators/ternary_chemical_activation.cpp delete mode 100644 src/development/reactions/validators/troe.cpp delete mode 100644 src/development/reactions/validators/tunneling.cpp delete mode 100644 src/development/reactions/validators/user_defined.cpp delete mode 100644 src/development/reactions/validators/wet_deposition.cpp delete mode 100644 src/development/type_parsers.cpp delete mode 100644 src/development/type_validators.cpp delete mode 100644 src/development/utils.cpp create mode 100644 src/errors.cpp create mode 100644 src/parse.cpp delete mode 100644 src/parse_status.cpp delete mode 100644 src/parser.cpp delete mode 100644 src/v1/mechanism_parsers.cpp create mode 100644 src/v1/reactions/arrhenius.cpp delete mode 100644 src/v1/reactions/arrhenius_parser.cpp create mode 100644 src/v1/reactions/branched.cpp delete mode 100644 src/v1/reactions/branched_parser.cpp create mode 100644 src/v1/reactions/emission.cpp delete mode 100644 src/v1/reactions/emission_parser.cpp create mode 100644 src/v1/reactions/first_order_loss.cpp delete mode 100644 src/v1/reactions/first_order_loss_parser.cpp delete mode 100644 src/v1/reactions/lambda_parser.cpp create mode 100644 src/v1/reactions/lambda_rate_constant.cpp create mode 100644 src/v1/reactions/photolysis.cpp delete mode 100644 src/v1/reactions/photolysis_parser.cpp create mode 100644 src/v1/reactions/surface.cpp delete mode 100644 src/v1/reactions/surface_parser.cpp create mode 100644 src/v1/reactions/taylor_series.cpp delete mode 100644 src/v1/reactions/taylor_series_parser.cpp create mode 100644 src/v1/reactions/ternary_chemical_activation.cpp delete mode 100644 src/v1/reactions/ternary_chemical_activation_parser.cpp create mode 100644 src/v1/reactions/troe.cpp delete mode 100644 src/v1/reactions/troe_parser.cpp create mode 100644 src/v1/reactions/tunneling.cpp delete mode 100644 src/v1/reactions/tunneling_parser.cpp create mode 100644 src/v1/reactions/user_defined.cpp delete mode 100644 src/v1/reactions/user_defined_parser.cpp create mode 100644 src/v1/type_parsers.cpp create mode 100644 src/v1/type_schema.cpp create mode 100644 src/validate.cpp delete mode 100644 test/integration/test_development_parser.cpp delete mode 100644 test/unit/development/CMakeLists.txt delete mode 100644 test/unit/development/development_unit_configs/models/gas/gas_phase_not_found_in_phases.json delete mode 100644 test/unit/development/development_unit_configs/models/gas/gas_phase_not_found_in_phases.yaml delete mode 100644 test/unit/development/development_unit_configs/models/gas/missing_phase.json delete mode 100644 test/unit/development/development_unit_configs/models/gas/missing_phase.yaml delete mode 100644 test/unit/development/development_unit_configs/models/gas/valid.json delete mode 100644 test/unit/development/development_unit_configs/models/gas/valid.yaml delete mode 100644 test/unit/development/development_unit_configs/models/modal/missing_modal_variable.json delete mode 100644 test/unit/development/development_unit_configs/models/modal/missing_modal_variable.yaml delete mode 100644 test/unit/development/development_unit_configs/models/modal/missing_modes.json delete mode 100644 test/unit/development/development_unit_configs/models/modal/missing_modes.yaml delete mode 100644 test/unit/development/development_unit_configs/models/modal/mode_phase_not_found_in_phases.json delete mode 100644 test/unit/development/development_unit_configs/models/modal/mode_phase_not_found_in_phases.yaml delete mode 100644 test/unit/development/development_unit_configs/models/modal/valid.json delete mode 100644 test/unit/development/development_unit_configs/models/modal/valid.yaml delete mode 100644 test/unit/development/development_unit_configs/phases/duplicate_phases.json delete mode 100644 test/unit/development/development_unit_configs/phases/duplicate_phases.yaml delete mode 100644 test/unit/development/development_unit_configs/phases/duplicate_species_in_phase.json delete mode 100644 test/unit/development/development_unit_configs/phases/duplicate_species_in_phase.yaml delete mode 100644 test/unit/development/development_unit_configs/phases/invalid_key.json delete mode 100644 test/unit/development/development_unit_configs/phases/invalid_key.yaml delete mode 100644 test/unit/development/development_unit_configs/phases/invalid_species_object.json delete mode 100644 test/unit/development/development_unit_configs/phases/invalid_species_object.yaml delete mode 100644 test/unit/development/development_unit_configs/phases/missing_required_key.json delete mode 100644 test/unit/development/development_unit_configs/phases/missing_required_key.yaml delete mode 100644 test/unit/development/development_unit_configs/phases/phase_species_properties.json delete mode 100644 test/unit/development/development_unit_configs/phases/phase_species_properties.yaml delete mode 100644 test/unit/development/development_unit_configs/phases/unknown_species.json delete mode 100644 test/unit/development/development_unit_configs/phases/unknown_species.yaml delete mode 100644 test/unit/development/development_unit_configs/phases/valid_phases.json delete mode 100644 test/unit/development/development_unit_configs/phases/valid_phases.yaml delete mode 100644 test/unit/development/development_unit_configs/reactions/aqueous_equilibrium/bad_reaction_component.json delete mode 100644 test/unit/development/development_unit_configs/reactions/aqueous_equilibrium/bad_reaction_component.yaml delete mode 100644 test/unit/development/development_unit_configs/reactions/aqueous_equilibrium/missing_phase.json delete mode 100644 test/unit/development/development_unit_configs/reactions/aqueous_equilibrium/missing_phase.yaml delete mode 100644 test/unit/development/development_unit_configs/reactions/aqueous_equilibrium/unknown_species.json delete mode 100644 test/unit/development/development_unit_configs/reactions/aqueous_equilibrium/unknown_species.yaml delete mode 100644 test/unit/development/development_unit_configs/reactions/aqueous_equilibrium/valid.json delete mode 100644 test/unit/development/development_unit_configs/reactions/aqueous_equilibrium/valid.yaml delete mode 100644 test/unit/development/development_unit_configs/reactions/arrhenius/bad_reaction_component.json delete mode 100644 test/unit/development/development_unit_configs/reactions/arrhenius/bad_reaction_component.yaml delete mode 100644 test/unit/development/development_unit_configs/reactions/arrhenius/missing_phase.json delete mode 100644 test/unit/development/development_unit_configs/reactions/arrhenius/missing_phase.yaml delete mode 100644 test/unit/development/development_unit_configs/reactions/arrhenius/mutually_exclusive.json delete mode 100644 test/unit/development/development_unit_configs/reactions/arrhenius/mutually_exclusive.yaml delete mode 100644 test/unit/development/development_unit_configs/reactions/arrhenius/unknown_species.json delete mode 100644 test/unit/development/development_unit_configs/reactions/arrhenius/unknown_species.yaml delete mode 100644 test/unit/development/development_unit_configs/reactions/arrhenius/valid.json delete mode 100644 test/unit/development/development_unit_configs/reactions/arrhenius/valid.yaml delete mode 100644 test/unit/development/development_unit_configs/reactions/branched/bad_reaction_component.json delete mode 100644 test/unit/development/development_unit_configs/reactions/branched/bad_reaction_component.yaml delete mode 100644 test/unit/development/development_unit_configs/reactions/branched/missing_phase.json delete mode 100644 test/unit/development/development_unit_configs/reactions/branched/missing_phase.yaml delete mode 100644 test/unit/development/development_unit_configs/reactions/branched/unknown_species.json delete mode 100644 test/unit/development/development_unit_configs/reactions/branched/unknown_species.yaml delete mode 100644 test/unit/development/development_unit_configs/reactions/branched/valid.json delete mode 100644 test/unit/development/development_unit_configs/reactions/branched/valid.yaml delete mode 100644 test/unit/development/development_unit_configs/reactions/condensed_phase_arrhenius/bad_reaction_component.json delete mode 100644 test/unit/development/development_unit_configs/reactions/condensed_phase_arrhenius/bad_reaction_component.yaml delete mode 100644 test/unit/development/development_unit_configs/reactions/condensed_phase_arrhenius/missing_phase.json delete mode 100644 test/unit/development/development_unit_configs/reactions/condensed_phase_arrhenius/missing_phase.yaml delete mode 100644 test/unit/development/development_unit_configs/reactions/condensed_phase_arrhenius/mutually_exclusive.json delete mode 100644 test/unit/development/development_unit_configs/reactions/condensed_phase_arrhenius/mutually_exclusive.yaml delete mode 100644 test/unit/development/development_unit_configs/reactions/condensed_phase_arrhenius/species_not_in_aqueous_phase.json delete mode 100644 test/unit/development/development_unit_configs/reactions/condensed_phase_arrhenius/species_not_in_aqueous_phase.yaml delete mode 100644 test/unit/development/development_unit_configs/reactions/condensed_phase_arrhenius/unknown_species.json delete mode 100644 test/unit/development/development_unit_configs/reactions/condensed_phase_arrhenius/unknown_species.yaml delete mode 100644 test/unit/development/development_unit_configs/reactions/condensed_phase_arrhenius/valid.json delete mode 100644 test/unit/development/development_unit_configs/reactions/condensed_phase_arrhenius/valid.yaml delete mode 100644 test/unit/development/development_unit_configs/reactions/condensed_phase_photolysis/bad_reaction_component.json delete mode 100644 test/unit/development/development_unit_configs/reactions/condensed_phase_photolysis/bad_reaction_component.yaml delete mode 100644 test/unit/development/development_unit_configs/reactions/condensed_phase_photolysis/missing_phase.json delete mode 100644 test/unit/development/development_unit_configs/reactions/condensed_phase_photolysis/missing_phase.yaml delete mode 100644 test/unit/development/development_unit_configs/reactions/condensed_phase_photolysis/more_than_one_reactant.json delete mode 100644 test/unit/development/development_unit_configs/reactions/condensed_phase_photolysis/more_than_one_reactant.yaml delete mode 100644 test/unit/development/development_unit_configs/reactions/condensed_phase_photolysis/species_not_in_aqueous_phase.json delete mode 100644 test/unit/development/development_unit_configs/reactions/condensed_phase_photolysis/species_not_in_aqueous_phase.yaml delete mode 100644 test/unit/development/development_unit_configs/reactions/condensed_phase_photolysis/unknown_species.json delete mode 100644 test/unit/development/development_unit_configs/reactions/condensed_phase_photolysis/unknown_species.yaml delete mode 100644 test/unit/development/development_unit_configs/reactions/condensed_phase_photolysis/valid.json delete mode 100644 test/unit/development/development_unit_configs/reactions/condensed_phase_photolysis/valid.yaml delete mode 100644 test/unit/development/development_unit_configs/reactions/emission/bad_reaction_component.json delete mode 100644 test/unit/development/development_unit_configs/reactions/emission/bad_reaction_component.yaml delete mode 100644 test/unit/development/development_unit_configs/reactions/emission/missing_phase.json delete mode 100644 test/unit/development/development_unit_configs/reactions/emission/missing_phase.yaml delete mode 100644 test/unit/development/development_unit_configs/reactions/emission/unknown_species.json delete mode 100644 test/unit/development/development_unit_configs/reactions/emission/unknown_species.yaml delete mode 100644 test/unit/development/development_unit_configs/reactions/emission/valid.json delete mode 100644 test/unit/development/development_unit_configs/reactions/emission/valid.yaml delete mode 100644 test/unit/development/development_unit_configs/reactions/first_order_loss/bad_reaction_component.json delete mode 100644 test/unit/development/development_unit_configs/reactions/first_order_loss/bad_reaction_component.yaml delete mode 100644 test/unit/development/development_unit_configs/reactions/first_order_loss/missing_phase.json delete mode 100644 test/unit/development/development_unit_configs/reactions/first_order_loss/missing_phase.yaml delete mode 100644 test/unit/development/development_unit_configs/reactions/first_order_loss/too_many_reactants.json delete mode 100644 test/unit/development/development_unit_configs/reactions/first_order_loss/too_many_reactants.yaml delete mode 100644 test/unit/development/development_unit_configs/reactions/first_order_loss/unknown_species.json delete mode 100644 test/unit/development/development_unit_configs/reactions/first_order_loss/unknown_species.yaml delete mode 100644 test/unit/development/development_unit_configs/reactions/first_order_loss/valid.json delete mode 100644 test/unit/development/development_unit_configs/reactions/first_order_loss/valid.yaml delete mode 100644 test/unit/development/development_unit_configs/reactions/henrys_law/solvent_species_not_registered_in_phase.json delete mode 100644 test/unit/development/development_unit_configs/reactions/henrys_law/solvent_species_not_registered_in_phase.yaml delete mode 100644 test/unit/development/development_unit_configs/reactions/henrys_law/species_not_found_in_gas_phase.json delete mode 100644 test/unit/development/development_unit_configs/reactions/henrys_law/species_not_found_in_gas_phase.yaml delete mode 100644 test/unit/development/development_unit_configs/reactions/henrys_law/species_not_in_aqueous_phase.json delete mode 100644 test/unit/development/development_unit_configs/reactions/henrys_law/species_not_in_aqueous_phase.yaml delete mode 100644 test/unit/development/development_unit_configs/reactions/henrys_law/unknown_species.json delete mode 100644 test/unit/development/development_unit_configs/reactions/henrys_law/unknown_species.yaml delete mode 100644 test/unit/development/development_unit_configs/reactions/henrys_law/valid.json delete mode 100644 test/unit/development/development_unit_configs/reactions/henrys_law/valid.yaml delete mode 100644 test/unit/development/development_unit_configs/reactions/photolysis/bad_reaction_component.json delete mode 100644 test/unit/development/development_unit_configs/reactions/photolysis/bad_reaction_component.yaml delete mode 100644 test/unit/development/development_unit_configs/reactions/photolysis/missing_phase.json delete mode 100644 test/unit/development/development_unit_configs/reactions/photolysis/missing_phase.yaml delete mode 100644 test/unit/development/development_unit_configs/reactions/photolysis/more_than_one_reactant.json delete mode 100644 test/unit/development/development_unit_configs/reactions/photolysis/more_than_one_reactant.yaml delete mode 100644 test/unit/development/development_unit_configs/reactions/photolysis/unknown_species.json delete mode 100644 test/unit/development/development_unit_configs/reactions/photolysis/unknown_species.yaml delete mode 100644 test/unit/development/development_unit_configs/reactions/photolysis/valid.json delete mode 100644 test/unit/development/development_unit_configs/reactions/photolysis/valid.yaml delete mode 100644 test/unit/development/development_unit_configs/reactions/simpol_phase_transfer/missing_aqueous_phase.json delete mode 100644 test/unit/development/development_unit_configs/reactions/simpol_phase_transfer/missing_aqueous_phase.yaml delete mode 100644 test/unit/development/development_unit_configs/reactions/simpol_phase_transfer/missing_aqueous_phase_species_in_aqueous_phase.json delete mode 100644 test/unit/development/development_unit_configs/reactions/simpol_phase_transfer/missing_aqueous_phase_species_in_aqueous_phase.yaml delete mode 100644 test/unit/development/development_unit_configs/reactions/simpol_phase_transfer/missing_gas_phase.json delete mode 100644 test/unit/development/development_unit_configs/reactions/simpol_phase_transfer/missing_gas_phase.yaml delete mode 100644 test/unit/development/development_unit_configs/reactions/simpol_phase_transfer/missing_gas_phase_species_in_gas_phase.json delete mode 100644 test/unit/development/development_unit_configs/reactions/simpol_phase_transfer/missing_gas_phase_species_in_gas_phase.yaml delete mode 100644 test/unit/development/development_unit_configs/reactions/simpol_phase_transfer/unknown_species.json delete mode 100644 test/unit/development/development_unit_configs/reactions/simpol_phase_transfer/unknown_species.yaml delete mode 100644 test/unit/development/development_unit_configs/reactions/simpol_phase_transfer/valid.json delete mode 100644 test/unit/development/development_unit_configs/reactions/simpol_phase_transfer/valid.yaml delete mode 100644 test/unit/development/development_unit_configs/reactions/surface/bad_reaction_component.json delete mode 100644 test/unit/development/development_unit_configs/reactions/surface/bad_reaction_component.yaml delete mode 100644 test/unit/development/development_unit_configs/reactions/surface/missing_condensed_phase.json delete mode 100644 test/unit/development/development_unit_configs/reactions/surface/missing_condensed_phase.yaml delete mode 100644 test/unit/development/development_unit_configs/reactions/surface/missing_gas_phase.json delete mode 100644 test/unit/development/development_unit_configs/reactions/surface/missing_gas_phase.yaml delete mode 100644 test/unit/development/development_unit_configs/reactions/surface/unknown_species.json delete mode 100644 test/unit/development/development_unit_configs/reactions/surface/unknown_species.yaml delete mode 100644 test/unit/development/development_unit_configs/reactions/surface/valid.json delete mode 100644 test/unit/development/development_unit_configs/reactions/surface/valid.yaml delete mode 100644 test/unit/development/development_unit_configs/reactions/taylor_series/bad_reaction_component.json delete mode 100644 test/unit/development/development_unit_configs/reactions/taylor_series/bad_reaction_component.yaml delete mode 100644 test/unit/development/development_unit_configs/reactions/taylor_series/missing_phase.json delete mode 100644 test/unit/development/development_unit_configs/reactions/taylor_series/missing_phase.yaml delete mode 100644 test/unit/development/development_unit_configs/reactions/taylor_series/mutually_exclusive.json delete mode 100644 test/unit/development/development_unit_configs/reactions/taylor_series/mutually_exclusive.yaml delete mode 100644 test/unit/development/development_unit_configs/reactions/taylor_series/unknown_species.json delete mode 100644 test/unit/development/development_unit_configs/reactions/taylor_series/unknown_species.yaml delete mode 100644 test/unit/development/development_unit_configs/reactions/taylor_series/valid.json delete mode 100644 test/unit/development/development_unit_configs/reactions/taylor_series/valid.yaml delete mode 100644 test/unit/development/development_unit_configs/reactions/ternary_chemical_activation/contains_nonstandard_key.json delete mode 100644 test/unit/development/development_unit_configs/reactions/ternary_chemical_activation/contains_nonstandard_key.yaml delete mode 100644 test/unit/development/development_unit_configs/reactions/ternary_chemical_activation/missing_products.json delete mode 100644 test/unit/development/development_unit_configs/reactions/ternary_chemical_activation/missing_products.yaml delete mode 100644 test/unit/development/development_unit_configs/reactions/ternary_chemical_activation/missing_reactants.json delete mode 100644 test/unit/development/development_unit_configs/reactions/ternary_chemical_activation/missing_reactants.yaml delete mode 100644 test/unit/development/development_unit_configs/reactions/ternary_chemical_activation/unknown_species.json delete mode 100644 test/unit/development/development_unit_configs/reactions/ternary_chemical_activation/unknown_species.yaml delete mode 100644 test/unit/development/development_unit_configs/reactions/ternary_chemical_activation/valid.json delete mode 100644 test/unit/development/development_unit_configs/reactions/ternary_chemical_activation/valid.yaml delete mode 100644 test/unit/development/development_unit_configs/reactions/troe/bad_reaction_component.json delete mode 100644 test/unit/development/development_unit_configs/reactions/troe/bad_reaction_component.yaml delete mode 100644 test/unit/development/development_unit_configs/reactions/troe/missing_phase.json delete mode 100644 test/unit/development/development_unit_configs/reactions/troe/missing_phase.yaml delete mode 100644 test/unit/development/development_unit_configs/reactions/troe/unknown_species.json delete mode 100644 test/unit/development/development_unit_configs/reactions/troe/unknown_species.yaml delete mode 100644 test/unit/development/development_unit_configs/reactions/troe/valid.json delete mode 100644 test/unit/development/development_unit_configs/reactions/troe/valid.yaml delete mode 100644 test/unit/development/development_unit_configs/reactions/tunneling/bad_reaction_component.json delete mode 100644 test/unit/development/development_unit_configs/reactions/tunneling/bad_reaction_component.yaml delete mode 100644 test/unit/development/development_unit_configs/reactions/tunneling/missing_phase.json delete mode 100644 test/unit/development/development_unit_configs/reactions/tunneling/missing_phase.yaml delete mode 100644 test/unit/development/development_unit_configs/reactions/tunneling/unknown_species.json delete mode 100644 test/unit/development/development_unit_configs/reactions/tunneling/unknown_species.yaml delete mode 100644 test/unit/development/development_unit_configs/reactions/tunneling/valid.json delete mode 100644 test/unit/development/development_unit_configs/reactions/tunneling/valid.yaml delete mode 100644 test/unit/development/development_unit_configs/reactions/user_defined/bad_reaction_component.json delete mode 100644 test/unit/development/development_unit_configs/reactions/user_defined/bad_reaction_component.yaml delete mode 100644 test/unit/development/development_unit_configs/reactions/user_defined/missing_phase.json delete mode 100644 test/unit/development/development_unit_configs/reactions/user_defined/missing_phase.yaml delete mode 100644 test/unit/development/development_unit_configs/reactions/user_defined/unknown_species.json delete mode 100644 test/unit/development/development_unit_configs/reactions/user_defined/unknown_species.yaml delete mode 100644 test/unit/development/development_unit_configs/reactions/user_defined/valid.json delete mode 100644 test/unit/development/development_unit_configs/reactions/user_defined/valid.yaml delete mode 100644 test/unit/development/development_unit_configs/reactions/wet_deposition/missing_phase.json delete mode 100644 test/unit/development/development_unit_configs/reactions/wet_deposition/missing_phase.yaml delete mode 100644 test/unit/development/development_unit_configs/reactions/wet_deposition/valid.json delete mode 100644 test/unit/development/development_unit_configs/reactions/wet_deposition/valid.yaml delete mode 100644 test/unit/development/development_unit_configs/species/duplicate_species.json delete mode 100644 test/unit/development/development_unit_configs/species/duplicate_species.yaml delete mode 100644 test/unit/development/development_unit_configs/species/invalid_key.json delete mode 100644 test/unit/development/development_unit_configs/species/invalid_key.yaml delete mode 100644 test/unit/development/development_unit_configs/species/missing_required_key.json delete mode 100644 test/unit/development/development_unit_configs/species/missing_required_key.yaml delete mode 100644 test/unit/development/development_unit_configs/species/valid_species.json delete mode 100644 test/unit/development/development_unit_configs/species/valid_species.yaml delete mode 100644 test/unit/development/models/CMakeLists.txt delete mode 100644 test/unit/development/models/test_parse_gas_model.cpp delete mode 100644 test/unit/development/models/test_parse_modal.cpp delete mode 100644 test/unit/development/reactions/CMakeLists.txt delete mode 100644 test/unit/development/reactions/test_parse_aqueous_equilibrium.cpp delete mode 100644 test/unit/development/reactions/test_parse_arrhenius.cpp delete mode 100644 test/unit/development/reactions/test_parse_branched.cpp delete mode 100644 test/unit/development/reactions/test_parse_condensed_phase_arrhenius.cpp delete mode 100644 test/unit/development/reactions/test_parse_condensed_phase_photolysis.cpp delete mode 100644 test/unit/development/reactions/test_parse_emission.cpp delete mode 100644 test/unit/development/reactions/test_parse_first_order_loss.cpp delete mode 100644 test/unit/development/reactions/test_parse_henrys_law.cpp delete mode 100644 test/unit/development/reactions/test_parse_photolysis.cpp delete mode 100644 test/unit/development/reactions/test_parse_simpol_phase_transfer.cpp delete mode 100644 test/unit/development/reactions/test_parse_surface.cpp delete mode 100644 test/unit/development/reactions/test_parse_taylor_series.cpp delete mode 100644 test/unit/development/reactions/test_parse_ternary_chemical_activation.cpp delete mode 100644 test/unit/development/reactions/test_parse_troe.cpp delete mode 100644 test/unit/development/reactions/test_parse_tunneling.cpp delete mode 100644 test/unit/development/reactions/test_parse_user_defined.cpp delete mode 100644 test/unit/development/reactions/test_parse_wet_deposition.cpp delete mode 100644 test/unit/development/test_parse_phases.cpp delete mode 100644 test/unit/development/test_parse_species.cpp create mode 100644 test/unit/test_validate.cpp delete mode 100644 test/unit/v1/v1_unit_configs/reactions/aqueous_equilibrium/bad_reaction_component.json delete mode 100644 test/unit/v1/v1_unit_configs/reactions/aqueous_equilibrium/bad_reaction_component.yaml delete mode 100644 test/unit/v1/v1_unit_configs/reactions/aqueous_equilibrium/missing_phase.json delete mode 100644 test/unit/v1/v1_unit_configs/reactions/aqueous_equilibrium/missing_phase.yaml delete mode 100644 test/unit/v1/v1_unit_configs/reactions/aqueous_equilibrium/unknown_species.json delete mode 100644 test/unit/v1/v1_unit_configs/reactions/aqueous_equilibrium/unknown_species.yaml delete mode 100644 test/unit/v1/v1_unit_configs/reactions/aqueous_equilibrium/valid.json delete mode 100644 test/unit/v1/v1_unit_configs/reactions/aqueous_equilibrium/valid.yaml delete mode 100644 test/unit/v1/v1_unit_configs/reactions/henrys_law/missing_phase.json delete mode 100644 test/unit/v1/v1_unit_configs/reactions/henrys_law/missing_phase.yaml delete mode 100644 test/unit/v1/v1_unit_configs/reactions/henrys_law/solvent_species_not_registered_in_phase.json delete mode 100644 test/unit/v1/v1_unit_configs/reactions/henrys_law/solvent_species_not_registered_in_phase.yaml delete mode 100644 test/unit/v1/v1_unit_configs/reactions/henrys_law/species_not_found_in_gas_phase.json delete mode 100644 test/unit/v1/v1_unit_configs/reactions/henrys_law/species_not_found_in_gas_phase.yaml delete mode 100644 test/unit/v1/v1_unit_configs/reactions/henrys_law/species_not_in_aqueous_phase.json delete mode 100644 test/unit/v1/v1_unit_configs/reactions/henrys_law/species_not_in_aqueous_phase.yaml delete mode 100644 test/unit/v1/v1_unit_configs/reactions/henrys_law/unknown_species.json delete mode 100644 test/unit/v1/v1_unit_configs/reactions/henrys_law/unknown_species.yaml delete mode 100644 test/unit/v1/v1_unit_configs/reactions/henrys_law/valid.json delete mode 100644 test/unit/v1/v1_unit_configs/reactions/henrys_law/valid.yaml diff --git a/.github/workflows/ubuntu.yml b/.github/workflows/ubuntu.yml index 39c09daa..8760229c 100644 --- a/.github/workflows/ubuntu.yml +++ b/.github/workflows/ubuntu.yml @@ -18,11 +18,15 @@ jobs: strategy: matrix: compiler: + - { cpp: g++-12, c: gcc-12 } - { cpp: g++-13, c: gcc-13 } - { cpp: g++-14, c: gcc-14 } - { cpp: clang++, c: clang } build_type: [Release] use_fmt: [OFF, ON] + exclude: + - compiler: { cpp: g++-12, c: gcc-12 } + use_fmt: OFF env: CC: ${{ matrix.compiler.c }} CXX: ${{ matrix.compiler.cpp }} @@ -30,8 +34,20 @@ jobs: - name: Checkout code uses: actions/checkout@v4 + # Clang on Ubuntu defaults to libstdc++, whose std::expected is not visible to + # clang-18 (no template named 'expected'). Build the clang job against libc++, + # which provides std::expected and std::format. + - name: Install libc++ (clang) + if: matrix.compiler.cpp == 'clang++' + run: sudo apt-get update && sudo apt-get install -y libc++-dev libc++abi-dev + - name: Configure CMake - run: cmake -S . -B build -D CMAKE_BUILD_TYPE=${{ matrix.build_type }} -D MECH_CONFIG_USE_FMT=${{ matrix.use_fmt }} -D MECH_CONFIG_COMPILE_WARNING_AS_ERROR=ON + run: | + EXTRA_FLAGS="" + if [ "${{ matrix.compiler.cpp }}" = "clang++" ]; then + EXTRA_FLAGS="-D CMAKE_CXX_FLAGS=-stdlib=libc++" + fi + cmake -S . -B build -D CMAKE_BUILD_TYPE=${{ matrix.build_type }} -D MECH_CONFIG_USE_FMT=${{ matrix.use_fmt }} -D MECH_CONFIG_COMPILE_WARNING_AS_ERROR=ON $EXTRA_FLAGS - name: Build run: cmake --build build --config ${{ matrix.build_type }} --parallel 10 diff --git a/CMakeLists.txt b/CMakeLists.txt index a9452d22..66237b60 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,7 +6,7 @@ set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED ON) # must be on the same line so that pyproject.toml can correctly identify the version -project(mechanism_configuration VERSION 1.1.2 LANGUAGES CXX) +project(mechanism_configuration VERSION 2.0.0 LANGUAGES CXX) if(NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE "Release" CACHE STRING diff --git a/README.md b/README.md index 6b2fae30..cf757faf 100644 --- a/README.md +++ b/README.md @@ -3,8 +3,7 @@ An attempt at defining a model-independent configuration schema for atmospheric chemical systems in JSON and YAML. [![GitHub Releases](https://img.shields.io/github/release/ncar/MechanismConfiguration.svg)](https://github.com/ncar/MechanismConfiguration/releases) -[![License](https://img.shields.io/github/license/ncar/MechanismConfiguration.svg)](https://github.com/ncar/MechanismConfiguration/blob/master/LICENSE) -[![Docs build](https://github.com/ncar/MechanismConfiguration/actions/workflows/gh-pages.yml/badge.svg)](https://github.com/ncar/MechanismConfiguration/actions/workflows/gh-pages.yml) +[![License](https://img.shields.io/badge/license-Apache_2.0-blue.svg)](https://github.com/NCAR/MechanismConfiguration/blob/main/LICENSE) [![Windows](https://github.com/ncar/MechanismConfiguration/actions/workflows/windows.yml/badge.svg)](https://github.com/ncar/MechanismConfiguration/actions/workflows/windows.yml) [![Mac](https://github.com/ncar/MechanismConfiguration/actions/workflows/mac.yml/badge.svg)](https://github.com/ncar/MechanismConfiguration/actions/workflows/mac.yml) [![Ubuntu](https://github.com/ncar/MechanismConfiguration/actions/workflows/ubuntu.yml/badge.svg)](https://github.com/ncar/MechanismConfiguration/actions/workflows/ubuntu.yml) @@ -15,6 +14,72 @@ Copyright (C) 2017–2026 University Corporation for Atmospheric Research, Unive The configuration documentation can be found [here](https://ncar.github.io/MechanismConfiguration/). +## Usage + +Everything goes through the canonical `mechanism_configuration::Mechanism`. You can either +**parse** a configuration file (the version is detected and dispatched automatically), or build +a `Mechanism` in code and **validate** it. `Validate()` runs the same semantic checks the parser +uses, so it applies to any mechanism regardless of where it came from. + +```cpp +#include + +#include + +using namespace mechanism_configuration; + +void print_errors(const Errors& errors) +{ + for (const auto& [code, message] : errors) + std::cerr << " [" << ErrorCodeToString(code) << "] " << message << '\n'; +} + +int main() +{ + int status = 0; + + // 1) Parse from a file (YAML or JSON; v0 or v1). Returns std::expected + // with both structural and semantic errors reported. + if (auto parsed = Parse("examples/v1/full_configuration.yaml")) + { + const Mechanism& mechanism = *parsed; + std::cout << "Parsed '" << mechanism.name << "': " << mechanism.species.size() + << " species, " << mechanism.reactions.arrhenius.size() << " Arrhenius reactions\n"; + } + else + { + std::cerr << "Failed to parse file:\n"; + print_errors(parsed.error()); + status = 1; + } + + // 2) Build a Mechanism in code and validate it (species exist, reactants are in their + // phase, no duplicate names, ...). + Mechanism mechanism; + mechanism.name = "example"; + mechanism.species = { { .name = "A" }, { .name = "B" } }; + mechanism.phases = { { .name = "gas", .species = { { .name = "A" }, { .name = "B" } } } }; + + types::Arrhenius reaction; + reaction.name = "A -> B"; + reaction.gas_phase = "gas"; + reaction.reactants = { { .name = "A" } }; // reactants must be registered in the phase + reaction.products = { { .name = "B" } }; // products may reference any phase + mechanism.reactions.arrhenius = { reaction }; + + if (Errors errors = Validate(mechanism); errors.empty()) + std::cout << "In-code mechanism is valid\n"; + else + { + std::cerr << "In-code mechanism is invalid:\n"; + print_errors(errors); + status = 1; + } + + return status; +} +``` + ## Building the Documentation With python and pip installed, go to the `docs/` folder and run: diff --git a/cmake/test_util.cmake b/cmake/test_util.cmake index bf0e20a8..828d371c 100644 --- a/cmake/test_util.cmake +++ b/cmake/test_util.cmake @@ -13,6 +13,10 @@ function(create_standard_test) add_executable(test_${TEST_NAME} ${TEST_SOURCES}) target_link_libraries(test_${TEST_NAME} PUBLIC musica::mechanism_configuration GTest::gtest_main) + target_include_directories(test_${TEST_NAME} + PUBLIC + ${PROJECT_SOURCE_DIR}/src + ) # link additional libraries diff --git a/docs/source/changelog.rst b/docs/source/changelog.rst new file mode 100644 index 00000000..baaf1782 --- /dev/null +++ b/docs/source/changelog.rst @@ -0,0 +1,102 @@ +Changelog +========= + +Version 2.0.0 +------------- + +Version 2.0.0 introduces breaking changes to the C++ API compared to the 1.x series. +The configuration file formats (``v0`` and ``v1``) are unchanged; the breaking changes +are in how the library is consumed from C++. + +API Changes +^^^^^^^^^^^ + +- Parsing is now a free function that returns ``std::expected``: + ``std::expected Parse(const std::filesystem::path&)``. + The previous ``UniversalParser`` / ``ParserResult`` interface has been removed. +- A version-neutral ``Errors Validate(const Mechanism&)`` has been added so an in-code + ``Mechanism`` can be checked with the same semantic rules the parser uses. +- A single canonical ``mechanism_configuration::Mechanism`` (with ``mechanism_configuration::types::*``) + replaces the version-specific ``v0::types::Mechanism`` and ``v1::types::Mechanism``. +- Errors are reported through ``Errors`` (a list of ``{ErrorCode, std::string}``) and + ``ErrorCodeToString``; the previous parse-status helpers have been removed. + +Header Reorganization +^^^^^^^^^^^^^^^^^^^^^^ + +- A single public umbrella header is now provided. Including + ```` is sufficient to use the library. +- The public surface is limited to ``parse.hpp``, ``validate.hpp``, ``mechanism.hpp``, + ``types.hpp``, ``errors.hpp``, and ``version.hpp`` (plus the umbrella). +- Internal headers (the ``v0`` / ``v1`` parsers, schema and validation helpers) have moved + into a private ``detail`` tree and are no longer installed. Code that included headers such + as ``parser.hpp``, ``parser_result.hpp``, ``parse_status.hpp``, ``error_location.hpp``, or the + versioned ``v1/types.hpp`` / ``v1/mechanism.hpp`` must migrate to the public headers above. + +Removed Reactions +^^^^^^^^^^^^^^^^^ + +The following reaction types were removed from the ``v1`` mechanism: + +- ``AQUEOUS_EQUILIBRIUM`` +- ``CONDENSED_PHASE_ARRHENIUS`` +- ``CONDENSED_PHASE_PHOTOLYSIS`` +- ``HENRYS_LAW`` +- ``SIMPOL_PHASE_TRANSFER`` +- ``WET_DEPOSITION`` + +Other Changes +^^^^^^^^^^^^^ + +- Reaction components accept the legacy ``species name`` key as an alias for ``name``. +- A ``v1`` configuration may split ``species``, ``phases``, and ``reactions`` across multiple + files using the ``files`` list form (minor version 1.1 or later). +- Products may reference a species in any phase; only reactants must belong to the + reaction's phase. + +Migration +^^^^^^^^^ + +Old approach (1.x): + +.. code-block:: cpp + + #include + + using namespace mechanism_configuration; + + UniversalParser parser; + ParserResult result = parser.Parse("config.yaml"); + if (result) + { + GlobalMechanism& mechanism = *result; + // ... + } + else + { + for (const auto& error : result.errors) + { + // ... + } + } + +New approach (2.0): + +.. code-block:: cpp + + #include + + using namespace mechanism_configuration; + + if (auto parsed = Parse("config.yaml")) + { + const Mechanism& mechanism = *parsed; + // ... + } + else + { + for (const auto& [code, message] : parsed.error()) + { + // ... + } + } diff --git a/docs/source/index.rst b/docs/source/index.rst index be692b36..6d1205d4 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -12,7 +12,7 @@ .. ~ for subsubsubsections .. " for paragraphs -.. |project_version| replace:: 1.1.2 +.. |project_version| replace:: 2.0.0 ############################################################### Welcome to the NSF NCAR Mechanism Configuration documentation! @@ -24,6 +24,7 @@ Welcome to the NSF NCAR Mechanism Configuration documentation! v0/index v1/index + changelog bibliography diff --git a/docs/source/v1/reactions/index.rst b/docs/source/v1/reactions/index.rst index cca9324b..48b92f42 100644 --- a/docs/source/v1/reactions/index.rst +++ b/docs/source/v1/reactions/index.rst @@ -11,6 +11,7 @@ Their configuration is defined in this repository, as are the algorithms that mi * :doc:`branched` - :cpp:class:`micm::BranchedRateConstant` * :doc:`emission` - :cpp:class:`micm::UserDefinedRateConstant` * :doc:`first_order_loss` - :cpp:class:`micm::UserDefinedRateConstant` +* :doc:`lambda_rate_constant` - :cpp:class:`micm::UserDefinedRateConstant` * :doc:`photolysis` - :cpp:class:`micm::UserDefinedRateConstant` * :doc:`surface` - :cpp:class:`micm::SurfaceRateConstant` * :doc:`taylor_series` - :cpp:class:`micm::TaylorSeriesRateConstant` @@ -29,6 +30,7 @@ Their configuration is defined in this repository, as are the algorithms that mi branched emission first_order_loss + lambda_rate_constant photolysis surface taylor_series diff --git a/docs/source/v1/reactions/lambda_rate_constant.rst b/docs/source/v1/reactions/lambda_rate_constant.rst new file mode 100644 index 00000000..68a29749 --- /dev/null +++ b/docs/source/v1/reactions/lambda_rate_constant.rst @@ -0,0 +1,76 @@ +Lambda Rate Constant +==================== + +Lambda rate constant reactions compute the rate constant from a user-supplied lambda +function of temperature (and optionally pressure): + +.. math:: + + \ce{X_1 ( + X_2 \dots ) -> Y_1 ( + Y_2 \dots )} + +where :math:`\ce{X_n}` are the reactants, and :math:`\ce{Y_n}` are the products of the reaction. + +The rate constant is given by the value returned from the supplied ``lambda function`` when +evaluated at the current temperature :math:`T` (in K) and, optionally, pressure :math:`P` (in Pa). + +Input data for lambda rate constant reactions have the following format: + +.. tab-set:: + + .. tab-item:: YAML + + .. code-block:: yaml + + type: LAMBDA_RATE_CONSTANT + name: foo-lambda + gas phase: gas + lambda function: "[](double T, double P) { return 1.2e-5 * exp(-500.0 / T); }" + reactants: + - species name: foo + coefficient: 1.0 + products: + - species name: bar + coefficient: 0.5 + - species name: baz + coefficient: 0.3 + + + .. tab-item:: JSON + + .. code-block:: json + + { + "type": "LAMBDA_RATE_CONSTANT", + "name": "foo-lambda", + "gas phase": "gas", + "lambda function": "[](double T, double P) { return 1.2e-5 * exp(-500.0 / T); }", + "reactants": [ + { + "species name": "foo", + "coefficient": 1.0 + } + ], + "products": [ + { + "species name": "bar", + "coefficient": 0.5 + }, + { + "species name": "baz", + "coefficient": 0.3 + } + ] + } + +The key-value pairs ``reactants``, ``products``, and ``lambda function`` are required. +Any number of reactants and products may be present. Reactants and products without a specified ``coefficient`` are +assumed to have a ``coefficient`` of 1.0. + +The ``lambda function`` is a string holding a function that takes temperature :math:`T` and, +optionally, pressure :math:`P` and returns the rate constant. It is expected to be compiled +by a conforming implementation. + +The ``gas phase`` key is required and must be set to the name of the phase the +reaction takes place in. Each reactant must be present in the specified phase. + +Rate constants are in units of :math:`\mathrm{(m^{3}\ mol^{-1})^{(n-1)}\ s^{-1}}` where :math:`n` is the total number of reactants. diff --git a/examples/development/full_configuration.json b/examples/development/full_configuration.json deleted file mode 100644 index 563e72d9..00000000 --- a/examples/development/full_configuration.json +++ /dev/null @@ -1,586 +0,0 @@ -{ - "version": "2.0.0", - "name": "Full Configuration", - "species": [ - { - "name": "A", - "__absolute tolerance": 1.0e-30 - }, - { - "name": "B", - "constant concentration [mol m-3]": 1.0e19 - }, - { - "name": "C", - "is third body": true - }, - { - "name": "M" - }, - { - "name": "H2O2", - "HLC(298K) [mol m-3 Pa-1]": 1.011596348, - "HLC exponential factor [K]": 6340, - "diffusion coefficient [m2 s-1]": 1.46E-05, - "N star": 1.74, - "molecular weight [kg mol-1]": 0.0340147, - "density [kg m-3]": 1000.0, - "constant mixing ratio [mol mol-1]": 1.0e-6, - "__absolute tolerance": 1.0e-10 - }, - { - "name": "ethanol", - "diffusion coefficient [m2 s-1]": 0.95E-05, - "N star": 2.55, - "molecular weight [kg mol-1]": 0.04607, - "__absolute tolerance": 1.0e-20 - }, - { - "name": "ethanol_aq", - "molecular weight [kg mol-1]": 0.04607, - "density [kg m-3]": 1000.0, - "__absolute tolerance": 1.0e-20 - }, - { - "name": "H2O2_aq", - "molecular weight [kg mol-1]": 0.0340147, - "density [kg m-3]": 1000.0, - "__absolute tolerance": 1.0e-10 - }, - { - "name": "H2O", - "density [kg m-3]": 1000.0, - "molecular weight [kg mol-1]": 0.01801 - }, - { - "name": "aerosol stuff", - "molecular weight [kg mol-1]": 0.5, - "density [kg m-3]": 1000.0, - "__absolute tolerance": 1.0e-20 - }, - { - "name": "more aerosol stuff", - "molecular weight [kg mol-1]": 0.2, - "density [kg m-3]": 1000.0, - "__absolute tolerance": 1.0e-20 - } - ], - "phases": [ - { - "name": "gas", - "species": [ - { - "name": "A" - }, - { - "name": "B" - }, - { - "name": "C" - }, - { - "name": "ethanol" - }, - { - "name": "H2O2" - }, - { - "name": "M" - } - ] - }, - { - "name": "aqueous", - "species": [ - { - "name": "A" - }, - { - "name": "B" - }, - { - "name": "C" - }, - { - "name": "H2O2_aq" - }, - { - "name": "ethanol_aq" - }, - { - "name": "H2O" - } - ] - }, - { - "name": "surface reacting phase", - "species": [ - { - "name": "aerosol stuff" - }, - { - "name": "more aerosol stuff" - } - ] - }, - { - "name": "organic", - "species": [ - { - "name": "B" - }, - { - "name": "C" - } - ] - } - ], - "models": [ - { - "name": "gas", - "type": "GAS_PHASE", - "phase": "gas" - }, - { - "name": "aqueous", - "type": "MODAL", - "modes": [ - { - "name": "aitken", - "geometric mean diameter [m]": 2.6e-8, - "geometric standard deviation": 1.6, - "phase": "aqueous" - }, - { - "name": "accumulation", - "geometric mean diameter [m]": 1.1e-7, - "geometric standard deviation": 1.8, - "phase": "organic" - } - ] - } - ], - "reactions": [ - { - "type": "TAYLOR_SERIES", - "gas phase": "gas", - "reactants": [ - { - "name": "A", - "coefficient": 1 - } - ], - "products": [ - { - "name": "B", - "coefficient": 1.2 - }, - { - "name": "C", - "coefficient": 0.3 - } - ], - "A": 32.1, - "B": -2.3, - "C": 102.3, - "D": 63.4, - "E": -1.3, - "taylor coefficients": [ - 1.0, - 2.0, - 3.0 - ], - "name": "my taylor_series", - "__solver_param": 0.1 - }, - { - "type": "HL_PHASE_TRANSFER", - "gas": { - "name": "gas", - "species": [ - { - "name": "H2O2", - "diffusion coefficient [m2 s-1]": 0.7 - } - ] - }, - "particle": { - "phase": "aqueous", - "solutes": [ - { - "name": "H2O2_aq" - } - ], - "solvent": [ - { - "name": "H2O" - } - ] - }, - "name": "my henry's law" - }, - { - "type": "SIMPOL_PHASE_TRANSFER", - "gas phase": "gas", - "gas-phase species": [ - { - "name": "ethanol" - } - ], - "condensed phase": "aqueous", - "condensed-phase species": [ - { - "name": "ethanol_aq" - } - ], - "B": [ - -1.97E+03, - 2.91E+00, - 1.96E-03, - -4.96E-01 - ], - "name": "my simpol" - }, - { - "type": "AQUEOUS_EQUILIBRIUM", - "condensed phase": "aqueous", - "condensed-phase water": "H2O", - "A": 1.14e-2, - "C": 2300.0, - "k_reverse": 0.32, - "reactants": [ - { - "name": "A", - "coefficient": 2 - } - ], - "products": [ - { - "name": "B", - "coefficient": 1 - }, - { - "name": "C", - "coefficient": 1 - } - ], - "name": "my aqueous eq" - }, - { - "type": "CONDENSED_PHASE_ARRHENIUS", - "condensed phase": "aqueous", - "A": 123.45, - "Ea": 123.45, - "B": 1.3, - "D": 300.0, - "E": 0.6E-5, - "reactants": [ - { - "name": "H2O2_aq", - "coefficient": 1 - }, - { - "name": "H2O", - "coefficient": 1 - } - ], - "products": [ - { - "name": "ethanol_aq", - "coefficient": 1 - } - ], - "name": "my condensed arrhenius" - }, - { - "type": "CONDENSED_PHASE_ARRHENIUS", - "condensed phase": "aqueous", - "A": 123.45, - "C": 123.45, - "B": 1.3, - "D": 300.0, - "E": 0.6E-5, - "reactants": [ - { - "name": "H2O2_aq", - "coefficient": 1 - }, - { - "name": "H2O", - "coefficient": 1 - } - ], - "products": [ - { - "name": "ethanol_aq", - "coefficient": 1 - } - ], - "name": "my other condensed arrhenius" - }, - { - "type": "CONDENSED_PHASE_PHOTOLYSIS", - "condensed phase": "aqueous", - "reactants": [ - { - "name": "H2O2_aq", - "coefficient": 1 - } - ], - "products": [ - { - "name": "ethanol_aq", - "coefficient": 1 - } - ], - "scaling factor": 12.3, - "name": "condensed photo B" - }, - { - "type": "EMISSION", - "gas phase": "gas", - "products": [ - { - "name": "B", - "coefficient": 1 - } - ], - "name": "my emission", - "scaling factor": 12.3 - }, - { - "type": "FIRST_ORDER_LOSS", - "gas phase": "gas", - "reactants": [ - { - "name": "C", - "coefficient": 1 - } - ], - "name": "my first order loss", - "scaling factor": 12.3 - }, - { - "type": "PHOTOLYSIS", - "gas phase": "gas", - "reactants": [ - { - "name": "B", - "coefficient": 1 - } - ], - "products": [ - { - "name": "C", - "coefficient": 1 - } - ], - "name": "photo B", - "scaling factor": 12.3 - }, - { - "type": "SURFACE", - "gas phase": "gas", - "gas-phase species": [ - { - "name": "A", - "coefficient": 1 - } - ], - "reaction probability": 2.0e-2, - "gas-phase products": [ - { - "name": "B", - "coefficient": 1 - }, - { - "name": "C", - "coefficient": 1 - } - ], - "condensed phase": "surface reacting phase", - "name": "my surface" - }, - { - "type": "TROE", - "gas phase": "gas", - "reactants": [ - { - "name": "B", - "coefficient": 1 - }, - { - "name": "M", - "coefficient": 1 - } - ], - "products": [ - { - "name": "C", - "coefficient": 1 - } - ], - "k0_A": 1.2e-12, - "k0_B": 167, - "k0_C": 3, - "kinf_A": 136, - "kinf_B": 5, - "kinf_C": 24, - "Fc": 0.9, - "N": 0.8, - "name": "my troe" - }, - { - "type": "TERNARY_CHEMICAL_ACTIVATION", - "gas phase": "gas", - "name": "my ternary chemical activation", - "reactants": [ - { - "name": "A", - "coefficient": 1 - }, - { - "name": "B", - "coefficient": 1 - } - ], - "products": [ - { - "name": "A", - "coefficient": 0.5 - }, - { - "name": "C", - "coefficient": 0.0 - } - ], - "k0_A": 32.1, - "k0_B": -2.3, - "k0_C": 102.3, - "kinf_A": 63.4, - "kinf_B": -1.3, - "kinf_C": 908.5, - "Fc": 1.3, - "N": 32.1 - }, - { - "type": "BRANCHED_NO_RO2", - "gas phase": "gas", - "reactants": [ - { - "name": "A", - "coefficient": 1 - } - ], - "alkoxy products": [ - { - "name": "B", - "coefficient": 1 - } - ], - "nitrate products": [ - { - "name": "C", - "coefficient": 1 - } - ], - "X": 1.2e-4, - "Y": 167, - "a0": 0.15, - "n": 9, - "name": "my branched" - }, - { - "gas phase": "gas", - "name": "my tunneling", - "type": "TUNNELING", - "A": 123.45, - "B": 1200.0, - "C": 1.0e8, - "reactants": [ - { - "name": "B", - "coefficient": 1 - } - ], - "products": [ - { - "name": "C", - "coefficient": 1 - } - ] - }, - { - "type": "WET_DEPOSITION", - "condensed phase": "aqueous", - "name": "rxn cloud", - "scaling factor": 12.3 - }, - { - "type": "ARRHENIUS", - "gas phase": "gas", - "reactants": [ - { - "name": "B", - "coefficient": 1 - } - ], - "products": [ - { - "name": "C", - "coefficient": 1 - } - ], - "A": 32.1, - "B": -2.3, - "C": 102.3, - "D": 63.4, - "E": -1.3, - "name": "my arrhenius" - }, - { - "type": "ARRHENIUS", - "gas phase": "gas", - "reactants": [ - { - "name": "A", - "coefficient": 1 - } - ], - "products": [ - { - "name": "B", - "coefficient": 1.2 - } - ], - "A": 29.3, - "B": -1.5, - "Ea": 101.2, - "D": 82.6, - "E": -0.98, - "name": "my other arrhenius" - }, - { - "type": "USER_DEFINED", - "gas phase": "gas", - "reactants": [ - { - "name": "A", - "coefficient": 1 - }, - { - "name": "B", - "coefficient": 1 - } - ], - "products": [ - { - "name": "C", - "coefficient": 1.3 - } - ], - "name": "my user defined", - "scaling factor": 12.3 - } - ] -} \ No newline at end of file diff --git a/examples/development/full_configuration.yaml b/examples/development/full_configuration.yaml deleted file mode 100644 index 4d259d07..00000000 --- a/examples/development/full_configuration.yaml +++ /dev/null @@ -1,358 +0,0 @@ -version: 2.0.0 -name: Full Configuration -species: - - name: A - __absolute tolerance: 1.0e-30 - - name: B - constant concentration [mol m-3]: 1.0e19 - - name: C - is third body: true - - name: M - - name: H2O2 - HLC(298K) [mol m-3 Pa-1]: 1.011596348 - HLC exponential factor [K]: 6340 - diffusion coefficient [m2 s-1]: 1.46E-05 - N star: 1.74 - molecular weight [kg mol-1]: 0.0340147 - density [kg m-3]: 1000.0 - constant mixing ratio [mol mol-1]: 1.0e-6 - __absolute tolerance: 1.0e-10 - - name: ethanol - diffusion coefficient [m2 s-1]: 0.95E-05 - N star: 2.55 - molecular weight [kg mol-1]: 0.04607 - __absolute tolerance: 1.0e-20 - - name: ethanol_aq - molecular weight [kg mol-1]: 0.04607 - density [kg m-3]: 1000.0 - __absolute tolerance: 1.0e-20 - - name: H2O2_aq - molecular weight [kg mol-1]: 0.0340147 - density [kg m-3]: 1000.0 - __absolute tolerance: 1.0e-10 - - name: H2O - density [kg m-3]: 1000.0 - molecular weight [kg mol-1]: 0.01801 - - name: aerosol stuff - molecular weight [kg mol-1]: 0.5 - density [kg m-3]: 1000.0 - __absolute tolerance: 1.0e-20 - - name: more aerosol stuff - molecular weight [kg mol-1]: 0.2 - density [kg m-3]: 1000.0 - __absolute tolerance: 1.0e-20 - -phases: - - name: gas - species: - - name: A - - name: B - - name: C - - name: ethanol - - name: H2O2 - - name: M - - name: aqueous - species: - - name: A - - name: B - - name: C - - name: H2O2_aq - - name: ethanol_aq - - name: H2O - - name: surface reacting phase - species: - - name: aerosol stuff - - name: more aerosol stuff - - name: organic - species: - - name: B - - name: C - -models: - - name: gas - type: GAS_PHASE - phase: gas - - name: aqueous - type: MODAL - modes: - - name: aitken - geometric mean diameter [m]: 2.6e-8 - geometric standard deviation: 1.6 - phase: aqueous - - name: accumulation - geometric mean diameter [m]: 1.1e-7 - geometric standard deviation: 1.8 - phase: organic - -reactions: - - type: TAYLOR_SERIES - gas phase: gas - reactants: - - name: A - coefficient: 1 - products: - - name: B - coefficient: 1.2 - - name: C - coefficient: 0.3 - A: 32.1 - B: -2.3 - C: 102.3 - D: 63.4 - E: -1.3 - taylor coefficients: - - 1.0 - - 2.0 - - 3.0 - name: my taylor_series - __solver_param: 0.1 - - - type: HL_PHASE_TRANSFER - gas: - name: gas - species: - - name: H2O2 - diffusion coefficient [m2 s-1]: 0.7 - particle: - phase: aqueous - solutes: - - name: H2O2_aq - solvent: - - name: H2O - name: my henry's law - - - type: SIMPOL_PHASE_TRANSFER - gas phase: gas - gas-phase species: - - name: ethanol - condensed phase: aqueous - condensed-phase species: - - name: ethanol_aq - B: - - -1.97E+03 - - 2.91E+00 - - 1.96E-03 - - -4.96E-01 - name: my simpol - - - type: AQUEOUS_EQUILIBRIUM - condensed phase: aqueous - condensed-phase water: H2O - A: 1.14e-2 - C: 2300.0 - k_reverse: 0.32 - reactants: - - name: A - coefficient: 2 - products: - - name: B - coefficient: 1 - - name: C - coefficient: 1 - name: my aqueous eq - - - type: CONDENSED_PHASE_ARRHENIUS - condensed phase: aqueous - A: 123.45 - Ea: 123.45 - B: 1.3 - D: 300.0 - E: 0.6E-5 - reactants: - - name: H2O2_aq - coefficient: 1 - - name: H2O - coefficient: 1 - products: - - name: ethanol_aq - coefficient: 1 - name: my condensed arrhenius - - - type: CONDENSED_PHASE_ARRHENIUS - condensed phase: aqueous - A: 123.45 - C: 123.45 - B: 1.3 - D: 300.0 - E: 0.6E-5 - reactants: - - name: H2O2_aq - coefficient: 1 - - name: H2O - coefficient: 1 - products: - - name: ethanol_aq - coefficient: 1 - name: my other condensed arrhenius - - - type: CONDENSED_PHASE_PHOTOLYSIS - condensed phase: aqueous - reactants: - - name: H2O2_aq - coefficient: 1 - products: - - name: ethanol_aq - coefficient: 1 - scaling factor: 12.3 - name: condensed photo B - - - type: EMISSION - gas phase: gas - products: - - name: B - coefficient: 1 - name: my emission - scaling factor: 12.3 - - - type: FIRST_ORDER_LOSS - gas phase: gas - reactants: - - name: C - coefficient: 1 - name: my first order loss - scaling factor: 12.3 - - - type: PHOTOLYSIS - gas phase: gas - reactants: - - name: B - coefficient: 1 - products: - - name: C - coefficient: 1 - name: photo B - scaling factor: 12.3 - - - type: SURFACE - gas phase: gas - gas-phase species: - - name: A - coefficient: 1 - reaction probability: 2.0e-2 - gas-phase products: - - name: B - coefficient: 1 - - name: C - coefficient: 1 - condensed phase: surface reacting phase - name: my surface - - - type: TROE - gas phase: gas - reactants: - - name: B - coefficient: 1 - - name: M - coefficient: 1 - products: - - name: C - coefficient: 1 - k0_A: 1.2e-12 - k0_B: 167 - k0_C: 3 - kinf_A: 136 - kinf_B: 5 - kinf_C: 24 - Fc: 0.9 - N: 0.8 - name: my troe - - - type: TERNARY_CHEMICAL_ACTIVATION - gas phase: gas - name: my ternary chemical activation - reactants: - - name: A - coefficient: 1 - - name: B - coefficient: 1 - products: - - name: A - coefficient: 0.5 - - name: C - coefficient: 0.0 - k0_A: 32.1 - k0_B: -2.3 - k0_C: 102.3 - kinf_A: 63.4 - kinf_B: -1.3 - kinf_C: 908.5 - Fc: 1.3 - N: 32.1 - - - type: BRANCHED_NO_RO2 - gas phase: gas - reactants: - - name: A - coefficient: 1 - alkoxy products: - - name: B - coefficient: 1 - nitrate products: - - name: C - coefficient: 1 - X: 1.2e-4 - Y: 167 - a0: 0.15 - n: 9 - name: my branched - - - type: TUNNELING - gas phase: gas - name: my tunneling - A: 123.45 - B: 1200.0 - C: 1.0e8 - reactants: - - name: B - coefficient: 1 - products: - - name: C - coefficient: 1 - - - type: WET_DEPOSITION - condensed phase: aqueous - name: rxn cloud - scaling factor: 12.3 - - - type: ARRHENIUS - gas phase: gas - reactants: - - name: B - coefficient: 1 - products: - - name: C - coefficient: 1 - A: 32.1 - B: -2.3 - C: 102.3 - D: 63.4 - E: -1.3 - name: my arrhenius - - - type: ARRHENIUS - gas phase: gas - reactants: - - name: A - coefficient: 1 - products: - - name: B - coefficient: 1.2 - A: 29.3 - B: -1.5 - Ea: 101.2 - D: 82.6 - E: -0.98 - name: my other arrhenius - - - type: USER_DEFINED - gas phase: gas - reactants: - - name: A - coefficient: 1 - - name: B - coefficient: 1 - products: - - name: C - coefficient: 1.3 - name: my user defined - scaling factor: 12.3 diff --git a/examples/v1/full_configuration.json b/examples/v1/full_configuration.json index bc61afd0..c67b108b 100644 --- a/examples/v1/full_configuration.json +++ b/examples/v1/full_configuration.json @@ -40,6 +40,7 @@ {"name": "A"}, {"name": "B"}, {"name": "C"}, + {"name": "M"}, { "name": "ethanol", "diffusion coefficient [m2 s-1]": 2.1e-5 @@ -154,21 +155,21 @@ "N": 32.1, "reactants": [ { - "species name": "bar", + "species name": "A", "coefficient": 1 }, { - "species name": "baz", + "species name": "B", "coefficient": 1 } ], "products": [ { - "species name": "bar", + "species name": "B", "coefficient": 0.5 }, { - "species name": "foo", + "species name": "C", "coefficient": 0.3 } ] @@ -308,6 +309,24 @@ "coefficient": 1 } ] + }, + { + "type": "LAMBDA_RATE_CONSTANT", + "name": "my lambda rate constant", + "gas phase": "gas", + "lambda function": "[](double T, double P) { return 1.2e-5 * exp(-500.0 / T); }", + "reactants": [ + { + "species name": "B", + "coefficient": 1 + } + ], + "products": [ + { + "species name": "C", + "coefficient": 1 + } + ] } ] } \ No newline at end of file diff --git a/examples/v1/full_configuration.yaml b/examples/v1/full_configuration.yaml index eeed8016..8a51f858 100644 --- a/examples/v1/full_configuration.yaml +++ b/examples/v1/full_configuration.yaml @@ -23,6 +23,7 @@ phases: - name: A - name: B - name: C + - name: M - name: ethanol diffusion coefficient [m2 s-1]: 2.1e-5 - name: H2O2 @@ -93,14 +94,14 @@ reactions: Fc: 1.3 N: 32.1 reactants: - - species name: bar + - species name: A coefficient: 1 - - species name: baz + - species name: B coefficient: 1 products: - - species name: bar + - species name: B coefficient: 0.5 - - species name: foo + - species name: C coefficient: 0.3 - type: BRANCHED_NO_RO2 name: my branched @@ -182,6 +183,16 @@ reactions: - 0.1 - -0.01 gas phase: gas + reactants: + - species name: B + coefficient: 1 + products: + - species name: C + coefficient: 1 + - type: LAMBDA_RATE_CONSTANT + name: my lambda rate constant + gas phase: gas + lambda function: "[](double T, double P) { return 1.2e-5 * exp(-500.0 / T); }" reactants: - species name: B coefficient: 1 diff --git a/include/mechanism_configuration/development/mechanism.hpp b/include/mechanism_configuration/development/mechanism.hpp deleted file mode 100644 index 01ec4ccd..00000000 --- a/include/mechanism_configuration/development/mechanism.hpp +++ /dev/null @@ -1,76 +0,0 @@ -// Copyright (C) 2023–2026 University Corporation for Atmospheric Research -// University of Illinois at Urbana-Champaign -// SPDX-License-Identifier: Apache-2.0 - -#pragma once - -#include -#include -#include -#include - -#include - -#include -#include - -namespace mechanism_configuration -{ - namespace development - { - namespace types - { - - /// @brief Represents a full mechanism definition - struct Mechanism : public ::mechanism_configuration::Mechanism - { - /// @brief Mechanism name (optional) - std::string name; - /// @brief Species list - std::vector species; - /// @brief Phases list - std::vector phases; - /// @brief Represents a collection of different reaction types, each stored in a vector - /// corresponding to a specific mechanism - Reactions reactions; - /// @brief Represents a general model (optional) - Models models; - }; - - } // namespace types - - class Parser - { - public: - Parser() = default; - - /// @brief Load a YAML file and return its root node - /// @throws std::runtime_error If the file is missing, not a regular file, or cannot be parsed - YAML::Node FileToYaml(const std::filesystem::path& config_path); - - /// @brief Validates mechanism YAML node. - /// @param object The YAML node to validate - /// @param read_from_config_file Whether to use the provided config path or the default - /// @return A collection of validation errors; empty if the node is valid - Errors Validate(const YAML::Node& object, bool read_from_config_file = true); - - /// @brief Constructs a Mechanism object from the provided YAML node - /// @note Must be called only after successful validation - types::Mechanism Parse(const YAML::Node& object); - - inline void SetConfigPath(const std::string& config_path) - { - config_path_ = config_path; - } - - private: - std::string config_path_; - - inline void SetDefaultConfigPath() - { - config_path_ = ""; - } - }; - - } // namespace development -} // namespace mechanism_configuration \ No newline at end of file diff --git a/include/mechanism_configuration/development/model_parsers.hpp b/include/mechanism_configuration/development/model_parsers.hpp deleted file mode 100644 index 7952f693..00000000 --- a/include/mechanism_configuration/development/model_parsers.hpp +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright (C) 2023–2026 University Corporation for Atmospheric Research -// University of Illinois at Urbana-Champaign -// SPDX-License-Identifier: Apache-2.0 - -#pragma once - -#include -#include -#include -#include - -#include - -#include - -namespace mechanism_configuration -{ - namespace development - { - /// @brief Abstract interface for model parsers - class IModelParser - { - public: - /// @brief Validates a YAML node representing a model - /// @param object The YAML node containing model information - /// @param existing_phases A list of chemical phases - /// @return A list of any validation errors encountered - virtual Errors Validate(const YAML::Node& object, const std::vector& existing_phases) = 0; - - /// @brief Parses a YAML node representing a model and populate the models object - /// @param object The YAML node containing model information - /// @param models The container to which the parsed models will be added - virtual void Parse(const YAML::Node& object, types::Models& models) = 0; - - /// @brief Destructor - virtual ~IModelParser() = default; - }; - - /// @brief Parser for gas-phase models - class GasModelParser : public IModelParser - { - public: - Errors Validate(const YAML::Node& object, const std::vector& existing_phases) override; - - void Parse(const YAML::Node& object, types::Models& models) override; - }; - - /// @brief Parser for modal aerosol models - class ModalModelParser : public IModelParser - { - public: - Errors Validate(const YAML::Node& object, const std::vector& existing_phases) override; - - void Parse(const YAML::Node& object, types::Models& models) override; - }; - - /// @brief Returns a static map of model type keys to their parser instances - inline std::map>& GetModelParserMap() - { - static std::map> model_parsers = [] - { - std::map> map; - map[validation::GasModel_key] = std::make_unique(); - map[validation::ModalModel_key] = std::make_unique(); - return map; - }(); - - return model_parsers; - } - - } // namespace development -} // namespace mechanism_configuration \ No newline at end of file diff --git a/include/mechanism_configuration/development/model_types.hpp b/include/mechanism_configuration/development/model_types.hpp deleted file mode 100644 index 12a04d9a..00000000 --- a/include/mechanism_configuration/development/model_types.hpp +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright (C) 2023–2026 University Corporation for Atmospheric Research -// University of Illinois at Urbana-Champaign -// SPDX-License-Identifier: Apache-2.0 - -#pragma once - -#include -#include -#include - -namespace mechanism_configuration -{ - namespace development - { - namespace types - { - - /// @brief Represents gas model - struct GasModel - { - std::string name; - std::string type; - std::string phase; - /// @brief Unknown properties, prefixed with two underscores (__) - std::unordered_map unknown_properties; - }; - - /// @brief Represents a single mode with log-normal size distribution - struct Mode - { - std::string name; - double geometric_mean_diameter; - double geometric_standard_deviation; - std::string phase; - /// @brief Unknown properties, prefixed with two underscores (__) - std::unordered_map unknown_properties; - }; - - /// @brief Models a collection of multiple modes - struct ModalModel - { - std::string name; - std::string type; - std::vector modes; - /// @brief Unknown properties, prefixed with two underscores (__) - std::unordered_map unknown_properties; - }; - - /// @brief Represents a collection of different model types - struct Models - { - GasModel gas_model; - ModalModel modal_model; - }; - } // namespace types - } // namespace development -} // namespace mechanism_configuration diff --git a/include/mechanism_configuration/development/reaction_parsers.hpp b/include/mechanism_configuration/development/reaction_parsers.hpp deleted file mode 100644 index f70b9fb6..00000000 --- a/include/mechanism_configuration/development/reaction_parsers.hpp +++ /dev/null @@ -1,273 +0,0 @@ -// Copyright (C) 2023–2026 University Corporation for Atmospheric Research -// University of Illinois at Urbana-Champaign -// SPDX-License-Identifier: Apache-2.0 - -#pragma once - -#include -#include -#include -#include - -#include - -#include - -namespace mechanism_configuration -{ - namespace development - { - - /// @brief Abstract interface for reaction parsers - class IReactionParser - { - public: - /// @brief Validates a YAML node representing a chemical reaction - /// @param object The YAML node containing reaction information - /// @param existing_species A list of species previously defined in the mechanism - /// @param existing_phases A list of chemical phases relevant to the reaction - /// @return A list of any validation errors encountered - virtual Errors Validate( - const YAML::Node& object, - const std::vector& existing_species, - const std::vector& existing_phases) = 0; - - /// @brief Parses a YAML node representing a chemical reaction - /// @param object The YAML node containing reaction information - /// @param reactions The container to which the parsed reactions will be added - virtual void Parse(const YAML::Node& object, types::Reactions& reactions) = 0; - - /// @brief Destructor - virtual ~IReactionParser() = default; - }; - - class ArrheniusParser : public IReactionParser - { - public: - Errors Validate( - const YAML::Node& object, - const std::vector& existing_species, - const std::vector& existing_phases) override; - - void Parse(const YAML::Node& object, types::Reactions& reactions) override; - }; - - class BranchedParser : public IReactionParser - { - public: - Errors Validate( - const YAML::Node& object, - const std::vector& existing_species, - const std::vector& existing_phases) override; - - void Parse(const YAML::Node& object, types::Reactions& reactions) override; - }; - - class CondensedPhaseArrheniusParser : public IReactionParser - { - public: - Errors Validate( - const YAML::Node& object, - const std::vector& existing_species, - const std::vector& existing_phases) override; - - void Parse(const YAML::Node& object, types::Reactions& reactions) override; - }; - - class CondensedPhasePhotolysisParser : public IReactionParser - { - public: - Errors Validate( - const YAML::Node& object, - const std::vector& existing_species, - const std::vector& existing_phases) override; - - void Parse(const YAML::Node& object, types::Reactions& reactions) override; - }; - - class EmissionParser : public IReactionParser - { - public: - Errors Validate( - const YAML::Node& object, - const std::vector& existing_species, - const std::vector& existing_phases) override; - - void Parse(const YAML::Node& object, types::Reactions& reactions) override; - }; - - class FirstOrderLossParser : public IReactionParser - { - public: - Errors Validate( - const YAML::Node& object, - const std::vector& existing_species, - const std::vector& existing_phases) override; - - void Parse(const YAML::Node& object, types::Reactions& reactions) override; - }; - - class SimpolPhaseTransferParser : public IReactionParser - { - public: - Errors Validate( - const YAML::Node& object, - const std::vector& existing_species, - const std::vector& existing_phases) override; - - void Parse(const YAML::Node& object, types::Reactions& reactions) override; - }; - - class AqueousEquilibriumParser : public IReactionParser - { - public: - Errors Validate( - const YAML::Node& object, - const std::vector& existing_species, - const std::vector& existing_phases) override; - - void Parse(const YAML::Node& object, types::Reactions& reactions) override; - }; - - class WetDepositionParser : public IReactionParser - { - public: - Errors Validate( - const YAML::Node& object, - const std::vector& existing_species, - const std::vector& existing_phases) override; - - void Parse(const YAML::Node& object, types::Reactions& reactions) override; - }; - - class HenrysLawParser : public IReactionParser - { - public: - Errors Validate( - const YAML::Node& object, - const std::vector& existing_species, - const std::vector& existing_phases) override; - - void Parse(const YAML::Node& object, types::Reactions& reactions) override; - }; - - class PhotolysisParser : public IReactionParser - { - public: - Errors Validate( - const YAML::Node& object, - const std::vector& existing_species, - const std::vector& existing_phases) override; - - void Parse(const YAML::Node& object, types::Reactions& reactions) override; - }; - - class SurfaceParser : public IReactionParser - { - public: - Errors Validate( - const YAML::Node& object, - const std::vector& existing_species, - const std::vector& existing_phases) override; - - void Parse(const YAML::Node& object, types::Reactions& reactions) override; - }; - - class TaylorSeriesParser : public IReactionParser - { - public: - Errors Validate( - const YAML::Node& object, - const std::vector& existing_species, - const std::vector& existing_phases) override; - - void Parse(const YAML::Node& object, types::Reactions& reactions) override; - }; - - class TroeParser : public IReactionParser - { - public: - Errors Validate( - const YAML::Node& object, - const std::vector& existing_species, - const std::vector& existing_phases) override; - - void Parse(const YAML::Node& object, types::Reactions& reactions) override; - }; - - class TernaryChemicalActivationParser : public IReactionParser - { - public: - Errors Validate( - const YAML::Node& object, - const std::vector& existing_species, - const std::vector& existing_phases) override; - - void Parse(const YAML::Node& object, types::Reactions& reactions) override; - }; - - class TunnelingParser : public IReactionParser - { - public: - Errors Validate( - const YAML::Node& object, - const std::vector& existing_species, - const std::vector& existing_phases) override; - - void Parse(const YAML::Node& object, types::Reactions& reactions) override; - }; - - class UserDefinedParser : public IReactionParser - { - public: - Errors Validate( - const YAML::Node& object, - const std::vector& existing_species, - const std::vector& existing_phases) override; - - void Parse(const YAML::Node& object, types::Reactions& reactions) override; - }; - - class LambdaRateConstantParser : public IReactionParser - { - public: - Errors Validate( - const YAML::Node& object, - const std::vector& existing_species, - const std::vector& existing_phases) override; - - void Parse(const YAML::Node& object, types::Reactions& reactions) override; - }; - - /// @brief Returns a static map of reaction type keys to their parser instances - inline std::map>& GetReactionParserMap() - { - static std::map> reaction_parsers = [] - { - std::map> map; - map[validation::Arrhenius_key] = std::make_unique(); - map[validation::HenrysLaw_key] = std::make_unique(); - map[validation::WetDeposition_key] = std::make_unique(); - map[validation::AqueousPhaseEquilibrium_key] = std::make_unique(); - map[validation::SimpolPhaseTransfer_key] = std::make_unique(); - map[validation::FirstOrderLoss_key] = std::make_unique(); - map[validation::Emission_key] = std::make_unique(); - map[validation::CondensedPhasePhotolysis_key] = std::make_unique(); - map[validation::Photolysis_key] = std::make_unique(); - map[validation::Surface_key] = std::make_unique(); - map[validation::TaylorSeries_key] = std::make_unique(); - map[validation::Tunneling_key] = std::make_unique(); - map[validation::Branched_key] = std::make_unique(); - map[validation::Troe_key] = std::make_unique(); - map[validation::TernaryChemicalActivation_key] = std::make_unique(); - map[validation::CondensedPhaseArrhenius_key] = std::make_unique(); - map[validation::UserDefined_key] = std::make_unique(); - map[validation::LambdaRateConstant_key] = std::make_unique(); - return map; - }(); - - return reaction_parsers; - } - - } // namespace development -} // namespace mechanism_configuration diff --git a/include/mechanism_configuration/development/reaction_types.hpp b/include/mechanism_configuration/development/reaction_types.hpp deleted file mode 100644 index a820537c..00000000 --- a/include/mechanism_configuration/development/reaction_types.hpp +++ /dev/null @@ -1,402 +0,0 @@ -// Copyright (C) 2023–2026 University Corporation for Atmospheric Research -// University of Illinois at Urbana-Champaign -// SPDX-License-Identifier: Apache-2.0 - -#pragma once - -#include - -#include -#include -#include -#include -#include - -namespace mechanism_configuration -{ - namespace development - { - namespace types - { - - struct Arrhenius - { - /// @brief Pre-exponential factor [(mol m−3)^(−(𝑛−1)) s−1] - double A{ 1 }; - /// @brief Unitless exponential factor - double B{ 0 }; - /// @brief Activation threshold, expected to be the negative activation energy divided by the boltzman constant - /// [-E_a / k_b), K] - double C{ 0 }; - /// @brief A factor that determines temperature dependence [K] - double D{ 300 }; - /// @brief A factor that determines pressure dependence [Pa-1] - double E{ 0 }; - /// @brief A list of reactants - std::vector reactants; - /// @brief A list of products - std::vector products; - /// @brief An identifier, optional, uniqueness not enforced - std::string name; - /// @brief An identifier indicating which gas phase this reaction takes place in - std::string gas_phase; - /// @brief Unknown properties, prefixed with two underscores (__) - std::unordered_map unknown_properties; - }; - - struct Branched - { - /// @brief pre-exponential factor - double X; - /// @brief exponential factor - double Y; - /// @brief branching factor - double a0; - /// @brief number of heavy atoms in the RO2 reacting species (excluding the peroxy moiety) - int n; - /// @brief A list of reactants - std::vector reactants; - /// @brief A list of nitrate products - std::vector nitrate_products; - /// @brief A list of alkoxy products - std::vector alkoxy_products; - /// @brief An identifier, optional, uniqueness not enforced - std::string name; - /// @brief An identifier indicating which gas phase this reaction takes place in - std::string gas_phase; - /// @brief Unknown properties, prefixed with two underscores (__) - std::unordered_map unknown_properties; - }; - - struct CondensedPhaseArrhenius - { - /// @brief Pre-exponential factor [(mol m−3)^(−(𝑛−1)) s−1] - double A{ 1 }; - /// @brief Unitless exponential factor - double B{ 0 }; - /// @brief Activation threshold, expected to be the negative activation energy divided by the boltzman constant - /// [-E_a / k_b), K] - double C{ 0 }; - /// @brief A factor that determines temperature dependence [K] - double D{ 300 }; - /// @brief A factor that determines pressure dependence [Pa-1] - double E{ 0 }; - /// @brief A list of reactants - std::vector reactants; - /// @brief A list of products - std::vector products; - /// @brief An identifier, optional, uniqueness not enforced - std::string name; - /// @brief An identifier for the condensed phase where this reaction occurs - std::string condensed_phase; - /// @brief Unknown properties, prefixed with two underscores (__) - std::unordered_map unknown_properties; - }; - - struct CondensedPhasePhotolysis - { - /// @brief Scaling factor to apply to user-provided rate constants - double scaling_factor{ 1.0 }; - /// @brief A single reactant - ReactionComponent reactants; - /// @brief A list of products - std::vector products; - /// @brief An identifier, optional, uniqueness not enforced - std::string name; - /// @brief An identifier for the condensed phase where this reaction occurs - std::string condensed_phase; - /// @brief Unknown properties, prefixed with two underscores (__) - std::unordered_map unknown_properties; - }; - - struct Emission - { - /// @brief Scaling factor to apply to user-provided rate constants - double scaling_factor{ 1.0 }; - /// @brief A list of products - std::vector products; - /// @brief An identifier, optional, uniqueness not enforced - std::string name; - /// @brief An identifier indicating which gas phase this reaction takes place in - std::string gas_phase; - /// @brief Unknown properties, prefixed with two underscores (__) - std::unordered_map unknown_properties; - }; - - struct FirstOrderLoss - { - /// @brief Scaling factor to apply to user-provided rate constants - double scaling_factor{ 1.0 }; - /// @brief A single reactant - ReactionComponent reactants; - /// @brief An identifier, optional, uniqueness not enforced - std::string name; - /// @brief An identifier indicating which gas phase this reaction takes place in - std::string gas_phase; - /// @brief Unknown properties, prefixed with two underscores (__) - std::unordered_map unknown_properties; - }; - - struct SimpolPhaseTransfer - { - /// @brief An identifier indicating which gas phase this reaction takes place in - std::string gas_phase; - /// @brief The species in the gas phase participating in this reaction - std::vector gas_phase_species; - /// @brief An identifier for the condensed phase where this reaction occurs - std::string condensed_phase; - /// @brief The species in the condensed phase participating in this reaction - std::vector condensed_phase_species; - /// @brief An identifier, optional, uniqueness not enforced - std::string name; - /// @brief The 4 SIMPOL parameters - std::array B; - /// @brief Unknown properties, prefixed with two underscores (__) - std::unordered_map unknown_properties; - }; - - struct AqueousEquilibrium - { - /// @brief An identifier, optional, uniqueness not enforced - std::string name; - /// @brief An identifier for the condensed phase where this reaction occurs - std::string condensed_phase; - /// @brief Name for condensed-phase water - std::string condensed_phase_water; - /// @brief A list of reactants - std::vector reactants; - /// @brief A list of products - std::vector products; - /// @brief Pre-exponential factor (s-1) - double A{ 1 }; - /// @brief A constant - double C{ 0 }; - /// @brief Reverse reation rate constant (s-1) - double k_reverse{ 0 }; - /// @brief Unknown properties, prefixed with two underscores (__) - std::unordered_map unknown_properties; - }; - - struct WetDeposition - { - /// @brief Scaling factor to apply to user-provided rate constants - double scaling_factor{ 1.0 }; - /// @brief An identifier, optional, uniqueness not enforced - std::string name; - /// @brief An identifier for the condensed phase where this reaction occurs - std::string condensed_phase; - /// @brief Unknown properties, prefixed with two underscores (__) - std::unordered_map unknown_properties; - }; - - struct HenrysLaw - { - /// @brief An identifier, optional, uniqueness not enforced - std::string name; - /// @brief Represents the composition of a gas mixture - Phase gas; - /// @brief Represents a particle within a solution, including its phase and chemical composition - Particle particle; - /// @brief Unknown properties, prefixed with two underscores (__) - std::unordered_map unknown_properties; - }; - - struct Photolysis - { - /// @brief Scaling factor to apply to user-provided rate constants - double scaling_factor{ 1.0 }; - /// @brief A single reactant - ReactionComponent reactants; - /// @brief A list of products - std::vector products; - /// @brief An identifier, optional, uniqueness not enforced - std::string name; - /// @brief An identifier indicating which gas phase this reaction takes place in - std::string gas_phase; - /// @brief Unknown properties, prefixed with two underscores (__) - std::unordered_map unknown_properties; - }; - - struct Surface - { - /// @brief Reaction probability (0-1) [unitless] - double reaction_probability{ 1.0 }; - /// @brief A single gas-phase species - ReactionComponent gas_phase_species; - /// @brief A list of products - std::vector gas_phase_products; - /// @brief An identifier, optional, uniqueness not enforced - std::string name; - /// @brief An identifier indicating which gas phase this reaction takes place in - std::string gas_phase; - /// @brief An identifier for the condensed phase where this reaction occurs - std::string condensed_phase; - /// @brief Unknown properties, prefixed with two underscores (__) - std::unordered_map unknown_properties; - }; - - struct TaylorSeries - { - /// @brief Pre-exponential factor [(mol m−3)^(−(𝑛−1)) s−1] - double A{ 1 }; - /// @brief Unitless exponential factor - double B{ 0 }; - /// @brief Activation threshold, expected to be the negative activation energy divided by the boltzman constant - /// [-E_a / k_b), K] - double C{ 0 }; - /// @brief A factor that determines temperature dependence [K] - double D{ 300 }; - /// @brief A factor that determines pressure dependence [Pa-1] - double E{ 0 }; - /// @brief An array of coefficients for the Taylor series expansion - std::vector taylor_coefficients{ 1.0 }; - /// @brief A list of reactants - std::vector reactants; - /// @brief A list of products - std::vector products; - /// @brief An identifier, optional, uniqueness not enforced - std::string name; - /// @brief An identifier indicating which gas phase this reaction takes place in - std::string gas_phase; - /// @brief Unknown properties, prefixed with two underscores (__) - std::unordered_map unknown_properties; - }; - - struct Troe - { - /// @brief low-pressure pre-exponential factor - double k0_A = 1.0; - /// @brief low-pressure temperature-scaling parameter - double k0_B = 0.0; - /// @brief low-pressure exponential factor - double k0_C = 0.0; - /// @brief high-pressure pre-exponential factor - double kinf_A = 1.0; - /// @brief high-pressure temperature-scaling parameter - double kinf_B = 0.0; - /// @brief high-pressure exponential factor - double kinf_C = 0.0; - /// @brief Troe F_c parameter - double Fc = 0.6; - /// @brief Troe N parameter - double N = 1.0; - /// @brief A list of reactants - std::vector reactants; - /// @brief A list of products - std::vector products; - /// @brief An identifier, optional, uniqueness not enforced - std::string name; - /// @brief An identifier indicating which gas phase this reaction takes place in - std::string gas_phase; - /// @brief Unknown properties, prefixed with two underscores (__) - std::unordered_map unknown_properties; - }; - - struct TernaryChemicalActivation - { - /// @brief low-pressure pre-exponential factor - double k0_A = 1.0; - /// @brief low-pressure temperature-scaling parameter - double k0_B = 0.0; - /// @brief low-pressure exponential factor - double k0_C = 0.0; - /// @brief high-pressure pre-exponential factor - double kinf_A = 1.0; - /// @brief high-pressure temperature-scaling parameter - double kinf_B = 0.0; - /// @brief high-pressure exponential factor - double kinf_C = 0.0; - /// @brief TernaryChemicalActivation F_c parameter - double Fc = 0.6; - /// @brief TernaryChemicalActivation N parameter - double N = 1.0; - /// @brief A list of reactants - std::vector reactants; - /// @brief A list of products - std::vector products; - /// @brief An identifier, optional, uniqueness not enforced - std::string name; - /// @brief An identifier indicating which gas phase this reaction takes place in - std::string gas_phase; - /// @brief Unknown properties, prefixed with two underscores (__) - std::unordered_map unknown_properties; - }; - - struct Tunneling - { - /// @brief Pre-exponential factor [(mol m−3)^(−(𝑛−1)) s−1] - double A = 1.0; - /// @brief Linear temperature-dependent parameter [K] - double B = 0.0; - /// @brief Cubed temperature-dependent parameter [K^3] - double C = 0.0; - /// @brief A list of reactants - std::vector reactants; - /// @brief A list of products - std::vector products; - /// @brief An identifier, optional, uniqueness not enforced - std::string name; - /// @brief An identifier indicating which gas phase this reaction takes place in - std::string gas_phase; - /// @brief Unknown properties, prefixed with two underscores (__) - std::unordered_map unknown_properties; - }; - - struct UserDefined - { - /// @brief Scaling factor to apply to user-provided rate constants - double scaling_factor{ 1.0 }; - /// @brief A list of reactants - std::vector reactants; - /// @brief A list of products - std::vector products; - /// @brief An identifier, optional, uniqueness not enforced - std::string name; - /// @brief An identifier indicating which gas phase this reaction takes place in - std::string gas_phase; - /// @brief Unknown properties, prefixed with two underscores (__) - std::unordered_map unknown_properties; - }; - - struct LambdaRateConstant - { - /// @brief A lambda function as a string, expected to be a function of temperature (T) and optionally pressure (P) - std::string lambda_function; - /// @brief A list of reactants - std::vector reactants; - /// @brief A list of products - std::vector products; - /// @brief An identifier, optional, uniqueness not enforced - std::string name; - /// @brief An identifier indicating which gas phase this reaction takes place in - std::string gas_phase; - /// @brief Unknown properties, prefixed with two underscores (__) - std::unordered_map unknown_properties; - }; - - /// @brief Represents a collection of different reaction types - struct Reactions - { - std::vector arrhenius; - std::vector branched; - std::vector condensed_phase_arrhenius; - std::vector condensed_phase_photolysis; - std::vector emission; - std::vector first_order_loss; - std::vector simpol_phase_transfer; - std::vector aqueous_equilibrium; - std::vector wet_deposition; - std::vector henrys_law; - std::vector photolysis; - std::vector surface; - std::vector taylor_series; - std::vector troe; - std::vector ternary_chemical_activation; - std::vector tunneling; - std::vector user_defined; - std::vector lambda_rate_constant; - }; - - } // namespace types - } // namespace development -} // namespace mechanism_configuration \ No newline at end of file diff --git a/include/mechanism_configuration/development/type_parsers.hpp b/include/mechanism_configuration/development/type_parsers.hpp deleted file mode 100644 index 080df5c3..00000000 --- a/include/mechanism_configuration/development/type_parsers.hpp +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright (C) 2023–2026 University Corporation for Atmospheric Research -// University of Illinois at Urbana-Champaign -// SPDX-License-Identifier: Apache-2.0 - -#pragma once - -#include -#include -#include -#include - -#include - -#include -#include - -namespace mechanism_configuration -{ - namespace development - { - /// @brief Parses a YAML node into a vector of Species - /// The input must be validated using ValidateSpecies(). - /// This function assumes the structure and types are correct. - /// @param objects YAML node representing species list - /// @return A vector of parsed species - std::vector ParseSpecies(const YAML::Node& objects); - - /// @brief Parses a YAML node into a vector of Phases - /// Extracts each phase's name and its associated species (including optional properties). - /// Assumes the input YAML has already been validated for required structure and keys. - /// @param objects YAML node representing phase list - /// @return A vector of parsed Phases - std::vector ParsePhases(const YAML::Node& objects); - - /// @brief Parses a YAML node into reaction components - /// @param object YAML node representing ReactionComponents - /// @param key Key of the sequence to parse - /// @return Vector of `types::ReactionComponent` with names, optional coefficients, and comments - std::vector ParseReactionComponents(const YAML::Node& object, const std::string& key); - - /// @brief Parses a single reaction component from a YAML node. - /// The parser performs no validation or error checking. - /// @param object YAML node representing ReactionComponents - /// @param key Key identifying the reaction component - /// @return The parsed `types::ReactionComponent`, or a default-constructed one if none found - types::ReactionComponent ParseReactionComponent(const YAML::Node& object, const std::string& key); - - /// @brief Parses a collection of YAML nodes into reaction objects - /// Iterates over the given YAML nodes, identifies the parser for each reaction type, - /// and populates a `types::Reactions` container with the parsed reactions. - /// @param objects YAML node containing multiple reaction definitions - /// @return A `types::Reactions` object with all successfully parsed reactions - types::Reactions ParseReactions(const YAML::Node& objects); - - /// @brief Parses a collection of YAML nodes into model objects - /// Iterates over the given YAML nodes, identifies the parser for each model type, - /// and populates a `types::Models` container with the parsed models. - /// @param objects YAML node containing multiple model definitions - /// @return A `types::Models` object with all successfully parsed models - types::Models ParseModels(const YAML::Node& objects); - - } // namespace development -} // namespace mechanism_configuration diff --git a/include/mechanism_configuration/development/type_validators.hpp b/include/mechanism_configuration/development/type_validators.hpp deleted file mode 100644 index f8c1593e..00000000 --- a/include/mechanism_configuration/development/type_validators.hpp +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright (C) 2023–2026 University Corporation for Atmospheric Research -// University of Illinois at Urbana-Champaign -// SPDX-License-Identifier: Apache-2.0 - -#pragma once - -#include -#include - -#include - -namespace mechanism_configuration -{ - namespace development - { - /// @brief Validates a list of species definitions from a YAML node. - /// This function checks each species object in the input YAML list to ensure that: - /// - All required keys are present - /// - Optional keys are properly handled - /// - No duplicate species names exist - /// @param species_list YAML node containing species entries - /// @return List of validation errors, or empty if all entries are valid - Errors ValidateSpecies(const YAML::Node& species_list); - - /// @brief Validates the structure and content of phase definitions in a YAML node. - /// Performs schema validation for each phase and its associated species. - /// - All required keys are present - /// - Detects duplicate species within a single phase - /// - Detects species not defined in the existing_species list - /// - Detects duplicate phase names - /// @param phases_list YAML node containing the list of phase entries - /// @param existing_species List of defined species to validate against - /// @return List of validation errors, or empty if all entries are valid - Errors ValidatePhases(const YAML::Node& phases_list, const std::vector& existing_species); - - /// @brief Validates the content of reactants or products definitions in a YAML node - /// @param list YAML node representing a sequence of reactants or products. - /// @return List of validation errors, or empty if all entries are valid - Errors ValidateReactantsOrProducts(const YAML::Node& object); - - /// @brief Validates a list of particle definitions in a YAML node - /// @param list YAML node containing particle - /// @return List of validation errors, or empty if all entries are valid - Errors ValidateParticles(const YAML::Node& list); - - /// @brief Validates a YAML list of reactions for type correctness and supported schema. - /// Performs a two-pass validation over the reaction list. The first pass checks that each - /// reaction has a defined and recognized type. The second pass validates the content of - /// reactions using their respective parser. - /// @param reactions_list YAML node containing the list of reactions - /// @param existing_species List of known species to validate species references - /// @param existing_phases List of known phases to validate phase references - /// @return list of validation errors, if any - Errors ValidateReactions( - const YAML::Node& reactions_list, - const std::vector& existing_species, - const std::vector& existing_phases); - - /// @brief Validates a list of model definitions in a YAML node - /// @param models_list YAML node containing the list of models - /// @param existing_phases List of known phases to validate phase references - /// @return list of validation errors, if any - Errors ValidateModels(const YAML::Node& models_list, const std::vector& existing_phases); - - } // namespace development -} // namespace mechanism_configuration \ No newline at end of file diff --git a/include/mechanism_configuration/development/types.hpp b/include/mechanism_configuration/development/types.hpp deleted file mode 100644 index bfc88fd3..00000000 --- a/include/mechanism_configuration/development/types.hpp +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright (C) 2023–2026 University Corporation for Atmospheric Research -// University of Illinois at Urbana-Champaign -// SPDX-License-Identifier: Apache-2.0 - -#pragma once - -#include - -#include -#include -#include -#include - -namespace mechanism_configuration -{ - namespace development - { - namespace types - { - - struct Species - { - std::string name; - std::optional absolute_tolerance; - std::optional diffusion_coefficient; - std::optional molecular_weight; - std::optional henrys_law_constant_298; - std::optional henrys_law_constant_exponential_factor; - std::optional n_star; - std::optional density; - std::optional tracer_type; - std::optional constant_concentration; - std::optional constant_mixing_ratio; - std::optional is_third_body; - /// @brief Unknown properties, prefixed with two underscores (__) - std::unordered_map unknown_properties; - Errors validate(); - }; - - struct PhaseSpecies - { - std::string name; - std::optional diffusion_coefficient; - /// @brief Unknown properties, prefixed with two underscores (__) - std::unordered_map unknown_properties; - }; - - struct Phase - { - std::string name; - std::vector species; - /// @brief Unknown properties, prefixed with two underscores (__) - std::unordered_map unknown_properties; - }; - - struct ReactionComponent - { - std::string name; - double coefficient{ 1.0 }; - /// @brief Unknown properties, prefixed with two underscores (__) - std::unordered_map unknown_properties; - }; - - struct Particle - { - /// @brief Describes the physical state of the particle - std::string phase; - /// @brief Lists the chemical species dissolved in the solvent - std::vector solutes; - /// @brief Specifies the liquid medium in which solutes are dissolved - ReactionComponent solvent; - /// @brief Unknown properties, prefixed with two underscores (__) - std::unordered_map unknown_properties; - }; - - } // namespace types - } // namespace development -} // namespace mechanism_configuration \ No newline at end of file diff --git a/include/mechanism_configuration/development/utils.hpp b/include/mechanism_configuration/development/utils.hpp deleted file mode 100644 index 2009a327..00000000 --- a/include/mechanism_configuration/development/utils.hpp +++ /dev/null @@ -1,155 +0,0 @@ -// Copyright (C) 2023–2026 University Corporation for Atmospheric Research -// University of Illinois at Urbana-Champaign -// SPDX-License-Identifier: Apache-2.0 - -#pragma once - -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include -#include -#include - -namespace mechanism_configuration -{ - namespace development - { - struct NodeInfo - { - std::string name; - YAML::Node nodes; - }; - - struct DuplicateEntryInfo - { - std::string name; - std::vector nodes; - }; - - /// @brief Ensures a YAML node is treated as a sequence - /// @param node The YAML node to convert - /// @return A YAML sequence node containing the original node(s) - YAML::Node AsSequence(const YAML::Node& node); - - void AppendFilePath(const std::string& config_path, Errors& errors); - - std::unordered_map GetComments(const YAML::Node& object); - - /// @brief Extract species names from a vector of PhaseSpecies - std::vector GetSpeciesNames(const std::vector& phase_species); - - void ReportUnknownSpecies( - const YAML::Node& object, - const std::vector& unknown_species, - Errors& errors, - const ConfigParseStatus& parser_status = ConfigParseStatus::UnknownSpecies); - - std::optional> CheckPhaseExists( - const YAML::Node& object, - const std::string& phase_key, - const std::vector& existing_phases, - Errors& errors, - const ConfigParseStatus& parser_status = ConfigParseStatus::UnknownPhase, - std::string type = {}); - - void CheckSpeciesPresenceInPhase( - const YAML::Node& object, - const types::Phase& phase, - const std::vector>& species_node_pairs, - Errors& errors, - const ConfigParseStatus& parser_status = ConfigParseStatus::RequestedSpeciesNotRegisteredInPhase); - - template - std::vector FindDuplicateObjectsByName(const std::vector>& collection) - { - std::unordered_map> name_to_nodes; - - if constexpr (std::is_same_v) - { - for (const auto& [elem, node] : collection) - { - name_to_nodes[elem].push_back(node); - } - } - else - { - for (const auto& [elem, node] : collection) - { - name_to_nodes[elem.name].push_back(node); - } - } - - std::vector duplicates; - - for (const auto& [name, nodes] : name_to_nodes) - { - if (nodes.size() > 1) - { - duplicates.push_back({ name, nodes }); - } - } - - return duplicates; - } - - template - std::vector FindUnknownObjectsByName( - const std::vector& existing_objects, - std::vector>& requested_objects) - { - std::unordered_set existing_names; - - if constexpr (std::is_same_v) - { - for (const auto& name : existing_objects) - { - existing_names.insert(name); - } - } - else - { - for (const auto& object : existing_objects) - { - existing_names.insert(object.name); - } - } - - std::vector unknowns; - - if constexpr (std::is_same_v) - { - for (const auto& [name, node] : requested_objects) - { - if (existing_names.find(name) == existing_names.end()) - { - unknowns.emplace_back(name, node); - } - } - } - else - { - for (const auto& [elem, node] : requested_objects) - { - const auto& name = elem.name; - if (existing_names.find(name) == existing_names.end()) - { - unknowns.emplace_back(name, node); - } - } - } - - return unknowns; - } - - } // namespace development -} // namespace mechanism_configuration diff --git a/include/mechanism_configuration/development/validation.hpp b/include/mechanism_configuration/development/validation.hpp deleted file mode 100644 index fc949365..00000000 --- a/include/mechanism_configuration/development/validation.hpp +++ /dev/null @@ -1,218 +0,0 @@ -// Copyright (C) 2023–2026 University Corporation for Atmospheric Research -// University of Illinois at Urbana-Champaign -// SPDX-License-Identifier: Apache-2.0 - -#pragma once - -namespace mechanism_configuration -{ - namespace development - { - namespace validation - { - // Shared, but also Mechanism - static constexpr const char* version = "version"; - static constexpr const char* name = "name"; - - // Configuration - static constexpr const char* species = "species"; - static constexpr const char* phases = "phases"; - static constexpr const char* models = "models"; - static constexpr const char* reactions = "reactions"; - - // Species - static constexpr const char* absolute_tolerance = "absolute tolerance"; - static constexpr const char* diffusion_coefficient = "diffusion coefficient [m2 s-1]"; - static constexpr const char* molecular_weight = "molecular weight [kg mol-1]"; - static constexpr const char* henrys_law_constant_298 = "HLC(298K) [mol m-3 Pa-1]"; - static constexpr const char* henrys_law_constant_exponential_factor = "HLC exponential factor [K]"; - static constexpr const char* phase = "phase"; - static constexpr const char* n_star = "N star"; - static constexpr const char* density = "density [kg m-3]"; - static constexpr const char* tracer_type = "tracer type"; - static constexpr const char* constant_concentration = "constant concentration [mol m-3]"; - static constexpr const char* constant_mixing_ratio = "constant mixing ratio [mol mol-1]"; - static constexpr const char* is_third_body = "is third body"; - static constexpr const char* third_body = "THIRD_BODY"; - - // Reactions - static constexpr const char* reactants = "reactants"; - static constexpr const char* products = "products"; - static constexpr const char* type = "type"; - static constexpr const char* gas_phase = "gas phase"; - - // Reactant and product - static constexpr const char* coefficient = "coefficient"; - // also name - - // ---------------------------------------- - // Reaction types - // ---------------------------------------- - - // Arrhenius - static constexpr const char* Arrhenius_key = "ARRHENIUS"; - static constexpr const char* A = "A"; - static constexpr const char* B = "B"; - static constexpr const char* C = "C"; - static constexpr const char* D = "D"; - static constexpr const char* E = "E"; - static constexpr const char* Ea = "Ea"; - - // TaylorSeries - static constexpr const char* TaylorSeries_key = "TAYLOR_SERIES"; - static constexpr const char* taylor_coefficients = "taylor coefficients"; - // also these - // A - // B - // C - // D - // E - // Ea - - // Condensed Phase Arrhenius - static constexpr const char* CondensedPhaseArrhenius_key = "CONDENSED_PHASE_ARRHENIUS"; - // also these - // condensed phase - // A - // B - // C - // D - // E - // Ea - - // Troe - static constexpr const char* Troe_key = "TROE"; - static constexpr const char* k0_A = "k0_A"; - static constexpr const char* k0_B = "k0_B"; - static constexpr const char* k0_C = "k0_C"; - static constexpr const char* kinf_A = "kinf_A"; - static constexpr const char* kinf_B = "kinf_B"; - static constexpr const char* kinf_C = "kinf_C"; - static constexpr const char* Fc = "Fc"; - static constexpr const char* N = "N"; - - // Ternary Chemical Activation - static constexpr const char* TernaryChemicalActivation_key = "TERNARY_CHEMICAL_ACTIVATION"; - // also k0_A - // k0_B - // k0_C - // kinf_A - // kinf_B - // kinf_C - // Fc - // N - - // Branched - static constexpr const char* Branched_key = "BRANCHED_NO_RO2"; - static constexpr const char* X = "X"; - static constexpr const char* Y = "Y"; - static constexpr const char* a0 = "a0"; - static constexpr const char* n = "n"; - static constexpr const char* nitrate_products = "nitrate products"; - static constexpr const char* alkoxy_products = "alkoxy products"; - - // Tunneling - static constexpr const char* Tunneling_key = "TUNNELING"; - // also these, but they are defined above - // A - // B - // C - - // Surface - static constexpr const char* Surface_key = "SURFACE"; - static constexpr const char* reaction_probability = "reaction probability"; - static constexpr const char* gas_phase_species = "gas-phase species"; - static constexpr const char* gas_phase_products = "gas-phase products"; - static constexpr const char* condensed_phase = "condensed phase"; - - // Photolysis - static constexpr const char* Photolysis_key = "PHOTOLYSIS"; - static constexpr const char* scaling_factor = "scaling factor"; - - // Condensed Phae Photolysis - static constexpr const char* CondensedPhasePhotolysis_key = "CONDENSED_PHASE_PHOTOLYSIS"; - // also - // scaling factor - // condensed phase - - // Emissions - static constexpr const char* Emission_key = "EMISSION"; - // also scaling factor - - // First Order Loss - static constexpr const char* FirstOrderLoss_key = "FIRST_ORDER_LOSS"; - // also scaling factor - - // Simpol Phase Transfer - static constexpr const char* SimpolPhaseTransfer_key = "SIMPOL_PHASE_TRANSFER"; - static constexpr const char* condensed_phase_species = "condensed-phase species"; - // also - // gas phase - // gas-phase species - // condensed phase - // condensed-phase species - // B - - // Aqueous Equilibrium - static constexpr const char* AqueousPhaseEquilibrium_key = "AQUEOUS_EQUILIBRIUM"; - static constexpr const char* condensed_phase_water = "condensed-phase water"; - // also - // condensed phase - // A - // C - static constexpr const char* k_reverse = "k_reverse"; - - // Wet Deposition - static constexpr const char* WetDeposition_key = "WET_DEPOSITION"; - // also - // scaling factor - // condensed phase - - // Henry's Law Phase Transfer - static constexpr const char* HenrysLaw_key = "HL_PHASE_TRANSFER"; - static constexpr const char* gas = "gas"; - static constexpr const char* particle = "particle"; - static constexpr const char* solutes = "solutes"; - static constexpr const char* solvent = "solvent"; - // also - // phase - // species - - // User Defined - static constexpr const char* UserDefined_key = "USER_DEFINED"; - // also - // gas phase - // reactants - // products - // scaling factor - - // Lambda Rate Constant - static constexpr const char* LambdaRateConstant_key = "LAMBDA_RATE_CONSTANT"; - static constexpr const char* lambda_function = "lambda function"; - // also - // gas phase - // reactants - // products - // name - - // ---------------------------------------- - // Model types - // ---------------------------------------- - // Gas model - static constexpr const char* GasModel_key = "GAS_PHASE"; - // also - // name - // phases - - // Modal model - static constexpr const char* ModalModel_key = "MODAL"; - static constexpr const char* modes = "modes"; - static constexpr const char* geometric_mean_diameter = "geometric mean diameter [m]"; - static constexpr const char* geometric_standard_deviation = "geometric standard deviation"; - // also - // name - // phase - - } // namespace validation - } // namespace development -} // namespace mechanism_configuration \ No newline at end of file diff --git a/include/mechanism_configuration/error_location.hpp b/include/mechanism_configuration/error_location.hpp deleted file mode 100644 index 7d4edf48..00000000 --- a/include/mechanism_configuration/error_location.hpp +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright (C) 2023–2026 University Corporation for Atmospheric Research -// University of Illinois at Urbana-Champaign -// SPDX-License-Identifier: Apache-2.0 - -#pragma once - -#include - -#include - -namespace mechanism_configuration -{ - struct ErrorLocation - { - int line, column; - - /// @brief Constructor that adjusts 0-based indices to 1-based - /// @param line_number 0-based line number (from YAML::Mark) - /// @param column_number 0-based column number (from YAML::Mark) - ErrorLocation(int line_number, int column_number) - : line(line_number + 1), - column(column_number + 1) - { - } - }; -} // namespace mechanism_configuration - -#ifdef MECH_CONFIG_USE_FMT -template<> -struct fmt::formatter -{ - constexpr auto parse(fmt::format_parse_context& ctx) const - { - return ctx.begin(); - } - template - auto format(const mechanism_configuration::ErrorLocation& loc, FormatContext& ctx) const - { - return fmt::format_to(ctx.out(), "{}:{}", loc.line, loc.column); - } -}; -#else -template<> -struct std::formatter -{ - constexpr auto parse(std::format_parse_context& ctx) const - { - return ctx.begin(); - } - template - auto format(const mechanism_configuration::ErrorLocation& loc, FormatContext& ctx) const - { - return std::format_to(ctx.out(), "{}:{}", loc.line, loc.column); - } -}; -#endif \ No newline at end of file diff --git a/include/mechanism_configuration/errors.hpp b/include/mechanism_configuration/errors.hpp index a49235d6..a838f9ea 100644 --- a/include/mechanism_configuration/errors.hpp +++ b/include/mechanism_configuration/errors.hpp @@ -4,13 +4,94 @@ #pragma once -#include +#include +#include #include #include #include namespace mechanism_configuration { - using Errors = std::vector>; -} // namespace mechanism_configuration \ No newline at end of file + struct ErrorLocation + { + int line, column; + + /// @brief Constructor that adjusts 0-based indices to 1-based + /// @param line_number 0-based line number (from YAML::Mark) + /// @param column_number 0-based column number (from YAML::Mark) + ErrorLocation(int line_number, int column_number) + : line(line_number + 1), + column(column_number + 1) + { + } + }; + + enum class ErrorCode + { + Success, + None, + InvalidKey, + UnknownKey, + InvalidFilePath, + ObjectTypeNotFound, + RequiredKeyNotFound, + MutuallyExclusiveOption, + DuplicateSpeciesDetected, + DuplicatePhasesDetected, + DuplicateSpeciesInPhaseDetected, + PhaseRequiresUnknownSpecies, + ReactionRequiresUnknownSpecies, + UnknownSpecies, + UnknownPhase, + RequestedSpeciesNotRegisteredInPhase, + TooManyReactionComponents, + InvalidVersion, + MissingVersionField, + InvalidType, + UnknownType, + FileNotFound, + UnexpectedError, + EmptyObject, + }; + + std::string ErrorCodeToString(const ErrorCode& status); + + // For Google Test printing + inline void PrintTo(const ErrorCode& status, std::ostream* os) + { + *os << ErrorCodeToString(status); + } + + using Errors = std::vector>; +} // namespace mechanism_configuration + +#ifdef MECH_CONFIG_USE_FMT +template<> +struct fmt::formatter +{ + constexpr auto parse(fmt::format_parse_context& ctx) const + { + return ctx.begin(); + } + template + auto format(const mechanism_configuration::ErrorLocation& loc, FormatContext& ctx) const + { + return fmt::format_to(ctx.out(), "{}:{}", loc.line, loc.column); + } +}; +#else +template<> +struct std::formatter +{ + constexpr auto parse(std::format_parse_context& ctx) const + { + return ctx.begin(); + } + template + auto format(const mechanism_configuration::ErrorLocation& loc, FormatContext& ctx) const + { + return std::format_to(ctx.out(), "{}:{}", loc.line, loc.column); + } +}; +#endif \ No newline at end of file diff --git a/include/mechanism_configuration/mechanism.hpp b/include/mechanism_configuration/mechanism.hpp index f1088339..2c656adc 100644 --- a/include/mechanism_configuration/mechanism.hpp +++ b/include/mechanism_configuration/mechanism.hpp @@ -4,7 +4,7 @@ #pragma once -#include +#include #include #include @@ -13,7 +13,7 @@ namespace mechanism_configuration { -// Trying to build on linux for the python release, I learned that glibc had a bug which defined + // Trying to build on linux for the python release, I learned that glibc had a bug which defined // a macro called major and minor. This caused a conflict with the Version struct. To fix this, I // undefine the macros before defining the struct and then redefine them after the struct. // https://stackoverflow.com/a/22253389/5217293 @@ -74,20 +74,21 @@ namespace mechanism_configuration #pragma pop_macro("minor") #pragma pop_macro("major") + /// @brief Represents a full mechanism definition struct Mechanism { + /// @brief Mechanism name (optional) + std::string name; + /// @brief Species list + std::vector species; + /// @brief Phases list + std::vector phases; + /// @brief Represents a collection of different reaction types, each stored in a vector + /// corresponding to a specific mechanism + types::Reactions reactions; + /// @brief Version of the mechanism configuration format used, in major.minor.patch format Version version; - - Mechanism(Version version) - : version(version) - { - } - Mechanism() - : version() - { - } - virtual ~Mechanism() = default; + /// @brief Relative tolerance for solver (optional, default: 1e-6) + double relative_tolerance{ 1e-6 }; }; - - using GlobalMechanism = ::mechanism_configuration::Mechanism; } // namespace mechanism_configuration \ No newline at end of file diff --git a/include/mechanism_configuration/mechanism_configuration.hpp b/include/mechanism_configuration/mechanism_configuration.hpp new file mode 100644 index 00000000..db2e42a5 --- /dev/null +++ b/include/mechanism_configuration/mechanism_configuration.hpp @@ -0,0 +1,13 @@ +// Copyright (C) 2023–2026 University Corporation for Atmospheric Research +// University of Illinois at Urbana-Champaign +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include +#include +#include +#include +#include +#include +#include diff --git a/include/mechanism_configuration/parse.hpp b/include/mechanism_configuration/parse.hpp new file mode 100644 index 00000000..ee3d3849 --- /dev/null +++ b/include/mechanism_configuration/parse.hpp @@ -0,0 +1,20 @@ +// Copyright (C) 2023–2026 University Corporation for Atmospheric Research +// University of Illinois at Urbana-Champaign +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include +#include + +#include +#include + +namespace mechanism_configuration +{ + /// @brief Parse a mechanism configuration file, dispatching on its version. + /// @param config_path Path to a configuration file (a std::string converts implicitly), + /// or a directory of version-0 CAMP files. + /// @return The parsed Mechanism, or all structural and semantic errors encountered. + std::expected Parse(const std::filesystem::path& config_path); +} // namespace mechanism_configuration \ No newline at end of file diff --git a/include/mechanism_configuration/parse_status.hpp b/include/mechanism_configuration/parse_status.hpp deleted file mode 100644 index 51a04d7d..00000000 --- a/include/mechanism_configuration/parse_status.hpp +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright (C) 2023–2026 University Corporation for Atmospheric Research -// University of Illinois at Urbana-Champaign -// SPDX-License-Identifier: Apache-2.0 - -#pragma once - -#include -#include - -namespace mechanism_configuration -{ - enum class ConfigParseStatus - { - Success, - None, - InvalidKey, - UnknownKey, - InvalidFilePath, - ObjectTypeNotFound, - RequiredKeyNotFound, - MutuallyExclusiveOption, - DuplicateSpeciesDetected, - DuplicatePhasesDetected, - DuplicateSpeciesInPhaseDetected, - PhaseRequiresUnknownSpecies, - ReactionRequiresUnknownSpecies, - UnknownSpecies, - UnknownPhase, - RequestedSpeciesNotRegisteredInPhase, - TooManyReactionComponents, - InvalidIonPair, - InvalidVersion, - MissingVersionField, - InvalidParameterNumber, - InvalidType, - UnknownType, - FileNotFound, - UnexpectedError, - EmptyObject, - }; - - std::string configParseStatusToString(const ConfigParseStatus& status); - - // For Google Test printing - inline void PrintTo(const ConfigParseStatus& status, std::ostream* os) - { - *os << configParseStatusToString(status); - } -} // namespace mechanism_configuration diff --git a/include/mechanism_configuration/parser.hpp b/include/mechanism_configuration/parser.hpp deleted file mode 100644 index 1b0a020b..00000000 --- a/include/mechanism_configuration/parser.hpp +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright (C) 2023–2026 University Corporation for Atmospheric Research -// University of Illinois at Urbana-Champaign -// SPDX-License-Identifier: Apache-2.0 - -#pragma once - -#include -#include - -#include - -namespace mechanism_configuration -{ - struct VersionInfo - { - unsigned int version; // major version - Errors errors; - }; - - class UniversalParser - { - public: - /// @brief Extracts the major version from the given configuration file - /// @return VersionInfo containing the version and validation errors - VersionInfo GetVersion(const std::filesystem::path& config_path); - - /// @brief Parses a configuration file using the appropriate versioned parser. - /// Determines the configuration version and calls the corresponding parser - /// implementation. If the version field is missing, the function falls - /// back to the version 0 parser. - /// @param config_path Path to the YAML configuration file - /// @return ParserResult containing the parsed GlobalMechanism on success, - /// or a list of accumulated errors on failure - ParserResult Parse(const std::filesystem::path& config_path); - }; -} // namespace mechanism_configuration \ No newline at end of file diff --git a/include/mechanism_configuration/parser_result.hpp b/include/mechanism_configuration/parser_result.hpp deleted file mode 100644 index 8615ac22..00000000 --- a/include/mechanism_configuration/parser_result.hpp +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright (C) 2023–2026 University Corporation for Atmospheric Research -// University of Illinois at Urbana-Champaign -// SPDX-License-Identifier: Apache-2.0 - -#pragma once - -#include -#include - -#include -#include -#include -#include - -namespace mechanism_configuration -{ - - template - struct ParserResult - { - std::unique_ptr mechanism = nullptr; - Errors errors; - - bool has_errors() const - { - return !errors.empty(); - } - - operator bool() const - { - return mechanism != nullptr && errors.empty(); - } - - MechanismType& operator*() - { - return *mechanism; - } - }; -} // namespace mechanism_configuration diff --git a/include/mechanism_configuration/types.hpp b/include/mechanism_configuration/types.hpp new file mode 100644 index 00000000..fb568711 --- /dev/null +++ b/include/mechanism_configuration/types.hpp @@ -0,0 +1,329 @@ +// Copyright (C) 2023–2026 University Corporation for Atmospheric Research +// University of Illinois at Urbana-Champaign +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include + +#include +#include +#include +#include +#include + +namespace mechanism_configuration::types +{ + + struct Species + { + std::string name; + std::optional absolute_tolerance; + std::optional diffusion_coefficient; + std::optional molecular_weight; + std::optional henrys_law_constant_298; + std::optional henrys_law_constant_exponential_factor; + std::optional n_star; + std::optional density; + std::optional tracer_type; + std::optional constant_concentration; + std::optional constant_mixing_ratio; + std::optional is_third_body; + /// @brief Unknown properties, prefixed with two underscores (__) + std::unordered_map unknown_properties; + }; + + struct PhaseSpecies + { + std::string name; + std::optional diffusion_coefficient; + /// @brief Unknown properties, prefixed with two underscores (__) + std::unordered_map unknown_properties; + }; + + struct Phase + { + std::string name; + std::vector species; + /// @brief Unknown properties, prefixed with two underscores (__) + std::unordered_map unknown_properties; + }; + + struct ReactionComponent + { + std::string name; + double coefficient{ 1.0 }; + /// @brief Unknown properties, prefixed with two underscores (__) + std::unordered_map unknown_properties; + }; + + struct Arrhenius + { + /// @brief Pre-exponential factor [(mol m−3)^(−(𝑛−1)) s−1] + double A{ 1 }; + /// @brief Unitless exponential factor + double B{ 0 }; + /// @brief Activation threshold, expected to be the negative activation energy divided by the boltzman constant + /// [-E_a / k_b), K] + double C{ 0 }; + /// @brief A factor that determines temperature dependence [K] + double D{ 300 }; + /// @brief A factor that determines pressure dependence [Pa-1] + double E{ 0 }; + /// @brief A list of reactants + std::vector reactants; + /// @brief A list of products + std::vector products; + /// @brief An identifier, optional, uniqueness not enforced + std::string name; + /// @brief An identifier indicating which gas phase this reaction takes place in + std::string gas_phase; + /// @brief Unknown properties, prefixed with two underscores (__) + std::unordered_map unknown_properties; + }; + + struct Branched + { + /// @brief pre-exponential factor + double X; + /// @brief exponential factor + double Y; + /// @brief branching factor + double a0; + /// @brief number of heavy atoms in the RO2 reacting species (excluding the peroxy moiety) + int n; + /// @brief A list of reactants + std::vector reactants; + /// @brief A list of nitrate products + std::vector nitrate_products; + /// @brief A list of alkoxy products + std::vector alkoxy_products; + /// @brief An identifier, optional, uniqueness not enforced + std::string name; + /// @brief An identifier indicating which gas phase this reaction takes place in + std::string gas_phase; + /// @brief Unknown properties, prefixed with two underscores (__) + std::unordered_map unknown_properties; + }; + + struct Emission + { + /// @brief Scaling factor to apply to user-provided rate constants + double scaling_factor{ 1.0 }; + /// @brief A list of products + std::vector products; + /// @brief An identifier, optional, uniqueness not enforced + std::string name; + /// @brief An identifier indicating which gas phase this reaction takes place in + std::string gas_phase; + /// @brief Unknown properties, prefixed with two underscores (__) + std::unordered_map unknown_properties; + }; + + struct FirstOrderLoss + { + /// @brief Scaling factor to apply to user-provided rate constants + double scaling_factor{ 1.0 }; + /// @brief A single reactant + ReactionComponent reactants; + /// @brief A list of products, optional for first-order loss reactions + std::vector products; + /// @brief An identifier, optional, uniqueness not enforced + std::string name; + /// @brief An identifier indicating which gas phase this reaction takes place in + std::string gas_phase; + /// @brief Unknown properties, prefixed with two underscores (__) + std::unordered_map unknown_properties; + }; + + struct Photolysis + { + /// @brief Scaling factor to apply to user-provided rate constants + double scaling_factor{ 1.0 }; + /// @brief A single reactant + ReactionComponent reactants; + /// @brief A list of products + std::vector products; + /// @brief An identifier, optional, uniqueness not enforced + std::string name; + /// @brief An identifier indicating which gas phase this reaction takes place in + std::string gas_phase; + /// @brief Unknown properties, prefixed with two underscores (__) + std::unordered_map unknown_properties; + }; + + struct Surface + { + /// @brief Reaction probability (0-1) [unitless] + double reaction_probability{ 1.0 }; + /// @brief A single gas-phase species + ReactionComponent gas_phase_species; + /// @brief A list of products + std::vector gas_phase_products; + /// @brief An identifier, optional, uniqueness not enforced + std::string name; + /// @brief An identifier indicating which gas phase this reaction takes place in + std::string gas_phase; + /// @brief An identifier for the condensed phase where this reaction occurs + std::string condensed_phase; + /// @brief Unknown properties, prefixed with two underscores (__) + std::unordered_map unknown_properties; + }; + + struct TaylorSeries + { + /// @brief Pre-exponential factor [(mol m−3)^(−(𝑛−1)) s−1] + double A{ 1 }; + /// @brief Unitless exponential factor + double B{ 0 }; + /// @brief Activation threshold, expected to be the negative activation energy divided by the boltzman constant + /// [-E_a / k_b), K] + double C{ 0 }; + /// @brief A factor that determines temperature dependence [K] + double D{ 300 }; + /// @brief A factor that determines pressure dependence [Pa-1] + double E{ 0 }; + /// @brief An array of coefficients for the Taylor series expansion + std::vector taylor_coefficients{ 1.0 }; + /// @brief A list of reactants + std::vector reactants; + /// @brief A list of products + std::vector products; + /// @brief An identifier, optional, uniqueness not enforced + std::string name; + /// @brief An identifier indicating which gas phase this reaction takes place in + std::string gas_phase; + /// @brief Unknown properties, prefixed with two underscores (__) + std::unordered_map unknown_properties; + }; + + struct Troe + { + /// @brief low-pressure pre-exponential factor + double k0_A = 1.0; + /// @brief low-pressure temperature-scaling parameter + double k0_B = 0.0; + /// @brief low-pressure exponential factor + double k0_C = 0.0; + /// @brief high-pressure pre-exponential factor + double kinf_A = 1.0; + /// @brief high-pressure temperature-scaling parameter + double kinf_B = 0.0; + /// @brief high-pressure exponential factor + double kinf_C = 0.0; + /// @brief Troe F_c parameter + double Fc = 0.6; + /// @brief Troe N parameter + double N = 1.0; + /// @brief A list of reactants + std::vector reactants; + /// @brief A list of products + std::vector products; + /// @brief An identifier, optional, uniqueness not enforced + std::string name; + /// @brief An identifier indicating which gas phase this reaction takes place in + std::string gas_phase; + /// @brief Unknown properties, prefixed with two underscores (__) + std::unordered_map unknown_properties; + }; + + struct TernaryChemicalActivation + { + /// @brief low-pressure pre-exponential factor + double k0_A = 1.0; + /// @brief low-pressure temperature-scaling parameter + double k0_B = 0.0; + /// @brief low-pressure exponential factor + double k0_C = 0.0; + /// @brief high-pressure pre-exponential factor + double kinf_A = 1.0; + /// @brief high-pressure temperature-scaling parameter + double kinf_B = 0.0; + /// @brief high-pressure exponential factor + double kinf_C = 0.0; + /// @brief TernaryChemicalActivation F_c parameter + double Fc = 0.6; + /// @brief TernaryChemicalActivation N parameter + double N = 1.0; + /// @brief A list of reactants + std::vector reactants; + /// @brief A list of products + std::vector products; + /// @brief An identifier, optional, uniqueness not enforced + std::string name; + /// @brief An identifier indicating which gas phase this reaction takes place in + std::string gas_phase; + /// @brief Unknown properties, prefixed with two underscores (__) + std::unordered_map unknown_properties; + }; + + struct Tunneling + { + /// @brief Pre-exponential factor [(mol m−3)^(−(𝑛−1)) s−1] + double A = 1.0; + /// @brief Linear temperature-dependent parameter [K] + double B = 0.0; + /// @brief Cubed temperature-dependent parameter [K^3] + double C = 0.0; + /// @brief A list of reactants + std::vector reactants; + /// @brief A list of products + std::vector products; + /// @brief An identifier, optional, uniqueness not enforced + std::string name; + /// @brief An identifier indicating which gas phase this reaction takes place in + std::string gas_phase; + /// @brief Unknown properties, prefixed with two underscores (__) + std::unordered_map unknown_properties; + }; + + struct UserDefined + { + /// @brief Scaling factor to apply to user-provided rate constants + double scaling_factor{ 1.0 }; + /// @brief A list of reactants + std::vector reactants; + /// @brief A list of products + std::vector products; + /// @brief An identifier, optional, uniqueness not enforced + std::string name; + /// @brief An identifier indicating which gas phase this reaction takes place in + std::string gas_phase; + /// @brief Unknown properties, prefixed with two underscores (__) + std::unordered_map unknown_properties; + }; + + struct LambdaRateConstant + { + /// @brief A lambda function as a string, expected to be a function of temperature (T) and optionally pressure (P) + std::string lambda_function; + /// @brief A list of reactants + std::vector reactants; + /// @brief A list of products + std::vector products; + /// @brief An identifier, optional, uniqueness not enforced + std::string name; + /// @brief An identifier indicating which gas phase this reaction takes place in + std::string gas_phase; + /// @brief Unknown properties, prefixed with two underscores (__) + std::unordered_map unknown_properties; + }; + + /// @brief Represents a collection of different reaction types + struct Reactions + { + std::vector arrhenius; + std::vector branched; + std::vector emission; + std::vector first_order_loss; + std::vector photolysis; + std::vector surface; + std::vector taylor_series; + std::vector troe; + std::vector ternary_chemical_activation; + std::vector tunneling; + std::vector user_defined; + std::vector lambda_rate_constant; + }; + +} // namespace mechanism_configuration diff --git a/include/mechanism_configuration/v0/parser.hpp b/include/mechanism_configuration/v0/parser.hpp deleted file mode 100644 index 9742fd23..00000000 --- a/include/mechanism_configuration/v0/parser.hpp +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright (C) 2023-2024 National Center for Atmospheric Research -// SPDX-License-Identifier: Apache-2.0 -#pragma once - -#include -#include -#include -#include - -#include - -#include -#include - -namespace mechanism_configuration -{ - namespace v0 - { - class Parser - { - const std::string DEFAULT_CONFIG_FILE_JSON = "config.json"; - const std::string DEFAULT_CONFIG_FILE_YAML = "config.yaml"; - const std::string CAMP_FILES = "camp-files"; - const std::string CAMP_DATA = "camp-data"; - const std::string TYPE = "type"; - - Errors GetCampFiles(const std::filesystem::path& config_path, std::vector& camp_files); - - public: - ParserResult Parse(const std::filesystem::path& config_path); - }; - } // namespace v0 -} // namespace mechanism_configuration diff --git a/include/mechanism_configuration/v0/parser_types.hpp b/include/mechanism_configuration/v0/parser_types.hpp deleted file mode 100644 index 55a597f7..00000000 --- a/include/mechanism_configuration/v0/parser_types.hpp +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (C) 2023-2024 National Center for Atmospheric Research, University of Illinois at Urbana-Champaign -// -// SPDX-License-Identifier: Apache-2.0 - -#pragma once - -#include -#include -#include - -#include - -#include - -namespace mechanism_configuration -{ - namespace v0 - { - // species and mechanism - Errors ParseChemicalSpecies(std::unique_ptr& mechanism, const YAML::Node& object); - Errors ParseProducts(const YAML::Node& object, std::vector& products); - Errors ParseReactants(const YAML::Node& object, std::vector& reactants); - Errors ParseRelativeTolerance(std::unique_ptr& mechanism, const YAML::Node& object); - - // reactions - Errors ArrheniusParser(std::unique_ptr& mechanism, const YAML::Node& object); - Errors BranchedParser(std::unique_ptr& mechanism, const YAML::Node& object); - Errors EmissionParser(std::unique_ptr& mechanism, const YAML::Node& object); - Errors FirstOrderLossParser(std::unique_ptr& mechanism, const YAML::Node& object); - Errors PhotolysisParser(std::unique_ptr& mechanism, const YAML::Node& object); - Errors SurfaceParser(std::unique_ptr& mechanism, const YAML::Node& object); - Errors TernaryChemicalActivationParser(std::unique_ptr& mechanism, const YAML::Node& object); - Errors TroeParser(std::unique_ptr& mechanism, const YAML::Node& object); - Errors TunnelingParser(std::unique_ptr& mechanism, const YAML::Node& object); - Errors UserDefinedParser(std::unique_ptr& mechanism, const YAML::Node& object); - - } // namespace v0 -} // namespace mechanism_configuration diff --git a/include/mechanism_configuration/v0/types.hpp b/include/mechanism_configuration/v0/types.hpp deleted file mode 100644 index a8c026fc..00000000 --- a/include/mechanism_configuration/v0/types.hpp +++ /dev/null @@ -1,208 +0,0 @@ -// Copyright (C) 2023-2024 National Center for Atmospheric Research, University of Illinois at Urbana-Champaign -// -// SPDX-License-Identifier: Apache-2.0 - -#pragma once - -#include - -#include -#include -#include -#include -#include -#include - -namespace mechanism_configuration -{ - namespace v0 - { - namespace types - { - struct Species - { - std::string name; - std::optional molecular_weight; - std::optional diffusion_coefficient; - std::optional absolute_tolerance; - std::optional tracer_type; - /// @brief Unknown properties, prefixed with two underscores (__) - std::unordered_map unknown_properties; - }; - - struct Phase - { - std::string name; - std::vector species; - /// @brief Unknown properties, prefixed with two underscores (__) - std::unordered_map unknown_properties; - }; - - struct ReactionComponent - { - std::string species_name; - double coefficient{ 1.0 }; - /// @brief Unknown properties, prefixed with two underscores (__) - std::unordered_map unknown_properties; - }; - - struct Arrhenius - { - /// @brief Pre-exponential factor [(mol m−3)^(−(𝑛−1)) s−1] - double A{ 1 }; - /// @brief Unitless exponential factor - double B{ 0 }; - /// @brief Activation threshold, expected to be the negative activation energy divided by the boltzman constant - /// [-E_a / k_b), K] - double C{ 0 }; - /// @brief A factor that determines temperature dependence [K] - double D{ 300 }; - /// @brief A factor that determines pressure dependence [Pa-1] - double E{ 0 }; - /// @brief A list of reactants - std::vector reactants; - /// @brief A list of products - std::vector products; - /// @brief Unknown properties, prefixed with two underscores (__) - std::unordered_map unknown_properties; - }; - - struct Troe - { - /// @brief low-pressure pre-exponential factor - double k0_A = 1.0; - /// @brief low-pressure temperature-scaling parameter - double k0_B = 0.0; - /// @brief low-pressure exponential factor - double k0_C = 0.0; - /// @brief high-pressure pre-exponential factor - double kinf_A = 1.0; - /// @brief high-pressure temperature-scaling parameter - double kinf_B = 0.0; - /// @brief high-pressure exponential factor - double kinf_C = 0.0; - /// @brief Troe F_c parameter - double Fc = 0.6; - /// @brief Troe N parameter - double N = 1.0; - /// @brief A list of reactants - std::vector reactants; - /// @brief A list of products - std::vector products; - /// @brief Unknown properties, prefixed with two underscores (__) - std::unordered_map unknown_properties; - }; - - struct TernaryChemicalActivation - { - /// @brief low-pressure pre-exponential factor - double k0_A = 1.0; - /// @brief low-pressure temperature-scaling parameter - double k0_B = 0.0; - /// @brief low-pressure exponential factor - double k0_C = 0.0; - /// @brief high-pressure pre-exponential factor - double kinf_A = 1.0; - /// @brief high-pressure temperature-scaling parameter - double kinf_B = 0.0; - /// @brief high-pressure exponential factor - double kinf_C = 0.0; - /// @brief TernaryChemicalActivation F_c parameter - double Fc = 0.6; - /// @brief TernaryChemicalActivation N parameter - double N = 1.0; - std::vector reactants; - /// @brief A list of products - std::vector products; - /// @brief Unknown properties, prefixed with two underscores (__) - std::unordered_map unknown_properties; - }; - - struct Branched - { - /// @brief pre-exponential factor - double X; - /// @brief exponential factor - double Y; - /// @brief branching factor - double a0; - /// @brief number of heavy atoms in the RO2 reacting species (excluding the peroxy moiety) - int n; - /// @brief A list of reactants - std::vector reactants; - /// @brief A list of nitrate products - std::vector nitrate_products; - /// @brief A list of alkoxy products - std::vector alkoxy_products; - /// @brief Unknown properties, prefixed with two underscores (__) - std::unordered_map unknown_properties; - }; - - struct Tunneling - { - /// @brief Pre-exponential factor [(mol m−3)^(−(𝑛−1)) s−1] - double A = 1.0; - /// @brief Linear temperature-dependent parameter [K] - double B = 0.0; - /// @brief Cubed temperature-dependent parameter [K^3] - double C = 0.0; - /// @brief A list of reactants - std::vector reactants; - /// @brief A list of products - std::vector products; - /// @brief Unknown properties, prefixed with two underscores (__) - std::unordered_map unknown_properties; - }; - - struct Surface - { - /// @brief Reaction probability (0-1) [unitless] - double reaction_probability{ 1.0 }; - /// @brief A list of reactants - ReactionComponent gas_phase_species; - /// @brief A list of products - std::vector gas_phase_products; - /// @brief An identifier, optional, uniqueness not enforced - std::string name; - /// @brief Unknown properties, prefixed with two underscores (__) - std::unordered_map unknown_properties; - }; - - struct UserDefined - { - /// @brief Scaling factor to apply to user-provided rate constants - double scaling_factor{ 1.0 }; - /// @brief A list of reactants - std::vector reactants; - /// @brief A list of products - std::vector products; - /// @brief An identifier, optional, uniqueness not enforced - std::string name; - /// @brief Unknown properties, prefixed with two underscores (__) - std::unordered_map unknown_properties; - }; - - struct Reactions - { - std::vector arrhenius; - std::vector branched; - std::vector user_defined; - std::vector surface; - std::vector troe; - std::vector ternary_chemical_activation; - std::vector tunneling; - }; - - struct Mechanism : public ::mechanism_configuration::Mechanism - { - /// @brief An identifier, optional - std::string name; - std::vector species; - std::vector phases; - Reactions reactions; - double relative_tolerance{ 1e-6 }; - }; - - } // namespace types - } // namespace v0 -} // namespace mechanism_configuration \ No newline at end of file diff --git a/include/mechanism_configuration/v0/validation.hpp b/include/mechanism_configuration/v0/validation.hpp deleted file mode 100644 index c4f2e027..00000000 --- a/include/mechanism_configuration/v0/validation.hpp +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright (C) 2023-2024 National Center for Atmospheric Research, University of Illinois at Urbana-Champaign -// -// SPDX-License-Identifier: Apache-2.0 - -#pragma once - -#include -#include - -namespace mechanism_configuration -{ - namespace v0 - { - namespace validation - { - static constexpr const char* NAME = "name"; - static constexpr const char* TYPE = "type"; - - static constexpr const char* VALUE = "value"; - - static constexpr const char* REACTIONS = "reactions"; - - static constexpr const char* TRACER_TYPE = "tracer type"; - static constexpr const char* ABS_TOLERANCE = "absolute tolerance"; - static constexpr const char* DIFFUSION_COEFF = "diffusion coefficient [m2 s-1]"; - static constexpr const char* MOL_WEIGHT = "molecular weight [kg mol-1]"; - static constexpr const char* THIRD_BODY = "THIRD_BODY"; - - static constexpr const char* REACTANTS = "reactants"; - static constexpr const char* PRODUCTS = "products"; - static constexpr const char* MUSICA_NAME = "MUSICA name"; - static constexpr const char* SCALING_FACTOR = "scaling factor"; - static constexpr const char* GAS_PHASE_REACTANT = "gas-phase reactant"; - static constexpr const char* GAS_PHASE_PRODUCTS = "gas-phase products"; - - static constexpr const char* QTY = "qty"; - static constexpr const char* YIELD = "yield"; - - static constexpr const char* SPECIES = "species"; - - static constexpr const char* ALKOXY_PRODUCTS = "alkoxy products"; - static constexpr const char* NITRATE_PRODUCTS = "nitrate products"; - static constexpr const char* X = "X"; - static constexpr const char* Y = "Y"; - static constexpr const char* A0 = "a0"; - static constexpr const char* N = "N"; - static constexpr const char* n = "n"; - - static constexpr const char* PROBABILITY = "reaction probability"; - - static constexpr const char* A = "A"; - static constexpr const char* B = "B"; - static constexpr const char* C = "C"; - static constexpr const char* D = "D"; - static constexpr const char* E = "E"; - static constexpr const char* Ea = "Ea"; - - static constexpr const char* K0_A = "k0_A"; - static constexpr const char* K0_B = "k0_B"; - static constexpr const char* K0_C = "k0_C"; - static constexpr const char* KINF_A = "kinf_A"; - static constexpr const char* KINF_B = "kinf_B"; - static constexpr const char* KINF_C = "kinf_C"; - static constexpr const char* FC = "Fc"; - } // namespace validation - } // namespace v0 -} // namespace mechanism_configuration \ No newline at end of file diff --git a/include/mechanism_configuration/v1/mechanism.hpp b/include/mechanism_configuration/v1/mechanism.hpp deleted file mode 100644 index 7bc1ef8a..00000000 --- a/include/mechanism_configuration/v1/mechanism.hpp +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright (C) 2023–2026 University Corporation for Atmospheric Research -// University of Illinois at Urbana-Champaign -// SPDX-License-Identifier: Apache-2.0 - -#pragma once - -#include -#include -#include - -#include -#include - -namespace mechanism_configuration -{ - namespace v1 - { - namespace types - { - - struct Mechanism : public ::mechanism_configuration::Mechanism - { - /// @brief Mechanism name - /// @note This is optional. - std::string name; - /// @brief Represents species - std::vector species; - /// @brief Represents phases - std::vector phases; - /// @brief Represents a collection of different reaction types, each stored in a vector - /// corresponding to a specific mechanism - Reactions reactions; - }; - } // namespace types - } // namespace v1 -} // namespace mechanism_configuration \ No newline at end of file diff --git a/include/mechanism_configuration/v1/mechanism_parsers.hpp b/include/mechanism_configuration/v1/mechanism_parsers.hpp deleted file mode 100644 index 938bfeae..00000000 --- a/include/mechanism_configuration/v1/mechanism_parsers.hpp +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (C) 2023–2026 University Corporation for Atmospheric Research -// University of Illinois at Urbana-Champaign -// SPDX-License-Identifier: Apache-2.0 - -#pragma once - -#include -#include -#include - -#include - -#include -#include - -namespace mechanism_configuration -{ - namespace v1 - { - std::pair> ParseSpecies(const YAML::Node& objects); - - std::pair> ParsePhases( - const YAML::Node& objects, - const std::vector existing_species); - - std::pair ParseReactionComponent(const YAML::Node& object); - - std::pair> ParseReactantsOrProducts( - const std::string& key, - const YAML::Node& object); - - std::pair ParseReactions( - const YAML::Node& objects, - const std::vector& existing_species, - const std::vector& existing_phases); - - } // namespace v1 -} // namespace mechanism_configuration diff --git a/include/mechanism_configuration/v1/parser.hpp b/include/mechanism_configuration/v1/parser.hpp deleted file mode 100644 index 7891f0d7..00000000 --- a/include/mechanism_configuration/v1/parser.hpp +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright (C) 2023–2026 University Corporation for Atmospheric Research -// University of Illinois at Urbana-Champaign -// SPDX-License-Identifier: Apache-2.0 - -#pragma once - -#include -#include - -#include - -namespace YAML -{ - class Node; -} // namespace YAML - -namespace mechanism_configuration -{ - namespace v1 - { - class Parser - { - private: - enum class EntityFormat - { - FileList, // { "files": [...] } - Inline, // [ { "name": ... }, ... ] - Invalid, - }; - - EntityFormat GetEntityFormat(const YAML::Node& node); - - ParserResult ParseFromFileConfig( - const YAML::Node& object, - const std::filesystem::path& config_path, - EntityFormat spc_format, - EntityFormat phs_format, - EntityFormat rxn_format); - - public: - ParserResult Parse(const std::filesystem::path& config_path); - ParserResult ParseFromString(const std::string& content); - ParserResult ParseFromNode(const YAML::Node& object); - }; - } // namespace v1 -} // namespace mechanism_configuration diff --git a/include/mechanism_configuration/v1/reaction_parsers.hpp b/include/mechanism_configuration/v1/reaction_parsers.hpp deleted file mode 100644 index ef44c8ae..00000000 --- a/include/mechanism_configuration/v1/reaction_parsers.hpp +++ /dev/null @@ -1,239 +0,0 @@ -// Copyright (C) 2023–2026 University Corporation for Atmospheric Research -// University of Illinois at Urbana-Champaign -// SPDX-License-Identifier: Apache-2.0 - -#pragma once - -#include -#include -#include - -#include - -#include - -namespace mechanism_configuration -{ - namespace v1 - { - - /// @brief Abstract interface for reaction parsers - class IReactionParser - { - public: - /// @brief Parses a YAML node representing a chemical reaction - /// @param object The YAML node containing reaction information - /// @param existing_species A list of species previously defined in the mechanism - /// @param existing_phases A list of chemical phases relevant to the reaction - /// @param reactions The container to which the parsed reactions will be added - /// @return A list of any parsing errors encountered - virtual Errors parse( - const YAML::Node& object, - const std::vector& existing_species, - const std::vector& existing_phases, - types::Reactions& reactions) = 0; - - /// @brief Destructor - virtual ~IReactionParser() = default; - }; - - class ArrheniusParser : public IReactionParser - { - public: - /// @brief Parser for Arrhenius reactions - Errors parse( - const YAML::Node& object, - const std::vector& existing_species, - const std::vector& existing_phases, - types::Reactions& reactions) override; - }; - - class BranchedParser : public IReactionParser - { - public: - /// @brief Parser for branched reactions - Errors parse( - const YAML::Node& object, - const std::vector& existing_species, - const std::vector& existing_phases, - types::Reactions& reactions) override; - }; - - class CondensedPhaseArrheniusParser : public IReactionParser - { - public: - /// @brief Parser for condensed-phase Arrhenius reactions - Errors parse( - const YAML::Node& object, - const std::vector& existing_species, - const std::vector& existing_phases, - types::Reactions& reactions) override; - }; - - class CondensedPhasePhotolysisParser : public IReactionParser - { - public: - /// @brief Parser for condensed-phase photolysis reactions - Errors parse( - const YAML::Node& object, - const std::vector& existing_species, - const std::vector& existing_phases, - types::Reactions& reactions) override; - }; - - class EmissionParser : public IReactionParser - { - public: - /// @brief Parser for emission reactions - Errors parse( - const YAML::Node& object, - const std::vector& existing_species, - const std::vector& existing_phases, - types::Reactions& reactions) override; - }; - - class FirstOrderLossParser : public IReactionParser - { - public: - /// @brief Parser for first-order loss reactions - Errors parse( - const YAML::Node& object, - const std::vector& existing_species, - const std::vector& existing_phases, - types::Reactions& reactions) override; - }; - - class SimpolPhaseTransferParser : public IReactionParser - { - public: - /// @brief Parser for SIMPOL-phase transfer reactions - Errors parse( - const YAML::Node& object, - const std::vector& existing_species, - const std::vector& existing_phases, - types::Reactions& reactions) override; - }; - - class AqueousEquilibriumParser : public IReactionParser - { - public: - /// @brief Parser for aqueous equilibrium reactions - Errors parse( - const YAML::Node& object, - const std::vector& existing_species, - const std::vector& existing_phases, - types::Reactions& reactions) override; - }; - - class WetDepositionParser : public IReactionParser - { - public: - /// @brief Parser for wet deposition reactions - Errors parse( - const YAML::Node& object, - const std::vector& existing_species, - const std::vector& existing_phases, - types::Reactions& reactions) override; - }; - - class HenrysLawParser : public IReactionParser - { - public: - /// @brief Parser for Henry's Law reactions - Errors parse( - const YAML::Node& object, - const std::vector& existing_species, - const std::vector& existing_phases, - types::Reactions& reactions) override; - }; - - class PhotolysisParser : public IReactionParser - { - public: - /// @brief Parser for photolysis reactions - Errors parse( - const YAML::Node& object, - const std::vector& existing_species, - const std::vector& existing_phases, - types::Reactions& reactions) override; - }; - - class SurfaceParser : public IReactionParser - { - public: - /// @brief Parser for surface reactions - Errors parse( - const YAML::Node& object, - const std::vector& existing_species, - const std::vector& existing_phases, - types::Reactions& reactions) override; - }; - - class TaylorSeriesParser : public IReactionParser - { - public: - /// @brief Parser for Taylor series reactions - Errors parse( - const YAML::Node& object, - const std::vector& existing_species, - const std::vector& existing_phases, - types::Reactions& reactions) override; - }; - - class TroeParser : public IReactionParser - { - public: - /// @brief Parser for Troe reactions - Errors parse( - const YAML::Node& object, - const std::vector& existing_species, - const std::vector& existing_phases, - types::Reactions& reactions) override; - }; - - class TernaryChemicalActivationParser : public IReactionParser - { - public: - /// @brief Parser for Ternary Chemical Activation reactions - Errors parse( - const YAML::Node& object, - const std::vector& existing_species, - const std::vector& existing_phases, - types::Reactions& reactions) override; - }; - - class TunnelingParser : public IReactionParser - { - public: - /// @brief Parser for tunneling reactions - Errors parse( - const YAML::Node& object, - const std::vector& existing_species, - const std::vector& existing_phases, - types::Reactions& reactions) override; - }; - - class UserDefinedParser : public IReactionParser - { - public: - /// @brief Parser for user-defined reactions - Errors parse( - const YAML::Node& object, - const std::vector& existing_species, - const std::vector& existing_phases, - types::Reactions& reactions) override; - }; - - class LambdaRateConstantParser : public IReactionParser - { - public: - /// @brief Parser for lambda rate constant reactions - Errors parse( - const YAML::Node& object, - const std::vector& existing_species, - const std::vector& existing_phases, - types::Reactions& reactions) override; - }; - - } // namespace v1 -} // namespace mechanism_configuration diff --git a/include/mechanism_configuration/v1/reaction_types.hpp b/include/mechanism_configuration/v1/reaction_types.hpp deleted file mode 100644 index 89901b65..00000000 --- a/include/mechanism_configuration/v1/reaction_types.hpp +++ /dev/null @@ -1,291 +0,0 @@ -// Copyright (C) 2023–2026 University Corporation for Atmospheric Research -// University of Illinois at Urbana-Champaign -// SPDX-License-Identifier: Apache-2.0 - -#pragma once - -#include - -#include -#include -#include -#include -#include - -namespace mechanism_configuration -{ - namespace v1 - { - namespace types - { - - struct Arrhenius - { - /// @brief Pre-exponential factor [(mol m−3)^(−(𝑛−1)) s−1] - double A{ 1 }; - /// @brief Unitless exponential factor - double B{ 0 }; - /// @brief Activation threshold, expected to be the negative activation energy divided by the boltzman constant - /// [-E_a / k_b), K] - double C{ 0 }; - /// @brief A factor that determines temperature dependence [K] - double D{ 300 }; - /// @brief A factor that determines pressure dependence [Pa-1] - double E{ 0 }; - /// @brief A list of reactants - std::vector reactants; - /// @brief A list of products - std::vector products; - /// @brief An identifier, optional, uniqueness not enforced - std::string name; - /// @brief An identifier indicating which gas phase this reaction takes place in - std::string gas_phase; - /// @brief Unknown properties, prefixed with two underscores (__) - std::unordered_map unknown_properties; - }; - - struct Branched - { - /// @brief pre-exponential factor - double X; - /// @brief exponential factor - double Y; - /// @brief branching factor - double a0; - /// @brief number of heavy atoms in the RO2 reacting species (excluding the peroxy moiety) - int n; - /// @brief A list of reactants - std::vector reactants; - /// @brief A list of nitrate products - std::vector nitrate_products; - /// @brief A list of alkoxy products - std::vector alkoxy_products; - /// @brief An identifier, optional, uniqueness not enforced - std::string name; - /// @brief An identifier indicating which gas phase this reaction takes place in - std::string gas_phase; - /// @brief Unknown properties, prefixed with two underscores (__) - std::unordered_map unknown_properties; - }; - - struct Emission - { - /// @brief Scaling factor to apply to user-provided rate constants - double scaling_factor{ 1.0 }; - /// @brief A list of products - std::vector products; - /// @brief An identifier, optional, uniqueness not enforced - std::string name; - /// @brief An identifier indicating which gas phase this reaction takes place in - std::string gas_phase; - /// @brief Unknown properties, prefixed with two underscores (__) - std::unordered_map unknown_properties; - }; - - struct FirstOrderLoss - { - /// @brief Scaling factor to apply to user-provided rate constants - double scaling_factor{ 1.0 }; - /// @brief A list of products - std::vector products; - /// @brief A list of reactants - std::vector reactants; - /// @brief An identifier, optional, uniqueness not enforced - std::string name; - /// @brief An identifier indicating which gas phase this reaction takes place in - std::string gas_phase; - /// @brief Unknown properties, prefixed with two underscores (__) - std::unordered_map unknown_properties; - }; - - struct Photolysis - { - /// @brief Scaling factor to apply to user-provided rate constants - double scaling_factor{ 1.0 }; - /// @brief A list of reactants - std::vector reactants; - /// @brief A list of products - std::vector products; - /// @brief An identifier, optional, uniqueness not enforced - std::string name; - /// @brief An identifier indicating which gas phase this reaction takes place in - std::string gas_phase; - /// @brief Unknown properties, prefixed with two underscores (__) - std::unordered_map unknown_properties; - }; - - struct Surface - { - /// @brief Reaction probability (0-1) [unitless] - double reaction_probability{ 1.0 }; - /// @brief A list of reactants - ReactionComponent gas_phase_species; - /// @brief A list of products - std::vector gas_phase_products; - /// @brief An identifier, optional, uniqueness not enforced - std::string name; - /// @brief An identifier indicating which gas phase this reaction takes place in - std::string gas_phase; - /// @brief Unknown properties, prefixed with two underscores (__) - std::unordered_map unknown_properties; - }; - - struct TaylorSeries - { - /// @brief Pre-exponential factor [(mol m−3)^(−(𝑛−1)) s−1] - double A{ 1 }; - /// @brief Unitless exponential factor - double B{ 0 }; - /// @brief Activation threshold, expected to be the negative activation energy divided by the boltzman constant - /// [-E_a / k_b), K] - double C{ 0 }; - /// @brief A factor that determines temperature dependence [K] - double D{ 300 }; - /// @brief A factor that determines pressure dependence [Pa-1] - double E{ 0 }; - /// @brief An array of coefficients for the Taylor series expansion - std::vector taylor_coefficients{ 1.0 }; - /// @brief A list of reactants - std::vector reactants; - /// @brief A list of products - std::vector products; - /// @brief An identifier, optional, uniqueness not enforced - std::string name; - /// @brief An identifier indicating which gas phase this reaction takes place in - std::string gas_phase; - /// @brief Unknown properties, prefixed with two underscores (__) - std::unordered_map unknown_properties; - }; - - struct Troe - { - /// @brief low-pressure pre-exponential factor - double k0_A = 1.0; - /// @brief low-pressure temperature-scaling parameter - double k0_B = 0.0; - /// @brief low-pressure exponential factor - double k0_C = 0.0; - /// @brief high-pressure pre-exponential factor - double kinf_A = 1.0; - /// @brief high-pressure temperature-scaling parameter - double kinf_B = 0.0; - /// @brief high-pressure exponential factor - double kinf_C = 0.0; - /// @brief Troe F_c parameter - double Fc = 0.6; - /// @brief Troe N parameter - double N = 1.0; - /// @brief A list of reactants - std::vector reactants; - /// @brief A list of products - std::vector products; - /// @brief An identifier, optional, uniqueness not enforced - std::string name; - /// @brief An identifier indicating which gas phase this reaction takes place in - std::string gas_phase; - /// @brief Unknown properties, prefixed with two underscores (__) - std::unordered_map unknown_properties; - }; - - struct TernaryChemicalActivation - { - /// @brief low-pressure pre-exponential factor - double k0_A = 1.0; - /// @brief low-pressure temperature-scaling parameter - double k0_B = 0.0; - /// @brief low-pressure exponential factor - double k0_C = 0.0; - /// @brief high-pressure pre-exponential factor - double kinf_A = 1.0; - /// @brief high-pressure temperature-scaling parameter - double kinf_B = 0.0; - /// @brief high-pressure exponential factor - double kinf_C = 0.0; - /// @brief TernaryChemicalActivation F_c parameter - double Fc = 0.6; - /// @brief TernaryChemicalActivation N parameter - double N = 1.0; - /// @brief A list of reactants - std::vector reactants; - /// @brief A list of products - std::vector products; - /// @brief An identifier, optional, uniqueness not enforced - std::string name; - /// @brief An identifier indicating which gas phase this reaction takes place in - std::string gas_phase; - /// @brief Unknown properties, prefixed with two underscores (__) - std::unordered_map unknown_properties; - }; - - struct Tunneling - { - /// @brief Pre-exponential factor [(mol m−3)^(−(𝑛−1)) s−1] - double A = 1.0; - /// @brief Linear temperature-dependent parameter [K] - double B = 0.0; - /// @brief Cubed temperature-dependent parameter [K^3] - double C = 0.0; - /// @brief A list of reactants - std::vector reactants; - /// @brief A list of products - std::vector products; - /// @brief An identifier, optional, uniqueness not enforced - std::string name; - /// @brief An identifier indicating which gas phase this reaction takes place in - std::string gas_phase; - /// @brief Unknown properties, prefixed with two underscores (__) - std::unordered_map unknown_properties; - }; - - struct UserDefined - { - /// @brief Scaling factor to apply to user-provided rate constants - double scaling_factor{ 1.0 }; - /// @brief A list of reactants - std::vector reactants; - /// @brief A list of products - std::vector products; - /// @brief An identifier, optional, uniqueness not enforced - std::string name; - /// @brief An identifier indicating which gas phase this reaction takes place in - std::string gas_phase; - /// @brief Unknown properties, prefixed with two underscores (__) - std::unordered_map unknown_properties; - }; - - struct LambdaRateConstant - { - /// @brief A lambda function as a string, expected to be a function of temperature (T) and optionally pressure (P) - std::string lambda_function; - /// @brief A list of reactants - std::vector reactants; - /// @brief A list of products - std::vector products; - /// @brief An identifier, optional, uniqueness not enforced - std::string name; - /// @brief An identifier indicating which gas phase this reaction takes place in - std::string gas_phase; - /// @brief Unknown properties, prefixed with two underscores (__) - std::unordered_map unknown_properties; - }; - - /// @brief Represents a collection of different reaction types - struct Reactions - { - std::vector arrhenius; - std::vector branched; - std::vector emission; - std::vector first_order_loss; - std::vector photolysis; - std::vector surface; - std::vector taylor_series; - std::vector troe; - std::vector ternary_chemical_activation; - std::vector tunneling; - std::vector user_defined; - std::vector lambda_rate_constant; - }; - - } // namespace types - } // namespace v1 -} // namespace mechanism_configuration \ No newline at end of file diff --git a/include/mechanism_configuration/v1/types.hpp b/include/mechanism_configuration/v1/types.hpp deleted file mode 100644 index 789f1ab7..00000000 --- a/include/mechanism_configuration/v1/types.hpp +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright (C) 2023–2026 University Corporation for Atmospheric Research -// University of Illinois at Urbana-Champaign -// SPDX-License-Identifier: Apache-2.0 - -#pragma once - -#include - -#include -#include -#include -#include - -namespace mechanism_configuration -{ - namespace v1 - { - namespace types - { - - struct Species - { - std::string name; - std::optional molecular_weight; - std::optional constant_concentration; - std::optional constant_mixing_ratio; - std::optional is_third_body; - /// @brief Unknown properties, prefixed with two underscores (__) - std::unordered_map unknown_properties; - }; - - struct PhaseSpecies - { - std::string name; - std::optional diffusion_coefficient; - /// @brief Unknown properties, prefixed with two underscores (__) - std::unordered_map unknown_properties; - }; - - struct Phase - { - std::string name; - std::vector species; - /// @brief Unknown properties, prefixed with two underscores (__) - std::unordered_map unknown_properties; - }; - - struct ReactionComponent - { - std::string species_name; - double coefficient{ 1.0 }; - /// @brief Unknown properties, prefixed with two underscores (__) - std::unordered_map unknown_properties; - }; - - } // namespace types - } // namespace v1 -} // namespace mechanism_configuration \ No newline at end of file diff --git a/include/mechanism_configuration/v1/utils.hpp b/include/mechanism_configuration/v1/utils.hpp deleted file mode 100644 index 1f5f0257..00000000 --- a/include/mechanism_configuration/v1/utils.hpp +++ /dev/null @@ -1,103 +0,0 @@ -// Copyright (C) 2023–2026 University Corporation for Atmospheric Research -// University of Illinois at Urbana-Champaign -// SPDX-License-Identifier: Apache-2.0 - -#pragma once - -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include -#include - -namespace mechanism_configuration -{ - namespace v1 - { - struct DuplicateEntryInfo - { - std::string name; - std::vector nodes; - }; - - std::unordered_map GetComments(const YAML::Node& object); - - /// @brief Extract species names from a vector of PhaseSpecies - std::vector GetSpeciesNames(const std::vector& phase_species); - - template - std::vector FindDuplicateObjectsByName(const std::vector>& collection) - { - std::unordered_map> name_to_nodes; - - if constexpr (std::is_same_v) - { - for (const auto& [elem, node] : collection) - { - name_to_nodes[elem].push_back(node); - } - } - else - { - for (const auto& [elem, node] : collection) - { - name_to_nodes[elem.name].push_back(node); - } - } - - std::vector duplicates; - - for (const auto& [name, nodes] : name_to_nodes) - { - if (nodes.size() > 1) - { - duplicates.push_back({ name, nodes }); - } - } - - return duplicates; - } - - template - std::vector FindUnknownSpecies( - const std::vector& requested_species, - const std::vector& existing_species) - { - std::unordered_set existing_names; - - if constexpr (std::is_same_v) - { - for (const auto& species : existing_species) - { - existing_names.insert(species); - } - } - else - { - for (const auto& species : existing_species) - { - existing_names.insert(species.name); - } - } - - std::vector unknown_species; - for (const auto& name : requested_species) - { - if (existing_names.find(name) == existing_names.end()) - { - unknown_species.emplace_back(name); - } - } - - return unknown_species; - } - } // namespace v1 -} // namespace mechanism_configuration diff --git a/include/mechanism_configuration/v1/validation.hpp b/include/mechanism_configuration/v1/validation.hpp deleted file mode 100644 index 6813ec8f..00000000 --- a/include/mechanism_configuration/v1/validation.hpp +++ /dev/null @@ -1,140 +0,0 @@ -// Copyright (C) 2023–2026 University Corporation for Atmospheric Research -// University of Illinois at Urbana-Champaign -// SPDX-License-Identifier: Apache-2.0 - -#pragma once - -namespace mechanism_configuration -{ - namespace v1 - { - namespace validation - { - // Shared, but also Mechanism - static constexpr const char* version = "version"; - static constexpr const char* name = "name"; - - // Configuration - static constexpr const char* species = "species"; - static constexpr const char* phases = "phases"; - static constexpr const char* reactions = "reactions"; - - // Species - static constexpr const char* molecular_weight = "molecular weight [kg mol-1]"; - static constexpr const char* constant_concentration = "constant concentration [mol m-3]"; - static constexpr const char* constant_mixing_ratio = "constant mixing ratio [mol mol-1]"; - static constexpr const char* is_third_body = "is third body"; - - // Phase-species - static constexpr const char* diffusion_coefficient = "diffusion coefficient [m2 s-1]"; - - // Reactions - static constexpr const char* reactants = "reactants"; - static constexpr const char* products = "products"; - static constexpr const char* type = "type"; - static constexpr const char* gas_phase = "gas phase"; - - // Reactant and product - static constexpr const char* species_name = "species name"; - static constexpr const char* coefficient = "coefficient"; - - // ---------------------------------------- - // Reaction types - // ---------------------------------------- - - // Arrhenius - static constexpr const char* Arrhenius_key = "ARRHENIUS"; - static constexpr const char* A = "A"; - static constexpr const char* B = "B"; - static constexpr const char* C = "C"; - static constexpr const char* D = "D"; - static constexpr const char* E = "E"; - static constexpr const char* Ea = "Ea"; - - // TaylorSeries - static constexpr const char* TaylorSeries_key = "TAYLOR_SERIES"; - static constexpr const char* taylor_coefficients = "taylor coefficients"; - // also these - // A - // B - // C - // D - // E - // Ea - - // Troe - static constexpr const char* Troe_key = "TROE"; - static constexpr const char* k0_A = "k0_A"; - static constexpr const char* k0_B = "k0_B"; - static constexpr const char* k0_C = "k0_C"; - static constexpr const char* kinf_A = "kinf_A"; - static constexpr const char* kinf_B = "kinf_B"; - static constexpr const char* kinf_C = "kinf_C"; - static constexpr const char* Fc = "Fc"; - static constexpr const char* N = "N"; - - // Ternary Chemical Activation - static constexpr const char* TernaryChemicalActivation_key = "TERNARY_CHEMICAL_ACTIVATION"; - // also k0_A - // k0_B - // k0_C - // kinf_A - // kinf_B - // kinf_C - // Fc - // N - - // Branched - static constexpr const char* Branched_key = "BRANCHED_NO_RO2"; - static constexpr const char* X = "X"; - static constexpr const char* Y = "Y"; - static constexpr const char* a0 = "a0"; - static constexpr const char* n = "n"; - static constexpr const char* nitrate_products = "nitrate products"; - static constexpr const char* alkoxy_products = "alkoxy products"; - - // Tunneling - static constexpr const char* Tunneling_key = "TUNNELING"; - // also these, but they are defined above - // A - // B - // C - - // Surface - static constexpr const char* Surface_key = "SURFACE"; - static constexpr const char* reaction_probability = "reaction probability"; - static constexpr const char* gas_phase_species = "gas-phase species"; - static constexpr const char* gas_phase_products = "gas-phase products"; - - // Photolysis - static constexpr const char* Photolysis_key = "PHOTOLYSIS"; - static constexpr const char* scaling_factor = "scaling factor"; - - // Emissions - static constexpr const char* Emission_key = "EMISSION"; - // also scaling factor - - // First Order Loss - static constexpr const char* FirstOrderLoss_key = "FIRST_ORDER_LOSS"; - // also scaling factor - - // User Defined - static constexpr const char* UserDefined_key = "USER_DEFINED"; - // also - // gas phase - // reactants - // products - // scaling factor - - // Lambda Rate Constant - static constexpr const char* LambdaRateConstant_key = "LAMBDA_RATE_CONSTANT"; - static constexpr const char* lambda_function = "lambda function"; - // also - // gas phase - // reactants - // products - // name - - } // namespace validation - } // namespace v1 -} // namespace mechanism_configuration \ No newline at end of file diff --git a/include/mechanism_configuration/validate.hpp b/include/mechanism_configuration/validate.hpp new file mode 100644 index 00000000..c603271a --- /dev/null +++ b/include/mechanism_configuration/validate.hpp @@ -0,0 +1,63 @@ +// Copyright (C) 2023–2026 University Corporation for Atmospheric Research +// University of Illinois at Urbana-Champaign +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include +#include + +#include +#include +#include + +namespace mechanism_configuration +{ + // Intermediate over which all semantic validation runs. Both a parsed document and an + // in-code Mechanism produce one of these and hand it to ValidateSemantics, so the rules + // live in exactly one place. A parsed document fills in source locations (so errors carry + // line:col); an in-code Mechanism leaves them empty. The domain types stay location-free. + namespace semantics + { + struct NamedRef + { + std::string name; + std::optional location; + }; + + struct PhaseRef + { + std::string name; + std::vector species; + std::optional location; + }; + + struct ReactionRef + { + std::string type; + std::string phase; + std::vector reactants; // must exist and be registered in `phase` + std::vector products; // must exist; may belong to any phase + std::optional location; + }; + + struct Input + { + std::vector species; + std::vector phases; + std::vector reactions; + }; + } // namespace semantics + + /// @brief The single home for the mechanism's semantic rules. Errors include `line:col` + /// for any element whose source location was supplied. + Errors ValidateSemantics(const semantics::Input& input); + + /// @brief Validates the semantic invariants of a canonical Mechanism, independent of how it + /// was produced (parsed from any version, or constructed in code). Convenience wrapper + /// that builds a location-free semantics::Input and calls ValidateSemantics. + /// + /// Structural/deserialization concerns (YAML keys, types, formatting) are the responsibility + /// of the version-specific parsers and are not repeated here. + Errors Validate(const Mechanism& mechanism); +} // namespace mechanism_configuration diff --git a/include/mechanism_configuration/validate_schema.hpp b/include/mechanism_configuration/validate_schema.hpp deleted file mode 100644 index d6232eed..00000000 --- a/include/mechanism_configuration/validate_schema.hpp +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (C) 2023–2026 University Corporation for Atmospheric Research -// University of Illinois at Urbana-Champaign -// SPDX-License-Identifier: Apache-2.0 - -#pragma once - -#include -#include - -#include - -#include -#include - -namespace mechanism_configuration -{ - Errors ValidateSchema( - const YAML::Node& object, - const std::vector& required_keys, - const std::vector& optional_keys); -} // namespace mechanism_configuration diff --git a/include/mechanism_configuration/version.hpp b/include/mechanism_configuration/version.hpp index ea47ad36..a3e11ce6 100644 --- a/include/mechanism_configuration/version.hpp +++ b/include/mechanism_configuration/version.hpp @@ -1,3 +1,7 @@ +// Copyright (C) 2023–2026 University Corporation for Atmospheric Research +// University of Illinois at Urbana-Champaign +// SPDX-License-Identifier: Apache-2.0 + // clang-format off #pragma once @@ -9,19 +13,19 @@ extern "C" { const char* getVersionString() { - return "1.1.2"; + return "2.0.0"; } unsigned getVersionMajor() { - return 1; + return 2; } unsigned getVersionMinor() { - return 1+0; + return 0+0; } unsigned getVersionPatch() { - return 2+0; + return 0+0; } unsigned getVersionTweak() { diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 8a686138..be92c6e0 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -10,7 +10,7 @@ endif() add_library(musica::mechanism_configuration ALIAS mechanism_configuration) -target_compile_features(mechanism_configuration PUBLIC cxx_std_20) +target_compile_features(mechanism_configuration PUBLIC cxx_std_23) if(MECH_CONFIG_USE_FMT) target_compile_definitions(mechanism_configuration PUBLIC MECH_CONFIG_USE_FMT) @@ -27,20 +27,22 @@ set_target_properties(mechanism_configuration PROPERTIES target_sources(mechanism_configuration PRIVATE - parse_status.cpp - parser.cpp - validate_schema.cpp + errors.cpp + parse.cpp + validate.cpp + check_schema.cpp ) target_include_directories(mechanism_configuration PUBLIC $ $ + PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR} ) add_subdirectory(v0) add_subdirectory(v1) -add_subdirectory(development) target_link_libraries(mechanism_configuration PUBLIC diff --git a/src/validate_schema.cpp b/src/check_schema.cpp similarity index 53% rename from src/validate_schema.cpp rename to src/check_schema.cpp index 64f17cd1..8d7704c7 100644 --- a/src/validate_schema.cpp +++ b/src/check_schema.cpp @@ -2,18 +2,18 @@ // University of Illinois at Urbana-Champaign // SPDX-License-Identifier: Apache-2.0 -#include #include -#include +#include "detail/check_schema.hpp" #include namespace mechanism_configuration { - Errors ValidateSchema( + Errors CheckSchema( const YAML::Node& object, - const std::vector& required_keys, - const std::vector& optional_keys) + const std::vector& required_keys, + const std::vector& optional_keys, + const std::vector>& exactly_one_of) { Errors errors; ErrorLocation error_location{ object.Mark().line, object.Mark().column }; @@ -21,7 +21,7 @@ namespace mechanism_configuration if (!object || object.IsNull()) { std::string message = mc_fmt::format("{} error: Object is null.", error_location); - errors.push_back({ ConfigParseStatus::EmptyObject, message }); + errors.push_back({ ErrorCode::EmptyObject, message }); return errors; } @@ -33,9 +33,9 @@ namespace mechanism_configuration object_keys.emplace_back(key.first.as()); } - // Sort keys for comparison - auto sorted_required_keys = required_keys; - auto sorted_optional_keys = optional_keys; + // Sort keys for comparison (own the strings so comparisons stay homogeneous) + std::vector sorted_required_keys(required_keys.begin(), required_keys.end()); + std::vector sorted_optional_keys(optional_keys.begin(), optional_keys.end()); std::sort(object_keys.begin(), object_keys.end()); std::sort(sorted_required_keys.begin(), sorted_required_keys.end()); std::sort(sorted_optional_keys.begin(), sorted_optional_keys.end()); @@ -52,9 +52,46 @@ namespace mechanism_configuration for (const auto& key : missing_keys) { std::string message = mc_fmt::format("{} error: Required key '{}' is missing.", error_location, key); - errors.push_back({ ConfigParseStatus::RequiredKeyNotFound, message }); + errors.push_back({ ErrorCode::RequiredKeyNotFound, message }); } + // Exactly-one-of groups: exactly one member of each group must be present. + // Group members also count as allowed keys, so they are never flagged as invalid. + for (const auto& group : exactly_one_of) + { + std::vector present; + for (const auto& key : group) + { + std::string key_str(key); + sorted_optional_keys.push_back(key_str); + if (std::find(object_keys.begin(), object_keys.end(), key_str) != object_keys.end()) + present.push_back(key_str); + } + + if (present.size() != 1) + { + std::string joined; + for (size_t i = 0; i < group.size(); ++i) + { + joined += "'" + std::string(group[i]) + "'"; + if (i + 1 < group.size()) + joined += ", "; + } + + if (present.empty()) + { + std::string message = mc_fmt::format("{} error: Exactly one of {} is required.", error_location, joined); + errors.push_back({ ErrorCode::RequiredKeyNotFound, message }); + } + else + { + std::string message = mc_fmt::format("{} error: Only one of {} may be specified.", error_location, joined); + errors.push_back({ ErrorCode::MutuallyExclusiveOption, message }); + } + } + } + std::sort(sorted_optional_keys.begin(), sorted_optional_keys.end()); + // Find keys that are neither required nor optional std::vector extra_keys; std::set_difference( @@ -78,7 +115,7 @@ namespace mechanism_configuration if (key.find("__") == std::string::npos) { std::string message = mc_fmt::format("{} error: Non-standard key '{}' found.", error_location, key); - errors.push_back({ ConfigParseStatus::InvalidKey, message }); + errors.push_back({ ErrorCode::InvalidKey, message }); } } diff --git a/src/detail/check_schema.hpp b/src/detail/check_schema.hpp new file mode 100644 index 00000000..0aa0b997 --- /dev/null +++ b/src/detail/check_schema.hpp @@ -0,0 +1,30 @@ +// Copyright (C) 2023–2026 University Corporation for Atmospheric Research +// University of Illinois at Urbana-Champaign +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include + +#include + +#include +#include +#include + +namespace mechanism_configuration +{ + /// @brief Checks the keys of a YAML object against a schema. + /// @param object The YAML node to validate + /// @param required_keys Keys that must all be present + /// @param optional_keys Keys that may be present + /// @param exactly_one_of Groups of mutually-exclusive keys; exactly one member of each + /// group must be present (zero -> RequiredKeyNotFound, more than one -> + /// MutuallyExclusiveOption). Group members are treated as allowed keys. + /// @return A collection of schema errors; empty if the object conforms. + Errors CheckSchema( + const YAML::Node& object, + const std::vector& required_keys, + const std::vector& optional_keys, + const std::vector>& exactly_one_of = {}); +} // namespace mechanism_configuration diff --git a/include/mechanism_configuration/constants.hpp b/src/detail/constants.hpp similarity index 100% rename from include/mechanism_configuration/constants.hpp rename to src/detail/constants.hpp diff --git a/include/mechanism_configuration/conversions.hpp b/src/detail/conversions.hpp similarity index 89% rename from include/mechanism_configuration/conversions.hpp rename to src/detail/conversions.hpp index 41f0f6ff..7eb5c9d8 100644 --- a/include/mechanism_configuration/conversions.hpp +++ b/src/detail/conversions.hpp @@ -4,7 +4,7 @@ #pragma once -#include +#include namespace mechanism_configuration { diff --git a/src/detail/v0/keys.hpp b/src/detail/v0/keys.hpp new file mode 100644 index 00000000..b6ec9200 --- /dev/null +++ b/src/detail/v0/keys.hpp @@ -0,0 +1,61 @@ +// Copyright (C) 2023–2026 University Corporation for Atmospheric Research +// University of Illinois at Urbana-Champaign +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include +#include + +namespace mechanism_configuration::v0::keys +{ + inline constexpr std::string_view NAME = "name"; + inline constexpr std::string_view TYPE = "type"; + + inline constexpr std::string_view VALUE = "value"; + + inline constexpr std::string_view REACTIONS = "reactions"; + + inline constexpr std::string_view TRACER_TYPE = "tracer type"; + inline constexpr std::string_view ABS_TOLERANCE = "absolute tolerance"; + inline constexpr std::string_view DIFFUSION_COEFF = "diffusion coefficient [m2 s-1]"; + inline constexpr std::string_view MOL_WEIGHT = "molecular weight [kg mol-1]"; + inline constexpr std::string_view THIRD_BODY = "THIRD_BODY"; + + inline constexpr std::string_view REACTANTS = "reactants"; + inline constexpr std::string_view PRODUCTS = "products"; + inline constexpr std::string_view MUSICA_NAME = "MUSICA name"; + inline constexpr std::string_view SCALING_FACTOR = "scaling factor"; + inline constexpr std::string_view GAS_PHASE_REACTANT = "gas-phase reactant"; + inline constexpr std::string_view GAS_PHASE_PRODUCTS = "gas-phase products"; + + inline constexpr std::string_view QTY = "qty"; + inline constexpr std::string_view YIELD = "yield"; + + inline constexpr std::string_view SPECIES = "species"; + + inline constexpr std::string_view ALKOXY_PRODUCTS = "alkoxy products"; + inline constexpr std::string_view NITRATE_PRODUCTS = "nitrate products"; + inline constexpr std::string_view X = "X"; + inline constexpr std::string_view Y = "Y"; + inline constexpr std::string_view A0 = "a0"; + inline constexpr std::string_view N = "N"; + inline constexpr std::string_view n = "n"; + + inline constexpr std::string_view PROBABILITY = "reaction probability"; + + inline constexpr std::string_view A = "A"; + inline constexpr std::string_view B = "B"; + inline constexpr std::string_view C = "C"; + inline constexpr std::string_view D = "D"; + inline constexpr std::string_view E = "E"; + inline constexpr std::string_view Ea = "Ea"; + + inline constexpr std::string_view K0_A = "k0_A"; + inline constexpr std::string_view K0_B = "k0_B"; + inline constexpr std::string_view K0_C = "k0_C"; + inline constexpr std::string_view KINF_A = "kinf_A"; + inline constexpr std::string_view KINF_B = "kinf_B"; + inline constexpr std::string_view KINF_C = "kinf_C"; + inline constexpr std::string_view FC = "Fc"; +} // namespace mechanism_configuration::v0::keys \ No newline at end of file diff --git a/src/detail/v0/parser.hpp b/src/detail/v0/parser.hpp new file mode 100644 index 00000000..bb63ab8c --- /dev/null +++ b/src/detail/v0/parser.hpp @@ -0,0 +1,31 @@ +// Copyright (C) 2023–2026 University Corporation for Atmospheric Research +// University of Illinois at Urbana-Champaign +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include +#include + +#include + +#include +#include +#include + +namespace mechanism_configuration::v0 +{ + class Parser + { + const std::string DEFAULT_CONFIG_FILE_JSON = "config.json"; + const std::string DEFAULT_CONFIG_FILE_YAML = "config.yaml"; + const std::string CAMP_FILES = "camp-files"; + const std::string CAMP_DATA = "camp-data"; + const std::string TYPE = "type"; + + Errors GetCampFiles(const std::filesystem::path& config_path, std::vector& camp_files); + + public: + std::expected Parse(const std::filesystem::path& config_path); + }; +} // namespace mechanism_configuration::v0 diff --git a/src/detail/v0/parser_types.hpp b/src/detail/v0/parser_types.hpp new file mode 100644 index 00000000..9dae5f2f --- /dev/null +++ b/src/detail/v0/parser_types.hpp @@ -0,0 +1,34 @@ +// Copyright (C) 2023–2026 University Corporation for Atmospheric Research +// University of Illinois at Urbana-Champaign +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include +#include +#include + +#include + +#include + +namespace mechanism_configuration::v0 +{ + // species and mechanism + Errors ParseChemicalSpecies(Mechanism& mechanism, const YAML::Node& object); + Errors ParseProducts(const YAML::Node& object, std::vector& products); + Errors ParseReactants(const YAML::Node& object, std::vector& reactants); + Errors ParseRelativeTolerance(Mechanism& mechanism, const YAML::Node& object); + + // reactions + Errors ArrheniusParser(Mechanism& mechanism, const YAML::Node& object); + Errors BranchedParser(Mechanism& mechanism, const YAML::Node& object); + Errors EmissionParser(Mechanism& mechanism, const YAML::Node& object); + Errors FirstOrderLossParser(Mechanism& mechanism, const YAML::Node& object); + Errors PhotolysisParser(Mechanism& mechanism, const YAML::Node& object); + Errors SurfaceParser(Mechanism& mechanism, const YAML::Node& object); + Errors TernaryChemicalActivationParser(Mechanism& mechanism, const YAML::Node& object); + Errors TroeParser(Mechanism& mechanism, const YAML::Node& object); + Errors TunnelingParser(Mechanism& mechanism, const YAML::Node& object); + Errors UserDefinedParser(Mechanism& mechanism, const YAML::Node& object); +} // namespace mechanism_configuration::v0 diff --git a/src/detail/v1/keys.hpp b/src/detail/v1/keys.hpp new file mode 100644 index 00000000..939a1337 --- /dev/null +++ b/src/detail/v1/keys.hpp @@ -0,0 +1,179 @@ +// Copyright (C) 2023–2026 University Corporation for Atmospheric Research +// University of Illinois at Urbana-Champaign +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include + +namespace mechanism_configuration::v1::keys +{ + // Shared, but also Mechanism + inline constexpr std::string_view version = "version"; + inline constexpr std::string_view name = "name"; + // Legacy alias for a reaction component's species reference, accepted alongside `name` + // for backward compatibility with v1 configuration files. + inline constexpr std::string_view species_name = "species name"; + + // Configuration + inline constexpr std::string_view species = "species"; + inline constexpr std::string_view phases = "phases"; + inline constexpr std::string_view models = "models"; + inline constexpr std::string_view reactions = "reactions"; + + // Species + inline constexpr std::string_view absolute_tolerance = "absolute tolerance"; + inline constexpr std::string_view diffusion_coefficient = "diffusion coefficient [m2 s-1]"; + inline constexpr std::string_view molecular_weight = "molecular weight [kg mol-1]"; + inline constexpr std::string_view henrys_law_constant_298 = "HLC(298K) [mol m-3 Pa-1]"; + inline constexpr std::string_view henrys_law_constant_exponential_factor = "HLC exponential factor [K]"; + inline constexpr std::string_view n_star = "N star"; + inline constexpr std::string_view density = "density [kg m-3]"; + inline constexpr std::string_view tracer_type = "tracer type"; + inline constexpr std::string_view constant_concentration = "constant concentration [mol m-3]"; + inline constexpr std::string_view constant_mixing_ratio = "constant mixing ratio [mol mol-1]"; + inline constexpr std::string_view is_third_body = "is third body"; + inline constexpr std::string_view third_body = "THIRD_BODY"; + + // Reactions + inline constexpr std::string_view reactants = "reactants"; + inline constexpr std::string_view products = "products"; + inline constexpr std::string_view type = "type"; + inline constexpr std::string_view gas_phase = "gas phase"; + + // Reactant and product + inline constexpr std::string_view coefficient = "coefficient"; + // also name + + // ---------------------------------------- + // Reaction types + // ---------------------------------------- + + // Arrhenius + inline constexpr std::string_view Arrhenius_key = "ARRHENIUS"; + inline constexpr std::string_view A = "A"; + inline constexpr std::string_view B = "B"; + inline constexpr std::string_view C = "C"; + inline constexpr std::string_view D = "D"; + inline constexpr std::string_view E = "E"; + inline constexpr std::string_view Ea = "Ea"; + + // TaylorSeries + inline constexpr std::string_view TaylorSeries_key = "TAYLOR_SERIES"; + inline constexpr std::string_view taylor_coefficients = "taylor coefficients"; + // also these + // A + // B + // C + // D + // E + // Ea + + // Condensed Phase Arrhenius + inline constexpr std::string_view CondensedPhaseArrhenius_key = "CONDENSED_PHASE_ARRHENIUS"; + // also these + // condensed phase + // A + // B + // C + // D + // E + // Ea + + // Troe + inline constexpr std::string_view Troe_key = "TROE"; + inline constexpr std::string_view k0_A = "k0_A"; + inline constexpr std::string_view k0_B = "k0_B"; + inline constexpr std::string_view k0_C = "k0_C"; + inline constexpr std::string_view kinf_A = "kinf_A"; + inline constexpr std::string_view kinf_B = "kinf_B"; + inline constexpr std::string_view kinf_C = "kinf_C"; + inline constexpr std::string_view Fc = "Fc"; + inline constexpr std::string_view N = "N"; + + // Ternary Chemical Activation + inline constexpr std::string_view TernaryChemicalActivation_key = "TERNARY_CHEMICAL_ACTIVATION"; + // also k0_A + // k0_B + // k0_C + // kinf_A + // kinf_B + // kinf_C + // Fc + // N + + // Branched + inline constexpr std::string_view Branched_key = "BRANCHED_NO_RO2"; + inline constexpr std::string_view X = "X"; + inline constexpr std::string_view Y = "Y"; + inline constexpr std::string_view a0 = "a0"; + inline constexpr std::string_view n = "n"; + inline constexpr std::string_view nitrate_products = "nitrate products"; + inline constexpr std::string_view alkoxy_products = "alkoxy products"; + + // Tunneling + inline constexpr std::string_view Tunneling_key = "TUNNELING"; + // also these, but they are defined above + // A + // B + // C + + // Surface + inline constexpr std::string_view Surface_key = "SURFACE"; + inline constexpr std::string_view reaction_probability = "reaction probability"; + inline constexpr std::string_view gas_phase_species = "gas-phase species"; + inline constexpr std::string_view gas_phase_products = "gas-phase products"; + inline constexpr std::string_view condensed_phase = "condensed phase"; + + // Photolysis + inline constexpr std::string_view Photolysis_key = "PHOTOLYSIS"; + inline constexpr std::string_view scaling_factor = "scaling factor"; + + // Condensed Phae Photolysis + inline constexpr std::string_view CondensedPhasePhotolysis_key = "CONDENSED_PHASE_PHOTOLYSIS"; + // also + // scaling factor + // condensed phase + + // Emissions + inline constexpr std::string_view Emission_key = "EMISSION"; + // also scaling factor + + // First Order Loss + inline constexpr std::string_view FirstOrderLoss_key = "FIRST_ORDER_LOSS"; + // also scaling factor + + // Simpol Phase Transfer + inline constexpr std::string_view SimpolPhaseTransfer_key = "SIMPOL_PHASE_TRANSFER"; + inline constexpr std::string_view condensed_phase_species = "condensed-phase species"; + // also + // gas phase + // gas-phase species + // condensed phase + // condensed-phase species + // B + + // Wet Deposition + inline constexpr std::string_view WetDeposition_key = "WET_DEPOSITION"; + // also + // scaling factor + // condensed phase + + // User Defined + inline constexpr std::string_view UserDefined_key = "USER_DEFINED"; + // also + // gas phase + // reactants + // products + // scaling factor + + // Lambda Rate Constant + inline constexpr std::string_view LambdaRateConstant_key = "LAMBDA_RATE_CONSTANT"; + inline constexpr std::string_view lambda_function = "lambda function"; + // also + // gas phase + // reactants + // products + // name + +} // namespace mechanism_configuration::v1::keys diff --git a/src/detail/v1/parser.hpp b/src/detail/v1/parser.hpp new file mode 100644 index 00000000..22197bf7 --- /dev/null +++ b/src/detail/v1/parser.hpp @@ -0,0 +1,73 @@ +// Copyright (C) 2023–2026 University Corporation for Atmospheric Research +// University of Illinois at Urbana-Champaign +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include +#include + +#include + +#include +#include +#include + +namespace mechanism_configuration::v1 +{ + /// @brief Extracts a located semantics::Input from a fully-resolved (inline) v1 YAML node, so + /// the version-neutral ValidateSemantics can run the semantic checks with line:col. + semantics::Input BuildSemanticInput(const YAML::Node& object); + + class Parser + { + public: + Parser() = default; + + /// @brief Parse a v1 mechanism from a configuration file: resolves any file-list sections + /// (v1.1+ `{ files: [...] }`) into a single document, validates it, and builds the + /// Mechanism. This is the file entry point — no separate resolve/validate step. + /// @param config_path Path to the main configuration file. + /// @return The parsed Mechanism, or all structural / file-loading / semantic errors. + std::expected Parse(const std::filesystem::path& config_path); + + /// @brief Parse a v1 mechanism from an in-memory YAML/JSON document string. + /// @param content The document contents (not a file path). + /// @return The parsed Mechanism, or all structural and semantic errors. + std::expected Parse(const std::string& content); + + /// @brief Validate an already-loaded YAML node (structure + semantics) and build the + /// Mechanism. Validation always runs first, so a caller cannot build from an + /// unvalidated node. + /// @param object The YAML node to validate and parse + /// @return The parsed Mechanism, or all structural and semantic errors encountered + std::expected Parse(const YAML::Node& object); + + private: + std::string config_path_; + + /// @brief Resolves a configuration file's file-list sections into a single inline node. + std::expected ResolveFileConfig(const std::filesystem::path& config_path); + + /// @brief Runs structural then semantic validation and, if both pass, builds the Mechanism, + /// mapping any thrown exception to an error. Uses config_path_ for message prefixes. + std::expected ValidateAndBuild(const YAML::Node& object); + + /// @brief Checks the structural schema of a mechanism YAML node (keys/shape only). Semantic + /// invariants are checked separately by ValidateSemantics. + Errors CheckSchema(const YAML::Node& object); + + /// @brief Constructs a Mechanism from an already-validated node. + Mechanism Build(const YAML::Node& object); + + inline void SetConfigPath(const std::string& config_path) + { + config_path_ = config_path; + } + + inline void SetDefaultConfigPath() + { + config_path_ = ""; + } + }; +} // namespace mechanism_configuration::v1 \ No newline at end of file diff --git a/src/detail/v1/reaction_parsers.hpp b/src/detail/v1/reaction_parsers.hpp new file mode 100644 index 00000000..41455c5f --- /dev/null +++ b/src/detail/v1/reaction_parsers.hpp @@ -0,0 +1,195 @@ +// Copyright (C) 2023–2026 University Corporation for Atmospheric Research +// University of Illinois at Urbana-Champaign +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include +#include + +#include +#include + +#include + +namespace mechanism_configuration::v1 +{ + /// @brief Abstract interface for reaction parsers + class IReactionParser + { + public: + /// @brief Checks the schema of a YAML node representing a chemical reaction + /// @param object The YAML node containing reaction information + /// @param existing_species A list of species previously defined in the mechanism + /// @param existing_phases A list of chemical phases relevant to the reaction + /// @return A list of any validation errors encountered + virtual Errors CheckSchema( + const YAML::Node& object, + const std::vector& existing_species, + const std::vector& existing_phases) = 0; + + /// @brief Parses a YAML node representing a chemical reaction + /// @param object The YAML node containing reaction information + /// @param reactions The container to which the parsed reactions will be added + virtual void Parse(const YAML::Node& object, types::Reactions& reactions) = 0; + + /// @brief Destructor + virtual ~IReactionParser() = default; + }; + + class ArrheniusParser : public IReactionParser + { + public: + Errors CheckSchema( + const YAML::Node& object, + const std::vector& existing_species, + const std::vector& existing_phases) override; + + void Parse(const YAML::Node& object, types::Reactions& reactions) override; + }; + + class BranchedParser : public IReactionParser + { + public: + Errors CheckSchema( + const YAML::Node& object, + const std::vector& existing_species, + const std::vector& existing_phases) override; + + void Parse(const YAML::Node& object, types::Reactions& reactions) override; + }; + + class EmissionParser : public IReactionParser + { + public: + Errors CheckSchema( + const YAML::Node& object, + const std::vector& existing_species, + const std::vector& existing_phases) override; + + void Parse(const YAML::Node& object, types::Reactions& reactions) override; + }; + + class FirstOrderLossParser : public IReactionParser + { + public: + Errors CheckSchema( + const YAML::Node& object, + const std::vector& existing_species, + const std::vector& existing_phases) override; + + void Parse(const YAML::Node& object, types::Reactions& reactions) override; + }; + + class PhotolysisParser : public IReactionParser + { + public: + Errors CheckSchema( + const YAML::Node& object, + const std::vector& existing_species, + const std::vector& existing_phases) override; + + void Parse(const YAML::Node& object, types::Reactions& reactions) override; + }; + + class SurfaceParser : public IReactionParser + { + public: + Errors CheckSchema( + const YAML::Node& object, + const std::vector& existing_species, + const std::vector& existing_phases) override; + + void Parse(const YAML::Node& object, types::Reactions& reactions) override; + }; + + class TaylorSeriesParser : public IReactionParser + { + public: + Errors CheckSchema( + const YAML::Node& object, + const std::vector& existing_species, + const std::vector& existing_phases) override; + + void Parse(const YAML::Node& object, types::Reactions& reactions) override; + }; + + class TroeParser : public IReactionParser + { + public: + Errors CheckSchema( + const YAML::Node& object, + const std::vector& existing_species, + const std::vector& existing_phases) override; + + void Parse(const YAML::Node& object, types::Reactions& reactions) override; + }; + + class TernaryChemicalActivationParser : public IReactionParser + { + public: + Errors CheckSchema( + const YAML::Node& object, + const std::vector& existing_species, + const std::vector& existing_phases) override; + + void Parse(const YAML::Node& object, types::Reactions& reactions) override; + }; + + class TunnelingParser : public IReactionParser + { + public: + Errors CheckSchema( + const YAML::Node& object, + const std::vector& existing_species, + const std::vector& existing_phases) override; + + void Parse(const YAML::Node& object, types::Reactions& reactions) override; + }; + + class UserDefinedParser : public IReactionParser + { + public: + Errors CheckSchema( + const YAML::Node& object, + const std::vector& existing_species, + const std::vector& existing_phases) override; + + void Parse(const YAML::Node& object, types::Reactions& reactions) override; + }; + + class LambdaRateConstantParser : public IReactionParser + { + public: + Errors CheckSchema( + const YAML::Node& object, + const std::vector& existing_species, + const std::vector& existing_phases) override; + + void Parse(const YAML::Node& object, types::Reactions& reactions) override; + }; + + /// @brief Returns a static map of reaction type keys to their parser instances + inline std::map>& GetReactionParserMap() + { + static std::map> reaction_parsers = [] + { + std::map> map; + map[std::string(keys::Arrhenius_key)] = std::make_unique(); + map[std::string(keys::FirstOrderLoss_key)] = std::make_unique(); + map[std::string(keys::Emission_key)] = std::make_unique(); + map[std::string(keys::Photolysis_key)] = std::make_unique(); + map[std::string(keys::Surface_key)] = std::make_unique(); + map[std::string(keys::TaylorSeries_key)] = std::make_unique(); + map[std::string(keys::Tunneling_key)] = std::make_unique(); + map[std::string(keys::Branched_key)] = std::make_unique(); + map[std::string(keys::Troe_key)] = std::make_unique(); + map[std::string(keys::TernaryChemicalActivation_key)] = std::make_unique(); + map[std::string(keys::UserDefined_key)] = std::make_unique(); + map[std::string(keys::LambdaRateConstant_key)] = std::make_unique(); + return map; + }(); + + return reaction_parsers; + } +} // namespace mechanism_configuration::v1 diff --git a/src/detail/v1/type_parsers.hpp b/src/detail/v1/type_parsers.hpp new file mode 100644 index 00000000..51ef29e6 --- /dev/null +++ b/src/detail/v1/type_parsers.hpp @@ -0,0 +1,51 @@ +// Copyright (C) 2023–2026 University Corporation for Atmospheric Research +// University of Illinois at Urbana-Champaign +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include +#include + +#include + +#include +#include + +namespace mechanism_configuration::v1 +{ + /// @brief Parses a YAML node into a vector of Species + /// The input must be validated using CheckSpeciesSchema(). + /// This function assumes the structure and types are correct. + /// @param objects YAML node representing species list + /// @return A vector of parsed species + std::vector ParseSpecies(const YAML::Node& objects); + + /// @brief Parses a YAML node into a vector of Phases + /// Extracts each phase's name and its associated species (including optional properties). + /// Assumes the input YAML has already been validated for required structure and keys. + /// @param objects YAML node representing phase list + /// @return A vector of parsed Phases + std::vector ParsePhases(const YAML::Node& objects); + + /// @brief Parses a YAML node into reaction components + /// @param object YAML node representing ReactionComponents + /// @param key Key of the sequence to parse + /// @return Vector of `types::ReactionComponent` with names, optional coefficients, and comments + std::vector ParseReactionComponents(const YAML::Node& object, std::string_view key); + + /// @brief Parses a single reaction component from a YAML node. + /// The parser performs no validation or error checking. + /// @param object YAML node representing ReactionComponents + /// @param key Key identifying the reaction component + /// @return The parsed `types::ReactionComponent`, or a default-constructed one if none found + types::ReactionComponent ParseReactionComponent(const YAML::Node& object, std::string_view key); + + /// @brief Parses a collection of YAML nodes into reaction objects + /// Iterates over the given YAML nodes, identifies the parser for each reaction type, + /// and populates a `types::Reactions` container with the parsed reactions. + /// @param objects YAML node containing multiple reaction definitions + /// @return A `types::Reactions` object with all successfully parsed reactions + types::Reactions ParseReactions(const YAML::Node& objects); + +} // namespace mechanism_configuration::v1 diff --git a/src/detail/v1/type_schema.hpp b/src/detail/v1/type_schema.hpp new file mode 100644 index 00000000..7d5e9c6a --- /dev/null +++ b/src/detail/v1/type_schema.hpp @@ -0,0 +1,46 @@ +// Copyright (C) 2023–2026 University Corporation for Atmospheric Research +// University of Illinois at Urbana-Champaign +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include +#include + +#include + +namespace mechanism_configuration::v1 +{ + // Structural (schema) validation of v1 YAML. These check required/optional keys and value + // shape only; semantic invariants (duplicate names, unknown species, phase membership) are + // checked separately by the version-neutral ValidateSemantics on the built Mechanism. + + /// @brief Schema-validates each species entry's keys. + /// @param species_list YAML node containing species entries + /// @return List of structural errors, or empty if all entries conform + Errors CheckSpeciesSchema(const YAML::Node& species_list); + + /// @brief Schema-validates each phase and its phase-species entries. + /// @param phases_list YAML node containing the list of phase entries + /// @param existing_species Unused; retained for call-site compatibility + /// @return List of structural errors, or empty if all entries conform + Errors CheckPhasesSchema(const YAML::Node& phases_list, const std::vector& existing_species); + + /// @brief Schema-validates a sequence of reaction components (reactants or products), + /// requiring exactly one of `name` / `species name` plus an optional coefficient. + /// @param object YAML node representing a sequence of reactants or products + /// @return List of structural errors, or empty if all entries conform + Errors CheckReactantsOrProductsSchema(const YAML::Node& object); + + /// @brief Schema-validates a YAML list of reactions: each has a defined, recognized type, + /// and then each reaction's keys are validated by its parser. + /// @param reactions_list YAML node containing the list of reactions + /// @param existing_species Unused; retained for call-site compatibility + /// @param existing_phases Unused; retained for call-site compatibility + /// @return List of structural errors, or empty if all entries conform + Errors CheckReactionsSchema( + const YAML::Node& reactions_list, + const std::vector& existing_species, + const std::vector& existing_phases); + +} // namespace mechanism_configuration::v1 \ No newline at end of file diff --git a/src/detail/v1/utils.hpp b/src/detail/v1/utils.hpp new file mode 100644 index 00000000..4411c8a3 --- /dev/null +++ b/src/detail/v1/utils.hpp @@ -0,0 +1,36 @@ +// Copyright (C) 2023–2026 University Corporation for Atmospheric Research +// University of Illinois at Urbana-Champaign +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +namespace mechanism_configuration::v1 +{ + /// @brief Ensures a YAML node is treated as a sequence + /// @param node The YAML node to convert + /// @return A YAML sequence node containing the original node(s) + YAML::Node AsSequence(const YAML::Node& node); + + void AppendFilePath(const std::string& config_path, Errors& errors); + + std::unordered_map GetComments(const YAML::Node& object); + + /// @brief Reads a reaction component's species reference, accepting either the + /// canonical `name` key or the legacy `species name` alias (v1 files). + /// @note Assumes the component has already been validated to contain exactly one of them. + std::string GetReactionComponentName(const YAML::Node& component); + +} // namespace mechanism_configuration::v1 diff --git a/src/development/CMakeLists.txt b/src/development/CMakeLists.txt deleted file mode 100644 index f482a88c..00000000 --- a/src/development/CMakeLists.txt +++ /dev/null @@ -1,10 +0,0 @@ -target_sources(mechanism_configuration - PRIVATE - mechanism.cpp - type_parsers.cpp - type_validators.cpp - utils.cpp -) - -add_subdirectory(models) -add_subdirectory(reactions) \ No newline at end of file diff --git a/src/development/mechanism.cpp b/src/development/mechanism.cpp deleted file mode 100644 index 4627bdac..00000000 --- a/src/development/mechanism.cpp +++ /dev/null @@ -1,140 +0,0 @@ -// Copyright (C) 2023–2026 University Corporation for Atmospheric Research -// University of Illinois at Urbana-Champaign -// SPDX-License-Identifier: Apache-2.0 - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -namespace mechanism_configuration -{ - namespace development - { - - YAML::Node Parser::FileToYaml(const std::filesystem::path& config_path) - { - if (!std::filesystem::exists(config_path) || !std::filesystem::is_regular_file(config_path)) - { - throw std::runtime_error( - mc_fmt::format("Configuration file '{}' does not exist or is not a regular file.", config_path.string())); - } - - SetConfigPath(config_path.string()); - - try - { - return YAML::LoadFile(config_path.string()); - } - catch (const YAML::Exception& e) - { - throw std::runtime_error(mc_fmt::format("Failed to parse '{}': {}", config_path.string(), e.what())); - } - } - - Errors Parser::Validate(const YAML::Node& object, bool read_from_config_file) - { - if (!read_from_config_file) - { - SetDefaultConfigPath(); - } - - Errors errors; - - std::vector required_keys = { - validation::version, validation::species, validation::phases, validation::reactions - }; - std::vector optional_keys = { validation::name, validation::models }; - - // Return early if the required keys are not found - auto validation_errors = ValidateSchema(object, required_keys, optional_keys); - if (!validation_errors.empty()) - { - AppendFilePath(config_path_, validation_errors); - errors.insert(errors.end(), validation_errors.begin(), validation_errors.end()); - return errors; - } - - constexpr unsigned int MAJOR_VERSION = 2; - Version version = Version(object[validation::version].as()); - if (version.major != MAJOR_VERSION) - { - ErrorLocation error_location{ object[validation::version].Mark().line, object[validation::version].Mark().column }; - - std::string message = mc_fmt::format( - "{} error: The version must be '{}' but the invalid version number '{}' found.", - error_location, - MAJOR_VERSION, - version.major); - errors.push_back({ ConfigParseStatus::InvalidVersion, config_path_ + ":" + message }); - } - - validation_errors = ValidateSpecies(object[validation::species]); - if (!validation_errors.empty()) - { - AppendFilePath(config_path_, validation_errors); - errors.insert(errors.end(), validation_errors.begin(), validation_errors.end()); - return errors; - } - - auto parsed_species = ParseSpecies(object[validation::species]); - - validation_errors = ValidatePhases(object[validation::phases], parsed_species); - if (!validation_errors.empty()) - { - AppendFilePath(config_path_, validation_errors); - errors.insert(errors.end(), validation_errors.begin(), validation_errors.end()); - return errors; - } - - auto parsed_phases = ParsePhases(object[validation::phases]); - - validation_errors = ValidateReactions(object[validation::reactions], parsed_species, parsed_phases); - if (!validation_errors.empty()) - { - AppendFilePath(config_path_, validation_errors); - errors.insert(errors.end(), validation_errors.begin(), validation_errors.end()); - } - - if (object[validation::models]) - { - validation_errors = ValidateModels(object[validation::models], parsed_phases); - if (!validation_errors.empty()) - { - AppendFilePath(config_path_, validation_errors); - errors.insert(errors.end(), validation_errors.begin(), validation_errors.end()); - } - } - - return errors; - } - - types::Mechanism Parser::Parse(const YAML::Node& object) - { - types::Mechanism mechanism; - - mechanism.version = Version(object[validation::version].as()); - mechanism.species = ParseSpecies(object[validation::species]); - mechanism.phases = ParsePhases(object[validation::phases]); - mechanism.reactions = ParseReactions(object[validation::reactions]); - - if (object[validation::name]) - { - mechanism.name = object[validation::name].as(); - } - if (object[validation::models]) - { - mechanism.models = ParseModels(object[validation::models]); - } - - return mechanism; - } - - } // namespace development -} // namespace mechanism_configuration diff --git a/src/development/models/CMakeLists.txt b/src/development/models/CMakeLists.txt deleted file mode 100644 index dc2ea034..00000000 --- a/src/development/models/CMakeLists.txt +++ /dev/null @@ -1,2 +0,0 @@ -add_subdirectory(parsers) -add_subdirectory(validators) \ No newline at end of file diff --git a/src/development/models/parsers/CMakeLists.txt b/src/development/models/parsers/CMakeLists.txt deleted file mode 100644 index 4fdd2d4c..00000000 --- a/src/development/models/parsers/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -target_sources(mechanism_configuration - PRIVATE - gas.cpp - modal.cpp -) \ No newline at end of file diff --git a/src/development/models/parsers/gas.cpp b/src/development/models/parsers/gas.cpp deleted file mode 100644 index 58135ff5..00000000 --- a/src/development/models/parsers/gas.cpp +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (C) 2023–2026 University Corporation for Atmospheric Research -// University of Illinois at Urbana-Champaign -// SPDX-License-Identifier: Apache-2.0 - -#include -#include -#include - -#include - -namespace mechanism_configuration -{ - namespace development - { - void GasModelParser::Parse(const YAML::Node& object, types::Models& models) - { - types::GasModel model; - - model.type = object[validation::type].as(); - model.phase = object[validation::phase].as(); - model.unknown_properties = GetComments(object); - - if (object[validation::name]) - { - model.name = object[validation::name].as(); - } - - models.gas_model = std::move(model); - } - - } // namespace development -} // namespace mechanism_configuration diff --git a/src/development/models/parsers/modal.cpp b/src/development/models/parsers/modal.cpp deleted file mode 100644 index 79af762b..00000000 --- a/src/development/models/parsers/modal.cpp +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright (C) 2023–2026 University Corporation for Atmospheric Research -// University of Illinois at Urbana-Champaign -// SPDX-License-Identifier: Apache-2.0 - -#include -#include -#include - -#include - -namespace mechanism_configuration -{ - namespace development - { - void ModalModelParser::Parse(const YAML::Node& object, types::Models& models) - { - types::ModalModel model; - - model.type = object[validation::type].as(); - model.unknown_properties = GetComments(object); - - for (const auto& mode_object : object[validation::modes]) - { - types::Mode mode; - mode.name = mode_object[validation::name].as(); - mode.geometric_mean_diameter = mode_object[validation::geometric_mean_diameter].as(); - mode.geometric_standard_deviation = mode_object[validation::geometric_standard_deviation].as(); - mode.phase = mode_object[validation::phase].as(); - mode.unknown_properties = GetComments(mode_object); - model.modes.emplace_back(std::move(mode)); - } - - if (object[validation::name]) - { - model.name = object[validation::name].as(); - } - - models.modal_model = std::move(model); - } - - } // namespace development -} // namespace mechanism_configuration diff --git a/src/development/models/validators/CMakeLists.txt b/src/development/models/validators/CMakeLists.txt deleted file mode 100644 index 4fdd2d4c..00000000 --- a/src/development/models/validators/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -target_sources(mechanism_configuration - PRIVATE - gas.cpp - modal.cpp -) \ No newline at end of file diff --git a/src/development/models/validators/gas.cpp b/src/development/models/validators/gas.cpp deleted file mode 100644 index c9da44e8..00000000 --- a/src/development/models/validators/gas.cpp +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright (C) 2023–2026 University Corporation for Atmospheric Research -// University of Illinois at Urbana-Champaign -// SPDX-License-Identifier: Apache-2.0 - -#include -#include -#include -#include - -#include - -namespace mechanism_configuration -{ - namespace development - { - Errors GasModelParser::Validate(const YAML::Node& object, const std::vector& existing_phases) - { - std::vector required_keys = { validation::type, validation::phase }; - std::vector optional_keys = { validation::name }; - - Errors errors; - - auto validation_errors = ValidateSchema(object, required_keys, optional_keys); - if (!validation_errors.empty()) - { - errors.insert(errors.end(), validation_errors.begin(), validation_errors.end()); - return errors; - } - - CheckPhaseExists(object, validation::phase, existing_phases, errors); - - return errors; - } - - } // namespace development -} // namespace mechanism_configuration diff --git a/src/development/models/validators/modal.cpp b/src/development/models/validators/modal.cpp deleted file mode 100644 index dfbadd24..00000000 --- a/src/development/models/validators/modal.cpp +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright (C) 2023–2026 University Corporation for Atmospheric Research -// University of Illinois at Urbana-Champaign -// SPDX-License-Identifier: Apache-2.0 - -#include -#include -#include -#include -#include -#include - -#include - -namespace mechanism_configuration -{ - namespace development - { - Errors ModalModelParser::Validate(const YAML::Node& object, const std::vector& existing_phases) - { - std::vector required_top_level_keys = { validation::type, validation::modes }; - std::vector optional_top_level_keys = { validation::name }; - - std::vector required_second_level_keys = { - validation::name, validation::geometric_mean_diameter, validation::geometric_standard_deviation, validation::phase - }; - std::vector optional_second_level_keys = {}; - - Errors errors; - - auto validation_errors = ValidateSchema(object, required_top_level_keys, optional_top_level_keys); - if (!validation_errors.empty()) - { - errors.insert(errors.end(), validation_errors.begin(), validation_errors.end()); - return errors; - } - - if (!object[validation::modes].IsSequence()) - { - const auto& node = object[validation::modes]; - ErrorLocation error_location{ node.Mark().line, node.Mark().column }; - - std::string message = mc_fmt::format( - "{} error: Expected 'modes' to be a sequence, but found a different type in the '{}' model.", - error_location, - object[validation::type].as()); - - errors.push_back({ ConfigParseStatus::InvalidType, message }); - - return errors; - } - - for (const auto& mode_object : object[validation::modes]) - { - validation_errors = ValidateSchema(mode_object, required_second_level_keys, optional_second_level_keys); - if (!validation_errors.empty()) - { - errors.insert(errors.end(), validation_errors.begin(), validation_errors.end()); - continue; - } - - CheckPhaseExists( - mode_object, - validation::phase, - existing_phases, - errors, - ConfigParseStatus::UnknownPhase, - object[validation::type].as()); - } - - return errors; - } - - } // namespace development -} // namespace mechanism_configuration diff --git a/src/development/reactions/CMakeLists.txt b/src/development/reactions/CMakeLists.txt deleted file mode 100644 index dc2ea034..00000000 --- a/src/development/reactions/CMakeLists.txt +++ /dev/null @@ -1,2 +0,0 @@ -add_subdirectory(parsers) -add_subdirectory(validators) \ No newline at end of file diff --git a/src/development/reactions/parsers/CMakeLists.txt b/src/development/reactions/parsers/CMakeLists.txt deleted file mode 100644 index ce25ac23..00000000 --- a/src/development/reactions/parsers/CMakeLists.txt +++ /dev/null @@ -1,21 +0,0 @@ -target_sources(mechanism_configuration - PRIVATE - aqueous_equilibrium.cpp - arrhenius.cpp - branched.cpp - condensed_phase_arrhenius.cpp - condensed_phase_photolysis.cpp - emission.cpp - first_order_loss.cpp - henrys_law.cpp - photolysis.cpp - simpol_phase_transfer.cpp - surface.cpp - taylor_series.cpp - ternary_chemical_activation.cpp - troe.cpp - tunneling.cpp - user_defined.cpp - lambda_rate_constant.cpp - wet_deposition.cpp -) \ No newline at end of file diff --git a/src/development/reactions/parsers/aqueous_equilibrium.cpp b/src/development/reactions/parsers/aqueous_equilibrium.cpp deleted file mode 100644 index 170cf261..00000000 --- a/src/development/reactions/parsers/aqueous_equilibrium.cpp +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright (C) 2023–2026 University Corporation for Atmospheric Research -// University of Illinois at Urbana-Champaign -// SPDX-License-Identifier: Apache-2.0 - -#include -#include -#include -#include - -namespace mechanism_configuration -{ - namespace development - { - void AqueousEquilibriumParser::Parse(const YAML::Node& object, types::Reactions& reactions) - { - types::AqueousEquilibrium aqueous_equilibrium; - - aqueous_equilibrium.condensed_phase = object[validation::condensed_phase].as(); - aqueous_equilibrium.condensed_phase_water = object[validation::condensed_phase_water].as(); - aqueous_equilibrium.k_reverse = object[validation::k_reverse].as(); - aqueous_equilibrium.reactants = ParseReactionComponents(object, validation::reactants); - aqueous_equilibrium.products = ParseReactionComponents(object, validation::products); - aqueous_equilibrium.unknown_properties = GetComments(object); - - if (object[validation::A]) - { - aqueous_equilibrium.A = object[validation::A].as(); - } - if (object[validation::C]) - { - aqueous_equilibrium.C = object[validation::C].as(); - } - if (object[validation::name]) - { - aqueous_equilibrium.name = object[validation::name].as(); - } - - reactions.aqueous_equilibrium.emplace_back(std::move(aqueous_equilibrium)); - } - - } // namespace development -} // namespace mechanism_configuration diff --git a/src/development/reactions/parsers/arrhenius.cpp b/src/development/reactions/parsers/arrhenius.cpp deleted file mode 100644 index ada280fb..00000000 --- a/src/development/reactions/parsers/arrhenius.cpp +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright (C) 2023–2026 University Corporation for Atmospheric Research -// University of Illinois at Urbana-Champaign -// SPDX-License-Identifier: Apache-2.0 - -#include -#include -#include -#include -#include -#include - -namespace mechanism_configuration -{ - namespace development - { - /// @brief Parses a YAML-defined Arrhenius reaction and appends it to the reaction list. - /// Extracts reactants, products, kinetic parameters (A–E, Ea), gas phase, - /// optional metadata (name, comments), and constructs a `types::Arrhenius` object. - /// @param object The YAML node representing the reaction - /// @param reactions The reactions container to append the parsed reaction to - void ArrheniusParser::Parse(const YAML::Node& object, types::Reactions& reactions) - { - types::Arrhenius arrhenius; - - arrhenius.gas_phase = object[validation::gas_phase].as(); - arrhenius.reactants = ParseReactionComponents(object, validation::reactants); - arrhenius.products = ParseReactionComponents(object, validation::products); - arrhenius.unknown_properties = GetComments(object); - - if (object[validation::A]) - { - arrhenius.A = object[validation::A].as(); - } - if (object[validation::B]) - { - arrhenius.B = object[validation::B].as(); - } - if (object[validation::C]) - { - arrhenius.C = object[validation::C].as(); - } - if (object[validation::D]) - { - arrhenius.D = object[validation::D].as(); - } - if (object[validation::E]) - { - arrhenius.E = object[validation::E].as(); - } - if (object[validation::Ea]) - { - arrhenius.C = -1 * object[validation::Ea].as() / constants::boltzmann; - } - if (object[validation::name]) - { - arrhenius.name = object[validation::name].as(); - } - - reactions.arrhenius.emplace_back(std::move(arrhenius)); - } - - } // namespace development -} // namespace mechanism_configuration diff --git a/src/development/reactions/parsers/branched.cpp b/src/development/reactions/parsers/branched.cpp deleted file mode 100644 index c8a11e0c..00000000 --- a/src/development/reactions/parsers/branched.cpp +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright (C) 2023–2026 University Corporation for Atmospheric Research -// University of Illinois at Urbana-Champaign -// SPDX-License-Identifier: Apache-2.0 - -#include -#include -#include -#include - -namespace mechanism_configuration -{ - namespace development - { - void BranchedParser::Parse(const YAML::Node& object, types::Reactions& reactions) - { - types::Branched branched; - - branched.gas_phase = object[validation::gas_phase].as(); - branched.reactants = ParseReactionComponents(object, validation::reactants); - branched.alkoxy_products = ParseReactionComponents(object, validation::alkoxy_products); - branched.nitrate_products = ParseReactionComponents(object, validation::nitrate_products); - branched.unknown_properties = GetComments(object); - - if (object[validation::X]) - { - branched.X = object[validation::X].as(); - } - if (object[validation::Y]) - { - branched.Y = object[validation::Y].as(); - } - if (object[validation::a0]) - { - branched.a0 = object[validation::a0].as(); - } - if (object[validation::n]) - { - branched.n = object[validation::n].as(); - } - if (object[validation::name]) - { - branched.name = object[validation::name].as(); - } - - reactions.branched.emplace_back(std::move(branched)); - } - - } // namespace development -} // namespace mechanism_configuration diff --git a/src/development/reactions/parsers/condensed_phase_arrhenius.cpp b/src/development/reactions/parsers/condensed_phase_arrhenius.cpp deleted file mode 100644 index e70b68ee..00000000 --- a/src/development/reactions/parsers/condensed_phase_arrhenius.cpp +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright (C) 2023–2026 University Corporation for Atmospheric Research -// University of Illinois at Urbana-Champaign -// SPDX-License-Identifier: Apache-2.0 - -#include -#include -#include -#include -#include - -namespace mechanism_configuration -{ - namespace development - { - void CondensedPhaseArrheniusParser::Parse(const YAML::Node& object, types::Reactions& reactions) - { - types::CondensedPhaseArrhenius condensed_phase_arrhenius; - - condensed_phase_arrhenius.condensed_phase = object[validation::condensed_phase].as(); - condensed_phase_arrhenius.reactants = ParseReactionComponents(object, validation::reactants); - condensed_phase_arrhenius.products = ParseReactionComponents(object, validation::products); - condensed_phase_arrhenius.unknown_properties = GetComments(object); - - if (object[validation::A]) - { - condensed_phase_arrhenius.A = object[validation::A].as(); - } - if (object[validation::B]) - { - condensed_phase_arrhenius.B = object[validation::B].as(); - } - if (object[validation::C]) - { - condensed_phase_arrhenius.C = object[validation::C].as(); - } - if (object[validation::D]) - { - condensed_phase_arrhenius.D = object[validation::D].as(); - } - if (object[validation::E]) - { - condensed_phase_arrhenius.E = object[validation::E].as(); - } - if (object[validation::Ea]) - { - condensed_phase_arrhenius.C = -1 * object[validation::Ea].as() / constants::boltzmann; - } - if (object[validation::name]) - { - condensed_phase_arrhenius.name = object[validation::name].as(); - } - - reactions.condensed_phase_arrhenius.emplace_back(std::move(condensed_phase_arrhenius)); - } - - } // namespace development -} // namespace mechanism_configuration diff --git a/src/development/reactions/parsers/condensed_phase_photolysis.cpp b/src/development/reactions/parsers/condensed_phase_photolysis.cpp deleted file mode 100644 index f6c37ae4..00000000 --- a/src/development/reactions/parsers/condensed_phase_photolysis.cpp +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright (C) 2023–2026 University Corporation for Atmospheric Research -// University of Illinois at Urbana-Champaign -// SPDX-License-Identifier: Apache-2.0 - -#include -#include -#include -#include - -namespace mechanism_configuration -{ - namespace development - { - void CondensedPhasePhotolysisParser::Parse(const YAML::Node& object, types::Reactions& reactions) - { - types::CondensedPhasePhotolysis condensed_phase_photolysis; - - condensed_phase_photolysis.condensed_phase = object[validation::condensed_phase].as(); - condensed_phase_photolysis.reactants = ParseReactionComponent(object, validation::reactants); - condensed_phase_photolysis.products = ParseReactionComponents(object, validation::products); - condensed_phase_photolysis.unknown_properties = GetComments(object); - - if (object[validation::scaling_factor]) - { - condensed_phase_photolysis.scaling_factor = object[validation::scaling_factor].as(); - } - if (object[validation::name]) - { - condensed_phase_photolysis.name = object[validation::name].as(); - } - - reactions.condensed_phase_photolysis.emplace_back(std::move(condensed_phase_photolysis)); - } - - } // namespace development -} // namespace mechanism_configuration diff --git a/src/development/reactions/parsers/emission.cpp b/src/development/reactions/parsers/emission.cpp deleted file mode 100644 index fa3510a9..00000000 --- a/src/development/reactions/parsers/emission.cpp +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright (C) 2023–2026 University Corporation for Atmospheric Research -// University of Illinois at Urbana-Champaign -// SPDX-License-Identifier: Apache-2.0 - -#include -#include -#include -#include - -namespace mechanism_configuration -{ - namespace development - { - void EmissionParser::Parse(const YAML::Node& object, types::Reactions& reactions) - { - types::Emission emission; - - emission.gas_phase = object[validation::gas_phase].as(); - emission.products = ParseReactionComponents(object, validation::products); - emission.unknown_properties = GetComments(object); - - if (object[validation::scaling_factor]) - { - emission.scaling_factor = object[validation::scaling_factor].as(); - } - if (object[validation::name]) - { - emission.name = object[validation::name].as(); - } - - reactions.emission.emplace_back(std::move(emission)); - } - - } // namespace development -} // namespace mechanism_configuration diff --git a/src/development/reactions/parsers/first_order_loss.cpp b/src/development/reactions/parsers/first_order_loss.cpp deleted file mode 100644 index c16b7157..00000000 --- a/src/development/reactions/parsers/first_order_loss.cpp +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright (C) 2023–2026 University Corporation for Atmospheric Research -// University of Illinois at Urbana-Champaign -// SPDX-License-Identifier: Apache-2.0 - -#include -#include -#include -#include - -namespace mechanism_configuration -{ - namespace development - { - void FirstOrderLossParser::Parse(const YAML::Node& object, types::Reactions& reactions) - { - types::FirstOrderLoss first_order_loss; - - first_order_loss.gas_phase = object[validation::gas_phase].as(); - first_order_loss.reactants = ParseReactionComponent(object, validation::reactants); - first_order_loss.unknown_properties = GetComments(object); - - if (object[validation::scaling_factor]) - { - first_order_loss.scaling_factor = object[validation::scaling_factor].as(); - } - if (object[validation::name]) - { - first_order_loss.name = object[validation::name].as(); - } - - reactions.first_order_loss.emplace_back(std::move(first_order_loss)); - } - - } // namespace development -} // namespace mechanism_configuration diff --git a/src/development/reactions/parsers/henrys_law.cpp b/src/development/reactions/parsers/henrys_law.cpp deleted file mode 100644 index d7b3b9f2..00000000 --- a/src/development/reactions/parsers/henrys_law.cpp +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright (C) 2023–2026 University Corporation for Atmospheric Research -// University of Illinois at Urbana-Champaign -// SPDX-License-Identifier: Apache-2.0 - -#include -#include -#include -#include - -namespace mechanism_configuration -{ - namespace development - { - void HenrysLawParser::Parse(const YAML::Node& object, types::Reactions& reactions) - { - types::HenrysLaw henrys_law; - - // Parse gas - types::Phase gas; - gas.name = object[validation::gas][validation::name].as(); - - for (const auto& elem : object[validation::gas][validation::species]) - { - types::PhaseSpecies phase_species; - phase_species.name = elem[validation::name].as(); - phase_species.unknown_properties = GetComments(elem); - if (elem[validation::diffusion_coefficient]) - { - phase_species.diffusion_coefficient = elem[validation::diffusion_coefficient].as(); - } - gas.species.emplace_back(std::move(phase_species)); - } - - henrys_law.gas = std::move(gas); - henrys_law.particle.phase = object[validation::particle][validation::phase].as(); - henrys_law.particle.solutes = ParseReactionComponents(object[validation::particle], validation::solutes); - henrys_law.particle.solvent = ParseReactionComponent(object[validation::particle], validation::solvent); - henrys_law.unknown_properties = GetComments(object); - - if (object[validation::name]) - { - henrys_law.name = object[validation::name].as(); - } - - reactions.henrys_law.emplace_back(std::move(henrys_law)); - } - - } // namespace development -} // namespace mechanism_configuration \ No newline at end of file diff --git a/src/development/reactions/parsers/lambda_rate_constant.cpp b/src/development/reactions/parsers/lambda_rate_constant.cpp deleted file mode 100644 index 86fdaed6..00000000 --- a/src/development/reactions/parsers/lambda_rate_constant.cpp +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright (C) 2023–2026 University Corporation for Atmospheric Research -// University of Illinois at Urbana-Champaign -// SPDX-License-Identifier: Apache-2.0 - -#include -#include -#include -#include -#include - -namespace mechanism_configuration -{ - namespace development - { - void LambdaRateConstantParser::Parse(const YAML::Node& object, types::Reactions& reactions) - { - types::LambdaRateConstant lambda_rate_constant; - - lambda_rate_constant.reactants = ParseReactionComponents(object, validation::reactants); - lambda_rate_constant.products = ParseReactionComponents(object, validation::products); - lambda_rate_constant.gas_phase = object[validation::gas_phase].as(); - lambda_rate_constant.lambda_function = object[validation::lambda_function].as(); - lambda_rate_constant.unknown_properties = GetComments(object); - - if (object[validation::name]) - { - lambda_rate_constant.name = object[validation::name].as(); - } - - reactions.lambda_rate_constant.emplace_back(std::move(lambda_rate_constant)); - } - - } // namespace development -} // namespace mechanism_configuration diff --git a/src/development/reactions/parsers/photolysis.cpp b/src/development/reactions/parsers/photolysis.cpp deleted file mode 100644 index ea3db3cd..00000000 --- a/src/development/reactions/parsers/photolysis.cpp +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright (C) 2023–2026 University Corporation for Atmospheric Research -// University of Illinois at Urbana-Champaign -// SPDX-License-Identifier: Apache-2.0 - -#include -#include -#include -#include - -namespace mechanism_configuration -{ - namespace development - { - void PhotolysisParser::Parse(const YAML::Node& object, types::Reactions& reactions) - { - types::Photolysis photolysis; - - photolysis.gas_phase = object[validation::gas_phase].as(); - photolysis.reactants = ParseReactionComponent(object, validation::reactants); - photolysis.products = ParseReactionComponents(object, validation::products); - photolysis.unknown_properties = GetComments(object); - - if (object[validation::scaling_factor]) - { - photolysis.scaling_factor = object[validation::scaling_factor].as(); - } - if (object[validation::name]) - { - photolysis.name = object[validation::name].as(); - } - - reactions.photolysis.emplace_back(std::move(photolysis)); - } - - } // namespace development -} // namespace mechanism_configuration diff --git a/src/development/reactions/parsers/simpol_phase_transfer.cpp b/src/development/reactions/parsers/simpol_phase_transfer.cpp deleted file mode 100644 index 210c71ea..00000000 --- a/src/development/reactions/parsers/simpol_phase_transfer.cpp +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (C) 2023–2026 University Corporation for Atmospheric Research -// University of Illinois at Urbana-Champaign -// SPDX-License-Identifier: Apache-2.0 - -#include -#include -#include -#include - -namespace mechanism_configuration -{ - namespace development - { - void SimpolPhaseTransferParser::Parse(const YAML::Node& object, types::Reactions& reactions) - { - types::SimpolPhaseTransfer simpol_phase_transfer; - - simpol_phase_transfer.gas_phase = object[validation::gas_phase].as(); - simpol_phase_transfer.condensed_phase = object[validation::condensed_phase].as(); - simpol_phase_transfer.gas_phase_species = ParseReactionComponents(object, validation::gas_phase_species); - simpol_phase_transfer.condensed_phase_species = ParseReactionComponents(object, validation::condensed_phase_species); - simpol_phase_transfer.unknown_properties = GetComments(object); - - for (size_t i = 0; i < 4; ++i) - { - simpol_phase_transfer.B[i] = object[validation::B][i].as(); - } - - if (object[validation::name]) - { - simpol_phase_transfer.name = object[validation::name].as(); - } - - reactions.simpol_phase_transfer.emplace_back(std::move(simpol_phase_transfer)); - } - - } // namespace development -} // namespace mechanism_configuration diff --git a/src/development/reactions/parsers/surface.cpp b/src/development/reactions/parsers/surface.cpp deleted file mode 100644 index bd898c1e..00000000 --- a/src/development/reactions/parsers/surface.cpp +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright (C) 2023–2026 University Corporation for Atmospheric Research -// University of Illinois at Urbana-Champaign -// SPDX-License-Identifier: Apache-2.0 - -#include -#include -#include -#include - -namespace mechanism_configuration -{ - namespace development - { - void SurfaceParser::Parse(const YAML::Node& object, types::Reactions& reactions) - { - types::Surface surface; - - surface.gas_phase = object[validation::gas_phase].as(); - surface.condensed_phase = object[validation::condensed_phase].as(); - surface.gas_phase_species = ParseReactionComponent(object, validation::gas_phase_species); - surface.gas_phase_products = ParseReactionComponents(object, validation::gas_phase_products); - surface.unknown_properties = GetComments(object); - - if (object[validation::reaction_probability]) - { - surface.reaction_probability = object[validation::reaction_probability].as(); - } - if (object[validation::name]) - { - surface.name = object[validation::name].as(); - } - - reactions.surface.emplace_back(std::move(surface)); - } - - } // namespace development -} // namespace mechanism_configuration diff --git a/src/development/reactions/parsers/taylor_series.cpp b/src/development/reactions/parsers/taylor_series.cpp deleted file mode 100644 index c97c92cb..00000000 --- a/src/development/reactions/parsers/taylor_series.cpp +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright (C) 2023–2026 University Corporation for Atmospheric Research -// University of Illinois at Urbana-Champaign -// SPDX-License-Identifier: Apache-2.0 - -#include -#include -#include -#include -#include - -namespace mechanism_configuration -{ - namespace development - { - /// @brief Parses a YAML-defined Taylor Series reaction and appends it to the reaction list. - /// Extracts reactants, products, kinetic parameters (A–E, Ea), gas phase, - /// optional metadata (name, comments), and constructs a `types::TaylorSeries` object. - /// @param object The YAML node representing the reaction - /// @param reactions The reactions container to append the parsed reaction to - void TaylorSeriesParser::Parse(const YAML::Node& object, types::Reactions& reactions) - { - types::TaylorSeries taylor_series; - - taylor_series.gas_phase = object[validation::gas_phase].as(); - taylor_series.reactants = ParseReactionComponents(object, validation::reactants); - taylor_series.products = ParseReactionComponents(object, validation::products); - taylor_series.unknown_properties = GetComments(object); - - if (object[validation::A]) - { - taylor_series.A = object[validation::A].as(); - } - if (object[validation::B]) - { - taylor_series.B = object[validation::B].as(); - } - if (object[validation::C]) - { - taylor_series.C = object[validation::C].as(); - } - if (object[validation::D]) - { - taylor_series.D = object[validation::D].as(); - } - if (object[validation::E]) - { - taylor_series.E = object[validation::E].as(); - } - if (object[validation::Ea]) - { - taylor_series.C = -1 * object[validation::Ea].as() / constants::boltzmann; - } - if (object[validation::taylor_coefficients]) - { - taylor_series.taylor_coefficients = object[validation::taylor_coefficients].as>(); - } - if (object[validation::name]) - { - taylor_series.name = object[validation::name].as(); - } - - reactions.taylor_series.emplace_back(std::move(taylor_series)); - } - - } // namespace development -} // namespace mechanism_configuration diff --git a/src/development/reactions/parsers/ternary_chemical_activation.cpp b/src/development/reactions/parsers/ternary_chemical_activation.cpp deleted file mode 100644 index f41b983c..00000000 --- a/src/development/reactions/parsers/ternary_chemical_activation.cpp +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright (C) 2023–2026 University Corporation for Atmospheric Research -// University of Illinois at Urbana-Champaign -// SPDX-License-Identifier: Apache-2.0 - -#include -#include -#include -#include - -namespace mechanism_configuration -{ - namespace development - { - void TernaryChemicalActivationParser::Parse(const YAML::Node& object, types::Reactions& reactions) - { - types::TernaryChemicalActivation ternary; - - ternary.gas_phase = object[validation::gas_phase].as(); - ternary.reactants = ParseReactionComponents(object, validation::reactants); - ternary.products = ParseReactionComponents(object, validation::products); - ternary.unknown_properties = GetComments(object); - - if (object[validation::k0_A]) - { - ternary.k0_A = object[validation::k0_A].as(); - } - if (object[validation::k0_B]) - { - ternary.k0_B = object[validation::k0_B].as(); - } - if (object[validation::k0_C]) - { - ternary.k0_C = object[validation::k0_C].as(); - } - if (object[validation::kinf_A]) - { - ternary.kinf_A = object[validation::kinf_A].as(); - } - if (object[validation::kinf_B]) - { - ternary.kinf_B = object[validation::kinf_B].as(); - } - if (object[validation::kinf_C]) - { - ternary.kinf_C = object[validation::kinf_C].as(); - } - if (object[validation::Fc]) - { - ternary.Fc = object[validation::Fc].as(); - } - if (object[validation::N]) - { - ternary.N = object[validation::N].as(); - } - if (object[validation::name]) - { - ternary.name = object[validation::name].as(); - } - - reactions.ternary_chemical_activation.emplace_back(std::move(ternary)); - } - - } // namespace development -} // namespace mechanism_configuration diff --git a/src/development/reactions/parsers/troe.cpp b/src/development/reactions/parsers/troe.cpp deleted file mode 100644 index 7a45bb97..00000000 --- a/src/development/reactions/parsers/troe.cpp +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright (C) 2023–2026 University Corporation for Atmospheric Research -// University of Illinois at Urbana-Champaign -// SPDX-License-Identifier: Apache-2.0 - -#include -#include -#include -#include - -namespace mechanism_configuration -{ - namespace development - { - void TroeParser::Parse(const YAML::Node& object, types::Reactions& reactions) - { - types::Troe troe; - - troe.gas_phase = object[validation::gas_phase].as(); - troe.reactants = ParseReactionComponents(object, validation::reactants); - troe.products = ParseReactionComponents(object, validation::products); - troe.unknown_properties = GetComments(object); - - if (object[validation::k0_A]) - { - troe.k0_A = object[validation::k0_A].as(); - } - if (object[validation::k0_B]) - { - troe.k0_B = object[validation::k0_B].as(); - } - if (object[validation::k0_C]) - { - troe.k0_C = object[validation::k0_C].as(); - } - if (object[validation::kinf_A]) - { - troe.kinf_A = object[validation::kinf_A].as(); - } - if (object[validation::kinf_B]) - { - troe.kinf_B = object[validation::kinf_B].as(); - } - if (object[validation::kinf_C]) - { - troe.kinf_C = object[validation::kinf_C].as(); - } - if (object[validation::Fc]) - { - troe.Fc = object[validation::Fc].as(); - } - if (object[validation::N]) - { - troe.N = object[validation::N].as(); - } - if (object[validation::name]) - { - troe.name = object[validation::name].as(); - } - - reactions.troe.emplace_back(std::move(troe)); - } - - } // namespace development -} // namespace mechanism_configuration diff --git a/src/development/reactions/parsers/tunneling.cpp b/src/development/reactions/parsers/tunneling.cpp deleted file mode 100644 index ed25cabf..00000000 --- a/src/development/reactions/parsers/tunneling.cpp +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright (C) 2023–2026 University Corporation for Atmospheric Research -// University of Illinois at Urbana-Champaign -// SPDX-License-Identifier: Apache-2.0 - -#include -#include -#include -#include - -namespace mechanism_configuration -{ - namespace development - { - void TunnelingParser::Parse(const YAML::Node& object, types::Reactions& reactions) - { - types::Tunneling tunneling; - - tunneling.gas_phase = object[validation::gas_phase].as(); - tunneling.reactants = ParseReactionComponents(object, validation::reactants); - tunneling.products = ParseReactionComponents(object, validation::products); - tunneling.unknown_properties = GetComments(object); - - if (object[validation::A]) - { - tunneling.A = object[validation::A].as(); - } - if (object[validation::B]) - { - tunneling.B = object[validation::B].as(); - } - if (object[validation::C]) - { - tunneling.C = object[validation::C].as(); - } - if (object[validation::name]) - { - tunneling.name = object[validation::name].as(); - } - - reactions.tunneling.emplace_back(std::move(tunneling)); - } - - } // namespace development -} // namespace mechanism_configuration diff --git a/src/development/reactions/parsers/user_defined.cpp b/src/development/reactions/parsers/user_defined.cpp deleted file mode 100644 index a4702370..00000000 --- a/src/development/reactions/parsers/user_defined.cpp +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (C) 2023–2026 University Corporation for Atmospheric Research -// University of Illinois at Urbana-Champaign -// SPDX-License-Identifier: Apache-2.0 - -#include -#include -#include -#include -#include - -namespace mechanism_configuration -{ - namespace development - { - void UserDefinedParser::Parse(const YAML::Node& object, types::Reactions& reactions) - { - types::UserDefined user_defined; - - user_defined.reactants = ParseReactionComponents(object, validation::reactants); - user_defined.products = ParseReactionComponents(object, validation::products); - user_defined.gas_phase = object[validation::gas_phase].as(); - user_defined.unknown_properties = GetComments(object); - - if (object[validation::scaling_factor]) - { - user_defined.scaling_factor = object[validation::scaling_factor].as(); - } - - if (object[validation::name]) - { - user_defined.name = object[validation::name].as(); - } - - reactions.user_defined.emplace_back(std::move(user_defined)); - } - - } // namespace development -} // namespace mechanism_configuration diff --git a/src/development/reactions/parsers/wet_deposition.cpp b/src/development/reactions/parsers/wet_deposition.cpp deleted file mode 100644 index 14642776..00000000 --- a/src/development/reactions/parsers/wet_deposition.cpp +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright (C) 2023–2026 University Corporation for Atmospheric Research -// University of Illinois at Urbana-Champaign -// SPDX-License-Identifier: Apache-2.0 - -#include -#include -#include -#include - -namespace mechanism_configuration -{ - namespace development - { - void WetDepositionParser::Parse(const YAML::Node& object, types::Reactions& reactions) - { - types::WetDeposition wet_deposition; - - wet_deposition.condensed_phase = object[validation::condensed_phase].as(); - wet_deposition.unknown_properties = GetComments(object); - - if (object[validation::scaling_factor]) - { - wet_deposition.scaling_factor = object[validation::scaling_factor].as(); - } - - if (object[validation::name]) - { - wet_deposition.name = object[validation::name].as(); - } - - reactions.wet_deposition.emplace_back(std::move(wet_deposition)); - } - - } // namespace development -} // namespace mechanism_configuration \ No newline at end of file diff --git a/src/development/reactions/validators/CMakeLists.txt b/src/development/reactions/validators/CMakeLists.txt deleted file mode 100644 index ce25ac23..00000000 --- a/src/development/reactions/validators/CMakeLists.txt +++ /dev/null @@ -1,21 +0,0 @@ -target_sources(mechanism_configuration - PRIVATE - aqueous_equilibrium.cpp - arrhenius.cpp - branched.cpp - condensed_phase_arrhenius.cpp - condensed_phase_photolysis.cpp - emission.cpp - first_order_loss.cpp - henrys_law.cpp - photolysis.cpp - simpol_phase_transfer.cpp - surface.cpp - taylor_series.cpp - ternary_chemical_activation.cpp - troe.cpp - tunneling.cpp - user_defined.cpp - lambda_rate_constant.cpp - wet_deposition.cpp -) \ No newline at end of file diff --git a/src/development/reactions/validators/aqueous_equilibrium.cpp b/src/development/reactions/validators/aqueous_equilibrium.cpp deleted file mode 100644 index ddb14d77..00000000 --- a/src/development/reactions/validators/aqueous_equilibrium.cpp +++ /dev/null @@ -1,105 +0,0 @@ -// Copyright (C) 2023–2026 University Corporation for Atmospheric Research -// University of Illinois at Urbana-Champaign -// SPDX-License-Identifier: Apache-2.0 - -#include -#include -#include -#include -#include -#include -#include -#include - -namespace mechanism_configuration -{ - namespace development - { - /// @brief Validates a YAML-defined Aqueous Equilibrium reaction entry. - /// Performs schema validation, ensures all referenced species and phases exist, - /// and collects any errors found. - /// @param object The YAML node representing the reaction - /// @param existing_species The list of known species used for validation - /// @param existing_phases The list of known phases used for validation - /// @return A list of validation errors, if any - Errors AqueousEquilibriumParser::Validate( - const YAML::Node& object, - const std::vector& existing_species, - const std::vector& existing_phases) - { - std::vector required_keys = { validation::type, - validation::reactants, - validation::products, - validation::condensed_phase, - validation::condensed_phase_water, - validation::k_reverse }; - std::vector optional_keys = { validation::name, validation::A, validation::C }; - - Errors errors; - - auto validation_errors = ValidateSchema(object, required_keys, optional_keys); - if (!validation_errors.empty()) - { - errors.insert(errors.end(), validation_errors.begin(), validation_errors.end()); - return errors; - } - - bool is_valid = true; - - // Reactants - validation_errors = ValidateReactantsOrProducts(object[validation::reactants]); - if (!validation_errors.empty()) - { - errors.insert(errors.end(), validation_errors.begin(), validation_errors.end()); - is_valid = false; - } - - // Products - validation_errors = ValidateReactantsOrProducts(object[validation::products]); - if (!validation_errors.empty()) - { - errors.insert(errors.end(), validation_errors.begin(), validation_errors.end()); - is_valid = false; - } - - if (!is_valid) - return errors; - - std::vector> species_node_pairs; - - for (const auto& obj : object[validation::reactants]) - { - types::ReactionComponent component; - component.name = obj[validation::name].as(); - species_node_pairs.emplace_back(component, obj); - } - for (const auto& obj : object[validation::products]) - { - types::ReactionComponent component; - component.name = obj[validation::name].as(); - species_node_pairs.emplace_back(component, obj); - } - - // Check for unknown species in reactants and products - std::vector unknown_species = FindUnknownObjectsByName(existing_species, species_node_pairs); - if (!unknown_species.empty()) - { - ReportUnknownSpecies(object, unknown_species, errors, ConfigParseStatus::ReactionRequiresUnknownSpecies); - } - - // Check for phase existence and get phase reference - auto phase_optional = CheckPhaseExists(object, validation::condensed_phase, existing_phases, errors); - if (!phase_optional) - { - return errors; - } - - // Check if phase-specific species in reaction is found in phase - const auto& phase = phase_optional->get(); - CheckSpeciesPresenceInPhase(object, phase, species_node_pairs, errors); - - return errors; - } - - } // namespace development -} // namespace mechanism_configuration diff --git a/src/development/reactions/validators/arrhenius.cpp b/src/development/reactions/validators/arrhenius.cpp deleted file mode 100644 index 43ebbdba..00000000 --- a/src/development/reactions/validators/arrhenius.cpp +++ /dev/null @@ -1,117 +0,0 @@ -// Copyright (C) 2023–2026 University Corporation for Atmospheric Research -// University of Illinois at Urbana-Champaign -// SPDX-License-Identifier: Apache-2.0 - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace mechanism_configuration -{ - namespace development - { - /// @brief Validates a YAML-defined Arrhenius reaction entry - /// Performs schema validation, checks for mutually exclusive parameters (`Ea` vs `C`), - /// ensures all referenced species and phases exist, and collects any errors found. - /// @param object The YAML node representing the reaction - /// @param existing_species The list of known species used for validation - /// @param existing_phases The list of known phases used for validation - /// @return A list of validation errors, if any - Errors ArrheniusParser::Validate( - const YAML::Node& object, - const std::vector& existing_species, - const std::vector& existing_phases) - { - std::vector required_keys = { - validation::reactants, validation::products, validation::type, validation::gas_phase - }; - std::vector optional_keys = { validation::A, validation::B, validation::C, validation::D, - validation::E, validation::Ea, validation::name }; - Errors errors; - - auto validation_errors = ValidateSchema(object, required_keys, optional_keys); - if (!validation_errors.empty()) - { - errors.insert(errors.end(), validation_errors.begin(), validation_errors.end()); - return errors; - } - - bool is_valid = true; - - // Reactants - validation_errors = ValidateReactantsOrProducts(object[validation::reactants]); - if (!validation_errors.empty()) - { - errors.insert(errors.end(), validation_errors.begin(), validation_errors.end()); - is_valid = false; - } - - // Products - validation_errors = ValidateReactantsOrProducts(object[validation::products]); - if (!validation_errors.empty()) - { - errors.insert(errors.end(), validation_errors.begin(), validation_errors.end()); - is_valid = false; - } - - if (object[validation::Ea] && object[validation::C]) - { - const auto& node = object[validation::Ea]; - ErrorLocation error_location{ node.Mark().line, node.Mark().column }; - - std::string message = mc_fmt::format( - "{} error: Mutually exclusive option of 'Ea' and 'C' found in '{}' reaction.", - error_location, - object[validation::type].as()); - - errors.push_back({ ConfigParseStatus::MutuallyExclusiveOption, message }); - is_valid = false; - } - - if (!is_valid) - return errors; - - std::vector> species_node_pairs; - - for (const auto& obj : object[validation::reactants]) - { - types::ReactionComponent component; - component.name = obj[validation::name].as(); - species_node_pairs.emplace_back(component, obj); - } - for (const auto& obj : object[validation::products]) - { - types::ReactionComponent component; - component.name = obj[validation::name].as(); - species_node_pairs.emplace_back(component, obj); - } - - // Check for unknown species in reactants and products - std::vector unknown_species = FindUnknownObjectsByName(existing_species, species_node_pairs); - if (!unknown_species.empty()) - { - ReportUnknownSpecies(object, unknown_species, errors, ConfigParseStatus::ReactionRequiresUnknownSpecies); - } - - // Check for phase existence and get phase reference - auto phase_optional = CheckPhaseExists(object, validation::gas_phase, existing_phases, errors); - if (!phase_optional) - { - return errors; - } - - // Check if phase-specific species in reaction is found in phase - const auto& phase = phase_optional->get(); - CheckSpeciesPresenceInPhase(object, phase, species_node_pairs, errors); - - return errors; - } - - } // namespace development -} // namespace mechanism_configuration diff --git a/src/development/reactions/validators/branched.cpp b/src/development/reactions/validators/branched.cpp deleted file mode 100644 index 5c1783d2..00000000 --- a/src/development/reactions/validators/branched.cpp +++ /dev/null @@ -1,120 +0,0 @@ -// Copyright (C) 2023–2026 University Corporation for Atmospheric Research -// University of Illinois at Urbana-Champaign -// SPDX-License-Identifier: Apache-2.0 - -#include -#include -#include -#include -#include -#include -#include -#include - -namespace mechanism_configuration -{ - namespace development - { - /// @brief Validates a YAML-defined Branched reaction entry - /// Performs schema validation, ensures all referenced species and phases exist, - /// and collects any errors found. - /// @param object The YAML node representing the reaction - /// @param existing_species The list of known species used for validation - /// @param existing_phases The list of known phases used for validation - /// @return A list of validation errors, if any - Errors BranchedParser::Validate( - const YAML::Node& object, - const std::vector& existing_species, - const std::vector& existing_phases) - { - std::vector required_keys = { validation::type, - validation::gas_phase, - validation::reactants, - validation::alkoxy_products, - validation::nitrate_products }; - std::vector optional_keys = { - validation::name, validation::X, validation::Y, validation::a0, validation::n - }; - - Errors errors; - - auto validation_errors = ValidateSchema(object, required_keys, optional_keys); - if (!validation_errors.empty()) - { - errors.insert(errors.end(), validation_errors.begin(), validation_errors.end()); - return errors; - } - - bool is_valid = true; - - // Reactants - validation_errors = ValidateReactantsOrProducts(object[validation::reactants]); - if (!validation_errors.empty()) - { - errors.insert(errors.end(), validation_errors.begin(), validation_errors.end()); - is_valid = false; - } - - // Alkoxy products - validation_errors = ValidateReactantsOrProducts(object[validation::alkoxy_products]); - if (!validation_errors.empty()) - { - errors.insert(errors.end(), validation_errors.begin(), validation_errors.end()); - is_valid = false; - } - - // Nitrate products - validation_errors = ValidateReactantsOrProducts(object[validation::nitrate_products]); - if (!validation_errors.empty()) - { - errors.insert(errors.end(), validation_errors.begin(), validation_errors.end()); - is_valid = false; - } - - if (!is_valid) - return errors; - - std::vector> species_node_pairs; - - for (const auto& obj : object[validation::reactants]) - { - types::ReactionComponent component; - component.name = obj[validation::name].as(); - species_node_pairs.emplace_back(component, obj); - } - for (const auto& obj : object[validation::alkoxy_products]) - { - types::ReactionComponent component; - component.name = obj[validation::name].as(); - species_node_pairs.emplace_back(component, obj); - } - for (const auto& obj : object[validation::nitrate_products]) - { - types::ReactionComponent component; - component.name = obj[validation::name].as(); - species_node_pairs.emplace_back(component, obj); - } - - // Check for unknown species in reactants and products - std::vector unknown_species = FindUnknownObjectsByName(existing_species, species_node_pairs); - if (!unknown_species.empty()) - { - ReportUnknownSpecies(object, unknown_species, errors, ConfigParseStatus::ReactionRequiresUnknownSpecies); - } - - // Check for phase existence and get phase reference - auto phase_optional = CheckPhaseExists(object, validation::gas_phase, existing_phases, errors); - if (!phase_optional) - { - return errors; - } - - // Check if phase-specific species in reaction is found in phase - const auto& phase = phase_optional->get(); - CheckSpeciesPresenceInPhase(object, phase, species_node_pairs, errors); - - return errors; - } - - } // namespace development -} // namespace mechanism_configuration diff --git a/src/development/reactions/validators/condensed_phase_arrhenius.cpp b/src/development/reactions/validators/condensed_phase_arrhenius.cpp deleted file mode 100644 index c1f11e3d..00000000 --- a/src/development/reactions/validators/condensed_phase_arrhenius.cpp +++ /dev/null @@ -1,117 +0,0 @@ -// Copyright (C) 2023–2026 University Corporation for Atmospheric Research -// University of Illinois at Urbana-Champaign -// SPDX-License-Identifier: Apache-2.0 - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace mechanism_configuration -{ - namespace development - { - /// @brief Validates a YAML-defined Condensed-phase Arrhenius reaction entry - /// Performs schema validation, checks for mutually exclusive parameters (`Ea` vs `C`), - /// ensures all referenced species and phases exist, and collects any errors found. - /// @param object The YAML node representing the reaction - /// @param existing_species The list of known species used for validation - /// @param existing_phases The list of known phases used for validation - /// @return A list of validation errors, if any - Errors CondensedPhaseArrheniusParser::Validate( - const YAML::Node& object, - const std::vector& existing_species, - const std::vector& existing_phases) - { - std::vector required_keys = { - validation::reactants, validation::products, validation::type, validation::condensed_phase - }; - std::vector optional_keys = { validation::A, validation::B, validation::C, validation::D, - validation::E, validation::Ea, validation::name }; - Errors errors; - - auto validation_errors = ValidateSchema(object, required_keys, optional_keys); - if (!validation_errors.empty()) - { - errors.insert(errors.end(), validation_errors.begin(), validation_errors.end()); - return errors; - } - - bool is_valid = true; - - // Reactants - validation_errors = ValidateReactantsOrProducts(object[validation::reactants]); - if (!validation_errors.empty()) - { - errors.insert(errors.end(), validation_errors.begin(), validation_errors.end()); - is_valid = false; - } - - // Products - validation_errors = ValidateReactantsOrProducts(object[validation::products]); - if (!validation_errors.empty()) - { - errors.insert(errors.end(), validation_errors.begin(), validation_errors.end()); - is_valid = false; - } - - if (object[validation::Ea] && object[validation::C]) - { - const auto& node = object[validation::Ea]; - ErrorLocation error_location{ node.Mark().line, node.Mark().column }; - - std::string message = mc_fmt::format( - "{} error: Mutually exclusive option of 'Ea' and 'C' found in '{}' reaction.", - error_location, - object[validation::type].as()); - - errors.push_back({ ConfigParseStatus::MutuallyExclusiveOption, message }); - is_valid = false; - } - - if (!is_valid) - return errors; - - std::vector> species_node_pairs; - - for (const auto& obj : object[validation::reactants]) - { - types::ReactionComponent component; - component.name = obj[validation::name].as(); - species_node_pairs.emplace_back(component, obj); - } - for (const auto& obj : object[validation::products]) - { - types::ReactionComponent component; - component.name = obj[validation::name].as(); - species_node_pairs.emplace_back(component, obj); - } - - // Check for unknown species in reactants and products - std::vector unknown_species = FindUnknownObjectsByName(existing_species, species_node_pairs); - if (!unknown_species.empty()) - { - ReportUnknownSpecies(object, unknown_species, errors, ConfigParseStatus::ReactionRequiresUnknownSpecies); - } - - // Check for phase existence and get phase reference - auto phase_optional = CheckPhaseExists(object, validation::condensed_phase, existing_phases, errors); - if (!phase_optional) - { - return errors; - } - - // Validate reaction species presence in phase - const auto& phase = phase_optional->get(); - CheckSpeciesPresenceInPhase(object, phase, species_node_pairs, errors); - - return errors; - } - - } // namespace development -} // namespace mechanism_configuration diff --git a/src/development/reactions/validators/condensed_phase_photolysis.cpp b/src/development/reactions/validators/condensed_phase_photolysis.cpp deleted file mode 100644 index 6469fb6f..00000000 --- a/src/development/reactions/validators/condensed_phase_photolysis.cpp +++ /dev/null @@ -1,119 +0,0 @@ -// Copyright (C) 2023–2026 University Corporation for Atmospheric Research -// University of Illinois at Urbana-Champaign -// SPDX-License-Identifier: Apache-2.0 - -#include -#include -#include -#include -#include -#include -#include -#include - -namespace mechanism_configuration -{ - namespace development - { - /// @brief Validates a YAML-defined Condensed-phase Photolysis reaction entry. - /// Performs schema validation, ensures all referenced species and phases exist, - /// and collects any errors found. - /// @param object The YAML node representing the reaction - /// @param existing_species The list of known species used for validation - /// @param existing_phases The list of known phases used for validation - /// @return A list of validation errors, if any - Errors CondensedPhasePhotolysisParser::Validate( - const YAML::Node& object, - const std::vector& existing_species, - const std::vector& existing_phases) - { - std::vector required_keys = { - validation::reactants, validation::products, validation::type, validation::condensed_phase - }; - std::vector optional_keys = { validation::name, validation::scaling_factor }; - - Errors errors; - - auto validation_errors = ValidateSchema(object, required_keys, optional_keys); - if (!validation_errors.empty()) - { - errors.insert(errors.end(), validation_errors.begin(), validation_errors.end()); - return errors; - } - - bool is_valid = true; - - // Reactants - validation_errors = ValidateReactantsOrProducts(object[validation::reactants]); - if (!validation_errors.empty()) - { - errors.insert(errors.end(), validation_errors.begin(), validation_errors.end()); - is_valid = false; - } - - // Products - validation_errors = ValidateReactantsOrProducts(object[validation::products]); - if (!validation_errors.empty()) - { - errors.insert(errors.end(), validation_errors.begin(), validation_errors.end()); - is_valid = false; - } - - if (!is_valid) - return errors; - - std::vector> species_node_pairs; - - for (const auto& obj : object[validation::reactants]) - { - types::ReactionComponent component; - component.name = obj[validation::name].as(); - species_node_pairs.emplace_back(component, obj); - } - - // Validates the number of reactants - // This must be done before collecting errors from the products - if (species_node_pairs.size() > 1) - { - const auto& node = object[validation::reactants]; - ErrorLocation error_location{ node.Mark().line, node.Mark().column }; - - std::string message = mc_fmt::format( - "{} error: '{}' reaction requires one reactant, but {} were provided.", - error_location, - object[validation::type].as(), - species_node_pairs.size()); - - errors.push_back({ ConfigParseStatus::TooManyReactionComponents, message }); - } - - for (const auto& obj : object[validation::products]) - { - types::ReactionComponent component; - component.name = obj[validation::name].as(); - species_node_pairs.emplace_back(component, obj); - } - - // Check for unknown species in reactants and products - std::vector unknown_species = FindUnknownObjectsByName(existing_species, species_node_pairs); - if (!unknown_species.empty()) - { - ReportUnknownSpecies(object, unknown_species, errors, ConfigParseStatus::ReactionRequiresUnknownSpecies); - } - - // Check for phase existence and get phase reference - auto phase_optional = CheckPhaseExists(object, validation::condensed_phase, existing_phases, errors); - if (!phase_optional) - { - return errors; - } - - // Check if phase-specific species in reaction is found in phase - const auto& phase = phase_optional->get(); - CheckSpeciesPresenceInPhase(object, phase, species_node_pairs, errors); - - return errors; - } - - } // namespace development -} // namespace mechanism_configuration diff --git a/src/development/reactions/validators/emission.cpp b/src/development/reactions/validators/emission.cpp deleted file mode 100644 index 5bd8aa17..00000000 --- a/src/development/reactions/validators/emission.cpp +++ /dev/null @@ -1,86 +0,0 @@ -// Copyright (C) 2023–2026 University Corporation for Atmospheric Research -// University of Illinois at Urbana-Champaign -// SPDX-License-Identifier: Apache-2.0 - -#include -#include -#include -#include -#include -#include -#include -#include - -namespace mechanism_configuration -{ - namespace development - { - /// @brief Validates a YAML-defined Emission reaction entry. - /// Performs schema validation, ensures all referenced species and phases exist, - /// and collects any errors found. - /// @param object The YAML node representing the reaction - /// @param existing_species The list of known species used for validation - /// @param existing_phases The list of known phases used for validation - /// @return A list of validation errors, if any - Errors EmissionParser::Validate( - const YAML::Node& object, - const std::vector& existing_species, - const std::vector& existing_phases) - { - std::vector required_keys = { validation::products, validation::type, validation::gas_phase }; - std::vector optional_keys = { validation::name, validation::scaling_factor }; - - Errors errors; - - auto validation_errors = ValidateSchema(object, required_keys, optional_keys); - if (!validation_errors.empty()) - { - errors.insert(errors.end(), validation_errors.begin(), validation_errors.end()); - return errors; - } - - bool is_valid = true; - - // Products - validation_errors = ValidateReactantsOrProducts(object[validation::products]); - if (!validation_errors.empty()) - { - errors.insert(errors.end(), validation_errors.begin(), validation_errors.end()); - is_valid = false; - } - - if (!is_valid) - return errors; - - std::vector> species_node_pairs; - - for (const auto& obj : object[validation::products]) - { - types::ReactionComponent component; - component.name = obj[validation::name].as(); - species_node_pairs.emplace_back(component, obj); - } - - // Check for unknown species in reactants and products - std::vector unknown_species = FindUnknownObjectsByName(existing_species, species_node_pairs); - if (!unknown_species.empty()) - { - ReportUnknownSpecies(object, unknown_species, errors, ConfigParseStatus::ReactionRequiresUnknownSpecies); - } - - // Check for phase existence and get phase reference - auto phase_optional = CheckPhaseExists(object, validation::gas_phase, existing_phases, errors); - if (!phase_optional) - { - return errors; - } - - // Check if phase-specific species in reaction is found in phase - const auto& phase = phase_optional->get(); - CheckSpeciesPresenceInPhase(object, phase, species_node_pairs, errors); - - return errors; - } - - } // namespace development -} // namespace mechanism_configuration diff --git a/src/development/reactions/validators/first_order_loss.cpp b/src/development/reactions/validators/first_order_loss.cpp deleted file mode 100644 index 5adf1b48..00000000 --- a/src/development/reactions/validators/first_order_loss.cpp +++ /dev/null @@ -1,100 +0,0 @@ -// Copyright (C) 2023–2026 University Corporation for Atmospheric Research -// University of Illinois at Urbana-Champaign -// SPDX-License-Identifier: Apache-2.0 - -#include -#include -#include -#include -#include -#include -#include -#include - -namespace mechanism_configuration -{ - namespace development - { - /// @brief Validates a YAML-defined First order loss reaction entry. - /// Performs schema validation, ensures all referenced species and phases exist, - /// and collects any errors found. - /// @param object The YAML node representing the reaction - /// @param existing_species The list of known species used for validation - /// @param existing_phases The list of known phases used for validation - /// @return A list of validation errors, if any - Errors FirstOrderLossParser::Validate( - const YAML::Node& object, - const std::vector& existing_species, - const std::vector& existing_phases) - { - std::vector required_keys = { validation::reactants, validation::type, validation::gas_phase }; - std::vector optional_keys = { validation::name, validation::scaling_factor }; - - Errors errors; - - auto validation_errors = ValidateSchema(object, required_keys, optional_keys); - if (!validation_errors.empty()) - { - errors.insert(errors.end(), validation_errors.begin(), validation_errors.end()); - return errors; - } - - bool is_valid = true; - - // Reactants - validation_errors = ValidateReactantsOrProducts(object[validation::reactants]); - if (!validation_errors.empty()) - { - errors.insert(errors.end(), validation_errors.begin(), validation_errors.end()); - is_valid = false; - } - - if (!is_valid) - return errors; - - std::vector> species_node_pairs; - - for (const auto& obj : object[validation::reactants]) - { - types::ReactionComponent component; - component.name = obj[validation::name].as(); - species_node_pairs.emplace_back(component, obj); - } - - if (species_node_pairs.size() > 1) - { - const auto& node = object[validation::reactants]; - ErrorLocation error_location{ node.Mark().line, node.Mark().column }; - - std::string message = mc_fmt::format( - "{} error: '{}' reaction requires one reactant, but {} were provided.", - error_location, - object[validation::type].as(), - species_node_pairs.size()); - - errors.push_back({ ConfigParseStatus::TooManyReactionComponents, message }); - } - - // Check for unknown species in reactants and products - std::vector unknown_species = FindUnknownObjectsByName(existing_species, species_node_pairs); - if (!unknown_species.empty()) - { - ReportUnknownSpecies(object, unknown_species, errors, ConfigParseStatus::ReactionRequiresUnknownSpecies); - } - - // Check for phase existence and get phase reference - auto phase_optional = CheckPhaseExists(object, validation::gas_phase, existing_phases, errors); - if (!phase_optional) - { - return errors; - } - - // Check if phase-specific species in reaction is found in phase - const auto& phase = phase_optional->get(); - CheckSpeciesPresenceInPhase(object, phase, species_node_pairs, errors); - - return errors; - } - - } // namespace development -} // namespace mechanism_configuration diff --git a/src/development/reactions/validators/henrys_law.cpp b/src/development/reactions/validators/henrys_law.cpp deleted file mode 100644 index c9839d12..00000000 --- a/src/development/reactions/validators/henrys_law.cpp +++ /dev/null @@ -1,151 +0,0 @@ -// Copyright (C) 2023–2026 University Corporation for Atmospheric Research -// University of Illinois at Urbana-Champaign -// SPDX-License-Identifier: Apache-2.0 - -#include -#include -#include -#include -#include -#include -#include -#include - -namespace mechanism_configuration -{ - namespace development - { - /// @brief Validates a YAML-defined Henry's Law reaction entry. - /// Performs schema validation, ensures all referenced species and phases exist, - /// and collects any errors found. - /// @param object The YAML node representing the reaction - /// @param existing_species The list of known species used for validation - /// @param existing_phases The list of known phases used for validation - /// @return A list of validation errors, if any - Errors HenrysLawParser::Validate( - const YAML::Node& object, - const std::vector& existing_species, - const std::vector& existing_phases) - { - std::vector required_keys = { validation::type, validation::gas, validation::particle }; - std::vector opt_keys = { validation::name }; - - Errors errors; - - auto validation_errors = ValidateSchema(object, required_keys, opt_keys); - if (!validation_errors.empty()) - { - errors.insert(errors.end(), validation_errors.begin(), validation_errors.end()); - return errors; - } - - bool is_valid = true; - - // Gas phase - validation_errors = ValidatePhases(object[validation::gas], existing_species); - if (!validation_errors.empty()) - { - errors.insert(errors.end(), validation_errors.begin(), validation_errors.end()); - is_valid = false; - } - - // Particle - validation_errors = ValidateParticles(object[validation::particle]); - if (!validation_errors.empty()) - { - errors.insert(errors.end(), validation_errors.begin(), validation_errors.end()); - is_valid = false; - } - - if (!is_valid) - return errors; - - // Gather gas and particle species node pairs - std::vector> gas_species_node_pairs; - - // Although the type being validated is PhaseSpecies instead of ReactionComponent, - // the corresponding struct is conceptually the same. (diffusion coefficient vs. coefficient) - // Treating these entries as ReactionComponent objects is acceptable. - for (const auto& obj : object[validation::gas][validation::species]) - { - types::ReactionComponent component; - component.name = obj[validation::name].as(); - gas_species_node_pairs.emplace_back(std::move(component), obj); - } - - std::vector> particle_species_node_pairs; - - // Solvent - for (const auto& obj : object[validation::particle][validation::solvent]) - { - types::ReactionComponent component; - component.name = obj[validation::name].as(); - particle_species_node_pairs.emplace_back(component, obj); - } - - // Validates the number of solvent - // This must be done before collecting errors from the solutes - if (particle_species_node_pairs.size() > 1) - { - const auto& node = object[validation::particle][validation::solvent]; - ErrorLocation error_location{ node.Mark().line, node.Mark().column }; - - std::string message = mc_fmt::format( - "{} error: '{}' reaction requires one solute, but {} were provided.", - error_location, - object[validation::type].as(), - particle_species_node_pairs.size()); - - errors.push_back({ ConfigParseStatus::TooManyReactionComponents, message }); - } - - // Solutes - for (const auto& obj : object[validation::particle][validation::solutes]) - { - types::ReactionComponent component; - component.name = obj[validation::name].as(); - particle_species_node_pairs.emplace_back(std::move(component), obj); - } - - // Unknown species - std::vector unknown_species = FindUnknownObjectsByName(existing_species, gas_species_node_pairs); - if (!unknown_species.empty()) - { - ReportUnknownSpecies(object, unknown_species, errors, ConfigParseStatus::ReactionRequiresUnknownSpecies); - } - - unknown_species = FindUnknownObjectsByName(existing_species, particle_species_node_pairs); - if (!unknown_species.empty()) - { - ReportUnknownSpecies(object, unknown_species, errors, ConfigParseStatus::ReactionRequiresUnknownSpecies); - } - - auto gas_phase_opt = CheckPhaseExists( - object[validation::gas], - validation::name, - existing_phases, - errors, - ConfigParseStatus::UnknownPhase, - object[validation::type].as()); - - auto particle_phase_opt = CheckPhaseExists( - object[validation::particle], - validation::phase, - existing_phases, - errors, - ConfigParseStatus::UnknownPhase, - object[validation::type].as()); - if (!gas_phase_opt || !particle_phase_opt) - { - return errors; - } - - // Check if phase-specific species in reaction is found in phase - CheckSpeciesPresenceInPhase(object, gas_phase_opt->get(), gas_species_node_pairs, errors); - CheckSpeciesPresenceInPhase(object, particle_phase_opt->get(), particle_species_node_pairs, errors); - - return errors; - } - - } // namespace development -} // namespace mechanism_configuration diff --git a/src/development/reactions/validators/lambda_rate_constant.cpp b/src/development/reactions/validators/lambda_rate_constant.cpp deleted file mode 100644 index ea8e82f6..00000000 --- a/src/development/reactions/validators/lambda_rate_constant.cpp +++ /dev/null @@ -1,101 +0,0 @@ -// Copyright (C) 2023–2026 University Corporation for Atmospheric Research -// University of Illinois at Urbana-Champaign -// SPDX-License-Identifier: Apache-2.0 - -#include -#include -#include -#include -#include -#include -#include -#include - -namespace mechanism_configuration -{ - namespace development - { - /// @brief Validates a YAML-defined Lambda Rate Constant reaction entry - /// Performs schema validation, ensures all referenced species and phases exist, - /// and collects any errors found. - /// @param object The YAML node representing the reaction - /// @param existing_species The list of known species used for validation - /// @param existing_phases The list of known phases used for validation - /// @return A list of validation errors, if any - Errors LambdaRateConstantParser::Validate( - const YAML::Node& object, - const std::vector& existing_species, - const std::vector& existing_phases) - { - std::vector required_keys = { - validation::reactants, validation::products, validation::type, validation::gas_phase, validation::lambda_function - }; - std::vector optional_keys = { validation::name }; - Errors errors; - - auto validation_errors = ValidateSchema(object, required_keys, optional_keys); - if (!validation_errors.empty()) - { - errors.insert(errors.end(), validation_errors.begin(), validation_errors.end()); - return errors; - } - - bool is_valid = true; - - // Reactants - validation_errors = ValidateReactantsOrProducts(object[validation::reactants]); - if (!validation_errors.empty()) - { - errors.insert(errors.end(), validation_errors.begin(), validation_errors.end()); - is_valid = false; - } - - // Products - validation_errors = ValidateReactantsOrProducts(object[validation::products]); - if (!validation_errors.empty()) - { - errors.insert(errors.end(), validation_errors.begin(), validation_errors.end()); - is_valid = false; - } - - if (!is_valid) - return errors; - - std::vector> species_node_pairs; - - for (const auto& obj : object[validation::reactants]) - { - types::ReactionComponent component; - component.name = obj[validation::name].as(); - species_node_pairs.emplace_back(component, obj); - } - for (const auto& obj : object[validation::products]) - { - types::ReactionComponent component; - component.name = obj[validation::name].as(); - species_node_pairs.emplace_back(component, obj); - } - - // Check for unknown species in reactants and products - std::vector unknown_species = FindUnknownObjectsByName(existing_species, species_node_pairs); - if (!unknown_species.empty()) - { - ReportUnknownSpecies(object, unknown_species, errors, ConfigParseStatus::ReactionRequiresUnknownSpecies); - } - - // Check for phase existence and get phase reference - auto phase_optional = CheckPhaseExists(object, validation::gas_phase, existing_phases, errors); - if (!phase_optional) - { - return errors; - } - - // Check if phase-specific species in reaction is found in phase - const auto& phase = phase_optional->get(); - CheckSpeciesPresenceInPhase(object, phase, species_node_pairs, errors); - - return errors; - } - - } // namespace development -} // namespace mechanism_configuration diff --git a/src/development/reactions/validators/photolysis.cpp b/src/development/reactions/validators/photolysis.cpp deleted file mode 100644 index df45bfd0..00000000 --- a/src/development/reactions/validators/photolysis.cpp +++ /dev/null @@ -1,119 +0,0 @@ -// Copyright (C) 2023–2026 University Corporation for Atmospheric Research -// University of Illinois at Urbana-Champaign -// SPDX-License-Identifier: Apache-2.0 - -#include -#include -#include -#include -#include -#include -#include -#include - -namespace mechanism_configuration -{ - namespace development - { - /// @brief Validates a YAML-defined Photolysis reaction entry. - /// Performs schema validation, ensures all referenced species and phases exist, - /// and collects any errors found. - /// @param object The YAML node representing the reaction - /// @param existing_species The list of known species used for validation - /// @param existing_phases The list of known phases used for validation - /// @return A list of validation errors, if any - Errors PhotolysisParser::Validate( - const YAML::Node& object, - const std::vector& existing_species, - const std::vector& existing_phases) - { - std::vector required_keys = { - validation::reactants, validation::products, validation::type, validation::gas_phase - }; - std::vector optional_keys = { validation::name, validation::scaling_factor }; - - Errors errors; - - auto validation_errors = ValidateSchema(object, required_keys, optional_keys); - if (!validation_errors.empty()) - { - errors.insert(errors.end(), validation_errors.begin(), validation_errors.end()); - return errors; - } - - bool is_valid = true; - - // Reactants - validation_errors = ValidateReactantsOrProducts(object[validation::reactants]); - if (!validation_errors.empty()) - { - errors.insert(errors.end(), validation_errors.begin(), validation_errors.end()); - is_valid = false; - } - - // Products - validation_errors = ValidateReactantsOrProducts(object[validation::products]); - if (!validation_errors.empty()) - { - errors.insert(errors.end(), validation_errors.begin(), validation_errors.end()); - is_valid = false; - } - - if (!is_valid) - return errors; - - std::vector> species_node_pairs; - - for (const auto& obj : object[validation::reactants]) - { - types::ReactionComponent component; - component.name = obj[validation::name].as(); - species_node_pairs.emplace_back(component, obj); - } - - // Validates the number of reactants - // This must be done before collecting errors from the products - if (species_node_pairs.size() > 1) - { - const auto& node = object[validation::reactants]; - ErrorLocation error_location{ node.Mark().line, node.Mark().column }; - - std::string message = mc_fmt::format( - "{} error: '{}' reaction requires one reactant, but {} were provided.", - error_location, - object[validation::type].as(), - species_node_pairs.size()); - - errors.push_back({ ConfigParseStatus::TooManyReactionComponents, message }); - } - - for (const auto& obj : object[validation::products]) - { - types::ReactionComponent component; - component.name = obj[validation::name].as(); - species_node_pairs.emplace_back(component, obj); - } - - // Check for unknown species in reactants and products - std::vector unknown_species = FindUnknownObjectsByName(existing_species, species_node_pairs); - if (!unknown_species.empty()) - { - ReportUnknownSpecies(object, unknown_species, errors, ConfigParseStatus::ReactionRequiresUnknownSpecies); - } - - // Check for phase existence and get phase reference - auto phase_optional = CheckPhaseExists(object, validation::gas_phase, existing_phases, errors); - if (!phase_optional) - { - return errors; - } - - // Check if phase-specific species in reaction is found in phase - const auto& phase = phase_optional->get(); - CheckSpeciesPresenceInPhase(object, phase, species_node_pairs, errors); - - return errors; - } - - } // namespace development -} // namespace mechanism_configuration diff --git a/src/development/reactions/validators/simpol_phase_transfer.cpp b/src/development/reactions/validators/simpol_phase_transfer.cpp deleted file mode 100644 index f4d8cc65..00000000 --- a/src/development/reactions/validators/simpol_phase_transfer.cpp +++ /dev/null @@ -1,174 +0,0 @@ -// Copyright (C) 2023–2026 University Corporation for Atmospheric Research -// University of Illinois at Urbana-Champaign -// SPDX-License-Identifier: Apache-2.0 - -#include -#include -#include -#include -#include -#include -#include -#include - -namespace mechanism_configuration -{ - namespace development - { - /// @brief Validates a YAML-defined Simpol Phase Transfer reaction entry. - /// Performs schema validation, ensures all referenced species and phases exist, - /// and collects any errors found. - /// @param object The YAML node representing the reaction - /// @param existing_species The list of known species used for validation - /// @param existing_phases The list of known phases used for validation - /// @return A list of validation errors, if any - Errors SimpolPhaseTransferParser::Validate( - const YAML::Node& object, - const std::vector& existing_species, - const std::vector& existing_phases) - { - std::vector required_keys = { validation::type, - validation::gas_phase, - validation::gas_phase_species, - validation::condensed_phase, - validation::condensed_phase_species, - validation::B }; - std::vector optional_keys = { validation::name }; - - Errors errors; - - auto validation_errors = ValidateSchema(object, required_keys, optional_keys); - if (!validation_errors.empty()) - { - errors.insert(errors.end(), validation_errors.begin(), validation_errors.end()); - return errors; - } - - bool is_valid = true; - - validation_errors = ValidateReactantsOrProducts(object[validation::gas_phase_species]); - if (!validation_errors.empty()) - { - errors.insert(errors.end(), validation_errors.begin(), validation_errors.end()); - is_valid = false; - } - - validation_errors = ValidateReactantsOrProducts(object[validation::condensed_phase_species]); - if (!validation_errors.empty()) - { - errors.insert(errors.end(), validation_errors.begin(), validation_errors.end()); - is_valid = false; - } - - if (!is_valid) - return errors; - - // Validate parameter 'B' - constexpr double NUM_PARAMS = 4; - if (!object[validation::B].IsSequence() || object[validation::B].size() != NUM_PARAMS) - { - const auto& node = object[validation::B]; - ErrorLocation error_location{ node.Mark().line, node.Mark().column }; - - std::string issue; - if (!object[validation::B].IsSequence()) - { - issue = "value must be a sequence"; - } - else - { - issue = mc_fmt::format("requires {} parameters, but {} were provided", NUM_PARAMS, object[validation::B].size()); - } - - std::string message = mc_fmt::format( - "{} error: '{}' reaction parameter 'B' {}.", error_location, object[validation::type].as(), issue); - - errors.push_back({ ConfigParseStatus::InvalidParameterNumber, message }); - } - - // Validates the number of gas phase species - std::vector> gas_species_node_pairs; - - for (const auto& obj : object[validation::gas_phase_species]) - { - types::ReactionComponent component; - component.name = obj[validation::name].as(); - gas_species_node_pairs.emplace_back(component, obj); - } - - if (gas_species_node_pairs.size() > 1) - { - const auto& node = object[validation::gas_phase_species]; - ErrorLocation error_location{ node.Mark().line, node.Mark().column }; - - std::string message = mc_fmt::format( - "{} error: '{}' reaction requires one gas phase, but {} were provided.", - error_location, - object[validation::type].as(), - gas_species_node_pairs.size()); - - errors.push_back({ ConfigParseStatus::TooManyReactionComponents, message }); - } - - // Check for unknown species in gas phase species - std::vector unknown_species = FindUnknownObjectsByName(existing_species, gas_species_node_pairs); - if (!unknown_species.empty()) - { - ReportUnknownSpecies(object, unknown_species, errors, ConfigParseStatus::ReactionRequiresUnknownSpecies); - } - - // Validates the number of condensed phase species - std::vector> condensed_species_node_pairs; - - for (const auto& obj : object[validation::condensed_phase_species]) - { - types::ReactionComponent component; - component.name = obj[validation::name].as(); - condensed_species_node_pairs.emplace_back(component, obj); - } - - if (condensed_species_node_pairs.size() > 1) - { - const auto& node = object[validation::condensed_phase_species]; - ErrorLocation error_location{ node.Mark().line, node.Mark().column }; - - std::string message = mc_fmt::format( - "{} error: '{}' reaction requires one condensed phase, but {} were provided.", - error_location, - object[validation::type].as(), - condensed_species_node_pairs.size()); - - errors.push_back({ ConfigParseStatus::TooManyReactionComponents, message }); - } - - // Check for unknown species in condensed phase species - unknown_species = FindUnknownObjectsByName(existing_species, condensed_species_node_pairs); - if (!unknown_species.empty()) - { - ReportUnknownSpecies(object, unknown_species, errors, ConfigParseStatus::ReactionRequiresUnknownSpecies); - } - - // Check for phase existence and get phase reference - auto gas_phase_optional = CheckPhaseExists(object, validation::gas_phase, existing_phases, errors); - if (!gas_phase_optional) - { - return errors; - } - auto condensed_phase_optional = CheckPhaseExists(object, validation::condensed_phase, existing_phases, errors); - if (!condensed_phase_optional) - { - return errors; - } - - // Check if phase-specific species in reaction is found in phase - const auto& gas_phase = gas_phase_optional->get(); - CheckSpeciesPresenceInPhase(object, gas_phase, gas_species_node_pairs, errors); - - const auto& condensed_phase = condensed_phase_optional->get(); - CheckSpeciesPresenceInPhase(object, condensed_phase, condensed_species_node_pairs, errors); - - return errors; - } - - } // namespace development -} // namespace mechanism_configuration diff --git a/src/development/reactions/validators/surface.cpp b/src/development/reactions/validators/surface.cpp deleted file mode 100644 index 1342133d..00000000 --- a/src/development/reactions/validators/surface.cpp +++ /dev/null @@ -1,125 +0,0 @@ -// Copyright (C) 2023–2026 University Corporation for Atmospheric Research -// University of Illinois at Urbana-Champaign -// SPDX-License-Identifier: Apache-2.0 - -#include -#include -#include -#include -#include -#include -#include -#include - -namespace mechanism_configuration -{ - namespace development - { - /// @brief Validates a YAML-defined Surface reaction entry. - /// Performs schema validation, ensures all referenced species and phases exist, - /// and collects any errors found. - /// @param object The YAML node representing the reaction - /// @param existing_species The list of known species used for validation - /// @param existing_phases The list of known phases used for validation - /// @return A list of validation errors, if any - Errors SurfaceParser::Validate( - const YAML::Node& object, - const std::vector& existing_species, - const std::vector& existing_phases) - { - std::vector required_keys = { validation::gas_phase_products, - validation::gas_phase_species, - validation::type, - validation::gas_phase, - validation::condensed_phase }; - std::vector optional_keys = { validation::name, validation::reaction_probability }; - - Errors errors; - - auto validation_errors = ValidateSchema(object, required_keys, optional_keys); - if (!validation_errors.empty()) - { - errors.insert(errors.end(), validation_errors.begin(), validation_errors.end()); - return errors; - } - - bool is_valid = true; - - // Gas phase species reactant - validation_errors = ValidateReactantsOrProducts(object[validation::gas_phase_species]); - if (!validation_errors.empty()) - { - errors.insert(errors.end(), validation_errors.begin(), validation_errors.end()); - is_valid = false; - } - - // Products - validation_errors = ValidateReactantsOrProducts(object[validation::gas_phase_products]); - if (!validation_errors.empty()) - { - errors.insert(errors.end(), validation_errors.begin(), validation_errors.end()); - is_valid = false; - } - - if (!is_valid) - return errors; - - std::vector> species_node_pairs; - - for (const auto& obj : object[validation::gas_phase_species]) - { - types::ReactionComponent component; - component.name = obj[validation::name].as(); - species_node_pairs.emplace_back(component, obj); - } - - // Validates the number of reactants - // This must be done before collecting errors from the products - if (species_node_pairs.size() > 1) - { - const auto& node = object[validation::gas_phase_species]; - ErrorLocation error_location{ node.Mark().line, node.Mark().column }; - - std::string message = mc_fmt::format( - "{} error: '{}' reaction requires one reactant, but {} were provided.", - error_location, - object[validation::type].as(), - species_node_pairs.size()); - - errors.push_back({ ConfigParseStatus::TooManyReactionComponents, message }); - } - - for (const auto& obj : object[validation::gas_phase_products]) - { - types::ReactionComponent component; - component.name = obj[validation::name].as(); - species_node_pairs.emplace_back(component, obj); - } - - // Check for unknown species in reactants and products - std::vector unknown_species = FindUnknownObjectsByName(existing_species, species_node_pairs); - if (!unknown_species.empty()) - { - ReportUnknownSpecies(object, unknown_species, errors, ConfigParseStatus::ReactionRequiresUnknownSpecies); - } - - // Check for phase existence and get phase reference - auto gas_phase_optional = CheckPhaseExists(object, validation::gas_phase, existing_phases, errors); - if (!gas_phase_optional) - { - return errors; - } - auto condensed_phase_optional = CheckPhaseExists(object, validation::condensed_phase, existing_phases, errors); - if (!condensed_phase_optional) - { - return errors; - } - - // Check if phase-specific species in reaction is found in phase - const auto& gas_phase = gas_phase_optional->get(); - CheckSpeciesPresenceInPhase(object, gas_phase, species_node_pairs, errors); - - return errors; - } - } // namespace development -} // namespace mechanism_configuration diff --git a/src/development/reactions/validators/taylor_series.cpp b/src/development/reactions/validators/taylor_series.cpp deleted file mode 100644 index 76f3c5ec..00000000 --- a/src/development/reactions/validators/taylor_series.cpp +++ /dev/null @@ -1,118 +0,0 @@ -// Copyright (C) 2023–2026 University Corporation for Atmospheric Research -// University of Illinois at Urbana-Champaign -// SPDX-License-Identifier: Apache-2.0 - -#include -#include -#include -#include -#include -#include -#include -#include - -namespace mechanism_configuration -{ - namespace development - { - /// @brief Validates a YAML-defined Taylor Series reaction entry - /// Performs schema validation, checks for mutually exclusive parameters (`Ea` vs `C`), - /// ensures all referenced species and phases exist, and collects any errors found. - /// @param object The YAML node representing the reaction - /// @param existing_species The list of known species used for validation - /// @param existing_phases The list of known phases used for validation - /// @return A list of validation errors, if any - Errors TaylorSeriesParser::Validate( - const YAML::Node& object, - const std::vector& existing_species, - const std::vector& existing_phases) - { - std::vector required_keys = { - validation::reactants, validation::products, validation::type, validation::gas_phase - }; - std::vector optional_keys = { validation::A, validation::B, - validation::C, validation::D, - validation::E, validation::Ea, - validation::name, validation::taylor_coefficients }; - Errors errors; - - auto validation_errors = ValidateSchema(object, required_keys, optional_keys); - if (!validation_errors.empty()) - { - errors.insert(errors.end(), validation_errors.begin(), validation_errors.end()); - return errors; - } - - bool is_valid = true; - - // Reactants - validation_errors = ValidateReactantsOrProducts(object[validation::reactants]); - if (!validation_errors.empty()) - { - errors.insert(errors.end(), validation_errors.begin(), validation_errors.end()); - is_valid = false; - } - - // Products - validation_errors = ValidateReactantsOrProducts(object[validation::products]); - if (!validation_errors.empty()) - { - errors.insert(errors.end(), validation_errors.begin(), validation_errors.end()); - is_valid = false; - } - - if (object[validation::Ea] && object[validation::C]) - { - const auto& node = object[validation::Ea]; - ErrorLocation error_location{ node.Mark().line, node.Mark().column }; - - std::string message = mc_fmt::format( - "{} error: Mutually exclusive option of 'Ea' and 'C' found in '{}' reaction.", - error_location, - object[validation::type].as()); - - errors.push_back({ ConfigParseStatus::MutuallyExclusiveOption, message }); - is_valid = false; - } - - if (!is_valid) - return errors; - - std::vector> species_node_pairs; - - for (const auto& obj : object[validation::reactants]) - { - types::ReactionComponent component; - component.name = obj[validation::name].as(); - species_node_pairs.emplace_back(component, obj); - } - for (const auto& obj : object[validation::products]) - { - types::ReactionComponent component; - component.name = obj[validation::name].as(); - species_node_pairs.emplace_back(component, obj); - } - - // Check for unknown species in reactants and products - std::vector unknown_species = FindUnknownObjectsByName(existing_species, species_node_pairs); - if (!unknown_species.empty()) - { - ReportUnknownSpecies(object, unknown_species, errors, ConfigParseStatus::ReactionRequiresUnknownSpecies); - } - - // Check for phase existence and get phase reference - auto phase_optional = CheckPhaseExists(object, validation::gas_phase, existing_phases, errors); - if (!phase_optional) - { - return errors; - } - - // Check if phase-specific species in reaction is found in phase - const auto& phase = phase_optional->get(); - CheckSpeciesPresenceInPhase(object, phase, species_node_pairs, errors); - - return errors; - } - - } // namespace development -} // namespace mechanism_configuration diff --git a/src/development/reactions/validators/ternary_chemical_activation.cpp b/src/development/reactions/validators/ternary_chemical_activation.cpp deleted file mode 100644 index 2294425e..00000000 --- a/src/development/reactions/validators/ternary_chemical_activation.cpp +++ /dev/null @@ -1,102 +0,0 @@ -// Copyright (C) 2023–2026 University Corporation for Atmospheric Research -// University of Illinois at Urbana-Champaign -// SPDX-License-Identifier: Apache-2.0 - -#include -#include -#include -#include -#include -#include -#include - -namespace mechanism_configuration -{ - namespace development - { - /// @brief Validates a YAML-defined Ternary ChemicalActivation reaction entry - /// Performs schema validation, ensures all referenced species and phases exist, - /// and collects any errors found. - /// @param object The YAML node representing the reaction - /// @param existing_species The list of known species used for validation - /// @param existing_phases The list of known phases used for validation - /// @return A list of validation errors, if any - Errors TernaryChemicalActivationParser::Validate( - const YAML::Node& object, - const std::vector& existing_species, - const std::vector& existing_phases) - { - std::vector required_keys = { - validation::reactants, validation::products, validation::type, validation::gas_phase - }; - std::vector optional_keys = { validation::name, validation::k0_A, validation::k0_B, - validation::k0_C, validation::kinf_A, validation::kinf_B, - validation::kinf_C, validation::Fc, validation::N }; - Errors errors; - - auto validation_errors = ValidateSchema(object, required_keys, optional_keys); - if (!validation_errors.empty()) - { - errors.insert(errors.end(), validation_errors.begin(), validation_errors.end()); - return errors; - } - - bool is_valid = true; - - // Reactants - validation_errors = ValidateReactantsOrProducts(object[validation::reactants]); - if (!validation_errors.empty()) - { - errors.insert(errors.end(), validation_errors.begin(), validation_errors.end()); - is_valid = false; - } - - // Products - validation_errors = ValidateReactantsOrProducts(object[validation::products]); - if (!validation_errors.empty()) - { - errors.insert(errors.end(), validation_errors.begin(), validation_errors.end()); - is_valid = false; - } - - if (!is_valid) - return errors; - - std::vector> species_node_pairs; - - for (const auto& obj : object[validation::reactants]) - { - types::ReactionComponent component; - component.name = obj[validation::name].as(); - species_node_pairs.emplace_back(component, obj); - } - for (const auto& obj : object[validation::products]) - { - types::ReactionComponent component; - component.name = obj[validation::name].as(); - species_node_pairs.emplace_back(component, obj); - } - - // Check for unknown species in reactants and products - std::vector unknown_species = FindUnknownObjectsByName(existing_species, species_node_pairs); - if (!unknown_species.empty()) - { - ReportUnknownSpecies(object, unknown_species, errors, ConfigParseStatus::ReactionRequiresUnknownSpecies); - } - - // Check for phase existence and get phase reference - auto phase_optional = CheckPhaseExists(object, validation::gas_phase, existing_phases, errors); - if (!phase_optional) - { - return errors; - } - - // Check if phase-specific species in reaction is found in phase - const auto& phase = phase_optional->get(); - CheckSpeciesPresenceInPhase(object, phase, species_node_pairs, errors); - - return errors; - } - - } // namespace development -} // namespace mechanism_configuration diff --git a/src/development/reactions/validators/troe.cpp b/src/development/reactions/validators/troe.cpp deleted file mode 100644 index 63cb588f..00000000 --- a/src/development/reactions/validators/troe.cpp +++ /dev/null @@ -1,102 +0,0 @@ -// Copyright (C) 2023–2026 University Corporation for Atmospheric Research -// University of Illinois at Urbana-Champaign -// SPDX-License-Identifier: Apache-2.0 - -#include -#include -#include -#include -#include -#include -#include - -namespace mechanism_configuration -{ - namespace development - { - /// @brief Validates a YAML-defined Troe reaction entry - /// Performs schema validation, ensures all referenced species and phases exist, - /// and collects any errors found. - /// @param object The YAML node representing the reaction - /// @param existing_species The list of known species used for validation - /// @param existing_phases The list of known phases used for validation - /// @return A list of validation errors, if any - Errors TroeParser::Validate( - const YAML::Node& object, - const std::vector& existing_species, - const std::vector& existing_phases) - { - std::vector required_keys = { - validation::reactants, validation::products, validation::type, validation::gas_phase - }; - std::vector optional_keys = { validation::name, validation::k0_A, validation::k0_B, - validation::k0_C, validation::kinf_A, validation::kinf_B, - validation::kinf_C, validation::Fc, validation::N }; - Errors errors; - - auto validation_errors = ValidateSchema(object, required_keys, optional_keys); - if (!validation_errors.empty()) - { - errors.insert(errors.end(), validation_errors.begin(), validation_errors.end()); - return errors; - } - - bool is_valid = true; - - // Reactants - validation_errors = ValidateReactantsOrProducts(object[validation::reactants]); - if (!validation_errors.empty()) - { - errors.insert(errors.end(), validation_errors.begin(), validation_errors.end()); - is_valid = false; - } - - // Products - validation_errors = ValidateReactantsOrProducts(object[validation::products]); - if (!validation_errors.empty()) - { - errors.insert(errors.end(), validation_errors.begin(), validation_errors.end()); - is_valid = false; - } - - if (!is_valid) - return errors; - - std::vector> species_node_pairs; - - for (const auto& obj : object[validation::reactants]) - { - types::ReactionComponent component; - component.name = obj[validation::name].as(); - species_node_pairs.emplace_back(component, obj); - } - for (const auto& obj : object[validation::products]) - { - types::ReactionComponent component; - component.name = obj[validation::name].as(); - species_node_pairs.emplace_back(component, obj); - } - - // Check for unknown species in reactants and products - std::vector unknown_species = FindUnknownObjectsByName(existing_species, species_node_pairs); - if (!unknown_species.empty()) - { - ReportUnknownSpecies(object, unknown_species, errors, ConfigParseStatus::ReactionRequiresUnknownSpecies); - } - - // Check for phase existence and get phase reference - auto phase_optional = CheckPhaseExists(object, validation::gas_phase, existing_phases, errors); - if (!phase_optional) - { - return errors; - } - - // Check if phase-specific species in reaction is found in phase - const auto& phase = phase_optional->get(); - CheckSpeciesPresenceInPhase(object, phase, species_node_pairs, errors); - - return errors; - } - - } // namespace development -} // namespace mechanism_configuration diff --git a/src/development/reactions/validators/tunneling.cpp b/src/development/reactions/validators/tunneling.cpp deleted file mode 100644 index c15f6bb7..00000000 --- a/src/development/reactions/validators/tunneling.cpp +++ /dev/null @@ -1,101 +0,0 @@ -// Copyright (C) 2023–2026 University Corporation for Atmospheric Research -// University of Illinois at Urbana-Champaign -// SPDX-License-Identifier: Apache-2.0 - -#include -#include -#include -#include -#include -#include -#include - -namespace mechanism_configuration -{ - namespace development - { - /// @brief Validates a YAML-defined Tunneling reaction entry - /// Performs schema validation, ensures all referenced species and phases exist, - /// and collects any errors found. - /// @param object The YAML node representing the reaction - /// @param existing_species The list of known species used for validation - /// @param existing_phases The list of known phases used for validation - /// @return A list of validation errors, if any - Errors TunnelingParser::Validate( - const YAML::Node& object, - const std::vector& existing_species, - const std::vector& existing_phases) - { - std::vector required_keys = { - validation::reactants, validation::products, validation::type, validation::gas_phase - }; - std::vector optional_keys = { validation::name, validation::A, validation::B, validation::C }; - - Errors errors; - - auto validation_errors = ValidateSchema(object, required_keys, optional_keys); - if (!validation_errors.empty()) - { - errors.insert(errors.end(), validation_errors.begin(), validation_errors.end()); - return errors; - } - - bool is_valid = true; - - // Reactants - validation_errors = ValidateReactantsOrProducts(object[validation::reactants]); - if (!validation_errors.empty()) - { - errors.insert(errors.end(), validation_errors.begin(), validation_errors.end()); - is_valid = false; - } - - // Products - validation_errors = ValidateReactantsOrProducts(object[validation::products]); - if (!validation_errors.empty()) - { - errors.insert(errors.end(), validation_errors.begin(), validation_errors.end()); - is_valid = false; - } - - if (!is_valid) - return errors; - - std::vector> species_node_pairs; - - for (const auto& obj : object[validation::reactants]) - { - types::ReactionComponent component; - component.name = obj[validation::name].as(); - species_node_pairs.emplace_back(component, obj); - } - for (const auto& obj : object[validation::products]) - { - types::ReactionComponent component; - component.name = obj[validation::name].as(); - species_node_pairs.emplace_back(component, obj); - } - - // Check for unknown species in reactants and products - std::vector unknown_species = FindUnknownObjectsByName(existing_species, species_node_pairs); - if (!unknown_species.empty()) - { - ReportUnknownSpecies(object, unknown_species, errors, ConfigParseStatus::ReactionRequiresUnknownSpecies); - } - - // Check for phase existence and get phase reference - auto phase_optional = CheckPhaseExists(object, validation::gas_phase, existing_phases, errors); - if (!phase_optional) - { - return errors; - } - - // Check if phase-specific species in reaction is found in phase - const auto& phase = phase_optional->get(); - CheckSpeciesPresenceInPhase(object, phase, species_node_pairs, errors); - - return errors; - } - - } // namespace development -} // namespace mechanism_configuration diff --git a/src/development/reactions/validators/user_defined.cpp b/src/development/reactions/validators/user_defined.cpp deleted file mode 100644 index 622c9238..00000000 --- a/src/development/reactions/validators/user_defined.cpp +++ /dev/null @@ -1,102 +0,0 @@ -// Copyright (C) 2023–2026 University Corporation for Atmospheric Research -// University of Illinois at Urbana-Champaign -// SPDX-License-Identifier: Apache-2.0 - -#include -#include -#include -#include -#include -#include -#include -#include - -namespace mechanism_configuration -{ - namespace development - { - /// @brief Validates a YAML-defined User-defined reaction entry - /// Performs schema validation, ensures all referenced species and phases exist, - /// and collects any errors found. - /// @param object The YAML node representing the reaction - /// @param existing_species The list of known species used for validation - /// @param existing_phases The list of known phases used for validation - /// @return A list of validation errors, if any - Errors UserDefinedParser::Validate( - const YAML::Node& object, - const std::vector& existing_species, - const std::vector& existing_phases) - { - std::vector required_keys = { - validation::reactants, validation::products, validation::type, validation::gas_phase - }; - std::vector optional_keys = { validation::name, validation::scaling_factor }; - - Errors errors; - - auto validation_errors = ValidateSchema(object, required_keys, optional_keys); - if (!validation_errors.empty()) - { - errors.insert(errors.end(), validation_errors.begin(), validation_errors.end()); - return errors; - } - - bool is_valid = true; - - // Reactants - validation_errors = ValidateReactantsOrProducts(object[validation::reactants]); - if (!validation_errors.empty()) - { - errors.insert(errors.end(), validation_errors.begin(), validation_errors.end()); - is_valid = false; - } - - // Products - validation_errors = ValidateReactantsOrProducts(object[validation::products]); - if (!validation_errors.empty()) - { - errors.insert(errors.end(), validation_errors.begin(), validation_errors.end()); - is_valid = false; - } - - if (!is_valid) - return errors; - - std::vector> species_node_pairs; - - for (const auto& obj : object[validation::reactants]) - { - types::ReactionComponent component; - component.name = obj[validation::name].as(); - species_node_pairs.emplace_back(component, obj); - } - for (const auto& obj : object[validation::products]) - { - types::ReactionComponent component; - component.name = obj[validation::name].as(); - species_node_pairs.emplace_back(component, obj); - } - - // Check for unknown species in reactants and products - std::vector unknown_species = FindUnknownObjectsByName(existing_species, species_node_pairs); - if (!unknown_species.empty()) - { - ReportUnknownSpecies(object, unknown_species, errors, ConfigParseStatus::ReactionRequiresUnknownSpecies); - } - - // Check for phase existence and get phase reference - auto phase_optional = CheckPhaseExists(object, validation::gas_phase, existing_phases, errors); - if (!phase_optional) - { - return errors; - } - - // Check if phase-specific species in reaction is found in phase - const auto& phase = phase_optional->get(); - CheckSpeciesPresenceInPhase(object, phase, species_node_pairs, errors); - - return errors; - } - - } // namespace development -} // namespace mechanism_configuration diff --git a/src/development/reactions/validators/wet_deposition.cpp b/src/development/reactions/validators/wet_deposition.cpp deleted file mode 100644 index fce3a603..00000000 --- a/src/development/reactions/validators/wet_deposition.cpp +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright (C) 2023–2026 University Corporation for Atmospheric Research -// University of Illinois at Urbana-Champaign -// SPDX-License-Identifier: Apache-2.0 - -#include -#include -#include -#include -#include -#include -#include -#include - -namespace mechanism_configuration -{ - namespace development - { - /// @brief Validates a YAML-defined Wet Deposition reaction entry. - /// Performs schema validation and ensures the referenced phase exists. - /// @param object The YAML node representing the reaction - /// @param existing_species The list of known species used for validation, not used - /// @param existing_phases The list of known phases used for validation - /// @return A list of validation errors, if any - Errors WetDepositionParser::Validate( - const YAML::Node& object, - const std::vector& existing_species, - const std::vector& existing_phases) - { - std::vector required_keys = { validation::condensed_phase, validation::type }; - std::vector optional_keys = { validation::name, validation::scaling_factor }; - - Errors errors; - - auto validation_errors = ValidateSchema(object, required_keys, optional_keys); - if (!validation_errors.empty()) - { - errors.insert(errors.end(), validation_errors.begin(), validation_errors.end()); - return errors; - } - - // Check for phase existence - auto phase_optional = CheckPhaseExists(object, validation::condensed_phase, existing_phases, errors); - if (!phase_optional) - { - return errors; - } - - return errors; - } - - } // namespace development -} // namespace mechanism_configuration \ No newline at end of file diff --git a/src/development/type_parsers.cpp b/src/development/type_parsers.cpp deleted file mode 100644 index 8da245df..00000000 --- a/src/development/type_parsers.cpp +++ /dev/null @@ -1,155 +0,0 @@ -// Copyright (C) 2023–2026 University Corporation for Atmospheric Research -// University of Illinois at Urbana-Champaign -// SPDX-License-Identifier: Apache-2.0 - -#include -#include -#include -#include -#include -#include - -namespace mechanism_configuration -{ - namespace development - { - std::vector ParseSpecies(const YAML::Node& objects) - { - std::vector all_species; - for (const auto& object : objects) - { - types::Species species; - - species.name = object[validation::name].as(); - - if (object[validation::tracer_type]) - species.tracer_type = object[validation::tracer_type].as(); - if (object[validation::absolute_tolerance]) - species.absolute_tolerance = object[validation::absolute_tolerance].as(); - if (object[validation::diffusion_coefficient]) - species.diffusion_coefficient = object[validation::diffusion_coefficient].as(); - if (object[validation::molecular_weight]) - species.molecular_weight = object[validation::molecular_weight].as(); - if (object[validation::henrys_law_constant_298]) - species.henrys_law_constant_298 = object[validation::henrys_law_constant_298].as(); - if (object[validation::henrys_law_constant_exponential_factor]) - species.henrys_law_constant_exponential_factor = - object[validation::henrys_law_constant_exponential_factor].as(); - if (object[validation::n_star]) - species.n_star = object[validation::n_star].as(); - if (object[validation::density]) - species.density = object[validation::density].as(); - if (object[validation::constant_concentration]) - species.constant_concentration = object[validation::constant_concentration].as(); - if (object[validation::constant_mixing_ratio]) - species.constant_mixing_ratio = object[validation::constant_mixing_ratio].as(); - if (object[validation::is_third_body]) - species.is_third_body = object[validation::is_third_body].as(); - - species.unknown_properties = GetComments(object); - - all_species.push_back(species); - } - return all_species; - } - - std::vector ParsePhases(const YAML::Node& objects) - { - std::vector all_phases; - for (const auto& object : objects) - { - types::Phase phase; - phase.name = object[validation::name].as(); - - std::vector species; - - for (const auto& spec : object[validation::species]) - { - types::PhaseSpecies phase_species; - - phase_species.name = spec[validation::name].as(); - if (spec[validation::diffusion_coefficient]) - { - phase_species.diffusion_coefficient = spec[validation::diffusion_coefficient].as(); - } - phase_species.unknown_properties = GetComments(spec); - - species.emplace_back(phase_species); - } - - phase.species = species; - phase.unknown_properties = GetComments(object); - all_phases.emplace_back(phase); - } - - return all_phases; - } - - std::vector ParseReactionComponents(const YAML::Node& object, const std::string& key) - { - std::vector component_list; - for (const auto& elem : AsSequence(object[key])) - { - types::ReactionComponent component; - component.name = elem[validation::name].as(); - component.unknown_properties = GetComments(elem); - - if (elem[validation::coefficient]) - { - component.coefficient = elem[validation::coefficient].as(); - } - - component_list.emplace_back(std::move(component)); - } - - return component_list; - }; - - types::ReactionComponent ParseReactionComponent(const YAML::Node& object, const std::string& key) - { - auto reaction_components = ParseReactionComponents(object, key); - - if (reaction_components.empty()) - { - return types::ReactionComponent(); - } - - return std::move(reaction_components.front()); - }; - - types::Reactions ParseReactions(const YAML::Node& objects) - { - auto& parsers = GetReactionParserMap(); - types::Reactions reactions; - - for (const auto& object : objects) - { - auto it = parsers.find(object[validation::type].as()); - if (it != parsers.end()) - { - it->second->Parse(object, reactions); - } - } - - return reactions; - } - - types::Models ParseModels(const YAML::Node& objects) - { - auto& parsers = GetModelParserMap(); - types::Models models; - - for (const auto& object : objects) - { - auto it = parsers.find(object[validation::type].as()); - if (it != parsers.end()) - { - it->second->Parse(object, models); - } - } - - return models; - } - - } // namespace development -} // namespace mechanism_configuration diff --git a/src/development/type_validators.cpp b/src/development/type_validators.cpp deleted file mode 100644 index 47104142..00000000 --- a/src/development/type_validators.cpp +++ /dev/null @@ -1,358 +0,0 @@ -// Copyright (C) 2023–2026 University Corporation for Atmospheric Research -// University of Illinois at Urbana-Champaign -// SPDX-License-Identifier: Apache-2.0 - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -namespace mechanism_configuration -{ - namespace development - { - Errors ValidateSpecies(const YAML::Node& species_list) - { - const std::vector required_keys = { validation::name }; - const std::vector optional_keys = { validation::absolute_tolerance, - validation::diffusion_coefficient, - validation::molecular_weight, - validation::henrys_law_constant_298, - validation::henrys_law_constant_exponential_factor, - validation::n_star, - validation::density, - validation::tracer_type, - validation::constant_concentration, - validation::constant_mixing_ratio, - validation::is_third_body }; - Errors errors; - bool is_valid = true; - - std::vector> species_node_pairs; - - for (const auto& object : species_list) - { - auto validation_errors = ValidateSchema(object, required_keys, optional_keys); - if (!validation_errors.empty()) - { - errors.insert(errors.end(), validation_errors.begin(), validation_errors.end()); - is_valid = false; - continue; - } - - // Get the name to check duplicate species - types::Species species; - species.name = object[validation::name].as(); - - species_node_pairs.emplace_back(species, object); - } - - if (!is_valid) - return errors; - - std::vector duplicates = FindDuplicateObjectsByName(species_node_pairs); - if (!duplicates.empty()) - { - for (const auto& duplicate : duplicates) - { - size_t total = duplicate.nodes.size(); - - for (size_t i = 0; i < total; ++i) - { - const auto& object = duplicate.nodes[i]; - ErrorLocation error_location{ object.Mark().line, object.Mark().column }; - - std::string message = mc_fmt::format( - "{} error: Duplicate species name '{}' found ({} of {}).", error_location, duplicate.name, i + 1, total); - - errors.push_back({ ConfigParseStatus::DuplicateSpeciesDetected, message }); - } - } - } - return errors; - } - - Errors ValidatePhases(const YAML::Node& phases_list, const std::vector& existing_species) - { - // Phase - const std::vector required_keys = { validation::name, validation::species }; - const std::vector optional_keys = {}; - // PhaseSpecies - const std::vector species_required_keys = { validation::name }; - const std::vector species_optional_keys = { validation::diffusion_coefficient }; - - Errors errors; - bool is_valid = true; - - std::vector> phase_node_pairs; - - for (const auto& object : AsSequence(phases_list)) - { - auto validation_errors = ValidateSchema(object, required_keys, optional_keys); - if (!validation_errors.empty()) - { - is_valid = false; - errors.insert(errors.end(), validation_errors.begin(), validation_errors.end()); - } - - for (const auto& spec : object[validation::species]) - { - auto species_validation_errors = ValidateSchema(spec, species_required_keys, species_optional_keys); - if (!species_validation_errors.empty()) - { - is_valid = false; - errors.insert(errors.end(), species_validation_errors.begin(), species_validation_errors.end()); - } - } - - if (!is_valid) - return errors; - - types::Phase phase; - phase.name = object[validation::name].as(); - - std::vector> species_node_pairs; - - for (const auto& spec : object[validation::species]) - { - types::PhaseSpecies phase_species; - phase_species.name = spec[validation::name].as(); - - if (spec[validation::diffusion_coefficient]) - phase_species.diffusion_coefficient = spec[validation::diffusion_coefficient].as(); - - species_node_pairs.emplace_back(phase_species, spec); - } - - // Check for duplicate species within this phase - std::vector duplicates = FindDuplicateObjectsByName(species_node_pairs); - if (!duplicates.empty()) - { - for (const auto& duplicate : duplicates) - { - size_t total = duplicate.nodes.size(); - - for (size_t i = 0; i < total; ++i) - { - const auto& duplicate_obj = duplicate.nodes[i]; - ErrorLocation error_location{ duplicate_obj.Mark().line, duplicate_obj.Mark().column }; - - std::string message = mc_fmt::format( - "{} error: Duplicate species name '{}' found ({} of {}).", error_location, duplicate.name, i + 1, total); - - errors.push_back({ ConfigParseStatus::DuplicateSpeciesInPhaseDetected, message }); - } - } - } - - // Check for unknown species within this phase - std::vector unknown_species = FindUnknownObjectsByName(existing_species, species_node_pairs); - if (!unknown_species.empty()) - { - for (const auto& [name, node] : unknown_species) - { - ErrorLocation error_location{ node.Mark().line, node.Mark().column }; - - std::string message = - mc_fmt::format("{} error: Unknown species name '{}' found in '{}' phase.", error_location, name, phase.name); - - errors.push_back({ ConfigParseStatus::PhaseRequiresUnknownSpecies, message }); - } - } - phase_node_pairs.emplace_back(phase, object); - } - - // Check for duplicate phase names - std::vector duplicates = FindDuplicateObjectsByName(phase_node_pairs); - if (!duplicates.empty()) - { - for (const auto& duplicate : duplicates) - { - size_t total = duplicate.nodes.size(); - - for (size_t i = 0; i < total; ++i) - { - const auto& duplicate_object = duplicate.nodes[i]; - ErrorLocation error_location{ duplicate_object.Mark().line, duplicate_object.Mark().column }; - - std::string message = mc_fmt::format( - "{} error: Duplicate phase name '{}' found ({} of {})", error_location, duplicate.name, i + 1, total); - - errors.push_back({ ConfigParseStatus::DuplicatePhasesDetected, message }); - } - } - } - return errors; - } - - Errors ValidateReactantsOrProducts(const YAML::Node& list) - { - const std::vector required_keys = { validation::name }; - const std::vector optional_keys = { validation::coefficient }; - - Errors errors; - - for (const auto& object : list) - { - auto validation_errors = ValidateSchema(object, required_keys, optional_keys); - if (!validation_errors.empty()) - { - errors.insert(errors.end(), validation_errors.begin(), validation_errors.end()); - } - } - - return errors; - } - - Errors ValidateParticles(const YAML::Node& list) - { - const std::vector required_keys = { validation::phase, validation::solutes, validation::solvent }; - const std::vector optional_keys = {}; - - Errors errors; - - for (const auto& object : AsSequence(list)) - { - auto validation_errors = ValidateSchema(object, required_keys, optional_keys); - if (!validation_errors.empty()) - { - errors.insert(errors.end(), validation_errors.begin(), validation_errors.end()); - } - - // Solutes - validation_errors = ValidateReactantsOrProducts(object[validation::solutes]); - if (!validation_errors.empty()) - { - errors.insert(errors.end(), validation_errors.begin(), validation_errors.end()); - } - - // Solvent - validation_errors = ValidateReactantsOrProducts(object[validation::solvent]); - if (!validation_errors.empty()) - { - errors.insert(errors.end(), validation_errors.begin(), validation_errors.end()); - } - } - - return errors; - } - - Errors ValidateReactions( - const YAML::Node& reactions_list, - const std::vector& existing_species, - const std::vector& existing_phases) - { - Errors errors; - bool is_valid = true; - - auto& parsers = GetReactionParserMap(); - - std::vector> valid_reactions; - - for (const auto& object : reactions_list) - { - if (!object[validation::type]) - { - ErrorLocation error_location{ object.Mark().line, object.Mark().column }; - std::string message = mc_fmt::format("{} error: Missing 'type' object in reaction.", error_location); - errors.push_back({ ConfigParseStatus::RequiredKeyNotFound, message }); - is_valid = false; - continue; - } - - std::string type = object[validation::type].as(); - - auto it = parsers.find(type); - if (it == parsers.end()) - { - const auto& node = object[validation::type]; - ErrorLocation error_location{ node.Mark().line, node.Mark().column }; - - std::string message = mc_fmt::format("{} error: Unknown reaction type '{}' found.", error_location, type); - - errors.push_back({ ConfigParseStatus::UnknownType, message }); - is_valid = false; - - continue; - } - valid_reactions.emplace_back(object, it->second.get()); - } - - if (!is_valid) - return errors; - - for (const auto& [reaction_node, parser] : valid_reactions) - { - auto validation_errors = parser->Validate(reaction_node, existing_species, existing_phases); - if (!validation_errors.empty()) - { - errors.insert(errors.end(), validation_errors.begin(), validation_errors.end()); - } - } - - return errors; - } - - Errors ValidateModels(const YAML::Node& models_list, const std::vector& existing_phases) - { - Errors errors; - bool is_valid = true; - - auto& parsers = GetModelParserMap(); - - std::vector> valid_models; - - for (const auto& object : models_list) - { - if (!object[validation::type]) - { - ErrorLocation error_location{ object.Mark().line, object.Mark().column }; - std::string message = mc_fmt::format("{} error: Missing 'type' object in model.", error_location); - errors.push_back({ ConfigParseStatus::RequiredKeyNotFound, message }); - is_valid = false; - continue; - } - - std::string type = object[validation::type].as(); - - auto it = parsers.find(type); - if (it == parsers.end()) - { - const auto& node = object[validation::type]; - ErrorLocation error_location{ node.Mark().line, node.Mark().column }; - - std::string message = mc_fmt::format("{} error: Unknown model type '{}' found.", error_location, type); - - errors.push_back({ ConfigParseStatus::UnknownType, message }); - is_valid = false; - - continue; - } - valid_models.emplace_back(object, it->second.get()); - } - - if (!is_valid) - return errors; - - for (const auto& [model_node, parser] : valid_models) - { - auto validation_errors = parser->Validate(model_node, existing_phases); - if (!validation_errors.empty()) - { - errors.insert(errors.end(), validation_errors.begin(), validation_errors.end()); - } - } - - return errors; - } - - } // namespace development -} // namespace mechanism_configuration \ No newline at end of file diff --git a/src/development/utils.cpp b/src/development/utils.cpp deleted file mode 100644 index 82d077b4..00000000 --- a/src/development/utils.cpp +++ /dev/null @@ -1,191 +0,0 @@ -// Copyright (C) 2023–2026 University Corporation for Atmospheric Research -// University of Illinois at Urbana-Champaign -// SPDX-License-Identifier: Apache-2.0 - -#include -#include -#include -#include -#include - -#include -#include -#include - -namespace mechanism_configuration -{ - namespace development - { - YAML::Node AsSequence(const YAML::Node& node) - { - if (node.IsSequence()) - return node; - - YAML::Node sequence; - sequence.push_back(node); - - return sequence; - } - - void AppendFilePath(const std::string& config_path, Errors& errors) - { - for (auto& error : errors) - { - error.second = config_path + ":" + error.second; - } - } - - std::unordered_map GetComments(const YAML::Node& object) - { - std::unordered_map unknown_properties; - const std::string comment_start = "__"; - - for (const auto& key : object) - { - std::string key_str = key.first.as(); - - // Check if the key starts with the comment prefix - if (key_str.compare(0, comment_start.size(), comment_start) == 0) - { - // Check if the value is a YAML node - if (key.second.IsScalar()) - { - unknown_properties[key_str] = key.second.as(); - } - else - { - std::stringstream ss; - ss << key.second; - unknown_properties[key_str] = ss.str(); - } - } - } - - // Return the map of extracted comments - return unknown_properties; - } - - std::vector GetSpeciesNames(const std::vector& phase_species) - { - std::vector names; - names.reserve(phase_species.size()); - for (const auto& species : phase_species) - { - names.push_back(species.name); - } - return names; - } - - void ReportUnknownSpecies( - const YAML::Node& object, - const std::vector& unknown_species, - Errors& errors, - const ConfigParseStatus& parser_status) - { - if (unknown_species.empty()) - return; - - for (const auto& [name, node] : unknown_species) - { - ErrorLocation error_location{ node.Mark().line, node.Mark().column }; - - std::string message = mc_fmt::format( - "{} error: Unknown species name '{}' found in '{}'.", - error_location, - name, - object[validation::type].as()); - - errors.push_back({ parser_status, message }); - } - } - - std::optional> CheckPhaseExists( - const YAML::Node& object, - const std::string& phase_key, - const std::vector& existing_phases, - Errors& errors, - const ConfigParseStatus& parser_status, - std::string type) - { - if (type.empty()) - { - if (object[validation::type]) - { - type = object[validation::type].as(); - } - else - { - type = "unknown type"; - } - } - - if (!object[phase_key]) - { - ErrorLocation error_location{ object.Mark().line, object.Mark().column }; - - std::string message = mc_fmt::format( - "{} error: Invalid phase key '{}'. This phase was not found in the object of type '{}'.", - error_location, - phase_key, - type); - - errors.push_back({ parser_status, message }); - return std::nullopt; - } - - const auto& phase_node = object[phase_key]; - std::string phase_name = phase_node.as(); - - auto it = std::find_if( - existing_phases.begin(), - existing_phases.end(), - [&phase_name](const auto& phase) { return phase.name == phase_name; }); - - if (it == existing_phases.end()) - { - ErrorLocation error_location{ phase_node.Mark().line, phase_node.Mark().column }; - - std::string message = - mc_fmt::format("{} error: Unknown phase name '{}' found in '{}'.", error_location, phase_name, type); - - errors.push_back({ parser_status, message }); - return std::nullopt; - } - - return std::cref(*it); - } - - void CheckSpeciesPresenceInPhase( - const YAML::Node& object, - const types::Phase& phase, - const std::vector>& species_node_pairs, - Errors& errors, - const ConfigParseStatus& parser_status) - { - std::unordered_set phase_species_set; - for (const auto& species : phase.species) - { - phase_species_set.insert(species.name); - } - - for (const auto& [component, node] : species_node_pairs) - { - if (phase_species_set.find(component.name) == phase_species_set.end()) - { - ErrorLocation error_location{ node.Mark().line, node.Mark().column }; - - std::string message = mc_fmt::format( - "{} error: {}-phase species '{}' is used in '{}' but is not defined in the '{}' phase.", - error_location, - phase.name, - component.name, - object[validation::type].as(), - phase.name); - - errors.push_back({ parser_status, message }); - } - } - } - - } // namespace development -} // namespace mechanism_configuration diff --git a/src/errors.cpp b/src/errors.cpp new file mode 100644 index 00000000..49875267 --- /dev/null +++ b/src/errors.cpp @@ -0,0 +1,40 @@ +// Copyright (C) 2023–2026 University Corporation for Atmospheric Research +// University of Illinois at Urbana-Champaign +// SPDX-License-Identifier: Apache-2.0 + +#include + +namespace mechanism_configuration +{ + std::string ErrorCodeToString(const ErrorCode& status) + { + switch (status) + { + case ErrorCode::Success: return "Success"; + case ErrorCode::None: return "None"; + case ErrorCode::InvalidKey: return "InvalidKey"; + case ErrorCode::UnknownKey: return "UnknownKey"; + case ErrorCode::InvalidFilePath: return "InvalidFilePath"; + case ErrorCode::ObjectTypeNotFound: return "ObjectTypeNotFound"; + case ErrorCode::RequiredKeyNotFound: return "RequiredKeyNotFound"; + case ErrorCode::MutuallyExclusiveOption: return "MutuallyExclusiveOption"; + case ErrorCode::DuplicateSpeciesDetected: return "DuplicateSpeciesDetected"; + case ErrorCode::DuplicatePhasesDetected: return "DuplicatePhasesDetected"; + case ErrorCode::DuplicateSpeciesInPhaseDetected: return "DuplicateSpeciesInPhaseDetected"; + case ErrorCode::PhaseRequiresUnknownSpecies: return "PhaseRequiresUnknownSpecies"; + case ErrorCode::ReactionRequiresUnknownSpecies: return "ReactionRequiresUnknownSpecies"; + case ErrorCode::UnknownSpecies: return "UnknownSpecies"; + case ErrorCode::UnknownPhase: return "UnknownPhase"; + case ErrorCode::RequestedSpeciesNotRegisteredInPhase: return "RequestedSpeciesNotRegisteredInPhase"; + case ErrorCode::TooManyReactionComponents: return "TooManyReactionComponents"; + case ErrorCode::InvalidVersion: return "InvalidVersion"; + case ErrorCode::MissingVersionField: return "MissingVersionField"; + case ErrorCode::InvalidType: return "InvalidType"; + case ErrorCode::UnknownType: return "UnknownType"; + case ErrorCode::FileNotFound: return "FileNotFound"; + case ErrorCode::UnexpectedError: return "UnexpectedError"; + case ErrorCode::EmptyObject: return "EmptyObject"; + default: return "Unknown"; + } + } +} // namespace mechanism_configuration \ No newline at end of file diff --git a/src/parse.cpp b/src/parse.cpp new file mode 100644 index 00000000..1da95e6d --- /dev/null +++ b/src/parse.cpp @@ -0,0 +1,93 @@ +// Copyright (C) 2023–2026 University Corporation for Atmospheric Research +// University of Illinois at Urbana-Champaign +// SPDX-License-Identifier: Apache-2.0 + +#include +#include +#include +#include + +#include "detail/v0/parser.hpp" +#include "detail/v1/parser.hpp" + +#include + +#include +#include +#include + +namespace mechanism_configuration +{ + // The detected version plus the source location of the `version` field, when the document + // had one (a directory or version-less document has no location). + struct DetectedVersion + { + Version version; + std::optional location; + }; + + std::expected GetVersion(const std::filesystem::path& config_path) + { + if (!std::filesystem::exists(config_path)) + { + return std::unexpected( + Errors{ { ErrorCode::FileNotFound, mc_fmt::format("Configuration file '{}' does not exist.", config_path.string()) } }); + } + + if (std::filesystem::exists(config_path) && std::filesystem::is_directory(config_path)) { + return DetectedVersion{ Version(0, 0, 0), std::nullopt }; + } + + YAML::Node object; + try + { + object = YAML::LoadFile(config_path.string()); + } + catch (const YAML::Exception& e) + { + return std::unexpected( + Errors{ { ErrorCode::UnexpectedError, mc_fmt::format("Failed to parse '{}': {}", config_path.string(), e.what()) } }); + } + + // The version field is version-agnostic (it's how we dispatch), so read it literally + // rather than depending on any version's key vocabulary. + if (!object["version"]) + { + // assume it's a v0 config + return DetectedVersion{ Version(0, 0, 0), std::nullopt }; + } + + const YAML::Node version_node = object["version"]; + return DetectedVersion{ Version(version_node.as()), + ErrorLocation{ version_node.Mark().line, version_node.Mark().column } }; + } + + std::expected Parse(const std::filesystem::path& config_path) + { + auto version = GetVersion(config_path); + + if (!version) + { + return std::unexpected(std::move(version.error())); + } + + switch (version->version.major) + { + case 0: + return v0::Parser{}.Parse(config_path); + case 1: + return v1::Parser{}.Parse(config_path); + default: + { + // We only reach here after reading the version out of config_path, so it names a real + // file and the version field has a location; point the error at it (path:line:col). + const std::string body = version->location + ? mc_fmt::format("{} error: Unsupported version number '{}'.", + *version->location, version->version.to_string()) + : mc_fmt::format("error: Unsupported version number '{}'.", version->version.to_string()); + return std::unexpected(Errors{ { ErrorCode::InvalidVersion, config_path.string() + ":" + body } }); + } + } + } + +} // namespace mechanism_configuration diff --git a/src/parse_status.cpp b/src/parse_status.cpp deleted file mode 100644 index 987dc451..00000000 --- a/src/parse_status.cpp +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright (C) 2023–2026 University Corporation for Atmospheric Research -// University of Illinois at Urbana-Champaign -// SPDX-License-Identifier: Apache-2.0 - -#include - -namespace mechanism_configuration -{ - std::string configParseStatusToString(const ConfigParseStatus& status) - { - switch (status) - { - case ConfigParseStatus::Success: return "Success"; - case ConfigParseStatus::None: return "None"; - case ConfigParseStatus::InvalidKey: return "InvalidKey"; - case ConfigParseStatus::UnknownKey: return "UnknownKey"; - case ConfigParseStatus::InvalidFilePath: return "InvalidFilePath"; - case ConfigParseStatus::ObjectTypeNotFound: return "ObjectTypeNotFound"; - case ConfigParseStatus::RequiredKeyNotFound: return "RequiredKeyNotFound"; - case ConfigParseStatus::MutuallyExclusiveOption: return "MutuallyExclusiveOption"; - case ConfigParseStatus::DuplicateSpeciesDetected: return "DuplicateSpeciesDetected"; - case ConfigParseStatus::DuplicatePhasesDetected: return "DuplicatePhasesDetected"; - case ConfigParseStatus::DuplicateSpeciesInPhaseDetected: return "DuplicateSpeciesInPhaseDetected"; - case ConfigParseStatus::PhaseRequiresUnknownSpecies: return "PhaseRequiresUnknownSpecies"; - case ConfigParseStatus::ReactionRequiresUnknownSpecies: return "ReactionRequiresUnknownSpecies"; - case ConfigParseStatus::UnknownSpecies: return "UnknownSpecies"; - case ConfigParseStatus::UnknownPhase: return "UnknownPhase"; - case ConfigParseStatus::RequestedSpeciesNotRegisteredInPhase: return "RequestedSpeciesNotRegisteredInPhase"; - case ConfigParseStatus::TooManyReactionComponents: return "TooManyReactionComponents"; - case ConfigParseStatus::InvalidIonPair: return "InvalidIonPair"; - case ConfigParseStatus::InvalidVersion: return "InvalidVersion"; - case ConfigParseStatus::MissingVersionField: return "MissingVersionField"; - case ConfigParseStatus::InvalidParameterNumber: return "InvalidParameterNumber"; - case ConfigParseStatus::InvalidType: return "InvalidType"; - case ConfigParseStatus::UnknownType: return "UnknownType"; - case ConfigParseStatus::FileNotFound: return "FileNotFound"; - case ConfigParseStatus::UnexpectedError: return "UnexpectedError"; - case ConfigParseStatus::EmptyObject: return "EmptyObject"; - default: return "Unknown"; - } - } -} // namespace mechanism_configuration \ No newline at end of file diff --git a/src/parser.cpp b/src/parser.cpp deleted file mode 100644 index e20f1bac..00000000 --- a/src/parser.cpp +++ /dev/null @@ -1,157 +0,0 @@ -// Copyright (C) 2023–2026 University Corporation for Atmospheric Research -// University of Illinois at Urbana-Champaign -// SPDX-License-Identifier: Apache-2.0 - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include - -namespace mechanism_configuration -{ - - VersionInfo UniversalParser::GetVersion(const std::filesystem::path& config_path) - { - VersionInfo info; - - if (!std::filesystem::exists(config_path)) - { - info.errors.push_back({ ConfigParseStatus::FileNotFound, - mc_fmt::format("Configuration file '{}' does not exist.", config_path.string()) }); - return info; - } - - YAML::Node object; - try - { - object = YAML::LoadFile(config_path.string()); - } - catch (const YAML::Exception& e) - { - info.errors.push_back({ ConfigParseStatus::UnexpectedError, - mc_fmt::format("Failed to parse '{}': {}", config_path.string(), e.what()) }); - return info; - } - - if (!object[development::validation::version]) - { - info.errors.push_back({ ConfigParseStatus::MissingVersionField, - mc_fmt::format("The version field was not found in '{}'.", config_path.string()) }); - return info; - } - - Version version = Version(object[development::validation::version].as()); - info.version = version.major; - - return info; - } - - ParserResult UniversalParser::Parse(const std::filesystem::path& config_path) - { - ParserResult result; - - // Check if the path is a directory - // If it's a directory, use the v0 parser without version checking - if (std::filesystem::exists(config_path) && std::filesystem::is_directory(config_path)) - { - v0::Parser v0_parser; - auto parser_result = v0_parser.Parse(config_path); - if (parser_result.errors.empty()) - { - result.mechanism = std::move(parser_result.mechanism); - } - else - { - result.errors.insert(result.errors.end(), parser_result.errors.begin(), parser_result.errors.end()); - } - return result; - } - - // For files, check the version - VersionInfo version_info = GetVersion(config_path); - if (!version_info.errors.empty()) - { - // If the version field is missing, the parser defaults to version 0. - // This approach is temporary and fragile, but is required to support - // the version 0 configurations. It can be removed once version 0 is fully - // deprecated or no longer supported. - for (auto& [status, message] : version_info.errors) - { - if (status == ConfigParseStatus::MissingVersionField) - { - v0::Parser v0_parser; - auto parser_result = v0_parser.Parse(config_path); - if (parser_result.errors.empty()) - { - result.mechanism = std::move(parser_result.mechanism); - } - else - { - result.errors.insert(result.errors.end(), parser_result.errors.begin(), parser_result.errors.end()); - } - return result; - } - } - result.errors.insert(result.errors.end(), version_info.errors.begin(), version_info.errors.end()); - - return result; - } - - constexpr unsigned int DEV_VERSION = 2; - constexpr unsigned int V1_VERSION = 1; - - if (version_info.version == DEV_VERSION) - { - development::Parser parser; - YAML::Node object = parser.FileToYaml(config_path); - auto validation_errors = parser.Validate(object); - if (validation_errors.empty()) - { - result.mechanism = std::make_unique(parser.Parse(object)); - } - else - { - result.errors.insert(result.errors.end(), validation_errors.begin(), validation_errors.end()); - } - return result; - } - else if (version_info.version == V1_VERSION) - { - v1::Parser v1_parser; - auto parser_result = v1_parser.Parse(config_path); - if (parser_result.errors.empty()) - { - result.mechanism = std::move(parser_result.mechanism); - } - else - { - result.errors.insert(result.errors.end(), parser_result.errors.begin(), parser_result.errors.end()); - } - return result; - } - else - { - std::string message = mc_fmt::format( - "error: The supported versions are '{}', '{}' but the invalid version number '{}' was found: '{}'.", - DEV_VERSION, - V1_VERSION, - version_info.version, - config_path.string()); - result.errors.push_back({ ConfigParseStatus::InvalidVersion, message }); - } - - return result; - } - -} // namespace mechanism_configuration \ No newline at end of file diff --git a/src/v0/arrhenius_parser.cpp b/src/v0/arrhenius_parser.cpp index 181dd09e..1cbc3528 100644 --- a/src/v0/arrhenius_parser.cpp +++ b/src/v0/arrhenius_parser.cpp @@ -1,84 +1,85 @@ -#include -#include -#include -#include -#include +// Copyright (C) 2023–2026 University Corporation for Atmospheric Research +// University of Illinois at Urbana-Champaign +// SPDX-License-Identifier: Apache-2.0 -namespace mechanism_configuration +#include "detail/conversions.hpp" +#include "detail/v0/parser.hpp" +#include "detail/v0/parser_types.hpp" +#include "detail/v0/keys.hpp" +#include "detail/check_schema.hpp" + +namespace mechanism_configuration::v0 { - namespace v0 + Errors ArrheniusParser(Mechanism& mechanism, const YAML::Node& object) { - Errors ArrheniusParser(std::unique_ptr& mechanism, const YAML::Node& object) - { - Errors errors; + Errors errors; - std::vector required = { validation::TYPE, validation::REACTANTS, validation::PRODUCTS }; - std::vector optional = { validation::A, validation::B, validation::C, validation::D, - validation::E, validation::Ea, validation::MUSICA_NAME }; + std::vector required = { keys::TYPE, keys::REACTANTS, keys::PRODUCTS }; + std::vector optional = { keys::A, keys::B, keys::C, keys::D, + keys::E, keys::Ea, keys::MUSICA_NAME }; - auto validate = ValidateSchema(object, required, optional); - errors.insert(errors.end(), validate.begin(), validate.end()); - if (validate.empty()) - { - std::vector reactants; - std::vector products; + auto validate = CheckSchema(object, required, optional); + errors.insert(errors.end(), validate.begin(), validate.end()); + if (validate.empty()) + { + std::vector reactants; + std::vector products; - auto parse_error = ParseReactants(object[validation::REACTANTS], reactants); - errors.insert(errors.end(), parse_error.begin(), parse_error.end()); + auto parse_error = ParseReactants(object[keys::REACTANTS], reactants); + errors.insert(errors.end(), parse_error.begin(), parse_error.end()); - parse_error = ParseProducts(object[validation::PRODUCTS], products); - errors.insert(errors.end(), parse_error.begin(), parse_error.end()); + parse_error = ParseProducts(object[keys::PRODUCTS], products); + errors.insert(errors.end(), parse_error.begin(), parse_error.end()); - types::Arrhenius parameters; - if (object[validation::A]) - { - parameters.A = object[validation::A].as(); - } - int total_moles = 0; - for (const auto& reactant : reactants) - { - total_moles += reactant.coefficient; - } - parameters.A *= std::pow(conversions::MolesM3ToMoleculesCm3, total_moles - 1); - if (object[validation::B]) - { - parameters.B = object[validation::B].as(); - } - if (object[validation::C]) - { - parameters.C = object[validation::C].as(); - } - if (object[validation::D]) - { - parameters.D = object[validation::D].as(); - } - if (object[validation::E]) + types::Arrhenius parameters; + if (object[keys::A]) + { + parameters.A = object[keys::A].as(); + } + int total_moles = 0; + for (const auto& reactant : reactants) + { + total_moles += reactant.coefficient; + } + parameters.A *= std::pow(conversions::MolesM3ToMoleculesCm3, total_moles - 1); + if (object[keys::B]) + { + parameters.B = object[keys::B].as(); + } + if (object[keys::C]) + { + parameters.C = object[keys::C].as(); + } + if (object[keys::D]) + { + parameters.D = object[keys::D].as(); + } + if (object[keys::E]) + { + parameters.E = object[keys::E].as(); + } + if (object[keys::Ea]) + { + if (parameters.C != 0) { - parameters.E = object[validation::E].as(); + std::string line = std::to_string(object[keys::Ea].Mark().line + 1); + std::string column = std::to_string(object[keys::Ea].Mark().column + 1); + errors.push_back( + { ErrorCode::MutuallyExclusiveOption, line + ":" + column + ": Cannot specify both 'C' and 'Ea'" }); } - if (object[validation::Ea]) + else { - if (parameters.C != 0) - { - std::string line = std::to_string(object[validation::Ea].Mark().line + 1); - std::string column = std::to_string(object[validation::Ea].Mark().column + 1); - errors.push_back( - { ConfigParseStatus::MutuallyExclusiveOption, line + ":" + column + ": Cannot specify both 'C' and 'Ea'" }); - } - else - { - // Calculate 'C' using 'Ea' - parameters.C = -1 * object[validation::Ea].as() / constants::boltzmann; - } + // Calculate 'C' using 'Ea' + parameters.C = -1 * object[keys::Ea].as() / constants::boltzmann; } - - parameters.reactants = reactants; - parameters.products = products; - - mechanism->reactions.arrhenius.push_back(parameters); } - return errors; + parameters.reactants = reactants; + parameters.products = products; + + mechanism.reactions.arrhenius.push_back(parameters); } - } // namespace v0 -} // namespace mechanism_configuration + + return errors; + } +} // namespace mechanism_configuration::v0 diff --git a/src/v0/branched_parser.cpp b/src/v0/branched_parser.cpp index 1a21061f..534dbca4 100644 --- a/src/v0/branched_parser.cpp +++ b/src/v0/branched_parser.cpp @@ -1,65 +1,66 @@ -#include -#include -#include -#include -#include -#include +// Copyright (C) 2023–2026 University Corporation for Atmospheric Research +// University of Illinois at Urbana-Champaign +// SPDX-License-Identifier: Apache-2.0 -namespace mechanism_configuration +#include "detail/constants.hpp" +#include "detail/conversions.hpp" +#include "detail/v0/parser.hpp" +#include "detail/v0/parser_types.hpp" +#include "detail/v0/keys.hpp" +#include "detail/check_schema.hpp" + +namespace mechanism_configuration::v0 { - namespace v0 + Errors BranchedParser(Mechanism& mechanism, const YAML::Node& object) { - Errors BranchedParser(std::unique_ptr& mechanism, const YAML::Node& object) - { - Errors errors; - - std::vector required = { validation::TYPE, - validation::REACTANTS, - validation::ALKOXY_PRODUCTS, - validation::NITRATE_PRODUCTS, - validation::X, - validation::Y, - validation::A0, - validation::n }; - - auto validate = ValidateSchema(object, required, {}); - errors.insert(errors.end(), validate.begin(), validate.end()); - if (validate.empty()) - { - std::vector reactants; - std::vector alkoxy_products; - std::vector nitrate_products; + Errors errors; - auto parse_error = ParseReactants(object[validation::REACTANTS], reactants); - errors.insert(errors.end(), parse_error.begin(), parse_error.end()); + std::vector required = { keys::TYPE, + keys::REACTANTS, + keys::ALKOXY_PRODUCTS, + keys::NITRATE_PRODUCTS, + keys::X, + keys::Y, + keys::A0, + keys::n }; - parse_error = ParseProducts(object[validation::ALKOXY_PRODUCTS], alkoxy_products); - errors.insert(errors.end(), parse_error.begin(), parse_error.end()); + auto validate = CheckSchema(object, required, {}); + errors.insert(errors.end(), validate.begin(), validate.end()); + if (validate.empty()) + { + std::vector reactants; + std::vector alkoxy_products; + std::vector nitrate_products; - parse_error = ParseProducts(object[validation::NITRATE_PRODUCTS], nitrate_products); - errors.insert(errors.end(), parse_error.begin(), parse_error.end()); + auto parse_error = ParseReactants(object[keys::REACTANTS], reactants); + errors.insert(errors.end(), parse_error.begin(), parse_error.end()); - types::Branched parameters; - parameters.X = object[validation::X].as(); - // Account for the conversion of reactant concentrations to molecules cm-3 - int total_moles = 0; - for (const auto& reactant : reactants) - { - total_moles += reactant.coefficient; - } - parameters.X *= std::pow(conversions::MolesM3ToMoleculesCm3, total_moles - 1); - parameters.Y = object[validation::Y].as(); - parameters.a0 = object[validation::A0].as(); - parameters.n = object[validation::n].as(); + parse_error = ParseProducts(object[keys::ALKOXY_PRODUCTS], alkoxy_products); + errors.insert(errors.end(), parse_error.begin(), parse_error.end()); - parameters.reactants = reactants; - parameters.alkoxy_products = alkoxy_products; - parameters.nitrate_products = nitrate_products; + parse_error = ParseProducts(object[keys::NITRATE_PRODUCTS], nitrate_products); + errors.insert(errors.end(), parse_error.begin(), parse_error.end()); - mechanism->reactions.branched.push_back(parameters); + types::Branched parameters; + parameters.X = object[keys::X].as(); + // Account for the conversion of reactant concentrations to molecules cm-3 + int total_moles = 0; + for (const auto& reactant : reactants) + { + total_moles += reactant.coefficient; } + parameters.X *= std::pow(conversions::MolesM3ToMoleculesCm3, total_moles - 1); + parameters.Y = object[keys::Y].as(); + parameters.a0 = object[keys::A0].as(); + parameters.n = object[keys::n].as(); - return errors; + parameters.reactants = reactants; + parameters.alkoxy_products = alkoxy_products; + parameters.nitrate_products = nitrate_products; + + mechanism.reactions.branched.push_back(parameters); } - } // namespace v0 -} // namespace mechanism_configuration + + return errors; + } +} // namespace mechanism_configuration::v0 diff --git a/src/v0/emission_parser.cpp b/src/v0/emission_parser.cpp index 9cd344a8..316aa304 100644 --- a/src/v0/emission_parser.cpp +++ b/src/v0/emission_parser.cpp @@ -1,39 +1,40 @@ -#include -#include -#include -#include -#include +// Copyright (C) 2023–2026 University Corporation for Atmospheric Research +// University of Illinois at Urbana-Champaign +// SPDX-License-Identifier: Apache-2.0 -namespace mechanism_configuration +#include "detail/constants.hpp" +#include "detail/v0/parser.hpp" +#include "detail/v0/parser_types.hpp" +#include "detail/v0/keys.hpp" +#include "detail/check_schema.hpp" + +namespace mechanism_configuration::v0 { - namespace v0 + Errors EmissionParser(Mechanism& mechanism, const YAML::Node& object) { - Errors EmissionParser(std::unique_ptr& mechanism, const YAML::Node& object) - { - Errors errors; - - std::vector required = { validation::TYPE, validation::SPECIES, validation::MUSICA_NAME }; - std::vector optional = { validation::SCALING_FACTOR, validation::PRODUCTS }; + Errors errors; - auto validate = ValidateSchema(object, required, optional); - errors.insert(errors.end(), validate.begin(), validate.end()); - if (validate.empty()) - { - std::string species = object[validation::SPECIES].as(); - YAML::Node products_object{}; - std::vector reactants; - std::vector products; - products.push_back({ .species_name = species, .coefficient = 1.0 }); - double scaling_factor = object[validation::SCALING_FACTOR] ? object[validation::SCALING_FACTOR].as() : 1.0; + std::vector required = { keys::TYPE, keys::SPECIES, keys::MUSICA_NAME }; + std::vector optional = { keys::SCALING_FACTOR, keys::PRODUCTS }; - std::string name = "EMIS." + object[validation::MUSICA_NAME].as(); - types::UserDefined user_defined = { - .scaling_factor = scaling_factor, .reactants = reactants, .products = products, .name = name - }; - mechanism->reactions.user_defined.push_back(user_defined); - } + auto validate = CheckSchema(object, required, optional); + errors.insert(errors.end(), validate.begin(), validate.end()); + if (validate.empty()) + { + std::string species = object[keys::SPECIES].as(); + YAML::Node products_object{}; + std::vector reactants; + std::vector products; + products.push_back({ .name = species, .coefficient = 1.0 }); + double scaling_factor = object[keys::SCALING_FACTOR] ? object[keys::SCALING_FACTOR].as() : 1.0; - return errors; + std::string name = "EMIS." + object[keys::MUSICA_NAME].as(); + types::UserDefined user_defined = { + .scaling_factor = scaling_factor, .reactants = reactants, .products = products, .name = name + }; + mechanism.reactions.user_defined.push_back(user_defined); } - } // namespace v0 -} // namespace mechanism_configuration + + return errors; + } +} // namespace mechanism_configuration::v0 diff --git a/src/v0/first_order_loss_parser.cpp b/src/v0/first_order_loss_parser.cpp index 1bb55831..00afb0cd 100644 --- a/src/v0/first_order_loss_parser.cpp +++ b/src/v0/first_order_loss_parser.cpp @@ -1,40 +1,41 @@ -#include -#include -#include -#include -#include +// Copyright (C) 2023–2026 University Corporation for Atmospheric Research +// University of Illinois at Urbana-Champaign +// SPDX-License-Identifier: Apache-2.0 -namespace mechanism_configuration +#include "detail/constants.hpp" +#include "detail/v0/parser.hpp" +#include "detail/v0/parser_types.hpp" +#include "detail/v0/keys.hpp" +#include "detail/check_schema.hpp" + +namespace mechanism_configuration::v0 { - namespace v0 + Errors FirstOrderLossParser(Mechanism& mechanism, const YAML::Node& object) { - Errors FirstOrderLossParser(std::unique_ptr& mechanism, const YAML::Node& object) - { - Errors errors; - - std::vector required = { validation::TYPE, validation::SPECIES, validation::MUSICA_NAME }; - std::vector optional = { validation::SCALING_FACTOR }; + Errors errors; - auto validate = ValidateSchema(object, required, optional); - errors.insert(errors.end(), validate.begin(), validate.end()); - if (validate.empty()) - { - std::string species = object[validation::SPECIES].as(); - YAML::Node products_object{}; - std::vector reactants; - std::vector products; + std::vector required = { keys::TYPE, keys::SPECIES, keys::MUSICA_NAME }; + std::vector optional = { keys::SCALING_FACTOR }; - reactants.push_back({ .species_name = species, .coefficient = 1.0 }); - double scaling_factor = object[validation::SCALING_FACTOR] ? object[validation::SCALING_FACTOR].as() : 1.0; + auto validate = CheckSchema(object, required, optional); + errors.insert(errors.end(), validate.begin(), validate.end()); + if (validate.empty()) + { + std::string species = object[keys::SPECIES].as(); + YAML::Node products_object{}; + std::vector reactants; + std::vector products; - std::string name = "LOSS." + object[validation::MUSICA_NAME].as(); - types::UserDefined user_defined = { - .scaling_factor = scaling_factor, .reactants = reactants, .products = products, .name = name - }; - mechanism->reactions.user_defined.push_back(user_defined); - } + reactants.push_back({ .name = species, .coefficient = 1.0 }); + double scaling_factor = object[keys::SCALING_FACTOR] ? object[keys::SCALING_FACTOR].as() : 1.0; - return errors; + std::string name = "LOSS." + object[keys::MUSICA_NAME].as(); + types::UserDefined user_defined = { + .scaling_factor = scaling_factor, .reactants = reactants, .products = products, .name = name + }; + mechanism.reactions.user_defined.push_back(user_defined); } - } // namespace v0 -} // namespace mechanism_configuration + + return errors; + } +} // namespace mechanism_configuration::v0 diff --git a/src/v0/parser.cpp b/src/v0/parser.cpp index 33e77c9c..659da655 100644 --- a/src/v0/parser.cpp +++ b/src/v0/parser.cpp @@ -1,141 +1,135 @@ -// Copyright (C) 2023-2024 National Center for Atmospheric Research, University of Illinois at Urbana-Champaign -// +// Copyright (C) 2023–2026 University Corporation for Atmospheric Research +// University of Illinois at Urbana-Champaign // SPDX-License-Identifier: Apache-2.0 -#include -#include -#include -#include -#include -#include +#include "detail/constants.hpp" +#include "detail/conversions.hpp" +#include "detail/v0/parser.hpp" +#include "detail/v0/parser_types.hpp" +#include "detail/v0/keys.hpp" +#include "detail/check_schema.hpp" #include #include -namespace mechanism_configuration +namespace mechanism_configuration::v0 { - namespace v0 - { - - using ParserMap = std::map&, const YAML::Node&)>>; + using ParserMap = std::map>; - Errors run_parsers(const ParserMap& parsers, std::unique_ptr& mechanism, const YAML::Node& object) + Errors run_parsers(const ParserMap& parsers, Mechanism& mechanism, const YAML::Node& object) + { + Errors errors; + for (const auto& element : object) { - Errors errors; - for (const auto& element : object) + std::string type = element[keys::TYPE].as(); + auto it = parsers.find(type); + if (it != parsers.end()) { - std::string type = element[validation::TYPE].as(); - auto it = parsers.find(type); - if (it != parsers.end()) - { - auto parse_errors = it->second(mechanism, element); - errors.insert(errors.end(), parse_errors.begin(), parse_errors.end()); - } - else - { - const std::string& msg = "Unknown type: " + type; - throw std::runtime_error(msg); - } + auto parse_errors = it->second(mechanism, element); + errors.insert(errors.end(), parse_errors.begin(), parse_errors.end()); + } + else + { + const std::string& msg = "Unknown type: " + type; + throw std::runtime_error(msg); } - return errors; } + return errors; + } + + Errors ParseMechanism(const ParserMap& parsers, Mechanism& mechanism, const YAML::Node& object) + { + std::vector required = { keys::NAME, keys::REACTIONS, keys::TYPE }; - Errors ParseMechanism(const ParserMap& parsers, std::unique_ptr& mechanism, const YAML::Node& object) + Errors errors; + auto validate = CheckSchema(object, required, {}); + errors.insert(errors.end(), validate.begin(), validate.end()); + if (validate.empty()) { - std::vector required = { validation::NAME, validation::REACTIONS, validation::TYPE }; + mechanism.name = object[keys::NAME].as(); + auto parse_errors = run_parsers(parsers, mechanism, object[keys::REACTIONS]); + errors.insert(errors.end(), parse_errors.begin(), parse_errors.end()); + } - Errors errors; - auto validate = ValidateSchema(object, required, {}); - errors.insert(errors.end(), validate.begin(), validate.end()); - if (validate.empty()) - { - mechanism->name = object[validation::NAME].as(); - auto parse_errors = run_parsers(parsers, mechanism, object[validation::REACTIONS]); - errors.insert(errors.end(), parse_errors.begin(), parse_errors.end()); - } + return errors; + } + Errors Parser::GetCampFiles(const std::filesystem::path& config_path, std::vector& camp_files) + { + Errors errors; + // Look for CAMP config path + if (!std::filesystem::exists(config_path)) + { + errors.push_back({ ErrorCode::FileNotFound, "File not found" }); return errors; } - Errors Parser::GetCampFiles(const std::filesystem::path& config_path, std::vector& camp_files) - { - Errors errors; - // Look for CAMP config path - if (!std::filesystem::exists(config_path)) - { - errors.push_back({ ConfigParseStatus::FileNotFound, "File not found" }); - return errors; - } - - std::filesystem::path config_dir; - std::filesystem::path config_file; + std::filesystem::path config_dir; + std::filesystem::path config_file; - if (std::filesystem::is_directory(config_path)) + if (std::filesystem::is_directory(config_path)) + { + // If config path is a directory, use default config file name + config_dir = config_path; + if (std::filesystem::exists(config_dir / DEFAULT_CONFIG_FILE_YAML)) { - // If config path is a directory, use default config file name - config_dir = config_path; - if (std::filesystem::exists(config_dir / DEFAULT_CONFIG_FILE_YAML)) - { - config_file = config_dir / DEFAULT_CONFIG_FILE_YAML; - } - else - { - config_file = config_dir / DEFAULT_CONFIG_FILE_JSON; - } + config_file = config_dir / DEFAULT_CONFIG_FILE_YAML; } else { - // Extract configuration dir from configuration file path - config_dir = config_path.parent_path(); - config_file = config_path; + config_file = config_dir / DEFAULT_CONFIG_FILE_JSON; } + } + else + { + // Extract configuration dir from configuration file path + config_dir = config_path.parent_path(); + config_file = config_path; + } + + // Load the CAMP file list YAML + YAML::Node camp_data = YAML::LoadFile(config_file.string()); + if (!camp_data[CAMP_FILES]) + { + std::string msg = "Required key not found: " + CAMP_FILES; + errors.push_back({ ErrorCode::RequiredKeyNotFound, msg }); + return errors; + } - // Load the CAMP file list YAML - YAML::Node camp_data = YAML::LoadFile(config_file.string()); - if (!camp_data[CAMP_FILES]) + // Build a list of individual CAMP config files + for (const auto& element : camp_data[CAMP_FILES]) + { + std::filesystem::path camp_file = config_dir / element.as(); + if (!std::filesystem::exists(camp_file)) { - std::string msg = "Required key not found: " + CAMP_FILES; - errors.push_back({ ConfigParseStatus::RequiredKeyNotFound, msg }); - return errors; + errors.push_back({ ErrorCode::FileNotFound, "File not found: " + camp_file.string() }); } - - // Build a list of individual CAMP config files - for (const auto& element : camp_data[CAMP_FILES]) + else { - std::filesystem::path camp_file = config_dir / element.as(); - if (!std::filesystem::exists(camp_file)) - { - errors.push_back({ ConfigParseStatus::FileNotFound, "File not found: " + camp_file.string() }); - } - else - { - camp_files.push_back(camp_file); - } + camp_files.push_back(camp_file); } - - return errors; } - ParserResult Parser::Parse(const std::filesystem::path& config_path) - { - ParserResult result; - result.mechanism = std::make_unique(); + return errors; + } - std::vector camp_files; - auto errors = GetCampFiles(config_path, camp_files); + std::expected Parser::Parse(const std::filesystem::path& config_path) + { + Errors errors; + auto mechanism = Mechanism(); - if (!errors.empty()) - { - result.errors = errors; - return result; - } + std::vector camp_files; + auto file_errors = GetCampFiles(config_path, camp_files); + errors.insert(errors.end(), file_errors.begin(), file_errors.end()); + // Only attempt to parse the mechanism if we were able to gather the CAMP files. + if (errors.empty()) + { ParserMap parsers; - std::function&, const YAML::Node&)> ParseMechanismArray = - [&](std::unique_ptr& mechanism, const YAML::Node& object) - { return ParseMechanism(parsers, mechanism, object); }; + std::function ParseMechanismArray = + [&](Mechanism& mechanism, const YAML::Node& object) { return ParseMechanism(parsers, mechanism, object); }; parsers["CHEM_SPEC"] = ParseChemicalSpecies; parsers["RELATIVE_TOLERANCE"] = ParseRelativeTolerance; @@ -155,28 +149,48 @@ namespace mechanism_configuration for (const auto& camp_file : camp_files) { - YAML::Node config_subset = YAML::LoadFile(camp_file.string()); - - auto parse_errors = run_parsers(parsers, result.mechanism, config_subset[CAMP_DATA]); - // prepend the file name to the error messages - for (auto& error : parse_errors) + // Parse each file independently so one malformed file does not abort the rest. + try { - error.second = camp_file.string() + ":" + error.second; + YAML::Node config_subset = YAML::LoadFile(camp_file.string()); + + auto parse_errors = run_parsers(parsers, mechanism, config_subset[CAMP_DATA]); + // prepend the file name to the error messages + for (auto& error : parse_errors) + { + error.second = camp_file.string() + ":" + error.second; + } + errors.insert(errors.end(), parse_errors.begin(), parse_errors.end()); + } + catch (const std::exception& e) + { + errors.push_back({ ErrorCode::UnexpectedError, camp_file.string() + ":" + e.what() }); } - result.errors.insert(result.errors.end(), parse_errors.begin(), parse_errors.end()); } // all species in version 0 are in the gas phase types::Phase gas_phase; gas_phase.name = "GAS"; - for (auto& species : result.mechanism->species) + for (auto& species : mechanism.species) { - gas_phase.species.push_back(species.name); + types::PhaseSpecies phase_species; + phase_species.name = species.name; + gas_phase.species.push_back(phase_species); } + mechanism.phases.push_back(gas_phase); - result.mechanism->version = Version(0, 0, 0); + mechanism.version = Version(0, 0, 0); + } - return result; + std::expected result; + if (!errors.empty()) + { + result = std::unexpected(std::move(errors)); + } + else + { + result = mechanism; } - } // namespace v0 -} // namespace mechanism_configuration \ No newline at end of file + return result; + } +} // namespace mechanism_configuration::v0 \ No newline at end of file diff --git a/src/v0/photolysis_parser.cpp b/src/v0/photolysis_parser.cpp index ec8c0c44..25fa81b5 100644 --- a/src/v0/photolysis_parser.cpp +++ b/src/v0/photolysis_parser.cpp @@ -1,45 +1,46 @@ -#include -#include -#include -#include -#include +// Copyright (C) 2023–2026 University Corporation for Atmospheric Research +// University of Illinois at Urbana-Champaign +// SPDX-License-Identifier: Apache-2.0 -namespace mechanism_configuration +#include "detail/constants.hpp" +#include "detail/v0/parser.hpp" +#include "detail/v0/parser_types.hpp" +#include "detail/v0/keys.hpp" +#include "detail/check_schema.hpp" + +namespace mechanism_configuration::v0 { - namespace v0 + Errors PhotolysisParser(Mechanism& mechanism, const YAML::Node& object) { - Errors PhotolysisParser(std::unique_ptr& mechanism, const YAML::Node& object) + Errors errors; + + std::vector required = { + keys::TYPE, keys::REACTANTS, keys::PRODUCTS, keys::MUSICA_NAME + }; + std::vector optional = { keys::SCALING_FACTOR }; + + auto validate = CheckSchema(object, required, optional); + errors.insert(errors.end(), validate.begin(), validate.end()); + if (validate.empty()) { - Errors errors; + std::vector reactants; + std::vector products; + + auto parse_error = ParseReactants(object[keys::REACTANTS], reactants); + errors.insert(errors.end(), parse_error.begin(), parse_error.end()); - std::vector required = { - validation::TYPE, validation::REACTANTS, validation::PRODUCTS, validation::MUSICA_NAME + parse_error = ParseProducts(object[keys::PRODUCTS], products); + errors.insert(errors.end(), parse_error.begin(), parse_error.end()); + + double scaling_factor = object[keys::SCALING_FACTOR] ? object[keys::SCALING_FACTOR].as() : 1.0; + + std::string name = "PHOTO." + object[keys::MUSICA_NAME].as(); + types::UserDefined user_defined = { + .scaling_factor = scaling_factor, .reactants = reactants, .products = products, .name = name }; - std::vector optional = { validation::SCALING_FACTOR }; - - auto validate = ValidateSchema(object, required, optional); - errors.insert(errors.end(), validate.begin(), validate.end()); - if (validate.empty()) - { - std::vector reactants; - std::vector products; - - auto parse_error = ParseReactants(object[validation::REACTANTS], reactants); - errors.insert(errors.end(), parse_error.begin(), parse_error.end()); - - parse_error = ParseProducts(object[validation::PRODUCTS], products); - errors.insert(errors.end(), parse_error.begin(), parse_error.end()); - - double scaling_factor = object[validation::SCALING_FACTOR] ? object[validation::SCALING_FACTOR].as() : 1.0; - - std::string name = "PHOTO." + object[validation::MUSICA_NAME].as(); - types::UserDefined user_defined = { - .scaling_factor = scaling_factor, .reactants = reactants, .products = products, .name = name - }; - mechanism->reactions.user_defined.push_back(user_defined); - } - - return errors; - } // namespace mechanism_configuration - } // namespace v0 -} // namespace mechanism_configuration + mechanism.reactions.user_defined.push_back(user_defined); + } + + return errors; + } +} // namespace mechanism_configuration::v0 diff --git a/src/v0/species_parser.cpp b/src/v0/species_parser.cpp index fcd37440..64069d6a 100644 --- a/src/v0/species_parser.cpp +++ b/src/v0/species_parser.cpp @@ -1,116 +1,117 @@ +// Copyright (C) 2023–2026 University Corporation for Atmospheric Research +// University of Illinois at Urbana-Champaign +// SPDX-License-Identifier: Apache-2.0 + #include -#include -#include -#include +#include "detail/v0/parser_types.hpp" +#include "detail/v0/keys.hpp" +#include "detail/check_schema.hpp" -namespace mechanism_configuration +namespace mechanism_configuration::v0 { - namespace v0 + Errors ParseChemicalSpecies(Mechanism& mechanism, const YAML::Node& object) { - Errors ParseChemicalSpecies(std::unique_ptr& mechanism, const YAML::Node& object) + Errors errors; + std::vector required = { keys::NAME, keys::TYPE }; + std::vector optional = { + keys::TRACER_TYPE, keys::ABS_TOLERANCE, keys::DIFFUSION_COEFF, keys::MOL_WEIGHT + }; + + auto validate = CheckSchema(object, required, optional); + errors.insert(errors.end(), validate.begin(), validate.end()); + if (validate.empty()) { - Errors errors; - std::vector required = { validation::NAME, validation::TYPE }; - std::vector optional = { - validation::TRACER_TYPE, validation::ABS_TOLERANCE, validation::DIFFUSION_COEFF, validation::MOL_WEIGHT - }; + std::string name = object[keys::NAME].as(); + types::Species species; + species.name = name; - auto validate = ValidateSchema(object, required, optional); - errors.insert(errors.end(), validate.begin(), validate.end()); - if (validate.empty()) - { - std::string name = object[validation::NAME].as(); - types::Species species; - species.name = name; + if (object[keys::MOL_WEIGHT]) + species.molecular_weight = object[keys::MOL_WEIGHT].as(); + if (object[keys::DIFFUSION_COEFF]) + species.diffusion_coefficient = object[keys::DIFFUSION_COEFF].as(); + if (object[keys::ABS_TOLERANCE]) + species.absolute_tolerance = object[keys::ABS_TOLERANCE].as(); + if (object[keys::TRACER_TYPE]) + species.tracer_type = object[keys::TRACER_TYPE].as(); - if (object[validation::MOL_WEIGHT]) - species.molecular_weight = object[validation::MOL_WEIGHT].as(); - if (object[validation::DIFFUSION_COEFF]) - species.diffusion_coefficient = object[validation::DIFFUSION_COEFF].as(); - if (object[validation::ABS_TOLERANCE]) - species.absolute_tolerance = object[validation::ABS_TOLERANCE].as(); - if (object[validation::TRACER_TYPE]) - species.tracer_type = object[validation::TRACER_TYPE].as(); + // Load remaining keys as unknown properties + for (auto it = object.begin(); it != object.end(); ++it) + { + auto key = it->first.as(); + auto value = it->second; - // Load remaining keys as unknown properties - for (auto it = object.begin(); it != object.end(); ++it) + if (std::find(required.begin(), required.end(), key) == required.end() && + std::find(optional.begin(), optional.end(), key) == optional.end()) { - auto key = it->first.as(); - auto value = it->second; - - if (std::find(required.begin(), required.end(), key) == required.end() && - std::find(optional.begin(), optional.end(), key) == optional.end()) - { - std::string stringValue = value.as(); - species.unknown_properties[key] = stringValue; - } + std::string stringValue = value.as(); + species.unknown_properties[key] = stringValue; } - mechanism->species.push_back(species); } + mechanism.species.push_back(species); + } + + return errors; + } - return errors; + Errors ParseRelativeTolerance(Mechanism& mechanism, const YAML::Node& object) + { + Errors errors; + std::vector required = { keys::VALUE, keys::TYPE }; + + auto validate = CheckSchema(object, required, {}); + errors.insert(errors.end(), validate.begin(), validate.end()); + if (validate.empty()) + { + mechanism.relative_tolerance = object[keys::VALUE].as(); } - Errors ParseRelativeTolerance(std::unique_ptr& mechanism, const YAML::Node& object) + return errors; + } + + Errors ParseReactants(const YAML::Node& object, std::vector& reactants) + { + Errors errors; + for (auto it = object.begin(); it != object.end(); ++it) { - Errors errors; - std::vector required = { validation::VALUE, validation::TYPE }; + auto key = it->first.as(); + auto value = it->second; - auto validate = ValidateSchema(object, required, {}); + auto validate = CheckSchema(value, {}, { keys::QTY }); errors.insert(errors.end(), validate.begin(), validate.end()); if (validate.empty()) { - mechanism->relative_tolerance = object[validation::VALUE].as(); + double qty = 1; + if (value[keys::QTY]) + qty = value[keys::QTY].as(); + types::ReactionComponent reactant = { .name = key, .coefficient = qty }; + reactants.push_back(reactant); } - - return errors; } - Errors ParseReactants(const YAML::Node& object, std::vector& reactants) - { - Errors errors; - for (auto it = object.begin(); it != object.end(); ++it) - { - auto key = it->first.as(); - auto value = it->second; - - auto validate = ValidateSchema(value, {}, { validation::QTY }); - errors.insert(errors.end(), validate.begin(), validate.end()); - if (validate.empty()) - { - double qty = 1; - if (value[validation::QTY]) - qty = value[validation::QTY].as(); - types::ReactionComponent reactant = { .species_name = key, .coefficient = qty }; - reactants.push_back(reactant); - } - } - - return errors; - } + return errors; + } - Errors ParseProducts(const YAML::Node& object, std::vector& products) + Errors ParseProducts(const YAML::Node& object, std::vector& products) + { + Errors errors; + for (auto it = object.begin(); it != object.end(); ++it) { - Errors errors; - for (auto it = object.begin(); it != object.end(); ++it) - { - auto key = it->first.as(); - auto value = it->second; + auto key = it->first.as(); + auto value = it->second; - auto validate = ValidateSchema(value, {}, { validation::YIELD }); - errors.insert(errors.end(), validate.begin(), validate.end()); - if (validate.empty()) + auto validate = CheckSchema(value, {}, { keys::YIELD }); + errors.insert(errors.end(), validate.begin(), validate.end()); + if (validate.empty()) + { + types::ReactionComponent product = { .name = key, .coefficient = 1 }; + if (value[keys::YIELD]) { - types::ReactionComponent product = { .species_name = key, .coefficient = 1 }; - if (value[validation::YIELD]) - { - double yield = value[validation::YIELD].as(); - product.coefficient = yield; - } - products.push_back(product); + double yield = value[keys::YIELD].as(); + product.coefficient = yield; } + products.push_back(product); } - return errors; } - } // namespace v0 -} // namespace mechanism_configuration \ No newline at end of file + return errors; + } +} // namespace mechanism_configuration::v0 \ No newline at end of file diff --git a/src/v0/surface_parser.cpp b/src/v0/surface_parser.cpp index 9a48802b..9e849668 100644 --- a/src/v0/surface_parser.cpp +++ b/src/v0/surface_parser.cpp @@ -1,51 +1,52 @@ -#include -#include -#include -#include -#include +// Copyright (C) 2023–2026 University Corporation for Atmospheric Research +// University of Illinois at Urbana-Champaign +// SPDX-License-Identifier: Apache-2.0 -namespace mechanism_configuration +#include "detail/constants.hpp" +#include "detail/v0/parser.hpp" +#include "detail/v0/parser_types.hpp" +#include "detail/v0/keys.hpp" +#include "detail/check_schema.hpp" + +namespace mechanism_configuration::v0 { - namespace v0 + Errors SurfaceParser(Mechanism& mechanism, const YAML::Node& object) { - Errors SurfaceParser(std::unique_ptr& mechanism, const YAML::Node& object) + Errors errors; + std::vector required = { + keys::TYPE, keys::GAS_PHASE_PRODUCTS, keys::GAS_PHASE_REACTANT, keys::MUSICA_NAME + }; + std::vector optional = { keys::PROBABILITY }; + + auto validate = CheckSchema(object, required, optional); + errors.insert(errors.end(), validate.begin(), validate.end()); + if (validate.empty()) { - Errors errors; - std::vector required = { - validation::TYPE, validation::GAS_PHASE_PRODUCTS, validation::GAS_PHASE_REACTANT, validation::MUSICA_NAME - }; - std::vector optional = { validation::PROBABILITY }; - - auto validate = ValidateSchema(object, required, optional); - errors.insert(errors.end(), validate.begin(), validate.end()); - if (validate.empty()) - { - std::vector reactants; - std::vector products; - - std::string species_name = object[validation::GAS_PHASE_REACTANT].as(); - reactants.push_back({ .species_name = species_name, .coefficient = 1.0 }); - - auto parse_error = ParseProducts(object[validation::GAS_PHASE_PRODUCTS], products); - errors.insert(errors.end(), parse_error.begin(), parse_error.end()); + std::vector reactants; + std::vector products; - types::Surface parameters; + std::string species_name = object[keys::GAS_PHASE_REACTANT].as(); + reactants.push_back({ .name = species_name, .coefficient = 1.0 }); - parameters.gas_phase_species = reactants[0]; - parameters.gas_phase_products = products; + auto parse_error = ParseProducts(object[keys::GAS_PHASE_PRODUCTS], products); + errors.insert(errors.end(), parse_error.begin(), parse_error.end()); - if (object[validation::PROBABILITY]) - { - parameters.reaction_probability = object[validation::PROBABILITY].as(); - } + types::Surface parameters; - std::string name = "SURF." + object[validation::MUSICA_NAME].as(); - parameters.name = name; + parameters.gas_phase_species = reactants[0]; + parameters.gas_phase_products = products; - mechanism->reactions.surface.push_back(parameters); + if (object[keys::PROBABILITY]) + { + parameters.reaction_probability = object[keys::PROBABILITY].as(); } - return errors; + std::string name = "SURF." + object[keys::MUSICA_NAME].as(); + parameters.name = name; + + mechanism.reactions.surface.push_back(parameters); } - } // namespace v0 -} // namespace mechanism_configuration + + return errors; + } +} // namespace mechanism_configuration::v0 diff --git a/src/v0/ternary_chemical_activation_parser.cpp b/src/v0/ternary_chemical_activation_parser.cpp index 92666ad3..08e68765 100644 --- a/src/v0/ternary_chemical_activation_parser.cpp +++ b/src/v0/ternary_chemical_activation_parser.cpp @@ -1,84 +1,85 @@ -#include -#include -#include -#include -#include -#include +// Copyright (C) 2023–2026 University Corporation for Atmospheric Research +// University of Illinois at Urbana-Champaign +// SPDX-License-Identifier: Apache-2.0 -namespace mechanism_configuration +#include "detail/constants.hpp" +#include "detail/conversions.hpp" +#include "detail/v0/parser.hpp" +#include "detail/v0/parser_types.hpp" +#include "detail/v0/keys.hpp" +#include "detail/check_schema.hpp" + +namespace mechanism_configuration::v0 { - namespace v0 + Errors TernaryChemicalActivationParser(Mechanism& mechanism, const YAML::Node& object) { - Errors TernaryChemicalActivationParser(std::unique_ptr& mechanism, const YAML::Node& object) - { - Errors errors; - - std::vector required = { validation::TYPE, validation::REACTANTS, validation::PRODUCTS }; - std::vector optional = { validation::K0_A, validation::K0_B, validation::K0_C, validation::KINF_A, - validation::KINF_B, validation::KINF_C, validation::FC, validation::N }; + Errors errors; - auto validate = ValidateSchema(object, required, optional); - errors.insert(errors.end(), validate.begin(), validate.end()); - if (validate.empty()) - { - std::vector reactants; - std::vector products; + std::vector required = { keys::TYPE, keys::REACTANTS, keys::PRODUCTS }; + std::vector optional = { keys::K0_A, keys::K0_B, keys::K0_C, keys::KINF_A, + keys::KINF_B, keys::KINF_C, keys::FC, keys::N }; - auto parse_error = ParseReactants(object[validation::REACTANTS], reactants); - errors.insert(errors.end(), parse_error.begin(), parse_error.end()); + auto validate = CheckSchema(object, required, optional); + errors.insert(errors.end(), validate.begin(), validate.end()); + if (validate.empty()) + { + std::vector reactants; + std::vector products; - parse_error = ParseProducts(object[validation::PRODUCTS], products); - errors.insert(errors.end(), parse_error.begin(), parse_error.end()); + auto parse_error = ParseReactants(object[keys::REACTANTS], reactants); + errors.insert(errors.end(), parse_error.begin(), parse_error.end()); - types::TernaryChemicalActivation parameters; - if (object[validation::K0_A]) - { - parameters.k0_A = object[validation::K0_A].as(); - } - // Account for the conversion of reactant concentrations (including M) to molecules cm-3 - int total_moles = 0; - for (const auto& reactant : reactants) - { - total_moles += reactant.coefficient; - } - parameters.k0_A *= std::pow(conversions::MolesM3ToMoleculesCm3, total_moles); - if (object[validation::K0_B]) - { - parameters.k0_B = object[validation::K0_B].as(); - } - if (object[validation::K0_C]) - { - parameters.k0_C = object[validation::K0_C].as(); - } - if (object[validation::KINF_A]) - { - parameters.kinf_A = object[validation::KINF_A].as(); - } - // Account for terms in denominator and exponent that include [M] but not other reactants - parameters.kinf_A *= std::pow(conversions::MolesM3ToMoleculesCm3, total_moles - 1); - if (object[validation::KINF_B]) - { - parameters.kinf_B = object[validation::KINF_B].as(); - } - if (object[validation::KINF_C]) - { - parameters.kinf_C = object[validation::KINF_C].as(); - } - if (object[validation::FC]) - { - parameters.Fc = object[validation::FC].as(); - } - if (object[validation::N]) - { - parameters.N = object[validation::N].as(); - } + parse_error = ParseProducts(object[keys::PRODUCTS], products); + errors.insert(errors.end(), parse_error.begin(), parse_error.end()); - parameters.reactants = reactants; - parameters.products = products; - mechanism->reactions.ternary_chemical_activation.push_back(parameters); + types::TernaryChemicalActivation parameters; + if (object[keys::K0_A]) + { + parameters.k0_A = object[keys::K0_A].as(); + } + // Account for the conversion of reactant concentrations (including M) to molecules cm-3 + int total_moles = 0; + for (const auto& reactant : reactants) + { + total_moles += reactant.coefficient; + } + parameters.k0_A *= std::pow(conversions::MolesM3ToMoleculesCm3, total_moles); + if (object[keys::K0_B]) + { + parameters.k0_B = object[keys::K0_B].as(); + } + if (object[keys::K0_C]) + { + parameters.k0_C = object[keys::K0_C].as(); + } + if (object[keys::KINF_A]) + { + parameters.kinf_A = object[keys::KINF_A].as(); + } + // Account for terms in denominator and exponent that include [M] but not other reactants + parameters.kinf_A *= std::pow(conversions::MolesM3ToMoleculesCm3, total_moles - 1); + if (object[keys::KINF_B]) + { + parameters.kinf_B = object[keys::KINF_B].as(); + } + if (object[keys::KINF_C]) + { + parameters.kinf_C = object[keys::KINF_C].as(); + } + if (object[keys::FC]) + { + parameters.Fc = object[keys::FC].as(); + } + if (object[keys::N]) + { + parameters.N = object[keys::N].as(); } - return errors; + parameters.reactants = reactants; + parameters.products = products; + mechanism.reactions.ternary_chemical_activation.push_back(parameters); } - } // namespace v0 -} // namespace mechanism_configuration + + return errors; + } +} // namespace mechanism_configuration::v0 diff --git a/src/v0/troe_parser.cpp b/src/v0/troe_parser.cpp index b5f90747..01111a73 100644 --- a/src/v0/troe_parser.cpp +++ b/src/v0/troe_parser.cpp @@ -1,84 +1,85 @@ -#include -#include -#include -#include -#include -#include +// Copyright (C) 2023–2026 University Corporation for Atmospheric Research +// University of Illinois at Urbana-Champaign +// SPDX-License-Identifier: Apache-2.0 -namespace mechanism_configuration +#include "detail/constants.hpp" +#include "detail/conversions.hpp" +#include "detail/v0/parser.hpp" +#include "detail/v0/parser_types.hpp" +#include "detail/v0/keys.hpp" +#include "detail/check_schema.hpp" + +namespace mechanism_configuration::v0 { - namespace v0 + Errors TroeParser(Mechanism& mechanism, const YAML::Node& object) { - Errors TroeParser(std::unique_ptr& mechanism, const YAML::Node& object) - { - Errors errors; - - std::vector required = { validation::TYPE, validation::REACTANTS, validation::PRODUCTS }; - std::vector optional = { validation::K0_A, validation::K0_B, validation::K0_C, validation::KINF_A, - validation::KINF_B, validation::KINF_C, validation::FC, validation::N }; + Errors errors; - auto validate = ValidateSchema(object, required, optional); - errors.insert(errors.end(), validate.begin(), validate.end()); - if (validate.empty()) - { - std::vector reactants; - std::vector products; + std::vector required = { keys::TYPE, keys::REACTANTS, keys::PRODUCTS }; + std::vector optional = { keys::K0_A, keys::K0_B, keys::K0_C, keys::KINF_A, + keys::KINF_B, keys::KINF_C, keys::FC, keys::N }; - auto parse_error = ParseReactants(object[validation::REACTANTS], reactants); - errors.insert(errors.end(), parse_error.begin(), parse_error.end()); + auto validate = CheckSchema(object, required, optional); + errors.insert(errors.end(), validate.begin(), validate.end()); + if (validate.empty()) + { + std::vector reactants; + std::vector products; - parse_error = ParseProducts(object[validation::PRODUCTS], products); - errors.insert(errors.end(), parse_error.begin(), parse_error.end()); + auto parse_error = ParseReactants(object[keys::REACTANTS], reactants); + errors.insert(errors.end(), parse_error.begin(), parse_error.end()); - types::Troe parameters; - if (object[validation::K0_A]) - { - parameters.k0_A = object[validation::K0_A].as(); - } - // Account for the conversion of reactant concentrations (including M) to molecules cm-3 - int total_moles = 0; - for (const auto& reactant : reactants) - { - total_moles += reactant.coefficient; - } - parameters.k0_A *= std::pow(conversions::MolesM3ToMoleculesCm3, total_moles); - if (object[validation::K0_B]) - { - parameters.k0_B = object[validation::K0_B].as(); - } - if (object[validation::K0_C]) - { - parameters.k0_C = object[validation::K0_C].as(); - } - if (object[validation::KINF_A]) - { - parameters.kinf_A = object[validation::KINF_A].as(); - } - // Account for terms in denominator and exponent that include [M] but not other reactants - parameters.kinf_A *= std::pow(conversions::MolesM3ToMoleculesCm3, total_moles - 1); - if (object[validation::KINF_B]) - { - parameters.kinf_B = object[validation::KINF_B].as(); - } - if (object[validation::KINF_C]) - { - parameters.kinf_C = object[validation::KINF_C].as(); - } - if (object[validation::FC]) - { - parameters.Fc = object[validation::FC].as(); - } - if (object[validation::N]) - { - parameters.N = object[validation::N].as(); - } + parse_error = ParseProducts(object[keys::PRODUCTS], products); + errors.insert(errors.end(), parse_error.begin(), parse_error.end()); - parameters.reactants = reactants; - parameters.products = products; - mechanism->reactions.troe.push_back(parameters); + types::Troe parameters; + if (object[keys::K0_A]) + { + parameters.k0_A = object[keys::K0_A].as(); + } + // Account for the conversion of reactant concentrations (including M) to molecules cm-3 + int total_moles = 0; + for (const auto& reactant : reactants) + { + total_moles += reactant.coefficient; + } + parameters.k0_A *= std::pow(conversions::MolesM3ToMoleculesCm3, total_moles); + if (object[keys::K0_B]) + { + parameters.k0_B = object[keys::K0_B].as(); + } + if (object[keys::K0_C]) + { + parameters.k0_C = object[keys::K0_C].as(); + } + if (object[keys::KINF_A]) + { + parameters.kinf_A = object[keys::KINF_A].as(); + } + // Account for terms in denominator and exponent that include [M] but not other reactants + parameters.kinf_A *= std::pow(conversions::MolesM3ToMoleculesCm3, total_moles - 1); + if (object[keys::KINF_B]) + { + parameters.kinf_B = object[keys::KINF_B].as(); + } + if (object[keys::KINF_C]) + { + parameters.kinf_C = object[keys::KINF_C].as(); + } + if (object[keys::FC]) + { + parameters.Fc = object[keys::FC].as(); + } + if (object[keys::N]) + { + parameters.N = object[keys::N].as(); } - return errors; + parameters.reactants = reactants; + parameters.products = products; + mechanism.reactions.troe.push_back(parameters); } - } // namespace v0 -} // namespace mechanism_configuration + + return errors; + } +} // namespace mechanism_configuration::v0 diff --git a/src/v0/tunneling_parser.cpp b/src/v0/tunneling_parser.cpp index af463fb8..04b5182f 100644 --- a/src/v0/tunneling_parser.cpp +++ b/src/v0/tunneling_parser.cpp @@ -1,60 +1,61 @@ -#include -#include -#include -#include -#include +// Copyright (C) 2023–2026 University Corporation for Atmospheric Research +// University of Illinois at Urbana-Champaign +// SPDX-License-Identifier: Apache-2.0 -namespace mechanism_configuration +#include "detail/conversions.hpp" +#include "detail/v0/parser.hpp" +#include "detail/v0/parser_types.hpp" +#include "detail/v0/keys.hpp" +#include "detail/check_schema.hpp" + +namespace mechanism_configuration::v0 { - namespace v0 + Errors TunnelingParser(Mechanism& mechanism, const YAML::Node& object) { - Errors TunnelingParser(std::unique_ptr& mechanism, const YAML::Node& object) + Errors errors; + + std::vector required = { keys::TYPE, keys::REACTANTS, keys::PRODUCTS }; + std::vector optional = { keys::A, keys::B, keys::C }; + + auto validate = CheckSchema(object, required, optional); + errors.insert(errors.end(), validate.begin(), validate.end()); + if (validate.empty()) { - Errors errors; + std::vector reactants; + std::vector products; - std::vector required = { validation::TYPE, validation::REACTANTS, validation::PRODUCTS }; - std::vector optional = { validation::A, validation::B, validation::C }; + auto parse_error = ParseReactants(object[keys::REACTANTS], reactants); + errors.insert(errors.end(), parse_error.begin(), parse_error.end()); - auto validate = ValidateSchema(object, required, optional); - errors.insert(errors.end(), validate.begin(), validate.end()); - if (validate.empty()) + parse_error = ParseProducts(object[keys::PRODUCTS], products); + errors.insert(errors.end(), parse_error.begin(), parse_error.end()); + + types::Tunneling parameters; + if (object[keys::A]) + { + parameters.A = object[keys::A].as(); + } + // Account for the conversion of reactant concentrations to molecules cm-3 + int total_moles = 0; + for (auto& reactant : reactants) { - std::vector reactants; - std::vector products; - - auto parse_error = ParseReactants(object[validation::REACTANTS], reactants); - errors.insert(errors.end(), parse_error.begin(), parse_error.end()); - - parse_error = ParseProducts(object[validation::PRODUCTS], products); - errors.insert(errors.end(), parse_error.begin(), parse_error.end()); - - types::Tunneling parameters; - if (object[validation::A]) - { - parameters.A = object[validation::A].as(); - } - // Account for the conversion of reactant concentrations to molecules cm-3 - int total_moles = 0; - for (auto& reactant : reactants) - { - total_moles += reactant.coefficient; - } - parameters.A *= std::pow(conversions::MolesM3ToMoleculesCm3, total_moles - 1); - if (object[validation::B]) - { - parameters.B = object[validation::B].as(); - } - if (object[validation::C]) - { - parameters.C = object[validation::C].as(); - } - - parameters.reactants = reactants; - parameters.products = products; - mechanism->reactions.tunneling.push_back(parameters); + total_moles += reactant.coefficient; + } + parameters.A *= std::pow(conversions::MolesM3ToMoleculesCm3, total_moles - 1); + if (object[keys::B]) + { + parameters.B = object[keys::B].as(); + } + if (object[keys::C]) + { + parameters.C = object[keys::C].as(); } - return errors; + parameters.reactants = reactants; + parameters.products = products; + mechanism.reactions.tunneling.push_back(parameters); } - } // namespace v0 -} // namespace mechanism_configuration + + return errors; + } +} // namespace mechanism_configuration::v0 diff --git a/src/v0/user_defined_reaction_parser.cpp b/src/v0/user_defined_reaction_parser.cpp index 31316c28..f99654d8 100644 --- a/src/v0/user_defined_reaction_parser.cpp +++ b/src/v0/user_defined_reaction_parser.cpp @@ -1,46 +1,47 @@ -#include -#include -#include -#include -#include +// Copyright (C) 2023–2026 University Corporation for Atmospheric Research +// University of Illinois at Urbana-Champaign +// SPDX-License-Identifier: Apache-2.0 -namespace mechanism_configuration +#include "detail/constants.hpp" +#include "detail/v0/parser.hpp" +#include "detail/v0/parser_types.hpp" +#include "detail/v0/keys.hpp" +#include "detail/check_schema.hpp" + +namespace mechanism_configuration::v0 { - namespace v0 + Errors UserDefinedParser(Mechanism& mechanism, const YAML::Node& object) { - Errors UserDefinedParser(std::unique_ptr& mechanism, const YAML::Node& object) - { - Errors errors; - - std::vector required = { - validation::TYPE, validation::REACTANTS, validation::PRODUCTS, validation::MUSICA_NAME - }; - std::vector optional = { validation::SCALING_FACTOR }; + Errors errors; - auto validate = ValidateSchema(object, required, optional); - errors.insert(errors.end(), validate.begin(), validate.end()); - if (validate.empty()) - { - std::vector reactants; - std::vector products; + std::vector required = { + keys::TYPE, keys::REACTANTS, keys::PRODUCTS, keys::MUSICA_NAME + }; + std::vector optional = { keys::SCALING_FACTOR }; - auto parse_error = ParseReactants(object[validation::REACTANTS], reactants); - errors.insert(errors.end(), parse_error.begin(), parse_error.end()); + auto validate = CheckSchema(object, required, optional); + errors.insert(errors.end(), validate.begin(), validate.end()); + if (validate.empty()) + { + std::vector reactants; + std::vector products; - parse_error = ParseProducts(object[validation::PRODUCTS], products); - errors.insert(errors.end(), parse_error.begin(), parse_error.end()); + auto parse_error = ParseReactants(object[keys::REACTANTS], reactants); + errors.insert(errors.end(), parse_error.begin(), parse_error.end()); - double scaling_factor = object[validation::SCALING_FACTOR] ? object[validation::SCALING_FACTOR].as() : 1.0; + parse_error = ParseProducts(object[keys::PRODUCTS], products); + errors.insert(errors.end(), parse_error.begin(), parse_error.end()); - std::string name = "USER." + object[validation::MUSICA_NAME].as(); + double scaling_factor = object[keys::SCALING_FACTOR] ? object[keys::SCALING_FACTOR].as() : 1.0; - types::UserDefined user_defined = { - .scaling_factor = scaling_factor, .reactants = reactants, .products = products, .name = name - }; - mechanism->reactions.user_defined.push_back(user_defined); - } + std::string name = "USER." + object[keys::MUSICA_NAME].as(); - return errors; + types::UserDefined user_defined = { + .scaling_factor = scaling_factor, .reactants = reactants, .products = products, .name = name + }; + mechanism.reactions.user_defined.push_back(user_defined); } - } // namespace v0 -} // namespace mechanism_configuration + + return errors; + } +} // namespace mechanism_configuration::v0 diff --git a/src/v1/CMakeLists.txt b/src/v1/CMakeLists.txt index ab40316b..d752c785 100644 --- a/src/v1/CMakeLists.txt +++ b/src/v1/CMakeLists.txt @@ -1,7 +1,8 @@ target_sources(mechanism_configuration PRIVATE parser.cpp - mechanism_parsers.cpp + type_parsers.cpp + type_schema.cpp utils.cpp ) diff --git a/src/v1/mechanism_parsers.cpp b/src/v1/mechanism_parsers.cpp deleted file mode 100644 index d04b22ee..00000000 --- a/src/v1/mechanism_parsers.cpp +++ /dev/null @@ -1,312 +0,0 @@ -// Copyright (C) 2023–2026 University Corporation for Atmospheric Research -// University of Illinois at Urbana-Champaign -// SPDX-License-Identifier: Apache-2.0 - -#include -#include -#include -#include -#include - -#include - -namespace -{ - std::string FormatYamlError(const YAML::Node& node, const std::string& message) - { - std::string line = std::to_string(node.Mark().line + 1); - std::string column = std::to_string(node.Mark().column + 1); - std::ostringstream oss; - oss << line << ":" << column << message; - return oss.str(); - } -} // namespace - -namespace mechanism_configuration -{ - namespace v1 - { - std::pair> ParseSpecies(const YAML::Node& objects) - - { - Errors errors; - std::vector all_species; - std::vector> species_node_pairs; - - for (const auto& object : objects) - { - types::Species species; - std::vector required_keys = { validation::name }; - std::vector optional_keys = { validation::molecular_weight, - validation::constant_concentration, - validation::constant_mixing_ratio, - validation::is_third_body }; - auto validate = ValidateSchema(object, required_keys, optional_keys); - errors.insert(errors.end(), validate.begin(), validate.end()); - if (validate.empty()) - { - std::string name = object[validation::name].as(); - species.name = name; - - if (object[validation::molecular_weight]) - species.molecular_weight = object[validation::molecular_weight].as(); - if (object[validation::constant_concentration]) - species.constant_concentration = object[validation::constant_concentration].as(); - if (object[validation::constant_mixing_ratio]) - species.constant_mixing_ratio = object[validation::constant_mixing_ratio].as(); - if (object[validation::is_third_body]) - species.is_third_body = object[validation::is_third_body].as(); - - species.unknown_properties = GetComments(object); - - all_species.push_back(species); - species_node_pairs.push_back({ species, object }); - } - } - - std::vector duplicates = FindDuplicateObjectsByName(species_node_pairs); - if (!duplicates.empty()) - { - for (const auto& duplicate : duplicates) - { - size_t total = duplicate.nodes.size(); - - for (size_t i = 0; i < total; ++i) - { - const auto& object = duplicate.nodes[i]; - std::string line = std::to_string(object.Mark().line + 1); - std::string column = std::to_string(object.Mark().column + 1); - - std::ostringstream oss; - oss << line << ":" << column << " error: Duplicate species name '" << duplicate.name << "' found (" << (i + 1) - << " of " << total << ")"; - - errors.push_back({ ConfigParseStatus::DuplicateSpeciesDetected, oss.str() }); - } - } - } - - return { errors, all_species }; - } - - std::pair> ParsePhases( - const YAML::Node& objects, - const std::vector existing_species) - { - Errors errors; - std::vector all_phases; - std::vector> phase_node_pairs; - - const std::vector phase_required_keys = { validation::name, validation::species }; - const std::vector phase_optional_keys = {}; - - for (const auto& object : objects) - { - types::Phase phase; - auto validate = ValidateSchema(object, phase_required_keys, phase_optional_keys); - errors.insert(errors.end(), validate.begin(), validate.end()); - if (validate.empty()) - { - std::string name = object[validation::name].as(); - - std::vector species{}; - for (const auto& spec : object[validation::species]) - { - types::PhaseSpecies phase_species; - if (spec.IsScalar()) - { - // Simple string species name - phase_species.name = spec.as(); - } - else if (spec.IsMap()) - { - // Complex species with properties - if (!spec[validation::name]) - { - errors.push_back({ ConfigParseStatus::RequiredKeyNotFound, - FormatYamlError(spec, "Species object missing required 'name' field") }); - continue; - } - - phase_species.name = spec[validation::name].as(); - - // Parse standard properties - if (spec[validation::diffusion_coefficient]) - phase_species.diffusion_coefficient = spec[validation::diffusion_coefficient].as(); - - // Parse custom properties (those starting with __) - phase_species.unknown_properties = GetComments(spec); - } - else - { - errors.push_back( - { ConfigParseStatus::InvalidKey, - FormatYamlError(spec, "Species must be either a string name or an object with properties") }); - continue; - } - species.push_back(phase_species); - } - - phase.name = name; - phase.species = species; - phase.unknown_properties = GetComments(object); - - // Check for duplicate species within this phase - for (size_t i = 0; i < species.size(); ++i) - { - for (size_t j = i + 1; j < species.size(); ++j) - { - if (species[i].name == species[j].name) - { - std::string line = std::to_string(object.Mark().line + 1); - std::string column = std::to_string(object.Mark().column + 1); - std::ostringstream oss; - oss << line << ":" << column << " error: Duplicate species '" << species[i].name << "' found in '" << name - << "' phase"; - errors.push_back({ ConfigParseStatus::DuplicateSpeciesInPhaseDetected, oss.str() }); - } - } - } - - std::vector species_names; - for (const auto& spec : species) - { - species_names.push_back(spec.name); - } - std::vector unknown_species = FindUnknownSpecies(species_names, existing_species); - if (!unknown_species.empty()) - { - std::ostringstream oss; - oss << " error: Phase '" << phase.name << "' requires unknown species: "; - for (size_t i = 0; i < unknown_species.size(); i++) - { - oss << "'" << unknown_species[i] << "'"; - if (i != unknown_species.size() - 1) - { - oss << ", "; - } - } - errors.push_back({ ConfigParseStatus::PhaseRequiresUnknownSpecies, oss.str() }); - } - - all_phases.push_back(phase); - phase_node_pairs.push_back({ phase, object }); - } - } - - std::vector duplicates = FindDuplicateObjectsByName(phase_node_pairs); - if (!duplicates.empty()) - { - for (const auto& duplicate : duplicates) - { - size_t total = duplicate.nodes.size(); - - for (size_t i = 0; i < total; ++i) - { - const auto& object = duplicate.nodes[i]; - std::string line = std::to_string(object.Mark().line + 1); - std::string column = std::to_string(object.Mark().column + 1); - - std::ostringstream oss; - oss << line << ":" << column << " error: Duplicate phase name '" << duplicate.name << "' found (" << (i + 1) - << " of " << total << ")"; - - errors.push_back({ ConfigParseStatus::DuplicatePhasesDetected, oss.str() }); - } - } - } - - return { errors, all_phases }; - } - - std::pair ParseReactionComponent(const YAML::Node& object) - { - Errors errors; - ConfigParseStatus status = ConfigParseStatus::Success; - types::ReactionComponent component; - const std::vector reaction_component_required_keys = { validation::species_name }; - const std::vector reaction_component_optional_keys = { validation::coefficient }; - - auto validate = ValidateSchema(object, reaction_component_required_keys, reaction_component_optional_keys); - errors.insert(errors.end(), validate.begin(), validate.end()); - if (validate.empty()) - if (status == ConfigParseStatus::Success) - { - std::string species_name = object[validation::species_name].as(); - double coefficient = 1; - if (object[validation::coefficient]) - { - coefficient = object[validation::coefficient].as(); - } - - component.species_name = species_name; - component.coefficient = coefficient; - component.unknown_properties = GetComments(object); - } - - return { errors, component }; - } - - std::pair> ParseReactantsOrProducts( - const std::string& key, - const YAML::Node& object) - { - Errors errors; - std::vector result{}; - for (const auto& product : object[key]) - { - auto component_parse = ParseReactionComponent(product); - errors.insert(errors.end(), component_parse.first.begin(), component_parse.first.end()); - if (component_parse.first.empty()) - { - result.push_back(component_parse.second); - } - } - return { errors, result }; - } - - std::pair ParseReactions( - const YAML::Node& objects, - const std::vector& existing_species, - const std::vector& existing_phases) - { - Errors errors; - types::Reactions reactions; - - std::map> parsers; - parsers[validation::Arrhenius_key] = std::make_unique(); - parsers[validation::FirstOrderLoss_key] = std::make_unique(); - parsers[validation::Emission_key] = std::make_unique(); - parsers[validation::Photolysis_key] = std::make_unique(); - parsers[validation::Surface_key] = std::make_unique(); - parsers[validation::TaylorSeries_key] = std::make_unique(); - parsers[validation::Tunneling_key] = std::make_unique(); - parsers[validation::Branched_key] = std::make_unique(); - parsers[validation::Troe_key] = std::make_unique(); - parsers[validation::TernaryChemicalActivation_key] = std::make_unique(); - parsers[validation::UserDefined_key] = std::make_unique(); - parsers[validation::LambdaRateConstant_key] = std::make_unique(); - - for (const auto& object : objects) - { - std::string type = object[validation::type].as(); - auto it = parsers.find(type); - if (it != parsers.end()) - { - auto parse_errors = it->second->parse(object, existing_species, existing_phases, reactions); - errors.insert(errors.end(), parse_errors.begin(), parse_errors.end()); - } - else - { - std::string line = std::to_string(object[validation::type].Mark().line + 1); - std::string column = std::to_string(object[validation::type].Mark().column + 1); - errors.push_back( - { ConfigParseStatus::UnknownType, "Unknown type: " + type + " at line " + line + " column " + column }); - } - } - - return { errors, reactions }; - } - - } // namespace v1 -} // namespace mechanism_configuration diff --git a/src/v1/parser.cpp b/src/v1/parser.cpp index d836db8f..02f8c61e 100644 --- a/src/v1/parser.cpp +++ b/src/v1/parser.cpp @@ -2,19 +2,34 @@ // University of Illinois at Urbana-Champaign // SPDX-License-Identifier: Apache-2.0 -#include -#include -#include -#include -#include +#include "detail/v1/parser.hpp" +#include "detail/v1/type_parsers.hpp" +#include "detail/v1/type_schema.hpp" +#include "detail/v1/utils.hpp" +#include "detail/check_schema.hpp" +#include "detail/v1/keys.hpp" +#include +#include +#include #include -namespace mechanism_configuration +#include +#include + +namespace mechanism_configuration::v1 { - namespace v1 + namespace { - Parser::EntityFormat Parser::GetEntityFormat(const YAML::Node& node) + // How a top-level section (species / phases / reactions) is expressed. + enum class EntityFormat + { + FileList, // { "files": [...] } — split across other files (v1.1+) + Inline, // [ ... ] — listed directly + Invalid, // present but neither of the above + }; + + EntityFormat GetEntityFormat(const YAML::Node& node) { if (node.IsMap() && node["files"]) return EntityFormat::FileList; @@ -23,226 +38,318 @@ namespace mechanism_configuration return EntityFormat::Invalid; } - ParserResult Parser::ParseFromString(const std::string& content) + ErrorLocation LocationOf(const YAML::Node& node) { - ParserResult result; - try - { - YAML::Node object = YAML::Load(content); + return ErrorLocation{ node.Mark().line, node.Mark().column }; + } - std::vector required_keys = { - validation::version, validation::species, validation::phases, validation::reactions - }; - std::vector optional_keys = { validation::name }; + // Appends each component under `key` (reactant- or product-like) as a located reference. + void CollectComponents(const YAML::Node& reaction, std::string_view key, std::vector& out) + { + const std::string k(key); + if (!reaction[k]) + return; + for (const auto& item : AsSequence(reaction[k])) + out.push_back({ GetReactionComponentName(item), LocationOf(item) }); + } + } // namespace - auto validate_errors = ValidateSchema(object, required_keys, optional_keys); - if (!validate_errors.empty()) - { - result.errors = validate_errors; - return result; - } + semantics::Input BuildSemanticInput(const YAML::Node& object) + { + semantics::Input input; + + if (object[std::string(keys::species)]) + for (const auto& s : object[std::string(keys::species)]) + input.species.push_back({ GetReactionComponentName(s), LocationOf(s) }); - return ParseFromNode(object); + if (object[std::string(keys::phases)]) + for (const auto& phase : object[std::string(keys::phases)]) + { + semantics::PhaseRef pr; + pr.name = phase[std::string(keys::name)].as(); + pr.location = LocationOf(phase); + if (phase[std::string(keys::species)]) + for (const auto& ps : phase[std::string(keys::species)]) + pr.species.push_back({ GetReactionComponentName(ps), LocationOf(ps) }); + input.phases.push_back(std::move(pr)); } - catch (const std::exception& e) + + if (object[std::string(keys::reactions)]) + for (const auto& reaction : object[std::string(keys::reactions)]) { - std::string msg = "Failed to parse content as YAML: " + std::string(e.what()); - msg += "\nContent:\n" + content; - result.errors.push_back({ ConfigParseStatus::UnexpectedError, msg }); + semantics::ReactionRef rr; + if (reaction[std::string(keys::type)]) + rr.type = reaction[std::string(keys::type)].as(); + if (reaction[std::string(keys::gas_phase)]) + { + rr.phase = reaction[std::string(keys::gas_phase)].as(); + rr.location = LocationOf(reaction[std::string(keys::gas_phase)]); + } + // Reactant-like keys (must be in the reaction's phase). + CollectComponents(reaction, keys::reactants, rr.reactants); + CollectComponents(reaction, keys::gas_phase_species, rr.reactants); + // Product-like keys (may reference any phase). + CollectComponents(reaction, keys::products, rr.products); + CollectComponents(reaction, keys::alkoxy_products, rr.products); + CollectComponents(reaction, keys::nitrate_products, rr.products); + CollectComponents(reaction, keys::gas_phase_products, rr.products); + input.reactions.push_back(std::move(rr)); } - return result; - } + return input; + } - ParserResult Parser::Parse(const std::filesystem::path& config_path) + std::expected Parser::ResolveFileConfig(const std::filesystem::path& config_path) + { + if (!std::filesystem::exists(config_path) || !std::filesystem::is_regular_file(config_path)) { - ParserResult result; + return std::unexpected( + Errors{ { ErrorCode::FileNotFound, + mc_fmt::format( + "Configuration file '{}' does not exist or is not a regular file.", config_path.string()) } }); + } - if (!std::filesystem::exists(config_path) || !std::filesystem::is_regular_file(config_path)) - { - result.errors.push_back({ ConfigParseStatus::FileNotFound, "File not found or is a directory" }); - return result; - } + SetConfigPath(config_path.string()); - auto prepend_path = [&](Errors& errors) - { - const std::string prefix = config_path.string() + ":"; - for (auto& error : errors) - error.second = prefix + error.second; - }; - - try - { - YAML::Node object = YAML::LoadFile(config_path.string()); + YAML::Node object; + try + { + object = YAML::LoadFile(config_path.string()); + } + catch (const std::exception& e) + { + return std::unexpected( + Errors{ + { ErrorCode::UnexpectedError, mc_fmt::format("Failed to parse '{}': {}", config_path.string(), e.what()) } }); + } - std::vector mechanism_required_keys = { - validation::version, validation::species, validation::phases, validation::reactions - }; - std::vector mechanism_optional_keys = { validation::name }; + Errors errors; + const std::filesystem::path base_dir = config_path.parent_path(); + const Version version = object[keys::version] ? Version(object[keys::version].as()) : Version(); - auto validate_errors = ValidateSchema(object, mechanism_required_keys, mechanism_optional_keys); + YAML::Node combined; + if (object[keys::version]) + combined[std::string(keys::version)] = object[keys::version]; + if (object[keys::name]) + combined[std::string(keys::name)] = object[keys::name]; - if (!validate_errors.empty()) + // Loads and concatenates every file referenced under `.files`. + auto load_files = [&](std::string_view entity) -> YAML::Node + { + YAML::Node merged(YAML::NodeType::Sequence); + for (const auto& file_node : object[std::string(entity)]["files"]) + { + const std::filesystem::path file_path = base_dir / file_node.as(); + if (!std::filesystem::exists(file_path)) { - result.errors = validate_errors; - prepend_path(result.errors); - return result; + errors.push_back({ ErrorCode::FileNotFound, "File not found: " + file_path.string() }); + continue; } - - Version version = Version(object[validation::version].as()); - if (version.major != 1) + try { - result.errors.push_back( - { ConfigParseStatus::InvalidVersion, - "Unsupported version '" + object[validation::version].as() + "'. Expected major version 1." }); - prepend_path(result.errors); - return result; + YAML::Node loaded = YAML::LoadFile(file_path.string()); + for (const auto& item : loaded) + merged.push_back(item); } - - EntityFormat spc_format = GetEntityFormat(object[validation::species]); - EntityFormat phs_format = GetEntityFormat(object[validation::phases]); - EntityFormat rxn_format = GetEntityFormat(object[validation::reactions]); - - auto check_invalid = [&](const std::string& entity, EntityFormat fmt) - { - if (fmt == EntityFormat::Invalid) - { - if (object[entity] && object[entity].IsMap()) - result.errors.push_back( - { ConfigParseStatus::RequiredKeyNotFound, "Missing 'files' key in '" + entity + "' section." }); - else - result.errors.push_back( - { ConfigParseStatus::InvalidType, "'" + entity + "' must be a file-list object or an inline array." }); - } - }; - check_invalid(validation::species, spc_format); - check_invalid(validation::phases, phs_format); - check_invalid(validation::reactions, rxn_format); - - if (result.errors.empty()) + catch (const std::exception& e) { - bool any_filelist = spc_format == EntityFormat::FileList || phs_format == EntityFormat::FileList || - rxn_format == EntityFormat::FileList; - if (any_filelist && version.minor < 1) - { - result.errors.push_back( - { ConfigParseStatus::InvalidVersion, - "File-list format requires minor version >= 1, got " + std::to_string(version.minor) + "." }); - } - else - { - result = ParseFromFileConfig(object, config_path, spc_format, phs_format, rxn_format); - } + errors.push_back({ ErrorCode::UnexpectedError, "Failed to parse file: " + file_path.string() + ": " + e.what() }); } } - catch (const std::exception& e) - { - result.errors.push_back({ ConfigParseStatus::UnexpectedError, - "Failed to parse '" + config_path.string() + "': " + std::string(e.what()) }); - return result; - } + return merged; + }; - if (!result.errors.empty()) + // Resolves one section into the combined node. Missing sections are left out so the + // normal schema validation reports them; malformed sections are flagged here. + auto resolve_section = [&](std::string_view entity) + { + const std::string key(entity); + if (!object[key]) + return; + + switch (GetEntityFormat(object[key])) { - prepend_path(result.errors); + case EntityFormat::Inline: combined[key] = object[key]; break; + case EntityFormat::FileList: combined[key] = load_files(entity); break; + case EntityFormat::Invalid: + if (object[key].IsMap()) + errors.push_back({ ErrorCode::RequiredKeyNotFound, "Missing 'files' key in '" + key + "' section." }); + else + errors.push_back({ ErrorCode::InvalidType, "'" + key + "' must be a file-list object or an inline array." }); + break; } + }; + // A file-list layout requires minor version >= 1; check before loading any files. + const bool uses_filelist = (object[std::string(keys::species)] && + GetEntityFormat(object[std::string(keys::species)]) == EntityFormat::FileList) || + (object[std::string(keys::phases)] && + GetEntityFormat(object[std::string(keys::phases)]) == EntityFormat::FileList) || + (object[std::string(keys::reactions)] && + GetEntityFormat(object[std::string(keys::reactions)]) == EntityFormat::FileList); + if (uses_filelist && version.minor < 1) + { + errors.push_back( + { ErrorCode::InvalidVersion, + "File-list format requires minor version >= 1, got " + std::to_string(version.minor) + "." }); + AppendFilePath(config_path_, errors); + return std::unexpected(std::move(errors)); + } - return result; + resolve_section(keys::species); + resolve_section(keys::phases); + resolve_section(keys::reactions); + + if (!errors.empty()) + { + AppendFilePath(config_path_, errors); + return std::unexpected(std::move(errors)); } - ParserResult Parser::ParseFromNode(const YAML::Node& object) + return combined; + } + + Errors Parser::CheckSchema(const YAML::Node& object) + { + Errors errors; + + std::vector required_keys = { + keys::version, keys::species, keys::phases, keys::reactions + }; + std::vector optional_keys = { keys::name }; + + // Return early if the required keys are not found + auto schema_errors = mechanism_configuration::CheckSchema(object, required_keys, optional_keys); + if (!schema_errors.empty()) { - ParserResult result; - std::unique_ptr mechanism = std::make_unique(); + AppendFilePath(config_path_, schema_errors); + errors.insert(errors.end(), schema_errors.begin(), schema_errors.end()); + return errors; + } - mechanism->version = Version(object[validation::version].as()); + constexpr unsigned int MAJOR_VERSION = 1; + Version version = Version(object[keys::version].as()); + if (version.major != MAJOR_VERSION) + { + ErrorLocation error_location{ object[keys::version].Mark().line, object[keys::version].Mark().column }; + + std::string message = mc_fmt::format( + "{} error: The version must be '{}' but the invalid version number '{}' found.", + error_location, + MAJOR_VERSION, + version.major); + errors.push_back({ ErrorCode::InvalidVersion, config_path_ + ":" + message }); + } - if (object[validation::name]) - { - std::string name = object[validation::name].as(); - mechanism->name = name; - } + schema_errors = CheckSpeciesSchema(object[keys::species]); + if (!schema_errors.empty()) + { + AppendFilePath(config_path_, schema_errors); + errors.insert(errors.end(), schema_errors.begin(), schema_errors.end()); + return errors; + } - auto species_parsing = ParseSpecies(object[validation::species]); - result.errors.insert(result.errors.end(), species_parsing.first.begin(), species_parsing.first.end()); - mechanism->species = species_parsing.second; + auto parsed_species = ParseSpecies(object[keys::species]); - auto phases_parsing = ParsePhases(object[validation::phases], species_parsing.second); - result.errors.insert(result.errors.end(), phases_parsing.first.begin(), phases_parsing.first.end()); - mechanism->phases = phases_parsing.second; + schema_errors = CheckPhasesSchema(object[keys::phases], parsed_species); + if (!schema_errors.empty()) + { + AppendFilePath(config_path_, schema_errors); + errors.insert(errors.end(), schema_errors.begin(), schema_errors.end()); + return errors; + } - auto reactions_parsing = ParseReactions(object[validation::reactions], species_parsing.second, phases_parsing.second); - result.errors.insert(result.errors.end(), reactions_parsing.first.begin(), reactions_parsing.first.end()); - mechanism->reactions = reactions_parsing.second; + auto parsed_phases = ParsePhases(object[keys::phases]); - result.mechanism = std::move(mechanism); - return result; + schema_errors = CheckReactionsSchema(object[keys::reactions], parsed_species, parsed_phases); + if (!schema_errors.empty()) + { + AppendFilePath(config_path_, schema_errors); + errors.insert(errors.end(), schema_errors.begin(), schema_errors.end()); + return errors; } - ParserResult Parser::ParseFromFileConfig( - const YAML::Node& object, - const std::filesystem::path& config_path, - EntityFormat spc_format, - EntityFormat phs_format, - EntityFormat rxn_format) + return errors; + } + + std::expected Parser::Parse(const std::filesystem::path& config_path) + { + // ResolveFileConfig sets config_path_ so errors carry the file path. + auto object = ResolveFileConfig(config_path); + if (!object) { - ParserResult result; + return std::unexpected(std::move(object.error())); + } + return ValidateAndBuild(*object); + } - std::filesystem::path base_dir = config_path.parent_path(); + std::expected Parser::Parse(const std::string& content) + { + SetDefaultConfigPath(); // no file backing this document + YAML::Node object; + try + { + object = YAML::Load(content); + } + catch (const std::exception& e) + { + return std::unexpected(Errors{ { ErrorCode::UnexpectedError, mc_fmt::format("Failed to parse document: {}", e.what()) } }); + } + return ValidateAndBuild(object); + } - auto load_files = [&](const std::string& entity) -> std::pair - { - Errors errors; - YAML::Node merged = YAML::Node(YAML::NodeType::Sequence); + std::expected Parser::Parse(const YAML::Node& object) + { + SetDefaultConfigPath(); // no file backing this node + return ValidateAndBuild(object); + } - for (const auto& file_node : object[entity]["files"]) - { - std::filesystem::path file_path = base_dir / file_node.as(); - if (!std::filesystem::exists(file_path)) - { - errors.push_back({ ConfigParseStatus::FileNotFound, "File not found: " + file_path.string() }); - continue; - } - try - { - YAML::Node loaded = YAML::LoadFile(file_path.string()); - for (const auto& item : loaded) - merged.push_back(item); - } - catch (const std::exception& e) - { - errors.push_back( - { ConfigParseStatus::UnexpectedError, "Failed to parse file: " + file_path.string() + ": " + e.what() }); - } - } - return { errors, merged }; - }; + std::expected Parser::ValidateAndBuild(const YAML::Node& object) + { + try + { + // 1) Structural (schema) validation. + Errors errors = CheckSchema(object); - auto resolve_section = [&](const std::string& entity, EntityFormat fmt) -> std::pair + // 2) Semantic validation — needs a structurally-valid document, so only run it when + // the structure is clean. Located via BuildSemanticInput so errors carry line:col. + if (errors.empty()) { - if (fmt == EntityFormat::Inline) - return { {}, object[entity] }; - return load_files(entity); - }; + auto semantic_errors = ValidateSemantics(BuildSemanticInput(object)); + AppendFilePath(config_path_, semantic_errors); + errors.insert(errors.end(), semantic_errors.begin(), semantic_errors.end()); + } - YAML::Node combined; - combined[validation::version] = object[validation::version]; - if (object[validation::name]) - combined[validation::name] = object[validation::name]; + if (!errors.empty()) + { + return std::unexpected(std::move(errors)); + } - auto [species_errors, species_node] = resolve_section(validation::species, spc_format); - result.errors.insert(result.errors.end(), species_errors.begin(), species_errors.end()); - combined[validation::species] = species_node; + // 3) Build the Mechanism (only reached when fully valid). + return Build(object); + } + catch (const std::exception& e) + { + const std::string where = config_path_.empty() ? "document" : "'" + config_path_ + "'"; + return std::unexpected( + Errors{ { ErrorCode::UnexpectedError, mc_fmt::format("Failed to parse {}: {}", where, e.what()) } }); + } + } - auto [phases_errors, phases_node] = resolve_section(validation::phases, phs_format); - result.errors.insert(result.errors.end(), phases_errors.begin(), phases_errors.end()); - combined[validation::phases] = phases_node; + Mechanism Parser::Build(const YAML::Node& object) + { + Mechanism mechanism; - auto [reactions_errors, reactions_node] = resolve_section(validation::reactions, rxn_format); - result.errors.insert(result.errors.end(), reactions_errors.begin(), reactions_errors.end()); - combined[validation::reactions] = reactions_node; + mechanism.version = Version(object[keys::version].as()); + mechanism.species = ParseSpecies(object[keys::species]); + mechanism.phases = ParsePhases(object[keys::phases]); + mechanism.reactions = ParseReactions(object[keys::reactions]); - return ParseFromNode(combined); + if (object[keys::name]) + { + mechanism.name = object[keys::name].as(); } - } // namespace v1 -} // namespace mechanism_configuration \ No newline at end of file + + return mechanism; + } + +} // namespace mechanism_configuration::v1 diff --git a/src/v1/reactions/CMakeLists.txt b/src/v1/reactions/CMakeLists.txt index 1a49b905..23f955b9 100644 --- a/src/v1/reactions/CMakeLists.txt +++ b/src/v1/reactions/CMakeLists.txt @@ -1,15 +1,15 @@ target_sources(mechanism_configuration PRIVATE - arrhenius_parser.cpp - branched_parser.cpp - emission_parser.cpp - first_order_loss_parser.cpp - lambda_parser.cpp - photolysis_parser.cpp - surface_parser.cpp - taylor_series_parser.cpp - troe_parser.cpp - ternary_chemical_activation_parser.cpp - tunneling_parser.cpp - user_defined_parser.cpp + arrhenius.cpp + branched.cpp + emission.cpp + first_order_loss.cpp + photolysis.cpp + surface.cpp + taylor_series.cpp + ternary_chemical_activation.cpp + troe.cpp + tunneling.cpp + user_defined.cpp + lambda_rate_constant.cpp ) diff --git a/src/v1/reactions/arrhenius.cpp b/src/v1/reactions/arrhenius.cpp new file mode 100644 index 00000000..498f6ace --- /dev/null +++ b/src/v1/reactions/arrhenius.cpp @@ -0,0 +1,124 @@ +// Copyright (C) 2023–2026 University Corporation for Atmospheric Research +// University of Illinois at Urbana-Champaign +// SPDX-License-Identifier: Apache-2.0 + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace mechanism_configuration +{ + namespace v1 + { + /// @brief Checks the structural schema of a YAML-defined Arrhenius reaction entry + /// Performs schema validation, checks for mutually exclusive parameters (`Ea` vs `C`), + /// and collects any structural errors found. + /// @param object The YAML node representing the reaction + /// @param existing_species Unused; semantic checks live in ValidateSemantics + /// @param existing_phases Unused; semantic checks live in ValidateSemantics + /// @return A list of validation errors, if any + Errors ArrheniusParser::CheckSchema( + const YAML::Node& object, + const std::vector& existing_species, + const std::vector& existing_phases) + { + std::vector required_keys = { + keys::reactants, keys::products, keys::type, keys::gas_phase + }; + std::vector optional_keys = { keys::A, keys::B, keys::C, keys::D, + keys::E, keys::Ea, keys::name }; + Errors errors; + + auto schema_errors = mechanism_configuration::CheckSchema(object, required_keys, optional_keys); + if (!schema_errors.empty()) + { + errors.insert(errors.end(), schema_errors.begin(), schema_errors.end()); + return errors; + } + + // Reactants + schema_errors = CheckReactantsOrProductsSchema(object[keys::reactants]); + if (!schema_errors.empty()) + { + errors.insert(errors.end(), schema_errors.begin(), schema_errors.end()); + } + + // Products + schema_errors = CheckReactantsOrProductsSchema(object[keys::products]); + if (!schema_errors.empty()) + { + errors.insert(errors.end(), schema_errors.begin(), schema_errors.end()); + } + + if (object[keys::Ea] && object[keys::C]) + { + const auto& node = object[keys::Ea]; + ErrorLocation error_location{ node.Mark().line, node.Mark().column }; + + std::string message = mc_fmt::format( + "{} error: Mutually exclusive option of 'Ea' and 'C' found in '{}' reaction.", + error_location, + object[keys::type].as()); + + errors.push_back({ ErrorCode::MutuallyExclusiveOption, message }); + } + + // Semantic checks (species existence, phase membership) are performed by the + // version-neutral ValidateSemantics over the canonical Mechanism. + return errors; + } + + /// @brief Parses a YAML-defined Arrhenius reaction and appends it to the reaction list. + /// Extracts reactants, products, kinetic parameters (A–E, Ea), gas phase, + /// optional metadata (name, comments), and constructs a `types::Arrhenius` object. + /// @param object The YAML node representing the reaction + /// @param reactions The reactions container to append the parsed reaction to + void ArrheniusParser::Parse(const YAML::Node& object, types::Reactions& reactions) + { + types::Arrhenius arrhenius; + + arrhenius.gas_phase = object[keys::gas_phase].as(); + arrhenius.reactants = ParseReactionComponents(object, keys::reactants); + arrhenius.products = ParseReactionComponents(object, keys::products); + arrhenius.unknown_properties = GetComments(object); + + if (object[keys::A]) + { + arrhenius.A = object[keys::A].as(); + } + if (object[keys::B]) + { + arrhenius.B = object[keys::B].as(); + } + if (object[keys::C]) + { + arrhenius.C = object[keys::C].as(); + } + if (object[keys::D]) + { + arrhenius.D = object[keys::D].as(); + } + if (object[keys::E]) + { + arrhenius.E = object[keys::E].as(); + } + if (object[keys::Ea]) + { + arrhenius.C = -1 * object[keys::Ea].as() / constants::boltzmann; + } + if (object[keys::name]) + { + arrhenius.name = object[keys::name].as(); + } + + reactions.arrhenius.emplace_back(std::move(arrhenius)); + } + + } // namespace v1 +} // namespace mechanism_configuration diff --git a/src/v1/reactions/arrhenius_parser.cpp b/src/v1/reactions/arrhenius_parser.cpp deleted file mode 100644 index e8220e51..00000000 --- a/src/v1/reactions/arrhenius_parser.cpp +++ /dev/null @@ -1,139 +0,0 @@ -// Copyright (C) 2023–2026 University Corporation for Atmospheric Research -// University of Illinois at Urbana-Champaign -// SPDX-License-Identifier: Apache-2.0 - -#include -#include -#include -#include -#include -#include - -namespace mechanism_configuration -{ - namespace v1 - { - Errors ArrheniusParser::parse( - const YAML::Node& object, - const std::vector& existing_species, - const std::vector& existing_phases, - types::Reactions& reactions) - { - Errors errors; - types::Arrhenius arrhenius; - - std::vector required_keys = { - validation::products, validation::reactants, validation::type, validation::gas_phase - }; - std::vector optional_keys = { validation::A, validation::B, validation::C, validation::D, - validation::E, validation::Ea, validation::name }; - - auto validate = ValidateSchema(object, required_keys, optional_keys); - errors.insert(errors.end(), validate.begin(), validate.end()); - if (validate.empty()) - { - auto products = ParseReactantsOrProducts(validation::products, object); - errors.insert(errors.end(), products.first.begin(), products.first.end()); - auto reactants = ParseReactantsOrProducts(validation::reactants, object); - errors.insert(errors.end(), reactants.first.begin(), reactants.first.end()); - - if (object[validation::A]) - { - arrhenius.A = object[validation::A].as(); - } - if (object[validation::B]) - { - arrhenius.B = object[validation::B].as(); - } - if (object[validation::C]) - { - arrhenius.C = object[validation::C].as(); - } - if (object[validation::D]) - { - arrhenius.D = object[validation::D].as(); - } - if (object[validation::E]) - { - arrhenius.E = object[validation::E].as(); - } - if (object[validation::Ea]) - { - if (arrhenius.C != 0) - { - std::string line = std::to_string(object[validation::Ea].Mark().line + 1); - std::string column = std::to_string(object[validation::Ea].Mark().column + 1); - errors.push_back({ ConfigParseStatus::MutuallyExclusiveOption, - line + ":" + column + ": Mutually exclusive option: Ea and C" }); - } - arrhenius.C = -1 * object[validation::Ea].as() / constants::boltzmann; - } - - if (object[validation::name]) - { - arrhenius.name = object[validation::name].as(); - } - - std::vector requested_species; - for (const auto& spec : products.second) - { - requested_species.push_back(spec.species_name); - } - for (const auto& spec : reactants.second) - { - requested_species.push_back(spec.species_name); - } - - std::vector unknown_species = FindUnknownSpecies(requested_species, existing_species); - if (!unknown_species.empty()) - { - std::ostringstream oss; - - std::string line = std::to_string(object.Mark().line + 1); - std::string column = std::to_string(object.Mark().column + 1); - oss << line << ":" << column; - - if (object[validation::name]) - { - oss << " error: Reaction '" << object[validation::name].as() << "' requires unknown species: "; - } - else - { - oss << " error: Reaction requires unknown species: "; - } - - for (size_t i = 0; i < unknown_species.size(); i++) - { - oss << "'" << unknown_species[i] << "'"; - if (i != unknown_species.size() - 1) - { - oss << ", "; - } - } - - errors.push_back({ ConfigParseStatus::ReactionRequiresUnknownSpecies, oss.str() }); - } - - std::string gas_phase = object[validation::gas_phase].as(); - auto it = std::find_if( - existing_phases.begin(), - existing_phases.end(), - [&gas_phase](const auto& phase) { return phase.name == gas_phase; }); - if (it == existing_phases.end()) - { - std::string line = std::to_string(object[validation::gas_phase].Mark().line + 1); - std::string column = std::to_string(object[validation::gas_phase].Mark().column + 1); - errors.push_back({ ConfigParseStatus::UnknownPhase, line + ":" + column + ": Unknown phase: " + gas_phase }); - } - - arrhenius.gas_phase = gas_phase; - arrhenius.products = products.second; - arrhenius.reactants = reactants.second; - arrhenius.unknown_properties = GetComments(object); - reactions.arrhenius.push_back(arrhenius); - } - - return errors; - } - } // namespace v1 -} // namespace mechanism_configuration diff --git a/src/v1/reactions/branched.cpp b/src/v1/reactions/branched.cpp new file mode 100644 index 00000000..34e117dd --- /dev/null +++ b/src/v1/reactions/branched.cpp @@ -0,0 +1,109 @@ +// Copyright (C) 2023–2026 University Corporation for Atmospheric Research +// University of Illinois at Urbana-Champaign +// SPDX-License-Identifier: Apache-2.0 + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace mechanism_configuration +{ + namespace v1 + { + /// @brief Checks the structural schema of a YAML-defined Branched reaction entry + /// Performs structural (schema) validation only; + /// and collects any errors found. + /// @param object The YAML node representing the reaction + /// @param existing_species Unused; semantic checks live in ValidateSemantics + /// @param existing_phases Unused; semantic checks live in ValidateSemantics + /// @return A list of validation errors, if any + Errors BranchedParser::CheckSchema( + const YAML::Node& object, + const std::vector& existing_species, + const std::vector& existing_phases) + { + std::vector required_keys = { keys::type, + keys::gas_phase, + keys::reactants, + keys::alkoxy_products, + keys::nitrate_products }; + std::vector optional_keys = { + keys::name, keys::X, keys::Y, keys::a0, keys::n + }; + + Errors errors; + + auto schema_errors = mechanism_configuration::CheckSchema(object, required_keys, optional_keys); + if (!schema_errors.empty()) + { + errors.insert(errors.end(), schema_errors.begin(), schema_errors.end()); + return errors; + } + + // Reactants + schema_errors = CheckReactantsOrProductsSchema(object[keys::reactants]); + if (!schema_errors.empty()) + { + errors.insert(errors.end(), schema_errors.begin(), schema_errors.end()); + } + + // Alkoxy products + schema_errors = CheckReactantsOrProductsSchema(object[keys::alkoxy_products]); + if (!schema_errors.empty()) + { + errors.insert(errors.end(), schema_errors.begin(), schema_errors.end()); + } + + // Nitrate products + schema_errors = CheckReactantsOrProductsSchema(object[keys::nitrate_products]); + if (!schema_errors.empty()) + { + errors.insert(errors.end(), schema_errors.begin(), schema_errors.end()); + } + + // Semantic checks (species existence, phase membership) are performed by the + // version-neutral ValidateSemantics over the canonical Mechanism. + return errors; + } + + void BranchedParser::Parse(const YAML::Node& object, types::Reactions& reactions) + { + types::Branched branched; + + branched.gas_phase = object[keys::gas_phase].as(); + branched.reactants = ParseReactionComponents(object, keys::reactants); + branched.alkoxy_products = ParseReactionComponents(object, keys::alkoxy_products); + branched.nitrate_products = ParseReactionComponents(object, keys::nitrate_products); + branched.unknown_properties = GetComments(object); + + if (object[keys::X]) + { + branched.X = object[keys::X].as(); + } + if (object[keys::Y]) + { + branched.Y = object[keys::Y].as(); + } + if (object[keys::a0]) + { + branched.a0 = object[keys::a0].as(); + } + if (object[keys::n]) + { + branched.n = object[keys::n].as(); + } + if (object[keys::name]) + { + branched.name = object[keys::name].as(); + } + + reactions.branched.emplace_back(std::move(branched)); + } + + } // namespace v1 +} // namespace mechanism_configuration diff --git a/src/v1/reactions/branched_parser.cpp b/src/v1/reactions/branched_parser.cpp deleted file mode 100644 index 6d7c8a3e..00000000 --- a/src/v1/reactions/branched_parser.cpp +++ /dev/null @@ -1,122 +0,0 @@ -// Copyright (C) 2023–2026 University Corporation for Atmospheric Research -// University of Illinois at Urbana-Champaign -// SPDX-License-Identifier: Apache-2.0 - -#include -#include -#include -#include -#include -#include - -namespace mechanism_configuration -{ - namespace v1 - { - Errors BranchedParser::parse( - const YAML::Node& object, - const std::vector& existing_species, - const std::vector& existing_phases, - types::Reactions& reactions) - { - Errors errors; - types::Branched branched; - - std::vector required_keys = { validation::nitrate_products, - validation::alkoxy_products, - validation::reactants, - validation::type, - validation::gas_phase }; - std::vector optional_keys = { - validation::name, validation::X, validation::Y, validation::a0, validation::n - }; - - auto validate = ValidateSchema(object, required_keys, optional_keys); - errors.insert(errors.end(), validate.begin(), validate.end()); - if (validate.empty()) - { - auto alkoxy_products = ParseReactantsOrProducts(validation::alkoxy_products, object); - errors.insert(errors.end(), alkoxy_products.first.begin(), alkoxy_products.first.end()); - auto nitrate_products = ParseReactantsOrProducts(validation::nitrate_products, object); - errors.insert(errors.end(), nitrate_products.first.begin(), nitrate_products.first.end()); - auto reactants = ParseReactantsOrProducts(validation::reactants, object); - errors.insert(errors.end(), reactants.first.begin(), reactants.first.end()); - - branched.X = object[validation::X].as(); - branched.Y = object[validation::Y].as(); - branched.a0 = object[validation::a0].as(); - branched.n = object[validation::n].as(); - - if (object[validation::name]) - { - branched.name = object[validation::name].as(); - } - - std::vector requested_species; - for (const auto& spec : nitrate_products.second) - { - requested_species.push_back(spec.species_name); - } - for (const auto& spec : alkoxy_products.second) - { - requested_species.push_back(spec.species_name); - } - for (const auto& spec : reactants.second) - { - requested_species.push_back(spec.species_name); - } - - std::vector unknown_species = FindUnknownSpecies(requested_species, existing_species); - if (!unknown_species.empty()) - { - std::ostringstream oss; - - std::string line = std::to_string(object.Mark().line + 1); - std::string column = std::to_string(object.Mark().column + 1); - oss << line << ":" << column; - - if (object[validation::name]) - { - oss << " error: Reaction '" << object[validation::name].as() << "' requires unknown species: "; - } - else - { - oss << " error: Reaction requires unknown species: "; - } - - for (size_t i = 0; i < unknown_species.size(); i++) - { - oss << "'" << unknown_species[i] << "'"; - if (i != unknown_species.size() - 1) - { - oss << ", "; - } - } - - errors.push_back({ ConfigParseStatus::ReactionRequiresUnknownSpecies, oss.str() }); - } - - std::string gas_phase = object[validation::gas_phase].as(); - auto it = std::find_if( - existing_phases.begin(), - existing_phases.end(), - [&gas_phase](const auto& phase) { return phase.name == gas_phase; }); - if (it == existing_phases.end()) - { - std::string line = std::to_string(object[validation::gas_phase].Mark().line + 1); - std::string column = std::to_string(object[validation::gas_phase].Mark().column + 1); - errors.push_back({ ConfigParseStatus::UnknownPhase, line + ":" + column + ": Unknown phase: " + gas_phase }); - } - - branched.gas_phase = gas_phase; - branched.nitrate_products = nitrate_products.second; - branched.alkoxy_products = alkoxy_products.second; - branched.reactants = reactants.second; - branched.unknown_properties = GetComments(object); - reactions.branched.push_back(branched); - } - - return errors; - } - } // namespace v1 -} // namespace mechanism_configuration diff --git a/src/v1/reactions/emission.cpp b/src/v1/reactions/emission.cpp new file mode 100644 index 00000000..2aecde92 --- /dev/null +++ b/src/v1/reactions/emission.cpp @@ -0,0 +1,75 @@ +// Copyright (C) 2023–2026 University Corporation for Atmospheric Research +// University of Illinois at Urbana-Champaign +// SPDX-License-Identifier: Apache-2.0 + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace mechanism_configuration +{ + namespace v1 + { + /// @brief Checks the structural schema of a YAML-defined Emission reaction entry. + /// Performs structural (schema) validation only; + /// and collects any errors found. + /// @param object The YAML node representing the reaction + /// @param existing_species Unused; semantic checks live in ValidateSemantics + /// @param existing_phases Unused; semantic checks live in ValidateSemantics + /// @return A list of validation errors, if any + Errors EmissionParser::CheckSchema( + const YAML::Node& object, + const std::vector& existing_species, + const std::vector& existing_phases) + { + std::vector required_keys = { keys::products, keys::type, keys::gas_phase }; + std::vector optional_keys = { keys::name, keys::scaling_factor }; + + Errors errors; + + auto schema_errors = mechanism_configuration::CheckSchema(object, required_keys, optional_keys); + if (!schema_errors.empty()) + { + errors.insert(errors.end(), schema_errors.begin(), schema_errors.end()); + return errors; + } + + // Products + schema_errors = CheckReactantsOrProductsSchema(object[keys::products]); + if (!schema_errors.empty()) + { + errors.insert(errors.end(), schema_errors.begin(), schema_errors.end()); + } + + // Semantic checks (species existence, phase membership) are performed by the + // version-neutral ValidateSemantics over the canonical Mechanism. + return errors; + } + + void EmissionParser::Parse(const YAML::Node& object, types::Reactions& reactions) + { + types::Emission emission; + + emission.gas_phase = object[keys::gas_phase].as(); + emission.products = ParseReactionComponents(object, keys::products); + emission.unknown_properties = GetComments(object); + + if (object[keys::scaling_factor]) + { + emission.scaling_factor = object[keys::scaling_factor].as(); + } + if (object[keys::name]) + { + emission.name = object[keys::name].as(); + } + + reactions.emission.emplace_back(std::move(emission)); + } + + } // namespace v1 +} // namespace mechanism_configuration diff --git a/src/v1/reactions/emission_parser.cpp b/src/v1/reactions/emission_parser.cpp deleted file mode 100644 index 3500fdc2..00000000 --- a/src/v1/reactions/emission_parser.cpp +++ /dev/null @@ -1,102 +0,0 @@ -// Copyright (C) 2023–2026 University Corporation for Atmospheric Research -// University of Illinois at Urbana-Champaign -// SPDX-License-Identifier: Apache-2.0 - -#include -#include -#include -#include -#include -#include - -namespace mechanism_configuration -{ - namespace v1 - { - Errors EmissionParser::parse( - const YAML::Node& object, - const std::vector& existing_species, - const std::vector& existing_phases, - types::Reactions& reactions) - { - Errors errors; - types::Emission emission; - - std::vector required_keys = { validation::products, validation::type, validation::gas_phase }; - std::vector optional_keys = { validation::name, validation::scaling_factor }; - - auto validate = ValidateSchema(object, required_keys, optional_keys); - errors.insert(errors.end(), validate.begin(), validate.end()); - if (validate.empty()) - { - auto products = ParseReactantsOrProducts(validation::products, object); - errors.insert(errors.end(), products.first.begin(), products.first.end()); - - if (object[validation::scaling_factor]) - { - emission.scaling_factor = object[validation::scaling_factor].as(); - } - - if (object[validation::name]) - { - emission.name = object[validation::name].as(); - } - - std::vector requested_species; - for (const auto& spec : products.second) - { - requested_species.push_back(spec.species_name); - } - - std::vector unknown_species = FindUnknownSpecies(requested_species, existing_species); - if (!unknown_species.empty()) - { - std::ostringstream oss; - - std::string line = std::to_string(object.Mark().line + 1); - std::string column = std::to_string(object.Mark().column + 1); - oss << line << ":" << column; - - if (object[validation::name]) - { - oss << " error: Reaction '" << object[validation::name].as() << "' requires unknown species: "; - } - else - { - oss << " error: Reaction requires unknown species: "; - } - - for (size_t i = 0; i < unknown_species.size(); i++) - { - oss << "'" << unknown_species[i] << "'"; - if (i != unknown_species.size() - 1) - { - oss << ", "; - } - } - - errors.push_back({ ConfigParseStatus::ReactionRequiresUnknownSpecies, oss.str() }); - } - - std::string gas_phase = object[validation::gas_phase].as(); - auto it = std::find_if( - existing_phases.begin(), - existing_phases.end(), - [&gas_phase](const auto& phase) { return phase.name == gas_phase; }); - if (it == existing_phases.end()) - { - std::string line = std::to_string(object[validation::gas_phase].Mark().line + 1); - std::string column = std::to_string(object[validation::gas_phase].Mark().column + 1); - errors.push_back({ ConfigParseStatus::UnknownPhase, line + ":" + column + ": Unknown phase: " + gas_phase }); - } - - emission.gas_phase = gas_phase; - emission.products = products.second; - emission.unknown_properties = GetComments(object); - reactions.emission.push_back(emission); - } - - return errors; - } - } // namespace v1 -} // namespace mechanism_configuration diff --git a/src/v1/reactions/first_order_loss.cpp b/src/v1/reactions/first_order_loss.cpp new file mode 100644 index 00000000..95e92716 --- /dev/null +++ b/src/v1/reactions/first_order_loss.cpp @@ -0,0 +1,105 @@ +// Copyright (C) 2023–2026 University Corporation for Atmospheric Research +// University of Illinois at Urbana-Champaign +// SPDX-License-Identifier: Apache-2.0 + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace mechanism_configuration +{ + namespace v1 + { + /// @brief Checks the structural schema of a YAML-defined First order loss reaction entry. + /// Performs structural (schema) validation only; + /// and collects any errors found. + /// @param object The YAML node representing the reaction + /// @param existing_species Unused; semantic checks live in ValidateSemantics + /// @param existing_phases Unused; semantic checks live in ValidateSemantics + /// @return A list of validation errors, if any + Errors FirstOrderLossParser::CheckSchema( + const YAML::Node& object, + const std::vector& existing_species, + const std::vector& existing_phases) + { + std::vector required_keys = { keys::reactants, keys::type, keys::gas_phase }; + std::vector optional_keys = { keys::name, keys::scaling_factor, keys::products }; + + Errors errors; + + auto schema_errors = mechanism_configuration::CheckSchema(object, required_keys, optional_keys); + if (!schema_errors.empty()) + { + errors.insert(errors.end(), schema_errors.begin(), schema_errors.end()); + return errors; + } + + // Reactants + schema_errors = CheckReactantsOrProductsSchema(object[keys::reactants]); + if (!schema_errors.empty()) + { + errors.insert(errors.end(), schema_errors.begin(), schema_errors.end()); + } + + if (!errors.empty()) + return errors; + + std::vector> species_node_pairs; + + for (const auto& obj : object[keys::reactants]) + { + types::ReactionComponent component; + component.name = GetReactionComponentName(obj); + species_node_pairs.emplace_back(component, obj); + } + + if (species_node_pairs.size() > 1) + { + const auto& node = object[keys::reactants]; + ErrorLocation error_location{ node.Mark().line, node.Mark().column }; + + std::string message = mc_fmt::format( + "{} error: '{}' reaction requires one reactant, but {} were provided.", + error_location, + object[keys::type].as(), + species_node_pairs.size()); + + errors.push_back({ ErrorCode::TooManyReactionComponents, message }); + } + + // Semantic checks (species existence, phase membership) are performed by the + // version-neutral ValidateSemantics over the canonical Mechanism. + return errors; + } + + void FirstOrderLossParser::Parse(const YAML::Node& object, types::Reactions& reactions) + { + types::FirstOrderLoss first_order_loss; + + first_order_loss.gas_phase = object[keys::gas_phase].as(); + first_order_loss.reactants = ParseReactionComponent(object, keys::reactants); + if (object[keys::products]) + { + first_order_loss.products = ParseReactionComponents(object, keys::products); + } + first_order_loss.unknown_properties = GetComments(object); + + if (object[keys::scaling_factor]) + { + first_order_loss.scaling_factor = object[keys::scaling_factor].as(); + } + if (object[keys::name]) + { + first_order_loss.name = object[keys::name].as(); + } + + reactions.first_order_loss.emplace_back(std::move(first_order_loss)); + } + + } // namespace v1 +} // namespace mechanism_configuration diff --git a/src/v1/reactions/first_order_loss_parser.cpp b/src/v1/reactions/first_order_loss_parser.cpp deleted file mode 100644 index 5440c3ab..00000000 --- a/src/v1/reactions/first_order_loss_parser.cpp +++ /dev/null @@ -1,117 +0,0 @@ -// Copyright (C) 2023–2026 University Corporation for Atmospheric Research -// University of Illinois at Urbana-Champaign -// SPDX-License-Identifier: Apache-2.0 - -#include -#include -#include -#include -#include -#include - -namespace mechanism_configuration -{ - namespace v1 - { - Errors FirstOrderLossParser::parse( - const YAML::Node& object, - const std::vector& existing_species, - const std::vector& existing_phases, - types::Reactions& reactions) - { - Errors errors; - types::FirstOrderLoss first_order_loss; - - std::vector required_keys = { validation::reactants, validation::type, validation::gas_phase }; - std::vector optional_keys = { validation::name, validation::scaling_factor, validation::products }; - - auto validate = ValidateSchema(object, required_keys, optional_keys); - errors.insert(errors.end(), validate.begin(), validate.end()); - if (validate.empty()) - { - auto products = ParseReactantsOrProducts(validation::products, object); - errors.insert(errors.end(), products.first.begin(), products.first.end()); - auto reactants = ParseReactantsOrProducts(validation::reactants, object); - errors.insert(errors.end(), reactants.first.begin(), reactants.first.end()); - - if (object[validation::scaling_factor]) - { - first_order_loss.scaling_factor = object[validation::scaling_factor].as(); - } - - if (object[validation::name]) - { - first_order_loss.name = object[validation::name].as(); - } - - std::vector requested_species; - for (const auto& spec : products.second) - { - requested_species.push_back(spec.species_name); - } - for (const auto& spec : reactants.second) - { - requested_species.push_back(spec.species_name); - } - - std::vector unknown_species = FindUnknownSpecies(requested_species, existing_species); - if (!unknown_species.empty()) - { - std::ostringstream oss; - - std::string line = std::to_string(object.Mark().line + 1); - std::string column = std::to_string(object.Mark().column + 1); - oss << line << ":" << column; - - if (object[validation::name]) - { - oss << " error: Reaction '" << object[validation::name].as() << "' requires unknown species: "; - } - else - { - oss << " error: Reaction requires unknown species: "; - } - - for (size_t i = 0; i < unknown_species.size(); i++) - { - oss << "'" << unknown_species[i] << "'"; - if (i != unknown_species.size() - 1) - { - oss << ", "; - } - } - - errors.push_back({ ConfigParseStatus::ReactionRequiresUnknownSpecies, oss.str() }); - } - - std::string gas_phase = object[validation::gas_phase].as(); - auto it = std::find_if( - existing_phases.begin(), - existing_phases.end(), - [&gas_phase](const auto& phase) { return phase.name == gas_phase; }); - if (it == existing_phases.end()) - { - std::string line = std::to_string(object[validation::gas_phase].Mark().line + 1); - std::string column = std::to_string(object[validation::gas_phase].Mark().column + 1); - errors.push_back({ ConfigParseStatus::UnknownPhase, line + ":" + column + ": Unknown phase: " + gas_phase }); - } - - if (reactants.second.size() > 1) - { - std::string line = std::to_string(object[validation::reactants].Mark().line + 1); - std::string column = std::to_string(object[validation::reactants].Mark().column + 1); - errors.push_back( - { ConfigParseStatus::TooManyReactionComponents, line + ":" + column + ": Too many reaction components" }); - } - - first_order_loss.gas_phase = gas_phase; - first_order_loss.reactants = reactants.second; - first_order_loss.products = products.second; - first_order_loss.unknown_properties = GetComments(object); - reactions.first_order_loss.push_back(first_order_loss); - } - - return errors; - } - } // namespace v1 -} // namespace mechanism_configuration diff --git a/src/v1/reactions/lambda_parser.cpp b/src/v1/reactions/lambda_parser.cpp deleted file mode 100644 index d962be12..00000000 --- a/src/v1/reactions/lambda_parser.cpp +++ /dev/null @@ -1,111 +0,0 @@ -// Copyright (C) 2023–2026 University Corporation for Atmospheric Research -// University of Illinois at Urbana-Champaign -// SPDX-License-Identifier: Apache-2.0 - -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -namespace mechanism_configuration -{ - namespace v1 - { - Errors LambdaRateConstantParser::parse( - const YAML::Node& object, - const std::vector& existing_species, - const std::vector& existing_phases, - types::Reactions& reactions) - { - Errors errors; - types::LambdaRateConstant lambda_rate_constant; - - std::vector required_keys = { - validation::reactants, validation::products, validation::type, validation::gas_phase, validation::lambda_function - }; - std::vector optional_keys = { validation::name }; - auto validate = ValidateSchema(object, required_keys, optional_keys); - errors.insert(errors.end(), validate.begin(), validate.end()); - if (validate.empty()) - { - auto products = ParseReactantsOrProducts(validation::products, object); - errors.insert(errors.end(), products.first.begin(), products.first.end()); - auto reactants = ParseReactantsOrProducts(validation::reactants, object); - errors.insert(errors.end(), reactants.first.begin(), reactants.first.end()); - - lambda_rate_constant.lambda_function = object[validation::lambda_function].as(); - - if (object[validation::name]) - { - lambda_rate_constant.name = object[validation::name].as(); - } - - std::vector requested_species; - for (const auto& spec : products.second) - { - requested_species.push_back(spec.species_name); - } - for (const auto& spec : reactants.second) - { - requested_species.push_back(spec.species_name); - } - - std::vector unknown_species = FindUnknownSpecies(requested_species, existing_species); - if (!unknown_species.empty()) - { - std::ostringstream oss; - - std::string line = std::to_string(object.Mark().line + 1); - std::string column = std::to_string(object.Mark().column + 1); - oss << line << ":" << column; - - if (object[validation::name]) - { - oss << " error: Reaction '" << object[validation::name].as() << "' requires unknown species: "; - } - else - { - oss << " error: Reaction requires unknown species: "; - } - - for (size_t i = 0; i < unknown_species.size(); i++) - { - oss << "'" << unknown_species[i] << "'"; - if (i != unknown_species.size() - 1) - { - oss << ", "; - } - } - - errors.push_back({ ConfigParseStatus::ReactionRequiresUnknownSpecies, oss.str() }); - } - - std::string gas_phase = object[validation::gas_phase].as(); - auto it = std::find_if( - existing_phases.begin(), - existing_phases.end(), - [&gas_phase](const auto& phase) { return phase.name == gas_phase; }); - if (it == existing_phases.end()) - { - std::string line = std::to_string(object[validation::gas_phase].Mark().line + 1); - std::string column = std::to_string(object[validation::gas_phase].Mark().column + 1); - errors.push_back({ ConfigParseStatus::UnknownPhase, line + ":" + column + ": Unknown phase: " + gas_phase }); - } - - lambda_rate_constant.gas_phase = gas_phase; - lambda_rate_constant.products = products.second; - lambda_rate_constant.reactants = reactants.second; - lambda_rate_constant.unknown_properties = GetComments(object); - reactions.lambda_rate_constant.push_back(lambda_rate_constant); - } - - return errors; - } - } // namespace v1 -} // namespace mechanism_configuration diff --git a/src/v1/reactions/lambda_rate_constant.cpp b/src/v1/reactions/lambda_rate_constant.cpp new file mode 100644 index 00000000..692d1b6e --- /dev/null +++ b/src/v1/reactions/lambda_rate_constant.cpp @@ -0,0 +1,81 @@ +// Copyright (C) 2023–2026 University Corporation for Atmospheric Research +// University of Illinois at Urbana-Champaign +// SPDX-License-Identifier: Apache-2.0 + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace mechanism_configuration +{ + namespace v1 + { + /// @brief Checks the structural schema of a YAML-defined Lambda Rate Constant reaction entry + /// Performs structural (schema) validation only; + /// and collects any errors found. + /// @param object The YAML node representing the reaction + /// @param existing_species Unused; semantic checks live in ValidateSemantics + /// @param existing_phases Unused; semantic checks live in ValidateSemantics + /// @return A list of validation errors, if any + Errors LambdaRateConstantParser::CheckSchema( + const YAML::Node& object, + const std::vector& existing_species, + const std::vector& existing_phases) + { + std::vector required_keys = { + keys::reactants, keys::products, keys::type, keys::gas_phase, keys::lambda_function + }; + std::vector optional_keys = { keys::name }; + Errors errors; + + auto schema_errors = mechanism_configuration::CheckSchema(object, required_keys, optional_keys); + if (!schema_errors.empty()) + { + errors.insert(errors.end(), schema_errors.begin(), schema_errors.end()); + return errors; + } + + // Reactants + schema_errors = CheckReactantsOrProductsSchema(object[keys::reactants]); + if (!schema_errors.empty()) + { + errors.insert(errors.end(), schema_errors.begin(), schema_errors.end()); + } + + // Products + schema_errors = CheckReactantsOrProductsSchema(object[keys::products]); + if (!schema_errors.empty()) + { + errors.insert(errors.end(), schema_errors.begin(), schema_errors.end()); + } + + // Semantic checks are performed by the version-neutral ValidateSemantics. + + return errors; + } + + void LambdaRateConstantParser::Parse(const YAML::Node& object, types::Reactions& reactions) + { + types::LambdaRateConstant lambda_rate_constant; + + lambda_rate_constant.reactants = ParseReactionComponents(object, keys::reactants); + lambda_rate_constant.products = ParseReactionComponents(object, keys::products); + lambda_rate_constant.gas_phase = object[keys::gas_phase].as(); + lambda_rate_constant.lambda_function = object[keys::lambda_function].as(); + lambda_rate_constant.unknown_properties = GetComments(object); + + if (object[keys::name]) + { + lambda_rate_constant.name = object[keys::name].as(); + } + + reactions.lambda_rate_constant.emplace_back(std::move(lambda_rate_constant)); + } + + } // namespace v1 +} // namespace mechanism_configuration diff --git a/src/v1/reactions/photolysis.cpp b/src/v1/reactions/photolysis.cpp new file mode 100644 index 00000000..7722473d --- /dev/null +++ b/src/v1/reactions/photolysis.cpp @@ -0,0 +1,114 @@ +// Copyright (C) 2023–2026 University Corporation for Atmospheric Research +// University of Illinois at Urbana-Champaign +// SPDX-License-Identifier: Apache-2.0 + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace mechanism_configuration +{ + namespace v1 + { + /// @brief Checks the structural schema of a YAML-defined Photolysis reaction entry. + /// Performs structural (schema) validation only; + /// and collects any errors found. + /// @param object The YAML node representing the reaction + /// @param existing_species Unused; semantic checks live in ValidateSemantics + /// @param existing_phases Unused; semantic checks live in ValidateSemantics + /// @return A list of validation errors, if any + Errors PhotolysisParser::CheckSchema( + const YAML::Node& object, + const std::vector& existing_species, + const std::vector& existing_phases) + { + std::vector required_keys = { + keys::reactants, keys::products, keys::type, keys::gas_phase + }; + std::vector optional_keys = { keys::name, keys::scaling_factor }; + + Errors errors; + + auto schema_errors = mechanism_configuration::CheckSchema(object, required_keys, optional_keys); + if (!schema_errors.empty()) + { + errors.insert(errors.end(), schema_errors.begin(), schema_errors.end()); + return errors; + } + + // Reactants + schema_errors = CheckReactantsOrProductsSchema(object[keys::reactants]); + if (!schema_errors.empty()) + { + errors.insert(errors.end(), schema_errors.begin(), schema_errors.end()); + } + + // Products + schema_errors = CheckReactantsOrProductsSchema(object[keys::products]); + if (!schema_errors.empty()) + { + errors.insert(errors.end(), schema_errors.begin(), schema_errors.end()); + } + + if (!errors.empty()) + return errors; + + // Reactants must belong to the reaction's phase; products may reference any phase. + std::vector> reactant_node_pairs; + for (const auto& obj : object[keys::reactants]) + { + types::ReactionComponent component; + component.name = GetReactionComponentName(obj); + reactant_node_pairs.emplace_back(component, obj); + } + std::vector> species_node_pairs = reactant_node_pairs; + + // Checks the number of reactants + // This must be done before collecting errors from the products + if (species_node_pairs.size() > 1) + { + const auto& node = object[keys::reactants]; + ErrorLocation error_location{ node.Mark().line, node.Mark().column }; + + std::string message = mc_fmt::format( + "{} error: '{}' reaction requires one reactant, but {} were provided.", + error_location, + object[keys::type].as(), + species_node_pairs.size()); + + errors.push_back({ ErrorCode::TooManyReactionComponents, message }); + } + + // Semantic checks (species existence, phase membership) are performed by the + // version-neutral ValidateSemantics over the canonical Mechanism. + return errors; + } + + void PhotolysisParser::Parse(const YAML::Node& object, types::Reactions& reactions) + { + types::Photolysis photolysis; + + photolysis.gas_phase = object[keys::gas_phase].as(); + photolysis.reactants = ParseReactionComponent(object, keys::reactants); + photolysis.products = ParseReactionComponents(object, keys::products); + photolysis.unknown_properties = GetComments(object); + + if (object[keys::scaling_factor]) + { + photolysis.scaling_factor = object[keys::scaling_factor].as(); + } + if (object[keys::name]) + { + photolysis.name = object[keys::name].as(); + } + + reactions.photolysis.emplace_back(std::move(photolysis)); + } + + } // namespace v1 +} // namespace mechanism_configuration diff --git a/src/v1/reactions/photolysis_parser.cpp b/src/v1/reactions/photolysis_parser.cpp deleted file mode 100644 index 077b2c87..00000000 --- a/src/v1/reactions/photolysis_parser.cpp +++ /dev/null @@ -1,118 +0,0 @@ -// Copyright (C) 2023–2026 University Corporation for Atmospheric Research -// University of Illinois at Urbana-Champaign -// SPDX-License-Identifier: Apache-2.0 - -#include -#include -#include -#include -#include -#include - -namespace mechanism_configuration -{ - namespace v1 - { - Errors PhotolysisParser::parse( - const YAML::Node& object, - const std::vector& existing_species, - const std::vector& existing_phases, - types::Reactions& reactions) - { - Errors errors; - types::Photolysis photolysis; - - std::vector required_keys = { - validation::reactants, validation::products, validation::type, validation::gas_phase - }; - std::vector optional_keys = { validation::name, validation::scaling_factor }; - - auto validate = ValidateSchema(object, required_keys, optional_keys); - errors.insert(errors.end(), validate.begin(), validate.end()); - if (validate.empty()) - { - auto products = ParseReactantsOrProducts(validation::products, object); - errors.insert(errors.end(), products.first.begin(), products.first.end()); - auto reactants = ParseReactantsOrProducts(validation::reactants, object); - errors.insert(errors.end(), reactants.first.begin(), reactants.first.end()); - - if (object[validation::scaling_factor]) - { - photolysis.scaling_factor = object[validation::scaling_factor].as(); - } - - if (object[validation::name]) - { - photolysis.name = object[validation::name].as(); - } - - std::vector requested_species; - for (const auto& spec : products.second) - { - requested_species.push_back(spec.species_name); - } - for (const auto& spec : reactants.second) - { - requested_species.push_back(spec.species_name); - } - - std::vector unknown_species = FindUnknownSpecies(requested_species, existing_species); - if (!unknown_species.empty()) - { - std::ostringstream oss; - - std::string line = std::to_string(object.Mark().line + 1); - std::string column = std::to_string(object.Mark().column + 1); - oss << line << ":" << column; - - if (object[validation::name]) - { - oss << " error: Reaction '" << object[validation::name].as() << "' requires unknown species: "; - } - else - { - oss << " error: Reaction requires unknown species: "; - } - - for (size_t i = 0; i < unknown_species.size(); i++) - { - oss << "'" << unknown_species[i] << "'"; - if (i != unknown_species.size() - 1) - { - oss << ", "; - } - } - - errors.push_back({ ConfigParseStatus::ReactionRequiresUnknownSpecies, oss.str() }); - } - - std::string gas_phase = object[validation::gas_phase].as(); - auto it = std::find_if( - existing_phases.begin(), - existing_phases.end(), - [&gas_phase](const auto& phase) { return phase.name == gas_phase; }); - if (it == existing_phases.end()) - { - std::string line = std::to_string(object[validation::gas_phase].Mark().line + 1); - std::string column = std::to_string(object[validation::gas_phase].Mark().column + 1); - errors.push_back({ ConfigParseStatus::UnknownPhase, line + ":" + column + ": Unknown phase: " + gas_phase }); - } - - if (reactants.second.size() > 1) - { - std::string line = std::to_string(object[validation::reactants].Mark().line + 1); - std::string column = std::to_string(object[validation::reactants].Mark().column + 1); - errors.push_back({ ConfigParseStatus::TooManyReactionComponents, line + ":" + column + ": Too many reactants" }); - } - - photolysis.gas_phase = gas_phase; - photolysis.products = products.second; - photolysis.reactants = reactants.second; - photolysis.unknown_properties = GetComments(object); - reactions.photolysis.push_back(photolysis); - } - - return errors; - } - } // namespace v1 -} // namespace mechanism_configuration diff --git a/src/v1/reactions/surface.cpp b/src/v1/reactions/surface.cpp new file mode 100644 index 00000000..e0a12afa --- /dev/null +++ b/src/v1/reactions/surface.cpp @@ -0,0 +1,120 @@ +// Copyright (C) 2023–2026 University Corporation for Atmospheric Research +// University of Illinois at Urbana-Champaign +// SPDX-License-Identifier: Apache-2.0 + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace mechanism_configuration +{ + namespace v1 + { + /// @brief Checks the structural schema of a YAML-defined Surface reaction entry. + /// Performs structural (schema) validation only; + /// and collects any errors found. + /// @param object The YAML node representing the reaction + /// @param existing_species Unused; semantic checks live in ValidateSemantics + /// @param existing_phases Unused; semantic checks live in ValidateSemantics + /// @return A list of validation errors, if any + Errors SurfaceParser::CheckSchema( + const YAML::Node& object, + const std::vector& existing_species, + const std::vector& existing_phases) + { + std::vector required_keys = { keys::gas_phase_products, + keys::gas_phase_species, + keys::type, + keys::gas_phase }; + std::vector optional_keys = { keys::name, + keys::reaction_probability, + keys::condensed_phase }; + + Errors errors; + + auto schema_errors = mechanism_configuration::CheckSchema(object, required_keys, optional_keys); + if (!schema_errors.empty()) + { + errors.insert(errors.end(), schema_errors.begin(), schema_errors.end()); + return errors; + } + + // Gas phase species reactant + schema_errors = CheckReactantsOrProductsSchema(object[keys::gas_phase_species]); + if (!schema_errors.empty()) + { + errors.insert(errors.end(), schema_errors.begin(), schema_errors.end()); + } + + // Products + schema_errors = CheckReactantsOrProductsSchema(object[keys::gas_phase_products]); + if (!schema_errors.empty()) + { + errors.insert(errors.end(), schema_errors.begin(), schema_errors.end()); + } + + if (!errors.empty()) + return errors; + + // The gas-phase species (reactant) must belong to the reaction's phase; gas-phase + // products may reference any phase, so only the reactant is phase-checked below. + std::vector> reactant_node_pairs; + for (const auto& obj : object[keys::gas_phase_species]) + { + types::ReactionComponent component; + component.name = GetReactionComponentName(obj); + reactant_node_pairs.emplace_back(component, obj); + } + + // Checks the number of reactants + // This must be done before collecting errors from the products + if (reactant_node_pairs.size() > 1) + { + const auto& node = object[keys::gas_phase_species]; + ErrorLocation error_location{ node.Mark().line, node.Mark().column }; + + std::string message = mc_fmt::format( + "{} error: '{}' reaction requires one reactant, but {} were provided.", + error_location, + object[keys::type].as(), + reactant_node_pairs.size()); + + errors.push_back({ ErrorCode::TooManyReactionComponents, message }); + } + + // Semantic checks (species existence, phase membership) are performed by the + // version-neutral ValidateSemantics over the canonical Mechanism. + return errors; + } + void SurfaceParser::Parse(const YAML::Node& object, types::Reactions& reactions) + { + types::Surface surface; + + surface.gas_phase = object[keys::gas_phase].as(); + if (object[keys::condensed_phase]) + { + surface.condensed_phase = object[keys::condensed_phase].as(); + } + surface.gas_phase_species = ParseReactionComponent(object, keys::gas_phase_species); + surface.gas_phase_products = ParseReactionComponents(object, keys::gas_phase_products); + surface.unknown_properties = GetComments(object); + + if (object[keys::reaction_probability]) + { + surface.reaction_probability = object[keys::reaction_probability].as(); + } + if (object[keys::name]) + { + surface.name = object[keys::name].as(); + } + + reactions.surface.emplace_back(std::move(surface)); + } + + } // namespace v1 +} // namespace mechanism_configuration diff --git a/src/v1/reactions/surface_parser.cpp b/src/v1/reactions/surface_parser.cpp deleted file mode 100644 index 07603fb2..00000000 --- a/src/v1/reactions/surface_parser.cpp +++ /dev/null @@ -1,111 +0,0 @@ -// Copyright (C) 2023–2026 University Corporation for Atmospheric Research -// University of Illinois at Urbana-Champaign -// SPDX-License-Identifier: Apache-2.0 - -#include -#include -#include -#include -#include -#include - -namespace mechanism_configuration -{ - namespace v1 - { - Errors SurfaceParser::parse( - const YAML::Node& object, - const std::vector& existing_species, - const std::vector& existing_phases, - types::Reactions& reactions) - { - Errors errors; - types::Surface surface; - - std::vector required_keys = { - validation::gas_phase_products, validation::gas_phase_species, validation::type, validation::gas_phase - }; - std::vector optional_keys = { validation::name, validation::reaction_probability }; - - auto validate = ValidateSchema(object, required_keys, optional_keys); - errors.insert(errors.end(), validate.begin(), validate.end()); - if (validate.empty()) - { - std::string gas_phase_species = object[validation::gas_phase_species].as(); - - auto products = ParseReactantsOrProducts(validation::gas_phase_products, object); - errors.insert(errors.end(), products.first.begin(), products.first.end()); - - if (object[validation::reaction_probability]) - { - surface.reaction_probability = object[validation::reaction_probability].as(); - } - - if (object[validation::name]) - { - surface.name = object[validation::name].as(); - } - - std::vector requested_species; - for (const auto& spec : products.second) - { - requested_species.push_back(spec.species_name); - } - requested_species.push_back(gas_phase_species); - - std::vector unknown_species = FindUnknownSpecies(requested_species, existing_species); - if (!unknown_species.empty()) - { - std::ostringstream oss; - - std::string line = std::to_string(object.Mark().line + 1); - std::string column = std::to_string(object.Mark().column + 1); - oss << line << ":" << column; - - if (object[validation::name]) - { - oss << " error: Reaction '" << object[validation::name].as() << "' requires unknown species: "; - } - else - { - oss << " error: Reaction requires unknown species: "; - } - - for (size_t i = 0; i < unknown_species.size(); i++) - { - oss << "'" << unknown_species[i] << "'"; - if (i != unknown_species.size() - 1) - { - oss << ", "; - } - } - - errors.push_back({ ConfigParseStatus::ReactionRequiresUnknownSpecies, oss.str() }); - } - - std::string gas_phase = object[validation::gas_phase].as(); - - auto it = std::find_if( - existing_phases.begin(), - existing_phases.end(), - [&gas_phase](const auto& phase) { return phase.name == gas_phase; }); - if (it == existing_phases.end()) - { - std::string line = std::to_string(object[validation::gas_phase].Mark().line + 1); - std::string column = std::to_string(object[validation::gas_phase].Mark().column + 1); - errors.push_back({ ConfigParseStatus::UnknownPhase, line + ":" + column + ": Unknown phase: " + gas_phase }); - } - - surface.gas_phase = gas_phase; - surface.gas_phase_products = products.second; - types::ReactionComponent component; - component.species_name = gas_phase_species; - surface.gas_phase_species = component; - surface.unknown_properties = GetComments(object); - reactions.surface.push_back(surface); - } - - return errors; - } - } // namespace v1 -} // namespace mechanism_configuration diff --git a/src/v1/reactions/taylor_series.cpp b/src/v1/reactions/taylor_series.cpp new file mode 100644 index 00000000..df8e2867 --- /dev/null +++ b/src/v1/reactions/taylor_series.cpp @@ -0,0 +1,130 @@ +// Copyright (C) 2023–2026 University Corporation for Atmospheric Research +// University of Illinois at Urbana-Champaign +// SPDX-License-Identifier: Apache-2.0 + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace mechanism_configuration +{ + namespace v1 + { + /// @brief Checks the structural schema of a YAML-defined Taylor Series reaction entry + /// Performs schema validation, checks for mutually exclusive parameters (`Ea` vs `C`), + /// and collects any structural errors found. + /// @param object The YAML node representing the reaction + /// @param existing_species Unused; semantic checks live in ValidateSemantics + /// @param existing_phases Unused; semantic checks live in ValidateSemantics + /// @return A list of validation errors, if any + Errors TaylorSeriesParser::CheckSchema( + const YAML::Node& object, + const std::vector& existing_species, + const std::vector& existing_phases) + { + std::vector required_keys = { + keys::reactants, keys::products, keys::type, keys::gas_phase + }; + std::vector optional_keys = { keys::A, keys::B, + keys::C, keys::D, + keys::E, keys::Ea, + keys::name, keys::taylor_coefficients }; + Errors errors; + + auto schema_errors = mechanism_configuration::CheckSchema(object, required_keys, optional_keys); + if (!schema_errors.empty()) + { + errors.insert(errors.end(), schema_errors.begin(), schema_errors.end()); + return errors; + } + + // Reactants + schema_errors = CheckReactantsOrProductsSchema(object[keys::reactants]); + if (!schema_errors.empty()) + { + errors.insert(errors.end(), schema_errors.begin(), schema_errors.end()); + } + + // Products + schema_errors = CheckReactantsOrProductsSchema(object[keys::products]); + if (!schema_errors.empty()) + { + errors.insert(errors.end(), schema_errors.begin(), schema_errors.end()); + } + + if (object[keys::Ea] && object[keys::C]) + { + const auto& node = object[keys::Ea]; + ErrorLocation error_location{ node.Mark().line, node.Mark().column }; + + std::string message = mc_fmt::format( + "{} error: Mutually exclusive option of 'Ea' and 'C' found in '{}' reaction.", + error_location, + object[keys::type].as()); + + errors.push_back({ ErrorCode::MutuallyExclusiveOption, message }); + } + + // Semantic checks are performed by the version-neutral ValidateSemantics. + + return errors; + } + + /// @brief Parses a YAML-defined Taylor Series reaction and appends it to the reaction list. + /// Extracts reactants, products, kinetic parameters (A–E, Ea), gas phase, + /// optional metadata (name, comments), and constructs a `types::TaylorSeries` object. + /// @param object The YAML node representing the reaction + /// @param reactions The reactions container to append the parsed reaction to + void TaylorSeriesParser::Parse(const YAML::Node& object, types::Reactions& reactions) + { + types::TaylorSeries taylor_series; + + taylor_series.gas_phase = object[keys::gas_phase].as(); + taylor_series.reactants = ParseReactionComponents(object, keys::reactants); + taylor_series.products = ParseReactionComponents(object, keys::products); + taylor_series.unknown_properties = GetComments(object); + + if (object[keys::A]) + { + taylor_series.A = object[keys::A].as(); + } + if (object[keys::B]) + { + taylor_series.B = object[keys::B].as(); + } + if (object[keys::C]) + { + taylor_series.C = object[keys::C].as(); + } + if (object[keys::D]) + { + taylor_series.D = object[keys::D].as(); + } + if (object[keys::E]) + { + taylor_series.E = object[keys::E].as(); + } + if (object[keys::Ea]) + { + taylor_series.C = -1 * object[keys::Ea].as() / constants::boltzmann; + } + if (object[keys::taylor_coefficients]) + { + taylor_series.taylor_coefficients = object[keys::taylor_coefficients].as>(); + } + if (object[keys::name]) + { + taylor_series.name = object[keys::name].as(); + } + + reactions.taylor_series.emplace_back(std::move(taylor_series)); + } + + } // namespace v1 +} // namespace mechanism_configuration diff --git a/src/v1/reactions/taylor_series_parser.cpp b/src/v1/reactions/taylor_series_parser.cpp deleted file mode 100644 index 1261d244..00000000 --- a/src/v1/reactions/taylor_series_parser.cpp +++ /dev/null @@ -1,149 +0,0 @@ -// Copyright (C) 2023–2026 University Corporation for Atmospheric Research -// University of Illinois at Urbana-Champaign -// SPDX-License-Identifier: Apache-2.0 - -#include -#include -#include -#include -#include -#include - -namespace mechanism_configuration -{ - namespace v1 - { - Errors TaylorSeriesParser::parse( - const YAML::Node& object, - const std::vector& existing_species, - const std::vector& existing_phases, - types::Reactions& reactions) - { - Errors errors; - types::TaylorSeries taylor_series; - - std::vector required_keys = { - validation::products, validation::reactants, validation::type, validation::gas_phase - }; - std::vector optional_keys = { validation::A, - validation::B, - validation::C, - validation::D, - validation::E, - validation::Ea, - validation::taylor_coefficients, - validation::name }; - - auto validate = ValidateSchema(object, required_keys, optional_keys); - errors.insert(errors.end(), validate.begin(), validate.end()); - if (validate.empty()) - { - auto products = ParseReactantsOrProducts(validation::products, object); - errors.insert(errors.end(), products.first.begin(), products.first.end()); - auto reactants = ParseReactantsOrProducts(validation::reactants, object); - errors.insert(errors.end(), reactants.first.begin(), reactants.first.end()); - - if (object[validation::A]) - { - taylor_series.A = object[validation::A].as(); - } - if (object[validation::B]) - { - taylor_series.B = object[validation::B].as(); - } - if (object[validation::C]) - { - taylor_series.C = object[validation::C].as(); - } - if (object[validation::D]) - { - taylor_series.D = object[validation::D].as(); - } - if (object[validation::E]) - { - taylor_series.E = object[validation::E].as(); - } - if (object[validation::Ea]) - { - if (taylor_series.C != 0) - { - std::string line = std::to_string(object[validation::Ea].Mark().line + 1); - std::string column = std::to_string(object[validation::Ea].Mark().column + 1); - errors.push_back({ ConfigParseStatus::MutuallyExclusiveOption, - line + ":" + column + ": Mutually exclusive option: Ea and C" }); - } - taylor_series.C = -1 * object[validation::Ea].as() / constants::boltzmann; - } - if (object[validation::taylor_coefficients]) - { - taylor_series.taylor_coefficients = object[validation::taylor_coefficients].as>(); - } - - if (object[validation::name]) - { - taylor_series.name = object[validation::name].as(); - } - - std::vector requested_species; - for (const auto& spec : products.second) - { - requested_species.push_back(spec.species_name); - } - for (const auto& spec : reactants.second) - { - requested_species.push_back(spec.species_name); - } - - std::vector unknown_species = FindUnknownSpecies(requested_species, existing_species); - if (!unknown_species.empty()) - { - std::ostringstream oss; - - std::string line = std::to_string(object.Mark().line + 1); - std::string column = std::to_string(object.Mark().column + 1); - oss << line << ":" << column; - - if (object[validation::name]) - { - oss << " error: Reaction '" << object[validation::name].as() << "' requires unknown species: "; - } - else - { - oss << " error: Reaction requires unknown species: "; - } - - for (size_t i = 0; i < unknown_species.size(); i++) - { - oss << "'" << unknown_species[i] << "'"; - if (i != unknown_species.size() - 1) - { - oss << ", "; - } - } - - errors.push_back({ ConfigParseStatus::ReactionRequiresUnknownSpecies, oss.str() }); - } - - std::string gas_phase = object[validation::gas_phase].as(); - auto it = std::find_if( - existing_phases.begin(), - existing_phases.end(), - [&gas_phase](const auto& phase) { return phase.name == gas_phase; }); - if (it == existing_phases.end()) - { - std::string line = std::to_string(object[validation::gas_phase].Mark().line + 1); - std::string column = std::to_string(object[validation::gas_phase].Mark().column + 1); - errors.push_back({ ConfigParseStatus::UnknownPhase, line + ":" + column + ": Unknown phase: " + gas_phase }); - } - - taylor_series.gas_phase = gas_phase; - taylor_series.products = products.second; - taylor_series.reactants = reactants.second; - taylor_series.unknown_properties = GetComments(object); - reactions.taylor_series.push_back(taylor_series); - } - - return errors; - } - } // namespace v1 -} // namespace mechanism_configuration diff --git a/src/v1/reactions/ternary_chemical_activation.cpp b/src/v1/reactions/ternary_chemical_activation.cpp new file mode 100644 index 00000000..938bb663 --- /dev/null +++ b/src/v1/reactions/ternary_chemical_activation.cpp @@ -0,0 +1,113 @@ +// Copyright (C) 2023–2026 University Corporation for Atmospheric Research +// University of Illinois at Urbana-Champaign +// SPDX-License-Identifier: Apache-2.0 + +#include +#include +#include +#include +#include +#include +#include + +namespace mechanism_configuration +{ + namespace v1 + { + /// @brief Checks the structural schema of a YAML-defined Ternary ChemicalActivation reaction entry + /// Performs structural (schema) validation only; + /// and collects any errors found. + /// @param object The YAML node representing the reaction + /// @param existing_species Unused; semantic checks live in ValidateSemantics + /// @param existing_phases Unused; semantic checks live in ValidateSemantics + /// @return A list of validation errors, if any + Errors TernaryChemicalActivationParser::CheckSchema( + const YAML::Node& object, + const std::vector& existing_species, + const std::vector& existing_phases) + { + std::vector required_keys = { + keys::reactants, keys::products, keys::type, keys::gas_phase + }; + std::vector optional_keys = { keys::name, keys::k0_A, keys::k0_B, + keys::k0_C, keys::kinf_A, keys::kinf_B, + keys::kinf_C, keys::Fc, keys::N }; + Errors errors; + + auto schema_errors = mechanism_configuration::CheckSchema(object, required_keys, optional_keys); + if (!schema_errors.empty()) + { + errors.insert(errors.end(), schema_errors.begin(), schema_errors.end()); + return errors; + } + + // Reactants + schema_errors = CheckReactantsOrProductsSchema(object[keys::reactants]); + if (!schema_errors.empty()) + { + errors.insert(errors.end(), schema_errors.begin(), schema_errors.end()); + } + + // Products + schema_errors = CheckReactantsOrProductsSchema(object[keys::products]); + if (!schema_errors.empty()) + { + errors.insert(errors.end(), schema_errors.begin(), schema_errors.end()); + } + + // Semantic checks are performed by the version-neutral ValidateSemantics. + + return errors; + } + + void TernaryChemicalActivationParser::Parse(const YAML::Node& object, types::Reactions& reactions) + { + types::TernaryChemicalActivation ternary; + + ternary.gas_phase = object[keys::gas_phase].as(); + ternary.reactants = ParseReactionComponents(object, keys::reactants); + ternary.products = ParseReactionComponents(object, keys::products); + ternary.unknown_properties = GetComments(object); + + if (object[keys::k0_A]) + { + ternary.k0_A = object[keys::k0_A].as(); + } + if (object[keys::k0_B]) + { + ternary.k0_B = object[keys::k0_B].as(); + } + if (object[keys::k0_C]) + { + ternary.k0_C = object[keys::k0_C].as(); + } + if (object[keys::kinf_A]) + { + ternary.kinf_A = object[keys::kinf_A].as(); + } + if (object[keys::kinf_B]) + { + ternary.kinf_B = object[keys::kinf_B].as(); + } + if (object[keys::kinf_C]) + { + ternary.kinf_C = object[keys::kinf_C].as(); + } + if (object[keys::Fc]) + { + ternary.Fc = object[keys::Fc].as(); + } + if (object[keys::N]) + { + ternary.N = object[keys::N].as(); + } + if (object[keys::name]) + { + ternary.name = object[keys::name].as(); + } + + reactions.ternary_chemical_activation.emplace_back(std::move(ternary)); + } + + } // namespace v1 +} // namespace mechanism_configuration diff --git a/src/v1/reactions/ternary_chemical_activation_parser.cpp b/src/v1/reactions/ternary_chemical_activation_parser.cpp deleted file mode 100644 index 218aa2ee..00000000 --- a/src/v1/reactions/ternary_chemical_activation_parser.cpp +++ /dev/null @@ -1,102 +0,0 @@ -// Copyright (C) 2023–2026 University Corporation for Atmospheric Research -// University of Illinois at Urbana-Champaign -// SPDX-License-Identifier: Apache-2.0 - -#include -#include -#include -#include -#include -#include -#include - -namespace mechanism_configuration -{ - namespace v1 - { - Errors TernaryChemicalActivationParser::parse( - const YAML::Node& object, - const std::vector& existing_species, - const std::vector& existing_phases, - types::Reactions& reactions) - { - Errors errors; - - std::vector required_keys = { - validation::products, validation::reactants, validation::type, validation::gas_phase - }; - std::vector optional_keys = { validation::name, validation::k0_A, validation::k0_B, - validation::k0_C, validation::kinf_A, validation::kinf_B, - validation::kinf_C, validation::Fc, validation::N }; - - auto validate = ValidateSchema(object, required_keys, optional_keys); - errors.insert(errors.end(), validate.begin(), validate.end()); - if (validate.empty()) - { - auto products = ParseReactantsOrProducts(validation::products, object); - errors.insert(errors.end(), products.first.begin(), products.first.end()); - auto reactants = ParseReactantsOrProducts(validation::reactants, object); - errors.insert(errors.end(), reactants.first.begin(), reactants.first.end()); - - types::TernaryChemicalActivation parameters; - if (object[validation::k0_A]) - { - parameters.k0_A = object[validation::k0_A].as(); - } - if (object[validation::k0_B]) - { - parameters.k0_B = object[validation::k0_B].as(); - } - if (object[validation::k0_C]) - { - parameters.k0_C = object[validation::k0_C].as(); - } - if (object[validation::kinf_A]) - { - parameters.kinf_A = object[validation::kinf_A].as(); - } - if (object[validation::kinf_B]) - { - parameters.kinf_B = object[validation::kinf_B].as(); - } - if (object[validation::kinf_C]) - { - parameters.kinf_C = object[validation::kinf_C].as(); - } - if (object[validation::Fc]) - { - parameters.Fc = object[validation::Fc].as(); - } - if (object[validation::N]) - { - parameters.N = object[validation::N].as(); - } - - if (object[validation::name]) - { - parameters.name = object[validation::name].as(); - } - - std::string gas_phase = object[validation::gas_phase].as(); - auto it = std::find_if( - existing_phases.begin(), - existing_phases.end(), - [&gas_phase](const auto& phase) { return phase.name == gas_phase; }); - if (it == existing_phases.end()) - { - std::string line = std::to_string(object[validation::gas_phase].Mark().line + 1); - std::string column = std::to_string(object[validation::gas_phase].Mark().column + 1); - errors.push_back({ ConfigParseStatus::UnknownPhase, line + ":" + column + ": Unknown phase: " + gas_phase }); - } - - parameters.gas_phase = gas_phase; - parameters.reactants = reactants.second; - parameters.products = products.second; - parameters.unknown_properties = GetComments(object); - reactions.ternary_chemical_activation.push_back(parameters); - } - - return errors; - } - } // namespace v1 -} // namespace mechanism_configuration diff --git a/src/v1/reactions/troe.cpp b/src/v1/reactions/troe.cpp new file mode 100644 index 00000000..bbe59213 --- /dev/null +++ b/src/v1/reactions/troe.cpp @@ -0,0 +1,113 @@ +// Copyright (C) 2023–2026 University Corporation for Atmospheric Research +// University of Illinois at Urbana-Champaign +// SPDX-License-Identifier: Apache-2.0 + +#include +#include +#include +#include +#include +#include +#include + +namespace mechanism_configuration +{ + namespace v1 + { + /// @brief Checks the structural schema of a YAML-defined Troe reaction entry + /// Performs structural (schema) validation only; + /// and collects any errors found. + /// @param object The YAML node representing the reaction + /// @param existing_species Unused; semantic checks live in ValidateSemantics + /// @param existing_phases Unused; semantic checks live in ValidateSemantics + /// @return A list of validation errors, if any + Errors TroeParser::CheckSchema( + const YAML::Node& object, + const std::vector& existing_species, + const std::vector& existing_phases) + { + std::vector required_keys = { + keys::reactants, keys::products, keys::type, keys::gas_phase + }; + std::vector optional_keys = { keys::name, keys::k0_A, keys::k0_B, + keys::k0_C, keys::kinf_A, keys::kinf_B, + keys::kinf_C, keys::Fc, keys::N }; + Errors errors; + + auto schema_errors = mechanism_configuration::CheckSchema(object, required_keys, optional_keys); + if (!schema_errors.empty()) + { + errors.insert(errors.end(), schema_errors.begin(), schema_errors.end()); + return errors; + } + + // Reactants + schema_errors = CheckReactantsOrProductsSchema(object[keys::reactants]); + if (!schema_errors.empty()) + { + errors.insert(errors.end(), schema_errors.begin(), schema_errors.end()); + } + + // Products + schema_errors = CheckReactantsOrProductsSchema(object[keys::products]); + if (!schema_errors.empty()) + { + errors.insert(errors.end(), schema_errors.begin(), schema_errors.end()); + } + + // Semantic checks are performed by the version-neutral ValidateSemantics. + + return errors; + } + + void TroeParser::Parse(const YAML::Node& object, types::Reactions& reactions) + { + types::Troe troe; + + troe.gas_phase = object[keys::gas_phase].as(); + troe.reactants = ParseReactionComponents(object, keys::reactants); + troe.products = ParseReactionComponents(object, keys::products); + troe.unknown_properties = GetComments(object); + + if (object[keys::k0_A]) + { + troe.k0_A = object[keys::k0_A].as(); + } + if (object[keys::k0_B]) + { + troe.k0_B = object[keys::k0_B].as(); + } + if (object[keys::k0_C]) + { + troe.k0_C = object[keys::k0_C].as(); + } + if (object[keys::kinf_A]) + { + troe.kinf_A = object[keys::kinf_A].as(); + } + if (object[keys::kinf_B]) + { + troe.kinf_B = object[keys::kinf_B].as(); + } + if (object[keys::kinf_C]) + { + troe.kinf_C = object[keys::kinf_C].as(); + } + if (object[keys::Fc]) + { + troe.Fc = object[keys::Fc].as(); + } + if (object[keys::N]) + { + troe.N = object[keys::N].as(); + } + if (object[keys::name]) + { + troe.name = object[keys::name].as(); + } + + reactions.troe.emplace_back(std::move(troe)); + } + + } // namespace v1 +} // namespace mechanism_configuration diff --git a/src/v1/reactions/troe_parser.cpp b/src/v1/reactions/troe_parser.cpp deleted file mode 100644 index 6ebc5df2..00000000 --- a/src/v1/reactions/troe_parser.cpp +++ /dev/null @@ -1,141 +0,0 @@ -// Copyright (C) 2023–2026 University Corporation for Atmospheric Research -// University of Illinois at Urbana-Champaign -// SPDX-License-Identifier: Apache-2.0 - -#include -#include -#include -#include -#include -#include - -namespace mechanism_configuration -{ - namespace v1 - { - Errors TroeParser::parse( - const YAML::Node& object, - const std::vector& existing_species, - const std::vector& existing_phases, - types::Reactions& reactions) - { - Errors errors; - types::Troe troe; - - std::vector required_keys = { - validation::products, validation::reactants, validation::type, validation::gas_phase - }; - std::vector optional_keys = { validation::name, validation::k0_A, validation::k0_B, - validation::k0_C, validation::kinf_A, validation::kinf_B, - validation::kinf_C, validation::Fc, validation::N }; - - auto validate = ValidateSchema(object, required_keys, optional_keys); - errors.insert(errors.end(), validate.begin(), validate.end()); - if (validate.empty()) - { - auto products = ParseReactantsOrProducts(validation::products, object); - errors.insert(errors.end(), products.first.begin(), products.first.end()); - auto reactants = ParseReactantsOrProducts(validation::reactants, object); - errors.insert(errors.end(), reactants.first.begin(), reactants.first.end()); - - if (object[validation::k0_A]) - { - troe.k0_A = object[validation::k0_A].as(); - } - if (object[validation::k0_B]) - { - troe.k0_B = object[validation::k0_B].as(); - } - if (object[validation::k0_C]) - { - troe.k0_C = object[validation::k0_C].as(); - } - if (object[validation::kinf_A]) - { - troe.kinf_A = object[validation::kinf_A].as(); - } - if (object[validation::kinf_B]) - { - troe.kinf_B = object[validation::kinf_B].as(); - } - if (object[validation::kinf_C]) - { - troe.kinf_C = object[validation::kinf_C].as(); - } - if (object[validation::Fc]) - { - troe.Fc = object[validation::Fc].as(); - } - if (object[validation::N]) - { - troe.N = object[validation::N].as(); - } - - if (object[validation::name]) - { - troe.name = object[validation::name].as(); - } - - std::vector requested_species; - for (const auto& spec : products.second) - { - requested_species.push_back(spec.species_name); - } - for (const auto& spec : reactants.second) - { - requested_species.push_back(spec.species_name); - } - - std::vector unknown_species = FindUnknownSpecies(requested_species, existing_species); - if (!unknown_species.empty()) - { - std::ostringstream oss; - - std::string line = std::to_string(object.Mark().line + 1); - std::string column = std::to_string(object.Mark().column + 1); - oss << line << ":" << column; - - if (object[validation::name]) - { - oss << " error: Reaction '" << object[validation::name].as() << "' requires unknown species: "; - } - else - { - oss << " error: Reaction requires unknown species: "; - } - - for (size_t i = 0; i < unknown_species.size(); i++) - { - oss << "'" << unknown_species[i] << "'"; - if (i != unknown_species.size() - 1) - { - oss << ", "; - } - } - - errors.push_back({ ConfigParseStatus::ReactionRequiresUnknownSpecies, oss.str() }); - } - - std::string gas_phase = object[validation::gas_phase].as(); - auto it = std::find_if( - existing_phases.begin(), - existing_phases.end(), - [&gas_phase](const auto& phase) { return phase.name == gas_phase; }); - if (it == existing_phases.end()) - { - std::string line = std::to_string(object[validation::gas_phase].Mark().line + 1); - std::string column = std::to_string(object[validation::gas_phase].Mark().column + 1); - errors.push_back({ ConfigParseStatus::UnknownPhase, line + ":" + column + ": Unknown phase: " + gas_phase }); - } - - troe.gas_phase = gas_phase; - troe.products = products.second; - troe.reactants = reactants.second; - troe.unknown_properties = GetComments(object); - reactions.troe.push_back(troe); - } - - return errors; - } - } // namespace v1 -} // namespace mechanism_configuration diff --git a/src/v1/reactions/tunneling.cpp b/src/v1/reactions/tunneling.cpp new file mode 100644 index 00000000..a0608852 --- /dev/null +++ b/src/v1/reactions/tunneling.cpp @@ -0,0 +1,92 @@ +// Copyright (C) 2023–2026 University Corporation for Atmospheric Research +// University of Illinois at Urbana-Champaign +// SPDX-License-Identifier: Apache-2.0 + +#include +#include +#include +#include +#include +#include +#include + +namespace mechanism_configuration +{ + namespace v1 + { + /// @brief Checks the structural schema of a YAML-defined Tunneling reaction entry + /// Performs structural (schema) validation only; + /// and collects any errors found. + /// @param object The YAML node representing the reaction + /// @param existing_species Unused; semantic checks live in ValidateSemantics + /// @param existing_phases Unused; semantic checks live in ValidateSemantics + /// @return A list of validation errors, if any + Errors TunnelingParser::CheckSchema( + const YAML::Node& object, + const std::vector& existing_species, + const std::vector& existing_phases) + { + std::vector required_keys = { + keys::reactants, keys::products, keys::type, keys::gas_phase + }; + std::vector optional_keys = { keys::name, keys::A, keys::B, keys::C }; + + Errors errors; + + auto schema_errors = mechanism_configuration::CheckSchema(object, required_keys, optional_keys); + if (!schema_errors.empty()) + { + errors.insert(errors.end(), schema_errors.begin(), schema_errors.end()); + return errors; + } + + // Reactants + schema_errors = CheckReactantsOrProductsSchema(object[keys::reactants]); + if (!schema_errors.empty()) + { + errors.insert(errors.end(), schema_errors.begin(), schema_errors.end()); + } + + // Products + schema_errors = CheckReactantsOrProductsSchema(object[keys::products]); + if (!schema_errors.empty()) + { + errors.insert(errors.end(), schema_errors.begin(), schema_errors.end()); + } + + // Semantic checks are performed by the version-neutral ValidateSemantics. + + return errors; + } + + void TunnelingParser::Parse(const YAML::Node& object, types::Reactions& reactions) + { + types::Tunneling tunneling; + + tunneling.gas_phase = object[keys::gas_phase].as(); + tunneling.reactants = ParseReactionComponents(object, keys::reactants); + tunneling.products = ParseReactionComponents(object, keys::products); + tunneling.unknown_properties = GetComments(object); + + if (object[keys::A]) + { + tunneling.A = object[keys::A].as(); + } + if (object[keys::B]) + { + tunneling.B = object[keys::B].as(); + } + if (object[keys::C]) + { + tunneling.C = object[keys::C].as(); + } + if (object[keys::name]) + { + tunneling.name = object[keys::name].as(); + } + + reactions.tunneling.emplace_back(std::move(tunneling)); + } + + } // namespace v1 +} // namespace mechanism_configuration diff --git a/src/v1/reactions/tunneling_parser.cpp b/src/v1/reactions/tunneling_parser.cpp deleted file mode 100644 index 06b2a7ed..00000000 --- a/src/v1/reactions/tunneling_parser.cpp +++ /dev/null @@ -1,119 +0,0 @@ -// Copyright (C) 2023–2026 University Corporation for Atmospheric Research -// University of Illinois at Urbana-Champaign -// SPDX-License-Identifier: Apache-2.0 - -#include -#include -#include -#include -#include -#include - -namespace mechanism_configuration -{ - namespace v1 - { - Errors TunnelingParser::parse( - const YAML::Node& object, - const std::vector& existing_species, - const std::vector& existing_phases, - types::Reactions& reactions) - { - Errors errors; - types::Tunneling tunneling; - - std::vector required_keys = { - validation::products, validation::reactants, validation::type, validation::gas_phase - }; - std::vector optional_keys = { validation::name, validation::A, validation::B, validation::C }; - - auto validate = ValidateSchema(object, required_keys, optional_keys); - errors.insert(errors.end(), validate.begin(), validate.end()); - if (validate.empty()) - { - auto products = ParseReactantsOrProducts(validation::products, object); - errors.insert(errors.end(), products.first.begin(), products.first.end()); - auto reactants = ParseReactantsOrProducts(validation::reactants, object); - errors.insert(errors.end(), reactants.first.begin(), reactants.first.end()); - - if (object[validation::A]) - { - tunneling.A = object[validation::A].as(); - } - if (object[validation::B]) - { - tunneling.B = object[validation::B].as(); - } - if (object[validation::C]) - { - tunneling.C = object[validation::C].as(); - } - - if (object[validation::name]) - { - tunneling.name = object[validation::name].as(); - } - - std::vector requested_species; - for (const auto& spec : products.second) - { - requested_species.push_back(spec.species_name); - } - for (const auto& spec : reactants.second) - { - requested_species.push_back(spec.species_name); - } - - std::vector unknown_species = FindUnknownSpecies(requested_species, existing_species); - if (!unknown_species.empty()) - { - std::ostringstream oss; - - std::string line = std::to_string(object.Mark().line + 1); - std::string column = std::to_string(object.Mark().column + 1); - oss << line << ":" << column; - - if (object[validation::name]) - { - oss << " error: Reaction '" << object[validation::name].as() << "' requires unknown species: "; - } - else - { - oss << " error: Reaction requires unknown species: "; - } - - for (size_t i = 0; i < unknown_species.size(); i++) - { - oss << "'" << unknown_species[i] << "'"; - if (i != unknown_species.size() - 1) - { - oss << ", "; - } - } - - errors.push_back({ ConfigParseStatus::ReactionRequiresUnknownSpecies, oss.str() }); - } - - std::string gas_phase = object[validation::gas_phase].as(); - auto it = std::find_if( - existing_phases.begin(), - existing_phases.end(), - [&gas_phase](const auto& phase) { return phase.name == gas_phase; }); - if (it == existing_phases.end()) - { - std::string line = std::to_string(object[validation::gas_phase].Mark().line + 1); - std::string column = std::to_string(object[validation::gas_phase].Mark().column + 1); - errors.push_back({ ConfigParseStatus::UnknownPhase, line + ":" + column + ": Unknown phase: " + gas_phase }); - } - - tunneling.gas_phase = gas_phase; - tunneling.products = products.second; - tunneling.reactants = reactants.second; - tunneling.unknown_properties = GetComments(object); - reactions.tunneling.push_back(tunneling); - } - - return errors; - } - } // namespace v1 -} // namespace mechanism_configuration diff --git a/src/v1/reactions/user_defined.cpp b/src/v1/reactions/user_defined.cpp new file mode 100644 index 00000000..9418f4d0 --- /dev/null +++ b/src/v1/reactions/user_defined.cpp @@ -0,0 +1,86 @@ +// Copyright (C) 2023–2026 University Corporation for Atmospheric Research +// University of Illinois at Urbana-Champaign +// SPDX-License-Identifier: Apache-2.0 + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace mechanism_configuration +{ + namespace v1 + { + /// @brief Checks the structural schema of a YAML-defined User-defined reaction entry + /// Performs structural (schema) validation only; + /// and collects any errors found. + /// @param object The YAML node representing the reaction + /// @param existing_species Unused; semantic checks live in ValidateSemantics + /// @param existing_phases Unused; semantic checks live in ValidateSemantics + /// @return A list of validation errors, if any + Errors UserDefinedParser::CheckSchema( + const YAML::Node& object, + const std::vector& existing_species, + const std::vector& existing_phases) + { + std::vector required_keys = { + keys::reactants, keys::products, keys::type, keys::gas_phase + }; + std::vector optional_keys = { keys::name, keys::scaling_factor }; + + Errors errors; + + auto schema_errors = mechanism_configuration::CheckSchema(object, required_keys, optional_keys); + if (!schema_errors.empty()) + { + errors.insert(errors.end(), schema_errors.begin(), schema_errors.end()); + return errors; + } + + // Reactants + schema_errors = CheckReactantsOrProductsSchema(object[keys::reactants]); + if (!schema_errors.empty()) + { + errors.insert(errors.end(), schema_errors.begin(), schema_errors.end()); + } + + // Products + schema_errors = CheckReactantsOrProductsSchema(object[keys::products]); + if (!schema_errors.empty()) + { + errors.insert(errors.end(), schema_errors.begin(), schema_errors.end()); + } + + // Semantic checks are performed by the version-neutral ValidateSemantics. + + return errors; + } + + void UserDefinedParser::Parse(const YAML::Node& object, types::Reactions& reactions) + { + types::UserDefined user_defined; + + user_defined.reactants = ParseReactionComponents(object, keys::reactants); + user_defined.products = ParseReactionComponents(object, keys::products); + user_defined.gas_phase = object[keys::gas_phase].as(); + user_defined.unknown_properties = GetComments(object); + + if (object[keys::scaling_factor]) + { + user_defined.scaling_factor = object[keys::scaling_factor].as(); + } + + if (object[keys::name]) + { + user_defined.name = object[keys::name].as(); + } + + reactions.user_defined.emplace_back(std::move(user_defined)); + } + + } // namespace v1 +} // namespace mechanism_configuration diff --git a/src/v1/reactions/user_defined_parser.cpp b/src/v1/reactions/user_defined_parser.cpp deleted file mode 100644 index 4a6286b9..00000000 --- a/src/v1/reactions/user_defined_parser.cpp +++ /dev/null @@ -1,111 +0,0 @@ -// Copyright (C) 2023–2026 University Corporation for Atmospheric Research -// University of Illinois at Urbana-Champaign -// SPDX-License-Identifier: Apache-2.0 - -#include -#include -#include -#include -#include -#include - -namespace mechanism_configuration -{ - namespace v1 - { - Errors UserDefinedParser::parse( - const YAML::Node& object, - const std::vector& existing_species, - const std::vector& existing_phases, - types::Reactions& reactions) - { - Errors errors; - types::UserDefined user_defined; - - std::vector required_keys = { - validation::reactants, validation::products, validation::type, validation::gas_phase - }; - std::vector optional_keys = { validation::name, validation::scaling_factor }; - - auto validate = ValidateSchema(object, required_keys, optional_keys); - errors.insert(errors.end(), validate.begin(), validate.end()); - if (validate.empty()) - { - auto products = ParseReactantsOrProducts(validation::products, object); - errors.insert(errors.end(), products.first.begin(), products.first.end()); - auto reactants = ParseReactantsOrProducts(validation::reactants, object); - errors.insert(errors.end(), reactants.first.begin(), reactants.first.end()); - - if (object[validation::scaling_factor]) - { - user_defined.scaling_factor = object[validation::scaling_factor].as(); - } - - if (object[validation::name]) - { - user_defined.name = object[validation::name].as(); - } - - std::vector requested_species; - for (const auto& spec : products.second) - { - requested_species.push_back(spec.species_name); - } - for (const auto& spec : reactants.second) - { - requested_species.push_back(spec.species_name); - } - - std::vector unknown_species = FindUnknownSpecies(requested_species, existing_species); - if (!unknown_species.empty()) - { - std::ostringstream oss; - - std::string line = std::to_string(object.Mark().line + 1); - std::string column = std::to_string(object.Mark().column + 1); - oss << line << ":" << column; - - if (object[validation::name]) - { - oss << " error: Reaction '" << object[validation::name].as() << "' requires unknown species: "; - } - else - { - oss << " error: Reaction requires unknown species: "; - } - - for (size_t i = 0; i < unknown_species.size(); i++) - { - oss << "'" << unknown_species[i] << "'"; - if (i != unknown_species.size() - 1) - { - oss << ", "; - } - } - - errors.push_back({ ConfigParseStatus::ReactionRequiresUnknownSpecies, oss.str() }); - } - - std::string gas_phase = object[validation::gas_phase].as(); - auto it = std::find_if( - existing_phases.begin(), - existing_phases.end(), - [&gas_phase](const auto& phase) { return phase.name == gas_phase; }); - if (it == existing_phases.end()) - { - std::string line = std::to_string(object[validation::gas_phase].Mark().line + 1); - std::string column = std::to_string(object[validation::gas_phase].Mark().column + 1); - errors.push_back({ ConfigParseStatus::UnknownPhase, line + ":" + column + ": Unknown phase: " + gas_phase }); - } - - user_defined.gas_phase = gas_phase; - user_defined.products = products.second; - user_defined.reactants = reactants.second; - user_defined.unknown_properties = GetComments(object); - reactions.user_defined.push_back(user_defined); - } - - return errors; - } - } // namespace v1 -} // namespace mechanism_configuration diff --git a/src/v1/type_parsers.cpp b/src/v1/type_parsers.cpp new file mode 100644 index 00000000..19c6e155 --- /dev/null +++ b/src/v1/type_parsers.cpp @@ -0,0 +1,151 @@ +// Copyright (C) 2023–2026 University Corporation for Atmospheric Research +// University of Illinois at Urbana-Champaign +// SPDX-License-Identifier: Apache-2.0 + +#include "detail/v1/reaction_parsers.hpp" +#include "detail/v1/type_parsers.hpp" +#include "detail/v1/utils.hpp" +#include "detail/v1/keys.hpp" +#include + +namespace mechanism_configuration +{ + namespace v1 + { + std::vector ParseSpecies(const YAML::Node& objects) + { + std::vector all_species; + for (const auto& object : objects) + { + types::Species species; + + species.name = object[keys::name].as(); + + if (object[keys::tracer_type]) + species.tracer_type = object[keys::tracer_type].as(); + if (object[keys::absolute_tolerance]) + species.absolute_tolerance = object[keys::absolute_tolerance].as(); + if (object[keys::diffusion_coefficient]) + species.diffusion_coefficient = object[keys::diffusion_coefficient].as(); + if (object[keys::molecular_weight]) + species.molecular_weight = object[keys::molecular_weight].as(); + if (object[keys::henrys_law_constant_298]) + species.henrys_law_constant_298 = object[keys::henrys_law_constant_298].as(); + if (object[keys::henrys_law_constant_exponential_factor]) + species.henrys_law_constant_exponential_factor = + object[keys::henrys_law_constant_exponential_factor].as(); + if (object[keys::n_star]) + species.n_star = object[keys::n_star].as(); + if (object[keys::density]) + species.density = object[keys::density].as(); + if (object[keys::constant_concentration]) + species.constant_concentration = object[keys::constant_concentration].as(); + if (object[keys::constant_mixing_ratio]) + species.constant_mixing_ratio = object[keys::constant_mixing_ratio].as(); + if (object[keys::is_third_body]) + species.is_third_body = object[keys::is_third_body].as(); + + species.unknown_properties = GetComments(object); + + all_species.push_back(species); + } + return all_species; + } + + std::vector ParsePhases(const YAML::Node& objects) + { + std::vector all_phases; + for (const auto& object : objects) + { + types::Phase phase; + phase.name = object[keys::name].as(); + + std::vector species; + + for (const auto& spec : object[keys::species]) + { + types::PhaseSpecies phase_species; + + if (spec.IsScalar()) + { + // Shorthand: a bare string is the species name. + phase_species.name = spec.as(); + } + else + { + // Object form: a name plus optional properties. + phase_species.name = spec[keys::name].as(); + if (spec[keys::diffusion_coefficient]) + { + phase_species.diffusion_coefficient = spec[keys::diffusion_coefficient].as(); + } + phase_species.unknown_properties = GetComments(spec); + } + + species.emplace_back(phase_species); + } + + phase.species = species; + phase.unknown_properties = GetComments(object); + all_phases.emplace_back(phase); + } + + return all_phases; + } + + std::vector ParseReactionComponents(const YAML::Node& object, std::string_view key) + { + std::vector component_list; + for (const auto& elem : AsSequence(object[key])) + { + types::ReactionComponent component; + component.name = GetReactionComponentName(elem); + + // A bare-string component carries only its name; coefficients/comments + // are only present on the object form. + if (!elem.IsScalar()) + { + component.unknown_properties = GetComments(elem); + if (elem[keys::coefficient]) + { + component.coefficient = elem[keys::coefficient].as(); + } + } + + component_list.emplace_back(std::move(component)); + } + + return component_list; + }; + + types::ReactionComponent ParseReactionComponent(const YAML::Node& object, std::string_view key) + { + auto reaction_components = ParseReactionComponents(object, key); + + if (reaction_components.empty()) + { + return types::ReactionComponent(); + } + + return std::move(reaction_components.front()); + }; + + types::Reactions ParseReactions(const YAML::Node& objects) + { + auto& parsers = GetReactionParserMap(); + types::Reactions reactions; + + for (const auto& object : objects) + { + auto it = parsers.find(object[keys::type].as()); + if (it != parsers.end()) + { + it->second->Parse(object, reactions); + } + } + + return reactions; + } + + } // namespace v1 +} // namespace mechanism_configuration diff --git a/src/v1/type_schema.cpp b/src/v1/type_schema.cpp new file mode 100644 index 00000000..23d53312 --- /dev/null +++ b/src/v1/type_schema.cpp @@ -0,0 +1,156 @@ +// Copyright (C) 2023–2026 University Corporation for Atmospheric Research +// University of Illinois at Urbana-Champaign +// SPDX-License-Identifier: Apache-2.0 + +#include +#include +#include + +#include "detail/v1/reaction_parsers.hpp" +#include "detail/v1/type_schema.hpp" +#include "detail/v1/utils.hpp" +#include "detail/v1/keys.hpp" +#include "detail/check_schema.hpp" + +#include +#include + +namespace mechanism_configuration +{ + namespace v1 + { + Errors CheckSpeciesSchema(const YAML::Node& species_list) + { + const std::vector required_keys = { keys::name }; + const std::vector optional_keys = { keys::absolute_tolerance, + keys::diffusion_coefficient, + keys::molecular_weight, + keys::henrys_law_constant_298, + keys::henrys_law_constant_exponential_factor, + keys::n_star, + keys::density, + keys::tracer_type, + keys::constant_concentration, + keys::constant_mixing_ratio, + keys::is_third_body }; + // Structural validation only. Duplicate-species detection (a semantic check) is performed + // by the version-neutral ValidateSemantics. + Errors errors; + for (const auto& object : species_list) + { + auto schema_errors = CheckSchema(object, required_keys, optional_keys); + errors.insert(errors.end(), schema_errors.begin(), schema_errors.end()); + } + return errors; + } + + Errors CheckPhasesSchema(const YAML::Node& phases_list, const std::vector& existing_species) + { + // Phase + const std::vector required_keys = { keys::name, keys::species }; + const std::vector optional_keys = {}; + // PhaseSpecies + const std::vector species_required_keys = { keys::name }; + const std::vector species_optional_keys = { keys::diffusion_coefficient }; + + // Structural validation only. Duplicate detection, phase-species existence, and + // phase-membership (semantic checks) are performed by the version-neutral + // ValidateSemantics. existing_species is intentionally unused here. + (void)existing_species; + Errors errors; + for (const auto& object : AsSequence(phases_list)) + { + auto schema_errors = CheckSchema(object, required_keys, optional_keys); + errors.insert(errors.end(), schema_errors.begin(), schema_errors.end()); + + for (const auto& spec : object[keys::species]) + { + // A bare string is shorthand for a species name and needs no schema validation. + if (spec.IsScalar()) + continue; + auto species_schema_errors = CheckSchema(spec, species_required_keys, species_optional_keys); + errors.insert(errors.end(), species_schema_errors.begin(), species_schema_errors.end()); + } + } + return errors; + } + + Errors CheckReactantsOrProductsSchema(const YAML::Node& list) + { + const std::vector required_keys = {}; + const std::vector optional_keys = { keys::coefficient }; + // A component's species reference may use the canonical `name` or the legacy + // `species name` alias, but exactly one of them. + const std::vector> exactly_one_of = { + { keys::name, keys::species_name } + }; + + Errors errors; + + for (const auto& object : list) + { + auto schema_errors = CheckSchema(object, required_keys, optional_keys, exactly_one_of); + if (!schema_errors.empty()) + { + errors.insert(errors.end(), schema_errors.begin(), schema_errors.end()); + } + } + + return errors; + } + + Errors CheckReactionsSchema( + const YAML::Node& reactions_list, + const std::vector& existing_species, + const std::vector& existing_phases) + { + Errors errors; + + auto& parsers = GetReactionParserMap(); + + std::vector> valid_reactions; + + for (const auto& object : reactions_list) + { + if (!object[keys::type]) + { + ErrorLocation error_location{ object.Mark().line, object.Mark().column }; + std::string message = mc_fmt::format("{} error: Missing 'type' object in reaction.", error_location); + errors.push_back({ ErrorCode::RequiredKeyNotFound, message }); + continue; + } + + std::string type = object[keys::type].as(); + + auto it = parsers.find(type); + if (it == parsers.end()) + { + const auto& node = object[keys::type]; + ErrorLocation error_location{ node.Mark().line, node.Mark().column }; + + std::string message = mc_fmt::format("{} error: Unknown reaction type '{}' found.", error_location, type); + + errors.push_back({ ErrorCode::UnknownType, message }); + + continue; + } + valid_reactions.emplace_back(object, it->second.get()); + } + + if (!errors.empty()) + return errors; + + for (const auto& [reaction_node, parser] : valid_reactions) + { + auto schema_errors = parser->CheckSchema(reaction_node, existing_species, existing_phases); + if (!schema_errors.empty()) + { + errors.insert(errors.end(), schema_errors.begin(), schema_errors.end()); + } + } + + return errors; + } + + } // namespace v1 +} // namespace mechanism_configuration \ No newline at end of file diff --git a/src/v1/utils.cpp b/src/v1/utils.cpp index 08ad0cdf..de3f94c0 100644 --- a/src/v1/utils.cpp +++ b/src/v1/utils.cpp @@ -2,14 +2,51 @@ // University of Illinois at Urbana-Champaign // SPDX-License-Identifier: Apache-2.0 -#include -#include -#include +#include +#include + +#include "detail/v1/utils.hpp" +#include "detail/v1/keys.hpp" +#include "detail/check_schema.hpp" + +#include +#include +#include namespace mechanism_configuration { namespace v1 { + YAML::Node AsSequence(const YAML::Node& node) + { + if (node.IsSequence()) + return node; + + YAML::Node sequence; + sequence.push_back(node); + + return sequence; + } + + std::string GetReactionComponentName(const YAML::Node& component) + { + // A component may be given as a bare string (shorthand for its name), + // or as an object keyed by the canonical `name` or the legacy `species name`. + if (component.IsScalar()) + return component.as(); + if (component[keys::name]) + return component[keys::name].as(); + return component[keys::species_name].as(); + } + + void AppendFilePath(const std::string& config_path, Errors& errors) + { + for (auto& error : errors) + { + error.second = config_path + ":" + error.second; + } + } + std::unordered_map GetComments(const YAML::Node& object) { std::unordered_map unknown_properties; @@ -40,16 +77,5 @@ namespace mechanism_configuration return unknown_properties; } - std::vector GetSpeciesNames(const std::vector& phase_species) - { - std::vector names; - names.reserve(phase_species.size()); - for (const auto& species : phase_species) - { - names.push_back(species.name); - } - return names; - } - } // namespace v1 } // namespace mechanism_configuration diff --git a/src/validate.cpp b/src/validate.cpp new file mode 100644 index 00000000..e94572a2 --- /dev/null +++ b/src/validate.cpp @@ -0,0 +1,181 @@ +// Copyright (C) 2023–2026 University Corporation for Atmospheric Research +// University of Illinois at Urbana-Champaign +// SPDX-License-Identifier: Apache-2.0 + +#include +#include + +#include +#include +#include +#include +#include +#include + +namespace mechanism_configuration +{ + namespace + { + // Formats a message, prefixing "line:col error:" when a source location is known. + std::string Message(const std::optional& location, const std::string& body) + { + if (location) + return mc_fmt::format("{} error: {}", *location, body); + return "error: " + body; + } + + // Emits one error per occurrence of each name that appears more than once. + void ReportDuplicates( + const std::vector& refs, + ErrorCode code, + std::string_view what, + Errors& errors) + { + std::unordered_map counts; + for (const auto& ref : refs) + ++counts[ref.name]; + for (const auto& ref : refs) + { + if (counts[ref.name] > 1) + errors.push_back({ code, Message(ref.location, mc_fmt::format("Duplicate {} name '{}' found.", what, ref.name)) }); + } + } + } // namespace + + Errors ValidateSemantics(const semantics::Input& input) + { + Errors errors; + + // ---- Species ---------------------------------------------------------------------------- + std::unordered_set species_names; + for (const auto& s : input.species) + species_names.insert(s.name); + ReportDuplicates(input.species, ErrorCode::DuplicateSpeciesDetected, "species", errors); + + // ---- Phases ----------------------------------------------------------------------------- + std::unordered_map> phase_species; + std::vector phase_names; + for (const auto& phase : input.phases) + { + phase_names.push_back({ phase.name, phase.location }); + auto& registered = phase_species[phase.name]; + for (const auto& ps : phase.species) + { + registered.insert(ps.name); + if (!species_names.contains(ps.name)) + errors.push_back({ ErrorCode::PhaseRequiresUnknownSpecies, + Message(ps.location, mc_fmt::format("Unknown species name '{}' found in '{}' phase.", + ps.name, phase.name)) }); + } + ReportDuplicates(phase.species, ErrorCode::DuplicateSpeciesInPhaseDetected, "species", errors); + } + ReportDuplicates(phase_names, ErrorCode::DuplicatePhasesDetected, "phase", errors); + + // ---- Reactions -------------------------------------------------------------------------- + for (const auto& reaction : input.reactions) + { + const auto phase_it = phase_species.find(reaction.phase); + const bool phase_exists = phase_it != phase_species.end(); + if (!phase_exists) + errors.push_back({ ErrorCode::UnknownPhase, + Message(reaction.location, + mc_fmt::format("Unknown phase '{}' in '{}' reaction.", reaction.phase, reaction.type)) }); + + for (const auto& reactant : reaction.reactants) + { + if (!species_names.contains(reactant.name)) + errors.push_back({ ErrorCode::ReactionRequiresUnknownSpecies, + Message(reactant.location, mc_fmt::format("Unknown species '{}' used in '{}' reaction.", + reactant.name, reaction.type)) }); + else if (phase_exists && !phase_it->second.contains(reactant.name)) + errors.push_back({ ErrorCode::RequestedSpeciesNotRegisteredInPhase, + Message(reactant.location, + mc_fmt::format("Species '{}' used in '{}' is not defined in the '{}' phase.", + reactant.name, reaction.type, reaction.phase)) }); + } + for (const auto& product : reaction.products) + { + if (!species_names.contains(product.name)) + errors.push_back({ ErrorCode::ReactionRequiresUnknownSpecies, + Message(product.location, mc_fmt::format("Unknown species '{}' used in '{}' reaction.", + product.name, reaction.type)) }); + } + } + + return errors; + } + + namespace + { + // Builds a location-free list of component references from a struct component list. + std::vector Refs(const std::vector& components) + { + std::vector refs; + refs.reserve(components.size()); + for (const auto& c : components) + refs.push_back({ c.name, std::nullopt }); + return refs; + } + + semantics::ReactionRef ReactionRefOf( + std::string_view type, + const std::string& phase, + std::vector reactants, + std::vector products) + { + return semantics::ReactionRef{ std::string(type), phase, std::move(reactants), std::move(products), std::nullopt }; + } + } // namespace + + Errors Validate(const Mechanism& mechanism) + { + semantics::Input input; + + for (const auto& s : mechanism.species) + input.species.push_back({ s.name, std::nullopt }); + + for (const auto& phase : mechanism.phases) + { + semantics::PhaseRef pr{ phase.name, {}, std::nullopt }; + for (const auto& ps : phase.species) + pr.species.push_back({ ps.name, std::nullopt }); + input.phases.push_back(std::move(pr)); + } + + const auto& r = mechanism.reactions; + auto add = [&](std::string_view type, const std::string& phase, + std::vector reactants, std::vector products) + { input.reactions.push_back(ReactionRefOf(type, phase, std::move(reactants), std::move(products))); }; + + for (const auto& x : r.arrhenius) + add("ARRHENIUS", x.gas_phase, Refs(x.reactants), Refs(x.products)); + for (const auto& x : r.troe) + add("TROE", x.gas_phase, Refs(x.reactants), Refs(x.products)); + for (const auto& x : r.ternary_chemical_activation) + add("TERNARY_CHEMICAL_ACTIVATION", x.gas_phase, Refs(x.reactants), Refs(x.products)); + for (const auto& x : r.tunneling) + add("TUNNELING", x.gas_phase, Refs(x.reactants), Refs(x.products)); + for (const auto& x : r.taylor_series) + add("TAYLOR_SERIES", x.gas_phase, Refs(x.reactants), Refs(x.products)); + for (const auto& x : r.user_defined) + add("USER_DEFINED", x.gas_phase, Refs(x.reactants), Refs(x.products)); + for (const auto& x : r.lambda_rate_constant) + add("LAMBDA_RATE_CONSTANT", x.gas_phase, Refs(x.reactants), Refs(x.products)); + for (const auto& x : r.emission) + add("EMISSION", x.gas_phase, {}, Refs(x.products)); + for (const auto& x : r.first_order_loss) + add("FIRST_ORDER_LOSS", x.gas_phase, Refs({ x.reactants }), Refs(x.products)); + for (const auto& x : r.photolysis) + add("PHOTOLYSIS", x.gas_phase, Refs({ x.reactants }), Refs(x.products)); + for (const auto& x : r.surface) + add("SURFACE", x.gas_phase, Refs({ x.gas_phase_species }), Refs(x.gas_phase_products)); + for (const auto& x : r.branched) + { + std::vector products = x.alkoxy_products; + products.insert(products.end(), x.nitrate_products.begin(), x.nitrate_products.end()); + add("BRANCHED", x.gas_phase, Refs(x.reactants), Refs(products)); + } + + return ValidateSemantics(input); + } +} // namespace mechanism_configuration diff --git a/src/version.hpp.in b/src/version.hpp.in index 9dcea9fe..5b77108d 100644 --- a/src/version.hpp.in +++ b/src/version.hpp.in @@ -1,3 +1,7 @@ +// Copyright (C) 2023–2026 University Corporation for Atmospheric Research +// University of Illinois at Urbana-Champaign +// SPDX-License-Identifier: Apache-2.0 + // clang-format off #pragma once diff --git a/test/integration/CMakeLists.txt b/test/integration/CMakeLists.txt index f07095ca..a5f00da1 100644 --- a/test/integration/CMakeLists.txt +++ b/test/integration/CMakeLists.txt @@ -10,4 +10,32 @@ create_standard_test(NAME parser SOURCES test_parser.cpp) create_standard_test(NAME v0_parser SOURCES test_v0_parser.cpp) create_standard_test(NAME v1_parser SOURCES test_v1_parser.cpp) create_standard_test(NAME v1_read_from_file_configs SOURCES test_v1_read_from_file_configs.cpp) -create_standard_test(NAME development_parser SOURCES test_development_parser.cpp) + +################################################################################ +# README integration test +# Extract the first ```cpp ... ``` code block from README.md at configure time +# and compile it as a standalone integration test. + +file(READ "${PROJECT_SOURCE_DIR}/README.md" _readme_content) + +string(FIND "${_readme_content}" "```cpp\n" _fence_start) +if(_fence_start EQUAL -1) + message(FATAL_ERROR "README integration test: could not find opening ```cpp fence in README.md") +endif() +math(EXPR _code_start "${_fence_start} + 7") # skip "```cpp\n" (7 chars) +string(SUBSTRING "${_readme_content}" ${_code_start} -1 _after_fence) + +string(FIND "${_after_fence}" "\n```" _fence_end) +if(_fence_end EQUAL -1) + message(FATAL_ERROR "README integration test: could not find closing ``` fence in README.md") +endif() +string(SUBSTRING "${_after_fence}" 0 ${_fence_end} _readme_example_code) + +set(_readme_example_dir "${CMAKE_BINARY_DIR}/readme_example") +set(_readme_example_src "${_readme_example_dir}/main.cpp") +file(MAKE_DIRECTORY "${_readme_example_dir}") +file(WRITE "${_readme_example_src}" "${_readme_example_code}") + +add_executable(test_readme_example "${_readme_example_src}") +target_link_libraries(test_readme_example PUBLIC musica::mechanism_configuration) +add_mech_config_test(readme_example test_readme_example "" "${CMAKE_BINARY_DIR}") diff --git a/test/integration/test_development_parser.cpp b/test/integration/test_development_parser.cpp deleted file mode 100644 index 9e1aae9a..00000000 --- a/test/integration/test_development_parser.cpp +++ /dev/null @@ -1,100 +0,0 @@ -#include -#include - -#include - -using namespace mechanism_configuration; - -TEST(ParseDevFullConfig, ParseValidConfig) -{ - development::Parser parser; - - std::vector extensions = { ".json", ".yaml" }; - - for (auto& extension : extensions) - { - std::string path = "examples/development/full_configuration" + extension; - YAML::Node object = parser.FileToYaml(path); - - auto errors = parser.Validate(object); - EXPECT_EQ(errors.size(), 0) << "Validation errors were: " << errors.size(); - - auto mechanism = parser.Parse(object); - - EXPECT_EQ(mechanism.name, "Full Configuration"); - EXPECT_EQ(mechanism.species.size(), 11); - EXPECT_EQ(mechanism.phases.size(), 4); - - EXPECT_EQ(mechanism.models.gas_model.type, "GAS_PHASE"); - EXPECT_EQ(mechanism.models.modal_model.modes.size(), 2); - - EXPECT_EQ(mechanism.reactions.aqueous_equilibrium.size(), 1); - EXPECT_EQ(mechanism.reactions.arrhenius.size(), 2); - EXPECT_EQ(mechanism.reactions.branched.size(), 1); - EXPECT_EQ(mechanism.reactions.condensed_phase_arrhenius.size(), 2); - EXPECT_EQ(mechanism.reactions.condensed_phase_photolysis.size(), 1); - EXPECT_EQ(mechanism.reactions.emission.size(), 1); - EXPECT_EQ(mechanism.reactions.first_order_loss.size(), 1); - EXPECT_EQ(mechanism.reactions.henrys_law.size(), 1); - EXPECT_EQ(mechanism.reactions.photolysis.size(), 1); - EXPECT_EQ(mechanism.reactions.simpol_phase_transfer.size(), 1); - EXPECT_EQ(mechanism.reactions.surface.size(), 1); - EXPECT_EQ(mechanism.reactions.taylor_series.size(), 1); - EXPECT_EQ(mechanism.reactions.ternary_chemical_activation.size(), 1); - EXPECT_EQ(mechanism.reactions.troe.size(), 1); - EXPECT_EQ(mechanism.reactions.tunneling.size(), 1); - EXPECT_EQ(mechanism.reactions.user_defined.size(), 1); - EXPECT_EQ(mechanism.reactions.wet_deposition.size(), 1); - - EXPECT_EQ(mechanism.species[1].constant_concentration.has_value(), true); - EXPECT_EQ(mechanism.species[1].constant_concentration.value(), 1.0e19); - EXPECT_EQ(mechanism.species[2].is_third_body.has_value(), true); - EXPECT_EQ(mechanism.species[2].is_third_body.value(), true); - EXPECT_EQ(mechanism.species[4].constant_mixing_ratio.has_value(), true); - EXPECT_EQ(mechanism.species[4].constant_mixing_ratio.value(), 1.0e-6); - - EXPECT_EQ(mechanism.version.major, 2); - EXPECT_EQ(mechanism.version.minor, 0); - EXPECT_EQ(mechanism.version.patch, 0); - } -} - -TEST(ParseDevFullConfig, ReportsBadFiles) -{ - development::Parser parser; - std::string path = "bad_path.yaml"; - - try - { - YAML::Node object = parser.FileToYaml(path); - FAIL() << "Expected std::runtime_error"; - } - catch (const std::runtime_error& e) - { - std::string error_msg(e.what()); - EXPECT_NE(error_msg.find("does not exist or is not a regular file"), std::string::npos) - << "Error message was: " << error_msg; - - std::cout << error_msg << std::endl; - } -} - -TEST(ParseDevFullConfig, ReportsDirectory) -{ - development::Parser parser; - std::string path = "examples/"; - - try - { - YAML::Node object = parser.FileToYaml(path); - FAIL() << "Expected std::runtime_error"; - } - catch (const std::runtime_error& e) - { - std::string error_msg(e.what()); - EXPECT_NE(error_msg.find("does not exist or is not a regular file"), std::string::npos) - << "Error message was: " << error_msg; - - std::cout << error_msg << std::endl; - } -} diff --git a/test/integration/test_parser.cpp b/test/integration/test_parser.cpp index 9daf78ef..a6cb717e 100644 --- a/test/integration/test_parser.cpp +++ b/test/integration/test_parser.cpp @@ -1,124 +1,73 @@ -#include -#include +// Copyright (C) 2023–2026 University Corporation for Atmospheric Research +// University of Illinois at Urbana-Champaign +// SPDX-License-Identifier: Apache-2.0 + +#include #include -TEST(UniversalParser, ConfigurationWithoutVersionFallsbackToV0) -{ - mechanism_configuration::UniversalParser parser; - std::vector extensions = { ".yaml", ".json" }; - for (auto& extension : extensions) - { - std::string path = "examples/v0/config" + extension; - auto parsed = parser.Parse(path); - EXPECT_TRUE(parsed); +#include +#include +#include - EXPECT_EQ(parsed.mechanism->version.major, 0); - EXPECT_EQ(parsed.mechanism->version.minor, 0); - EXPECT_EQ(parsed.mechanism->version.patch, 0); - } -} +using namespace mechanism_configuration; -TEST(UniversalParser, ParsesFullV1Configuration) +TEST(Parse, ConfigurationWithoutVersionFallsBackToV0) { - mechanism_configuration::UniversalParser parser; - std::vector extensions = { ".json", ".yaml" }; - for (auto& extension : extensions) + for (const auto& extension : { std::string(".yaml"), std::string(".json") }) { - std::string path = "examples/v1/full_configuration" + extension; - auto parsed = parser.Parse(path); - if (!parsed) - { - std::cout << "Errors: " << std::endl; - for (const auto& error : parsed.errors) - { - std::cout << error.second << std::endl; - } - } + auto parsed = Parse("examples/v0/config" + extension); EXPECT_TRUE(parsed); - - EXPECT_EQ(parsed.mechanism->version.major, 1); - EXPECT_EQ(parsed.mechanism->version.minor, 0); - EXPECT_EQ(parsed.mechanism->version.patch, 0); + if (parsed) + EXPECT_EQ(parsed->version.major, 0); } } -TEST(UniversalParser, ParsesFullDevConfiguration) +TEST(Parse, ParsesFullV1Configuration) { - mechanism_configuration::UniversalParser parser; - std::vector extensions = { ".json", ".yaml" }; - for (auto& extension : extensions) + for (const auto& extension : { std::string(".json"), std::string(".yaml") }) { - std::string path = "examples/development/full_configuration" + extension; - auto parsed = parser.Parse(path); + auto parsed = Parse("examples/v1/full_configuration" + extension); if (!parsed) - { - std::cout << "Errors: " << std::endl; - for (const auto& error : parsed.errors) - { - std::cout << error.second << std::endl; - } - } + for (const auto& [code, message] : parsed.error()) + std::cout << message << std::endl; EXPECT_TRUE(parsed); - - EXPECT_EQ(parsed.mechanism->version.major, 2); - EXPECT_EQ(parsed.mechanism->version.minor, 0); - EXPECT_EQ(parsed.mechanism->version.patch, 0); + if (parsed) + EXPECT_EQ(parsed->version.major, 1); } } -TEST(UniversalParser, ParserReportsBadFiles) +TEST(Parse, ReportsMissingFile) { - mechanism_configuration::UniversalParser parser; - std::vector extensions = { ".yaml", ".json" }; - for (auto& extension : extensions) + for (const auto& extension : { std::string(".yaml"), std::string(".json") }) { - std::string path = "examples/_missing_configuration" + extension; - auto parsed = parser.Parse(path); + auto parsed = Parse("examples/_missing_configuration" + extension); EXPECT_FALSE(parsed); - EXPECT_EQ(parsed.errors.size(), 1); - EXPECT_EQ(parsed.errors[0].first, mechanism_configuration::ConfigParseStatus::FileNotFound); + ASSERT_EQ(parsed.error().size(), 1); + EXPECT_EQ(parsed.error()[0].first, ErrorCode::FileNotFound); } } -TEST(UniversalParser, ParseUnsupportedVersion) +TEST(Parse, ReportsUnsupportedVersion) { - using namespace mechanism_configuration; + auto parsed = Parse("integration_configs/invalid_version.yaml"); + EXPECT_FALSE(parsed); - UniversalParser parser; - auto parsed = parser.Parse("integration_configs/invalid_version.yaml"); - EXPECT_EQ(parsed.errors.size(), 1); - - std::multiset expected = { ConfigParseStatus::InvalidVersion }; - std::multiset actual; - for (const auto& [status, message] : parsed.errors) + bool found_invalid_version = false; + for (const auto& [code, message] : parsed.error()) { - actual.insert(status); - std::cout << message << " " << configParseStatusToString(status) << std::endl; + if (code == ErrorCode::InvalidVersion) + found_invalid_version = true; + std::cout << message << " " << ErrorCodeToString(code) << std::endl; } - EXPECT_EQ(actual, expected); + EXPECT_TRUE(found_invalid_version); } -TEST(UniversalParser, ParsesV0DirectoryConfiguration) +TEST(Parse, ParsesV0DirectoryConfiguration) { - // Test that v0 parser can handle directory-based configurations - mechanism_configuration::UniversalParser parser; - - std::string directory_path = "examples/v0/"; - auto parsed = parser.Parse(directory_path); + // A directory is treated as a version-0 (CAMP) configuration. + auto parsed = Parse(std::filesystem::path("examples/v0/")); EXPECT_TRUE(parsed); - EXPECT_EQ(parsed.mechanism->version.major, 0); - EXPECT_EQ(parsed.mechanism->version.minor, 0); - EXPECT_EQ(parsed.mechanism->version.patch, 0); + if (parsed) + EXPECT_EQ(parsed->version.major, 0); } - -TEST(UniversalParser, RejectsDirectoryForV1Configuration) -{ - // Test v1 and upper version parsers do not accept directories - // V0 parser will attempt to parse a directory, but if the directory - // contains higher version files, it should throw an exception - mechanism_configuration::UniversalParser parser; - - std::string directory_path = "examples/v1"; - EXPECT_THROW({ auto parsed = parser.Parse(directory_path); }, std::exception); -} \ No newline at end of file diff --git a/test/integration/test_v0_parser.cpp b/test/integration/test_v0_parser.cpp index 1e709e1b..9ff1b36f 100644 --- a/test/integration/test_v0_parser.cpp +++ b/test/integration/test_v0_parser.cpp @@ -1,21 +1,25 @@ -#include -#include +// Copyright (C) 2023–2026 University Corporation for Atmospheric Research +// University of Illinois at Urbana-Champaign +// SPDX-License-Identifier: Apache-2.0 + +#include "detail/v0/parser.hpp" #include +#include +#include + using namespace mechanism_configuration; -TEST(ParserBase, ParsesFullv0Configuration) +TEST(V0Parser, ParsesFullV0Configuration) { v0::Parser parser; - std::vector extensions = { ".yaml", ".json" }; - for (auto& extension : extensions) + for (const auto& extension : { std::string(".yaml"), std::string(".json") }) { - std::string path = "examples/v0/config" + extension; - auto parsed = parser.Parse(path); - EXPECT_TRUE(parsed); + auto parsed = parser.Parse("examples/v0/config" + extension); + ASSERT_TRUE(parsed); - v0::types::Mechanism mechanism = *parsed; + Mechanism mechanism = *parsed; EXPECT_EQ(mechanism.reactions.user_defined.size(), 4); EXPECT_EQ(mechanism.reactions.arrhenius.size(), 1); EXPECT_EQ(mechanism.reactions.troe.size(), 1); @@ -25,23 +29,17 @@ TEST(ParserBase, ParsesFullv0Configuration) EXPECT_EQ(mechanism.reactions.surface.size(), 1); EXPECT_EQ(mechanism.version.major, 0); - EXPECT_EQ(mechanism.version.minor, 0); - EXPECT_EQ(mechanism.version.patch, 0); } } -TEST(ParserBase, ConfigPathIsDirectory) +TEST(V0Parser, ConfigPathIsDirectory) { v0::Parser parser; - std::string path = "examples/v0"; - auto parsed = parser.Parse(path); - EXPECT_TRUE(parsed); + auto parsed = parser.Parse(std::filesystem::path("examples/v0")); + ASSERT_TRUE(parsed); - v0::types::Mechanism mechanism = *parsed; + Mechanism mechanism = *parsed; EXPECT_EQ(mechanism.version.major, 0); - EXPECT_EQ(mechanism.version.minor, 0); - EXPECT_EQ(mechanism.version.patch, 0); - EXPECT_EQ(mechanism.reactions.user_defined.size(), 4); EXPECT_EQ(mechanism.reactions.arrhenius.size(), 1); EXPECT_EQ(mechanism.reactions.troe.size(), 1); @@ -51,16 +49,14 @@ TEST(ParserBase, ConfigPathIsDirectory) EXPECT_EQ(mechanism.reactions.surface.size(), 1); } -TEST(ParserBase, ParserReportsBadFiles) +TEST(V0Parser, ReportsMissingFile) { v0::Parser parser; - std::vector extensions = { ".yaml", ".json" }; - for (auto& extension : extensions) + for (const auto& extension : { std::string(".yaml"), std::string(".json") }) { - std::string path = "examples/_missing_configuration" + extension; - auto parsed = parser.Parse(path); + auto parsed = parser.Parse("examples/_missing_configuration" + extension); EXPECT_FALSE(parsed); - EXPECT_EQ(parsed.errors.size(), 1); - EXPECT_EQ(parsed.errors[0].first, ConfigParseStatus::FileNotFound); + ASSERT_EQ(parsed.error().size(), 1); + EXPECT_EQ(parsed.error()[0].first, ErrorCode::FileNotFound); } } diff --git a/test/integration/test_v1_parser.cpp b/test/integration/test_v1_parser.cpp index 1e16d985..fe7658aa 100644 --- a/test/integration/test_v1_parser.cpp +++ b/test/integration/test_v1_parser.cpp @@ -1,78 +1,27 @@ -#include -#include +// Copyright (C) 2023–2026 University Corporation for Atmospheric Research +// University of Illinois at Urbana-Champaign +// SPDX-License-Identifier: Apache-2.0 + +#include +#include "detail/v1/parser.hpp" #include #include -using namespace mechanism_configuration; - -TEST(ParserBase, ParsesFullV1Configuration) -{ - v1::Parser parser; - std::vector extensions = { ".json" }; - for (auto& extension : extensions) - { - std::string path = "examples/v1/full_configuration" + extension; - auto parsed = parser.Parse(path); - EXPECT_TRUE(parsed); - v1::types::Mechanism mechanism = *parsed; - EXPECT_EQ(mechanism.name, "Full Configuration"); - EXPECT_EQ(mechanism.species.size(), 7); - EXPECT_EQ(mechanism.phases.size(), 1); +#include +#include - EXPECT_EQ(mechanism.reactions.arrhenius.size(), 2); - EXPECT_EQ(mechanism.reactions.branched.size(), 1); - EXPECT_EQ(mechanism.reactions.emission.size(), 1); - EXPECT_EQ(mechanism.reactions.first_order_loss.size(), 1); - EXPECT_EQ(mechanism.reactions.photolysis.size(), 1); - EXPECT_EQ(mechanism.reactions.surface.size(), 1); - EXPECT_EQ(mechanism.reactions.taylor_series.size(), 1); - EXPECT_EQ(mechanism.reactions.troe.size(), 1); - EXPECT_EQ(mechanism.reactions.ternary_chemical_activation.size(), 1); - EXPECT_EQ(mechanism.reactions.tunneling.size(), 1); - EXPECT_EQ(mechanism.reactions.user_defined.size(), 1); - - EXPECT_EQ(mechanism.species[1].constant_concentration.has_value(), true); - EXPECT_EQ(mechanism.species[1].constant_concentration.value(), 1.0e19); - EXPECT_EQ(mechanism.species[2].constant_mixing_ratio.has_value(), true); - EXPECT_EQ(mechanism.species[2].constant_mixing_ratio.value(), 1.0e-20); - EXPECT_EQ(mechanism.species[3].is_third_body.has_value(), true); - EXPECT_EQ(mechanism.species[3].is_third_body.value(), true); - - EXPECT_EQ(mechanism.version.major, 1); - EXPECT_EQ(mechanism.version.minor, 0); - EXPECT_EQ(mechanism.version.patch, 0); - } -} +using namespace mechanism_configuration; -TEST(ParserBase, ParserReportsBadFiles) +namespace { - v1::Parser parser; - std::vector extensions = { ".yaml", ".json" }; - for (auto& extension : extensions) + // Parses an in-memory v1 document through the engine (validate, then build). + std::expected ParseString(const std::string& content) { - std::string path = "examples/_missing_configuration" + extension; - auto parsed = parser.Parse(path); - EXPECT_FALSE(parsed); - EXPECT_EQ(parsed.errors.size(), 1); - EXPECT_EQ(parsed.errors[0].first, ConfigParseStatus::FileNotFound); + return v1::Parser{}.Parse(content); } -} -TEST(ParserBase, ParserReportsDirectory) -{ - v1::Parser parser; - std::string path = "examples/"; - auto parsed = parser.Parse(path); - EXPECT_FALSE(parsed); - EXPECT_EQ(parsed.errors.size(), 1); - EXPECT_EQ(parsed.errors[0].first, ConfigParseStatus::FileNotFound); -} - -TEST(ParserBase, CanParseFromYamlString) -{ - v1::Parser parser; - std::string content = R"( + const std::string kYamlConfig = R"( version: 1.0.0 name: Simple Configuration species: @@ -87,11 +36,6 @@ name: Simple Configuration - type: ARRHENIUS name: my arrhenius gas phase: gas - A: 32.1 - B: -2.3 - C: 102.3 - D: 63.4 - E: -1.3 reactants: - species name: A coefficient: 1 @@ -99,128 +43,79 @@ name: Simple Configuration - species name: B coefficient: 1 )"; +} // namespace - auto parsed = parser.ParseFromString(content); - EXPECT_TRUE(parsed); +TEST(V1Parser, ParsesFullV1Configuration) +{ + auto parsed = Parse("examples/v1/full_configuration.json"); if (!parsed) - { - for (const auto& error : parsed.errors) - { - std::cerr << "Error: " << configParseStatusToString(error.first) << " - " << error.second << std::endl; - } - } - v1::types::Mechanism mechanism = *parsed; - EXPECT_EQ(mechanism.name, "Simple Configuration"); - EXPECT_EQ(mechanism.species.size(), 2); + for (const auto& [code, message] : parsed.error()) + std::cout << message << std::endl; + ASSERT_TRUE(parsed); + + const Mechanism& mechanism = *parsed; + EXPECT_EQ(mechanism.name, "Full Configuration"); + EXPECT_EQ(mechanism.species.size(), 7); EXPECT_EQ(mechanism.phases.size(), 1); - EXPECT_EQ(mechanism.reactions.arrhenius.size(), 1); + + EXPECT_EQ(mechanism.reactions.arrhenius.size(), 2); + EXPECT_EQ(mechanism.reactions.branched.size(), 1); + EXPECT_EQ(mechanism.reactions.emission.size(), 1); + EXPECT_EQ(mechanism.reactions.first_order_loss.size(), 1); + EXPECT_EQ(mechanism.reactions.photolysis.size(), 1); + EXPECT_EQ(mechanism.reactions.surface.size(), 1); + EXPECT_EQ(mechanism.reactions.taylor_series.size(), 1); + EXPECT_EQ(mechanism.reactions.troe.size(), 1); + EXPECT_EQ(mechanism.reactions.ternary_chemical_activation.size(), 1); + EXPECT_EQ(mechanism.reactions.tunneling.size(), 1); + EXPECT_EQ(mechanism.reactions.user_defined.size(), 1); + EXPECT_EQ(mechanism.version.major, 1); - EXPECT_EQ(mechanism.version.minor, 0); - EXPECT_EQ(mechanism.version.patch, 0); } -TEST(ParserBase, CanParseFromJsonString) +TEST(V1Parser, ReportsMissingFile) { - v1::Parser parser; - std::string content = R"({ + for (const auto& extension : { std::string(".yaml"), std::string(".json") }) + { + auto parsed = Parse("examples/_missing_configuration" + extension); + EXPECT_FALSE(parsed); + ASSERT_EQ(parsed.error().size(), 1); + EXPECT_EQ(parsed.error()[0].first, ErrorCode::FileNotFound); + } +} + +TEST(V1Parser, CanParseFromYamlString) +{ + auto parsed = ParseString(kYamlConfig); + ASSERT_TRUE(parsed); + EXPECT_EQ(parsed->name, "Simple Configuration"); + EXPECT_EQ(parsed->species.size(), 2); + EXPECT_EQ(parsed->phases.size(), 1); + EXPECT_EQ(parsed->reactions.arrhenius.size(), 1); + EXPECT_EQ(parsed->version.major, 1); +} + +TEST(V1Parser, CanParseFromJsonString) +{ + const std::string content = R"({ "version": "1.0.0", "name": "Simple Configuration", - "species": [ - { "name": "A" }, - { "name": "B" } - ], - "phases": [ - { - "name": "gas", - "species": [ {"name": "A"}, {"name": "B"} ] - } - ], + "species": [ { "name": "A" }, { "name": "B" } ], + "phases": [ { "name": "gas", "species": [ {"name": "A"}, {"name": "B"} ] } ], "reactions": [ { "type": "ARRHENIUS", "name": "my arrhenius", "gas phase": "gas", - "A": 32.1, - "B": -2.3, - "C": 102.3, - "D": 63.4, - "E": -1.3, - "reactants": [ - { - "species name": "A", - "coefficient": 1 - } - ], - "products": [ - { - "species name": "B", - "coefficient": 1 - } - ] + "reactants": [ { "species name": "A", "coefficient": 1 } ], + "products": [ { "species name": "B", "coefficient": 1 } ] } ] })"; - - auto parsed = parser.ParseFromString(content); - EXPECT_TRUE(parsed); - if (!parsed) - { - for (const auto& error : parsed.errors) - { - std::cerr << "Error: " << configParseStatusToString(error.first) << " - " << error.second << std::endl; - } - } - v1::types::Mechanism mechanism = *parsed; - EXPECT_EQ(mechanism.name, "Simple Configuration"); - EXPECT_EQ(mechanism.species.size(), 2); - EXPECT_EQ(mechanism.phases.size(), 1); - EXPECT_EQ(mechanism.reactions.arrhenius.size(), 1); - EXPECT_EQ(mechanism.version.major, 1); - EXPECT_EQ(mechanism.version.minor, 0); - EXPECT_EQ(mechanism.version.patch, 0); + auto parsed = ParseString(content); + ASSERT_TRUE(parsed); + EXPECT_EQ(parsed->name, "Simple Configuration"); + EXPECT_EQ(parsed->species.size(), 2); + EXPECT_EQ(parsed->reactions.arrhenius.size(), 1); + EXPECT_EQ(parsed->version.major, 1); } - -TEST(ParserBase, CanParseFromYamlNode) -{ - v1::Parser parser; - std::string content = R"( -version: 1.0.0 -name: Simple Configuration -species: - - name: A - - name: B -phases: - - name: gas - species: - - A - - B -reactions: - - type: ARRHENIUS - name: my arrhenius - gas phase: gas - A: 32.1 - B: -2.3 - C: 102.3 - D: 63.4 - E: -1.3 - reactants: - - species name: A - coefficient: 1 - products: - - species name: B - coefficient: 1 -)"; - - YAML::Node node = YAML::Load(content); - - auto parsed = parser.ParseFromNode(node); - EXPECT_TRUE(parsed); - v1::types::Mechanism mechanism = *parsed; - EXPECT_EQ(mechanism.name, "Simple Configuration"); - EXPECT_EQ(mechanism.species.size(), 2); - EXPECT_EQ(mechanism.phases.size(), 1); - EXPECT_EQ(mechanism.reactions.arrhenius.size(), 1); - EXPECT_EQ(mechanism.version.major, 1); - EXPECT_EQ(mechanism.version.minor, 0); - EXPECT_EQ(mechanism.version.patch, 0); -} \ No newline at end of file diff --git a/test/integration/test_v1_read_from_file_configs.cpp b/test/integration/test_v1_read_from_file_configs.cpp index 3a5a854d..2fca069e 100644 --- a/test/integration/test_v1_read_from_file_configs.cpp +++ b/test/integration/test_v1_read_from_file_configs.cpp @@ -1,44 +1,41 @@ -#include -#include -#include +// Copyright (C) 2023–2026 University Corporation for Atmospheric Research +// University of Illinois at Urbana-Champaign +// SPDX-License-Identifier: Apache-2.0 + +#include #include -#include #include #include -#include using namespace mechanism_configuration; -TEST(ParserBase, ParsesFullV1Configuration) +// A v1.1+ configuration may be split across multiple files via `{ files: [...] }`; +// Parse() resolves and merges them into one mechanism. +TEST(V1FileConfigs, ParsesMultiFileConfiguration) { - v1::Parser parser; - std::vector extensions = { "/json/main.json", "/yaml/main.yaml" }; - for (auto& extension : extensions) + for (const auto& main : { std::string("examples/v1/config/json/main.json"), + std::string("examples/v1/config/yaml/main.yaml") }) { - std::string path = "examples/v1/config" + extension; - auto parsed = parser.Parse(path); - for (const auto& error : parsed.errors) - std::cout << "[" << configParseStatusToString(error.first) << "] " << error.second << "\n"; + auto parsed = Parse(main); + if (!parsed) + for (const auto& [code, message] : parsed.error()) + std::cout << "[" << ErrorCodeToString(code) << "] " << message << "\n"; ASSERT_TRUE(parsed); - auto& mechanism = *parsed; - + const Mechanism& mechanism = *parsed; EXPECT_EQ(mechanism.name, "troposphere and stratosphere configs"); - // species: A, B, C ASSERT_EQ(mechanism.species.size(), 3); EXPECT_EQ(mechanism.species[0].name, "A"); EXPECT_EQ(mechanism.species[1].name, "B"); EXPECT_EQ(mechanism.species[2].name, "C"); - // phases: one gas phase with 3 species ASSERT_EQ(mechanism.phases.size(), 1); EXPECT_EQ(mechanism.phases[0].name, "gas"); ASSERT_EQ(mechanism.phases[0].species.size(), 3); - // reactions: 3 from troposphere + 3 from stratosphere = 6 arrhenius EXPECT_EQ(mechanism.reactions.arrhenius.size(), 6); } -} \ No newline at end of file +} diff --git a/test/unit/CMakeLists.txt b/test/unit/CMakeLists.txt index 87110d74..c7386c03 100644 --- a/test/unit/CMakeLists.txt +++ b/test/unit/CMakeLists.txt @@ -1,3 +1,4 @@ +create_standard_test(NAME validate SOURCES test_validate.cpp) + add_subdirectory(v0) add_subdirectory(v1) -add_subdirectory(development) \ No newline at end of file diff --git a/test/unit/development/CMakeLists.txt b/test/unit/development/CMakeLists.txt deleted file mode 100644 index 30ffc98e..00000000 --- a/test/unit/development/CMakeLists.txt +++ /dev/null @@ -1,16 +0,0 @@ -################################################################################ -# Tests - -create_standard_test(NAME development_parse_phases SOURCES test_parse_phases.cpp) -create_standard_test(NAME development_parse_species SOURCES test_parse_species.cpp) - -################################################################################ -# Copy test data - -add_custom_target(copy_development_unit_test_configs ALL ${CMAKE_COMMAND} -E copy_directory - ${CMAKE_CURRENT_SOURCE_DIR}/development_unit_configs ${CMAKE_BINARY_DIR}/development_unit_configs) - -################################################################################ - -add_subdirectory(models) -add_subdirectory(reactions) \ No newline at end of file diff --git a/test/unit/development/development_unit_configs/models/gas/gas_phase_not_found_in_phases.json b/test/unit/development/development_unit_configs/models/gas/gas_phase_not_found_in_phases.json deleted file mode 100644 index 70193719..00000000 --- a/test/unit/development/development_unit_configs/models/gas/gas_phase_not_found_in_phases.json +++ /dev/null @@ -1,89 +0,0 @@ -{ - "version": "2.0.0", - "name": "Gas phase not found in the initialized phases", - "species": [ - { - "name": "SO2" - }, - { - "name": "H2O2" - }, - { - "name": "O3" - }, - { - "name": "H2O" - }, - { - "name": "SO4" - } - ], - "phases": [ - { - "name": "gaseous_phase", - "species": [ - { - "name": "SO2" - }, - { - "name": "O3" - } - ] - }, - { - "name": "organic", - "species": [ - { - "name": "SO4" - }, - { - "name": "H2O2" - }, - { - "name": "H2O" - } - ] - } - ], - "models": [ - { - "name": "gas", - "type": "GAS_PHASE", - "phase": "gas" - } - ], - "reactions": [ - { - "type": "HL_PHASE_TRANSFER", - "gas": { - "name": "gaseous phase", - "species": [ - { - "name": "SO2", - "diffusion coefficient [m2 s-1]": 0.7 - } - ] - }, - "particle": { - "phase": "organic", - "solutes": [ - { - "name": "SO4", - "coefficient": 1.0 - }, - { - "name": "H2O2", - "coefficient": 1.0 - } - ], - "solvent": [ - { - "name": "H2O", - "coefficient": 1.0 - } - ] - }, - "__comment": "comment" - } - ] -} \ No newline at end of file diff --git a/test/unit/development/development_unit_configs/models/gas/gas_phase_not_found_in_phases.yaml b/test/unit/development/development_unit_configs/models/gas/gas_phase_not_found_in_phases.yaml deleted file mode 100644 index f5884833..00000000 --- a/test/unit/development/development_unit_configs/models/gas/gas_phase_not_found_in_phases.yaml +++ /dev/null @@ -1,47 +0,0 @@ -version: 2.0.0 -name: Gas phase not found in the initialized phases - -species: - - name: SO2 - - name: H2O2 - - name: O3 - - name: H2O - - name: SO4 - -phases: - - name: gaseous_phase - species: - - name: SO2 - - name: O3 - - name: organic - species: - - name: SO4 - - name: H2O2 - - name: H2O - -models: - - name: gas - type: GAS_PHASE - phase: gas - -reactions: - - type: HL_PHASE_TRANSFER - gas: - name: gaseous phase - species: - - name: SO2 - diffusion coefficient [m2 s-1]: 0.7 - - particle: - phase: organic - solutes: - - name: SO4 - coefficient: 1.0 - - name: H2O2 - coefficient: 1.0 - - solvent: - - name: H2O - coefficient: 1.0 - - __comment: comment diff --git a/test/unit/development/development_unit_configs/models/gas/missing_phase.json b/test/unit/development/development_unit_configs/models/gas/missing_phase.json deleted file mode 100644 index a22bdf57..00000000 --- a/test/unit/development/development_unit_configs/models/gas/missing_phase.json +++ /dev/null @@ -1,88 +0,0 @@ -{ - "version": "2.0.0", - "name": "Missing phase in gas model", - "species": [ - { - "name": "SO2" - }, - { - "name": "H2O2" - }, - { - "name": "O3" - }, - { - "name": "H2O" - }, - { - "name": "SO4" - } - ], - "phases": [ - { - "name": "gas", - "species": [ - { - "name": "SO2" - }, - { - "name": "O3" - } - ] - }, - { - "name": "organic", - "species": [ - { - "name": "SO4" - }, - { - "name": "H2O2" - }, - { - "name": "H2O" - } - ] - } - ], - "models": [ - { - "name": "gas", - "type": "GAS_PHASE" - } - ], - "reactions": [ - { - "type": "HL_PHASE_TRANSFER", - "gas": { - "name": "gas", - "species": [ - { - "name": "SO2", - "diffusion coefficient [m2 s-1]": 0.7 - } - ] - }, - "particle": { - "phase": "organic", - "solutes": [ - { - "name": "SO4", - "coefficient": 1.0 - }, - { - "name": "H2O2", - "coefficient": 1.0 - } - ], - "solvent": [ - { - "name": "H2O", - "coefficient": 1.0 - } - ] - }, - "__comment": "comment" - } - ] -} \ No newline at end of file diff --git a/test/unit/development/development_unit_configs/models/gas/missing_phase.yaml b/test/unit/development/development_unit_configs/models/gas/missing_phase.yaml deleted file mode 100644 index 5ee5b01d..00000000 --- a/test/unit/development/development_unit_configs/models/gas/missing_phase.yaml +++ /dev/null @@ -1,46 +0,0 @@ -version: 2.0.0 -name: Missing phase in gas model - -species: - - name: SO2 - - name: H2O2 - - name: O3 - - name: H2O - - name: SO4 - -phases: - - name: gas - species: - - name: SO2 - - name: O3 - - name: organic - species: - - name: SO4 - - name: H2O2 - - name: H2O - -models: - - name: gas - type: GAS_PHASE - -reactions: - - type: HL_PHASE_TRANSFER - gas: - name: gas - species: - - name: SO2 - diffusion coefficient [m2 s-1]: 0.7 - - particle: - phase: organic - solutes: - - name: SO4 - coefficient: 1.0 - - name: H2O2 - coefficient: 1.0 - - solvent: - - name: H2O - coefficient: 1.0 - - __comment: comment diff --git a/test/unit/development/development_unit_configs/models/gas/valid.json b/test/unit/development/development_unit_configs/models/gas/valid.json deleted file mode 100644 index ede495bc..00000000 --- a/test/unit/development/development_unit_configs/models/gas/valid.json +++ /dev/null @@ -1,89 +0,0 @@ -{ - "version": "2.0.0", - "name": "Gas model", - "species": [ - { - "name": "SO2" - }, - { - "name": "H2O2" - }, - { - "name": "O3" - }, - { - "name": "H2O" - }, - { - "name": "SO4" - } - ], - "phases": [ - { - "name": "gas", - "species": [ - { - "name": "SO2" - }, - { - "name": "O3" - } - ] - }, - { - "name": "organic", - "species": [ - { - "name": "SO4" - }, - { - "name": "H2O2" - }, - { - "name": "H2O" - } - ] - } - ], - "models": [ - { - "name": "gas", - "type": "GAS_PHASE", - "phase": "gas" - } - ], - "reactions": [ - { - "type": "HL_PHASE_TRANSFER", - "gas": { - "name": "gas", - "species": [ - { - "name": "SO2", - "diffusion coefficient [m2 s-1]": 0.7 - } - ] - }, - "particle": { - "phase": "organic", - "solutes": [ - { - "name": "SO4", - "coefficient": 1.0 - }, - { - "name": "H2O2", - "coefficient": 1.0 - } - ], - "solvent": [ - { - "name": "H2O", - "coefficient": 1.0 - } - ] - }, - "__comment": "comment" - } - ] -} \ No newline at end of file diff --git a/test/unit/development/development_unit_configs/models/gas/valid.yaml b/test/unit/development/development_unit_configs/models/gas/valid.yaml deleted file mode 100644 index 6b7dde5e..00000000 --- a/test/unit/development/development_unit_configs/models/gas/valid.yaml +++ /dev/null @@ -1,48 +0,0 @@ -version: 2.0.0 -name: Gas model - -species: - - name: SO2 - - name: H2O2 - - name: O3 - - name: H2O - - name: SO4 - -phases: - - name: gas - species: - - name: SO2 - - name: O3 - - - name: organic - species: - - name: SO4 - - name: H2O2 - - name: H2O - -models: - - name: gas - type: GAS_PHASE - phase: gas - -reactions: - - type: HL_PHASE_TRANSFER - gas: - name: gas - species: - - name: SO2 - diffusion coefficient [m2 s-1]: 0.7 - - particle: - phase: organic - solutes: - - name: SO4 - coefficient: 1.0 - - name: H2O2 - coefficient: 1.0 - - solvent: - - name: H2O - coefficient: 1.0 - - __comment: comment diff --git a/test/unit/development/development_unit_configs/models/modal/missing_modal_variable.json b/test/unit/development/development_unit_configs/models/modal/missing_modal_variable.json deleted file mode 100644 index 2806eaf7..00000000 --- a/test/unit/development/development_unit_configs/models/modal/missing_modal_variable.json +++ /dev/null @@ -1,184 +0,0 @@ -{ - "version": "2.0.0", - "name": "Missing modal member variable", - "species": [ - { - "name": "SO2", - "molecular weight [kg mol-1]": 0.06407, - "density [kg m-3]": 2.628, - "__absolute tolerance": 1.0e-20 - }, - { - "name": "H2O2", - "HLC(298K) [mol m-3 Pa-1]": 1.011596348, - "HLC exponential factor [K]": 6340, - "diffusion coefficient [m2 s-1]": 1.46E-05, - "N star": 1.74, - "molecular weight [kg mol-1]": 0.0340147, - "density [kg m-3]": 1000.0, - "__absolute tolerance": 1.0e-10 - }, - { - "name": "O3", - "molecular weight [kg mol-1]": 0.0479982, - "density [kg m-3]": 2.144, - "__absolute tolerance": 1.0e-20 - }, - { - "name": "H2O", - "molecular weight [kg mol-1]": 0.01801528, - "density [kg m-3]": 997.0, - "__absolute tolerance": 1.0e-20 - }, - { - "name": "H2SO4", - "molecular weight [kg mol-1]": 0.098079, - "density [kg m-3]": 1830.0, - "__absolute tolerance": 1.0e-20 - }, - { - "name": "SO4", - "molecular weight [kg mol-1]": 0.09606, - "density [kg m-3]": 1769.0, - "__absolute tolerance": 1.0e-20 - }, - { - "name": "organic carbon", - "molecular weight [kg mol-1]": 0.150, - "density [kg m-3]": 1200, - "__absolute tolerance": 1.0e-20 - } - ], - "phases": [ - { - "name": "gas", - "species": [ - { - "name": "SO2" - }, - { - "name": "H2O2" - }, - { - "name": "H2SO4" - }, - { - "name": "O3" - } - ] - }, - { - "name": "aqueous", - "species": [ - { - "name": "SO4" - }, - { - "name": "H2O2" - }, - { - "name": "H2SO4" - }, - { - "name": "H2O" - }, - { - "name": "O3" - } - ] - } - ], - "models": [ - { - "name": "aqueous", - "type": "MODAL", - "modes": [ - { - "name": "aitken", - "geometric mean diameter [m]": 2.6e-8, - "phase": "aqueous", - "__comment": "Aitken mode" - }, - { - "name": "accumulation", - "geometric mean diameter [m]": 1.1e-7, - "phase": "aqueous" - } - ] - } - ], - "reactions": [ - { - "type": "HL_PHASE_TRANSFER", - "gas": { - "name": "gas", - "species": [ - { - "name": "SO2", - "diffusion coefficient [m2 s-1]": 0.7 - }, - { - "name": "H2O2", - "diffusion coefficient [m2 s-1]": 0.7 - } - ] - }, - "particle": { - "phase": "aqueous", - "solutes": [ - { - "name": "SO4", - "coefficient": 1.0 - }, - { - "name": "H2O2", - "coefficient": 1.0 - } - ], - "solvent": [ - { - "name": "H2O", - "coefficient": 1.0 - } - ] - }, - "__comment": "SO4 condensed phase production due to H2O2 (kg/m2/s)" - }, - { - "type": "HL_PHASE_TRANSFER", - "gas": { - "name": "gas", - "species": [ - { - "name": "SO2", - "diffusion coefficient [m2 s-1]": 0.7 - }, - { - "name": "O3", - "diffusion coefficient [m2 s-1]": 0.7 - } - ] - }, - "particle": { - "phase": "aqueous", - "solutes": [ - { - "name": "SO4", - "coefficient": 1.0 - }, - { - "name": "O3", - "coefficient": 1.0 - } - ], - "solvent": [ - { - "name": "H2O", - "coefficient": 1.0 - } - ] - }, - "__comment": "SO4 condensed phase production due to O3 (kg/m2/s)" - } - ] -} \ No newline at end of file diff --git a/test/unit/development/development_unit_configs/models/modal/missing_modal_variable.yaml b/test/unit/development/development_unit_configs/models/modal/missing_modal_variable.yaml deleted file mode 100644 index c6c6c18c..00000000 --- a/test/unit/development/development_unit_configs/models/modal/missing_modal_variable.yaml +++ /dev/null @@ -1,116 +0,0 @@ -version: 2.0.0 -name: Missing modal member variable - -species: - - name: SO2 - molecular weight [kg mol-1]: 0.06407 - density [kg m-3]: 2.628 - __absolute tolerance: 1.0e-20 - - - name: H2O2 - HLC(298K) [mol m-3 Pa-1]: 1.011596348 - HLC exponential factor [K]: 6340 - diffusion coefficient [m2 s-1]: 1.46E-05 - N star: 1.74 - molecular weight [kg mol-1]: 0.0340147 - density [kg m-3]: 1000.0 - __absolute tolerance: 1.0e-10 - - - name: O3 - molecular weight [kg mol-1]: 0.0479982 - density [kg m-3]: 2.144 - __absolute tolerance: 1.0e-20 - - - name: H2O - molecular weight [kg mol-1]: 0.01801528 - density [kg m-3]: 997.0 - __absolute tolerance: 1.0e-20 - - - name: H2SO4 - molecular weight [kg mol-1]: 0.098079 - density [kg m-3]: 1830.0 - __absolute tolerance: 1.0e-20 - - - name: SO4 - molecular weight [kg mol-1]: 0.09606 - density [kg m-3]: 1769.0 - __absolute tolerance: 1.0e-20 - - - name: organic carbon - molecular weight [kg mol-1]: 0.150 - density [kg m-3]: 1200 - __absolute tolerance: 1.0e-20 - -phases: - - name: gas - species: - - name: SO2 - - name: H2O2 - - name: H2SO4 - - name: O3 - - - name: aqueous - species: - - name: SO4 - - name: H2O2 - - name: H2SO4 - - name: H2O - - name: O3 - -models: - - name: aqueous - type: MODAL - modes: - - name: aitken - geometric mean diameter [m]: 2.6e-8 - phase: aqueous - __comment: Aitken mode - - - name: accumulation - geometric mean diameter [m]: 1.1e-7 - phase: aqueous - -reactions: - - type: HL_PHASE_TRANSFER - gas: - name: gas - species: - - name: SO2 - diffusion coefficient [m2 s-1]: 0.7 - - name: H2O2 - diffusion coefficient [m2 s-1]: 0.7 - - particle: - phase: aqueous - solutes: - - name: SO4 - coefficient: 1.0 - - name: H2O2 - coefficient: 1.0 - solvent: - - name: H2O - coefficient: 1.0 - - __comment: SO4 condensed phase production due to H2O2 (kg/m2/s) - - - type: HL_PHASE_TRANSFER - gas: - name: gas - species: - - name: SO2 - diffusion coefficient [m2 s-1]: 0.7 - - name: O3 - diffusion coefficient [m2 s-1]: 0.7 - - particle: - phase: aqueous - solutes: - - name: SO4 - coefficient: 1.0 - - name: O3 - coefficient: 1.0 - solvent: - - name: H2O - coefficient: 1.0 - - __comment: SO4 condensed phase production due to O3 (kg/m2/s) diff --git a/test/unit/development/development_unit_configs/models/modal/missing_modes.json b/test/unit/development/development_unit_configs/models/modal/missing_modes.json deleted file mode 100644 index 6f549e88..00000000 --- a/test/unit/development/development_unit_configs/models/modal/missing_modes.json +++ /dev/null @@ -1,88 +0,0 @@ -{ - "version": "2.0.0", - "name": "Missing modes", - "species": [ - { - "name": "SO2" - }, - { - "name": "H2O2" - }, - { - "name": "O3" - }, - { - "name": "H2O" - }, - { - "name": "SO4" - } - ], - "phases": [ - { - "name": "gas", - "species": [ - { - "name": "SO2" - }, - { - "name": "O3" - } - ] - }, - { - "name": "organic", - "species": [ - { - "name": "SO4" - }, - { - "name": "H2O2" - }, - { - "name": "H2O" - } - ] - } - ], - "models": [ - { - "name": "aqueous", - "type": "MODAL" - } - ], - "reactions": [ - { - "type": "HL_PHASE_TRANSFER", - "gas": { - "name": "gas", - "species": [ - { - "name": "SO2", - "diffusion coefficient [m2 s-1]": 0.7 - } - ] - }, - "particle": { - "phase": "organic", - "solutes": [ - { - "name": "SO4", - "coefficient": 1.0 - }, - { - "name": "H2O2", - "coefficient": 1.0 - } - ], - "solvent": [ - { - "name": "H2O", - "coefficient": 1.0 - } - ] - }, - "__comment": "comment" - } - ] -} \ No newline at end of file diff --git a/test/unit/development/development_unit_configs/models/modal/missing_modes.yaml b/test/unit/development/development_unit_configs/models/modal/missing_modes.yaml deleted file mode 100644 index 9fa5854d..00000000 --- a/test/unit/development/development_unit_configs/models/modal/missing_modes.yaml +++ /dev/null @@ -1,46 +0,0 @@ -version: 2.0.0 -name: Missing modes - -species: - - name: SO2 - - name: H2O2 - - name: O3 - - name: H2O - - name: SO4 - -phases: - - name: gas - species: - - name: SO2 - - name: O3 - - - name: organic - species: - - name: SO4 - - name: H2O2 - - name: H2O - -models: - - name: aqueous - type: MODAL - -reactions: - - type: HL_PHASE_TRANSFER - gas: - name: gas - species: - - name: SO2 - diffusion coefficient [m2 s-1]: 0.7 - - particle: - phase: organic - solutes: - - name: SO4 - coefficient: 1.0 - - name: H2O2 - coefficient: 1.0 - solvent: - - name: H2O - coefficient: 1.0 - - __comment: comment diff --git a/test/unit/development/development_unit_configs/models/modal/mode_phase_not_found_in_phases.json b/test/unit/development/development_unit_configs/models/modal/mode_phase_not_found_in_phases.json deleted file mode 100644 index 4b4bce8f..00000000 --- a/test/unit/development/development_unit_configs/models/modal/mode_phase_not_found_in_phases.json +++ /dev/null @@ -1,103 +0,0 @@ -{ - "version": "2.0.0", - "name": "Mode phase not found in the phases", - "species": [ - { - "name": "SO2" - }, - { - "name": "H2O2" - }, - { - "name": "O3" - }, - { - "name": "H2O" - }, - { - "name": "SO4" - } - ], - "phases": [ - { - "name": "gas", - "species": [ - { - "name": "SO2" - }, - { - "name": "O3" - } - ] - }, - { - "name": "organic", - "species": [ - { - "name": "SO4" - }, - { - "name": "H2O2" - }, - { - "name": "H2O" - } - ] - } - ], - "models": [ - { - "name": "aqueous", - "type": "MODAL", - "modes": [ - { - "name": "aitken", - "geometric mean diameter [m]": 2.6e-8, - "geometric standard deviation": 1.6, - "phase": "aqueous", - "__comment": "Aitken mode" - }, - { - "name": "accumulation", - "geometric mean diameter [m]": 1.1e-7, - "geometric standard deviation": 1.6, - "phase": "organic" - } - ] - } - ], - "reactions": [ - { - "type": "HL_PHASE_TRANSFER", - "gas": { - "name": "gas", - "species": [ - { - "name": "SO2", - "diffusion coefficient [m2 s-1]": 0.7 - } - ] - }, - "particle": { - "phase": "organic", - "solutes": [ - { - "name": "SO4", - "coefficient": 1.0 - }, - { - "name": "H2O2", - "coefficient": 1.0 - } - ], - "solvent": [ - { - "name": "H2O", - "coefficient": 1.0 - } - ] - }, - "__comment": "comment" - } - ] -} \ No newline at end of file diff --git a/test/unit/development/development_unit_configs/models/modal/mode_phase_not_found_in_phases.yaml b/test/unit/development/development_unit_configs/models/modal/mode_phase_not_found_in_phases.yaml deleted file mode 100644 index e645e098..00000000 --- a/test/unit/development/development_unit_configs/models/modal/mode_phase_not_found_in_phases.yaml +++ /dev/null @@ -1,57 +0,0 @@ -version: 2.0.0 -name: Mode phase not found in the phases - -species: - - name: SO2 - - name: H2O2 - - name: O3 - - name: H2O - - name: SO4 - -phases: - - name: gas - species: - - name: SO2 - - name: O3 - - - name: organic - species: - - name: SO4 - - name: H2O2 - - name: H2O - -models: - - name: aqueous - type: MODAL - modes: - - name: aitken - geometric mean diameter [m]: 2.6e-8 - geometric standard deviation: 1.6 - phase: aqueous - __comment: Aitken mode - - - name: accumulation - geometric mean diameter [m]: 1.1e-7 - geometric standard deviation: 1.6 - phase: organic - -reactions: - - type: HL_PHASE_TRANSFER - gas: - name: gas - species: - - name: SO2 - diffusion coefficient [m2 s-1]: 0.7 - - particle: - phase: organic - solutes: - - name: SO4 - coefficient: 1.0 - - name: H2O2 - coefficient: 1.0 - solvent: - - name: H2O - coefficient: 1.0 - - __comment: comment diff --git a/test/unit/development/development_unit_configs/models/modal/valid.json b/test/unit/development/development_unit_configs/models/modal/valid.json deleted file mode 100644 index f049317f..00000000 --- a/test/unit/development/development_unit_configs/models/modal/valid.json +++ /dev/null @@ -1,200 +0,0 @@ -{ - "version": "2.0.0", - "name": "Sulfate Formation", - "species": [ - { - "name": "SO2", - "molecular weight [kg mol-1]": 0.06407, - "density [kg m-3]": 2.628, - "__absolute tolerance": 1.0e-20 - }, - { - "name": "H2O2", - "HLC(298K) [mol m-3 Pa-1]": 1.011596348, - "HLC exponential factor [K]": 6340, - "diffusion coefficient [m2 s-1]": 1.46E-05, - "N star": 1.74, - "molecular weight [kg mol-1]": 0.0340147, - "density [kg m-3]": 1000.0, - "__absolute tolerance": 1.0e-10 - }, - { - "name": "O3", - "molecular weight [kg mol-1]": 0.0479982, - "density [kg m-3]": 2.144, - "__absolute tolerance": 1.0e-20 - }, - { - "name": "H2O", - "molecular weight [kg mol-1]": 0.01801528, - "density [kg m-3]": 997.0, - "__absolute tolerance": 1.0e-20 - }, - { - "name": "H2SO4", - "molecular weight [kg mol-1]": 0.098079, - "density [kg m-3]": 1830.0, - "__absolute tolerance": 1.0e-20 - }, - { - "name": "SO4", - "molecular weight [kg mol-1]": 0.09606, - "density [kg m-3]": 1769.0, - "__absolute tolerance": 1.0e-20 - }, - { - "name": "organic carbon", - "molecular weight [kg mol-1]": 0.150, - "density [kg m-3]": 1200, - "__absolute tolerance": 1.0e-20 - } - ], - "phases": [ - { - "name": "gas", - "species": [ - { - "name": "SO2" - }, - { - "name": "H2O2" - }, - { - "name": "H2SO4" - }, - { - "name": "O3" - } - ] - }, - { - "name": "aqueous", - "species": [ - { - "name": "SO4" - }, - { - "name": "H2O2" - }, - { - "name": "H2SO4" - }, - { - "name": "H2O" - }, - { - "name": "O3" - } - ] - }, - { - "name": "organic", - "species": [ - { - "name": "organic carbon" - } - ] - } - ], - "models": [ - { - "name": "gas", - "type": "GAS_PHASE", - "phase": "gas" - }, - { - "name": "aqueous", - "type": "MODAL", - "modes": [ - { - "name": "aitken", - "geometric mean diameter [m]": 2.6e-8, - "geometric standard deviation": 1.6, - "phase": "aqueous", - "__comment": "Aitken mode" - }, - { - "name": "accumulation", - "geometric mean diameter [m]": 1.1e-7, - "geometric standard deviation": 1.8, - "phase": "organic" - } - ] - } - ], - "reactions": [ - { - "type": "HL_PHASE_TRANSFER", - "gas": { - "name": "gas", - "species": [ - { - "name": "SO2", - "diffusion coefficient [m2 s-1]": 0.7 - }, - { - "name": "H2O2", - "diffusion coefficient [m2 s-1]": 0.7 - } - ] - }, - "particle": { - "phase": "aqueous", - "solutes": [ - { - "name": "SO4", - "coefficient": 1.0 - }, - { - "name": "H2O2", - "coefficient": 1.0 - } - ], - "solvent": [ - { - "name": "H2O", - "coefficient": 1.0 - } - ] - }, - "__comment": "SO4 condensed phase production due to H2O2 (kg/m2/s)" - }, - { - "type": "HL_PHASE_TRANSFER", - "gas": { - "name": "gas", - "species": [ - { - "name": "SO2", - "diffusion coefficient [m2 s-1]": 0.7 - }, - { - "name": "O3", - "diffusion coefficient [m2 s-1]": 0.7 - } - ] - }, - - "particle": { - "phase": "aqueous", - "solutes": [ - { - "name": "SO4", - "coefficient": 1.0 - }, - { - "name": "O3", - "coefficient": 1.0 - } - ], - "solvent": [ - { - "name": "H2O", - "coefficient": 1.0 - } - ] - }, - "__comment": "SO4 condensed phase production due to O3 (kg/m2/s)" - } - ] -} \ No newline at end of file diff --git a/test/unit/development/development_unit_configs/models/modal/valid.yaml b/test/unit/development/development_unit_configs/models/modal/valid.yaml deleted file mode 100644 index 2e3c47bb..00000000 --- a/test/unit/development/development_unit_configs/models/modal/valid.yaml +++ /dev/null @@ -1,122 +0,0 @@ -version: 2.0.0 -name: Sulfate Formation - -species: - - name: SO2 - molecular weight [kg mol-1]: 0.06407 - density [kg m-3]: 2.628 - __absolute tolerance: 1.0e-20 - - - name: H2O2 - HLC(298K) [mol m-3 Pa-1]: 1.011596348 - HLC exponential factor [K]: 6340 - diffusion coefficient [m2 s-1]: 1.46e-05 - N star: 1.74 - molecular weight [kg mol-1]: 0.0340147 - density [kg m-3]: 1000.0 - __absolute tolerance: 1.0e-10 - - - name: O3 - molecular weight [kg mol-1]: 0.0479982 - density [kg m-3]: 2.144 - __absolute tolerance: 1.0e-20 - - - name: H2O - molecular weight [kg mol-1]: 0.01801528 - density [kg m-3]: 997.0 - __absolute tolerance: 1.0e-20 - - - name: H2SO4 - molecular weight [kg mol-1]: 0.098079 - density [kg m-3]: 1830.0 - __absolute tolerance: 1.0e-20 - - - name: SO4 - molecular weight [kg mol-1]: 0.09606 - density [kg m-3]: 1769.0 - __absolute tolerance: 1.0e-20 - - - name: organic carbon - molecular weight [kg mol-1]: 0.150 - density [kg m-3]: 1200 - __absolute tolerance: 1.0e-20 - -phases: - - name: gas - species: - - name: SO2 - - name: H2O2 - - name: H2SO4 - - name: O3 - - - name: aqueous - species: - - name: SO4 - - name: H2O2 - - name: H2SO4 - - name: H2O - - name: O3 - - - name: organic - species: - - name: organic carbon - -models: - - name: gas - type: GAS_PHASE - phase: gas - - - name: aqueous - type: MODAL - modes: - - name: aitken - geometric mean diameter [m]: 2.6e-8 - geometric standard deviation: 1.6 - phase: aqueous - __comment: Aitken mode - - - name: accumulation - geometric mean diameter [m]: 1.1e-7 - geometric standard deviation: 1.8 - phase: organic - -reactions: - - type: HL_PHASE_TRANSFER - gas: - name: gas - species: - - name: SO2 - diffusion coefficient [m2 s-1]: 0.7 - - name: H2O2 - diffusion coefficient [m2 s-1]: 0.7 - particle: - phase: aqueous - solutes: - - name: SO4 - coefficient: 1.0 - - name: H2O2 - coefficient: 1.0 - solvent: - - name: H2O - coefficient: 1.0 - __comment: SO4 condensed phase production due to H2O2 (kg/m2/s) - - - type: HL_PHASE_TRANSFER - gas: - name: gas - species: - - name: SO2 - diffusion coefficient [m2 s-1]: 0.7 - - name: O3 - diffusion coefficient [m2 s-1]: 0.7 - particle: - phase: aqueous - solutes: - - name: SO4 - coefficient: 1.0 - - name: O3 - coefficient: 1.0 - solvent: - - name: H2O - coefficient: 1.0 - __comment: SO4 condensed phase production due to O3 (kg/m2/s) diff --git a/test/unit/development/development_unit_configs/phases/duplicate_phases.json b/test/unit/development/development_unit_configs/phases/duplicate_phases.json deleted file mode 100644 index 2f7f58ca..00000000 --- a/test/unit/development/development_unit_configs/phases/duplicate_phases.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "version": "2.0.0", - "name": "Duplicate phases configuration", - "species": [ - { - "name": "A" - }, - { - "name": "B" - }, - { - "name": "C" - } - ], - "phases": [ - { - "name": "gas", - "species": [ - { - "name": "A" - }, - { - "name": "B" - } - ] - }, - { - "name": "gas", - "species": [ - { - "name": "A" - }, - { - "name": "B" - } - ] - }, - { - "name": "aqueos", - "species": [ - { - "name": "C" - } - ] - } - ], - "reactions": [] -} \ No newline at end of file diff --git a/test/unit/development/development_unit_configs/phases/duplicate_phases.yaml b/test/unit/development/development_unit_configs/phases/duplicate_phases.yaml deleted file mode 100644 index e1a5b75c..00000000 --- a/test/unit/development/development_unit_configs/phases/duplicate_phases.yaml +++ /dev/null @@ -1,24 +0,0 @@ -version: 2.0.0 -name: Duplicate phases configuration - -species: - - name: A - - name: B - - name: C - -phases: - - name: gas - species: - - name: A - - name: B - - - name: gas - species: - - name: A - - name: B - - - name: aqueos - species: - - name: C - -reactions: [] diff --git a/test/unit/development/development_unit_configs/phases/duplicate_species_in_phase.json b/test/unit/development/development_unit_configs/phases/duplicate_species_in_phase.json deleted file mode 100644 index a836f824..00000000 --- a/test/unit/development/development_unit_configs/phases/duplicate_species_in_phase.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "version": "2.0.0", - "name": "Duplicate species in phase configuration", - "species": [ - { - "name": "O2" - }, - { - "name": "N2" - }, - { - "name": "CO2" - } - ], - "phases": [ - { - "name": "gas", - "species": [ - { - "name": "O2" - }, - { - "name": "N2" - }, - { - "name": "O2" - } - ] - } - ], - "reactions": [] -} \ No newline at end of file diff --git a/test/unit/development/development_unit_configs/phases/duplicate_species_in_phase.yaml b/test/unit/development/development_unit_configs/phases/duplicate_species_in_phase.yaml deleted file mode 100644 index ca022cde..00000000 --- a/test/unit/development/development_unit_configs/phases/duplicate_species_in_phase.yaml +++ /dev/null @@ -1,16 +0,0 @@ -version: 2.0.0 -name: Duplicate species in phase configuration - -species: - - name: O2 - - name: N2 - - name: CO2 - -phases: - - name: gas - species: - - name: O2 - - name: N2 - - name: O2 # Duplicate species - -reactions: [] diff --git a/test/unit/development/development_unit_configs/phases/invalid_key.json b/test/unit/development/development_unit_configs/phases/invalid_key.json deleted file mode 100644 index ee9fe57a..00000000 --- a/test/unit/development/development_unit_configs/phases/invalid_key.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "version": "2.0.0", - "name": "Invalid key configuration", - "species": [ - { - "name": "A" - }, - { - "name": "B" - }, - { - "name": "C" - } - ], - "phases": [ - { - "name": "gas", - "species": [ - { - "name": "A" - }, - { - "name": "B" - } - ], - "other": "key" - } - ], - "reactions": [] -} \ No newline at end of file diff --git a/test/unit/development/development_unit_configs/phases/invalid_key.yaml b/test/unit/development/development_unit_configs/phases/invalid_key.yaml deleted file mode 100644 index f3c0a497..00000000 --- a/test/unit/development/development_unit_configs/phases/invalid_key.yaml +++ /dev/null @@ -1,16 +0,0 @@ -version: 2.0.0 -name: Invalid key configuration - -species: - - name: A - - name: B - - name: C - -phases: - - name: gas - species: - - name: A - - name: B - other: key - -reactions: [] diff --git a/test/unit/development/development_unit_configs/phases/invalid_species_object.json b/test/unit/development/development_unit_configs/phases/invalid_species_object.json deleted file mode 100644 index 37ac5547..00000000 --- a/test/unit/development/development_unit_configs/phases/invalid_species_object.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "version": "2.0.0", - "name": "Invalid species object test - missing name", - "species": [ - { - "name": "foo" - } - ], - "phases": [ - { - "name": "test phase", - "species": [ - { - "name": "foo" - }, - { - "diffusion coefficient [m2 s-1]": 1.0 - } - ] - } - ], - "reactions": [] -} \ No newline at end of file diff --git a/test/unit/development/development_unit_configs/phases/invalid_species_object.yaml b/test/unit/development/development_unit_configs/phases/invalid_species_object.yaml deleted file mode 100644 index 7199e442..00000000 --- a/test/unit/development/development_unit_configs/phases/invalid_species_object.yaml +++ /dev/null @@ -1,11 +0,0 @@ ---- -version: 2.0.0 -name: Invalid species object test - missing name -species: -- name: foo -phases: -- name: test phase - species: - - name: foo - - "diffusion coefficient [m2 s-1]": 1.0 # Missing name field -reactions: [] \ No newline at end of file diff --git a/test/unit/development/development_unit_configs/phases/missing_required_key.json b/test/unit/development/development_unit_configs/phases/missing_required_key.json deleted file mode 100644 index 5c5cf8a3..00000000 --- a/test/unit/development/development_unit_configs/phases/missing_required_key.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "version": "2.0.0", - "name": "Missing required phases key configuration", - "species": [], - "phases": [ - { - "name": "gas" - } - ], - "reactions": [] -} \ No newline at end of file diff --git a/test/unit/development/development_unit_configs/phases/missing_required_key.yaml b/test/unit/development/development_unit_configs/phases/missing_required_key.yaml deleted file mode 100644 index 78686843..00000000 --- a/test/unit/development/development_unit_configs/phases/missing_required_key.yaml +++ /dev/null @@ -1,6 +0,0 @@ -name: Missing required phases key configuration -phases: -- name: gas -reactions: [] -species: [] -version: 2.0.0 diff --git a/test/unit/development/development_unit_configs/phases/phase_species_properties.json b/test/unit/development/development_unit_configs/phases/phase_species_properties.json deleted file mode 100644 index 8525e37d..00000000 --- a/test/unit/development/development_unit_configs/phases/phase_species_properties.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "version": "2.0.0", - "name": "Phase species properties test configuration", - "species": [ - { - "name": "foo" - }, - { - "name": "bar" - }, - { - "name": "baz" - } - ], - "phases": [ - { - "name": "my phase", - "species": [ - { - "name": "foo", - "diffusion coefficient [m2 s-1]": 4.23e-7 - }, - { - "name": "bar", - "__custom property": 0.5, - "__another custom property": "value" - }, - { - "name": "baz", - } - ], - "__my custom phase property": "custom value" - } - ], - "reactions": [] -} \ No newline at end of file diff --git a/test/unit/development/development_unit_configs/phases/phase_species_properties.yaml b/test/unit/development/development_unit_configs/phases/phase_species_properties.yaml deleted file mode 100644 index e127f0b8..00000000 --- a/test/unit/development/development_unit_configs/phases/phase_species_properties.yaml +++ /dev/null @@ -1,18 +0,0 @@ ---- -version: 2.0.0 -name: Phase species properties test configuration -species: -- name: foo -- name: bar -- name: baz -phases: -- name: my phase - species: - - name: foo - "diffusion coefficient [m2 s-1]": 4.23e-7 - - name: bar - "__custom property": 0.5 - "__another custom property": "value" - - name: baz - "__my custom phase property": "custom value" -reactions: [] \ No newline at end of file diff --git a/test/unit/development/development_unit_configs/phases/unknown_species.json b/test/unit/development/development_unit_configs/phases/unknown_species.json deleted file mode 100644 index 79598c3b..00000000 --- a/test/unit/development/development_unit_configs/phases/unknown_species.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "version": "2.0.0", - "name": "Unknown species configuration", - "species": [ - { - "name": "A" - }, - { - "name": "B" - }, - { - "name": "C" - } - ], - "phases": [ - { - "name": "gas", - "species": [ - { - "name": "A" - }, - { - "name": "D" - }, - ], - "__other": "key" - } - ], - "reactions": [] -} \ No newline at end of file diff --git a/test/unit/development/development_unit_configs/phases/unknown_species.yaml b/test/unit/development/development_unit_configs/phases/unknown_species.yaml deleted file mode 100644 index 57a8e90c..00000000 --- a/test/unit/development/development_unit_configs/phases/unknown_species.yaml +++ /dev/null @@ -1,16 +0,0 @@ -version: 2.0.0 -name: Unknown species configuration - -species: - - name: A - - name: B - - name: C - -phases: - - name: gas - species: - - name: A - - name: D - __other: key - -reactions: [] diff --git a/test/unit/development/development_unit_configs/phases/valid_phases.json b/test/unit/development/development_unit_configs/phases/valid_phases.json deleted file mode 100644 index ed9c157f..00000000 --- a/test/unit/development/development_unit_configs/phases/valid_phases.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - "version": "2.0.0", - "name": "Valid phases configuration", - "species": [ - { - "name": "A" - }, - { - "name": "B" - }, - { - "name": "C" - } - ], - "phases": [ - { - "name": "gas", - "species": [ - { - "name": "A", - "diffusion coefficient [m2 s-1]": 4.23e-7 - }, - { - "name": "B" - } - ], - "__other": "This is a comment." - }, - { - "name": "aqueous", - "species": [ - { - "name": "C", - "diffusion coefficient [m2 s-1]": 4.23e-7 - } - ], - "__other1": "This is another comment.", - "__other2": "This is again a comment." - } - ], - "reactions": [] -} \ No newline at end of file diff --git a/test/unit/development/development_unit_configs/phases/valid_phases.yaml b/test/unit/development/development_unit_configs/phases/valid_phases.yaml deleted file mode 100644 index 8de098f4..00000000 --- a/test/unit/development/development_unit_configs/phases/valid_phases.yaml +++ /dev/null @@ -1,24 +0,0 @@ -version: 2.0.0 -name: Valid phases configuration - -species: - - name: A - - name: B - - name: C - -phases: - - name: gas - species: - - name: A - diffusion coefficient [m2 s-1]: 4.23e-7 - - name: B - __other: This is a comment. - - - name: aqueous - species: - - name: C - diffusion coefficient [m2 s-1]: 4.23e-7 - __other1: This is another comment. - __other2: This is again a comment. - -reactions: [] diff --git a/test/unit/development/development_unit_configs/reactions/aqueous_equilibrium/bad_reaction_component.json b/test/unit/development/development_unit_configs/reactions/aqueous_equilibrium/bad_reaction_component.json deleted file mode 100644 index e8bc0faf..00000000 --- a/test/unit/development/development_unit_configs/reactions/aqueous_equilibrium/bad_reaction_component.json +++ /dev/null @@ -1,61 +0,0 @@ -{ - "version": "2.0.0", - "name": "Bad reaction component", - "species": [ - { - "name": "A" - }, - { - "name": "B" - }, - { - "name": "C" - }, - { - "name": "H2O" - } - ], - "phases": [ - { - "name": "aqueous", - "species": [ - { - "name": "A" - }, - { - "name": "B" - }, - { - "name": "C" - }, - { - "name": "H2O" - } - ] - } - ], - "reactions": [ - { - "type": "AQUEOUS_EQUILIBRIUM", - "condensed phase": "aqueous", - "condensed-phase water": "H2O", - "k_reverse": 0.32, - "reactants": [ - { - "name": "A", - "Coefficient": 2 - } - ], - "products": [ - { - "name": "B", - "coefficient": 1 - }, - { - "name": "C", - "coefficient": 1 - } - ] - } - ] -} \ No newline at end of file diff --git a/test/unit/development/development_unit_configs/reactions/aqueous_equilibrium/bad_reaction_component.yaml b/test/unit/development/development_unit_configs/reactions/aqueous_equilibrium/bad_reaction_component.yaml deleted file mode 100644 index 87f98a87..00000000 --- a/test/unit/development/development_unit_configs/reactions/aqueous_equilibrium/bad_reaction_component.yaml +++ /dev/null @@ -1,27 +0,0 @@ -name: Bad reaction component -phases: -- name: aqueous - species: - - name: A - - name: B - - name: C - - name: H2O -reactions: -- condensed phase: aqueous - condensed-phase water: H2O - k_reverse: 0.32 - products: - - name: B - coefficient: 1 - - name: C - coefficient: 1 - reactants: - - name: A - Coefficient: 2 - type: AQUEOUS_EQUILIBRIUM -species: -- name: A -- name: B -- name: C -- name: H2O -version: 2.0.0 diff --git a/test/unit/development/development_unit_configs/reactions/aqueous_equilibrium/missing_phase.json b/test/unit/development/development_unit_configs/reactions/aqueous_equilibrium/missing_phase.json deleted file mode 100644 index 3bdc0ce4..00000000 --- a/test/unit/development/development_unit_configs/reactions/aqueous_equilibrium/missing_phase.json +++ /dev/null @@ -1,43 +0,0 @@ -{ - "version": "2.0.0", - "name": "Missing phase", - "species": [ - { - "name": "A" - }, - { - "name": "B" - }, - { - "name": "C" - }, - { - "name": "H2O" - } - ], - "phases": [], - "reactions": [ - { - "type": "AQUEOUS_EQUILIBRIUM", - "condensed phase": "aqueous", - "condensed-phase water": "H2O", - "k_reverse": 0.32, - "reactants": [ - { - "name": "A", - "coefficient": 2 - } - ], - "products": [ - { - "name": "B", - "coefficient": 1 - }, - { - "name": "C", - "coefficient": 1 - } - ] - } - ] -} \ No newline at end of file diff --git a/test/unit/development/development_unit_configs/reactions/aqueous_equilibrium/missing_phase.yaml b/test/unit/development/development_unit_configs/reactions/aqueous_equilibrium/missing_phase.yaml deleted file mode 100644 index 0da54d56..00000000 --- a/test/unit/development/development_unit_configs/reactions/aqueous_equilibrium/missing_phase.yaml +++ /dev/null @@ -1,21 +0,0 @@ -name: Missing phase -phases: [] -reactions: -- condensed phase: aqueous - condensed-phase water: H2O - k_reverse: 0.32 - products: - - coefficient: 1 - name: B - - coefficient: 1 - name: C - reactants: - - coefficient: 2 - name: A - type: AQUEOUS_EQUILIBRIUM -species: -- name: A -- name: B -- name: C -- name: H2O -version: 2.0.0 diff --git a/test/unit/development/development_unit_configs/reactions/aqueous_equilibrium/unknown_species.json b/test/unit/development/development_unit_configs/reactions/aqueous_equilibrium/unknown_species.json deleted file mode 100644 index d7a16ff8..00000000 --- a/test/unit/development/development_unit_configs/reactions/aqueous_equilibrium/unknown_species.json +++ /dev/null @@ -1,49 +0,0 @@ -{ - "version": "2.0.0", - "name": "Unknown species", - "species": [ - { - "name": "A" - }, - { - "name": "B" - } - ], - "phases": [ - { - "name": "aqueous", - "species": [ - { - "name": "A" - }, - { - "name": "B" - } - ] - } - ], - "reactions": [ - { - "type": "AQUEOUS_EQUILIBRIUM", - "condensed phase": "aqueous", - "condensed-phase water": "H2O", - "k_reverse": 0.32, - "reactants": [ - { - "name": "A", - "coefficient": 2 - } - ], - "products": [ - { - "name": "B", - "coefficient": 1 - }, - { - "name": "C", - "coefficient": 1 - } - ] - } - ] -} \ No newline at end of file diff --git a/test/unit/development/development_unit_configs/reactions/aqueous_equilibrium/unknown_species.yaml b/test/unit/development/development_unit_configs/reactions/aqueous_equilibrium/unknown_species.yaml deleted file mode 100644 index 38bb5b97..00000000 --- a/test/unit/development/development_unit_configs/reactions/aqueous_equilibrium/unknown_species.yaml +++ /dev/null @@ -1,23 +0,0 @@ -name: Unknown species -phases: -- name: aqueous - species: - - name: A - - name: B -reactions: -- condensed phase: aqueous - condensed-phase water: H2O - k_reverse: 0.32 - products: - - coefficient: 1 - name: B - - coefficient: 1 - name: C - reactants: - - coefficient: 2 - name: A - type: AQUEOUS_EQUILIBRIUM -species: -- name: A -- name: B -version: 2.0.0 diff --git a/test/unit/development/development_unit_configs/reactions/aqueous_equilibrium/valid.json b/test/unit/development/development_unit_configs/reactions/aqueous_equilibrium/valid.json deleted file mode 100644 index 6e3c89a4..00000000 --- a/test/unit/development/development_unit_configs/reactions/aqueous_equilibrium/valid.json +++ /dev/null @@ -1,87 +0,0 @@ -{ - "version": "2.0.0", - "name": "Valid aqueous equilibrium", - "species": [ - { - "name": "A" - }, - { - "name": "B" - }, - { - "name": "C" - }, - { - "name": "H2O" - } - ], - "phases": [ - { - "name": "aqueous", - "species": [ - { - "name": "A" - }, - { - "name": "B" - }, - { - "name": "C" - }, - { - "name": "H2O" - } - ] - } - ], - "reactions": [ - { - "type": "AQUEOUS_EQUILIBRIUM", - "condensed phase": "aqueous", - "condensed-phase water": "H2O", - "A": 1.14e-2, - "C": 2300.0, - "k_reverse": 0.32, - "reactants": [ - { - "name": "A", - "coefficient": 2 - } - ], - "products": [ - { - "name": "B", - "coefficient": 1 - }, - { - "name": "C", - "coefficient": 1 - } - ], - "name": "my aqueous eq", - "__comment": "GIF is pronounced with a hard g" - }, - { - "type": "AQUEOUS_EQUILIBRIUM", - "condensed phase": "aqueous", - "condensed-phase water": "H2O", - "k_reverse": 0.32, - "reactants": [ - { - "name": "A", - "coefficient": 2 - } - ], - "products": [ - { - "name": "B", - "coefficient": 1 - }, - { - "name": "C", - "coefficient": 1 - } - ] - } - ] -} \ No newline at end of file diff --git a/test/unit/development/development_unit_configs/reactions/aqueous_equilibrium/valid.yaml b/test/unit/development/development_unit_configs/reactions/aqueous_equilibrium/valid.yaml deleted file mode 100644 index 82be5ab4..00000000 --- a/test/unit/development/development_unit_configs/reactions/aqueous_equilibrium/valid.yaml +++ /dev/null @@ -1,43 +0,0 @@ -name: Valid aqueous equilibrium -phases: -- name: aqueous - species: - - name: A - - name: B - - name: C - - name: H2O -reactions: -- A: 0.0114 - C: 2300.0 - __comment: GIF is pronounced with a hard g - condensed phase: aqueous - condensed-phase water: H2O - k_reverse: 0.32 - name: my aqueous eq - products: - - coefficient: 1 - name: B - - coefficient: 1 - name: C - reactants: - - coefficient: 2 - name: A - type: AQUEOUS_EQUILIBRIUM -- condensed phase: aqueous - condensed-phase water: H2O - k_reverse: 0.32 - products: - - coefficient: 1 - name: B - - coefficient: 1 - name: C - reactants: - - coefficient: 2 - name: A - type: AQUEOUS_EQUILIBRIUM -species: -- name: A -- name: B -- name: C -- name: H2O -version: 2.0.0 diff --git a/test/unit/development/development_unit_configs/reactions/arrhenius/bad_reaction_component.json b/test/unit/development/development_unit_configs/reactions/arrhenius/bad_reaction_component.json deleted file mode 100644 index de4014d6..00000000 --- a/test/unit/development/development_unit_configs/reactions/arrhenius/bad_reaction_component.json +++ /dev/null @@ -1,41 +0,0 @@ -{ - "version": "2.0.0", - "name": "Bad reaction component", - "species": [ - { - "name": "A" - }, - { - "name": "B" - } - ], - "phases": [ - { - "name": "gas", - "species": [ - { - "name": "A" - }, - { - "name": "B" - } - ] - } - ], - "reactions": [ - { - "type": "ARRHENIUS", - "gas phase": "gas", - "reactants": [ - { - "Species name": "A" - } - ], - "products": [ - { - "name": "B" - } - ] - } - ] -} \ No newline at end of file diff --git a/test/unit/development/development_unit_configs/reactions/arrhenius/bad_reaction_component.yaml b/test/unit/development/development_unit_configs/reactions/arrhenius/bad_reaction_component.yaml deleted file mode 100644 index ea232211..00000000 --- a/test/unit/development/development_unit_configs/reactions/arrhenius/bad_reaction_component.yaml +++ /dev/null @@ -1,17 +0,0 @@ -name: Bad reaction component -phases: -- name: gas - species: - - name: A - - name: B -reactions: -- gas phase: gas - products: - - name: B - reactants: - - Species name: A - type: ARRHENIUS -species: -- name: A -- name: B -version: 2.0.0 diff --git a/test/unit/development/development_unit_configs/reactions/arrhenius/missing_phase.json b/test/unit/development/development_unit_configs/reactions/arrhenius/missing_phase.json deleted file mode 100644 index 7ebfab75..00000000 --- a/test/unit/development/development_unit_configs/reactions/arrhenius/missing_phase.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "version": "2.0.0", - "name": "Missing phase", - "species": [ - { - "name": "A" - }, - { - "name": "B" - }, - { - "name": "C" - } - ], - "phases": [], - "reactions": [ - { - "type": "ARRHENIUS", - "gas phase": "gas", - "reactants": [ - { - "name": "A" - } - ], - "products": [ - { - "name": "C" - } - ] - } - ] -} \ No newline at end of file diff --git a/test/unit/development/development_unit_configs/reactions/arrhenius/missing_phase.yaml b/test/unit/development/development_unit_configs/reactions/arrhenius/missing_phase.yaml deleted file mode 100644 index 7d3ceeb6..00000000 --- a/test/unit/development/development_unit_configs/reactions/arrhenius/missing_phase.yaml +++ /dev/null @@ -1,14 +0,0 @@ -name: Missing phase -phases: [] -reactions: -- gas phase: gas - products: - - name: C - reactants: - - name: A - type: ARRHENIUS -species: -- name: A -- name: B -- name: C -version: 2.0.0 diff --git a/test/unit/development/development_unit_configs/reactions/arrhenius/mutually_exclusive.json b/test/unit/development/development_unit_configs/reactions/arrhenius/mutually_exclusive.json deleted file mode 100644 index 0c3f5733..00000000 --- a/test/unit/development/development_unit_configs/reactions/arrhenius/mutually_exclusive.json +++ /dev/null @@ -1,43 +0,0 @@ -{ - "version": "2.0.0", - "name": "Mutually Exclusive", - "species": [ - { - "name": "A" - }, - { - "name": "B" - } - ], - "phases": [ - { - "name": "gas", - "species": [ - { - "name": "A" - }, - { - "name": "B" - } - ] - } - ], - "reactions": [ - { - "type": "ARRHENIUS", - "gas phase": "gas", - "reactants": [ - { - "name": "A" - } - ], - "products": [ - { - "name": "B" - } - ], - "C": 10, - "Ea": 0.5 - } - ] -} \ No newline at end of file diff --git a/test/unit/development/development_unit_configs/reactions/arrhenius/mutually_exclusive.yaml b/test/unit/development/development_unit_configs/reactions/arrhenius/mutually_exclusive.yaml deleted file mode 100644 index 3165dfc7..00000000 --- a/test/unit/development/development_unit_configs/reactions/arrhenius/mutually_exclusive.yaml +++ /dev/null @@ -1,19 +0,0 @@ -name: Mutually Exclusive -phases: -- name: gas - species: - - name: A - - name: B -reactions: -- C: 10 - Ea: 0.5 - gas phase: gas - products: - - name: B - reactants: - - name: A - type: ARRHENIUS -species: -- name: A -- name: B -version: 2.0.0 diff --git a/test/unit/development/development_unit_configs/reactions/arrhenius/unknown_species.json b/test/unit/development/development_unit_configs/reactions/arrhenius/unknown_species.json deleted file mode 100644 index 7e0cdddf..00000000 --- a/test/unit/development/development_unit_configs/reactions/arrhenius/unknown_species.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - "version": "2.0.0", - "name": "Unknown species", - "species": [ - { - "name": "A" - }, - { - "name": "B" - } - ], - "phases": [ - { - "name": "gas", - "species": [ - { - "name": "A" - }, - { - "name": "B" - } - ] - } - ], - "reactions": [ - { - "type": "ARRHENIUS", - "name": "Arrhenius", - "gas phase": "gas", - "reactants": [ - { - "name": "D" - } - ], - "products": [ - { - "name": "C" - } - ] - } - ] -} \ No newline at end of file diff --git a/test/unit/development/development_unit_configs/reactions/arrhenius/unknown_species.yaml b/test/unit/development/development_unit_configs/reactions/arrhenius/unknown_species.yaml deleted file mode 100644 index 8a962236..00000000 --- a/test/unit/development/development_unit_configs/reactions/arrhenius/unknown_species.yaml +++ /dev/null @@ -1,18 +0,0 @@ -name: Unknown species -phases: -- name: gas - species: - - name: A - - name: B -reactions: -- gas phase: gas - products: - - name: C - reactants: - - name: D - type: ARRHENIUS - name: Arrhenius -species: -- name: A -- name: B -version: 2.0.0 diff --git a/test/unit/development/development_unit_configs/reactions/arrhenius/valid.json b/test/unit/development/development_unit_configs/reactions/arrhenius/valid.json deleted file mode 100644 index 30a8d201..00000000 --- a/test/unit/development/development_unit_configs/reactions/arrhenius/valid.json +++ /dev/null @@ -1,101 +0,0 @@ -{ - "version": "2.0.0", - "name": "Valid arrhenius", - "species": [ - { - "name": "A" - }, - { - "name": "B" - }, - { - "name": "C" - } - ], - "phases": [ - { - "name": "gas", - "species": [ - { - "name": "A" - }, - { - "name": "B" - }, - { - "name": "C" - } - ] - } - ], - "reactions": [ - { - "type": "ARRHENIUS", - "gas phase": "gas", - "reactants": [ - { - "name": "A", - "coefficient": 1 - } - ], - "products": [ - { - "name": "B", - "coefficient": 1.2 - }, - { - "name": "C", - "coefficient": 0.3 - } - ], - "A": 32.1, - "B": -2.3, - "C": 102.3, - "D": 63.4, - "E": -1.3, - "name": "my arrhenius", - "__solver_param": 0.1 - }, - { - "type": "ARRHENIUS", - "gas phase": "gas", - "reactants": [ - { - "name": "A", - "coefficient": 2 - }, - { - "name": "B", - "coefficient": 0.1 - } - ], - "products": [ - { - "name": "C", - "coefficient": 0.5, - "__optional thing": "hello" - } - ], - "A": 3.1, - "B": -0.3, - "C": 12.3, - "D": 6.4, - "E": -0.3, - "name": "my arrhenius2" - }, - { - "type": "ARRHENIUS", - "gas phase": "gas", - "reactants": [ - { - "name": "A" - } - ], - "products": [ - { - "name": "C" - } - ] - } - ] -} \ No newline at end of file diff --git a/test/unit/development/development_unit_configs/reactions/arrhenius/valid.yaml b/test/unit/development/development_unit_configs/reactions/arrhenius/valid.yaml deleted file mode 100644 index 54f356dd..00000000 --- a/test/unit/development/development_unit_configs/reactions/arrhenius/valid.yaml +++ /dev/null @@ -1,53 +0,0 @@ -name: Valid arrhenius -phases: -- name: gas - species: - - name: A - - name: B - - name: C -reactions: -- A: 32.1 - B: -2.3 - C: 102.3 - D: 63.4 - E: -1.3 - __solver_param: 0.1 - gas phase: gas - name: my arrhenius - products: - - coefficient: 1.2 - name: B - - coefficient: 0.3 - name: C - reactants: - - coefficient: 1 - name: A - type: ARRHENIUS -- A: 3.1 - B: -0.3 - C: 12.3 - D: 6.4 - E: -0.3 - gas phase: gas - name: my arrhenius2 - products: - - __optional thing: hello - coefficient: 0.5 - name: C - reactants: - - coefficient: 2 - name: A - - coefficient: 0.1 - name: B - type: ARRHENIUS -- gas phase: gas - products: - - name: C - reactants: - - name: A - type: ARRHENIUS -species: -- name: A -- name: B -- name: C -version: 2.0.0 diff --git a/test/unit/development/development_unit_configs/reactions/branched/bad_reaction_component.json b/test/unit/development/development_unit_configs/reactions/branched/bad_reaction_component.json deleted file mode 100644 index 2433c84e..00000000 --- a/test/unit/development/development_unit_configs/reactions/branched/bad_reaction_component.json +++ /dev/null @@ -1,65 +0,0 @@ -{ - "version": "2.0.0", - "name": "Bad reaction component", - "species": [ - { - "name": "A" - }, - { - "name": "B" - }, - { - "name": "C" - } - ], - "phases": [ - { - "name": "gas", - "species": [ - { - "name": "A" - }, - { - "name": "B" - }, - { - "name": "C" - } - ] - } - ], - "reactions": [ - { - "type": "BRANCHED_NO_RO2", - "gas phase": "gas", - "reactants": [ - { - "Species name": "A" - } - ], - "alkoxy products": [ - { - "name": "B", - "coefficient": 0.2 - }, - { - "name": "A", - "coefficient": 1.2 - } - ], - "nitrate products": [ - { - "name": "C", - "coefficient": 1.2, - "__thing": "hi" - } - ], - "X": 1.2e-4, - "Y": 167, - "a0": 0.15, - "n": 9, - "name": "my branched", - "__comment": "thing" - } - ] -} \ No newline at end of file diff --git a/test/unit/development/development_unit_configs/reactions/branched/bad_reaction_component.yaml b/test/unit/development/development_unit_configs/reactions/branched/bad_reaction_component.yaml deleted file mode 100644 index 8b3c91d6..00000000 --- a/test/unit/development/development_unit_configs/reactions/branched/bad_reaction_component.yaml +++ /dev/null @@ -1,32 +0,0 @@ -name: Bad reaction component -phases: -- name: gas - species: - - name: A - - name: B - - name: C -reactions: -- X: 0.00012 - Y: 167 - __comment: thing - a0: 0.15 - alkoxy products: - - coefficient: 0.2 - name: B - - coefficient: 1.2 - name: A - gas phase: gas - n: 9 - name: my branched - nitrate products: - - __thing: hi - coefficient: 1.2 - name: C - reactants: - - Species name: A - type: BRANCHED_NO_RO2 -species: -- name: A -- name: B -- name: C -version: 2.0.0 diff --git a/test/unit/development/development_unit_configs/reactions/branched/missing_phase.json b/test/unit/development/development_unit_configs/reactions/branched/missing_phase.json deleted file mode 100644 index 5f9e21b4..00000000 --- a/test/unit/development/development_unit_configs/reactions/branched/missing_phase.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "version": "2.0.0", - "name": "Missing phase", - "species": [ - { - "name": "A" - }, - { - "name": "B" - }, - { - "name": "C" - } - ], - "phases": [], - "reactions": [ - { - "type": "BRANCHED_NO_RO2", - "gas phase": "gas", - "reactants": [ - { - "name": "A" - } - ], - "alkoxy products": [ - { - "name": "B", - "coefficient": 0.2 - }, - { - "name": "A", - "coefficient": 1.2 - } - ], - "nitrate products": [ - { - "name": "C", - "coefficient": 1.2, - "__thing": "hi" - } - ], - "X": 1.2e-4, - "Y": 167, - "a0": 0.15, - "n": 9, - "name": "my branched", - "__comment": "thing" - } - ] -} \ No newline at end of file diff --git a/test/unit/development/development_unit_configs/reactions/branched/missing_phase.yaml b/test/unit/development/development_unit_configs/reactions/branched/missing_phase.yaml deleted file mode 100644 index fe0aa204..00000000 --- a/test/unit/development/development_unit_configs/reactions/branched/missing_phase.yaml +++ /dev/null @@ -1,27 +0,0 @@ -name: Missing phase -phases: [] -reactions: -- X: 0.00012 - Y: 167 - __comment: thing - a0: 0.15 - alkoxy products: - - coefficient: 0.2 - name: B - - coefficient: 1.2 - name: A - gas phase: gas - n: 9 - name: my branched - nitrate products: - - __thing: hi - coefficient: 1.2 - name: C - reactants: - - name: A - type: BRANCHED_NO_RO2 -species: -- name: A -- name: B -- name: C -version: 2.0.0 diff --git a/test/unit/development/development_unit_configs/reactions/branched/unknown_species.json b/test/unit/development/development_unit_configs/reactions/branched/unknown_species.json deleted file mode 100644 index e7ee16d8..00000000 --- a/test/unit/development/development_unit_configs/reactions/branched/unknown_species.json +++ /dev/null @@ -1,59 +0,0 @@ -{ - "version": "2.0.0", - "name": "Unknown species", - "species": [ - { - "name": "A" - }, - { - "name": "B" - } - ], - "phases": [ - { - "name": "gas", - "species": [ - { - "name": "A" - }, - { - "name": "B" - } - ] - } - ], - "reactions": [ - { - "type": "BRANCHED_NO_RO2", - "gas phase": "gas", - "reactants": [ - { - "name": "A" - } - ], - "alkoxy products": [ - { - "name": "B", - "coefficient": 0.2 - }, - { - "name": "A", - "coefficient": 1.2 - } - ], - "nitrate products": [ - { - "name": "C", - "coefficient": 1.2, - "__thing": "hi" - } - ], - "X": 1.2e-4, - "Y": 167, - "a0": 0.15, - "n": 9, - "name": "my branched", - "__comment": "thing" - } - ] -} \ No newline at end of file diff --git a/test/unit/development/development_unit_configs/reactions/branched/unknown_species.yaml b/test/unit/development/development_unit_configs/reactions/branched/unknown_species.yaml deleted file mode 100644 index 191f97bd..00000000 --- a/test/unit/development/development_unit_configs/reactions/branched/unknown_species.yaml +++ /dev/null @@ -1,30 +0,0 @@ -name: Unknown species -phases: -- name: gas - species: - - name: A - - name: B -reactions: -- X: 0.00012 - Y: 167 - __comment: thing - a0: 0.15 - alkoxy products: - - coefficient: 0.2 - name: B - - coefficient: 1.2 - name: A - gas phase: gas - n: 9 - name: my branched - nitrate products: - - __thing: hi - coefficient: 1.2 - name: C - reactants: - - name: A - type: BRANCHED_NO_RO2 -species: -- name: A -- name: B -version: 2.0.0 diff --git a/test/unit/development/development_unit_configs/reactions/branched/valid.json b/test/unit/development/development_unit_configs/reactions/branched/valid.json deleted file mode 100644 index d5b10444..00000000 --- a/test/unit/development/development_unit_configs/reactions/branched/valid.json +++ /dev/null @@ -1,65 +0,0 @@ -{ - "version": "2.0.0", - "name": "Valid branched", - "species": [ - { - "name": "A" - }, - { - "name": "B" - }, - { - "name": "C" - } - ], - "phases": [ - { - "name": "gas", - "species": [ - { - "name": "A" - }, - { - "name": "B" - }, - { - "name": "C" - } - ] - } - ], - "reactions": [ - { - "type": "BRANCHED_NO_RO2", - "gas phase": "gas", - "reactants": [ - { - "name": "A" - } - ], - "alkoxy products": [ - { - "name": "B", - "coefficient": 0.2 - }, - { - "name": "A", - "coefficient": 1.2 - } - ], - "nitrate products": [ - { - "name": "C", - "coefficient": 1.2, - "__thing": "hi" - } - ], - "X": 1.2e-4, - "Y": 167, - "a0": 0.15, - "n": 9, - "name": "my branched", - "__comment": "thing" - } - ] -} \ No newline at end of file diff --git a/test/unit/development/development_unit_configs/reactions/branched/valid.yaml b/test/unit/development/development_unit_configs/reactions/branched/valid.yaml deleted file mode 100644 index f0bdeb88..00000000 --- a/test/unit/development/development_unit_configs/reactions/branched/valid.yaml +++ /dev/null @@ -1,32 +0,0 @@ -name: Valid branched -phases: -- name: gas - species: - - name: A - - name: B - - name: C -reactions: -- X: 0.00012 - Y: 167 - __comment: thing - a0: 0.15 - alkoxy products: - - coefficient: 0.2 - name: B - - coefficient: 1.2 - name: A - gas phase: gas - n: 9 - name: my branched - nitrate products: - - __thing: hi - coefficient: 1.2 - name: C - reactants: - - name: A - type: BRANCHED_NO_RO2 -species: -- name: A -- name: B -- name: C -version: 2.0.0 diff --git a/test/unit/development/development_unit_configs/reactions/condensed_phase_arrhenius/bad_reaction_component.json b/test/unit/development/development_unit_configs/reactions/condensed_phase_arrhenius/bad_reaction_component.json deleted file mode 100644 index b9a3f1eb..00000000 --- a/test/unit/development/development_unit_configs/reactions/condensed_phase_arrhenius/bad_reaction_component.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "version": "2.0.0", - "name": "Bad reaction component", - "species": [ - { - "name": "A" - }, - { - "name": "B" - }, - { - "name": "H2O" - } - ], - "phases": [ - { - "name": "aqueous", - "species": [ - { - "name": "A" - }, - { - "name": "B" - }, - { - "name": "H2O" - } - ] - } - ], - "reactions": [ - { - "type": "CONDENSED_PHASE_ARRHENIUS", - "condensed phase": "aqueous", - "reactants": [ - { - "Name": "A" - } - ], - "products": [ - { - "name": "B" - } - ] - } - ] -} \ No newline at end of file diff --git a/test/unit/development/development_unit_configs/reactions/condensed_phase_arrhenius/bad_reaction_component.yaml b/test/unit/development/development_unit_configs/reactions/condensed_phase_arrhenius/bad_reaction_component.yaml deleted file mode 100644 index 9fb842c6..00000000 --- a/test/unit/development/development_unit_configs/reactions/condensed_phase_arrhenius/bad_reaction_component.yaml +++ /dev/null @@ -1,19 +0,0 @@ -name: Bad reaction component -phases: -- name: aqueous - species: - - name: A - - name: B - - name: H2O -reactions: -- condensed phase: aqueous - products: - - name: B - reactants: - - Name: A - type: CONDENSED_PHASE_ARRHENIUS -species: -- name: A -- name: B -- name: H2O -version: 2.0.0 diff --git a/test/unit/development/development_unit_configs/reactions/condensed_phase_arrhenius/missing_phase.json b/test/unit/development/development_unit_configs/reactions/condensed_phase_arrhenius/missing_phase.json deleted file mode 100644 index a2518c4f..00000000 --- a/test/unit/development/development_unit_configs/reactions/condensed_phase_arrhenius/missing_phase.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "version": "2.0.0", - "name": "Missing phase", - "species": [ - { - "name": "A" - }, - { - "name": "B" - }, - { - "name": "C" - }, - { - "name": "H2O" - } - ], - "phases": [], - "reactions": [ - { - "type": "CONDENSED_PHASE_ARRHENIUS", - "condensed phase": "aqueous", - "reactants": [ - { - "name": "A" - } - ], - "products": [ - { - "name": "C" - } - ] - } - ] -} \ No newline at end of file diff --git a/test/unit/development/development_unit_configs/reactions/condensed_phase_arrhenius/missing_phase.yaml b/test/unit/development/development_unit_configs/reactions/condensed_phase_arrhenius/missing_phase.yaml deleted file mode 100644 index 9af64e90..00000000 --- a/test/unit/development/development_unit_configs/reactions/condensed_phase_arrhenius/missing_phase.yaml +++ /dev/null @@ -1,15 +0,0 @@ -name: Missing phase -phases: [] -reactions: -- condensed phase: aqueous - products: - - name: C - reactants: - - name: A - type: CONDENSED_PHASE_ARRHENIUS -species: -- name: A -- name: B -- name: C -- name: H2O -version: 2.0.0 diff --git a/test/unit/development/development_unit_configs/reactions/condensed_phase_arrhenius/mutually_exclusive.json b/test/unit/development/development_unit_configs/reactions/condensed_phase_arrhenius/mutually_exclusive.json deleted file mode 100644 index 07dfe1b1..00000000 --- a/test/unit/development/development_unit_configs/reactions/condensed_phase_arrhenius/mutually_exclusive.json +++ /dev/null @@ -1,49 +0,0 @@ -{ - "version": "2.0.0", - "name": "Mutually Exclusive", - "species": [ - { - "name": "A" - }, - { - "name": "B" - }, - { - "name": "H2O" - } - ], - "phases": [ - { - "name": "aqueous", - "species": [ - { - "name": "A" - }, - { - "name": "B" - }, - { - "name": "H2O" - } - ] - } - ], - "reactions": [ - { - "type": "CONDENSED_PHASE_ARRHENIUS", - "condensed phase": "aqueous", - "reactants": [ - { - "name": "A" - } - ], - "products": [ - { - "name": "B" - } - ], - "C": 10, - "Ea": 0.5 - } - ] -} \ No newline at end of file diff --git a/test/unit/development/development_unit_configs/reactions/condensed_phase_arrhenius/mutually_exclusive.yaml b/test/unit/development/development_unit_configs/reactions/condensed_phase_arrhenius/mutually_exclusive.yaml deleted file mode 100644 index 708caaab..00000000 --- a/test/unit/development/development_unit_configs/reactions/condensed_phase_arrhenius/mutually_exclusive.yaml +++ /dev/null @@ -1,21 +0,0 @@ -name: Mutually Exclusive -phases: -- name: aqueous - species: - - name: A - - name: B - - name: H2O -reactions: -- C: 10 - Ea: 0.5 - condensed phase: aqueous - products: - - name: B - reactants: - - name: A - type: CONDENSED_PHASE_ARRHENIUS -species: -- name: A -- name: B -- name: H2O -version: 2.0.0 diff --git a/test/unit/development/development_unit_configs/reactions/condensed_phase_arrhenius/species_not_in_aqueous_phase.json b/test/unit/development/development_unit_configs/reactions/condensed_phase_arrhenius/species_not_in_aqueous_phase.json deleted file mode 100644 index 419da12b..00000000 --- a/test/unit/development/development_unit_configs/reactions/condensed_phase_arrhenius/species_not_in_aqueous_phase.json +++ /dev/null @@ -1,104 +0,0 @@ -{ - "version": "2.0.0", - "name": "Condensed phase arrhenius using species not in its requested condensed phase", - "species": [ - { - "name": "A" - }, - { - "name": "B" - }, - { - "name": "C" - }, - { - "name": "H2O" - } - ], - "phases": [ - { - "name": "aqueous", - "species": [ - { - "name": "A" - }, - { - "name": "C" - }, - { - "name": "H2O" - } - ] - } - ], - "reactions": [ - { - "type": "CONDENSED_PHASE_ARRHENIUS", - "condensed phase": "aqueous", - "reactants": [ - { - "name": "A", - "coefficient": 1 - } - ], - "products": [ - { - "name": "B", - "coefficient": 1.2 - }, - { - "name": "C", - "coefficient": 0.3 - } - ], - "A": 32.1, - "B": -2.3, - "C": 102.3, - "D": 63.4, - "E": -1.3, - "name": "my arrhenius", - "__solver_param": 0.1 - }, - { - "type": "CONDENSED_PHASE_ARRHENIUS", - "condensed phase": "aqueous", - "reactants": [ - { - "name": "A", - "coefficient": 2 - }, - { - "name": "B", - "coefficient": 0.1 - } - ], - "products": [ - { - "name": "C", - "coefficient": 0.5, - "__optional thing": "hello" - } - ], - "A": 3.1, - "B": -0.3, - "C": 12.3, - "D": 6.4, - "E": -0.3, - "name": "my arrhenius2" - }, - { - "type": "CONDENSED_PHASE_ARRHENIUS", - "condensed phase": "aqueous", - "reactants": [ - { - "name": "A" - } - ], - "products": [ - { - "name": "C" - } - ] - } - ] -} \ No newline at end of file diff --git a/test/unit/development/development_unit_configs/reactions/condensed_phase_arrhenius/species_not_in_aqueous_phase.yaml b/test/unit/development/development_unit_configs/reactions/condensed_phase_arrhenius/species_not_in_aqueous_phase.yaml deleted file mode 100644 index 5fb21e55..00000000 --- a/test/unit/development/development_unit_configs/reactions/condensed_phase_arrhenius/species_not_in_aqueous_phase.yaml +++ /dev/null @@ -1,54 +0,0 @@ -name: Condensed phase arrhenius using species not in its requested condensed phase -phases: -- name: aqueous - species: - - name: A - - name: C - - name: H2O -reactions: -- A: 32.1 - B: -2.3 - C: 102.3 - D: 63.4 - E: -1.3 - __solver_param: 0.1 - condensed phase: aqueous - name: my arrhenius - products: - - coefficient: 1.2 - name: B - - coefficient: 0.3 - name: C - reactants: - - coefficient: 1 - name: A - type: CONDENSED_PHASE_ARRHENIUS -- A: 3.1 - B: -0.3 - C: 12.3 - D: 6.4 - E: -0.3 - condensed phase: aqueous - name: my arrhenius2 - products: - - __optional thing: hello - coefficient: 0.5 - name: C - reactants: - - coefficient: 2 - name: A - - coefficient: 0.1 - name: B - type: CONDENSED_PHASE_ARRHENIUS -- condensed phase: aqueous - products: - - name: C - reactants: - - name: A - type: CONDENSED_PHASE_ARRHENIUS -species: -- name: A -- name: B -- name: C -- name: H2O -version: 2.0.0 diff --git a/test/unit/development/development_unit_configs/reactions/condensed_phase_arrhenius/unknown_species.json b/test/unit/development/development_unit_configs/reactions/condensed_phase_arrhenius/unknown_species.json deleted file mode 100644 index 0a095c87..00000000 --- a/test/unit/development/development_unit_configs/reactions/condensed_phase_arrhenius/unknown_species.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "version": "2.0.0", - "name": "Unknown species", - "species": [ - { - "name": "A" - }, - { - "name": "B" - }, - { - "name": "H2O" - } - ], - "phases": [ - { - "name": "aqueous", - "species": [ - { - "name": "A" - }, - { - "name": "B" - }, - { - "name": "H2O" - } - ] - } - ], - "reactions": [ - { - "type": "CONDENSED_PHASE_ARRHENIUS", - "condensed phase": "aqueous", - "reactants": [ - { - "name": "A" - } - ], - "products": [ - { - "name": "C" - } - ] - } - ] -} \ No newline at end of file diff --git a/test/unit/development/development_unit_configs/reactions/condensed_phase_arrhenius/unknown_species.yaml b/test/unit/development/development_unit_configs/reactions/condensed_phase_arrhenius/unknown_species.yaml deleted file mode 100644 index 210aeaa8..00000000 --- a/test/unit/development/development_unit_configs/reactions/condensed_phase_arrhenius/unknown_species.yaml +++ /dev/null @@ -1,19 +0,0 @@ -name: Unknown species -phases: -- name: aqueous - species: - - name: A - - name: B - - name: H2O -reactions: -- condensed phase: aqueous - products: - - name: C - reactants: - - name: A - type: CONDENSED_PHASE_ARRHENIUS -species: -- name: A -- name: B -- name: H2O -version: 2.0.0 diff --git a/test/unit/development/development_unit_configs/reactions/condensed_phase_arrhenius/valid.json b/test/unit/development/development_unit_configs/reactions/condensed_phase_arrhenius/valid.json deleted file mode 100644 index c21a90da..00000000 --- a/test/unit/development/development_unit_configs/reactions/condensed_phase_arrhenius/valid.json +++ /dev/null @@ -1,107 +0,0 @@ -{ - "version": "2.0.0", - "name": "Valid condensed phase arrhenius", - "species": [ - { - "name": "A" - }, - { - "name": "B" - }, - { - "name": "C" - }, - { - "name": "H2O" - } - ], - "phases": [ - { - "name": "aqueous", - "species": [ - { - "name": "A" - }, - { - "name": "B" - }, - { - "name": "C" - }, - { - "name": "H2O" - } - ] - } - ], - "reactions": [ - { - "type": "CONDENSED_PHASE_ARRHENIUS", - "condensed phase": "aqueous", - "reactants": [ - { - "name": "A", - "coefficient": 1 - } - ], - "products": [ - { - "name": "B", - "coefficient": 1.2 - }, - { - "name": "C", - "coefficient": 0.3 - } - ], - "A": 32.1, - "B": -2.3, - "C": 102.3, - "D": 63.4, - "E": -1.3, - "name": "my arrhenius", - "__solver_param": 0.1 - }, - { - "type": "CONDENSED_PHASE_ARRHENIUS", - "condensed phase": "aqueous", - "reactants": [ - { - "name": "A", - "coefficient": 2 - }, - { - "name": "B", - "coefficient": 0.1 - } - ], - "products": [ - { - "name": "C", - "coefficient": 0.5, - "__optional thing": "hello" - } - ], - "A": 3.1, - "B": -0.3, - "C": 12.3, - "D": 6.4, - "E": -0.3, - "name": "my arrhenius2" - }, - { - "type": "CONDENSED_PHASE_ARRHENIUS", - "condensed phase": "aqueous", - "reactants": [ - { - "name": "A" - } - ], - "products": [ - { - "name": "C" - } - ] - } - ] -} \ No newline at end of file diff --git a/test/unit/development/development_unit_configs/reactions/condensed_phase_arrhenius/valid.yaml b/test/unit/development/development_unit_configs/reactions/condensed_phase_arrhenius/valid.yaml deleted file mode 100644 index 22e13f65..00000000 --- a/test/unit/development/development_unit_configs/reactions/condensed_phase_arrhenius/valid.yaml +++ /dev/null @@ -1,55 +0,0 @@ -name: Valid condensed phase arrhenius -phases: -- name: aqueous - species: - - name: A - - name: B - - name: C - - name: H2O -reactions: -- A: 32.1 - B: -2.3 - C: 102.3 - D: 63.4 - E: -1.3 - __solver_param: 0.1 - condensed phase: aqueous - name: my arrhenius - products: - - coefficient: 1.2 - name: B - - coefficient: 0.3 - name: C - reactants: - - coefficient: 1 - name: A - type: CONDENSED_PHASE_ARRHENIUS -- A: 3.1 - B: -0.3 - C: 12.3 - D: 6.4 - E: -0.3 - condensed phase: aqueous - name: my arrhenius2 - products: - - __optional thing: hello - coefficient: 0.5 - name: C - reactants: - - coefficient: 2 - name: A - - coefficient: 0.1 - name: B - type: CONDENSED_PHASE_ARRHENIUS -- condensed phase: aqueous - products: - - name: C - reactants: - - name: A - type: CONDENSED_PHASE_ARRHENIUS -species: -- name: A -- name: B -- name: C -- name: H2O -version: 2.0.0 diff --git a/test/unit/development/development_unit_configs/reactions/condensed_phase_photolysis/bad_reaction_component.json b/test/unit/development/development_unit_configs/reactions/condensed_phase_photolysis/bad_reaction_component.json deleted file mode 100644 index fcee9c1a..00000000 --- a/test/unit/development/development_unit_configs/reactions/condensed_phase_photolysis/bad_reaction_component.json +++ /dev/null @@ -1,55 +0,0 @@ -{ - "version": "2.0.0", - "name": "Bad reaction component", - "species": [ - { - "name": "A" - }, - { - "name": "B" - }, - { - "name": "C" - }, - { - "name": "H2O" - } - ], - "phases": [ - { - "name": "aqueous", - "species": [ - { - "name": "A" - }, - { - "name": "B" - }, - { - "name": "C" - }, - { - "name": "H2O" - } - ] - } - ], - "reactions": [ - { - "type": "CONDENSED_PHASE_PHOTOLYSIS", - "condensed phase": "aqueous", - "reactants": [ - { - "name": "A", - "Coefficient": 1.2 - } - ], - "products": [ - { - "name": "B", - "coefficient": 0.2 - } - ] - } - ] -} \ No newline at end of file diff --git a/test/unit/development/development_unit_configs/reactions/condensed_phase_photolysis/bad_reaction_component.yaml b/test/unit/development/development_unit_configs/reactions/condensed_phase_photolysis/bad_reaction_component.yaml deleted file mode 100644 index b990b5a7..00000000 --- a/test/unit/development/development_unit_configs/reactions/condensed_phase_photolysis/bad_reaction_component.yaml +++ /dev/null @@ -1,23 +0,0 @@ -name: Bad reaction component -phases: -- name: aqueous - species: - - name: A - - name: B - - name: C - - name: H2O -reactions: -- condensed phase: aqueous - products: - - coefficient: 0.2 - name: B - reactants: - - Coefficient: 1.2 - name: A - type: CONDENSED_PHASE_PHOTOLYSIS -species: -- name: A -- name: B -- name: C -- name: H2O -version: 2.0.0 diff --git a/test/unit/development/development_unit_configs/reactions/condensed_phase_photolysis/missing_phase.json b/test/unit/development/development_unit_configs/reactions/condensed_phase_photolysis/missing_phase.json deleted file mode 100644 index d733db96..00000000 --- a/test/unit/development/development_unit_configs/reactions/condensed_phase_photolysis/missing_phase.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "version": "2.0.0", - "name": "Missing phase", - "species": [ - { - "name": "A" - }, - { - "name": "B" - }, - { - "name": "C" - }, - { - "name": "H2O" - } - ], - "phases": [], - "reactions": [ - { - "type": "CONDENSED_PHASE_PHOTOLYSIS", - "condensed phase": "aqueous", - "reactants": [ - { - "name": "B", - "coefficient": 1.2 - } - ], - "products": [ - { - "name": "C", - "coefficient": 0.2 - } - ] - } - ] -} \ No newline at end of file diff --git a/test/unit/development/development_unit_configs/reactions/condensed_phase_photolysis/missing_phase.yaml b/test/unit/development/development_unit_configs/reactions/condensed_phase_photolysis/missing_phase.yaml deleted file mode 100644 index e517cb4c..00000000 --- a/test/unit/development/development_unit_configs/reactions/condensed_phase_photolysis/missing_phase.yaml +++ /dev/null @@ -1,17 +0,0 @@ -name: Missing phase -phases: [] -reactions: -- condensed phase: aqueous - products: - - coefficient: 0.2 - name: C - reactants: - - coefficient: 1.2 - name: B - type: CONDENSED_PHASE_PHOTOLYSIS -species: -- name: A -- name: B -- name: C -- name: H2O -version: 2.0.0 diff --git a/test/unit/development/development_unit_configs/reactions/condensed_phase_photolysis/more_than_one_reactant.json b/test/unit/development/development_unit_configs/reactions/condensed_phase_photolysis/more_than_one_reactant.json deleted file mode 100644 index e3eaf29d..00000000 --- a/test/unit/development/development_unit_configs/reactions/condensed_phase_photolysis/more_than_one_reactant.json +++ /dev/null @@ -1,57 +0,0 @@ -{ - "version": "2.0.0", - "name": "more than one reactant", - "species": [ - { - "name": "A" - }, - { - "name": "B" - }, - { - "name": "C" - }, - { - "name": "H2O" - } - ], - "phases": [ - { - "name": "aqueous", - "species": [ - { - "name": "A" - }, - { - "name": "B" - }, - { - "name": "C" - }, - { - "name": "H2O" - } - ] - } - ], - "reactions": [ - { - "type": "CONDENSED_PHASE_PHOTOLYSIS", - "condensed phase": "aqueous", - "reactants": [ - { - "name": "A" - }, - { - "name": "B" - } - ], - "products": [ - { - "name": "C", - "coefficient": 0.2 - } - ] - } - ] -} \ No newline at end of file diff --git a/test/unit/development/development_unit_configs/reactions/condensed_phase_photolysis/more_than_one_reactant.yaml b/test/unit/development/development_unit_configs/reactions/condensed_phase_photolysis/more_than_one_reactant.yaml deleted file mode 100644 index 980380bb..00000000 --- a/test/unit/development/development_unit_configs/reactions/condensed_phase_photolysis/more_than_one_reactant.yaml +++ /dev/null @@ -1,23 +0,0 @@ -name: more than one reactant -phases: -- name: aqueous - species: - - name: A - - name: B - - name: C - - name: H2O -reactions: -- condensed phase: aqueous - products: - - coefficient: 0.2 - name: C - reactants: - - name: A - - name: B - type: CONDENSED_PHASE_PHOTOLYSIS -species: -- name: A -- name: B -- name: C -- name: H2O -version: 2.0.0 diff --git a/test/unit/development/development_unit_configs/reactions/condensed_phase_photolysis/species_not_in_aqueous_phase.json b/test/unit/development/development_unit_configs/reactions/condensed_phase_photolysis/species_not_in_aqueous_phase.json deleted file mode 100644 index cbd06486..00000000 --- a/test/unit/development/development_unit_configs/reactions/condensed_phase_photolysis/species_not_in_aqueous_phase.json +++ /dev/null @@ -1,56 +0,0 @@ -{ - "version": "2.0.0", - "name": "Condensed phase photolysis using species not in its requested condensed phase", - "species": [ - { - "name": "A" - }, - { - "name": "B" - }, - { - "name": "C" - }, - { - "name": "H2O" - } - ], - "phases": [ - { - "name": "aqueous", - "species": [ - { - "name": "A" - }, - { - "name": "C" - }, - { - "name": "H2O" - } - ] - } - ], - "reactions": [ - { - "type": "CONDENSED_PHASE_PHOTOLYSIS", - "condensed phase": "aqueous", - "reactants": [ - { - "name": "A", - "coefficient": 1 - } - ], - "products": [ - { - "name": "B", - "coefficient": 1.2 - }, - { - "name": "C", - "coefficient": 0.3 - } - ] - } - ] -} \ No newline at end of file diff --git a/test/unit/development/development_unit_configs/reactions/condensed_phase_photolysis/species_not_in_aqueous_phase.yaml b/test/unit/development/development_unit_configs/reactions/condensed_phase_photolysis/species_not_in_aqueous_phase.yaml deleted file mode 100644 index 9c6b8600..00000000 --- a/test/unit/development/development_unit_configs/reactions/condensed_phase_photolysis/species_not_in_aqueous_phase.yaml +++ /dev/null @@ -1,24 +0,0 @@ -name: Condensed phase photolysis using species not in its requested condensed phase -phases: -- name: aqueous - species: - - name: A - - name: C - - name: H2O -reactions: -- condensed phase: aqueous - products: - - coefficient: 1.2 - name: B - - coefficient: 0.3 - name: C - reactants: - - coefficient: 1 - name: A - type: CONDENSED_PHASE_PHOTOLYSIS -species: -- name: A -- name: B -- name: C -- name: H2O -version: 2.0.0 diff --git a/test/unit/development/development_unit_configs/reactions/condensed_phase_photolysis/unknown_species.json b/test/unit/development/development_unit_configs/reactions/condensed_phase_photolysis/unknown_species.json deleted file mode 100644 index 6a9365c9..00000000 --- a/test/unit/development/development_unit_configs/reactions/condensed_phase_photolysis/unknown_species.json +++ /dev/null @@ -1,43 +0,0 @@ -{ - "version": "2.0.0", - "name": "Unknown species", - "species": [ - { - "name": "A" - }, - { - "name": "B" - } - ], - "phases": [ - { - "name": "aqueous", - "species": [ - { - "name": "A" - }, - { - "name": "B" - } - ] - } - ], - "reactions": [ - { - "type": "CONDENSED_PHASE_PHOTOLYSIS", - "condensed phase": "aqueous", - "reactants": [ - { - "name": "A", - "coefficient": 1.2 - } - ], - "products": [ - { - "name": "C", - "coefficient": 0.2 - } - ] - } - ] -} \ No newline at end of file diff --git a/test/unit/development/development_unit_configs/reactions/condensed_phase_photolysis/unknown_species.yaml b/test/unit/development/development_unit_configs/reactions/condensed_phase_photolysis/unknown_species.yaml deleted file mode 100644 index 26ecb52c..00000000 --- a/test/unit/development/development_unit_configs/reactions/condensed_phase_photolysis/unknown_species.yaml +++ /dev/null @@ -1,19 +0,0 @@ -name: Unknown species -phases: -- name: aqueous - species: - - name: A - - name: B -reactions: -- condensed phase: aqueous - products: - - coefficient: 0.2 - name: C - reactants: - - coefficient: 1.2 - name: A - type: CONDENSED_PHASE_PHOTOLYSIS -species: -- name: A -- name: B -version: 2.0.0 diff --git a/test/unit/development/development_unit_configs/reactions/condensed_phase_photolysis/valid.json b/test/unit/development/development_unit_configs/reactions/condensed_phase_photolysis/valid.json deleted file mode 100644 index 05d65ad3..00000000 --- a/test/unit/development/development_unit_configs/reactions/condensed_phase_photolysis/valid.json +++ /dev/null @@ -1,74 +0,0 @@ -{ - "version": "2.0.0", - "name": "Valid surface", - "species": [ - { - "name": "A" - }, - { - "name": "B" - }, - { - "name": "C" - }, - { - "name": "H2O" - } - ], - "phases": [ - { - "name": "aqueous", - "species": [ - { - "name": "A" - }, - { - "name": "B" - }, - { - "name": "C" - }, - { - "name": "H2O" - } - ] - } - ], - "reactions": [ - { - "type": "CONDENSED_PHASE_PHOTOLYSIS", - "condensed phase": "aqueous", - "__comment": "hi", - "reactants": [ - { - "name": "B", - "coefficient": 1 - } - ], - "products": [ - { - "name": "C", - "coefficient": 1 - } - ], - "name": "my condensed phase photolysis", - "scaling factor": 12.3 - }, - { - "type": "CONDENSED_PHASE_PHOTOLYSIS", - "condensed phase": "aqueous", - "reactants": [ - { - "name": "B", - "coefficient": 1.2 - } - ], - "products": [ - { - "name": "C", - "coefficient": 0.2 - } - ] - } - ] -} \ No newline at end of file diff --git a/test/unit/development/development_unit_configs/reactions/condensed_phase_photolysis/valid.yaml b/test/unit/development/development_unit_configs/reactions/condensed_phase_photolysis/valid.yaml deleted file mode 100644 index 441a2508..00000000 --- a/test/unit/development/development_unit_configs/reactions/condensed_phase_photolysis/valid.yaml +++ /dev/null @@ -1,34 +0,0 @@ -name: Valid surface -phases: -- name: aqueous - species: - - name: A - - name: B - - name: C - - name: H2O -reactions: -- __comment: hi - condensed phase: aqueous - name: my condensed phase photolysis - products: - - coefficient: 1 - name: C - reactants: - - coefficient: 1 - name: B - scaling factor: 12.3 - type: CONDENSED_PHASE_PHOTOLYSIS -- condensed phase: aqueous - products: - - coefficient: 0.2 - name: C - reactants: - - coefficient: 1.2 - name: B - type: CONDENSED_PHASE_PHOTOLYSIS -species: -- name: A -- name: B -- name: C -- name: H2O -version: 2.0.0 diff --git a/test/unit/development/development_unit_configs/reactions/emission/bad_reaction_component.json b/test/unit/development/development_unit_configs/reactions/emission/bad_reaction_component.json deleted file mode 100644 index 6b88a2f4..00000000 --- a/test/unit/development/development_unit_configs/reactions/emission/bad_reaction_component.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "version": "2.0.0", - "name": "Bad reaction component", - "species": [ - { - "name": "A" - }, - { - "name": "B" - } - ], - "phases": [ - { - "name": "gas", - "species": [ - { - "name": "A" - }, - { - "name": "B" - } - ] - } - ], - "reactions": [ - { - "type": "EMISSION", - "gas phase": "gas", - "products": [ - { - "Name": "C" - } - ] - } - ] -} \ No newline at end of file diff --git a/test/unit/development/development_unit_configs/reactions/emission/bad_reaction_component.yaml b/test/unit/development/development_unit_configs/reactions/emission/bad_reaction_component.yaml deleted file mode 100644 index 57d5a0d1..00000000 --- a/test/unit/development/development_unit_configs/reactions/emission/bad_reaction_component.yaml +++ /dev/null @@ -1,15 +0,0 @@ -name: Bad reaction component -phases: -- name: gas - species: - - name: A - - name: B -reactions: -- gas phase: gas - products: - - Name: C - type: EMISSION -species: -- name: A -- name: B -version: 2.0.0 diff --git a/test/unit/development/development_unit_configs/reactions/emission/missing_phase.json b/test/unit/development/development_unit_configs/reactions/emission/missing_phase.json deleted file mode 100644 index 010827da..00000000 --- a/test/unit/development/development_unit_configs/reactions/emission/missing_phase.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "version": "2.0.0", - "name": "Missing phase", - "species": [ - { - "name": "A" - }, - { - "name": "B" - }, - { - "name": "C" - } - ], - "phases": [], - "reactions": [ - { - "type": "EMISSION", - "gas phase": "gas", - "products": [ - { - "name": "C" - } - ] - } - ] -} \ No newline at end of file diff --git a/test/unit/development/development_unit_configs/reactions/emission/missing_phase.yaml b/test/unit/development/development_unit_configs/reactions/emission/missing_phase.yaml deleted file mode 100644 index 2eaf63ce..00000000 --- a/test/unit/development/development_unit_configs/reactions/emission/missing_phase.yaml +++ /dev/null @@ -1,12 +0,0 @@ -name: Missing phase -phases: [] -reactions: -- gas phase: gas - products: - - name: C - type: EMISSION -species: -- name: A -- name: B -- name: C -version: 2.0.0 diff --git a/test/unit/development/development_unit_configs/reactions/emission/unknown_species.json b/test/unit/development/development_unit_configs/reactions/emission/unknown_species.json deleted file mode 100644 index 81ecc45f..00000000 --- a/test/unit/development/development_unit_configs/reactions/emission/unknown_species.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "version": "2.0.0", - "name": "Unknown species", - "species": [ - { - "name": "A" - }, - { - "name": "B" - } - ], - "phases": [ - { - "name": "gas", - "species": [ - { - "name": "A" - }, - { - "name": "B" - } - ] - } - ], - "reactions": [ - { - "type": "EMISSION", - "gas phase": "gas", - "products": [ - { - "name": "C" - } - ] - } - ] -} \ No newline at end of file diff --git a/test/unit/development/development_unit_configs/reactions/emission/unknown_species.yaml b/test/unit/development/development_unit_configs/reactions/emission/unknown_species.yaml deleted file mode 100644 index 0dc0c52c..00000000 --- a/test/unit/development/development_unit_configs/reactions/emission/unknown_species.yaml +++ /dev/null @@ -1,15 +0,0 @@ -name: Unknown species -phases: -- name: gas - species: - - name: A - - name: B -reactions: -- gas phase: gas - products: - - name: C - type: EMISSION -species: -- name: A -- name: B -version: 2.0.0 diff --git a/test/unit/development/development_unit_configs/reactions/emission/valid.json b/test/unit/development/development_unit_configs/reactions/emission/valid.json deleted file mode 100644 index 3e029042..00000000 --- a/test/unit/development/development_unit_configs/reactions/emission/valid.json +++ /dev/null @@ -1,69 +0,0 @@ -{ - "version": "2.0.0", - "name": "Valid surface", - "species": [ - { - "name": "A" - }, - { - "name": "B" - }, - { - "name": "C" - } - ], - "phases": [ - { - "name": "gas", - "species": [ - { - "name": "A" - }, - { - "name": "B" - }, - { - "name": "C" - } - ] - }, - { - "name": "surface reacting phase", - "species": [ - { - "name": "A" - }, - { - "name": "B" - }, - { - "name": "C" - } - ] - } - ], - "reactions": [ - { - "type": "EMISSION", - "gas phase": "gas", - "products": [ - { - "name": "B", - "coefficient": 1 - } - ], - "name": "my emission", - "scaling factor": 12.3, - "__comment": "Dr. Pepper outranks any other soda" - }, - { - "type": "EMISSION", - "gas phase": "gas", - "products": [ - { - "name": "B" - } - ] - } - ] -} \ No newline at end of file diff --git a/test/unit/development/development_unit_configs/reactions/emission/valid.yaml b/test/unit/development/development_unit_configs/reactions/emission/valid.yaml deleted file mode 100644 index 4c07d29e..00000000 --- a/test/unit/development/development_unit_configs/reactions/emission/valid.yaml +++ /dev/null @@ -1,30 +0,0 @@ -name: Valid surface -phases: -- name: gas - species: - - name: A - - name: B - - name: C -- name: surface reacting phase - species: - - name: A - - name: B - - name: C -reactions: -- __comment: Dr. Pepper outranks any other soda - gas phase: gas - name: my emission - products: - - coefficient: 1 - name: B - scaling factor: 12.3 - type: EMISSION -- gas phase: gas - products: - - name: B - type: EMISSION -species: -- name: A -- name: B -- name: C -version: 2.0.0 diff --git a/test/unit/development/development_unit_configs/reactions/first_order_loss/bad_reaction_component.json b/test/unit/development/development_unit_configs/reactions/first_order_loss/bad_reaction_component.json deleted file mode 100644 index 4cca178c..00000000 --- a/test/unit/development/development_unit_configs/reactions/first_order_loss/bad_reaction_component.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "version": "2.0.0", - "name": "Bad reaction component", - "species": [ - { - "name": "A" - }, - { - "name": "B" - } - ], - "phases": [ - { - "name": "gas", - "species": [ - { - "name": "A" - }, - { - "name": "B" - } - ] - } - ], - "reactions": [ - { - "type": "FIRST_ORDER_LOSS", - "gas phase": "gas", - "reactants": [ - { - "Name": "C" - } - ] - } - ] -} \ No newline at end of file diff --git a/test/unit/development/development_unit_configs/reactions/first_order_loss/bad_reaction_component.yaml b/test/unit/development/development_unit_configs/reactions/first_order_loss/bad_reaction_component.yaml deleted file mode 100644 index 33f5c65d..00000000 --- a/test/unit/development/development_unit_configs/reactions/first_order_loss/bad_reaction_component.yaml +++ /dev/null @@ -1,15 +0,0 @@ -name: Bad reaction component -phases: -- name: gas - species: - - name: A - - name: B -reactions: -- gas phase: gas - reactants: - - Name: C - type: FIRST_ORDER_LOSS -species: -- name: A -- name: B -version: 2.0.0 diff --git a/test/unit/development/development_unit_configs/reactions/first_order_loss/missing_phase.json b/test/unit/development/development_unit_configs/reactions/first_order_loss/missing_phase.json deleted file mode 100644 index 1379f77d..00000000 --- a/test/unit/development/development_unit_configs/reactions/first_order_loss/missing_phase.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "version": "2.0.0", - "name": "Missing phase", - "species": [ - { - "name": "A" - }, - { - "name": "B" - }, - { - "name": "C" - } - ], - "phases": [], - "reactions": [ - { - "type": "FIRST_ORDER_LOSS", - "gas phase": "gas", - "reactants": [ - { - "name": "C" - } - ] - } - ] -} \ No newline at end of file diff --git a/test/unit/development/development_unit_configs/reactions/first_order_loss/missing_phase.yaml b/test/unit/development/development_unit_configs/reactions/first_order_loss/missing_phase.yaml deleted file mode 100644 index ef54f286..00000000 --- a/test/unit/development/development_unit_configs/reactions/first_order_loss/missing_phase.yaml +++ /dev/null @@ -1,12 +0,0 @@ -name: Missing phase -phases: [] -reactions: -- gas phase: gas - reactants: - - name: C - type: FIRST_ORDER_LOSS -species: -- name: A -- name: B -- name: C -version: 2.0.0 diff --git a/test/unit/development/development_unit_configs/reactions/first_order_loss/too_many_reactants.json b/test/unit/development/development_unit_configs/reactions/first_order_loss/too_many_reactants.json deleted file mode 100644 index 3c3f6a8c..00000000 --- a/test/unit/development/development_unit_configs/reactions/first_order_loss/too_many_reactants.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "version": "2.0.0", - "name": "Too many reactants", - "species": [ - { - "name": "A" - }, - { - "name": "B" - }, - { - "name": "C" - } - ], - "phases": [ - { - "name": "gas", - "species": [ - { - "name": "A" - }, - { - "name": "B" - }, - { - "name": "C" - } - ] - } - ], - "reactions": [ - { - "type": "FIRST_ORDER_LOSS", - "gas phase": "gas", - "reactants": [ - { - "name": "C", - "coefficient": 1 - }, - { - "name": "B", - "coefficient": 1 - } - ] - } - ] -} \ No newline at end of file diff --git a/test/unit/development/development_unit_configs/reactions/first_order_loss/too_many_reactants.yaml b/test/unit/development/development_unit_configs/reactions/first_order_loss/too_many_reactants.yaml deleted file mode 100644 index 20ef4e1d..00000000 --- a/test/unit/development/development_unit_configs/reactions/first_order_loss/too_many_reactants.yaml +++ /dev/null @@ -1,20 +0,0 @@ -name: Too many reactants -phases: -- name: gas - species: - - name: A - - name: B - - name: C -reactions: -- gas phase: gas - reactants: - - coefficient: 1 - name: C - - coefficient: 1 - name: B - type: FIRST_ORDER_LOSS -species: -- name: A -- name: B -- name: C -version: 2.0.0 diff --git a/test/unit/development/development_unit_configs/reactions/first_order_loss/unknown_species.json b/test/unit/development/development_unit_configs/reactions/first_order_loss/unknown_species.json deleted file mode 100644 index 8370ff98..00000000 --- a/test/unit/development/development_unit_configs/reactions/first_order_loss/unknown_species.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "version": "2.0.0", - "name": "Unknown species", - "species": [ - { - "name": "A" - }, - { - "name": "B" - } - ], - "phases": [ - { - "name": "gas", - "species": [ - { - "name": "A" - }, - { - "name": "B" - } - ] - } - ], - "reactions": [ - { - "type": "FIRST_ORDER_LOSS", - "gas phase": "gas", - "reactants": [ - { - "name": "C" - } - ] - } - ] -} \ No newline at end of file diff --git a/test/unit/development/development_unit_configs/reactions/first_order_loss/unknown_species.yaml b/test/unit/development/development_unit_configs/reactions/first_order_loss/unknown_species.yaml deleted file mode 100644 index 6b3ff2e4..00000000 --- a/test/unit/development/development_unit_configs/reactions/first_order_loss/unknown_species.yaml +++ /dev/null @@ -1,15 +0,0 @@ -name: Unknown species -phases: -- name: gas - species: - - name: A - - name: B -reactions: -- gas phase: gas - reactants: - - name: C - type: FIRST_ORDER_LOSS -species: -- name: A -- name: B -version: 2.0.0 diff --git a/test/unit/development/development_unit_configs/reactions/first_order_loss/valid.json b/test/unit/development/development_unit_configs/reactions/first_order_loss/valid.json deleted file mode 100644 index 8f51799c..00000000 --- a/test/unit/development/development_unit_configs/reactions/first_order_loss/valid.json +++ /dev/null @@ -1,56 +0,0 @@ -{ - "version": "2.0.0", - "name": "Valid surface", - "species": [ - { - "name": "A" - }, - { - "name": "B" - }, - { - "name": "C" - } - ], - "phases": [ - { - "name": "gas", - "species": [ - { - "name": "A" - }, - { - "name": "B" - }, - { - "name": "C" - } - ] - } - ], - "reactions": [ - { - "type": "FIRST_ORDER_LOSS", - "gas phase": "gas", - "reactants": [ - { - "name": "C", - "coefficient": 1 - } - ], - "name": "my first order loss", - "scaling factor": 12.3, - "__comment": "Strawberries are the superior fruit" - }, - { - "type": "FIRST_ORDER_LOSS", - "gas phase": "gas", - "reactants": [ - { - "name": "C", - "coefficient": 1 - } - ] - } - ] -} \ No newline at end of file diff --git a/test/unit/development/development_unit_configs/reactions/first_order_loss/valid.yaml b/test/unit/development/development_unit_configs/reactions/first_order_loss/valid.yaml deleted file mode 100644 index c1f80e05..00000000 --- a/test/unit/development/development_unit_configs/reactions/first_order_loss/valid.yaml +++ /dev/null @@ -1,26 +0,0 @@ -name: Valid surface -phases: -- name: gas - species: - - name: A - - name: B - - name: C -reactions: -- __comment: Strawberries are the superior fruit - gas phase: gas - name: my first order loss - reactants: - - coefficient: 1 - name: C - scaling factor: 12.3 - type: FIRST_ORDER_LOSS -- gas phase: gas - reactants: - - coefficient: 1 - name: C - type: FIRST_ORDER_LOSS -species: -- name: A -- name: B -- name: C -version: 2.0.0 diff --git a/test/unit/development/development_unit_configs/reactions/henrys_law/solvent_species_not_registered_in_phase.json b/test/unit/development/development_unit_configs/reactions/henrys_law/solvent_species_not_registered_in_phase.json deleted file mode 100644 index babc1773..00000000 --- a/test/unit/development/development_unit_configs/reactions/henrys_law/solvent_species_not_registered_in_phase.json +++ /dev/null @@ -1,72 +0,0 @@ -{ - "version": "2.0.0", - "name": "Solvent species in not registered in the corresponding phase", - "species": [ - { - "name": "A" - }, - { - "name": "B" - }, - { - "name": "C" - }, - { - "name": "H2O" - } - ], - "phases": [ - { - "name": "gas", - "species": [ - { - "name": "A" - }, - { - "name": "B" - } - ] - }, - { - "name": "aqueous", - "species": [ - { - "name": "C" - }, - { - "name": "H2O" - } - ] - } - ], - "reactions": [ - { - "type": "HL_PHASE_TRANSFER", - "gas": { - "name": "gas", - "species": [ - { - "name": "A", - "diffusion coefficient [m2 s-1]": 0.7 - } - ] - }, - "particle": { - "phase": "aqueous", - "solutes": [ - { - "name": "C", - "coefficient": 1.0 - } - ], - "solvent": [ - { - "name": "B" - } - ] - }, - "name": "my henry's law", - "__comment": "hi" - } - ] -} \ No newline at end of file diff --git a/test/unit/development/development_unit_configs/reactions/henrys_law/solvent_species_not_registered_in_phase.yaml b/test/unit/development/development_unit_configs/reactions/henrys_law/solvent_species_not_registered_in_phase.yaml deleted file mode 100644 index 241cff87..00000000 --- a/test/unit/development/development_unit_configs/reactions/henrys_law/solvent_species_not_registered_in_phase.yaml +++ /dev/null @@ -1,32 +0,0 @@ -version: 2.0.0 -name: Solvent species in not registered in the corresponding phase -species: - - name: A - - name: B - - name: C - - name: H2O -phases: - - name: gas - species: - - name: A - - name: B - - name: aqueous - species: - - name: H2O - - name: C -reactions: - - type: HL_PHASE_TRANSFER - gas: - name: gas - species: - - name: A - diffusion coefficient [m2 s-1]: 0.7 - particle: - phase: aqueous - solutes: - - name: C - coefficient: 1.0 - solvent: - - name: B - name: my henry's law - __comment: hi diff --git a/test/unit/development/development_unit_configs/reactions/henrys_law/species_not_found_in_gas_phase.json b/test/unit/development/development_unit_configs/reactions/henrys_law/species_not_found_in_gas_phase.json deleted file mode 100644 index 90c94eec..00000000 --- a/test/unit/development/development_unit_configs/reactions/henrys_law/species_not_found_in_gas_phase.json +++ /dev/null @@ -1,64 +0,0 @@ -{ - "version": "2.0.0", - "name": "Gas species in reactions are not found in gas phase", - "species": [ - { - "name": "A" - }, - { - "name": "B" - }, - { - "name": "H2O" - } - ], - "phases": [ - { - "name": "gas", - "species": [ - { - "name": "A" - } - ] - }, - { - "name": "aqueous", - "species": [ - { - "name": "B" - }, - { - "name": "H2O" - } - ] - } - ], - "reactions": [ - { - "type": "HL_PHASE_TRANSFER", - "gas": { - "name": "gas", - "species": [ - { - "name": "H2O", - "diffusion coefficient [m2 s-1]": 0.7 - } - ] - }, - "particle": { - "phase": "aqueous", - "solutes": [ - { - "name": "B", - "coefficient": 1.0 - } - ], - "solvent": [ - { - "name": "H2O" - } - ] - } - } - ] -} \ No newline at end of file diff --git a/test/unit/development/development_unit_configs/reactions/henrys_law/species_not_found_in_gas_phase.yaml b/test/unit/development/development_unit_configs/reactions/henrys_law/species_not_found_in_gas_phase.yaml deleted file mode 100644 index b37db7a1..00000000 --- a/test/unit/development/development_unit_configs/reactions/henrys_law/species_not_found_in_gas_phase.yaml +++ /dev/null @@ -1,28 +0,0 @@ -version: 2.0.0 -name: Gas species in reactions are not found in gas phase -species: - - name: A - - name: B - - name: H2O -phases: - - name: gas - species: - - name: A - - name: aqueous - species: - - name: B - - name: H2O -reactions: - - type: HL_PHASE_TRANSFER - gas: - name: gas - species: - - name: H2O - diffusion coefficient [m2 s-1]: 0.7 - particle: - phase: aqueous - solutes: - - name: B - coefficient: 1.0 - solvent: - - name: H2O diff --git a/test/unit/development/development_unit_configs/reactions/henrys_law/species_not_in_aqueous_phase.json b/test/unit/development/development_unit_configs/reactions/henrys_law/species_not_in_aqueous_phase.json deleted file mode 100644 index 7e78118c..00000000 --- a/test/unit/development/development_unit_configs/reactions/henrys_law/species_not_in_aqueous_phase.json +++ /dev/null @@ -1,66 +0,0 @@ -{ - "version": "2.0.0", - "name": "Condensed phase arrhenius using species not in its requested condensed phase", - "species": [ - { - "name": "A" - }, - { - "name": "B" - }, - { - "name": "H2O" - } - ], - "phases": [ - { - "name": "gas", - "species": [ - { - "name": "A" - }, - { - "name": "B" - } - ] - }, - { - "name": "aqueous", - "species": [ - { - "name": "H2O" - } - ] - } - ], - "reactions": [ - { - "type": "HL_PHASE_TRANSFER", - "gas": { - "name": "gas", - "species": [ - { - "name": "A", - "diffusion coefficient [m2 s-1]": 0.7 - } - ] - }, - "particle": { - "phase": "aqueous", - "solutes": [ - { - "name": "B", - "coefficient": 1.0 - } - ], - "solvent": [ - { - "name": "H2O" - } - ] - }, - "name": "my henry's law", - "__comment": "hi" - } - ] -} \ No newline at end of file diff --git a/test/unit/development/development_unit_configs/reactions/henrys_law/species_not_in_aqueous_phase.yaml b/test/unit/development/development_unit_configs/reactions/henrys_law/species_not_in_aqueous_phase.yaml deleted file mode 100644 index 1978b1e2..00000000 --- a/test/unit/development/development_unit_configs/reactions/henrys_law/species_not_in_aqueous_phase.yaml +++ /dev/null @@ -1,30 +0,0 @@ -version: 2.0.0 -name: Condensed phase arrhenius using species not in its requested condensed phase -species: - - name: A - - name: B - - name: H2O -phases: - - name: gas - species: - - name: A - - name: B - - name: aqueous - species: - - name: H2O -reactions: - - type: HL_PHASE_TRANSFER - gas: - name: gas - species: - - name: A - diffusion coefficient [m2 s-1]: 0.7 - particle: - phase: aqueous - solutes: - - name: B - coefficient: 1.0 - solvent: - - name: H2O - name: my henry's law - __comment: hi diff --git a/test/unit/development/development_unit_configs/reactions/henrys_law/unknown_species.json b/test/unit/development/development_unit_configs/reactions/henrys_law/unknown_species.json deleted file mode 100644 index 8eaad466..00000000 --- a/test/unit/development/development_unit_configs/reactions/henrys_law/unknown_species.json +++ /dev/null @@ -1,64 +0,0 @@ -{ - "version": "2.0.0", - "name": "Unknown species", - "species": [ - { - "name": "A" - }, - { - "name": "B" - }, - { - "name": "H2O" - } - ], - "phases": [ - { - "name": "gas", - "species": [ - { - "name": "A" - } - ] - }, - { - "name": "aqueous", - "species": [ - { - "name": "B" - }, - { - "name": "H2O" - } - ] - } - ], - "reactions": [ - { - "type": "HL_PHASE_TRANSFER", - "gas": { - "name": "gas", - "species": [ - { - "name": "C", - "diffusion coefficient [m2 s-1]": 0.7 - } - ] - }, - "particle": { - "phase": "aqueous", - "solutes": [ - { - "name": "B", - "coefficient": 1.0 - } - ], - "solvent": [ - { - "name": "H2O" - } - ] - } - } - ] -} \ No newline at end of file diff --git a/test/unit/development/development_unit_configs/reactions/henrys_law/unknown_species.yaml b/test/unit/development/development_unit_configs/reactions/henrys_law/unknown_species.yaml deleted file mode 100644 index b0f22388..00000000 --- a/test/unit/development/development_unit_configs/reactions/henrys_law/unknown_species.yaml +++ /dev/null @@ -1,29 +0,0 @@ -version: 2.0.0 -name: Unknown species -species: - - name: A - - name: B - - name: H2O -phases: - - name: gas - species: - - name: A - diffusion coefficient [m2 s-1]: 0.7 - - name: aqueous - species: - - name: B - - name: H2O -reactions: - - type: HL_PHASE_TRANSFER - gas: - name: gas - species: - - name: C - diffusion coefficient [m2 s-1]: 0.7 - particle: - phase: aqueous - solutes: - - name: B - coefficient: 1.0 - solvent: - - name: H2O diff --git a/test/unit/development/development_unit_configs/reactions/henrys_law/valid.json b/test/unit/development/development_unit_configs/reactions/henrys_law/valid.json deleted file mode 100644 index c5bcb41a..00000000 --- a/test/unit/development/development_unit_configs/reactions/henrys_law/valid.json +++ /dev/null @@ -1,102 +0,0 @@ -{ - "version": "2.0.0", - "name": "Valid surface", - "species": [ - { - "name": "A" - }, - { - "name": "B" - }, - { - "name": "H2O" - }, - { - "name": "C" - } - ], - "phases": [ - { - "name": "gas", - "species": [ - { - "name": "A" - } - ] - }, - { - "name": "aqueous", - "species": [ - { - "name": "B" - }, - { - "name": "H2O" - }, - { - "name": "C" - } - ] - } - ], - "reactions": [ - { - "type": "HL_PHASE_TRANSFER", - "gas": { - "name": "gas", - "species": [ - { - "name": "A", - "diffusion coefficient [m2 s-1]": 0.7 - } - ] - }, - "particle": { - "phase": "aqueous", - "solutes": [ - { - "name": "B", - "coefficient": 1.0 - } - ], - "solvent": [ - { - "name": "H2O" - } - ] - }, - "name": "my henry's law", - "__comment": "B condensed phase production (kg/m2/s)" - }, - { - "type": "HL_PHASE_TRANSFER", - "gas": { - "name": "gas", - "species": [ - { - "name": "A" - } - ] - }, - "particle": { - "phase": "aqueous", - "solutes": [ - { - "name": "B", - "coefficient": 1.0 - }, - { - "name": "C", - "coefficient": 1.0 - } - ], - "solvent": [ - { - "name": "H2O", - "coefficient": 1.0 - } - ] - } - } - ] -} \ No newline at end of file diff --git a/test/unit/development/development_unit_configs/reactions/henrys_law/valid.yaml b/test/unit/development/development_unit_configs/reactions/henrys_law/valid.yaml deleted file mode 100644 index af35edb0..00000000 --- a/test/unit/development/development_unit_configs/reactions/henrys_law/valid.yaml +++ /dev/null @@ -1,52 +0,0 @@ -version: 2.0.0 -name: Valid surface - -species: - - name: A - - name: B - - name: H2O - - name: C - -phases: - - name: gas - species: - - name: A - - name: aqueous - species: - - name: B - - name: H2O - - name: C - -reactions: - - type: HL_PHASE_TRANSFER - gas: - name: gas - species: - - name: A - diffusion coefficient [m2 s-1]: 0.7 - particle: - phase: aqueous - solutes: - - name: B - coefficient: 1.0 - solvent: - - name: H2O - name: my henry's law - __comment: B condensed phase production (kg/m2/s) - - - type: HL_PHASE_TRANSFER - gas: - name: gas - species: - - name: A - diffusion coefficient [m2 s-1]: 0.7 - particle: - phase: aqueous - solutes: - - name: B - coefficient: 1.0 - - name: C - coefficient: 1.0 - solvent: - - name: H2O - coefficient: 1.0 diff --git a/test/unit/development/development_unit_configs/reactions/photolysis/bad_reaction_component.json b/test/unit/development/development_unit_configs/reactions/photolysis/bad_reaction_component.json deleted file mode 100644 index df753d1a..00000000 --- a/test/unit/development/development_unit_configs/reactions/photolysis/bad_reaction_component.json +++ /dev/null @@ -1,43 +0,0 @@ -{ - "version": "2.0.0", - "name": "Bad reaction component", - "species": [ - { - "name": "A" - }, - { - "name": "B" - } - ], - "phases": [ - { - "name": "gas", - "species": [ - { - "name": "A" - }, - { - "name": "B" - } - ] - } - ], - "reactions": [ - { - "type": "PHOTOLYSIS", - "gas phase": "gas", - "reactants": [ - { - "name": "A", - "Coefficient": 1.2 - } - ], - "products": [ - { - "name": "B", - "coefficient": 0.2 - } - ] - } - ] -} \ No newline at end of file diff --git a/test/unit/development/development_unit_configs/reactions/photolysis/bad_reaction_component.yaml b/test/unit/development/development_unit_configs/reactions/photolysis/bad_reaction_component.yaml deleted file mode 100644 index d836c363..00000000 --- a/test/unit/development/development_unit_configs/reactions/photolysis/bad_reaction_component.yaml +++ /dev/null @@ -1,19 +0,0 @@ -name: Bad reaction component -phases: -- name: gas - species: - - name: A - - name: B -reactions: -- gas phase: gas - products: - - coefficient: 0.2 - name: B - reactants: - - Coefficient: 1.2 - name: A - type: PHOTOLYSIS -species: -- name: A -- name: B -version: 2.0.0 diff --git a/test/unit/development/development_unit_configs/reactions/photolysis/missing_phase.json b/test/unit/development/development_unit_configs/reactions/photolysis/missing_phase.json deleted file mode 100644 index ca28ef33..00000000 --- a/test/unit/development/development_unit_configs/reactions/photolysis/missing_phase.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "version": "2.0.0", - "name": "Missing phase", - "species": [ - { - "name": "A" - }, - { - "name": "B" - }, - { - "name": "C" - } - ], - "phases": [], - "reactions": [ - { - "type": "PHOTOLYSIS", - "gas phase": "gas", - "reactants": [ - { - "name": "B", - "coefficient": 1.2 - } - ], - "products": [ - { - "name": "C", - "coefficient": 0.2 - } - ] - } - ] -} \ No newline at end of file diff --git a/test/unit/development/development_unit_configs/reactions/photolysis/missing_phase.yaml b/test/unit/development/development_unit_configs/reactions/photolysis/missing_phase.yaml deleted file mode 100644 index 49842303..00000000 --- a/test/unit/development/development_unit_configs/reactions/photolysis/missing_phase.yaml +++ /dev/null @@ -1,16 +0,0 @@ -name: Missing phase -phases: [] -reactions: -- gas phase: gas - products: - - coefficient: 0.2 - name: C - reactants: - - coefficient: 1.2 - name: B - type: PHOTOLYSIS -species: -- name: A -- name: B -- name: C -version: 2.0.0 diff --git a/test/unit/development/development_unit_configs/reactions/photolysis/more_than_one_reactant.json b/test/unit/development/development_unit_configs/reactions/photolysis/more_than_one_reactant.json deleted file mode 100644 index c6ac0371..00000000 --- a/test/unit/development/development_unit_configs/reactions/photolysis/more_than_one_reactant.json +++ /dev/null @@ -1,84 +0,0 @@ -{ - "version": "2.0.0", - "name": "more than one reactant", - "species": [ - { - "name": "A" - }, - { - "name": "B" - }, - { - "name": "C" - } - ], - "phases": [ - { - "name": "gas", - "species": [ - { - "name": "A" - }, - { - "name": "B" - }, - { - "name": "C" - } - ] - }, - { - "name": "surface reacting phase", - "species": [ - { - "name": "A" - }, - { - "name": "B" - }, - { - "name": "C" - } - ] - } - ], - "reactions": [ - { - "type": "PHOTOLYSIS", - "gas phase": "gas", - "__comment": "hi", - "reactants": [ - { - "name": "B" - }, - { - "name": "A" - } - ], - "products": [ - { - "name": "C", - "coefficient": 1 - } - ], - "name": "my photolysis", - "scaling factor": 12.3 - }, - { - "type": "PHOTOLYSIS", - "gas phase": "gas", - "reactants": [ - { - "name": "B", - "coefficient": 1.2 - } - ], - "products": [ - { - "name": "C", - "coefficient": 0.2 - } - ] - } - ] -} \ No newline at end of file diff --git a/test/unit/development/development_unit_configs/reactions/photolysis/more_than_one_reactant.yaml b/test/unit/development/development_unit_configs/reactions/photolysis/more_than_one_reactant.yaml deleted file mode 100644 index a3710036..00000000 --- a/test/unit/development/development_unit_configs/reactions/photolysis/more_than_one_reactant.yaml +++ /dev/null @@ -1,37 +0,0 @@ -name: more than one reactant -phases: -- name: gas - species: - - name: A - - name: B - - name: C -- name: surface reacting phase - species: - - name: A - - name: B - - name: C -reactions: -- __comment: hi - gas phase: gas - name: my photolysis - products: - - coefficient: 1 - name: C - reactants: - - name: B - - name: A - scaling factor: 12.3 - type: PHOTOLYSIS -- gas phase: gas - products: - - coefficient: 0.2 - name: C - reactants: - - coefficient: 1.2 - name: B - type: PHOTOLYSIS -species: -- name: A -- name: B -- name: C -version: 2.0.0 diff --git a/test/unit/development/development_unit_configs/reactions/photolysis/unknown_species.json b/test/unit/development/development_unit_configs/reactions/photolysis/unknown_species.json deleted file mode 100644 index dcb12f45..00000000 --- a/test/unit/development/development_unit_configs/reactions/photolysis/unknown_species.json +++ /dev/null @@ -1,43 +0,0 @@ -{ - "version": "2.0.0", - "name": "Unknown species", - "species": [ - { - "name": "A" - }, - { - "name": "B" - } - ], - "phases": [ - { - "name": "gas", - "species": [ - { - "name": "A" - }, - { - "name": "B" - } - ] - } - ], - "reactions": [ - { - "type": "PHOTOLYSIS", - "gas phase": "gas", - "reactants": [ - { - "name": "B", - "coefficient": 1.2 - } - ], - "products": [ - { - "name": "C", - "coefficient": 0.2 - } - ] - } - ] -} \ No newline at end of file diff --git a/test/unit/development/development_unit_configs/reactions/photolysis/unknown_species.yaml b/test/unit/development/development_unit_configs/reactions/photolysis/unknown_species.yaml deleted file mode 100644 index 0ee34dba..00000000 --- a/test/unit/development/development_unit_configs/reactions/photolysis/unknown_species.yaml +++ /dev/null @@ -1,19 +0,0 @@ -name: Unknown species -phases: -- name: gas - species: - - name: A - - name: B -reactions: -- gas phase: gas - products: - - coefficient: 0.2 - name: C - reactants: - - coefficient: 1.2 - name: B - type: PHOTOLYSIS -species: -- name: A -- name: B -version: 2.0.0 diff --git a/test/unit/development/development_unit_configs/reactions/photolysis/valid.json b/test/unit/development/development_unit_configs/reactions/photolysis/valid.json deleted file mode 100644 index a0c0ba26..00000000 --- a/test/unit/development/development_unit_configs/reactions/photolysis/valid.json +++ /dev/null @@ -1,82 +0,0 @@ -{ - "version": "2.0.0", - "name": "Valid photolysis", - "species": [ - { - "name": "A" - }, - { - "name": "B" - }, - { - "name": "C" - } - ], - "phases": [ - { - "name": "gas", - "species": [ - { - "name": "A" - }, - { - "name": "B" - }, - { - "name": "C" - } - ] - }, - { - "name": "surface reacting phase", - "species": [ - { - "name": "A" - }, - { - "name": "B" - }, - { - "name": "C" - } - ] - } - ], - "reactions": [ - { - "type": "PHOTOLYSIS", - "gas phase": "gas", - "__comment": "hi", - "reactants": [ - { - "name": "B", - "coefficient": 1 - } - ], - "products": [ - { - "name": "C", - "coefficient": 1 - } - ], - "name": "my photolysis", - "scaling factor": 12.3 - }, - { - "type": "PHOTOLYSIS", - "gas phase": "gas", - "reactants": [ - { - "name": "B", - "coefficient": 1.2 - } - ], - "products": [ - { - "name": "C", - "coefficient": 0.2 - } - ] - } - ] -} \ No newline at end of file diff --git a/test/unit/development/development_unit_configs/reactions/photolysis/valid.yaml b/test/unit/development/development_unit_configs/reactions/photolysis/valid.yaml deleted file mode 100644 index 451f22a6..00000000 --- a/test/unit/development/development_unit_configs/reactions/photolysis/valid.yaml +++ /dev/null @@ -1,37 +0,0 @@ -name: Valid photolysis -phases: -- name: gas - species: - - name: A - - name: B - - name: C -- name: surface reacting phase - species: - - name: A - - name: B - - name: C -reactions: -- __comment: hi - gas phase: gas - name: my photolysis - products: - - coefficient: 1 - name: C - reactants: - - coefficient: 1 - name: B - scaling factor: 12.3 - type: PHOTOLYSIS -- gas phase: gas - products: - - coefficient: 0.2 - name: C - reactants: - - coefficient: 1.2 - name: B - type: PHOTOLYSIS -species: -- name: A -- name: B -- name: C -version: 2.0.0 diff --git a/test/unit/development/development_unit_configs/reactions/simpol_phase_transfer/missing_aqueous_phase.json b/test/unit/development/development_unit_configs/reactions/simpol_phase_transfer/missing_aqueous_phase.json deleted file mode 100644 index a848606f..00000000 --- a/test/unit/development/development_unit_configs/reactions/simpol_phase_transfer/missing_aqueous_phase.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "version": "2.0.0", - "name": "Valid surface", - "species": [ - { - "name": "A" - }, - { - "name": "B" - } - ], - "phases": [ - { - "name": "gas", - "species": [ - { - "name": "A" - } - ] - } - ], - "reactions": [ - { - "type": "SIMPOL_PHASE_TRANSFER", - "gas phase": "gas", - "gas-phase species": [ - { - "name": "A", - "coefficient": 1 - } - ], - "condensed phase": "aqueous", - "condensed-phase species": [ - { - "name": "B", - "coefficient": 1 - } - ], - "B": [ - -1.97E+03, - 2.91E+00, - 1.96E-03, - -4.96E-01 - ], - "name": "my simpol" - } - ] -} \ No newline at end of file diff --git a/test/unit/development/development_unit_configs/reactions/simpol_phase_transfer/missing_aqueous_phase.yaml b/test/unit/development/development_unit_configs/reactions/simpol_phase_transfer/missing_aqueous_phase.yaml deleted file mode 100644 index 3c489672..00000000 --- a/test/unit/development/development_unit_configs/reactions/simpol_phase_transfer/missing_aqueous_phase.yaml +++ /dev/null @@ -1,25 +0,0 @@ -name: Valid surface -phases: -- name: gas - species: - - name: A -reactions: -- B: - - -1970.0 - - 2.91 - - 0.00196 - - -0.496 - condensed phase: aqueous - condensed-phase species: - - name: B - coefficient: 1 - gas phase: gas - gas-phase species: - - name: A - coefficient: 1 - name: my simpol - type: SIMPOL_PHASE_TRANSFER -species: -- name: A -- name: B -version: 2.0.0 diff --git a/test/unit/development/development_unit_configs/reactions/simpol_phase_transfer/missing_aqueous_phase_species_in_aqueous_phase.json b/test/unit/development/development_unit_configs/reactions/simpol_phase_transfer/missing_aqueous_phase_species_in_aqueous_phase.json deleted file mode 100644 index c1483a2d..00000000 --- a/test/unit/development/development_unit_configs/reactions/simpol_phase_transfer/missing_aqueous_phase_species_in_aqueous_phase.json +++ /dev/null @@ -1,56 +0,0 @@ -{ - "version": "2.0.0", - "name": "Missing gas phase", - "species": [ - { - "name": "A" - }, - { - "name": "B" - } - ], - "phases": [ - { - "name": "gas", - "species": [ - { - "name": "A" - } - ] - }, - { - "name": "aqueous", - "species": [ - { - "name": "A" - } - ] - } - ], - "reactions": [ - { - "type": "SIMPOL_PHASE_TRANSFER", - "gas phase": "gas", - "gas-phase species": [ - { - "name": "A", - "coefficient": 1 - } - ], - "condensed phase": "aqueous", - "condensed-phase species": [ - { - "name": "B", - "coefficient": 1 - } - ], - "B": [ - -1.97E+03, - 2.91E+00, - 1.96E-03, - -4.96E-01 - ], - "name": "my simpol" - } - ] -} \ No newline at end of file diff --git a/test/unit/development/development_unit_configs/reactions/simpol_phase_transfer/missing_aqueous_phase_species_in_aqueous_phase.yaml b/test/unit/development/development_unit_configs/reactions/simpol_phase_transfer/missing_aqueous_phase_species_in_aqueous_phase.yaml deleted file mode 100644 index b84766d1..00000000 --- a/test/unit/development/development_unit_configs/reactions/simpol_phase_transfer/missing_aqueous_phase_species_in_aqueous_phase.yaml +++ /dev/null @@ -1,28 +0,0 @@ -name: Missing gas phase -phases: -- name: gas - species: - - name: A -- name: aqueous - species: - - name: A -reactions: -- B: - - -1970.0 - - 2.91 - - 0.00196 - - -0.496 - condensed phase: aqueous - condensed-phase species: - - name: B - coefficient: 1 - gas phase: gas - gas-phase species: - - name: A - coefficient: 1 - name: my simpol - type: SIMPOL_PHASE_TRANSFER -species: -- name: A -- name: B -version: 2.0.0 diff --git a/test/unit/development/development_unit_configs/reactions/simpol_phase_transfer/missing_gas_phase.json b/test/unit/development/development_unit_configs/reactions/simpol_phase_transfer/missing_gas_phase.json deleted file mode 100644 index 852a78a1..00000000 --- a/test/unit/development/development_unit_configs/reactions/simpol_phase_transfer/missing_gas_phase.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "version": "2.0.0", - "name": "Missing gas phase", - "species": [ - { - "name": "A" - }, - { - "name": "B" - } - ], - "phases": [ - { - "name": "aqueous", - "species": [ - { - "name": "B" - } - ] - } - ], - "reactions": [ - { - "type": "SIMPOL_PHASE_TRANSFER", - "gas phase": "gas", - "gas-phase species": [ - { - "name": "A", - "coefficient": 1 - } - ], - "condensed phase": "aqueous", - "condensed-phase species": [ - { - "name": "B", - "coefficient": 1 - } - ], - "B": [ - -1.97E+03, - 2.91E+00, - 1.96E-03, - -4.96E-01 - ], - "name": "my simpol" - } - ] -} \ No newline at end of file diff --git a/test/unit/development/development_unit_configs/reactions/simpol_phase_transfer/missing_gas_phase.yaml b/test/unit/development/development_unit_configs/reactions/simpol_phase_transfer/missing_gas_phase.yaml deleted file mode 100644 index 43eaf4b6..00000000 --- a/test/unit/development/development_unit_configs/reactions/simpol_phase_transfer/missing_gas_phase.yaml +++ /dev/null @@ -1,25 +0,0 @@ -name: Missing gas phase -phases: -- name: aqueous - species: - - name: B -reactions: -- B: - - -1970.0 - - 2.91 - - 0.00196 - - -0.496 - condensed phase: aqueous - condensed-phase species: - - name: B - coefficient: 1 - gas phase: gas - gas-phase species: - - name: A - coefficient: 1 - name: my simpol - type: SIMPOL_PHASE_TRANSFER -species: -- name: A -- name: B -version: 2.0.0 diff --git a/test/unit/development/development_unit_configs/reactions/simpol_phase_transfer/missing_gas_phase_species_in_gas_phase.json b/test/unit/development/development_unit_configs/reactions/simpol_phase_transfer/missing_gas_phase_species_in_gas_phase.json deleted file mode 100644 index 75df0e7d..00000000 --- a/test/unit/development/development_unit_configs/reactions/simpol_phase_transfer/missing_gas_phase_species_in_gas_phase.json +++ /dev/null @@ -1,56 +0,0 @@ -{ - "version": "2.0.0", - "name": "Missing gas phase", - "species": [ - { - "name": "A" - }, - { - "name": "B" - } - ], - "phases": [ - { - "name": "gas", - "species": [ - { - "name": "B" - } - ] - }, - { - "name": "aqueous", - "species": [ - { - "name": "B" - } - ] - } - ], - "reactions": [ - { - "type": "SIMPOL_PHASE_TRANSFER", - "gas phase": "gas", - "gas-phase species": [ - { - "name": "A", - "coefficient": 1 - } - ], - "condensed phase": "aqueous", - "condensed-phase species": [ - { - "name": "B", - "coefficient": 1 - } - ], - "B": [ - -1.97E+03, - 2.91E+00, - 1.96E-03, - -4.96E-01 - ], - "name": "my simpol" - } - ] -} \ No newline at end of file diff --git a/test/unit/development/development_unit_configs/reactions/simpol_phase_transfer/missing_gas_phase_species_in_gas_phase.yaml b/test/unit/development/development_unit_configs/reactions/simpol_phase_transfer/missing_gas_phase_species_in_gas_phase.yaml deleted file mode 100644 index d908be79..00000000 --- a/test/unit/development/development_unit_configs/reactions/simpol_phase_transfer/missing_gas_phase_species_in_gas_phase.yaml +++ /dev/null @@ -1,28 +0,0 @@ -name: Missing gas phase -phases: -- name: gas - species: - - name: B -- name: aqueous - species: - - name: B -reactions: -- B: - - -1970.0 - - 2.91 - - 0.00196 - - -0.496 - condensed phase: aqueous - condensed-phase species: - - name: B - coefficient: 1 - gas phase: gas - gas-phase species: - - name: A - coefficient: 1 - name: my simpol - type: SIMPOL_PHASE_TRANSFER -species: -- name: A -- name: B -version: 2.0.0 diff --git a/test/unit/development/development_unit_configs/reactions/simpol_phase_transfer/unknown_species.json b/test/unit/development/development_unit_configs/reactions/simpol_phase_transfer/unknown_species.json deleted file mode 100644 index fe1d362c..00000000 --- a/test/unit/development/development_unit_configs/reactions/simpol_phase_transfer/unknown_species.json +++ /dev/null @@ -1,56 +0,0 @@ -{ - "version": "2.0.0", - "name": "Unknown species", - "species": [ - { - "name": "A" - }, - { - "name": "B" - } - ], - "phases": [ - { - "name": "gas", - "species": [ - { - "name": "A" - } - ] - }, - { - "name": "aqueous", - "species": [ - { - "name": "B" - } - ] - } - ], - "reactions": [ - { - "type": "SIMPOL_PHASE_TRANSFER", - "gas phase": "gas", - "gas-phase species": [ - { - "name": "C", - "coefficient": 1 - } - ], - "condensed phase": "aqueous", - "condensed-phase species": [ - { - "name": "B", - "coefficient": 1 - } - ], - "B": [ - -1.97E+03, - 2.91E+00, - 1.96E-03, - -4.96E-01 - ], - "name": "my simpol" - } - ] -} \ No newline at end of file diff --git a/test/unit/development/development_unit_configs/reactions/simpol_phase_transfer/unknown_species.yaml b/test/unit/development/development_unit_configs/reactions/simpol_phase_transfer/unknown_species.yaml deleted file mode 100644 index 7f77d491..00000000 --- a/test/unit/development/development_unit_configs/reactions/simpol_phase_transfer/unknown_species.yaml +++ /dev/null @@ -1,28 +0,0 @@ -name: Unknown species -phases: -- name: gas - species: - - name: A -- name: aqueous - species: - - name: B -reactions: -- B: - - -1970.0 - - 2.91 - - 0.00196 - - -0.496 - condensed phase: aqueous - condensed-phase species: - - name: B - coefficient: 1 - gas phase: gas - gas-phase species: - - name: C - coefficient: 1 - name: my simpol - type: SIMPOL_PHASE_TRANSFER -species: -- name: A -- name: B -version: 2.0.0 diff --git a/test/unit/development/development_unit_configs/reactions/simpol_phase_transfer/valid.json b/test/unit/development/development_unit_configs/reactions/simpol_phase_transfer/valid.json deleted file mode 100644 index 97a98546..00000000 --- a/test/unit/development/development_unit_configs/reactions/simpol_phase_transfer/valid.json +++ /dev/null @@ -1,80 +0,0 @@ -{ - "version": "2.0.0", - "name": "Valid surface", - "species": [ - { - "name": "A" - }, - { - "name": "B" - } - ], - "phases": [ - { - "name": "gas", - "species": [ - { - "name": "A" - } - ] - }, - { - "name": "aqueous", - "species": [ - { - "name": "B" - } - ] - } - ], - "reactions": [ - { - "type": "SIMPOL_PHASE_TRANSFER", - "gas phase": "gas", - "gas-phase species": [ - { - "name": "A", - "coefficient": 1 - } - ], - "condensed phase": "aqueous", - "condensed-phase species": [ - { - "name": "B", - "coefficient": 1 - } - ], - "B": [ - -1.97E+03, - 2.91E+00, - 1.96E-03, - -4.96E-01 - ], - "name": "my simpol", - "__comment": "cereal is also soup" - }, - { - "type": "SIMPOL_PHASE_TRANSFER", - "gas phase": "gas", - "gas-phase species": [ - { - "name": "A", - "coefficient": 1 - } - ], - "condensed phase": "aqueous", - "condensed-phase species": [ - { - "name": "B", - "coefficient": 1 - } - ], - "B": [ - -1.97E+03, - 2.91E+00, - 1.96E-03, - -4.96E-01 - ] - } - ] -} \ No newline at end of file diff --git a/test/unit/development/development_unit_configs/reactions/simpol_phase_transfer/valid.yaml b/test/unit/development/development_unit_configs/reactions/simpol_phase_transfer/valid.yaml deleted file mode 100644 index 90749998..00000000 --- a/test/unit/development/development_unit_configs/reactions/simpol_phase_transfer/valid.yaml +++ /dev/null @@ -1,43 +0,0 @@ -version: 2.0.0 -name: Valid surface -species: - - name: A - - name: B -phases: - - name: gas - species: - - name: A - - name: aqueous - species: - - name: B -reactions: - - type: SIMPOL_PHASE_TRANSFER - gas phase: gas - gas-phase species: - - name: A - coefficient: 1 - condensed phase: aqueous - condensed-phase species: - - name: B - coefficient: 1 - B: - - -1970.0 - - 2.91 - - 0.00196 - - -0.496 - name: my simpol - __comment: cereal is also soup - - type: SIMPOL_PHASE_TRANSFER - gas phase: gas - gas-phase species: - - name: A - coefficient: 1 - condensed phase: aqueous - condensed-phase species: - - name: B - coefficient: 1 - B: - - -1970.0 - - 2.91 - - 0.00196 - - -0.496 diff --git a/test/unit/development/development_unit_configs/reactions/surface/bad_reaction_component.json b/test/unit/development/development_unit_configs/reactions/surface/bad_reaction_component.json deleted file mode 100644 index 73e68672..00000000 --- a/test/unit/development/development_unit_configs/reactions/surface/bad_reaction_component.json +++ /dev/null @@ -1,58 +0,0 @@ -{ - "version": "2.0.0", - "name": "Bad reaction component", - "species": [ - { - "name": "A" - }, - { - "name": "B" - } - ], - "phases": [ - { - "name": "gas", - "species": [ - { - "name": "A" - }, - { - "name": "B" - } - ] - }, - { - "name": "surface reacting phase", - "species": [ - { - "name": "A" - }, - { - "name": "B" - } - ] - } - ], - "reactions": [ - { - "type": "SURFACE", - "gas phase": "gas", - "gas-phase species": [ - { - "name": "A", - "coefficient": 1 - } - ], - "reaction probability": 2.0e-2, - "gas-phase products": [ - { - "Name": "B", - "coefficient": 1 - } - ], - "condensed phase": "surface reacting phase", - "name": "my surface", - "__coment": "key lime pie is superior to all other pies" - } - ] -} \ No newline at end of file diff --git a/test/unit/development/development_unit_configs/reactions/surface/bad_reaction_component.yaml b/test/unit/development/development_unit_configs/reactions/surface/bad_reaction_component.yaml deleted file mode 100644 index f9f7c24f..00000000 --- a/test/unit/development/development_unit_configs/reactions/surface/bad_reaction_component.yaml +++ /dev/null @@ -1,27 +0,0 @@ -name: Bad reaction component -phases: -- name: gas - species: - - name: A - - name: B -- name: surface reacting phase - species: - - name: A - - name: B -reactions: -- __coment: key lime pie is superior to all other pies - condensed phase: surface reacting phase - gas phase: gas - gas-phase products: - - Name: B - coefficient: 1 - gas-phase species: - - name: "A" - coefficient: 1 - name: my surface - reaction probability: 0.02 - type: SURFACE -species: -- name: A -- name: B -version: 2.0.0 diff --git a/test/unit/development/development_unit_configs/reactions/surface/missing_condensed_phase.json b/test/unit/development/development_unit_configs/reactions/surface/missing_condensed_phase.json deleted file mode 100644 index 569cf997..00000000 --- a/test/unit/development/development_unit_configs/reactions/surface/missing_condensed_phase.json +++ /dev/null @@ -1,53 +0,0 @@ -{ - "version": "2.0.0", - "name": "Missing condensed phase", - "species": [ - { - "name": "A" - }, - { - "name": "B" - }, - { - "name": "C" - } - ], - "phases": [ - { - "name": "gas", - "species": [ - { - "name": "A" - }, - { - "name": "B" - }, - { - "name": "C" - } - ] - } - ], - "reactions": [ - { - "type": "SURFACE", - "gas phase": "gas", - "gas-phase species": [ - { - "name": "A", - "coefficient": 1 - } - ], - "gas-phase products": [ - { - "name": "B", - "__optional thing": "hello" - }, - { - "name": "C" - } - ], - "condensed phase": "surface reacting phase" - } - ] -} \ No newline at end of file diff --git a/test/unit/development/development_unit_configs/reactions/surface/missing_condensed_phase.yaml b/test/unit/development/development_unit_configs/reactions/surface/missing_condensed_phase.yaml deleted file mode 100644 index 77e8e0bd..00000000 --- a/test/unit/development/development_unit_configs/reactions/surface/missing_condensed_phase.yaml +++ /dev/null @@ -1,23 +0,0 @@ -name: Missing condensed phase -phases: -- name: gas - species: - - name: A - - name: B - - name: C -reactions: -- condensed phase: surface reacting phase - gas phase: gas - gas-phase products: - - __optional thing: hello - name: B - - name: C - gas-phase species: - - name: "A" - coefficient: 1 - type: SURFACE -species: -- name: A -- name: B -- name: C -version: 2.0.0 diff --git a/test/unit/development/development_unit_configs/reactions/surface/missing_gas_phase.json b/test/unit/development/development_unit_configs/reactions/surface/missing_gas_phase.json deleted file mode 100644 index b0ddb2a6..00000000 --- a/test/unit/development/development_unit_configs/reactions/surface/missing_gas_phase.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "version": "2.0.0", - "name": "Missing gas phase", - "species": [ - { - "name": "A" - }, - { - "name": "B" - }, - { - "name": "C" - } - ], - "phases": [ - { - "name": "surface reacting phase", - "species": [ - { - "name": "B" - }, - { - "name": "C" - } - ] - } - ], - "reactions": [ - { - "type": "SURFACE", - "gas phase": "gas", - "gas-phase species": [ - { - "name": "A", - "coefficient": 1 - } - ], - "gas-phase products": [ - { - "name": "B", - "__optional thing": "hello" - }, - { - "name": "C" - } - ], - "condensed phase": "surface reacting phase" - } - ] -} \ No newline at end of file diff --git a/test/unit/development/development_unit_configs/reactions/surface/missing_gas_phase.yaml b/test/unit/development/development_unit_configs/reactions/surface/missing_gas_phase.yaml deleted file mode 100644 index 464a2be4..00000000 --- a/test/unit/development/development_unit_configs/reactions/surface/missing_gas_phase.yaml +++ /dev/null @@ -1,22 +0,0 @@ -name: Missing gas phase -phases: -- name: surface reacting phase - species: - - name: B - - name: C -reactions: -- condensed phase: surface reacting phase - gas phase: gas - gas-phase products: - - __optional thing: hello - name: B - - name: C - gas-phase species: - - name: "A" - coefficient: 1 - type: SURFACE -species: -- name: A -- name: B -- name: C -version: 2.0.0 diff --git a/test/unit/development/development_unit_configs/reactions/surface/unknown_species.json b/test/unit/development/development_unit_configs/reactions/surface/unknown_species.json deleted file mode 100644 index a1d4b624..00000000 --- a/test/unit/development/development_unit_configs/reactions/surface/unknown_species.json +++ /dev/null @@ -1,60 +0,0 @@ -{ - "version": "2.0.0", - "name": "Unknown species", - "species": [ - { - "name": "A" - }, - { - "name": "B" - } - ], - "phases": [ - { - "name": "gas", - "species": [ - { - "name": "A" - }, - { - "name": "B" - } - ] - }, - { - "name": "surface reacting phase", - "species": [ - { - "name": "A" - }, - { - "name": "B" - } - ] - } - ], - "reactions": [ - { - "type": "SURFACE", - "gas phase": "gas", - "gas-phase species": [ - { - "name": "A", - "coefficient": 1 - } - ], - "reaction probability": 2.0e-2, - "gas-phase products": [ - { - "name": "B", - "coefficient": 1 - }, - { - "name": "C", - "coefficient": 1 - } - ], - "condensed phase": "surface reacting phase" - } - ] -} \ No newline at end of file diff --git a/test/unit/development/development_unit_configs/reactions/surface/unknown_species.yaml b/test/unit/development/development_unit_configs/reactions/surface/unknown_species.yaml deleted file mode 100644 index 34d9840c..00000000 --- a/test/unit/development/development_unit_configs/reactions/surface/unknown_species.yaml +++ /dev/null @@ -1,27 +0,0 @@ -name: Unknown species -phases: -- name: gas - species: - - name: A - - name: B -- name: surface reacting phase - species: - - name: A - - name: B -reactions: -- condensed phase: surface reacting phase - gas phase: gas - gas-phase products: - - coefficient: 1 - name: B - - coefficient: 1 - name: C - gas-phase species: - - name: "A" - coefficient: 1 - reaction probability: 0.02 - type: SURFACE -species: -- name: A -- name: B -version: 2.0.0 diff --git a/test/unit/development/development_unit_configs/reactions/surface/valid.json b/test/unit/development/development_unit_configs/reactions/surface/valid.json deleted file mode 100644 index a446cdc4..00000000 --- a/test/unit/development/development_unit_configs/reactions/surface/valid.json +++ /dev/null @@ -1,91 +0,0 @@ -{ - "version": "2.0.0", - "name": "Valid surface", - "species": [ - { - "name": "A" - }, - { - "name": "B" - }, - { - "name": "C" - } - ], - "phases": [ - { - "name": "gas", - "species": [ - { - "name": "A" - }, - { - "name": "B" - }, - { - "name": "C" - } - ] - }, - { - "name": "surface reacting phase", - "species": [ - { - "name": "A" - }, - { - "name": "B" - }, - { - "name": "C" - } - ] - } - ], - "reactions": [ - { - "type": "SURFACE", - "gas phase": "gas", - "gas-phase species": [ - { - "name": "A", - "coefficient": 1 - } - ], - "reaction probability": 2.0e-2, - "gas-phase products": [ - { - "name": "B", - "coefficient": 1 - }, - { - "name": "C", - "coefficient": 1 - } - ], - "condensed phase": "surface reacting phase", - "name": "my surface", - "__comment": "key lime pie is superior to all other pies" - }, - { - "type": "SURFACE", - "gas phase": "gas", - "gas-phase species": [ - { - "name": "A", - "coefficient": 1 - } - ], - "gas-phase products": [ - { - "name": "B", - "__optional thing": "hello" - }, - { - "name": "C" - } - ], - "condensed phase": "surface reacting phase" - } - ] -} \ No newline at end of file diff --git a/test/unit/development/development_unit_configs/reactions/surface/valid.yaml b/test/unit/development/development_unit_configs/reactions/surface/valid.yaml deleted file mode 100644 index 165c5418..00000000 --- a/test/unit/development/development_unit_configs/reactions/surface/valid.yaml +++ /dev/null @@ -1,47 +0,0 @@ -version: "2.0.0" -name: "Valid surface" - -species: - - name: "A" - - name: "B" - - name: "C" - -phases: - - name: "gas" - species: - - name: "A" - - name: "B" - - name: "C" - - - name: "surface reacting phase" - species: - - name: "A" - - name: "B" - - name: "C" - -reactions: - - type: "SURFACE" - gas phase: "gas" - gas-phase species: - - name: "A" - coefficient: 1 - reaction probability: 2.0e-2 - gas-phase products: - - name: "B" - coefficient: 1 - - name: "C" - coefficient: 1 - condensed phase: "surface reacting phase" - name: "my surface" - __comment: "key lime pie is superior to all other pies" - - - type: "SURFACE" - gas phase: "gas" - gas-phase species: - - name: "A" - coefficient: 1 - gas-phase products: - - name: "B" - __optional thing: "hello" - - name: "C" - condensed phase: "surface reacting phase" diff --git a/test/unit/development/development_unit_configs/reactions/taylor_series/bad_reaction_component.json b/test/unit/development/development_unit_configs/reactions/taylor_series/bad_reaction_component.json deleted file mode 100644 index d2db359f..00000000 --- a/test/unit/development/development_unit_configs/reactions/taylor_series/bad_reaction_component.json +++ /dev/null @@ -1,41 +0,0 @@ -{ - "version": "2.0.0", - "name": "Bad reaction component", - "species": [ - { - "name": "A" - }, - { - "name": "B" - } - ], - "phases": [ - { - "name": "gas", - "species": [ - { - "name": "A" - }, - { - "name": "B" - } - ] - } - ], - "reactions": [ - { - "type": "TAYLOR_SERIES", - "gas phase": "gas", - "reactants": [ - { - "Name": "A" - } - ], - "products": [ - { - "name": "B" - } - ] - } - ] -} \ No newline at end of file diff --git a/test/unit/development/development_unit_configs/reactions/taylor_series/bad_reaction_component.yaml b/test/unit/development/development_unit_configs/reactions/taylor_series/bad_reaction_component.yaml deleted file mode 100644 index 985e3cb1..00000000 --- a/test/unit/development/development_unit_configs/reactions/taylor_series/bad_reaction_component.yaml +++ /dev/null @@ -1,17 +0,0 @@ -name: Bad reaction component -phases: -- name: gas - species: - - name: A - - name: B -reactions: -- gas phase: gas - products: - - name: B - reactants: - - name: A - type: TAYLOR_SERIES -species: -- Name: A -- name: B -version: 2.0.0 diff --git a/test/unit/development/development_unit_configs/reactions/taylor_series/missing_phase.json b/test/unit/development/development_unit_configs/reactions/taylor_series/missing_phase.json deleted file mode 100644 index a136d87c..00000000 --- a/test/unit/development/development_unit_configs/reactions/taylor_series/missing_phase.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "version": "2.0.0", - "name": "Missing phase", - "species": [ - { - "name": "A" - }, - { - "name": "B" - }, - { - "name": "C" - } - ], - "phases": [], - "reactions": [ - { - "type": "TAYLOR_SERIES", - "gas phase": "gas", - "reactants": [ - { - "name": "A" - } - ], - "products": [ - { - "name": "C" - } - ] - } - ] -} \ No newline at end of file diff --git a/test/unit/development/development_unit_configs/reactions/taylor_series/missing_phase.yaml b/test/unit/development/development_unit_configs/reactions/taylor_series/missing_phase.yaml deleted file mode 100644 index 7d570684..00000000 --- a/test/unit/development/development_unit_configs/reactions/taylor_series/missing_phase.yaml +++ /dev/null @@ -1,14 +0,0 @@ -name: Missing phase -phases: [] -reactions: -- gas phase: gas - products: - - name: C - reactants: - - name: A - type: TAYLOR_SERIES -species: -- name: A -- name: B -- name: C -version: 2.0.0 diff --git a/test/unit/development/development_unit_configs/reactions/taylor_series/mutually_exclusive.json b/test/unit/development/development_unit_configs/reactions/taylor_series/mutually_exclusive.json deleted file mode 100644 index 98212368..00000000 --- a/test/unit/development/development_unit_configs/reactions/taylor_series/mutually_exclusive.json +++ /dev/null @@ -1,43 +0,0 @@ -{ - "version": "2.0.0", - "name": "Mutually Exclusive", - "species": [ - { - "name": "A" - }, - { - "name": "B" - } - ], - "phases": [ - { - "name": "gas", - "species": [ - { - "name": "A" - }, - { - "name": "B" - } - ] - } - ], - "reactions": [ - { - "type": "TAYLOR_SERIES", - "gas phase": "gas", - "reactants": [ - { - "name": "A" - } - ], - "products": [ - { - "name": "B" - } - ], - "C": 10, - "Ea": 0.5 - } - ] -} \ No newline at end of file diff --git a/test/unit/development/development_unit_configs/reactions/taylor_series/mutually_exclusive.yaml b/test/unit/development/development_unit_configs/reactions/taylor_series/mutually_exclusive.yaml deleted file mode 100644 index 5e7e7853..00000000 --- a/test/unit/development/development_unit_configs/reactions/taylor_series/mutually_exclusive.yaml +++ /dev/null @@ -1,19 +0,0 @@ -name: Mutually Exclusive -phases: -- name: gas - species: - - name: A - - name: B -reactions: -- C: 10 - Ea: 0.5 - gas phase: gas - products: - - name: B - reactants: - - name: A - type: TAYLOR_SERIES -species: -- name: A -- name: B -version: 2.0.0 diff --git a/test/unit/development/development_unit_configs/reactions/taylor_series/unknown_species.json b/test/unit/development/development_unit_configs/reactions/taylor_series/unknown_species.json deleted file mode 100644 index a9a2d0c5..00000000 --- a/test/unit/development/development_unit_configs/reactions/taylor_series/unknown_species.json +++ /dev/null @@ -1,41 +0,0 @@ -{ - "version": "2.0.0", - "name": "Unknown species", - "species": [ - { - "name": "A" - }, - { - "name": "B" - } - ], - "phases": [ - { - "name": "gas", - "species": [ - { - "name": "A" - }, - { - "name": "B" - } - ] - } - ], - "reactions": [ - { - "type": "TAYLOR_SERIES", - "gas phase": "gas", - "reactants": [ - { - "name": "A" - } - ], - "products": [ - { - "name": "C" - } - ] - } - ] -} \ No newline at end of file diff --git a/test/unit/development/development_unit_configs/reactions/taylor_series/unknown_species.yaml b/test/unit/development/development_unit_configs/reactions/taylor_series/unknown_species.yaml deleted file mode 100644 index f6d49972..00000000 --- a/test/unit/development/development_unit_configs/reactions/taylor_series/unknown_species.yaml +++ /dev/null @@ -1,17 +0,0 @@ -name: Unknown species -phases: -- name: gas - species: - - name: A - - name: B -reactions: -- gas phase: gas - products: - - name: C - reactants: - - name: A - type: TAYLOR_SERIES -species: -- name: A -- name: B -version: 2.0.0 diff --git a/test/unit/development/development_unit_configs/reactions/taylor_series/valid.json b/test/unit/development/development_unit_configs/reactions/taylor_series/valid.json deleted file mode 100644 index ed1aed21..00000000 --- a/test/unit/development/development_unit_configs/reactions/taylor_series/valid.json +++ /dev/null @@ -1,109 +0,0 @@ -{ - "version": "2.0.0", - "name": "Valid taylor_series", - "species": [ - { - "name": "A" - }, - { - "name": "B" - }, - { - "name": "C" - } - ], - "phases": [ - { - "name": "gas", - "species": [ - { - "name": "A" - }, - { - "name": "B" - }, - { - "name": "C" - } - ] - } - ], - "reactions": [ - { - "type": "TAYLOR_SERIES", - "gas phase": "gas", - "reactants": [ - { - "name": "A", - "coefficient": 1 - } - ], - "products": [ - { - "name": "B", - "coefficient": 1.2 - }, - { - "name": "C", - "coefficient": 0.3 - } - ], - "A": 32.1, - "B": -2.3, - "C": 102.3, - "D": 63.4, - "E": -1.3, - "taylor coefficients": [ - 1.0, - 2.0, - 3.0 - ], - "name": "my taylor_series", - "__solver_param": 0.1 - }, - { - "type": "TAYLOR_SERIES", - "gas phase": "gas", - "reactants": [ - { - "name": "A", - "coefficient": 2 - }, - { - "name": "B", - "coefficient": 0.1 - } - ], - "products": [ - { - "name": "C", - "coefficient": 0.5, - "__optional thing": "hello" - } - ], - "A": 3.1, - "B": -0.3, - "C": 12.3, - "D": 6.4, - "E": -0.3, - "taylor coefficients": [ - 10.5 - ], - "name": "my taylor_series2" - }, - { - "type": "TAYLOR_SERIES", - "gas phase": "gas", - "reactants": [ - { - "name": "A" - } - ], - "products": [ - { - "name": "C" - } - ] - } - ] -} \ No newline at end of file diff --git a/test/unit/development/development_unit_configs/reactions/taylor_series/valid.yaml b/test/unit/development/development_unit_configs/reactions/taylor_series/valid.yaml deleted file mode 100644 index 0e7be1df..00000000 --- a/test/unit/development/development_unit_configs/reactions/taylor_series/valid.yaml +++ /dev/null @@ -1,59 +0,0 @@ -name: Valid taylor_series -phases: -- name: gas - species: - - name: A - - name: B - - name: C -reactions: -- A: 32.1 - B: -2.3 - C: 102.3 - D: 63.4 - E: -1.3 - taylor coefficients: - - 1.0 - - 2.0 - - 3.0 - __solver_param: 0.1 - gas phase: gas - name: my taylor_series - products: - - coefficient: 1.2 - name: B - - coefficient: 0.3 - name: C - reactants: - - coefficient: 1 - name: A - type: TAYLOR_SERIES -- A: 3.1 - B: -0.3 - C: 12.3 - D: 6.4 - E: -0.3 - taylor coefficients: - - 10.5 - gas phase: gas - name: my taylor_series2 - products: - - __optional thing: hello - coefficient: 0.5 - name: C - reactants: - - coefficient: 2 - name: A - - coefficient: 0.1 - name: B - type: TAYLOR_SERIES -- gas phase: gas - products: - - name: C - reactants: - - name: A - type: TAYLOR_SERIES -species: -- name: A -- name: B -- name: C -version: 2.0.0 diff --git a/test/unit/development/development_unit_configs/reactions/ternary_chemical_activation/contains_nonstandard_key.json b/test/unit/development/development_unit_configs/reactions/ternary_chemical_activation/contains_nonstandard_key.json deleted file mode 100644 index f3d156bf..00000000 --- a/test/unit/development/development_unit_configs/reactions/ternary_chemical_activation/contains_nonstandard_key.json +++ /dev/null @@ -1,127 +0,0 @@ -{ - "version": "2.0.0", - "name": "Contains Nonstandard Key", - "species": [ - { - "name": "foo" - }, - { - "name": "bar" - }, - { - "name": "baz" - }, - { - "name": "quz" - } - ], - "phases": [ - { - "name": "gas", - "species": [ - { - "name": "foo" - }, - { - "name": "bar" - }, - { - "name": "baz" - }, - { - "name": "quz" - } - ] - } - ], - "reactions": [ - { - "type": "TERNARY_CHEMICAL_ACTIVATION", - "gas phase": "gas", - "Reactants": [ - { - "name": "foo", - "coefficient": 1 - }, - { - "name": "quz", - "coefficient": 2 - } - ], - "products": [ - { - "name": "bar", - "coefficient": 1.0 - }, - { - "name": "baz", - "coefficient": 3.2 - } - ] - }, - { - "type": "TERNARY_CHEMICAL_ACTIVATION", - "gas phase": "gas", - "reactants": [ - { - "name": "bar", - "coefficient": 1 - }, - { - "name": "baz", - "coefficient": 1 - } - ], - "Products": [ - { - "name": "bar", - "coefficient": 0.5 - }, - { - "name": "foo", - "coefficient": 0.0 - } - ], - "k0_A": 32.1, - "k0_B": -2.3, - "k0_C": 102.3, - "kinf_A": 63.4, - "kinf_B": -1.3, - "kinf_C": 908.5, - "Fc": 1.3, - "N": 32.1 - }, - { - "type": "TERNARY_CHEMICAL_ACTIVATION", - "gas phase": "gas", - "reactants": [ - { - "name": "bar", - "coefficient": 1 - }, - { - "name": "baz", - "coefficient": 1 - } - ], - "products": [ - { - "name": "bar", - "coefficient": 0.5 - }, - { - "name": "foo", - "coefficient": 0.0 - } - ], - "k0_a": 32.1, - "k0_b": -2.3, - "k0_c": 102.3, - "kinf_a": 63.4, - "kinf_b": -1.3, - "kinf_c": 908.5, - "fc": 1.3, - "n": 32.1 - } - ] -} \ No newline at end of file diff --git a/test/unit/development/development_unit_configs/reactions/ternary_chemical_activation/contains_nonstandard_key.yaml b/test/unit/development/development_unit_configs/reactions/ternary_chemical_activation/contains_nonstandard_key.yaml deleted file mode 100644 index 8a9a3a3a..00000000 --- a/test/unit/development/development_unit_configs/reactions/ternary_chemical_activation/contains_nonstandard_key.yaml +++ /dev/null @@ -1,68 +0,0 @@ ---- -version: 2.0.0 -name: Contains Nonstandard Key -species: -- name: foo -- name: bar -- name: baz -- name: quz -phases: -- name: gas - species: - - name: foo - - name: bar - - name: baz - - name: quz -reactions: -- type: TERNARY_CHEMICAL_ACTIVATION - gas phase: gas - Reactants: - - name: foo - coefficient: 1 - - name: quz - coefficient: 2 - products: - - name: bar - coefficient: 1 - - name: baz - coefficient: 3.2 -- type: TERNARY_CHEMICAL_ACTIVATION - gas phase: gas - reactants: - - name: bar - coefficient: 1 - - name: baz - coefficient: 1 - Products: - - name: bar - coefficient: 0.5 - - name: foo - coefficient: 0 - k0_A: 32.1 - k0_B: -2.3 - k0_C: 102.3 - kinf_A: 63.4 - kinf_B: -1.3 - kinf_C: 908.5 - Fc: 1.3 - "N": 32.1 -- type: TERNARY_CHEMICAL_ACTIVATION - gas phase: gas - reactants: - - name: bar - coefficient: 1 - - name: baz - coefficient: 1 - products: - - name: bar - coefficient: 0.5 - - name: foo - coefficient: 0 - k0_a: 32.1 - k0_b: -2.3 - k0_c: 102.3 - kinf_a: 63.4 - kinf_b: -1.3 - kinf_c: 908.5 - fc: 1.3 - "n": 32.1 diff --git a/test/unit/development/development_unit_configs/reactions/ternary_chemical_activation/missing_products.json b/test/unit/development/development_unit_configs/reactions/ternary_chemical_activation/missing_products.json deleted file mode 100644 index 183f0966..00000000 --- a/test/unit/development/development_unit_configs/reactions/ternary_chemical_activation/missing_products.json +++ /dev/null @@ -1,53 +0,0 @@ -{ - "version": "2.0.0", - "name": "Missing products", - "species": [ - { - "name": "foo" - }, - { - "name": "bar" - }, - { - "name": "baz" - }, - { - "name": "quz" - } - ], - "phases": [ - { - "name": "gas", - "species": [ - { - "name": "foo" - }, - { - "name": "bar" - }, - { - "name": "baz" - }, - { - "name": "quz" - } - ] - } - ], - "reactions": [ - { - "type": "TERNARY_CHEMICAL_ACTIVATION", - "gas phase": "gas", - "reactants": [ - { - "name": "foo", - "coefficient": 1 - }, - { - "name": "quz", - "coefficient": 2 - } - ] - } - ] -} \ No newline at end of file diff --git a/test/unit/development/development_unit_configs/reactions/ternary_chemical_activation/missing_products.yaml b/test/unit/development/development_unit_configs/reactions/ternary_chemical_activation/missing_products.yaml deleted file mode 100644 index df24feb5..00000000 --- a/test/unit/development/development_unit_configs/reactions/ternary_chemical_activation/missing_products.yaml +++ /dev/null @@ -1,23 +0,0 @@ ---- -version: 2.0.0 -name: Missing products -species: -- name: foo -- name: bar -- name: baz -- name: quz -phases: -- name: gas - species: - - name: foo - - name: bar - - name: baz - - name: quz -reactions: -- type: TERNARY_CHEMICAL_ACTIVATION - gas phase: gas - reactants: - - name: foo - coefficient: 1 - - name: quz - coefficient: 2 diff --git a/test/unit/development/development_unit_configs/reactions/ternary_chemical_activation/missing_reactants.json b/test/unit/development/development_unit_configs/reactions/ternary_chemical_activation/missing_reactants.json deleted file mode 100644 index 519a19e4..00000000 --- a/test/unit/development/development_unit_configs/reactions/ternary_chemical_activation/missing_reactants.json +++ /dev/null @@ -1,53 +0,0 @@ -{ - "version": "2.0.0", - "name": "Missing reactants", - "species": [ - { - "name": "foo" - }, - { - "name": "bar" - }, - { - "name": "baz" - }, - { - "name": "quz" - } - ], - "phases": [ - { - "name": "gas", - "species": [ - { - "name": "foo" - }, - { - "name": "bar" - }, - { - "name": "baz" - }, - { - "name": "quz" - } - ] - } - ], - "reactions": [ - { - "type": "TERNARY_CHEMICAL_ACTIVATION", - "gas phase": "gas", - "products": [ - { - "name": "bar", - "yield": 1.0 - }, - { - "name": "baz", - "yield": 3.2 - } - ] - } - ] -} \ No newline at end of file diff --git a/test/unit/development/development_unit_configs/reactions/ternary_chemical_activation/missing_reactants.yaml b/test/unit/development/development_unit_configs/reactions/ternary_chemical_activation/missing_reactants.yaml deleted file mode 100644 index bbbe7423..00000000 --- a/test/unit/development/development_unit_configs/reactions/ternary_chemical_activation/missing_reactants.yaml +++ /dev/null @@ -1,23 +0,0 @@ ---- -version: 2.0.0 -name: Missing reactants -species: -- name: foo -- name: bar -- name: baz -- name: quz -phases: -- name: gas - species: - - name: foo - - name: bar - - name: baz - - name: quz -reactions: -- type: TERNARY_CHEMICAL_ACTIVATION - gas phase: gas - products: - - name: bar - yield: 1 - - name: baz - yield: 3.2 diff --git a/test/unit/development/development_unit_configs/reactions/ternary_chemical_activation/unknown_species.json b/test/unit/development/development_unit_configs/reactions/ternary_chemical_activation/unknown_species.json deleted file mode 100644 index 843a933a..00000000 --- a/test/unit/development/development_unit_configs/reactions/ternary_chemical_activation/unknown_species.json +++ /dev/null @@ -1,97 +0,0 @@ -{ - "version": "2.0.0", - "name": "Valid", - "species": [ - { - "name": "foo" - }, - { - "name": "bar" - }, - { - "name": "baz" - }, - { - "name": "quz" - } - ], - "phases": [ - { - "name": "gas", - "species": [ - { - "name": "foo" - }, - { - "name": "bar" - }, - { - "name": "baz" - }, - { - "name": "quz" - } - ] - } - ], - "reactions": [ - { - "type": "TERNARY_CHEMICAL_ACTIVATION", - "gas phase": "gas", - "reactants": [ - { - "name": "foo", - "coefficient": 1 - }, - { - "name": "quz", - "coefficient": 2 - } - ], - "products": [ - { - "name": "bar", - "coefficient": 1.0 - }, - { - "name": "baz", - "coefficient": 3.2 - } - ] - }, - { - "__optional thing": "hello", - "type": "TERNARY_CHEMICAL_ACTIVATION", - "gas phase": "gas", - "reactants": [ - { - "name": "bar", - "coefficient": 1 - }, - { - "name": "baz", - "coefficient": 1 - } - ], - "products": [ - { - "name": "bar", - "coefficient": 0.5 - }, - { - "name": "FooFoo", - "coefficient": 0.0 - } - ], - "k0_A": 32.1, - "k0_B": -2.3, - "k0_C": 102.3, - "kinf_A": 63.4, - "kinf_B": -1.3, - "kinf_C": 908.5, - "Fc": 1.3, - "N": 32.1, - "name": "my ternary chemical activation" - } - ] -} \ No newline at end of file diff --git a/test/unit/development/development_unit_configs/reactions/ternary_chemical_activation/unknown_species.yaml b/test/unit/development/development_unit_configs/reactions/ternary_chemical_activation/unknown_species.yaml deleted file mode 100644 index 6a38908a..00000000 --- a/test/unit/development/development_unit_configs/reactions/ternary_chemical_activation/unknown_species.yaml +++ /dev/null @@ -1,52 +0,0 @@ -version: 2.0.0 -name: Valid -species: - - name: foo - - name: bar - - name: baz - - name: quz - -phases: - - name: gas - species: - - name: foo - - name: bar - - name: baz - - name: quz - -reactions: - - type: TERNARY_CHEMICAL_ACTIVATION - gas phase: gas - reactants: - - name: foo - coefficient: 1 - - name: quz - coefficient: 2 - products: - - name: bar - coefficient: 1.0 - - name: baz - coefficient: 3.2 - - - __optional thing: hello - type: TERNARY_CHEMICAL_ACTIVATION - gas phase: gas - reactants: - - name: bar - coefficient: 1 - - name: baz - coefficient: 1 - products: - - name: bar - coefficient: 0.5 - - name: FooFoo - coefficient: 0.0 - k0_A: 32.1 - k0_B: -2.3 - k0_C: 102.3 - kinf_A: 63.4 - kinf_B: -1.3 - kinf_C: 908.5 - Fc: 1.3 - N: 32.1 - name: my ternary chemical activation diff --git a/test/unit/development/development_unit_configs/reactions/ternary_chemical_activation/valid.json b/test/unit/development/development_unit_configs/reactions/ternary_chemical_activation/valid.json deleted file mode 100644 index d0f2e820..00000000 --- a/test/unit/development/development_unit_configs/reactions/ternary_chemical_activation/valid.json +++ /dev/null @@ -1,97 +0,0 @@ -{ - "version": "2.0.0", - "name": "Valid", - "species": [ - { - "name": "foo" - }, - { - "name": "bar" - }, - { - "name": "baz" - }, - { - "name": "quz" - } - ], - "phases": [ - { - "name": "gas", - "species": [ - { - "name": "foo" - }, - { - "name": "bar" - }, - { - "name": "baz" - }, - { - "name": "quz" - } - ] - } - ], - "reactions": [ - { - "type": "TERNARY_CHEMICAL_ACTIVATION", - "gas phase": "gas", - "reactants": [ - { - "name": "foo", - "coefficient": 1 - }, - { - "name": "quz", - "coefficient": 2 - } - ], - "products": [ - { - "name": "bar", - "coefficient": 1.0 - }, - { - "name": "baz", - "coefficient": 3.2 - } - ] - }, - { - "__optional thing": "hello", - "type": "TERNARY_CHEMICAL_ACTIVATION", - "gas phase": "gas", - "reactants": [ - { - "name": "bar", - "coefficient": 1 - }, - { - "name": "baz", - "coefficient": 1 - } - ], - "products": [ - { - "name": "bar", - "coefficient": 0.5 - }, - { - "name": "foo", - "coefficient": 0.0 - } - ], - "k0_A": 32.1, - "k0_B": -2.3, - "k0_C": 102.3, - "kinf_A": 63.4, - "kinf_B": -1.3, - "kinf_C": 908.5, - "Fc": 1.3, - "N": 32.1, - "name": "my ternary chemical activation" - } - ] -} \ No newline at end of file diff --git a/test/unit/development/development_unit_configs/reactions/ternary_chemical_activation/valid.yaml b/test/unit/development/development_unit_configs/reactions/ternary_chemical_activation/valid.yaml deleted file mode 100644 index 21d8d484..00000000 --- a/test/unit/development/development_unit_configs/reactions/ternary_chemical_activation/valid.yaml +++ /dev/null @@ -1,50 +0,0 @@ ---- -version: 2.0.0 -name: Valid -species: -- name: foo -- name: bar -- name: baz -- name: quz -phases: -- name: gas - species: - - name: foo - - name: bar - - name: baz - - name: quz -reactions: -- type: TERNARY_CHEMICAL_ACTIVATION - gas phase: gas - reactants: - - name: foo - coefficient: 1 - - name: quz - coefficient: 2 - products: - - name: bar - coefficient: 1 - - name: baz - coefficient: 3.2 -- type: TERNARY_CHEMICAL_ACTIVATION - __optional thing: hello - gas phase: gas - reactants: - - name: bar - coefficient: 1 - - name: baz - coefficient: 1 - products: - - name: bar - coefficient: 0.5 - - name: foo - coefficient: 0 - k0_A: 32.1 - k0_B: -2.3 - k0_C: 102.3 - kinf_A: 63.4 - kinf_B: -1.3 - kinf_C: 908.5 - Fc: 1.3 - "N": 32.1 - name: my ternary chemical activation diff --git a/test/unit/development/development_unit_configs/reactions/troe/bad_reaction_component.json b/test/unit/development/development_unit_configs/reactions/troe/bad_reaction_component.json deleted file mode 100644 index 71bdf348..00000000 --- a/test/unit/development/development_unit_configs/reactions/troe/bad_reaction_component.json +++ /dev/null @@ -1,41 +0,0 @@ -{ - "version": "2.0.0", - "name": "Bad reaction component", - "species": [ - { - "name": "A" - }, - { - "name": "B" - } - ], - "phases": [ - { - "name": "gas", - "species": [ - { - "name": "A" - }, - { - "name": "B" - } - ] - } - ], - "reactions": [ - { - "type": "TROE", - "gas phase": "gas", - "reactants": [ - { - "Name": "A" - } - ], - "products": [ - { - "name": "B" - } - ] - } - ] -} \ No newline at end of file diff --git a/test/unit/development/development_unit_configs/reactions/troe/bad_reaction_component.yaml b/test/unit/development/development_unit_configs/reactions/troe/bad_reaction_component.yaml deleted file mode 100644 index 969f8516..00000000 --- a/test/unit/development/development_unit_configs/reactions/troe/bad_reaction_component.yaml +++ /dev/null @@ -1,17 +0,0 @@ -name: Bad reaction component -phases: -- name: gas - species: - - name: A - - name: B -reactions: -- gas phase: gas - products: - - name: B - reactants: - - Name: A - type: TROE -species: -- name: A -- name: B -version: 2.0.0 diff --git a/test/unit/development/development_unit_configs/reactions/troe/missing_phase.json b/test/unit/development/development_unit_configs/reactions/troe/missing_phase.json deleted file mode 100644 index 45a33c9a..00000000 --- a/test/unit/development/development_unit_configs/reactions/troe/missing_phase.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "version": "2.0.0", - "name": "Missing phase", - "species": [ - { - "name": "A" - }, - { - "name": "B" - }, - { - "name": "C" - } - ], - "phases": [], - "reactions": [ - { - "type": "TROE", - "gas phase": "gas", - "reactants": [ - { - "name": "A" - } - ], - "products": [ - { - "name": "C" - } - ] - } - ] -} \ No newline at end of file diff --git a/test/unit/development/development_unit_configs/reactions/troe/missing_phase.yaml b/test/unit/development/development_unit_configs/reactions/troe/missing_phase.yaml deleted file mode 100644 index 2bc6b03c..00000000 --- a/test/unit/development/development_unit_configs/reactions/troe/missing_phase.yaml +++ /dev/null @@ -1,14 +0,0 @@ -name: Missing phase -phases: [] -reactions: -- gas phase: gas - products: - - name: C - reactants: - - name: A - type: TROE -species: -- name: A -- name: B -- name: C -version: 2.0.0 diff --git a/test/unit/development/development_unit_configs/reactions/troe/unknown_species.json b/test/unit/development/development_unit_configs/reactions/troe/unknown_species.json deleted file mode 100644 index 849f1d64..00000000 --- a/test/unit/development/development_unit_configs/reactions/troe/unknown_species.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - "version": "2.0.0", - "name": "Unknown species", - "species": [ - { - "name": "A" - }, - { - "name": "B" - } - ], - "phases": [ - { - "name": "gas", - "species": [ - { - "name": "A" - }, - { - "name": "B" - } - ] - } - ], - "reactions": [ - { - "__my comment": {}, - "type": "TROE", - "gas phase": "gas", - "reactants": [ - { - "name": "A" - } - ], - "products": [ - { - "name": "C" - } - ] - } - ] -} \ No newline at end of file diff --git a/test/unit/development/development_unit_configs/reactions/troe/unknown_species.yaml b/test/unit/development/development_unit_configs/reactions/troe/unknown_species.yaml deleted file mode 100644 index 7766b6fc..00000000 --- a/test/unit/development/development_unit_configs/reactions/troe/unknown_species.yaml +++ /dev/null @@ -1,18 +0,0 @@ -name: Unknown species -phases: -- name: gas - species: - - name: A - - name: B -reactions: -- __my comment: {} - gas phase: gas - products: - - name: C - reactants: - - name: A - type: TROE -species: -- name: A -- name: B -version: 2.0.0 diff --git a/test/unit/development/development_unit_configs/reactions/troe/valid.json b/test/unit/development/development_unit_configs/reactions/troe/valid.json deleted file mode 100644 index 0051bb55..00000000 --- a/test/unit/development/development_unit_configs/reactions/troe/valid.json +++ /dev/null @@ -1,79 +0,0 @@ -{ - "version": "2.0.0", - "name": "Valid troe", - "species": [ - { - "name": "A" - }, - { - "name": "B" - }, - { - "name": "C" - } - ], - "phases": [ - { - "name": "gas", - "species": [ - { - "name": "A" - }, - { - "name": "B" - }, - { - "name": "C" - } - ] - } - ], - "reactions": [ - { - "__my object": { - "a": 1.0 - }, - "type": "TROE", - "gas phase": "gas", - "reactants": [ - { - "name": "A" - } - ], - "products": [ - { - "name": "C" - } - ] - }, - { - "type": "TROE", - "gas phase": "gas", - "name": "my troe", - "reactants": [ - { - "name": "C" - } - ], - "products": [ - { - "name": "A", - "coefficient": 0.2, - "__optional thing": "hello" - }, - { - "name": "B", - "coefficient": 1.2 - } - ], - "k0_A": 32.1, - "k0_B": -2.3, - "k0_C": 102.3, - "kinf_A": 63.4, - "kinf_B": -1.3, - "kinf_C": 908.5, - "Fc": 1.3, - "N": 32.1 - } - ] -} \ No newline at end of file diff --git a/test/unit/development/development_unit_configs/reactions/troe/valid.yaml b/test/unit/development/development_unit_configs/reactions/troe/valid.yaml deleted file mode 100644 index 1611749a..00000000 --- a/test/unit/development/development_unit_configs/reactions/troe/valid.yaml +++ /dev/null @@ -1,40 +0,0 @@ -name: Valid troe -phases: -- name: gas - species: - - name: A - - name: B - - name: C -reactions: -- __my object: - a: 1.0 - gas phase: gas - products: - - name: C - reactants: - - name: A - type: TROE -- Fc: 1.3 - N: 32.1 - gas phase: gas - k0_A: 32.1 - k0_B: -2.3 - k0_C: 102.3 - kinf_A: 63.4 - kinf_B: -1.3 - kinf_C: 908.5 - name: my troe - products: - - __optional thing: hello - coefficient: 0.2 - name: A - - coefficient: 1.2 - name: B - reactants: - - name: C - type: TROE -species: -- name: A -- name: B -- name: C -version: 2.0.0 diff --git a/test/unit/development/development_unit_configs/reactions/tunneling/bad_reaction_component.json b/test/unit/development/development_unit_configs/reactions/tunneling/bad_reaction_component.json deleted file mode 100644 index 00ab7d08..00000000 --- a/test/unit/development/development_unit_configs/reactions/tunneling/bad_reaction_component.json +++ /dev/null @@ -1,41 +0,0 @@ -{ - "version": "2.0.0", - "name": "Bad reaction component", - "species": [ - { - "name": "A" - }, - { - "name": "B" - } - ], - "phases": [ - { - "name": "gas", - "species": [ - { - "name": "A" - }, - { - "name": "B" - } - ] - } - ], - "reactions": [ - { - "type": "TUNNELING", - "gas phase": "gas", - "reactants": [ - { - "Name": "A" - } - ], - "products": [ - { - "name": "B" - } - ] - } - ] -} \ No newline at end of file diff --git a/test/unit/development/development_unit_configs/reactions/tunneling/bad_reaction_component.yaml b/test/unit/development/development_unit_configs/reactions/tunneling/bad_reaction_component.yaml deleted file mode 100644 index eeca6c8c..00000000 --- a/test/unit/development/development_unit_configs/reactions/tunneling/bad_reaction_component.yaml +++ /dev/null @@ -1,17 +0,0 @@ -name: Bad reaction component -phases: -- name: gas - species: - - name: A - - name: B -reactions: -- gas phase: gas - products: - - name: B - reactants: - - Name: A - type: TUNNELING -species: -- name: A -- name: B -version: 2.0.0 diff --git a/test/unit/development/development_unit_configs/reactions/tunneling/missing_phase.json b/test/unit/development/development_unit_configs/reactions/tunneling/missing_phase.json deleted file mode 100644 index aded9ad0..00000000 --- a/test/unit/development/development_unit_configs/reactions/tunneling/missing_phase.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "version": "2.0.0", - "name": "Missing phase", - "species": [ - { - "name": "A" - }, - { - "name": "B" - }, - { - "name": "C" - } - ], - "phases": [], - "reactions": [ - { - "type": "TUNNELING", - "gas phase": "gas", - "A": 123.45, - "B": 1200.0, - "C": 1.0e8, - "reactants": [ - { - "name": "B", - "coefficient": 1 - } - ], - "products": [ - { - "name": "C" - } - ] - } - ] -} \ No newline at end of file diff --git a/test/unit/development/development_unit_configs/reactions/tunneling/missing_phase.yaml b/test/unit/development/development_unit_configs/reactions/tunneling/missing_phase.yaml deleted file mode 100644 index f669aaa4..00000000 --- a/test/unit/development/development_unit_configs/reactions/tunneling/missing_phase.yaml +++ /dev/null @@ -1,18 +0,0 @@ -name: Missing phase -phases: [] -reactions: -- A: 123.45 - B: 1200.0 - C: 100000000.0 - gas phase: gas - products: - - name: C - reactants: - - coefficient: 1 - name: B - type: TUNNELING -species: -- name: A -- name: B -- name: C -version: 2.0.0 diff --git a/test/unit/development/development_unit_configs/reactions/tunneling/unknown_species.json b/test/unit/development/development_unit_configs/reactions/tunneling/unknown_species.json deleted file mode 100644 index 343e5e4d..00000000 --- a/test/unit/development/development_unit_configs/reactions/tunneling/unknown_species.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - "version": "2.0.0", - "name": "Unknown species", - "species": [ - { - "name": "A" - }, - { - "name": "B" - } - ], - "phases": [ - { - "name": "gas", - "species": [ - { - "name": "A" - }, - { - "name": "B" - } - ] - } - ], - "reactions": [ - { - "__my comment": {}, - "type": "TUNNELING", - "gas phase": "gas", - "reactants": [ - { - "name": "A" - } - ], - "products": [ - { - "name": "C" - } - ] - } - ] -} \ No newline at end of file diff --git a/test/unit/development/development_unit_configs/reactions/tunneling/unknown_species.yaml b/test/unit/development/development_unit_configs/reactions/tunneling/unknown_species.yaml deleted file mode 100644 index bc7a7a4f..00000000 --- a/test/unit/development/development_unit_configs/reactions/tunneling/unknown_species.yaml +++ /dev/null @@ -1,18 +0,0 @@ -name: Unknown species -phases: -- name: gas - species: - - name: A - - name: B -reactions: -- __my comment: {} - gas phase: gas - products: - - name: C - reactants: - - name: A - type: TUNNELING -species: -- name: A -- name: B -version: 2.0.0 diff --git a/test/unit/development/development_unit_configs/reactions/tunneling/valid.json b/test/unit/development/development_unit_configs/reactions/tunneling/valid.json deleted file mode 100644 index 6d43ea44..00000000 --- a/test/unit/development/development_unit_configs/reactions/tunneling/valid.json +++ /dev/null @@ -1,73 +0,0 @@ -{ - "version": "2.0.0", - "name": "Valid tunneling", - "species": [ - { - "name": "A" - }, - { - "name": "B" - }, - { - "name": "C" - } - ], - "phases": [ - { - "name": "gas", - "species": [ - { - "name": "A" - }, - { - "name": "B" - }, - { - "name": "C" - } - ] - } - ], - "reactions": [ - { - "type": "TUNNELING", - "gas phase": "gas", - "A": 123.45, - "B": 1200.0, - "C": 1.0e8, - "reactants": [ - { - "name": "B", - "coefficient": 1 - } - ], - "products": [ - { - "name": "C" - } - ] - }, - { - "type": "TUNNELING", - "gas phase": "gas", - "name": "my tunneling", - "reactants": [ - { - "name": "B", - "coefficient": 1 - } - ], - "products": [ - { - "name": "A", - "coefficient": 0.2, - "__optional thing": "hello" - }, - { - "name": "B", - "coefficient": 1.2 - } - ] - } - ] -} \ No newline at end of file diff --git a/test/unit/development/development_unit_configs/reactions/tunneling/valid.yaml b/test/unit/development/development_unit_configs/reactions/tunneling/valid.yaml deleted file mode 100644 index a3888a93..00000000 --- a/test/unit/development/development_unit_configs/reactions/tunneling/valid.yaml +++ /dev/null @@ -1,35 +0,0 @@ -name: Valid tunneling -phases: -- name: gas - species: - - name: A - - name: B - - name: C -reactions: -- A: 123.45 - B: 1200.0 - C: 100000000.0 - gas phase: gas - products: - - name: C - reactants: - - coefficient: 1 - name: B - type: TUNNELING -- gas phase: gas - name: my tunneling - products: - - __optional thing: hello - coefficient: 0.2 - name: A - - coefficient: 1.2 - name: B - reactants: - - coefficient: 1 - name: B - type: TUNNELING -species: -- name: A -- name: B -- name: C -version: 2.0.0 diff --git a/test/unit/development/development_unit_configs/reactions/user_defined/bad_reaction_component.json b/test/unit/development/development_unit_configs/reactions/user_defined/bad_reaction_component.json deleted file mode 100644 index 199830f9..00000000 --- a/test/unit/development/development_unit_configs/reactions/user_defined/bad_reaction_component.json +++ /dev/null @@ -1,44 +0,0 @@ -{ - "version": "2.0.0", - "name": "Bad reaction component", - "species": [ - { - "name": "A" - }, - { - "name": "B" - } - ], - "phases": [ - { - "name": "gas", - "species": [ - { - "name": "A" - }, - { - "name": "B" - } - ] - } - ], - "reactions": [ - { - "type": "USER_DEFINED", - "gas phase": "gas", - "reactants": [ - { - "Name": "A", - "Coefficient": 1.2 - } - ], - "products": [ - { - "name": "B", - "coefficient": 0.2 - } - ], - "name": "my bad reaction" - } - ] -} \ No newline at end of file diff --git a/test/unit/development/development_unit_configs/reactions/user_defined/bad_reaction_component.yaml b/test/unit/development/development_unit_configs/reactions/user_defined/bad_reaction_component.yaml deleted file mode 100644 index 1cea14c8..00000000 --- a/test/unit/development/development_unit_configs/reactions/user_defined/bad_reaction_component.yaml +++ /dev/null @@ -1,20 +0,0 @@ -name: Bad reaction component -phases: -- name: gas - species: - - name: A - - name: B -reactions: -- gas phase: gas - products: - - coefficient: 0.2 - name: B - reactants: - - Coefficient: 1.2 - Name: A - type: USER_DEFINED - name: my bad reaction -species: -- name: A -- name: B -version: 2.0.0 diff --git a/test/unit/development/development_unit_configs/reactions/user_defined/missing_phase.json b/test/unit/development/development_unit_configs/reactions/user_defined/missing_phase.json deleted file mode 100644 index 16062550..00000000 --- a/test/unit/development/development_unit_configs/reactions/user_defined/missing_phase.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "version": "2.0.0", - "name": "Missing phase", - "species": [ - { - "name": "A" - }, - { - "name": "B" - }, - { - "name": "C" - } - ], - "phases": [], - "reactions": [ - { - "type": "USER_DEFINED", - "gas phase": "gas", - "reactants": [ - { - "name": "B", - "coefficient": 1.2 - } - ], - "products": [ - { - "name": "C", - "coefficient": 0.2 - } - ] - } - ] -} \ No newline at end of file diff --git a/test/unit/development/development_unit_configs/reactions/user_defined/missing_phase.yaml b/test/unit/development/development_unit_configs/reactions/user_defined/missing_phase.yaml deleted file mode 100644 index ca0ca681..00000000 --- a/test/unit/development/development_unit_configs/reactions/user_defined/missing_phase.yaml +++ /dev/null @@ -1,16 +0,0 @@ -name: Missing phase -phases: [] -reactions: -- gas phase: gas - products: - - coefficient: 0.2 - name: C - reactants: - - coefficient: 1.2 - name: B - type: USER_DEFINED -species: -- name: A -- name: B -- name: C -version: 2.0.0 diff --git a/test/unit/development/development_unit_configs/reactions/user_defined/unknown_species.json b/test/unit/development/development_unit_configs/reactions/user_defined/unknown_species.json deleted file mode 100644 index 679a2e66..00000000 --- a/test/unit/development/development_unit_configs/reactions/user_defined/unknown_species.json +++ /dev/null @@ -1,43 +0,0 @@ -{ - "version": "2.0.0", - "name": "Unknown species", - "species": [ - { - "name": "A" - }, - { - "name": "B" - } - ], - "phases": [ - { - "name": "gas", - "species": [ - { - "name": "A" - }, - { - "name": "B" - } - ] - } - ], - "reactions": [ - { - "type": "USER_DEFINED", - "gas phase": "gas", - "reactants": [ - { - "name": "B", - "coefficient": 1.2 - } - ], - "products": [ - { - "name": "C", - "coefficient": 0.2 - } - ] - } - ] -} \ No newline at end of file diff --git a/test/unit/development/development_unit_configs/reactions/user_defined/unknown_species.yaml b/test/unit/development/development_unit_configs/reactions/user_defined/unknown_species.yaml deleted file mode 100644 index 00eb1334..00000000 --- a/test/unit/development/development_unit_configs/reactions/user_defined/unknown_species.yaml +++ /dev/null @@ -1,19 +0,0 @@ -name: Unknown species -phases: -- name: gas - species: - - name: A - - name: B -reactions: -- gas phase: gas - products: - - coefficient: 0.2 - name: C - reactants: - - coefficient: 1.2 - name: B - type: USER_DEFINED -species: -- name: A -- name: B -version: 2.0.0 diff --git a/test/unit/development/development_unit_configs/reactions/user_defined/valid.json b/test/unit/development/development_unit_configs/reactions/user_defined/valid.json deleted file mode 100644 index 9b3a33b6..00000000 --- a/test/unit/development/development_unit_configs/reactions/user_defined/valid.json +++ /dev/null @@ -1,86 +0,0 @@ -{ - "version": "2.0.0", - "name": "Valid user_defined", - "species": [ - { - "name": "A" - }, - { - "name": "B" - }, - { - "name": "C" - } - ], - "phases": [ - { - "name": "gas", - "species": [ - { - "name": "A" - }, - { - "name": "B" - }, - { - "name": "C" - } - ] - }, - { - "name": "surface reacting phase", - "species": [ - { - "name": "A" - }, - { - "name": "B" - }, - { - "name": "C" - } - ] - } - ], - "reactions": [ - { - "type": "USER_DEFINED", - "gas phase": "gas", - "__comment": "hi", - "reactants": [ - { - "name": "B", - "coefficient": 1 - } - ], - "products": [ - { - "name": "C", - "coefficient": 1 - } - ], - "name": "my user defined", - "scaling factor": 12.3 - }, - { - "type": "USER_DEFINED", - "gas phase": "gas", - "reactants": [ - { - "name": "B", - "coefficient": 1.2 - }, - { - "name": "A", - "coefficient": 0.5 - } - ], - "products": [ - { - "name": "C", - "coefficient": 0.2 - } - ] - } - ] -} \ No newline at end of file diff --git a/test/unit/development/development_unit_configs/reactions/user_defined/valid.yaml b/test/unit/development/development_unit_configs/reactions/user_defined/valid.yaml deleted file mode 100644 index 99ebfcbf..00000000 --- a/test/unit/development/development_unit_configs/reactions/user_defined/valid.yaml +++ /dev/null @@ -1,39 +0,0 @@ -name: Valid user_defined -phases: -- name: gas - species: - - name: A - - name: B - - name: C -- name: surface reacting phase - species: - - name: A - - name: B - - name: C -reactions: -- __comment: hi - gas phase: gas - name: my user defined - products: - - coefficient: 1 - name: C - reactants: - - coefficient: 1 - name: B - scaling factor: 12.3 - type: USER_DEFINED -- gas phase: gas - products: - - coefficient: 0.2 - name: C - reactants: - - coefficient: 1.2 - name: B - - coefficient: 0.5 - name: A - type: USER_DEFINED -species: -- name: A -- name: B -- name: C -version: 2.0.0 diff --git a/test/unit/development/development_unit_configs/reactions/wet_deposition/missing_phase.json b/test/unit/development/development_unit_configs/reactions/wet_deposition/missing_phase.json deleted file mode 100644 index 040a6f31..00000000 --- a/test/unit/development/development_unit_configs/reactions/wet_deposition/missing_phase.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "version": "2.0.0", - "name": "Missing phase", - "species": [ - { - "name": "A" - }, - { - "name": "B" - }, - { - "name": "C" - } - ], - "phases": [], - "reactions": [ - { - "type": "WET_DEPOSITION", - "condensed phase": "cloud", - "name": "rxn cloud" - } - ] -} \ No newline at end of file diff --git a/test/unit/development/development_unit_configs/reactions/wet_deposition/missing_phase.yaml b/test/unit/development/development_unit_configs/reactions/wet_deposition/missing_phase.yaml deleted file mode 100644 index 80d5b066..00000000 --- a/test/unit/development/development_unit_configs/reactions/wet_deposition/missing_phase.yaml +++ /dev/null @@ -1,11 +0,0 @@ -name: Missing phase -phases: [] -reactions: -- condensed phase: cloud - name: rxn cloud - type: WET_DEPOSITION -species: -- name: A -- name: B -- name: C -version: 2.0.0 diff --git a/test/unit/development/development_unit_configs/reactions/wet_deposition/valid.json b/test/unit/development/development_unit_configs/reactions/wet_deposition/valid.json deleted file mode 100644 index ebe924ca..00000000 --- a/test/unit/development/development_unit_configs/reactions/wet_deposition/valid.json +++ /dev/null @@ -1,45 +0,0 @@ -{ - "version": "2.0.0", - "name": "Valid wet deposition", - "species": [ - { - "name": "A" - }, - { - "name": "B" - }, - { - "name": "C" - } - ], - "phases": [ - { - "name": "cloud", - "species": [ - { - "name": "A" - }, - { - "name": "B" - }, - { - "name": "C" - } - ] - } - ], - "reactions": [ - { - "type": "WET_DEPOSITION", - "condensed phase": "cloud", - "name": "rxn cloud", - "scaling factor": 12.3, - "__comment": "Tuxedo cats are the best" - }, - { - "type": "WET_DEPOSITION", - "condensed phase": "cloud", - "name": "rxn cloud2" - } - ] -} \ No newline at end of file diff --git a/test/unit/development/development_unit_configs/reactions/wet_deposition/valid.yaml b/test/unit/development/development_unit_configs/reactions/wet_deposition/valid.yaml deleted file mode 100644 index 55fe0866..00000000 --- a/test/unit/development/development_unit_configs/reactions/wet_deposition/valid.yaml +++ /dev/null @@ -1,21 +0,0 @@ -name: Valid wet deposition -phases: -- name: cloud - species: - - name: A - - name: B - - name: C -reactions: -- __comment: Tuxedo cats are the best - condensed phase: cloud - name: rxn cloud - scaling factor: 12.3 - type: WET_DEPOSITION -- condensed phase: cloud - name: rxn cloud2 - type: WET_DEPOSITION -species: -- name: A -- name: B -- name: C -version: 2.0.0 diff --git a/test/unit/development/development_unit_configs/species/duplicate_species.json b/test/unit/development/development_unit_configs/species/duplicate_species.json deleted file mode 100644 index 57274a6e..00000000 --- a/test/unit/development/development_unit_configs/species/duplicate_species.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "version": "2.0.0", - "name": "Duplicate Species", - "species": [ - { - "name": "FOO" - }, - { - "name": "BAZ" - }, - { - "name": "CYON" - }, - { - "name": "QUIZ" - }, - { - "name": "BAR" - }, - { - "name": "FOO" - }, - { - "name": "QUIZ" - } - ], - "phases": [], - "reactions": [] -} \ No newline at end of file diff --git a/test/unit/development/development_unit_configs/species/duplicate_species.yaml b/test/unit/development/development_unit_configs/species/duplicate_species.yaml deleted file mode 100644 index 6a459180..00000000 --- a/test/unit/development/development_unit_configs/species/duplicate_species.yaml +++ /dev/null @@ -1,12 +0,0 @@ -name: Duplicate Species -phases: [] -reactions: [] -species: -- name: FOO -- name: BAZ -- name: CYON -- name: QUIZ -- name: BAR -- name: FOO -- name: QUIZ -version: 2.0.0 diff --git a/test/unit/development/development_unit_configs/species/invalid_key.json b/test/unit/development/development_unit_configs/species/invalid_key.json deleted file mode 100644 index 421366dc..00000000 --- a/test/unit/development/development_unit_configs/species/invalid_key.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "version": "2.0.0", - "name": "Invalid key", - "species": [ - { - "name": "A", - "_absolute tolerance": 1.0e-30 - } - ], - "phases": [], - "reactions": [] -} \ No newline at end of file diff --git a/test/unit/development/development_unit_configs/species/invalid_key.yaml b/test/unit/development/development_unit_configs/species/invalid_key.yaml deleted file mode 100644 index 5e4219f4..00000000 --- a/test/unit/development/development_unit_configs/species/invalid_key.yaml +++ /dev/null @@ -1,7 +0,0 @@ -name: Invalid key -phases: [] -reactions: [] -species: -- _absolute tolerance: 1.0e-30 - name: A -version: 2.0.0 diff --git a/test/unit/development/development_unit_configs/species/missing_required_key.json b/test/unit/development/development_unit_configs/species/missing_required_key.json deleted file mode 100644 index 941dda61..00000000 --- a/test/unit/development/development_unit_configs/species/missing_required_key.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "version": "2.0.0", - "name": "Invalid key", - "species": [ - { - "Name": "A" - } - ], - "phases": [], - "reactions": [] -} \ No newline at end of file diff --git a/test/unit/development/development_unit_configs/species/missing_required_key.yaml b/test/unit/development/development_unit_configs/species/missing_required_key.yaml deleted file mode 100644 index c88932fd..00000000 --- a/test/unit/development/development_unit_configs/species/missing_required_key.yaml +++ /dev/null @@ -1,6 +0,0 @@ -name: Invalid key -phases: [] -reactions: [] -species: -- Name: A -version: 2.0.0 diff --git a/test/unit/development/development_unit_configs/species/valid_species.json b/test/unit/development/development_unit_configs/species/valid_species.json deleted file mode 100644 index 6ee8969f..00000000 --- a/test/unit/development/development_unit_configs/species/valid_species.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "version": "2.0.0", - "name": "Valid species configuration", - "species": [ - { - "name": "A", - "__absolute tolerance": 1.0e-30, - "is third body": true, - "__long name": "ozone" - }, - { - "name": "H2O2", - "HLC(298K) [mol m-3 Pa-1]": 1.011596348, - "HLC exponential factor [K]": 6340, - "diffusion coefficient [m2 s-1]": 1.46E-05, - "N star": 1.74, - "molecular weight [kg mol-1]": 0.0340147, - "constant concentration [mol m-3]": 2.5E19, - "density [kg m-3]": 1000.0, - "__absolute tolerance": 1.0e-10 - }, - { - "name": "aerosol stuff", - "molecular weight [kg mol-1]": 0.5, - "density [kg m-3]": 1000.0, - "constant mixing ratio [mol mol-1]": 1.0e-6, - "__absolute tolerance": 1.0e-20 - } - ], - "phases": [], - "reactions": [] -} \ No newline at end of file diff --git a/test/unit/development/development_unit_configs/species/valid_species.yaml b/test/unit/development/development_unit_configs/species/valid_species.yaml deleted file mode 100644 index af7ca8d6..00000000 --- a/test/unit/development/development_unit_configs/species/valid_species.yaml +++ /dev/null @@ -1,23 +0,0 @@ -name: Valid species configuration -phases: [] -reactions: [] -species: -- __absolute tolerance: 1.0e-30 - name: A - is third body: true - __long name: ozone -- HLC exponential factor [K]: 6340 - HLC(298K) [mol m-3 Pa-1]: 1.011596348 - N star: 1.74 - __absolute tolerance: 1.0e-10 - density [kg m-3]: 1000.0 - diffusion coefficient [m2 s-1]: 1.46e-05 - molecular weight [kg mol-1]: 0.0340147 - constant concentration [mol m-3]: 2.5e19 - name: H2O2 -- __absolute tolerance: 1.0e-20 - density [kg m-3]: 1000.0 - molecular weight [kg mol-1]: 0.5 - constant mixing ratio [mol mol-1]: 1.0e-6 - name: aerosol stuff -version: 2.0.0 diff --git a/test/unit/development/models/CMakeLists.txt b/test/unit/development/models/CMakeLists.txt deleted file mode 100644 index 54835df8..00000000 --- a/test/unit/development/models/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -################################################################################ -# Tests - -create_standard_test(NAME development_parse_modal SOURCES test_parse_modal.cpp) -create_standard_test(NAME development_parse_gas_model SOURCES test_parse_gas_model.cpp) \ No newline at end of file diff --git a/test/unit/development/models/test_parse_gas_model.cpp b/test/unit/development/models/test_parse_gas_model.cpp deleted file mode 100644 index 2c3e3377..00000000 --- a/test/unit/development/models/test_parse_gas_model.cpp +++ /dev/null @@ -1,76 +0,0 @@ -#include - -#include - -using namespace mechanism_configuration; - -TEST(ParseGas, ParseValidConfig) -{ - development::Parser parser; - - std::string path = "development_unit_configs/models/gas/valid"; - std::vector extensions = { ".json", ".yaml" }; - - for (auto& extension : extensions) - { - YAML::Node object = parser.FileToYaml(path + extension); - - auto validation_errors = parser.Validate(object); - EXPECT_EQ(validation_errors.size(), 0) << "Validation errors were: " << validation_errors.size(); - - auto mechanism = parser.Parse(object); - EXPECT_EQ(mechanism.models.gas_model.name, "gas"); - EXPECT_EQ(mechanism.models.gas_model.type, "GAS_PHASE"); - EXPECT_EQ(mechanism.models.gas_model.phase, "gas"); - } -} - -TEST(ParseGas, MissingPhase) -{ - development::Parser parser; - - std::string path = "development_unit_configs/models/gas/missing_phase"; - std::vector extensions = { ".json", ".yaml" }; - - for (auto& extension : extensions) - { - YAML::Node object = parser.FileToYaml(path + extension); - - auto validation_errors = parser.Validate(object); - EXPECT_EQ(validation_errors.size(), 1); - - std::multiset expected = { ConfigParseStatus::RequiredKeyNotFound }; - std::multiset actual; - for (const auto& [status, message] : validation_errors) - { - actual.insert(status); - std::cout << message << " " << configParseStatusToString(status) << std::endl; - } - EXPECT_EQ(actual, expected); - } -} - -TEST(ParseGas, PhaseNotFoundInRegisteredPhases) -{ - development::Parser parser; - - std::string path = "development_unit_configs/models/gas/gas_phase_not_found_in_phases"; - std::vector extensions = { ".json", ".yaml" }; - - for (auto& extension : extensions) - { - YAML::Node object = parser.FileToYaml(path + extension); - - auto validation_errors = parser.Validate(object); - EXPECT_EQ(validation_errors.size(), 2); - - std::multiset expected = { ConfigParseStatus::UnknownPhase, ConfigParseStatus::UnknownPhase }; - std::multiset actual; - for (const auto& [status, message] : validation_errors) - { - actual.insert(status); - std::cout << message << " " << configParseStatusToString(status) << std::endl; - } - EXPECT_EQ(actual, expected); - } -} \ No newline at end of file diff --git a/test/unit/development/models/test_parse_modal.cpp b/test/unit/development/models/test_parse_modal.cpp deleted file mode 100644 index ed9f1fc1..00000000 --- a/test/unit/development/models/test_parse_modal.cpp +++ /dev/null @@ -1,114 +0,0 @@ -#include - -#include - -using namespace mechanism_configuration; - -TEST(ParseModal, ParseValidConfig) -{ - development::Parser parser; - - std::string path = "development_unit_configs/models/modal/valid"; - std::vector extensions = { ".json", ".yaml" }; - - for (auto& extension : extensions) - { - YAML::Node object = parser.FileToYaml(path + extension); - - auto validation_errors = parser.Validate(object); - EXPECT_EQ(validation_errors.size(), 0) << "Validation errors were: " << validation_errors.size(); - - auto mechanism = parser.Parse(object); - EXPECT_EQ(mechanism.models.modal_model.type, "MODAL"); - EXPECT_EQ(mechanism.models.modal_model.name, "aqueous"); - EXPECT_EQ(mechanism.models.modal_model.modes.size(), 2); - EXPECT_EQ(mechanism.models.modal_model.modes[0].name, "aitken"); - EXPECT_EQ(mechanism.models.modal_model.modes[0].geometric_mean_diameter, 2.6e-8); - EXPECT_EQ(mechanism.models.modal_model.modes[0].geometric_standard_deviation, 1.6); - EXPECT_EQ(mechanism.models.modal_model.modes[0].phase, "aqueous"); - EXPECT_EQ(mechanism.models.modal_model.modes[0].unknown_properties.size(), 1); - EXPECT_EQ(mechanism.models.modal_model.modes[0].unknown_properties["__comment"], "Aitken mode"); - - EXPECT_EQ(mechanism.models.modal_model.modes[1].name, "accumulation"); - EXPECT_EQ(mechanism.models.modal_model.modes[1].geometric_mean_diameter, 1.1e-7); - EXPECT_EQ(mechanism.models.modal_model.modes[1].geometric_standard_deviation, 1.8); - EXPECT_EQ(mechanism.models.modal_model.modes[1].phase, "organic"); - EXPECT_EQ(mechanism.models.modal_model.modes[1].unknown_properties.size(), 0); - } -} - -TEST(ParseModal, MissingModes) -{ - development::Parser parser; - - std::string path = "development_unit_configs/models/modal/missing_modes"; - std::vector extensions = { ".json", ".yaml" }; - - for (auto& extension : extensions) - { - YAML::Node object = parser.FileToYaml(path + extension); - - auto validation_errors = parser.Validate(object); - EXPECT_EQ(validation_errors.size(), 1); - - std::multiset expected = { ConfigParseStatus::RequiredKeyNotFound }; - std::multiset actual; - for (const auto& [status, message] : validation_errors) - { - actual.insert(status); - std::cout << message << " " << configParseStatusToString(status) << std::endl; - } - EXPECT_EQ(actual, expected); - } -} - -TEST(ParseModal, MissingModalMemberData) -{ - development::Parser parser; - - std::string path = "development_unit_configs/models/modal/missing_modal_variable"; - std::vector extensions = { ".json", ".yaml" }; - - for (auto& extension : extensions) - { - YAML::Node object = parser.FileToYaml(path + extension); - - auto validation_errors = parser.Validate(object); - EXPECT_EQ(validation_errors.size(), 2); - - std::multiset expected = { ConfigParseStatus::RequiredKeyNotFound, - ConfigParseStatus::RequiredKeyNotFound }; - std::multiset actual; - for (const auto& [status, message] : validation_errors) - { - actual.insert(status); - std::cout << message << " " << configParseStatusToString(status) << std::endl; - } - EXPECT_EQ(actual, expected); - } -} - -TEST(ParseModal, PhaseInModeNotFoundInRegisteredPhase) -{ - development::Parser parser; - - std::string path = "development_unit_configs/models/modal/mode_phase_not_found_in_phases"; - std::vector extensions = { ".json", ".yaml" }; - - for (auto& extension : extensions) - { - YAML::Node object = parser.FileToYaml(path + extension); - - auto validation_errors = parser.Validate(object); - EXPECT_EQ(validation_errors.size(), 1); - - std::multiset expected = { ConfigParseStatus::UnknownPhase }; - std::multiset actual; - for (const auto& [status, message] : validation_errors) - { - actual.insert(status); - std::cout << message << " " << configParseStatusToString(status) << std::endl; - } - EXPECT_EQ(actual, expected); - } -} \ No newline at end of file diff --git a/test/unit/development/reactions/CMakeLists.txt b/test/unit/development/reactions/CMakeLists.txt deleted file mode 100644 index 70c6192c..00000000 --- a/test/unit/development/reactions/CMakeLists.txt +++ /dev/null @@ -1,20 +0,0 @@ -################################################################################ -# Tests - -create_standard_test(NAME development_parse_aqueous_equilibrium SOURCES test_parse_aqueous_equilibrium.cpp) -create_standard_test(NAME development_parse_arrhenius SOURCES test_parse_arrhenius.cpp) -create_standard_test(NAME development_parse_branched SOURCES test_parse_branched.cpp) -create_standard_test(NAME development_parse_condensed_phase_arrhenius SOURCES test_parse_condensed_phase_arrhenius.cpp) -create_standard_test(NAME development_parse_condensed_phase_photolysis SOURCES test_parse_condensed_phase_photolysis.cpp) -create_standard_test(NAME development_parse_emission SOURCES test_parse_emission.cpp) -create_standard_test(NAME development_parse_first_order_loss SOURCES test_parse_first_order_loss.cpp) -create_standard_test(NAME development_parse_henrys_law SOURCES test_parse_henrys_law.cpp) -create_standard_test(NAME development_parse_photolysis SOURCES test_parse_photolysis.cpp) -create_standard_test(NAME development_parse_surface SOURCES test_parse_surface.cpp) -create_standard_test(NAME development_parse_taylor_series SOURCES test_parse_taylor_series.cpp) -create_standard_test(NAME development_parse_troe SOURCES test_parse_troe.cpp) -create_standard_test(NAME development_parse_tunneling SOURCES test_parse_tunneling.cpp) -create_standard_test(NAME development_parse_simpol_phase_transfer SOURCES test_parse_simpol_phase_transfer.cpp) -create_standard_test(NAME development_parse_wet_deposition SOURCES test_parse_wet_deposition.cpp) -create_standard_test(NAME development_parse_user_defined SOURCES test_parse_user_defined.cpp) -create_standard_test(NAME development_parse_ternary_chemical_activation SOURCES test_parse_ternary_chemical_activation.cpp) \ No newline at end of file diff --git a/test/unit/development/reactions/test_parse_aqueous_equilibrium.cpp b/test/unit/development/reactions/test_parse_aqueous_equilibrium.cpp deleted file mode 100644 index ca98e211..00000000 --- a/test/unit/development/reactions/test_parse_aqueous_equilibrium.cpp +++ /dev/null @@ -1,166 +0,0 @@ -#include -#include - -#include - -#include - -using namespace mechanism_configuration; - -TEST(ParseAqueousEquilibrium, ParseValidConfig) -{ - development::Parser parser; - - std::string path = "development_unit_configs/reactions/aqueous_equilibrium/valid"; - std::vector extensions = { ".json", ".yaml" }; - - for (auto& extension : extensions) - { - YAML::Node object = parser.FileToYaml(path + extension); - - auto validation_errors = parser.Validate(object); - EXPECT_EQ(validation_errors.size(), 0) << "Validation errors were: " << validation_errors.size(); - - auto mechanism = parser.Parse(object); - EXPECT_EQ(mechanism.reactions.aqueous_equilibrium.size(), 2); - - EXPECT_EQ(mechanism.reactions.aqueous_equilibrium[0].name, "my aqueous eq"); - EXPECT_EQ(mechanism.reactions.aqueous_equilibrium[0].condensed_phase, "aqueous"); - EXPECT_EQ(mechanism.reactions.aqueous_equilibrium[0].condensed_phase_water, "H2O"); - EXPECT_EQ(mechanism.reactions.aqueous_equilibrium[0].A, 1.14e-2); - EXPECT_EQ(mechanism.reactions.aqueous_equilibrium[0].C, 2300.0); - EXPECT_EQ(mechanism.reactions.aqueous_equilibrium[0].k_reverse, 0.32); - EXPECT_EQ(mechanism.reactions.aqueous_equilibrium[0].reactants.size(), 1); - EXPECT_EQ(mechanism.reactions.aqueous_equilibrium[0].reactants[0].name, "A"); - EXPECT_EQ(mechanism.reactions.aqueous_equilibrium[0].reactants[0].coefficient, 2); - EXPECT_EQ(mechanism.reactions.aqueous_equilibrium[0].products.size(), 2); - EXPECT_EQ(mechanism.reactions.aqueous_equilibrium[0].products[0].name, "B"); - EXPECT_EQ(mechanism.reactions.aqueous_equilibrium[0].products[0].coefficient, 1); - EXPECT_EQ(mechanism.reactions.aqueous_equilibrium[0].products[1].name, "C"); - EXPECT_EQ(mechanism.reactions.aqueous_equilibrium[0].products[1].coefficient, 1); - EXPECT_EQ(mechanism.reactions.aqueous_equilibrium[0].unknown_properties.size(), 1); - EXPECT_EQ(mechanism.reactions.aqueous_equilibrium[0].unknown_properties["__comment"], "GIF is pronounced with a hard g"); - - EXPECT_EQ(mechanism.reactions.aqueous_equilibrium[1].condensed_phase, "aqueous"); - EXPECT_EQ(mechanism.reactions.aqueous_equilibrium[1].condensed_phase_water, "H2O"); - EXPECT_EQ(mechanism.reactions.aqueous_equilibrium[1].A, 1); - EXPECT_EQ(mechanism.reactions.aqueous_equilibrium[1].C, 0); - EXPECT_EQ(mechanism.reactions.aqueous_equilibrium[1].k_reverse, 0.32); - EXPECT_EQ(mechanism.reactions.aqueous_equilibrium[1].reactants.size(), 1); - EXPECT_EQ(mechanism.reactions.aqueous_equilibrium[1].reactants[0].name, "A"); - EXPECT_EQ(mechanism.reactions.aqueous_equilibrium[1].reactants[0].coefficient, 2); - EXPECT_EQ(mechanism.reactions.aqueous_equilibrium[1].products.size(), 2); - EXPECT_EQ(mechanism.reactions.aqueous_equilibrium[1].products[0].name, "B"); - EXPECT_EQ(mechanism.reactions.aqueous_equilibrium[1].products[0].coefficient, 1); - EXPECT_EQ(mechanism.reactions.aqueous_equilibrium[1].products[1].name, "C"); - EXPECT_EQ(mechanism.reactions.aqueous_equilibrium[1].products[1].coefficient, 1); - } -} - -TEST(ParseAqueousEquilibrium, DetectsUnknownSpecies) -{ - development::Parser parser; - - std::string path = "development_unit_configs/reactions/aqueous_equilibrium/unknown_species"; - std::vector extensions = { ".json", ".yaml" }; - - for (auto& extension : extensions) - { - YAML::Node object = parser.FileToYaml(path + extension); - - auto validation_errors = parser.Validate(object); - EXPECT_EQ(validation_errors.size(), 2); - - std::multiset expected = { ConfigParseStatus::ReactionRequiresUnknownSpecies, - ConfigParseStatus::RequestedSpeciesNotRegisteredInPhase }; - std::multiset actual; - for (const auto& [status, message] : validation_errors) - { - actual.insert(status); - std::cout << message << " " << configParseStatusToString(status) << std::endl; - } - EXPECT_EQ(actual, expected); - } -} - -TEST(ParseAqueousEquilibrium, DetectsBadReactionComponent) -{ - development::Parser parser; - - std::string path = "development_unit_configs/reactions/aqueous_equilibrium/bad_reaction_component"; - std::vector extensions = { ".json", ".yaml" }; - - for (auto& extension : extensions) - { - YAML::Node object = parser.FileToYaml(path + extension); - - auto validation_errors = parser.Validate(object); - EXPECT_EQ(validation_errors.size(), 1); - - std::multiset expected = { ConfigParseStatus::InvalidKey }; - std::multiset actual; - for (const auto& [status, message] : validation_errors) - { - actual.insert(status); - std::cout << message << " " << configParseStatusToString(status) << std::endl; - } - EXPECT_EQ(actual, expected); - } -} - -TEST(ParseAqueousEquilibrium, DetectsUnknownPhase) -{ - development::Parser parser; - - std::string path = "development_unit_configs/reactions/aqueous_equilibrium/missing_phase"; - std::vector extensions = { ".json", ".yaml" }; - - for (auto& extension : extensions) - { - YAML::Node object = parser.FileToYaml(path + extension); - - auto validation_errors = parser.Validate(object); - EXPECT_EQ(validation_errors.size(), 1); - - std::multiset expected = { ConfigParseStatus::UnknownPhase }; - std::multiset actual; - for (const auto& [status, message] : validation_errors) - { - actual.insert(status); - std::cout << message << " " << configParseStatusToString(status) << std::endl; - } - EXPECT_EQ(actual, expected); - } -} - -TEST(ValidateAqueousEquilibrium, UnknownSpeciesUnknownPhaseFailsValidation) -{ - using namespace development; - - std::vector existing_species = { types::Species{ .name = "foo" }, types::Species{ .name = "bar" } }; - std::vector existing_phases = { types::Phase{ .name = "aqueous" } }; - - YAML::Node reaction_node; - reaction_node["type"] = "AQUEOUS_EQUILIBRIUM"; - reaction_node["products"] = YAML::Load("[{ name: foo }]"); - reaction_node["condensed-phase water"] = "H2O"; - reaction_node["k_reverse"] = 0.46; - reaction_node["reactants"] = YAML::Load("[{ name: Foo }, { name: bar }]"); - - // Unknown gas phase name triggers validation error - reaction_node["condensed phase"] = "Aqueous"; - - AqueousEquilibriumParser parser; - Errors errors = parser.Validate(reaction_node, existing_species, existing_phases); - EXPECT_EQ(errors.size(), 2); - - std::multiset expected = { ConfigParseStatus::ReactionRequiresUnknownSpecies, - ConfigParseStatus::UnknownPhase }; - std::multiset actual; - for (const auto& [status, message] : errors) - { - actual.insert(status); - std::cout << message << " " << configParseStatusToString(status) << std::endl; - } - EXPECT_EQ(actual, expected); -} \ No newline at end of file diff --git a/test/unit/development/reactions/test_parse_arrhenius.cpp b/test/unit/development/reactions/test_parse_arrhenius.cpp deleted file mode 100644 index 36d6fe37..00000000 --- a/test/unit/development/reactions/test_parse_arrhenius.cpp +++ /dev/null @@ -1,211 +0,0 @@ -#include -#include - -#include - -#include - -using namespace mechanism_configuration; - -TEST(ParseArrhenius, ParseValidConfig) -{ - development::Parser parser; - - std::string path = "development_unit_configs/reactions/arrhenius/valid"; - std::vector extensions = { ".json", ".yaml" }; - - for (auto& extension : extensions) - { - YAML::Node object = parser.FileToYaml(path + extension); - - auto validation_errors = parser.Validate(object); - EXPECT_EQ(validation_errors.size(), 0) << "Validation errors were: " << validation_errors.size(); - - auto mechanism = parser.Parse(object); - EXPECT_EQ(mechanism.reactions.arrhenius.size(), 3); - - EXPECT_EQ(mechanism.reactions.arrhenius[0].name, "my arrhenius"); - EXPECT_EQ(mechanism.reactions.arrhenius[0].gas_phase, "gas"); - EXPECT_EQ(mechanism.reactions.arrhenius[0].A, 32.1); - EXPECT_EQ(mechanism.reactions.arrhenius[0].B, -2.3); - EXPECT_EQ(mechanism.reactions.arrhenius[0].C, 102.3); - EXPECT_EQ(mechanism.reactions.arrhenius[0].D, 63.4); - EXPECT_EQ(mechanism.reactions.arrhenius[0].E, -1.3); - EXPECT_EQ(mechanism.reactions.arrhenius[0].reactants.size(), 1); - EXPECT_EQ(mechanism.reactions.arrhenius[0].reactants[0].name, "A"); - EXPECT_EQ(mechanism.reactions.arrhenius[0].reactants[0].coefficient, 1); - EXPECT_EQ(mechanism.reactions.arrhenius[0].products.size(), 2); - EXPECT_EQ(mechanism.reactions.arrhenius[0].products[0].name, "B"); - EXPECT_EQ(mechanism.reactions.arrhenius[0].products[0].coefficient, 1.2); - EXPECT_EQ(mechanism.reactions.arrhenius[0].products[1].name, "C"); - EXPECT_EQ(mechanism.reactions.arrhenius[0].products[1].coefficient, 0.3); - EXPECT_EQ(mechanism.reactions.arrhenius[0].unknown_properties.size(), 1); - EXPECT_EQ(mechanism.reactions.arrhenius[0].unknown_properties["__solver_param"], "0.1"); - - EXPECT_EQ(mechanism.reactions.arrhenius[1].name, "my arrhenius2"); - EXPECT_EQ(mechanism.reactions.arrhenius[1].gas_phase, "gas"); - EXPECT_EQ(mechanism.reactions.arrhenius[1].A, 3.1); - EXPECT_EQ(mechanism.reactions.arrhenius[1].B, -0.3); - EXPECT_EQ(mechanism.reactions.arrhenius[1].C, 12.3); - EXPECT_EQ(mechanism.reactions.arrhenius[1].D, 6.4); - EXPECT_EQ(mechanism.reactions.arrhenius[1].E, -0.3); - EXPECT_EQ(mechanism.reactions.arrhenius[1].reactants.size(), 2); - EXPECT_EQ(mechanism.reactions.arrhenius[1].reactants[0].name, "A"); - EXPECT_EQ(mechanism.reactions.arrhenius[1].reactants[0].coefficient, 2); - EXPECT_EQ(mechanism.reactions.arrhenius[1].reactants[1].name, "B"); - EXPECT_EQ(mechanism.reactions.arrhenius[1].reactants[1].coefficient, 0.1); - EXPECT_EQ(mechanism.reactions.arrhenius[1].products.size(), 1); - EXPECT_EQ(mechanism.reactions.arrhenius[1].products[0].name, "C"); - EXPECT_EQ(mechanism.reactions.arrhenius[1].products[0].coefficient, 0.5); - EXPECT_EQ(mechanism.reactions.arrhenius[1].products[0].unknown_properties.size(), 1); - EXPECT_EQ(mechanism.reactions.arrhenius[1].products[0].unknown_properties["__optional thing"], "hello"); - - EXPECT_EQ(mechanism.reactions.arrhenius[2].name, ""); - EXPECT_EQ(mechanism.reactions.arrhenius[2].gas_phase, "gas"); - EXPECT_EQ(mechanism.reactions.arrhenius[2].A, 1); - EXPECT_EQ(mechanism.reactions.arrhenius[2].B, 0); - EXPECT_EQ(mechanism.reactions.arrhenius[2].C, 0); - EXPECT_EQ(mechanism.reactions.arrhenius[2].D, 300); - EXPECT_EQ(mechanism.reactions.arrhenius[2].E, 0); - EXPECT_EQ(mechanism.reactions.arrhenius[2].reactants.size(), 1); - EXPECT_EQ(mechanism.reactions.arrhenius[2].reactants[0].name, "A"); - EXPECT_EQ(mechanism.reactions.arrhenius[2].reactants[0].coefficient, 1); - EXPECT_EQ(mechanism.reactions.arrhenius[2].products.size(), 1); - EXPECT_EQ(mechanism.reactions.arrhenius[2].products[0].name, "C"); - EXPECT_EQ(mechanism.reactions.arrhenius[2].products[0].coefficient, 1); - } -} - -TEST(ParseArrhenius, DetectsUnknownSpecies) -{ - development::Parser parser; - - std::string path = "development_unit_configs/reactions/arrhenius/unknown_species"; - std::vector extensions = { ".json", ".yaml" }; - - for (auto& extension : extensions) - { - YAML::Node object = parser.FileToYaml(path + extension); - - auto validation_errors = parser.Validate(object); - EXPECT_EQ(validation_errors.size(), 4); - - std::multiset expected = { ConfigParseStatus::ReactionRequiresUnknownSpecies, - ConfigParseStatus::ReactionRequiresUnknownSpecies, - ConfigParseStatus::RequestedSpeciesNotRegisteredInPhase, - ConfigParseStatus::RequestedSpeciesNotRegisteredInPhase }; - std::multiset actual; - for (const auto& [status, message] : validation_errors) - { - actual.insert(status); - std::cout << message << " " << configParseStatusToString(status) << std::endl; - } - EXPECT_EQ(actual, expected); - } -} - -TEST(ParseArrhenius, DetectsMutuallyExclusiveOptions) -{ - development::Parser parser; - - std::string path = "development_unit_configs/reactions/arrhenius/mutually_exclusive"; - std::vector extensions = { ".json", ".yaml" }; - - for (auto& extension : extensions) - { - YAML::Node object = parser.FileToYaml(path + extension); - - auto validation_errors = parser.Validate(object); - EXPECT_EQ(validation_errors.size(), 1); - - std::multiset expected = { ConfigParseStatus::MutuallyExclusiveOption }; - std::multiset actual; - for (const auto& [status, message] : validation_errors) - { - actual.insert(status); - std::cout << message << " " << configParseStatusToString(status) << std::endl; - } - EXPECT_EQ(actual, expected); - } -} - -TEST(ParseArrhenius, DetectsBadReactionComponent) -{ - development::Parser parser; - - std::string path = "development_unit_configs/reactions/arrhenius/bad_reaction_component"; - std::vector extensions = { ".json", ".yaml" }; - - for (auto& extension : extensions) - { - YAML::Node object = parser.FileToYaml(path + extension); - - auto validation_errors = parser.Validate(object); - EXPECT_EQ(validation_errors.size(), 2); - - std::multiset expected = { ConfigParseStatus::RequiredKeyNotFound, ConfigParseStatus::InvalidKey }; - std::multiset actual; - for (const auto& [status, message] : validation_errors) - { - actual.insert(status); - std::cout << message << " " << configParseStatusToString(status) << std::endl; - } - EXPECT_EQ(actual, expected); - } -} - -TEST(ParseArrhenius, DetectsUnknownPhase) -{ - development::Parser parser; - - std::string path = "development_unit_configs/reactions/arrhenius/missing_phase"; - std::vector extensions = { ".json", ".yaml" }; - - for (auto& extension : extensions) - { - YAML::Node object = parser.FileToYaml(path + extension); - - auto validation_errors = parser.Validate(object); - EXPECT_EQ(validation_errors.size(), 1); - - std::multiset expected = { ConfigParseStatus::UnknownPhase }; - std::multiset actual; - for (const auto& [status, message] : validation_errors) - { - actual.insert(status); - std::cout << message << " " << configParseStatusToString(status) << std::endl; - } - EXPECT_EQ(actual, expected); - } -} - -TEST(ValidateArrhenius, MutuallyExclusiveEaAndCFailsValidation) -{ - using namespace development; - - YAML::Node reaction_node; - reaction_node["reactants"] = YAML::Load("[{ name: foo }]"); - reaction_node["products"] = YAML::Load("[{ name: bar }]"); - reaction_node["type"] = "ARRHENIUS"; - reaction_node["gas phase"] = "gas"; - - // Specify both Ea and C to trigger validation error - reaction_node["Ea"] = 0.5; - reaction_node["C"] = 10.0; - - std::vector existing_species = { types::Species{ .name = "foo" }, types::Species{ .name = "bar" } }; - std::vector existing_phases = { types::Phase{ .name = "gas" } }; - - ArrheniusParser parser; - Errors errors = parser.Validate(reaction_node, existing_species, existing_phases); - EXPECT_EQ(errors.size(), 1); - - std::multiset expected = { ConfigParseStatus::MutuallyExclusiveOption }; - std::multiset actual; - for (const auto& [status, message] : errors) - { - actual.insert(status); - std::cout << message << " " << configParseStatusToString(status) << std::endl; - } - EXPECT_EQ(actual, expected); -} \ No newline at end of file diff --git a/test/unit/development/reactions/test_parse_branched.cpp b/test/unit/development/reactions/test_parse_branched.cpp deleted file mode 100644 index 8062d00c..00000000 --- a/test/unit/development/reactions/test_parse_branched.cpp +++ /dev/null @@ -1,193 +0,0 @@ -#include -#include - -#include - -#include - -using namespace mechanism_configuration; - -TEST(ParseBranched, ParseValidConfig) -{ - development::Parser parser; - - std::string path = "development_unit_configs/reactions/branched/valid"; - std::vector extensions = { ".json", ".yaml" }; - - for (auto& extension : extensions) - { - YAML::Node object = parser.FileToYaml(path + extension); - - auto validation_errors = parser.Validate(object); - EXPECT_EQ(validation_errors.size(), 0) << "Validation errors were: " << validation_errors.size(); - - auto mechanism = parser.Parse(object); - EXPECT_EQ(mechanism.reactions.branched.size(), 1); - - EXPECT_EQ(mechanism.reactions.branched[0].gas_phase, "gas"); - EXPECT_EQ(mechanism.reactions.branched[0].name, "my branched"); - EXPECT_EQ(mechanism.reactions.branched[0].X, 1.2e-4); - EXPECT_EQ(mechanism.reactions.branched[0].Y, 167); - EXPECT_EQ(mechanism.reactions.branched[0].a0, 0.15); - EXPECT_EQ(mechanism.reactions.branched[0].n, 9); - EXPECT_EQ(mechanism.reactions.branched[0].reactants.size(), 1); - EXPECT_EQ(mechanism.reactions.branched[0].reactants[0].name, "A"); - EXPECT_EQ(mechanism.reactions.branched[0].reactants[0].coefficient, 1); - EXPECT_EQ(mechanism.reactions.branched[0].nitrate_products.size(), 1); - EXPECT_EQ(mechanism.reactions.branched[0].nitrate_products[0].name, "C"); - EXPECT_EQ(mechanism.reactions.branched[0].nitrate_products[0].coefficient, 1.2); - EXPECT_EQ(mechanism.reactions.branched[0].nitrate_products[0].unknown_properties.size(), 1); - EXPECT_EQ(mechanism.reactions.branched[0].nitrate_products[0].unknown_properties["__thing"], "hi"); - EXPECT_EQ(mechanism.reactions.branched[0].alkoxy_products.size(), 2); - EXPECT_EQ(mechanism.reactions.branched[0].alkoxy_products[0].name, "B"); - EXPECT_EQ(mechanism.reactions.branched[0].alkoxy_products[0].coefficient, 0.2); - EXPECT_EQ(mechanism.reactions.branched[0].alkoxy_products[1].name, "A"); - EXPECT_EQ(mechanism.reactions.branched[0].alkoxy_products[1].coefficient, 1.2); - EXPECT_EQ(mechanism.reactions.branched[0].unknown_properties.size(), 1); - EXPECT_EQ(mechanism.reactions.branched[0].unknown_properties["__comment"], "thing"); - } -} - -TEST(ParseBranched, DetectsUnknownSpecies) -{ - development::Parser parser; - - std::string path = "development_unit_configs/reactions/branched/unknown_species"; - std::vector extensions = { ".json", ".yaml" }; - - for (auto& extension : extensions) - { - YAML::Node object = parser.FileToYaml(path + extension); - - auto validation_errors = parser.Validate(object); - EXPECT_EQ(validation_errors.size(), 2); - - std::multiset expected = { ConfigParseStatus::ReactionRequiresUnknownSpecies, - ConfigParseStatus::RequestedSpeciesNotRegisteredInPhase }; - std::multiset actual; - for (const auto& [status, message] : validation_errors) - { - actual.insert(status); - std::cout << message << " " << configParseStatusToString(status) << std::endl; - } - EXPECT_EQ(actual, expected); - } -} - -TEST(ParseBranched, DetectsBadReactionComponent) -{ - development::Parser parser; - - std::string path = "development_unit_configs/reactions/branched/bad_reaction_component"; - std::vector extensions = { ".json", ".yaml" }; - - for (auto& extension : extensions) - { - YAML::Node object = parser.FileToYaml(path + extension); - - auto validation_errors = parser.Validate(object); - EXPECT_EQ(validation_errors.size(), 2); - - std::multiset expected = { ConfigParseStatus::RequiredKeyNotFound, ConfigParseStatus::InvalidKey }; - std::multiset actual; - for (const auto& [status, message] : validation_errors) - { - actual.insert(status); - std::cout << message << " " << configParseStatusToString(status) << std::endl; - } - EXPECT_EQ(actual, expected); - } -} - -TEST(ParseBranched, DetectsUnknownPhase) -{ - development::Parser parser; - - std::string path = "development_unit_configs/reactions/branched/missing_phase"; - std::vector extensions = { ".json", ".yaml" }; - - for (auto& extension : extensions) - { - YAML::Node object = parser.FileToYaml(path + extension); - - auto validation_errors = parser.Validate(object); - EXPECT_EQ(validation_errors.size(), 1); - - std::multiset expected = { ConfigParseStatus::UnknownPhase }; - std::multiset actual; - for (const auto& [status, message] : validation_errors) - { - actual.insert(status); - std::cout << message << " " << configParseStatusToString(status) << std::endl; - } - EXPECT_EQ(actual, expected); - } -} - -TEST(ParseBranched, MissingRequiredKeyFailsValidation) -{ - using namespace development; - - std::vector existing_species = { types::Species{ .name = "foo" }, - types::Species{ .name = "bar" }, - types::Species{ .name = "quiz" } }; - std::vector existing_phases = { types::Phase{ .name = "gas" } }; - - YAML::Node reaction_node; - reaction_node["type"] = "BRANCHED_NO_RO2"; - reaction_node["gas phase"] = "gas"; - reaction_node["reactants"] = YAML::Load("[{ name: foo }]"); - reaction_node["alkoxy products"] = YAML::Load("[{ name: bar }]"); - - // Incorrect required key triggers validation error - reaction_node["wrong nitrate products"] = YAML::Load("[{ name: quiz }]"); - - BranchedParser parser; - Errors errors = parser.Validate(reaction_node, existing_species, existing_phases); - EXPECT_EQ(errors.size(), 2); - - std::multiset expected = { ConfigParseStatus::RequiredKeyNotFound, ConfigParseStatus::InvalidKey }; - std::multiset actual; - for (const auto& [status, message] : errors) - { - actual.insert(status); - std::cout << message << " " << configParseStatusToString(status) << std::endl; - } - EXPECT_EQ(actual, expected); -} - -TEST(ValidateBranched, UnknownSpeciesAndUnknownPhaseFailsValidation) -{ - using namespace development; - - std::vector existing_species = { types::Species{ .name = "foo" }, - types::Species{ .name = "bar" }, - types::Species{ .name = "quiz" } }; - - std::vector existing_phases = { types::Phase{ .name = "gas" } }; - - YAML::Node reaction_node; - reaction_node["type"] = "BRANCHED_NO_RO2"; - reaction_node["reactants"] = YAML::Load("[{ name: foo }]"); - reaction_node["nitrate products"] = YAML::Load("[{ name: quiz }]"); - - // Unknown species triggers validation error - reaction_node["alkoxy products"] = YAML::Load("[{ name: bar }, { name: ABC }]"); - - // Unknown gas phase name triggers validation error - reaction_node["gas phase"] = "Gaseous Phase"; - - BranchedParser parser; - Errors errors = parser.Validate(reaction_node, existing_species, existing_phases); - EXPECT_EQ(errors.size(), 2); - - std::multiset expected = { ConfigParseStatus::ReactionRequiresUnknownSpecies, - ConfigParseStatus::UnknownPhase }; - std::multiset actual; - for (const auto& [status, message] : errors) - { - actual.insert(status); - std::cout << message << " " << configParseStatusToString(status) << std::endl; - } - EXPECT_EQ(actual, expected); -} \ No newline at end of file diff --git a/test/unit/development/reactions/test_parse_condensed_phase_arrhenius.cpp b/test/unit/development/reactions/test_parse_condensed_phase_arrhenius.cpp deleted file mode 100644 index 7754fe6b..00000000 --- a/test/unit/development/reactions/test_parse_condensed_phase_arrhenius.cpp +++ /dev/null @@ -1,235 +0,0 @@ -#include -#include - -#include - -#include - -using namespace mechanism_configuration; - -TEST(ParseCondensedPhaseArrhenius, ParseValidConfig) -{ - development::Parser parser; - - std::string path = "development_unit_configs/reactions/condensed_phase_arrhenius/valid"; - std::vector extensions = { ".json", ".yaml" }; - - for (auto& extension : extensions) - { - YAML::Node object = parser.FileToYaml(path + extension); - - auto validation_errors = parser.Validate(object); - EXPECT_EQ(validation_errors.size(), 0) << "Validation errors were: " << validation_errors.size(); - - auto mechanism = parser.Parse(object); - EXPECT_EQ(mechanism.reactions.condensed_phase_arrhenius.size(), 3); - - EXPECT_EQ(mechanism.reactions.condensed_phase_arrhenius[0].name, "my arrhenius"); - EXPECT_EQ(mechanism.reactions.condensed_phase_arrhenius[0].condensed_phase, "aqueous"); - EXPECT_EQ(mechanism.reactions.condensed_phase_arrhenius[0].A, 32.1); - EXPECT_EQ(mechanism.reactions.condensed_phase_arrhenius[0].B, -2.3); - EXPECT_EQ(mechanism.reactions.condensed_phase_arrhenius[0].C, 102.3); - EXPECT_EQ(mechanism.reactions.condensed_phase_arrhenius[0].D, 63.4); - EXPECT_EQ(mechanism.reactions.condensed_phase_arrhenius[0].E, -1.3); - EXPECT_EQ(mechanism.reactions.condensed_phase_arrhenius[0].reactants.size(), 1); - EXPECT_EQ(mechanism.reactions.condensed_phase_arrhenius[0].reactants[0].name, "A"); - EXPECT_EQ(mechanism.reactions.condensed_phase_arrhenius[0].reactants[0].coefficient, 1); - EXPECT_EQ(mechanism.reactions.condensed_phase_arrhenius[0].products.size(), 2); - EXPECT_EQ(mechanism.reactions.condensed_phase_arrhenius[0].products[0].name, "B"); - EXPECT_EQ(mechanism.reactions.condensed_phase_arrhenius[0].products[0].coefficient, 1.2); - EXPECT_EQ(mechanism.reactions.condensed_phase_arrhenius[0].products[1].name, "C"); - EXPECT_EQ(mechanism.reactions.condensed_phase_arrhenius[0].products[1].coefficient, 0.3); - EXPECT_EQ(mechanism.reactions.condensed_phase_arrhenius[0].unknown_properties.size(), 1); - EXPECT_EQ(mechanism.reactions.condensed_phase_arrhenius[0].unknown_properties["__solver_param"], "0.1"); - - EXPECT_EQ(mechanism.reactions.condensed_phase_arrhenius[1].name, "my arrhenius2"); - EXPECT_EQ(mechanism.reactions.condensed_phase_arrhenius[1].condensed_phase, "aqueous"); - EXPECT_EQ(mechanism.reactions.condensed_phase_arrhenius[1].A, 3.1); - EXPECT_EQ(mechanism.reactions.condensed_phase_arrhenius[1].B, -0.3); - EXPECT_EQ(mechanism.reactions.condensed_phase_arrhenius[1].C, 12.3); - EXPECT_EQ(mechanism.reactions.condensed_phase_arrhenius[1].D, 6.4); - EXPECT_EQ(mechanism.reactions.condensed_phase_arrhenius[1].E, -0.3); - EXPECT_EQ(mechanism.reactions.condensed_phase_arrhenius[1].reactants.size(), 2); - EXPECT_EQ(mechanism.reactions.condensed_phase_arrhenius[1].reactants[0].name, "A"); - EXPECT_EQ(mechanism.reactions.condensed_phase_arrhenius[1].reactants[0].coefficient, 2); - EXPECT_EQ(mechanism.reactions.condensed_phase_arrhenius[1].reactants[1].name, "B"); - EXPECT_EQ(mechanism.reactions.condensed_phase_arrhenius[1].reactants[1].coefficient, 0.1); - EXPECT_EQ(mechanism.reactions.condensed_phase_arrhenius[1].products.size(), 1); - EXPECT_EQ(mechanism.reactions.condensed_phase_arrhenius[1].products[0].name, "C"); - EXPECT_EQ(mechanism.reactions.condensed_phase_arrhenius[1].products[0].coefficient, 0.5); - EXPECT_EQ(mechanism.reactions.condensed_phase_arrhenius[1].products[0].unknown_properties.size(), 1); - EXPECT_EQ(mechanism.reactions.condensed_phase_arrhenius[1].products[0].unknown_properties["__optional thing"], "hello"); - - EXPECT_EQ(mechanism.reactions.condensed_phase_arrhenius[2].name, ""); - EXPECT_EQ(mechanism.reactions.condensed_phase_arrhenius[2].condensed_phase, "aqueous"); - EXPECT_EQ(mechanism.reactions.condensed_phase_arrhenius[2].A, 1); - EXPECT_EQ(mechanism.reactions.condensed_phase_arrhenius[2].B, 0); - EXPECT_EQ(mechanism.reactions.condensed_phase_arrhenius[2].C, 0); - EXPECT_EQ(mechanism.reactions.condensed_phase_arrhenius[2].D, 300); - EXPECT_EQ(mechanism.reactions.condensed_phase_arrhenius[2].E, 0); - EXPECT_EQ(mechanism.reactions.condensed_phase_arrhenius[2].reactants.size(), 1); - EXPECT_EQ(mechanism.reactions.condensed_phase_arrhenius[2].reactants[0].name, "A"); - EXPECT_EQ(mechanism.reactions.condensed_phase_arrhenius[2].reactants[0].coefficient, 1); - EXPECT_EQ(mechanism.reactions.condensed_phase_arrhenius[2].products.size(), 1); - EXPECT_EQ(mechanism.reactions.condensed_phase_arrhenius[2].products[0].name, "C"); - EXPECT_EQ(mechanism.reactions.condensed_phase_arrhenius[2].products[0].coefficient, 1); - } -} - -TEST(ParseCondensedPhaseArrhenius, DetectsUnknownSpecies) -{ - development::Parser parser; - - std::string path = "development_unit_configs/reactions/condensed_phase_arrhenius/unknown_species"; - std::vector extensions = { ".json", ".yaml" }; - - for (auto& extension : extensions) - { - YAML::Node object = parser.FileToYaml(path + extension); - - auto validation_errors = parser.Validate(object); - EXPECT_EQ(validation_errors.size(), 2); - - std::multiset expected = { ConfigParseStatus::ReactionRequiresUnknownSpecies, - ConfigParseStatus::RequestedSpeciesNotRegisteredInPhase }; - std::multiset actual; - for (const auto& [status, message] : validation_errors) - { - actual.insert(status); - std::cout << message << " " << configParseStatusToString(status) << std::endl; - } - EXPECT_EQ(actual, expected); - } -} - -TEST(ParseCondensedPhaseArrhenius, DetectsMutuallyExclusiveOptions) -{ - development::Parser parser; - - std::string path = "development_unit_configs/reactions/condensed_phase_arrhenius/mutually_exclusive"; - std::vector extensions = { ".json", ".yaml" }; - - for (auto& extension : extensions) - { - YAML::Node object = parser.FileToYaml(path + extension); - - auto validation_errors = parser.Validate(object); - EXPECT_EQ(validation_errors.size(), 1); - - std::multiset expected = { ConfigParseStatus::MutuallyExclusiveOption }; - std::multiset actual; - for (const auto& [status, message] : validation_errors) - { - actual.insert(status); - std::cout << message << " " << configParseStatusToString(status) << std::endl; - } - EXPECT_EQ(actual, expected); - } -} - -TEST(ParseCondensedPhaseArrhenius, DetectsBadReactionComponent) -{ - development::Parser parser; - - std::string path = "development_unit_configs/reactions/condensed_phase_arrhenius/bad_reaction_component"; - std::vector extensions = { ".json", ".yaml" }; - - for (auto& extension : extensions) - { - YAML::Node object = parser.FileToYaml(path + extension); - - auto validation_errors = parser.Validate(object); - EXPECT_EQ(validation_errors.size(), 2); - - std::multiset expected = { ConfigParseStatus::InvalidKey, ConfigParseStatus::RequiredKeyNotFound }; - std::multiset actual; - for (const auto& [status, message] : validation_errors) - { - actual.insert(status); - std::cout << message << " " << configParseStatusToString(status) << std::endl; - } - EXPECT_EQ(actual, expected); - } -} - -TEST(ParseCondensedPhaseArrhenius, DetectsWhenRequestedSpeciesAreNotInAqueousPhase) -{ - development::Parser parser; - - std::string path = "development_unit_configs/reactions/condensed_phase_arrhenius/species_not_in_aqueous_phase"; - std::vector extensions = { ".json", ".yaml" }; - - for (auto& extension : extensions) - { - YAML::Node object = parser.FileToYaml(path + extension); - - auto validation_errors = parser.Validate(object); - EXPECT_EQ(validation_errors.size(), 2); - - std::multiset expected = { ConfigParseStatus::RequestedSpeciesNotRegisteredInPhase, - ConfigParseStatus::RequestedSpeciesNotRegisteredInPhase }; - std::multiset actual; - for (const auto& [status, message] : validation_errors) - { - actual.insert(status); - std::cout << message << " " << configParseStatusToString(status) << std::endl; - } - EXPECT_EQ(actual, expected); - } -} - -TEST(ParseCondensedPhaseArrhenius, DetectsMissingPhase) -{ - development::Parser parser; - - std::string path = "development_unit_configs/reactions/condensed_phase_arrhenius/missing_phase"; - std::vector extensions = { ".json", ".yaml" }; - - for (auto& extension : extensions) - { - YAML::Node object = parser.FileToYaml(path + extension); - - auto validation_errors = parser.Validate(object); - EXPECT_EQ(validation_errors.size(), 1); - - std::multiset expected = { ConfigParseStatus::UnknownPhase }; - std::multiset actual; - for (const auto& [status, message] : validation_errors) - { - actual.insert(status); - std::cout << message << " " << configParseStatusToString(status) << std::endl; - } - EXPECT_EQ(actual, expected); - } -} - -TEST(ValidateCondensedPhaseArrhenius, MutuallyExclusiveEaAndCFailsValidation) -{ - using namespace development; - - std::vector existing_species = { types::Species{ .name = "foo" }, types::Species{ .name = "bar" } }; - std::vector existing_phases = { types::Phase{ .name = "aqueous" } }; - - YAML::Node reaction_node; - reaction_node["reactants"] = YAML::Load("[{ name: foo }]"); - reaction_node["products"] = YAML::Load("[{ name: bar }]"); - reaction_node["type"] = "CONDENSED_PHASE_ARRHENIUS"; - reaction_node["condensed phase"] = "organic"; - - // Specify both Ea and C to trigger validation error - reaction_node["Ea"] = 0.5; - reaction_node["C"] = 10.0; - - CondensedPhaseArrheniusParser parser; - Errors errors = parser.Validate(reaction_node, existing_species, existing_phases); - EXPECT_EQ(errors.size(), 1); - - std::multiset expected = { ConfigParseStatus::MutuallyExclusiveOption }; - std::multiset actual; - for (const auto& [status, message] : errors) - { - actual.insert(status); - std::cout << message << " " << configParseStatusToString(status) << std::endl; - } - EXPECT_EQ(actual, expected); -} \ No newline at end of file diff --git a/test/unit/development/reactions/test_parse_condensed_phase_photolysis.cpp b/test/unit/development/reactions/test_parse_condensed_phase_photolysis.cpp deleted file mode 100644 index 024223e9..00000000 --- a/test/unit/development/reactions/test_parse_condensed_phase_photolysis.cpp +++ /dev/null @@ -1,205 +0,0 @@ -#include -#include - -#include - -#include - -using namespace mechanism_configuration; - -TEST(ParseCondensedPhasePhotolysis, ParseValidConfig) -{ - development::Parser parser; - - std::string path = "development_unit_configs/reactions/condensed_phase_photolysis/valid"; - std::vector extensions = { ".json", ".yaml" }; - - for (auto& extension : extensions) - { - YAML::Node object = parser.FileToYaml(path + extension); - - auto validation_errors = parser.Validate(object); - EXPECT_EQ(validation_errors.size(), 0) << "Validation errors were: " << validation_errors.size(); - - auto mechanism = parser.Parse(object); - EXPECT_EQ(mechanism.reactions.condensed_phase_photolysis.size(), 2); - - EXPECT_EQ(mechanism.reactions.condensed_phase_photolysis[0].condensed_phase, "aqueous"); - EXPECT_EQ(mechanism.reactions.condensed_phase_photolysis[0].name, "my condensed phase photolysis"); - EXPECT_EQ(mechanism.reactions.condensed_phase_photolysis[0].scaling_factor, 12.3); - EXPECT_EQ(mechanism.reactions.condensed_phase_photolysis[0].reactants.name, "B"); - EXPECT_EQ(mechanism.reactions.condensed_phase_photolysis[0].reactants.coefficient, 1); - EXPECT_EQ(mechanism.reactions.condensed_phase_photolysis[0].products.size(), 1); - EXPECT_EQ(mechanism.reactions.condensed_phase_photolysis[0].products[0].name, "C"); - EXPECT_EQ(mechanism.reactions.condensed_phase_photolysis[0].products[0].coefficient, 1); - EXPECT_EQ(mechanism.reactions.condensed_phase_photolysis[0].unknown_properties.size(), 1); - EXPECT_EQ(mechanism.reactions.condensed_phase_photolysis[0].unknown_properties["__comment"], "hi"); - - EXPECT_EQ(mechanism.reactions.condensed_phase_photolysis[1].condensed_phase, "aqueous"); - EXPECT_EQ(mechanism.reactions.condensed_phase_photolysis[1].scaling_factor, 1); - EXPECT_EQ(mechanism.reactions.condensed_phase_photolysis[1].reactants.name, "B"); - EXPECT_EQ(mechanism.reactions.condensed_phase_photolysis[1].reactants.coefficient, 1.2); - EXPECT_EQ(mechanism.reactions.condensed_phase_photolysis[1].products.size(), 1); - EXPECT_EQ(mechanism.reactions.condensed_phase_photolysis[1].products[0].name, "C"); - EXPECT_EQ(mechanism.reactions.condensed_phase_photolysis[1].products[0].coefficient, 0.2); - } -} - -TEST(ParseCondensedPhasePhotolysis, DetectsUnknownSpecies) -{ - development::Parser parser; - - std::string path = "development_unit_configs/reactions/condensed_phase_photolysis/unknown_species"; - std::vector extensions = { ".json", ".yaml" }; - - for (auto& extension : extensions) - { - YAML::Node object = parser.FileToYaml(path + extension); - - auto validation_errors = parser.Validate(object); - EXPECT_EQ(validation_errors.size(), 2); - - std::multiset expected = { ConfigParseStatus::ReactionRequiresUnknownSpecies, - ConfigParseStatus::RequestedSpeciesNotRegisteredInPhase }; - std::multiset actual; - for (const auto& [status, message] : validation_errors) - { - actual.insert(status); - std::cout << message << " " << configParseStatusToString(status) << std::endl; - } - EXPECT_EQ(actual, expected); - } -} - -TEST(ParseCondensedPhasePhotolysis, DetectsBadReactionComponent) -{ - development::Parser parser; - - std::string path = "development_unit_configs/reactions/condensed_phase_photolysis/bad_reaction_component"; - std::vector extensions = { ".json", ".yaml" }; - - for (auto& extension : extensions) - { - YAML::Node object = parser.FileToYaml(path + extension); - - auto validation_errors = parser.Validate(object); - EXPECT_EQ(validation_errors.size(), 1); - - std::multiset expected = { ConfigParseStatus::InvalidKey }; - std::multiset actual; - for (const auto& [status, message] : validation_errors) - { - actual.insert(status); - std::cout << message << " " << configParseStatusToString(status) << std::endl; - } - EXPECT_EQ(actual, expected); - } -} - -TEST(ParseCondensedPhasePhotolysis, DetectsUnknownPhase) -{ - development::Parser parser; - - std::string path = "development_unit_configs/reactions/condensed_phase_photolysis/missing_phase"; - std::vector extensions = { ".json", ".yaml" }; - - for (auto& extension : extensions) - { - YAML::Node object = parser.FileToYaml(path + extension); - - auto validation_errors = parser.Validate(object); - EXPECT_EQ(validation_errors.size(), 1); - - std::multiset expected = { ConfigParseStatus::UnknownPhase }; - std::multiset actual; - for (const auto& [status, message] : validation_errors) - { - actual.insert(status); - std::cout << message << " " << configParseStatusToString(status) << std::endl; - } - EXPECT_EQ(actual, expected); - } -} - -TEST(ParseCondensedPhasePhotolysis, DoesNotAcceptMoreThanOneReactant) -{ - development::Parser parser; - - std::string path = "development_unit_configs/reactions/condensed_phase_photolysis/more_than_one_reactant"; - std::vector extensions = { ".json", ".yaml" }; - - for (auto& extension : extensions) - { - YAML::Node object = parser.FileToYaml(path + extension); - - auto validation_errors = parser.Validate(object); - EXPECT_EQ(validation_errors.size(), 1); - - std::multiset expected = { ConfigParseStatus::TooManyReactionComponents }; - std::multiset actual; - for (const auto& [status, message] : validation_errors) - { - actual.insert(status); - std::cout << message << " " << configParseStatusToString(status) << std::endl; - } - EXPECT_EQ(actual, expected); - } -} - -TEST(ParseCondensedPhasePhotolysis, DetectsWhenRequestedSpeciesAreNotInAqueousPhase) -{ - development::Parser parser; - - std::string path = "development_unit_configs/reactions/condensed_phase_photolysis/species_not_in_aqueous_phase"; - std::vector extensions = { ".json", ".yaml" }; - - for (auto& extension : extensions) - { - YAML::Node object = parser.FileToYaml(path + extension); - - auto validation_errors = parser.Validate(object); - EXPECT_EQ(validation_errors.size(), 1); - - std::multiset expected = { ConfigParseStatus::RequestedSpeciesNotRegisteredInPhase }; - std::multiset actual; - for (const auto& [status, message] : validation_errors) - { - actual.insert(status); - std::cout << message << " " << configParseStatusToString(status) << std::endl; - } - EXPECT_EQ(actual, expected); - } -} - -TEST(ValidateCondensedPhasePhotolysis, InvalidNumberReactantUnknownSpeciesUnknownPhaseFailsValidation) -{ - using namespace development; - - std::vector existing_species = { types::Species{ .name = "foo" }, types::Species{ .name = "bar" } }; - std::vector existing_phases = { types::Phase{ .name = "aqueous" } }; - - YAML::Node reaction_node; - reaction_node["type"] = "CONDENSED_PHASE_PHOTOLYSIS"; - reaction_node["products"] = YAML::Load("[{ name: foo }]"); - - // Invalid number of reactions triggers validation error - reaction_node["reactants"] = YAML::Load("[{ name: quiz }, { name: bar }]"); - - // Unknown phase name triggers validation error - reaction_node["condensed phase"] = "organic"; - - CondensedPhasePhotolysisParser parser; - Errors errors = parser.Validate(reaction_node, existing_species, existing_phases); - EXPECT_EQ(errors.size(), 3); - - std::multiset expected = { ConfigParseStatus::TooManyReactionComponents, - ConfigParseStatus::ReactionRequiresUnknownSpecies, - ConfigParseStatus::UnknownPhase }; - std::multiset actual; - for (const auto& [status, message] : errors) - { - actual.insert(status); - std::cout << message << " " << configParseStatusToString(status) << std::endl; - } - EXPECT_EQ(actual, expected); -} \ No newline at end of file diff --git a/test/unit/development/reactions/test_parse_emission.cpp b/test/unit/development/reactions/test_parse_emission.cpp deleted file mode 100644 index 709d463b..00000000 --- a/test/unit/development/reactions/test_parse_emission.cpp +++ /dev/null @@ -1,147 +0,0 @@ -#include -#include - -#include - -#include - -using namespace mechanism_configuration; - -TEST(ParseEmission, ParseValidConfig) -{ - development::Parser parser; - - std::string path = "development_unit_configs/reactions/emission/valid"; - std::vector extensions = { ".json", ".yaml" }; - - for (auto& extension : extensions) - { - YAML::Node object = parser.FileToYaml(path + extension); - - auto validation_errors = parser.Validate(object); - EXPECT_EQ(validation_errors.size(), 0) << "Validation errors were: " << validation_errors.size(); - - auto mechanism = parser.Parse(object); - EXPECT_EQ(mechanism.reactions.emission.size(), 2); - - EXPECT_EQ(mechanism.reactions.emission[0].gas_phase, "gas"); - EXPECT_EQ(mechanism.reactions.emission[0].name, "my emission"); - EXPECT_EQ(mechanism.reactions.emission[0].scaling_factor, 12.3); - EXPECT_EQ(mechanism.reactions.emission[0].products.size(), 1); - EXPECT_EQ(mechanism.reactions.emission[0].products[0].name, "B"); - EXPECT_EQ(mechanism.reactions.emission[0].products[0].coefficient, 1); - EXPECT_EQ(mechanism.reactions.emission[0].unknown_properties.size(), 1); - EXPECT_EQ(mechanism.reactions.emission[0].unknown_properties["__comment"], "Dr. Pepper outranks any other soda"); - - EXPECT_EQ(mechanism.reactions.emission[1].gas_phase, "gas"); - EXPECT_EQ(mechanism.reactions.emission[1].scaling_factor, 1); - EXPECT_EQ(mechanism.reactions.emission[1].products.size(), 1); - EXPECT_EQ(mechanism.reactions.emission[1].products[0].name, "B"); - EXPECT_EQ(mechanism.reactions.emission[1].products[0].coefficient, 1); - } -} - -TEST(ParseEmission, DetectsUnknownSpecies) -{ - development::Parser parser; - - std::string path = "development_unit_configs/reactions/emission/unknown_species"; - std::vector extensions = { ".json", ".yaml" }; - - for (auto& extension : extensions) - { - YAML::Node object = parser.FileToYaml(path + extension); - - auto validation_errors = parser.Validate(object); - EXPECT_EQ(validation_errors.size(), 2); - - std::multiset expected = { ConfigParseStatus::ReactionRequiresUnknownSpecies, - ConfigParseStatus::RequestedSpeciesNotRegisteredInPhase }; - std::multiset actual; - for (const auto& [status, message] : validation_errors) - { - actual.insert(status); - std::cout << message << " " << configParseStatusToString(status) << std::endl; - } - EXPECT_EQ(actual, expected); - } -} - -TEST(ParseEmission, DetectsBadReactionComponent) -{ - development::Parser parser; - - std::string path = "development_unit_configs/reactions/emission/bad_reaction_component"; - std::vector extensions = { ".json", ".yaml" }; - - for (auto& extension : extensions) - { - YAML::Node object = parser.FileToYaml(path + extension); - - auto validation_errors = parser.Validate(object); - EXPECT_EQ(validation_errors.size(), 2); - - std::multiset expected = { ConfigParseStatus::RequiredKeyNotFound, ConfigParseStatus::InvalidKey }; - std::multiset actual; - for (const auto& [status, message] : validation_errors) - { - actual.insert(status); - std::cout << message << " " << configParseStatusToString(status) << std::endl; - } - EXPECT_EQ(actual, expected); - } -} - -TEST(ParseEmission, DetectsUnknownPhase) -{ - development::Parser parser; - - std::string path = "development_unit_configs/reactions/emission/missing_phase"; - std::vector extensions = { ".json", ".yaml" }; - - for (auto& extension : extensions) - { - YAML::Node object = parser.FileToYaml(path + extension); - - auto validation_errors = parser.Validate(object); - EXPECT_EQ(validation_errors.size(), 1); - - std::multiset expected = { ConfigParseStatus::UnknownPhase }; - std::multiset actual; - for (const auto& [status, message] : validation_errors) - { - actual.insert(status); - std::cout << message << " " << configParseStatusToString(status) << std::endl; - } - EXPECT_EQ(actual, expected); - } -} - -TEST(ValidateEmission, UnknownSpeciesAndUnknownPhaseFailsValidation) -{ - using namespace development; - - std::vector existing_species = { types::Species{ .name = "foo" }, types::Species{ .name = "bar" } }; - std::vector existing_phases = { types::Phase{ .name = "gas" } }; - - YAML::Node reaction_node; - reaction_node["type"] = "EMISSION"; - reaction_node["products"] = YAML::Load("[{ name: quiz }]"); - - // Unknown gas phase name triggers validation error - reaction_node["gas phase"] = "what is emission phase"; - - EmissionParser parser; - Errors errors = parser.Validate(reaction_node, existing_species, existing_phases); - EXPECT_EQ(errors.size(), 2); - - std::multiset expected = { ConfigParseStatus::ReactionRequiresUnknownSpecies, - ConfigParseStatus::UnknownPhase }; - std::multiset actual; - for (const auto& [status, message] : errors) - { - actual.insert(status); - std::cout << message << " " << configParseStatusToString(status) << std::endl; - } - EXPECT_EQ(actual, expected); -} \ No newline at end of file diff --git a/test/unit/development/reactions/test_parse_first_order_loss.cpp b/test/unit/development/reactions/test_parse_first_order_loss.cpp deleted file mode 100644 index 22974b61..00000000 --- a/test/unit/development/reactions/test_parse_first_order_loss.cpp +++ /dev/null @@ -1,174 +0,0 @@ -#include -#include - -#include - -#include - -using namespace mechanism_configuration; - -TEST(ParseFirstOrderLoss, ParseValidConfig) -{ - development::Parser parser; - - std::string path = "development_unit_configs/reactions/first_order_loss/valid"; - std::vector extensions = { ".json", ".yaml" }; - - for (auto& extension : extensions) - { - YAML::Node object = parser.FileToYaml(path + extension); - - auto validation_errors = parser.Validate(object); - EXPECT_EQ(validation_errors.size(), 0) << "Validation errors were: " << validation_errors.size(); - - auto mechanism = parser.Parse(object); - EXPECT_EQ(mechanism.reactions.first_order_loss.size(), 2); - - EXPECT_EQ(mechanism.reactions.first_order_loss[0].gas_phase, "gas"); - EXPECT_EQ(mechanism.reactions.first_order_loss[0].name, "my first order loss"); - EXPECT_EQ(mechanism.reactions.first_order_loss[0].scaling_factor, 12.3); - EXPECT_EQ(mechanism.reactions.first_order_loss[0].reactants.name, "C"); - EXPECT_EQ(mechanism.reactions.first_order_loss[0].reactants.coefficient, 1); - EXPECT_EQ(mechanism.reactions.first_order_loss[0].unknown_properties.size(), 1); - EXPECT_EQ( - mechanism.reactions.first_order_loss[0].unknown_properties["__comment"], "Strawberries are the superior fruit"); - - EXPECT_EQ(mechanism.reactions.first_order_loss[1].gas_phase, "gas"); - EXPECT_EQ(mechanism.reactions.first_order_loss[1].scaling_factor, 1); - EXPECT_EQ(mechanism.reactions.first_order_loss[1].reactants.name, "C"); - EXPECT_EQ(mechanism.reactions.first_order_loss[1].reactants.coefficient, 1); - } -} - -TEST(ParseFirstOrderLoss, DetectsUnknownSpecies) -{ - development::Parser parser; - - std::string path = "development_unit_configs/reactions/first_order_loss/unknown_species"; - std::vector extensions = { ".json", ".yaml" }; - - for (auto& extension : extensions) - { - YAML::Node object = parser.FileToYaml(path + extension); - - auto validation_errors = parser.Validate(object); - EXPECT_EQ(validation_errors.size(), 2); - - std::multiset expected = { ConfigParseStatus::ReactionRequiresUnknownSpecies, - ConfigParseStatus::RequestedSpeciesNotRegisteredInPhase }; - std::multiset actual; - for (const auto& [status, message] : validation_errors) - { - actual.insert(status); - std::cout << message << " " << configParseStatusToString(status) << std::endl; - } - EXPECT_EQ(actual, expected); - } -} - -TEST(ParseFirstOrderLoss, DetectsBadReactionComponent) -{ - development::Parser parser; - - std::string path = "development_unit_configs/reactions/first_order_loss/bad_reaction_component"; - std::vector extensions = { ".json", ".yaml" }; - - for (auto& extension : extensions) - { - YAML::Node object = parser.FileToYaml(path + extension); - - auto validation_errors = parser.Validate(object); - EXPECT_EQ(validation_errors.size(), 2); - - std::multiset expected = { ConfigParseStatus::RequiredKeyNotFound, ConfigParseStatus::InvalidKey }; - std::multiset actual; - for (const auto& [status, message] : validation_errors) - { - actual.insert(status); - std::cout << message << " " << configParseStatusToString(status) << std::endl; - } - EXPECT_EQ(actual, expected); - } -} - -TEST(ParseFirstOrderLoss, DetectsUnknownPhase) -{ - development::Parser parser; - - std::string path = "development_unit_configs/reactions/first_order_loss/missing_phase"; - std::vector extensions = { ".json", ".yaml" }; - - for (auto& extension : extensions) - { - YAML::Node object = parser.FileToYaml(path + extension); - - auto validation_errors = parser.Validate(object); - EXPECT_EQ(validation_errors.size(), 1); - - std::multiset expected = { ConfigParseStatus::UnknownPhase }; - std::multiset actual; - for (const auto& [status, message] : validation_errors) - { - actual.insert(status); - std::cout << message << " " << configParseStatusToString(status) << std::endl; - } - EXPECT_EQ(actual, expected); - } -} - -TEST(ParseFirstOrderLoss, DetectsMoreThanOneSpecies) -{ - development::Parser parser; - - std::string path = "development_unit_configs/reactions/first_order_loss/too_many_reactants"; - std::vector extensions = { ".json", ".yaml" }; - - for (auto& extension : extensions) - { - YAML::Node object = parser.FileToYaml(path + extension); - - auto validation_errors = parser.Validate(object); - EXPECT_EQ(validation_errors.size(), 1); - - std::multiset expected = { ConfigParseStatus::TooManyReactionComponents }; - std::multiset actual; - for (const auto& [status, message] : validation_errors) - { - actual.insert(status); - std::cout << message << " " << configParseStatusToString(status) << std::endl; - } - EXPECT_EQ(actual, expected); - } -} - -TEST(ValidateFirstOrderLoss, InvalidNumberReactantUnknownSpeciesUnknownPhaseFailsValidation) -{ - using namespace development; - - std::vector existing_species = { types::Species{ .name = "foo" }, types::Species{ .name = "bar" } }; - std::vector existing_phases = { types::Phase{ .name = "gas" } }; - - YAML::Node reaction_node; - reaction_node["type"] = "FIRST_ORDER_LOSS"; - - // Invalid number of reactions triggers validation error - reaction_node["reactants"] = YAML::Load("[{ name: quiz }, { name: bar }]"); - - // Unknown gas phase name triggers validation error - reaction_node["gas phase"] = "what is first order loss phase"; - - FirstOrderLossParser parser; - Errors errors = parser.Validate(reaction_node, existing_species, existing_phases); - EXPECT_EQ(errors.size(), 3); - - std::multiset expected = { ConfigParseStatus::TooManyReactionComponents, - ConfigParseStatus::ReactionRequiresUnknownSpecies, - ConfigParseStatus::UnknownPhase }; - std::multiset actual; - for (const auto& [status, message] : errors) - { - actual.insert(status); - std::cout << message << " " << configParseStatusToString(status) << std::endl; - } - EXPECT_EQ(actual, expected); -} \ No newline at end of file diff --git a/test/unit/development/reactions/test_parse_henrys_law.cpp b/test/unit/development/reactions/test_parse_henrys_law.cpp deleted file mode 100644 index 63facace..00000000 --- a/test/unit/development/reactions/test_parse_henrys_law.cpp +++ /dev/null @@ -1,360 +0,0 @@ -#include -#include - -#include - -#include - -using namespace mechanism_configuration; - -TEST(ParseHenrysLaw, ParseValidConfig) -{ - development::Parser parser; - - std::string path = "development_unit_configs/reactions/henrys_law/valid"; - std::vector extensions = { ".json", ".yaml" }; - - for (auto& extension : extensions) - { - YAML::Node object = parser.FileToYaml(path + extension); - - auto validation_errors = parser.Validate(object); - EXPECT_EQ(validation_errors.size(), 0) << "Validation errors were: " << validation_errors.size(); - - auto mechanism = parser.Parse(object); - EXPECT_EQ(mechanism.reactions.henrys_law.size(), 2); - EXPECT_EQ(mechanism.reactions.henrys_law[0].name, "my henry's law"); - EXPECT_EQ(mechanism.reactions.henrys_law[0].gas.name, "gas"); - EXPECT_EQ(mechanism.reactions.henrys_law[0].gas.species.size(), 1); - EXPECT_EQ(mechanism.reactions.henrys_law[0].gas.species[0].name, "A"); - EXPECT_EQ(mechanism.reactions.henrys_law[0].particle.phase, "aqueous"); - EXPECT_EQ(mechanism.reactions.henrys_law[0].particle.solutes.size(), 1); - EXPECT_EQ(mechanism.reactions.henrys_law[0].particle.solutes[0].name, "B"); - EXPECT_EQ(mechanism.reactions.henrys_law[0].particle.solutes[0].coefficient, 1); - EXPECT_EQ(mechanism.reactions.henrys_law[0].particle.solvent.name, "H2O"); - EXPECT_EQ(mechanism.reactions.henrys_law[0].particle.solvent.coefficient, 1); - EXPECT_EQ(mechanism.reactions.henrys_law[0].unknown_properties.size(), 1); - EXPECT_EQ(mechanism.reactions.henrys_law[0].unknown_properties["__comment"], "B condensed phase production (kg/m2/s)"); - - EXPECT_EQ(mechanism.reactions.henrys_law[1].name, ""); - EXPECT_EQ(mechanism.reactions.henrys_law[1].gas.name, "gas"); - EXPECT_EQ(mechanism.reactions.henrys_law[1].gas.species.size(), 1); - EXPECT_EQ(mechanism.reactions.henrys_law[1].gas.species[0].name, "A"); - EXPECT_EQ(mechanism.reactions.henrys_law[1].particle.phase, "aqueous"); - EXPECT_EQ(mechanism.reactions.henrys_law[1].particle.solutes.size(), 2); - EXPECT_EQ(mechanism.reactions.henrys_law[1].particle.solutes[0].name, "B"); - EXPECT_EQ(mechanism.reactions.henrys_law[1].particle.solutes[0].coefficient, 1); - EXPECT_EQ(mechanism.reactions.henrys_law[1].particle.solutes[1].name, "C"); - EXPECT_EQ(mechanism.reactions.henrys_law[1].particle.solutes[1].coefficient, 1); - EXPECT_EQ(mechanism.reactions.henrys_law[1].particle.solvent.name, "H2O"); - EXPECT_EQ(mechanism.reactions.henrys_law[1].particle.solvent.coefficient, 1); - EXPECT_EQ(mechanism.reactions.henrys_law[1].unknown_properties.size(), 0); - } -} - -TEST(ParseHenrysLaw, DetectsUnknownSpecies) -{ - development::Parser parser; - - std::string path = "development_unit_configs/reactions/henrys_law/unknown_species"; - std::vector extensions = { ".json", ".yaml" }; - - for (auto& extension : extensions) - { - YAML::Node object = parser.FileToYaml(path + extension); - - auto validation_errors = parser.Validate(object); - EXPECT_EQ(validation_errors.size(), 1); - - std::multiset expected = { ConfigParseStatus::PhaseRequiresUnknownSpecies }; - std::multiset actual; - for (const auto& [status, message] : validation_errors) - { - actual.insert(status); - std::cout << message << " " << configParseStatusToString(status) << std::endl; - } - EXPECT_EQ(actual, expected); - } -} - -TEST(ParseHenrysLaw, DetectsGasSpeciesInReactionNotFoundInGasPhase) -{ - development::Parser parser; - - std::string path = "development_unit_configs/reactions/henrys_law/species_not_found_in_gas_phase"; - std::vector extensions = { ".json", ".yaml" }; - - for (auto& extension : extensions) - { - YAML::Node object = parser.FileToYaml(path + extension); - - auto validation_errors = parser.Validate(object); - EXPECT_EQ(validation_errors.size(), 1); - - std::multiset expected = { ConfigParseStatus::RequestedSpeciesNotRegisteredInPhase }; - std::multiset actual; - for (const auto& [status, message] : validation_errors) - { - actual.insert(status); - std::cout << message << " " << configParseStatusToString(status) << std::endl; - } - EXPECT_EQ(actual, expected); - } -} - -TEST(ParseHenrysLaw, DetectsWhenRequestedSpeciesAreNotInAqueousPhase) -{ - development::Parser parser; - - std::string path = "development_unit_configs/reactions/henrys_law/species_not_in_aqueous_phase"; - std::vector extensions = { ".json", ".yaml" }; - - for (auto& extension : extensions) - { - YAML::Node object = parser.FileToYaml(path + extension); - - auto validation_errors = parser.Validate(object); - EXPECT_EQ(validation_errors.size(), 1); - - std::multiset expected = { ConfigParseStatus::RequestedSpeciesNotRegisteredInPhase }; - std::multiset actual; - for (const auto& [status, message] : validation_errors) - { - actual.insert(status); - std::cout << message << " " << configParseStatusToString(status) << std::endl; - } - EXPECT_EQ(actual, expected); - } -} - -TEST(ParseHenrysLaw, DetectsWhenRequestedSolventIsNotRegisteredInCorrectPhase) -{ - development::Parser parser; - - std::string path = "development_unit_configs/reactions/henrys_law/solvent_species_not_registered_in_phase"; - std::vector extensions = { ".json", ".yaml" }; - - for (auto& extension : extensions) - { - YAML::Node object = parser.FileToYaml(path + extension); - - auto validation_errors = parser.Validate(object); - EXPECT_EQ(validation_errors.size(), 1); - - std::multiset expected = { ConfigParseStatus::RequestedSpeciesNotRegisteredInPhase }; - std::multiset actual; - for (const auto& [status, message] : validation_errors) - { - actual.insert(status); - std::cout << message << " " << configParseStatusToString(status) << std::endl; - } - EXPECT_EQ(actual, expected); - } -} - -TEST(ValidateHenrysLaw, ValidationWithUnknownSpeciesUnknownPhaseFailsValidation) -{ - using namespace development; - - std::vector existing_species = { types::Species{ .name = "A" }, types::Species{ .name = "H2O" } }; - std::vector existing_phases = { - types::Phase{ .name = "gas", .species = { types::PhaseSpecies{ .name = "A" } } }, - types::Phase{ .name = "aqueous", .species = { types::PhaseSpecies{ .name = "H2O" } } } - }; - - YAML::Node reaction_node; - reaction_node["type"] = "HL_PHASE_TRANSFER"; - - reaction_node["gas"]["name"] = "gas"; - reaction_node["gas"]["species"] = YAML::Load("[{ name: A }]"); - - // Particle with unknown phase and unknown species - reaction_node["particle"]["phase"] = "unknown_phase"; - reaction_node["particle"]["solutes"] = YAML::Load("[{ name: H2O2, coefficient: 1.0 }]"); - reaction_node["particle"]["solvent"] = YAML::Load("[{ name: water, coefficient: 1.0 }]"); - - HenrysLawParser parser; - Errors errors = parser.Validate(reaction_node, existing_species, existing_phases); - EXPECT_EQ(errors.size(), 3); - - std::multiset expected = { ConfigParseStatus::ReactionRequiresUnknownSpecies, - ConfigParseStatus::ReactionRequiresUnknownSpecies, - ConfigParseStatus::UnknownPhase }; - std::multiset actual; - for (const auto& [status, message] : errors) - { - actual.insert(status); - std::cout << message << " " << configParseStatusToString(status) << std::endl; - } - EXPECT_EQ(actual, expected); -} - -TEST(ValidateHenrysLaw, ValidationWithSpeciesNotInPhasesFailsValidation) -{ - using namespace development; - - std::vector existing_species = { types::Species{ .name = "A" }, - types::Species{ .name = "B" }, - types::Species{ .name = "C" }, - types::Species{ .name = "H2O" } }; - std::vector existing_phases = { - types::Phase{ .name = "gas", .species = { types::PhaseSpecies{ .name = "A" } } }, - types::Phase{ .name = "aqueous", .species = { types::PhaseSpecies{ .name = "H2O" } } } - }; - - YAML::Node reaction_node; - reaction_node["type"] = "HL_PHASE_TRANSFER"; - - // Gas phase - species B exists but not in gas phase - reaction_node["gas"]["name"] = "gas"; - reaction_node["gas"]["species"] = YAML::Load("[{ name: B }]"); - - // Particle phase - species C exists but not in aqueous phase - reaction_node["particle"]["phase"] = "aqueous"; - reaction_node["particle"]["solutes"] = YAML::Load("[{ name: C, coefficient: 1.0 }]"); - reaction_node["particle"]["solvent"] = YAML::Load("[{ name: H2O, coefficient: 1.0 }]"); - - HenrysLawParser parser; - Errors errors = parser.Validate(reaction_node, existing_species, existing_phases); - EXPECT_EQ(errors.size(), 2); - - std::multiset expected = { ConfigParseStatus::RequestedSpeciesNotRegisteredInPhase, - ConfigParseStatus::RequestedSpeciesNotRegisteredInPhase }; - std::multiset actual; - for (const auto& [status, message] : errors) - { - actual.insert(status); - std::cout << message << " " << configParseStatusToString(status) << std::endl; - } - EXPECT_EQ(actual, expected); -} - -TEST(ValidateHenrysLaw, ValidationWithMissingRequiredKeysFailsValidation) -{ - using namespace development; - - std::vector existing_species = { types::Species{ .name = "A" }, types::Species{ .name = "H2O" } }; - std::vector existing_phases = { types::Phase{ .name = "gas" }, types::Phase{ .name = "aqueous" } }; - - YAML::Node reaction_node; - reaction_node["type"] = "HL_PHASE_TRANSFER"; - // Missing required "gas" and "particle" keys - - HenrysLawParser parser; - Errors errors = parser.Validate(reaction_node, existing_species, existing_phases); - EXPECT_EQ(errors.size(), 2); - - std::multiset expected = { ConfigParseStatus::RequiredKeyNotFound, - ConfigParseStatus::RequiredKeyNotFound }; - std::multiset actual; - for (const auto& [status, message] : errors) - { - actual.insert(status); - std::cout << message << " " << configParseStatusToString(status) << std::endl; - } - EXPECT_EQ(actual, expected); -} - -TEST(ValidateHenrysLaw, ValidationWithValidConfigurationPassesValidation) -{ - using namespace development; - - std::vector existing_species = { types::Species{ .name = "A" }, - types::Species{ .name = "B" }, - types::Species{ .name = "H2O" } }; - std::vector existing_phases = { - types::Phase{ .name = "gas", .species = { types::PhaseSpecies{ .name = "A" } } }, - types::Phase{ .name = "aqueous", - .species = { types::PhaseSpecies{ .name = "B" }, types::PhaseSpecies{ .name = "H2O" } } } - }; - - YAML::Node reaction_node; - reaction_node["type"] = "HL_PHASE_TRANSFER"; - - reaction_node["gas"]["name"] = "gas"; - reaction_node["gas"]["species"] = YAML::Load("[{ name: A, \"diffusion coefficient [m2 s-1]\": 0.7 }]"); - - reaction_node["particle"]["phase"] = "aqueous"; - reaction_node["particle"]["solutes"] = YAML::Load("[{ name: B, coefficient: 1.0 }]"); - reaction_node["particle"]["solvent"] = YAML::Load("[{ name: H2O, coefficient: 1.0 }]"); - - // Optional name field - reaction_node["name"] = "test henry's law reaction"; - - HenrysLawParser parser; - Errors errors = parser.Validate(reaction_node, existing_species, existing_phases); - EXPECT_EQ(errors.size(), 0); -} - -TEST(ValidateHenrysLaw, ValidationWithMultipleSolutes) -{ - using namespace development; - - std::vector existing_species = { types::Species{ .name = "A" }, - types::Species{ .name = "B" }, - types::Species{ .name = "C" }, - types::Species{ .name = "H2O" } }; - std::vector existing_phases = { types::Phase{ .name = "gas", - .species = { types::PhaseSpecies{ .name = "A" } } }, - types::Phase{ .name = "aqueous", - .species = { types::PhaseSpecies{ .name = "B" }, - types::PhaseSpecies{ .name = "C" }, - types::PhaseSpecies{ .name = "H2O" } } } }; - - YAML::Node reaction_node; - reaction_node["type"] = "HL_PHASE_TRANSFER"; - - reaction_node["gas"]["name"] = "gas"; - reaction_node["gas"]["species"] = YAML::Load("[{ name: A }]"); - - // Valid particle phase configuration with multiple solutes - reaction_node["particle"]["phase"] = "aqueous"; - reaction_node["particle"]["solutes"] = YAML::Load("[{ name: B, coefficient: 1.0 }, { name: C, coefficient: 2.0 }]"); - reaction_node["particle"]["solvent"] = YAML::Load("[{ name: H2O, coefficient: 1.0 }]"); - - HenrysLawParser parser; - Errors errors = parser.Validate(reaction_node, existing_species, existing_phases); - EXPECT_EQ(errors.size(), 0); -} - -TEST(ValidateHenrysLaw, InvalidNumberSolventFailsValidation) -{ - using namespace development; - - std::vector existing_species = { types::Species{ .name = "A" }, - types::Species{ .name = "B" }, - types::Species{ .name = "C" }, - types::Species{ .name = "H2O" }, - types::Species{ .name = "water" } }; - std::vector existing_phases = { types::Phase{ .name = "gas", - .species = { types::PhaseSpecies{ .name = "A" } } }, - types::Phase{ .name = "aqueous", - .species = { types::PhaseSpecies{ .name = "B" }, - types::PhaseSpecies{ .name = "C" }, - types::PhaseSpecies{ .name = "H2O" }, - types::PhaseSpecies{ .name = "water" } } } }; - - YAML::Node reaction_node; - reaction_node["type"] = "HL_PHASE_TRANSFER"; - - reaction_node["gas"]["name"] = "gas"; - reaction_node["gas"]["species"] = YAML::Load("[{ name: A }]"); - reaction_node["particle"]["phase"] = "aqueous"; - reaction_node["particle"]["solutes"] = YAML::Load("[{ name: B, coefficient: 1.0 }, { name: C, coefficient: 2.0 }]"); - - // The invalid number of the solvent triggers validation error - reaction_node["particle"]["solvent"] = YAML::Load("[{ name: H2O, coefficient: 1.0 }, { name: water, coefficient: 1.0 }]"); - - HenrysLawParser parser; - Errors errors = parser.Validate(reaction_node, existing_species, existing_phases); - EXPECT_EQ(errors.size(), 1); - - std::multiset expected = { ConfigParseStatus::TooManyReactionComponents }; - std::multiset actual; - for (const auto& [status, message] : errors) - { - actual.insert(status); - std::cout << message << " " << configParseStatusToString(status) << std::endl; - } - EXPECT_EQ(actual, expected); -} \ No newline at end of file diff --git a/test/unit/development/reactions/test_parse_photolysis.cpp b/test/unit/development/reactions/test_parse_photolysis.cpp deleted file mode 100644 index afd287c3..00000000 --- a/test/unit/development/reactions/test_parse_photolysis.cpp +++ /dev/null @@ -1,180 +0,0 @@ -#include -#include - -#include - -#include - -using namespace mechanism_configuration; - -TEST(ParsePhotolysis, ParseValidConfig) -{ - development::Parser parser; - - std::string path = "development_unit_configs/reactions/photolysis/valid"; - std::vector extensions = { ".json", ".yaml" }; - - for (auto& extension : extensions) - { - YAML::Node object = parser.FileToYaml(path + extension); - - auto validation_errors = parser.Validate(object); - EXPECT_EQ(validation_errors.size(), 0) << "Validation errors were: " << validation_errors.size(); - - auto mechanism = parser.Parse(object); - EXPECT_EQ(mechanism.reactions.photolysis.size(), 2); - - EXPECT_EQ(mechanism.reactions.photolysis[0].gas_phase, "gas"); - EXPECT_EQ(mechanism.reactions.photolysis[0].name, "my photolysis"); - EXPECT_EQ(mechanism.reactions.photolysis[0].scaling_factor, 12.3); - EXPECT_EQ(mechanism.reactions.photolysis[0].reactants.name, "B"); - EXPECT_EQ(mechanism.reactions.photolysis[0].reactants.coefficient, 1); - EXPECT_EQ(mechanism.reactions.photolysis[0].products.size(), 1); - EXPECT_EQ(mechanism.reactions.photolysis[0].products[0].name, "C"); - EXPECT_EQ(mechanism.reactions.photolysis[0].products[0].coefficient, 1); - EXPECT_EQ(mechanism.reactions.photolysis[0].unknown_properties.size(), 1); - EXPECT_EQ(mechanism.reactions.photolysis[0].unknown_properties["__comment"], "hi"); - - EXPECT_EQ(mechanism.reactions.photolysis[1].gas_phase, "gas"); - EXPECT_EQ(mechanism.reactions.photolysis[1].scaling_factor, 1); - EXPECT_EQ(mechanism.reactions.photolysis[1].reactants.name, "B"); - EXPECT_EQ(mechanism.reactions.photolysis[1].reactants.coefficient, 1.2); - EXPECT_EQ(mechanism.reactions.photolysis[1].products.size(), 1); - EXPECT_EQ(mechanism.reactions.photolysis[1].products[0].name, "C"); - EXPECT_EQ(mechanism.reactions.photolysis[1].products[0].coefficient, 0.2); - } -} - -TEST(ParsePhotolysis, DetectsUnknownSpecies) -{ - development::Parser parser; - - std::string path = "development_unit_configs/reactions/photolysis/unknown_species"; - std::vector extensions = { ".json", ".yaml" }; - - for (auto& extension : extensions) - { - YAML::Node object = parser.FileToYaml(path + extension); - - auto validation_errors = parser.Validate(object); - EXPECT_EQ(validation_errors.size(), 2); - - std::multiset expected = { ConfigParseStatus::ReactionRequiresUnknownSpecies, - ConfigParseStatus::RequestedSpeciesNotRegisteredInPhase }; - std::multiset actual; - for (const auto& [status, message] : validation_errors) - { - actual.insert(status); - std::cout << message << " " << configParseStatusToString(status) << std::endl; - } - EXPECT_EQ(actual, expected); - } -} - -TEST(ParsePhotolysis, DetectsBadReactionComponent) -{ - development::Parser parser; - - std::string path = "development_unit_configs/reactions/photolysis/bad_reaction_component"; - std::vector extensions = { ".json", ".yaml" }; - - for (auto& extension : extensions) - { - YAML::Node object = parser.FileToYaml(path + extension); - - auto validation_errors = parser.Validate(object); - EXPECT_EQ(validation_errors.size(), 1); - - std::multiset expected = { ConfigParseStatus::InvalidKey }; - std::multiset actual; - for (const auto& [status, message] : validation_errors) - { - actual.insert(status); - std::cout << message << " " << configParseStatusToString(status) << std::endl; - } - EXPECT_EQ(actual, expected); - } -} - -TEST(ParsePhotolysis, DetectsUnknownPhase) -{ - development::Parser parser; - - std::string path = "development_unit_configs/reactions/photolysis/missing_phase"; - std::vector extensions = { ".json", ".yaml" }; - - for (auto& extension : extensions) - { - YAML::Node object = parser.FileToYaml(path + extension); - - auto validation_errors = parser.Validate(object); - EXPECT_EQ(validation_errors.size(), 1); - - std::multiset expected = { ConfigParseStatus::UnknownPhase }; - std::multiset actual; - for (const auto& [status, message] : validation_errors) - { - actual.insert(status); - std::cout << message << " " << configParseStatusToString(status) << std::endl; - } - EXPECT_EQ(actual, expected); - } -} - -TEST(ParsePhotolysis, DoesNotAcceptMoreThanOneReactant) -{ - development::Parser parser; - - std::string path = "development_unit_configs/reactions/photolysis/more_than_one_reactant"; - std::vector extensions = { ".json", ".yaml" }; - - for (auto& extension : extensions) - { - YAML::Node object = parser.FileToYaml(path + extension); - - auto validation_errors = parser.Validate(object); - EXPECT_EQ(validation_errors.size(), 1); - - std::multiset expected = { ConfigParseStatus::TooManyReactionComponents }; - std::multiset actual; - for (const auto& [status, message] : validation_errors) - { - actual.insert(status); - std::cout << message << " " << configParseStatusToString(status) << std::endl; - } - EXPECT_EQ(actual, expected); - } -} - -TEST(ValidatePhotolysis, InvalidNumberReactantUnknownSpeciesUnknownPhaseFailsValidation) -{ - using namespace development; - - std::vector existing_species = { types::Species{ .name = "foo" }, types::Species{ .name = "bar" } }; - std::vector existing_phases = { types::Phase{ .name = "gas" } }; - - YAML::Node reaction_node; - reaction_node["type"] = "PHOTOLYSIS"; - reaction_node["products"] = YAML::Load("[{ name: foo }]"); - - // Invalid number of reactions triggers validation error - reaction_node["reactants"] = YAML::Load("[{ name: quiz }, { name: bar }]"); - - // Unknown gas phase name triggers validation error - reaction_node["gas phase"] = "aqueous"; - - PhotolysisParser parser; - Errors errors = parser.Validate(reaction_node, existing_species, existing_phases); - EXPECT_EQ(errors.size(), 3); - - std::multiset expected = { ConfigParseStatus::TooManyReactionComponents, - ConfigParseStatus::ReactionRequiresUnknownSpecies, - ConfigParseStatus::UnknownPhase }; - std::multiset actual; - for (const auto& [status, message] : errors) - { - actual.insert(status); - std::cout << message << " " << configParseStatusToString(status) << std::endl; - } - EXPECT_EQ(actual, expected); -} \ No newline at end of file diff --git a/test/unit/development/reactions/test_parse_simpol_phase_transfer.cpp b/test/unit/development/reactions/test_parse_simpol_phase_transfer.cpp deleted file mode 100644 index 6eb65d83..00000000 --- a/test/unit/development/reactions/test_parse_simpol_phase_transfer.cpp +++ /dev/null @@ -1,356 +0,0 @@ -#include -#include - -#include - -#include - -using namespace mechanism_configuration; - -TEST(ParseSimpolPhaseTransfer, ParseValidConfig) -{ - development::Parser parser; - - std::string path = "development_unit_configs/reactions/simpol_phase_transfer/valid"; - std::vector extensions = { ".json", ".yaml" }; - - for (auto& extension : extensions) - { - YAML::Node object = parser.FileToYaml(path + extension); - - auto validation_errors = parser.Validate(object); - EXPECT_EQ(validation_errors.size(), 0) << "Validation errors were: " << validation_errors.size(); - - auto mechanism = parser.Parse(object); - EXPECT_EQ(mechanism.reactions.simpol_phase_transfer.size(), 2); - - EXPECT_EQ(mechanism.reactions.simpol_phase_transfer[0].name, "my simpol"); - EXPECT_EQ(mechanism.reactions.simpol_phase_transfer[0].gas_phase, "gas"); - EXPECT_EQ(mechanism.reactions.simpol_phase_transfer[0].gas_phase_species[0].name, "A"); - EXPECT_EQ(mechanism.reactions.simpol_phase_transfer[0].gas_phase_species[0].coefficient, 1); - EXPECT_EQ(mechanism.reactions.simpol_phase_transfer[0].condensed_phase, "aqueous"); - EXPECT_EQ(mechanism.reactions.simpol_phase_transfer[0].condensed_phase_species[0].name, "B"); - EXPECT_EQ(mechanism.reactions.simpol_phase_transfer[0].condensed_phase_species[0].coefficient, 1); - EXPECT_EQ(mechanism.reactions.simpol_phase_transfer[0].B[0], -1.97e3); - EXPECT_EQ(mechanism.reactions.simpol_phase_transfer[0].B[1], 2.91e0); - EXPECT_EQ(mechanism.reactions.simpol_phase_transfer[0].B[2], 1.96e-3); - EXPECT_EQ(mechanism.reactions.simpol_phase_transfer[0].B[3], -4.96e-1); - EXPECT_EQ(mechanism.reactions.simpol_phase_transfer[0].unknown_properties.size(), 1); - EXPECT_EQ(mechanism.reactions.simpol_phase_transfer[0].unknown_properties["__comment"], "cereal is also soup"); - - EXPECT_EQ(mechanism.reactions.simpol_phase_transfer[1].name, ""); - EXPECT_EQ(mechanism.reactions.simpol_phase_transfer[1].gas_phase, "gas"); - EXPECT_EQ(mechanism.reactions.simpol_phase_transfer[1].gas_phase_species[0].name, "A"); - EXPECT_EQ(mechanism.reactions.simpol_phase_transfer[1].gas_phase_species[0].coefficient, 1); - EXPECT_EQ(mechanism.reactions.simpol_phase_transfer[1].condensed_phase, "aqueous"); - EXPECT_EQ(mechanism.reactions.simpol_phase_transfer[1].condensed_phase_species[0].name, "B"); - EXPECT_EQ(mechanism.reactions.simpol_phase_transfer[1].condensed_phase_species[0].coefficient, 1); - EXPECT_EQ(mechanism.reactions.simpol_phase_transfer[1].B[0], -1.97e3); - EXPECT_EQ(mechanism.reactions.simpol_phase_transfer[1].B[1], 2.91e0); - EXPECT_EQ(mechanism.reactions.simpol_phase_transfer[1].B[2], 1.96e-3); - EXPECT_EQ(mechanism.reactions.simpol_phase_transfer[1].B[3], -4.96e-1); - } -} - -TEST(ParseSimpolPhaseTransfer, DetectsUnknownSpecies) -{ - development::Parser parser; - - std::string path = "development_unit_configs/reactions/simpol_phase_transfer/unknown_species"; - std::vector extensions = { ".json", ".yaml" }; - - for (auto& extension : extensions) - { - YAML::Node object = parser.FileToYaml(path + extension); - - auto validation_errors = parser.Validate(object); - EXPECT_EQ(validation_errors.size(), 2); - - std::multiset expected = { ConfigParseStatus::ReactionRequiresUnknownSpecies, - ConfigParseStatus::RequestedSpeciesNotRegisteredInPhase }; - std::multiset actual; - for (const auto& [status, message] : validation_errors) - { - actual.insert(status); - std::cout << message << " " << configParseStatusToString(status) << std::endl; - } - EXPECT_EQ(actual, expected); - } -} - -TEST(ParseSimpolPhaseTransfer, DetectsUnknownAqueousPhase) -{ - development::Parser parser; - - std::string path = "development_unit_configs/reactions/simpol_phase_transfer/missing_aqueous_phase"; - std::vector extensions = { ".json", ".yaml" }; - - for (auto& extension : extensions) - { - YAML::Node object = parser.FileToYaml(path + extension); - - auto validation_errors = parser.Validate(object); - EXPECT_EQ(validation_errors.size(), 1); - - std::multiset expected = { ConfigParseStatus::UnknownPhase }; - std::multiset actual; - for (const auto& [status, message] : validation_errors) - { - actual.insert(status); - std::cout << message << " " << configParseStatusToString(status) << std::endl; - } - EXPECT_EQ(actual, expected); - } -} - -TEST(ParseSimpolPhaseTransfer, DetectsUnknownGasPhase) -{ - development::Parser parser; - - std::string path = "development_unit_configs/reactions/simpol_phase_transfer/missing_gas_phase"; - std::vector extensions = { ".json", ".yaml" }; - - for (auto& extension : extensions) - { - YAML::Node object = parser.FileToYaml(path + extension); - - auto validation_errors = parser.Validate(object); - EXPECT_EQ(validation_errors.size(), 1); - - std::multiset expected = { ConfigParseStatus::UnknownPhase }; - std::multiset actual; - for (const auto& [status, message] : validation_errors) - { - actual.insert(status); - std::cout << message << " " << configParseStatusToString(status) << std::endl; - } - EXPECT_EQ(actual, expected); - } -} - -TEST(ParseSimpolPhaseTransfer, DetectsUnknownGasPhaseSpeciesNotInGasPhase) -{ - development::Parser parser; - - std::string path = "development_unit_configs/reactions/simpol_phase_transfer/missing_gas_phase_species_in_gas_phase"; - std::vector extensions = { ".json", ".yaml" }; - - for (auto& extension : extensions) - { - YAML::Node object = parser.FileToYaml(path + extension); - - auto validation_errors = parser.Validate(object); - EXPECT_EQ(validation_errors.size(), 1); - - std::multiset expected = { ConfigParseStatus::RequestedSpeciesNotRegisteredInPhase }; - std::multiset actual; - for (const auto& [status, message] : validation_errors) - { - actual.insert(status); - std::cout << message << " " << configParseStatusToString(status) << std::endl; - } - EXPECT_EQ(actual, expected); - } -} - -TEST(ParseSimpolPhaseTransfer, DetectsUnknownAqueousPhaseSpeciesNotInAqueousPhase) -{ - development::Parser parser; - - std::string path = - "development_unit_configs/reactions/simpol_phase_transfer/missing_aqueous_phase_species_in_aqueous_phase"; - std::vector extensions = { ".json", ".yaml" }; - - for (auto& extension : extensions) - { - YAML::Node object = parser.FileToYaml(path + extension); - - auto validation_errors = parser.Validate(object); - EXPECT_EQ(validation_errors.size(), 1); - - std::multiset expected = { ConfigParseStatus::RequestedSpeciesNotRegisteredInPhase }; - std::multiset actual; - for (const auto& [status, message] : validation_errors) - { - actual.insert(status); - std::cout << message << " " << configParseStatusToString(status) << std::endl; - } - EXPECT_EQ(actual, expected); - } -} - -TEST(ValidateSimpolPhaseTransfer, InvalidBParameterNotSequenceFailsValidation) -{ - using namespace development; - - std::vector existing_species = { types::Species{ .name = "A" }, types::Species{ .name = "B" } }; - std::vector existing_phases = { - types::Phase{ .name = "gas", .species = { types::PhaseSpecies{ .name = "A" } } }, - types::Phase{ .name = "aqueous", .species = { types::PhaseSpecies{ .name = "B" } } } - }; - - YAML::Node reaction_node; - reaction_node["type"] = "SIMPOL_PHASE_TRANSFER"; - reaction_node["gas phase"] = "gas"; - reaction_node["gas-phase species"] = YAML::Load("[{ name: A, coefficient: 1 }]"); - reaction_node["condensed phase"] = "aqueous"; - reaction_node["condensed-phase species"] = YAML::Load("[{ name: B, coefficient: 1 }]"); - - // Invalid B parameter - not a sequence - reaction_node["B"] = "not a sequence"; - - SimpolPhaseTransferParser parser; - Errors errors = parser.Validate(reaction_node, existing_species, existing_phases); - EXPECT_EQ(errors.size(), 1); - - std::multiset expected = { ConfigParseStatus::InvalidParameterNumber }; - std::multiset actual; - for (const auto& [status, message] : errors) - { - actual.insert(status); - std::cout << message << " " << configParseStatusToString(status) << std::endl; - } - EXPECT_EQ(actual, expected); -} - -TEST(ValidateSimpolPhaseTransfer, InvalidBParameterWrongCountFailsValidation) -{ - using namespace development; - - std::vector existing_species = { types::Species{ .name = "A" }, types::Species{ .name = "B" } }; - std::vector existing_phases = { - types::Phase{ .name = "gas", .species = { types::PhaseSpecies{ .name = "A" } } }, - types::Phase{ .name = "aqueous", .species = { types::PhaseSpecies{ .name = "B" } } } - }; - - YAML::Node reaction_node; - reaction_node["type"] = "SIMPOL_PHASE_TRANSFER"; - reaction_node["gas phase"] = "gas"; - reaction_node["gas-phase species"] = YAML::Load("[{ name: A, coefficient: 1 }]"); - reaction_node["condensed phase"] = "aqueous"; - reaction_node["condensed-phase species"] = YAML::Load("[{ name: B, coefficient: 1 }]"); - - // Invalid B parameter - wrong number of parameters (should be 4) - reaction_node["B"] = YAML::Load("[-1.97E+03, 2.91E+00]"); - - SimpolPhaseTransferParser parser; - Errors errors = parser.Validate(reaction_node, existing_species, existing_phases); - EXPECT_EQ(errors.size(), 1); - - std::multiset expected = { ConfigParseStatus::InvalidParameterNumber }; - std::multiset actual; - for (const auto& [status, message] : errors) - { - actual.insert(status); - std::cout << message << " " << configParseStatusToString(status) << std::endl; - } - EXPECT_EQ(actual, expected); -} - -TEST(ValidateSimpolPhaseTransfer, TooManyGasSpeciesFailsValidation) -{ - using namespace development; - - std::vector existing_species = { types::Species{ .name = "A" }, - types::Species{ .name = "B" }, - types::Species{ .name = "C" } }; - std::vector existing_phases = { - types::Phase{ .name = "gas", .species = { types::PhaseSpecies{ .name = "A" }, types::PhaseSpecies{ .name = "C" } } }, - types::Phase{ .name = "aqueous", .species = { types::PhaseSpecies{ .name = "B" } } } - }; - - YAML::Node reaction_node; - reaction_node["type"] = "SIMPOL_PHASE_TRANSFER"; - reaction_node["gas phase"] = "gas"; - - // Too many gas phase species (should be exactly 1) - reaction_node["gas-phase species"] = YAML::Load("[{ name: A, coefficient: 1 }, { name: C, coefficient: 1 }]"); - - reaction_node["condensed phase"] = "aqueous"; - reaction_node["condensed-phase species"] = YAML::Load("[{ name: B, coefficient: 1 }]"); - reaction_node["B"] = YAML::Load("[-1.97E+03, 2.91E+00, 1.96E-03, -4.96E-01]"); - - SimpolPhaseTransferParser parser; - Errors errors = parser.Validate(reaction_node, existing_species, existing_phases); - EXPECT_EQ(errors.size(), 1); - - std::multiset expected = { ConfigParseStatus::TooManyReactionComponents }; - std::multiset actual; - for (const auto& [status, message] : errors) - { - actual.insert(status); - std::cout << message << " " << configParseStatusToString(status) << std::endl; - } - EXPECT_EQ(actual, expected); -} - -TEST(ValidateSimpolPhaseTransfer, TooManyCondensedSpeciesFailsValidation) -{ - using namespace development; - - std::vector existing_species = { types::Species{ .name = "A" }, - types::Species{ .name = "B" }, - types::Species{ .name = "C" } }; - std::vector existing_phases = { - types::Phase{ .name = "gas", .species = { types::PhaseSpecies{ .name = "A" } } }, - types::Phase{ .name = "aqueous", .species = { types::PhaseSpecies{ .name = "B" }, types::PhaseSpecies{ .name = "C" } } } - }; - - YAML::Node reaction_node; - reaction_node["type"] = "SIMPOL_PHASE_TRANSFER"; - reaction_node["gas phase"] = "gas"; - reaction_node["gas-phase species"] = YAML::Load("[{ name: A, coefficient: 1 }]"); - reaction_node["condensed phase"] = "aqueous"; - - // Too many condensed phase species (should be exactly 1) - reaction_node["condensed-phase species"] = YAML::Load("[{ name: B, coefficient: 1 }, { name: C, coefficient: 1 }]"); - - reaction_node["B"] = YAML::Load("[-1.97E+03, 2.91E+00, 1.96E-03, -4.96E-01]"); - - SimpolPhaseTransferParser parser; - Errors errors = parser.Validate(reaction_node, existing_species, existing_phases); - EXPECT_EQ(errors.size(), 1); - - std::multiset expected = { ConfigParseStatus::TooManyReactionComponents }; - std::multiset actual; - for (const auto& [status, message] : errors) - { - actual.insert(status); - std::cout << message << " " << configParseStatusToString(status) << std::endl; - } - EXPECT_EQ(actual, expected); -} - -TEST(ValidateSimpolPhaseTransfer, MultipleErrorsFailsValidation) -{ - using namespace development; - - std::vector existing_species = { types::Species{ .name = "A" }, types::Species{ .name = "B" } }; - std::vector existing_phases = { types::Phase{ .name = "gas" } }; // Missing aqueous phase - - YAML::Node reaction_node; - reaction_node["type"] = "SIMPOL_PHASE_TRANSFER"; - reaction_node["gas phase"] = "gas"; - - // Too many gas species + unknown species + unknown phase + invalid B parameter - reaction_node["gas-phase species"] = YAML::Load("[{ name: A, coefficient: 1 }, { name: UNKNOWN, coefficient: 1 }]"); - reaction_node["condensed phase"] = "aqueous"; // Unknown phase - reaction_node["condensed-phase species"] = YAML::Load("[{ name: B, coefficient: 1 }]"); - reaction_node["B"] = "invalid"; // Invalid B parameter - - SimpolPhaseTransferParser parser; - Errors errors = parser.Validate(reaction_node, existing_species, existing_phases); - EXPECT_GE(errors.size(), 3); - - std::multiset expected = { ConfigParseStatus::TooManyReactionComponents, - ConfigParseStatus::ReactionRequiresUnknownSpecies, - ConfigParseStatus::UnknownPhase, - ConfigParseStatus::InvalidParameterNumber }; - std::multiset actual; - for (const auto& [status, message] : errors) - { - actual.insert(status); - std::cout << message << " " << configParseStatusToString(status) << std::endl; - } - EXPECT_EQ(actual, expected); -} \ No newline at end of file diff --git a/test/unit/development/reactions/test_parse_surface.cpp b/test/unit/development/reactions/test_parse_surface.cpp deleted file mode 100644 index 628d358c..00000000 --- a/test/unit/development/reactions/test_parse_surface.cpp +++ /dev/null @@ -1,190 +0,0 @@ -#include -#include - -#include - -#include - -using namespace mechanism_configuration; - -TEST(ParseSurface, ParseValidConfig) -{ - development::Parser parser; - - std::string path = "development_unit_configs/reactions/surface/valid"; - std::vector extensions = { ".json", ".yaml" }; - - for (auto& extension : extensions) - { - YAML::Node object = parser.FileToYaml(path + extension); - - auto validation_errors = parser.Validate(object); - EXPECT_EQ(validation_errors.size(), 0) << "Validation errors were: " << validation_errors.size(); - - auto mechanism = parser.Parse(object); - EXPECT_EQ(mechanism.reactions.surface.size(), 2); - - EXPECT_EQ(mechanism.reactions.surface[0].gas_phase, "gas"); - EXPECT_EQ(mechanism.reactions.surface[0].name, "my surface"); - EXPECT_EQ(mechanism.reactions.surface[0].condensed_phase, "surface reacting phase"); - EXPECT_EQ(mechanism.reactions.surface[0].reaction_probability, 2.0e-2); - EXPECT_EQ(mechanism.reactions.surface[0].gas_phase_species.name, "A"); - EXPECT_EQ(mechanism.reactions.surface[0].gas_phase_species.coefficient, 1); - EXPECT_EQ(mechanism.reactions.surface[0].gas_phase_products.size(), 2); - EXPECT_EQ(mechanism.reactions.surface[0].gas_phase_products[0].name, "B"); - EXPECT_EQ(mechanism.reactions.surface[0].gas_phase_products[0].coefficient, 1); - EXPECT_EQ(mechanism.reactions.surface[0].gas_phase_products[1].name, "C"); - EXPECT_EQ(mechanism.reactions.surface[0].gas_phase_products[1].coefficient, 1); - EXPECT_EQ(mechanism.reactions.surface[0].unknown_properties.size(), 1); - EXPECT_EQ(mechanism.reactions.surface[0].unknown_properties["__comment"], "key lime pie is superior to all other pies"); - - EXPECT_EQ(mechanism.reactions.surface[1].gas_phase, "gas"); - EXPECT_EQ(mechanism.reactions.surface[1].condensed_phase, "surface reacting phase"); - EXPECT_EQ(mechanism.reactions.surface[1].reaction_probability, 1.0); - EXPECT_EQ(mechanism.reactions.surface[1].gas_phase_species.name, "A"); - EXPECT_EQ(mechanism.reactions.surface[1].gas_phase_species.coefficient, 1); - EXPECT_EQ(mechanism.reactions.surface[1].gas_phase_products.size(), 2); - EXPECT_EQ(mechanism.reactions.surface[1].gas_phase_products[0].name, "B"); - EXPECT_EQ(mechanism.reactions.surface[1].gas_phase_products[0].coefficient, 1); - EXPECT_EQ(mechanism.reactions.surface[1].gas_phase_products[0].unknown_properties.size(), 1); - EXPECT_EQ(mechanism.reactions.surface[1].gas_phase_products[0].unknown_properties["__optional thing"], "hello"); - EXPECT_EQ(mechanism.reactions.surface[1].gas_phase_products[1].name, "C"); - EXPECT_EQ(mechanism.reactions.surface[1].gas_phase_products[1].coefficient, 1); - } -} - -TEST(ParseSurface, DetectsUnknownSpecies) -{ - development::Parser parser; - - std::string path = "development_unit_configs/reactions/surface/unknown_species"; - std::vector extensions = { ".json", ".yaml" }; - - for (auto& extension : extensions) - { - YAML::Node object = parser.FileToYaml(path + extension); - - auto validation_errors = parser.Validate(object); - EXPECT_EQ(validation_errors.size(), 2); - - std::multiset expected = { ConfigParseStatus::ReactionRequiresUnknownSpecies, - ConfigParseStatus::RequestedSpeciesNotRegisteredInPhase }; - std::multiset actual; - for (const auto& [status, message] : validation_errors) - { - actual.insert(status); - std::cout << message << " " << configParseStatusToString(status) << std::endl; - } - EXPECT_EQ(actual, expected); - } -} - -TEST(ParseSurface, DetectsBadReactionComponent) -{ - development::Parser parser; - - std::string path = "development_unit_configs/reactions/surface/bad_reaction_component"; - std::vector extensions = { ".json", ".yaml" }; - - for (auto& extension : extensions) - { - YAML::Node object = parser.FileToYaml(path + extension); - - auto validation_errors = parser.Validate(object); - EXPECT_EQ(validation_errors.size(), 2); - - std::multiset expected = { ConfigParseStatus::RequiredKeyNotFound, ConfigParseStatus::InvalidKey }; - std::multiset actual; - for (const auto& [status, message] : validation_errors) - { - actual.insert(status); - std::cout << message << " " << configParseStatusToString(status) << std::endl; - } - EXPECT_EQ(actual, expected); - } -} - -TEST(ParseSurface, DetectsUnknownCondensedPhase) -{ - development::Parser parser; - - std::string path = "development_unit_configs/reactions/surface/missing_condensed_phase"; - std::vector extensions = { ".json", ".yaml" }; - - for (auto& extension : extensions) - { - YAML::Node object = parser.FileToYaml(path + extension); - - auto validation_errors = parser.Validate(object); - EXPECT_EQ(validation_errors.size(), 1); - - std::multiset expected = { ConfigParseStatus::UnknownPhase }; - std::multiset actual; - for (const auto& [status, message] : validation_errors) - { - actual.insert(status); - std::cout << message << " " << configParseStatusToString(status) << std::endl; - } - EXPECT_EQ(actual, expected); - } -} - -TEST(ParseSurface, DetectsUnknownGasPhase) -{ - development::Parser parser; - - std::string path = "development_unit_configs/reactions/surface/missing_gas_phase"; - std::vector extensions = { ".json", ".yaml" }; - - for (auto& extension : extensions) - { - YAML::Node object = parser.FileToYaml(path + extension); - - auto validation_errors = parser.Validate(object); - EXPECT_EQ(validation_errors.size(), 1); - - std::multiset expected = { ConfigParseStatus::UnknownPhase }; - std::multiset actual; - for (const auto& [status, message] : validation_errors) - { - actual.insert(status); - std::cout << message << " " << configParseStatusToString(status) << std::endl; - } - EXPECT_EQ(actual, expected); - } -} - -TEST(ValidateSurface, InvalidNumberReactantUnknownSpeciesUnknownPhaseFailsValidation) -{ - using namespace development; - - std::vector existing_species = { types::Species{ .name = "foo" }, types::Species{ .name = "bar" } }; - std::vector existing_phases = { types::Phase{ .name = "gas" } }; - - YAML::Node reaction_node; - reaction_node["type"] = "SURFACE"; - reaction_node["reaction probability"] = 0.7; - reaction_node["gas-phase products"] = YAML::Load("[{ name: foo }]"); - reaction_node["gas phase"] = "gas"; - - // Invalid number of reactions triggers validation error - reaction_node["gas-phase species"] = YAML::Load("[{ name: quiz }, { name: bar }]"); - - // Unknown condensed phase name triggers validation error - reaction_node["condensed phase"] = "condensed phase"; - - SurfaceParser parser; - Errors errors = parser.Validate(reaction_node, existing_species, existing_phases); - EXPECT_EQ(errors.size(), 3); - - std::multiset expected = { ConfigParseStatus::TooManyReactionComponents, - ConfigParseStatus::ReactionRequiresUnknownSpecies, - ConfigParseStatus::UnknownPhase }; - std::multiset actual; - for (const auto& [status, message] : errors) - { - actual.insert(status); - std::cout << message << " " << configParseStatusToString(status) << std::endl; - } - EXPECT_EQ(actual, expected); -} \ No newline at end of file diff --git a/test/unit/development/reactions/test_parse_taylor_series.cpp b/test/unit/development/reactions/test_parse_taylor_series.cpp deleted file mode 100644 index 403b4939..00000000 --- a/test/unit/development/reactions/test_parse_taylor_series.cpp +++ /dev/null @@ -1,217 +0,0 @@ -#include -#include - -#include - -#include - -using namespace mechanism_configuration; - -TEST(ParseTaylorSeries, ParseValidConfig) -{ - development::Parser parser; - - std::string path = "development_unit_configs/reactions/taylor_series/valid"; - std::vector extensions = { ".json", ".yaml" }; - - for (auto& extension : extensions) - { - YAML::Node object = parser.FileToYaml(path + extension); - - auto validation_errors = parser.Validate(object); - EXPECT_EQ(validation_errors.size(), 0) << "Validation errors were: " << validation_errors.size(); - - auto mechanism = parser.Parse(object); - EXPECT_EQ(mechanism.reactions.taylor_series.size(), 3); - - EXPECT_EQ(mechanism.reactions.taylor_series[0].name, "my taylor_series"); - EXPECT_EQ(mechanism.reactions.taylor_series[0].gas_phase, "gas"); - EXPECT_EQ(mechanism.reactions.taylor_series[0].A, 32.1); - EXPECT_EQ(mechanism.reactions.taylor_series[0].B, -2.3); - EXPECT_EQ(mechanism.reactions.taylor_series[0].C, 102.3); - EXPECT_EQ(mechanism.reactions.taylor_series[0].D, 63.4); - EXPECT_EQ(mechanism.reactions.taylor_series[0].E, -1.3); - EXPECT_EQ(mechanism.reactions.taylor_series[0].taylor_coefficients.size(), 3); - EXPECT_EQ(mechanism.reactions.taylor_series[0].taylor_coefficients[0], 1.0); - EXPECT_EQ(mechanism.reactions.taylor_series[0].taylor_coefficients[1], 2.0); - EXPECT_EQ(mechanism.reactions.taylor_series[0].taylor_coefficients[2], 3.0); - EXPECT_EQ(mechanism.reactions.taylor_series[0].reactants.size(), 1); - EXPECT_EQ(mechanism.reactions.taylor_series[0].reactants[0].name, "A"); - EXPECT_EQ(mechanism.reactions.taylor_series[0].reactants[0].coefficient, 1); - EXPECT_EQ(mechanism.reactions.taylor_series[0].products.size(), 2); - EXPECT_EQ(mechanism.reactions.taylor_series[0].products[0].name, "B"); - EXPECT_EQ(mechanism.reactions.taylor_series[0].products[0].coefficient, 1.2); - EXPECT_EQ(mechanism.reactions.taylor_series[0].products[1].name, "C"); - EXPECT_EQ(mechanism.reactions.taylor_series[0].products[1].coefficient, 0.3); - EXPECT_EQ(mechanism.reactions.taylor_series[0].unknown_properties.size(), 1); - EXPECT_EQ(mechanism.reactions.taylor_series[0].unknown_properties["__solver_param"], "0.1"); - - EXPECT_EQ(mechanism.reactions.taylor_series[1].name, "my taylor_series2"); - EXPECT_EQ(mechanism.reactions.taylor_series[1].gas_phase, "gas"); - EXPECT_EQ(mechanism.reactions.taylor_series[1].A, 3.1); - EXPECT_EQ(mechanism.reactions.taylor_series[1].B, -0.3); - EXPECT_EQ(mechanism.reactions.taylor_series[1].C, 12.3); - EXPECT_EQ(mechanism.reactions.taylor_series[1].D, 6.4); - EXPECT_EQ(mechanism.reactions.taylor_series[1].E, -0.3); - EXPECT_EQ(mechanism.reactions.taylor_series[1].taylor_coefficients.size(), 1); - EXPECT_EQ(mechanism.reactions.taylor_series[1].taylor_coefficients[0], 10.5); - EXPECT_EQ(mechanism.reactions.taylor_series[1].reactants.size(), 2); - EXPECT_EQ(mechanism.reactions.taylor_series[1].reactants[0].name, "A"); - EXPECT_EQ(mechanism.reactions.taylor_series[1].reactants[0].coefficient, 2); - EXPECT_EQ(mechanism.reactions.taylor_series[1].reactants[1].name, "B"); - EXPECT_EQ(mechanism.reactions.taylor_series[1].reactants[1].coefficient, 0.1); - EXPECT_EQ(mechanism.reactions.taylor_series[1].products.size(), 1); - EXPECT_EQ(mechanism.reactions.taylor_series[1].products[0].name, "C"); - EXPECT_EQ(mechanism.reactions.taylor_series[1].products[0].coefficient, 0.5); - EXPECT_EQ(mechanism.reactions.taylor_series[1].products[0].unknown_properties.size(), 1); - EXPECT_EQ(mechanism.reactions.taylor_series[1].products[0].unknown_properties["__optional thing"], "hello"); - - EXPECT_EQ(mechanism.reactions.taylor_series[2].name, ""); - EXPECT_EQ(mechanism.reactions.taylor_series[2].gas_phase, "gas"); - EXPECT_EQ(mechanism.reactions.taylor_series[2].A, 1); - EXPECT_EQ(mechanism.reactions.taylor_series[2].B, 0); - EXPECT_EQ(mechanism.reactions.taylor_series[2].C, 0); - EXPECT_EQ(mechanism.reactions.taylor_series[2].D, 300); - EXPECT_EQ(mechanism.reactions.taylor_series[2].E, 0); - EXPECT_EQ(mechanism.reactions.taylor_series[2].taylor_coefficients.size(), 1); - EXPECT_EQ(mechanism.reactions.taylor_series[2].taylor_coefficients[0], 1.0); - EXPECT_EQ(mechanism.reactions.taylor_series[2].reactants.size(), 1); - EXPECT_EQ(mechanism.reactions.taylor_series[2].reactants[0].name, "A"); - EXPECT_EQ(mechanism.reactions.taylor_series[2].reactants[0].coefficient, 1); - EXPECT_EQ(mechanism.reactions.taylor_series[2].products.size(), 1); - EXPECT_EQ(mechanism.reactions.taylor_series[2].products[0].name, "C"); - EXPECT_EQ(mechanism.reactions.taylor_series[2].products[0].coefficient, 1); - } -} - -TEST(ParseTaylorSeries, DetectsUnknownSpecies) -{ - development::Parser parser; - - std::string path = "development_unit_configs/reactions/taylor_series/unknown_species"; - std::vector extensions = { ".json", ".yaml" }; - - for (auto& extension : extensions) - { - YAML::Node object = parser.FileToYaml(path + extension); - - auto validation_errors = parser.Validate(object); - EXPECT_EQ(validation_errors.size(), 2); - - std::multiset expected = { ConfigParseStatus::ReactionRequiresUnknownSpecies, - ConfigParseStatus::RequestedSpeciesNotRegisteredInPhase }; - std::multiset actual; - for (const auto& [status, message] : validation_errors) - { - actual.insert(status); - std::cout << message << " " << configParseStatusToString(status) << std::endl; - } - EXPECT_EQ(actual, expected); - } -} - -TEST(ParseTaylorSeries, DetectsMutuallyExclusiveOptions) -{ - development::Parser parser; - - std::string path = "development_unit_configs/reactions/taylor_series/mutually_exclusive"; - std::vector extensions = { ".json", ".yaml" }; - - for (auto& extension : extensions) - { - YAML::Node object = parser.FileToYaml(path + extension); - - auto validation_errors = parser.Validate(object); - EXPECT_EQ(validation_errors.size(), 1); - - std::multiset expected = { ConfigParseStatus::MutuallyExclusiveOption }; - std::multiset actual; - for (const auto& [status, message] : validation_errors) - { - actual.insert(status); - std::cout << message << " " << configParseStatusToString(status) << std::endl; - } - EXPECT_EQ(actual, expected); - } -} - -TEST(ParseTaylorSeries, DetectsBadReactionComponent) -{ - development::Parser parser; - - std::string path = "development_unit_configs/reactions/taylor_series/bad_reaction_component"; - std::vector extensions = { ".json", ".yaml" }; - - for (auto& extension : extensions) - { - YAML::Node object = parser.FileToYaml(path + extension); - - auto validation_errors = parser.Validate(object); - EXPECT_EQ(validation_errors.size(), 2); - - std::multiset expected = { ConfigParseStatus::InvalidKey, ConfigParseStatus::RequiredKeyNotFound }; - std::multiset actual; - for (const auto& [status, message] : validation_errors) - { - actual.insert(status); - std::cout << message << " " << configParseStatusToString(status) << std::endl; - } - EXPECT_EQ(actual, expected); - } -} - -TEST(ParseTaylorSeries, DetectsUnknownPhase) -{ - development::Parser parser; - - std::string path = "development_unit_configs/reactions/taylor_series/missing_phase"; - std::vector extensions = { ".json", ".yaml" }; - - for (auto& extension : extensions) - { - YAML::Node object = parser.FileToYaml(path + extension); - - auto validation_errors = parser.Validate(object); - EXPECT_EQ(validation_errors.size(), 1); - - std::multiset expected = { ConfigParseStatus::UnknownPhase }; - std::multiset actual; - for (const auto& [status, message] : validation_errors) - { - actual.insert(status); - std::cout << message << " " << configParseStatusToString(status) << std::endl; - } - EXPECT_EQ(actual, expected); - } -} - -TEST(ValidateTaylorSeries, MutuallyExclusiveEaAndCFailsValidation) -{ - using namespace development; - - std::vector existing_species = { types::Species{ .name = "foo" }, types::Species{ .name = "bar" } }; - std::vector existing_phases = { types::Phase{ .name = "gas" } }; - - YAML::Node reaction_node; - reaction_node["reactants"] = YAML::Load("[{ name: foo }]"); - reaction_node["products"] = YAML::Load("[{ name: bar }]"); - reaction_node["type"] = "TAYLOR_SERIES"; - reaction_node["gas phase"] = "gas"; - - // Specify both Ea and C to trigger validation error - reaction_node["Ea"] = 0.5; - reaction_node["C"] = 10.0; - - TaylorSeriesParser parser; - Errors errors = parser.Validate(reaction_node, existing_species, existing_phases); - EXPECT_EQ(errors.size(), 1); - - std::multiset expected = { ConfigParseStatus::MutuallyExclusiveOption }; - std::multiset actual; - for (const auto& [status, message] : errors) - { - actual.insert(status); - std::cout << message << " " << configParseStatusToString(status) << std::endl; - } - EXPECT_EQ(actual, expected); -} diff --git a/test/unit/development/reactions/test_parse_ternary_chemical_activation.cpp b/test/unit/development/reactions/test_parse_ternary_chemical_activation.cpp deleted file mode 100644 index e19144ca..00000000 --- a/test/unit/development/reactions/test_parse_ternary_chemical_activation.cpp +++ /dev/null @@ -1,211 +0,0 @@ -#include -#include - -#include - -#include - -using namespace mechanism_configuration; - -TEST(ParserTernary, ParseValidConfig) -{ - development::Parser parser; - - std::string path = "development_unit_configs/reactions/ternary_chemical_activation/valid"; - std::vector extensions = { ".json", ".yaml" }; - - for (auto& extension : extensions) - { - YAML::Node object = parser.FileToYaml(path + extension); - - auto validation_errors = parser.Validate(object); - EXPECT_EQ(validation_errors.size(), 0) << "Validation errors were: " << validation_errors.size(); - - auto mechanism = parser.Parse(object); - auto& process_vector = mechanism.reactions.ternary_chemical_activation; - - EXPECT_EQ(process_vector.size(), 2); - - // first reaction - EXPECT_EQ(process_vector[0].reactants.size(), 2); - EXPECT_EQ(process_vector[0].reactants[0].name, "foo"); - EXPECT_EQ(process_vector[0].reactants[0].coefficient, 1.0); - EXPECT_EQ(process_vector[0].reactants[1].name, "quz"); - EXPECT_EQ(process_vector[0].reactants[1].coefficient, 2.0); - EXPECT_EQ(process_vector[0].products.size(), 2); - EXPECT_EQ(process_vector[0].products[0].name, "bar"); - EXPECT_EQ(process_vector[0].products[0].coefficient, 1.0); - EXPECT_EQ(process_vector[0].products[1].name, "baz"); - EXPECT_EQ(process_vector[0].products[1].coefficient, 3.2); - EXPECT_EQ(process_vector[0].k0_A, 1.0); - EXPECT_EQ(process_vector[0].k0_B, 0.0); - EXPECT_EQ(process_vector[0].k0_C, 0.0); - EXPECT_EQ(process_vector[0].kinf_A, 1.0); - EXPECT_EQ(process_vector[0].kinf_B, 0.0); - EXPECT_EQ(process_vector[0].kinf_C, 0.0); - EXPECT_EQ(process_vector[0].Fc, 0.6); - EXPECT_EQ(process_vector[0].N, 1.0); - - // second reaction - EXPECT_EQ(process_vector[1].unknown_properties.size(), 1); - EXPECT_EQ(process_vector[1].unknown_properties["__optional thing"], "hello"); - EXPECT_EQ(process_vector[1].reactants.size(), 2); - EXPECT_EQ(process_vector[1].reactants[0].name, "bar"); - EXPECT_EQ(process_vector[1].reactants[1].name, "baz"); - EXPECT_EQ(process_vector[1].products.size(), 2); - EXPECT_EQ(process_vector[1].products[0].name, "bar"); - EXPECT_EQ(process_vector[1].products[0].coefficient, 0.5); - EXPECT_EQ(process_vector[1].products[1].name, "foo"); - EXPECT_EQ(process_vector[1].products[1].coefficient, 0.0); - EXPECT_EQ(process_vector[1].k0_A, 32.1); - EXPECT_EQ(process_vector[1].k0_B, -2.3); - EXPECT_EQ(process_vector[1].k0_C, 102.3); - EXPECT_EQ(process_vector[1].kinf_A, 63.4); - EXPECT_EQ(process_vector[1].kinf_B, -1.3); - EXPECT_EQ(process_vector[1].kinf_C, 908.5); - EXPECT_EQ(process_vector[1].Fc, 1.3); - EXPECT_EQ(process_vector[1].N, 32.1); - EXPECT_EQ(process_vector[1].name, "my ternary chemical activation"); - } -} - -TEST(ParserTernary, DetectsNonStandardKey) -{ - development::Parser parser; - - std::string path = "development_unit_configs/reactions/ternary_chemical_activation/contains_nonstandard_key"; - std::vector extensions = { ".json", ".yaml" }; - - for (auto& extension : extensions) - { - YAML::Node object = parser.FileToYaml(path + extension); - - auto validation_errors = parser.Validate(object); - EXPECT_EQ(validation_errors.size(), 12); - - std::multiset expected = { ConfigParseStatus::RequiredKeyNotFound, ConfigParseStatus::InvalidKey, - ConfigParseStatus::RequiredKeyNotFound, ConfigParseStatus::InvalidKey, - ConfigParseStatus::InvalidKey, ConfigParseStatus::InvalidKey, - ConfigParseStatus::InvalidKey, ConfigParseStatus::InvalidKey, - ConfigParseStatus::InvalidKey, ConfigParseStatus::InvalidKey, - ConfigParseStatus::InvalidKey, ConfigParseStatus::InvalidKey }; - std::multiset actual; - for (const auto& [status, message] : validation_errors) - { - actual.insert(status); - std::cout << message << " " << configParseStatusToString(status) << std::endl; - } - EXPECT_EQ(actual, expected); - } -} - -TEST(ParserTernary, DetectsUnknownSpecies) -{ - development::Parser parser; - - std::string path = "development_unit_configs/reactions/ternary_chemical_activation/unknown_species"; - std::vector extensions = { ".json", ".yaml" }; - - for (auto& extension : extensions) - { - YAML::Node object = parser.FileToYaml(path + extension); - - auto validation_errors = parser.Validate(object); - EXPECT_EQ(validation_errors.size(), 2); - - std::multiset expected = { ConfigParseStatus::ReactionRequiresUnknownSpecies, - ConfigParseStatus::RequestedSpeciesNotRegisteredInPhase }; - std::multiset actual; - for (const auto& [status, message] : validation_errors) - { - actual.insert(status); - std::cout << message << " " << configParseStatusToString(status) << std::endl; - } - EXPECT_EQ(actual, expected); - } -} - -TEST(ParserTernary, DetectsMissingProducts) -{ - development::Parser parser; - - std::string path = "development_unit_configs/reactions/ternary_chemical_activation/missing_products"; - std::vector extensions = { ".json", ".yaml" }; - - for (auto& extension : extensions) - { - YAML::Node object = parser.FileToYaml(path + extension); - - auto validation_errors = parser.Validate(object); - EXPECT_EQ(validation_errors.size(), 1); - - std::multiset expected = { ConfigParseStatus::RequiredKeyNotFound }; - std::multiset actual; - for (const auto& [status, message] : validation_errors) - { - actual.insert(status); - std::cout << message << " " << configParseStatusToString(status) << std::endl; - } - EXPECT_EQ(actual, expected); - } -} - -TEST(ParserTernary, DetectsMissingReactants) -{ - development::Parser parser; - - std::string path = "development_unit_configs/reactions/ternary_chemical_activation/missing_reactants"; - std::vector extensions = { ".json", ".yaml" }; - - for (auto& extension : extensions) - { - YAML::Node object = parser.FileToYaml(path + extension); - - auto validation_errors = parser.Validate(object); - EXPECT_EQ(validation_errors.size(), 1); - - std::multiset expected = { ConfigParseStatus::RequiredKeyNotFound }; - std::multiset actual; - for (const auto& [status, message] : validation_errors) - { - actual.insert(status); - std::cout << message << " " << configParseStatusToString(status) << std::endl; - } - EXPECT_EQ(actual, expected); - } -} - -TEST(ValidateTernary, UnknownSpeciesAndUnknownPhaseFailsValidation) -{ - using namespace development; - - std::vector existing_species = { types::Species{ .name = "foo" }, - types::Species{ .name = "bar" }, - types::Species{ .name = "quiz" } }; - - std::vector existing_phases = { types::Phase{ .name = "gas" } }; - - YAML::Node reaction_node; - reaction_node["type"] = "TERNARY_CHEMICAL_ACTIVATION"; - reaction_node["products"] = YAML::Load("[{ name: quiz }]"); - - // Unknown species triggers validation error - reaction_node["reactants"] = YAML::Load("[{ name: bar }, { name: ABC }]"); - - // Unknown gas phase name triggers validation error - reaction_node["gas phase"] = "Gaseous Phase"; - - TernaryChemicalActivationParser parser; - Errors errors = parser.Validate(reaction_node, existing_species, existing_phases); - EXPECT_EQ(errors.size(), 2); - - std::multiset expected = { ConfigParseStatus::ReactionRequiresUnknownSpecies, - ConfigParseStatus::UnknownPhase }; - std::multiset actual; - for (const auto& [status, message] : errors) - { - actual.insert(status); - std::cout << message << " " << configParseStatusToString(status) << std::endl; - } - EXPECT_EQ(actual, expected); -} \ No newline at end of file diff --git a/test/unit/development/reactions/test_parse_troe.cpp b/test/unit/development/reactions/test_parse_troe.cpp deleted file mode 100644 index aeeb76c6..00000000 --- a/test/unit/development/reactions/test_parse_troe.cpp +++ /dev/null @@ -1,185 +0,0 @@ -#include -#include - -#include - -#include - -using namespace mechanism_configuration; - -TEST(ParserTroe, ParseValidConfig) -{ - development::Parser parser; - - std::string path = "development_unit_configs/reactions/troe/valid"; - std::vector extensions = { ".json", ".yaml" }; - - for (auto& extension : extensions) - { - YAML::Node object = parser.FileToYaml(path + extension); - - auto validation_errors = parser.Validate(object); - EXPECT_EQ(validation_errors.size(), 0) << "Validation errors were: " << validation_errors.size(); - - auto mechanism = parser.Parse(object); - EXPECT_EQ(mechanism.reactions.troe.size(), 2); - - EXPECT_EQ(mechanism.reactions.troe[0].gas_phase, "gas"); - EXPECT_EQ(mechanism.reactions.troe[0].k0_A, 1.0); - EXPECT_EQ(mechanism.reactions.troe[0].k0_B, 0.0); - EXPECT_EQ(mechanism.reactions.troe[0].k0_C, 0.0); - EXPECT_EQ(mechanism.reactions.troe[0].kinf_A, 1.0); - EXPECT_EQ(mechanism.reactions.troe[0].kinf_B, 0.0); - EXPECT_EQ(mechanism.reactions.troe[0].kinf_C, 0.0); - EXPECT_EQ(mechanism.reactions.troe[0].Fc, 0.6); - EXPECT_EQ(mechanism.reactions.troe[0].N, 1.0); - EXPECT_EQ(mechanism.reactions.troe[0].reactants.size(), 1); - EXPECT_EQ(mechanism.reactions.troe[0].reactants[0].name, "A"); - EXPECT_EQ(mechanism.reactions.troe[0].reactants[0].coefficient, 1); - EXPECT_EQ(mechanism.reactions.troe[0].products.size(), 1); - EXPECT_EQ(mechanism.reactions.troe[0].products[0].name, "C"); - EXPECT_EQ(mechanism.reactions.troe[0].products[0].coefficient, 1); - EXPECT_EQ(mechanism.reactions.troe[0].unknown_properties.size(), 1); - if (extension == ".json") - { - EXPECT_EQ(mechanism.reactions.troe[0].unknown_properties["__my object"], "{a: 1.0}"); - } - else - { - EXPECT_EQ(mechanism.reactions.troe[0].unknown_properties["__my object"], "a: 1.0"); - } - - EXPECT_EQ(mechanism.reactions.troe[1].name, "my troe"); - EXPECT_EQ(mechanism.reactions.troe[1].gas_phase, "gas"); - EXPECT_EQ(mechanism.reactions.troe[1].k0_A, 32.1); - EXPECT_EQ(mechanism.reactions.troe[1].k0_B, -2.3); - EXPECT_EQ(mechanism.reactions.troe[1].k0_C, 102.3); - EXPECT_EQ(mechanism.reactions.troe[1].kinf_A, 63.4); - EXPECT_EQ(mechanism.reactions.troe[1].kinf_B, -1.3); - EXPECT_EQ(mechanism.reactions.troe[1].kinf_C, 908.5); - EXPECT_EQ(mechanism.reactions.troe[1].Fc, 1.3); - EXPECT_EQ(mechanism.reactions.troe[1].N, 32.1); - EXPECT_EQ(mechanism.reactions.troe[1].reactants.size(), 1); - EXPECT_EQ(mechanism.reactions.troe[1].reactants[0].name, "C"); - EXPECT_EQ(mechanism.reactions.troe[1].reactants[0].coefficient, 1); - EXPECT_EQ(mechanism.reactions.troe[1].products.size(), 2); - EXPECT_EQ(mechanism.reactions.troe[1].products[0].name, "A"); - EXPECT_EQ(mechanism.reactions.troe[1].products[0].coefficient, 0.2); - EXPECT_EQ(mechanism.reactions.troe[1].products[0].unknown_properties.size(), 1); - EXPECT_EQ(mechanism.reactions.troe[1].products[0].unknown_properties["__optional thing"], "hello"); - EXPECT_EQ(mechanism.reactions.troe[1].products[1].name, "B"); - EXPECT_EQ(mechanism.reactions.troe[1].products[1].coefficient, 1.2); - EXPECT_EQ(mechanism.reactions.troe[1].products[1].unknown_properties.size(), 0); - } -} - -TEST(ParserTroe, DetectsUnknownSpecies) -{ - development::Parser parser; - - std::string path = "development_unit_configs/reactions/troe/unknown_species"; - std::vector extensions = { ".json", ".yaml" }; - - for (auto& extension : extensions) - { - YAML::Node object = parser.FileToYaml(path + extension); - - auto validation_errors = parser.Validate(object); - EXPECT_EQ(validation_errors.size(), 2); - - std::multiset expected = { ConfigParseStatus::ReactionRequiresUnknownSpecies, - ConfigParseStatus::RequestedSpeciesNotRegisteredInPhase }; - std::multiset actual; - for (const auto& [status, message] : validation_errors) - { - actual.insert(status); - std::cout << message << " " << configParseStatusToString(status) << std::endl; - } - EXPECT_EQ(actual, expected); - } -} - -TEST(ParserTroe, DetectsBadReactionComponent) -{ - development::Parser parser; - - std::string path = "development_unit_configs/reactions/troe/bad_reaction_component"; - std::vector extensions = { ".json", ".yaml" }; - - for (auto& extension : extensions) - { - YAML::Node object = parser.FileToYaml(path + extension); - - auto validation_errors = parser.Validate(object); - EXPECT_EQ(validation_errors.size(), 2); - - std::multiset expected = { ConfigParseStatus::RequiredKeyNotFound, ConfigParseStatus::InvalidKey }; - std::multiset actual; - for (const auto& [status, message] : validation_errors) - { - actual.insert(status); - std::cout << message << " " << configParseStatusToString(status) << std::endl; - } - EXPECT_EQ(actual, expected); - } -} - -TEST(ParserTroe, DetectsUnknownPhase) -{ - development::Parser parser; - - std::string path = "development_unit_configs/reactions/troe/missing_phase"; - std::vector extensions = { ".json", ".yaml" }; - - for (auto& extension : extensions) - { - YAML::Node object = parser.FileToYaml(path + extension); - - auto validation_errors = parser.Validate(object); - EXPECT_EQ(validation_errors.size(), 1); - - std::multiset expected = { ConfigParseStatus::UnknownPhase }; - std::multiset actual; - for (const auto& [status, message] : validation_errors) - { - actual.insert(status); - std::cout << message << " " << configParseStatusToString(status) << std::endl; - } - EXPECT_EQ(actual, expected); - } -} - -TEST(ValidateTroe, UnknownSpeciesAndUnknownPhaseFailsValidation) -{ - using namespace development; - - std::vector existing_species = { types::Species{ .name = "foo" }, - types::Species{ .name = "bar" }, - types::Species{ .name = "quiz" } }; - - std::vector existing_phases = { types::Phase{ .name = "gas" } }; - - YAML::Node reaction_node; - reaction_node["type"] = "TROE"; - reaction_node["products"] = YAML::Load("[{ name: quiz }]"); - - // Unknown species triggers validation error - reaction_node["reactants"] = YAML::Load("[{ name: bar }, { name: ABC }]"); - - // Unknown gas phase name triggers validation error - reaction_node["gas phase"] = "Gaseous Phase"; - - TroeParser parser; - Errors errors = parser.Validate(reaction_node, existing_species, existing_phases); - EXPECT_EQ(errors.size(), 2); - - std::multiset expected = { ConfigParseStatus::ReactionRequiresUnknownSpecies, - ConfigParseStatus::UnknownPhase }; - std::multiset actual; - for (const auto& [status, message] : errors) - { - actual.insert(status); - std::cout << message << " " << configParseStatusToString(status) << std::endl; - } - EXPECT_EQ(actual, expected); -} \ No newline at end of file diff --git a/test/unit/development/reactions/test_parse_tunneling.cpp b/test/unit/development/reactions/test_parse_tunneling.cpp deleted file mode 100644 index a91e8a20..00000000 --- a/test/unit/development/reactions/test_parse_tunneling.cpp +++ /dev/null @@ -1,166 +0,0 @@ -#include -#include - -#include - -#include - -using namespace mechanism_configuration; - -TEST(ParseTunneling, ParseValidConfig) -{ - development::Parser parser; - - std::string path = "development_unit_configs/reactions/tunneling/valid"; - std::vector extensions = { ".json", ".yaml" }; - - for (auto& extension : extensions) - { - YAML::Node object = parser.FileToYaml(path + extension); - - auto validation_errors = parser.Validate(object); - EXPECT_EQ(validation_errors.size(), 0) << "Validation errors were: " << validation_errors.size(); - - auto mechanism = parser.Parse(object); - EXPECT_EQ(mechanism.reactions.tunneling.size(), 2); - - EXPECT_EQ(mechanism.reactions.tunneling[0].gas_phase, "gas"); - EXPECT_EQ(mechanism.reactions.tunneling[0].A, 123.45); - EXPECT_EQ(mechanism.reactions.tunneling[0].B, 1200.0); - EXPECT_EQ(mechanism.reactions.tunneling[0].C, 1.0e8); - EXPECT_EQ(mechanism.reactions.tunneling[0].reactants.size(), 1); - EXPECT_EQ(mechanism.reactions.tunneling[0].reactants[0].name, "B"); - EXPECT_EQ(mechanism.reactions.tunneling[0].reactants[0].coefficient, 1); - EXPECT_EQ(mechanism.reactions.tunneling[0].products.size(), 1); - EXPECT_EQ(mechanism.reactions.tunneling[0].products[0].name, "C"); - EXPECT_EQ(mechanism.reactions.tunneling[0].products[0].coefficient, 1); - - EXPECT_EQ(mechanism.reactions.tunneling[1].name, "my tunneling"); - EXPECT_EQ(mechanism.reactions.tunneling[1].gas_phase, "gas"); - EXPECT_EQ(mechanism.reactions.tunneling[1].A, 1.0); - EXPECT_EQ(mechanism.reactions.tunneling[1].B, 0); - EXPECT_EQ(mechanism.reactions.tunneling[1].C, 0); - EXPECT_EQ(mechanism.reactions.tunneling[1].reactants.size(), 1); - EXPECT_EQ(mechanism.reactions.tunneling[1].reactants[0].name, "B"); - EXPECT_EQ(mechanism.reactions.tunneling[1].reactants[0].coefficient, 1); - EXPECT_EQ(mechanism.reactions.tunneling[1].products.size(), 2); - EXPECT_EQ(mechanism.reactions.tunneling[1].products[0].name, "A"); - EXPECT_EQ(mechanism.reactions.tunneling[1].products[0].coefficient, 0.2); - EXPECT_EQ(mechanism.reactions.tunneling[1].products[0].unknown_properties.size(), 1); - EXPECT_EQ(mechanism.reactions.tunneling[1].products[0].unknown_properties["__optional thing"], "hello"); - EXPECT_EQ(mechanism.reactions.tunneling[1].products[1].name, "B"); - EXPECT_EQ(mechanism.reactions.tunneling[1].products[1].coefficient, 1.2); - EXPECT_EQ(mechanism.reactions.tunneling[1].products[1].unknown_properties.size(), 0); - } -} - -TEST(ParseTunneling, DetectsUnknownSpecies) -{ - development::Parser parser; - - std::string path = "development_unit_configs/reactions/tunneling/unknown_species"; - std::vector extensions = { ".json", ".yaml" }; - - for (auto& extension : extensions) - { - YAML::Node object = parser.FileToYaml(path + extension); - - auto validation_errors = parser.Validate(object); - EXPECT_EQ(validation_errors.size(), 2); - - std::multiset expected = { ConfigParseStatus::ReactionRequiresUnknownSpecies, - ConfigParseStatus::RequestedSpeciesNotRegisteredInPhase }; - std::multiset actual; - for (const auto& [status, message] : validation_errors) - { - actual.insert(status); - std::cout << message << " " << configParseStatusToString(status) << std::endl; - } - EXPECT_EQ(actual, expected); - } -} - -TEST(ParseTunneling, DetectsBadReactionComponent) -{ - development::Parser parser; - - std::string path = "development_unit_configs/reactions/tunneling/bad_reaction_component"; - std::vector extensions = { ".json", ".yaml" }; - - for (auto& extension : extensions) - { - YAML::Node object = parser.FileToYaml(path + extension); - - auto validation_errors = parser.Validate(object); - EXPECT_EQ(validation_errors.size(), 2); - - std::multiset expected = { ConfigParseStatus::RequiredKeyNotFound, ConfigParseStatus::InvalidKey }; - std::multiset actual; - for (const auto& [status, message] : validation_errors) - { - actual.insert(status); - std::cout << message << " " << configParseStatusToString(status) << std::endl; - } - EXPECT_EQ(actual, expected); - } -} - -TEST(ParseTunneling, DetectsUnknownPhase) -{ - development::Parser parser; - - std::string path = "development_unit_configs/reactions/tunneling/missing_phase"; - std::vector extensions = { ".json", ".yaml" }; - - for (auto& extension : extensions) - { - YAML::Node object = parser.FileToYaml(path + extension); - - auto validation_errors = parser.Validate(object); - EXPECT_EQ(validation_errors.size(), 1); - - std::multiset expected = { ConfigParseStatus::UnknownPhase }; - std::multiset actual; - for (const auto& [status, message] : validation_errors) - { - actual.insert(status); - std::cout << message << " " << configParseStatusToString(status) << std::endl; - } - EXPECT_EQ(actual, expected); - } -} - -TEST(ValidateTunneling, UnknownSpeciesAndUnknownPhaseFailsValidation) -{ - using namespace development; - - std::vector existing_species = { types::Species{ .name = "foo" }, - types::Species{ .name = "bar" }, - types::Species{ .name = "quiz" } }; - - std::vector existing_phases = { types::Phase{ .name = "gas" } }; - - YAML::Node reaction_node; - reaction_node["type"] = "TUNNELING"; - reaction_node["products"] = YAML::Load("[{ name: quiz }]"); - - // Unknown species triggers validation error - reaction_node["reactants"] = YAML::Load("[{ name: bar }, { name: ABC }]"); - - // Unknown gas phase name triggers validation error - reaction_node["gas phase"] = "Gaseous Phase"; - - TunnelingParser parser; - Errors errors = parser.Validate(reaction_node, existing_species, existing_phases); - EXPECT_EQ(errors.size(), 2); - - std::multiset expected = { ConfigParseStatus::ReactionRequiresUnknownSpecies, - ConfigParseStatus::UnknownPhase }; - std::multiset actual; - for (const auto& [status, message] : errors) - { - actual.insert(status); - std::cout << message << " " << configParseStatusToString(status) << std::endl; - } - EXPECT_EQ(actual, expected); -} \ No newline at end of file diff --git a/test/unit/development/reactions/test_parse_user_defined.cpp b/test/unit/development/reactions/test_parse_user_defined.cpp deleted file mode 100644 index 0c06ebc4..00000000 --- a/test/unit/development/reactions/test_parse_user_defined.cpp +++ /dev/null @@ -1,164 +0,0 @@ -#include -#include - -#include - -#include - -using namespace mechanism_configuration; - -TEST(ParseUserDefined, ParseValidConfig) -{ - development::Parser parser; - - std::string path = "development_unit_configs/reactions/user_defined/valid"; - std::vector extensions = { ".json", ".yaml" }; - - for (auto& extension : extensions) - { - YAML::Node object = parser.FileToYaml(path + extension); - - auto validation_errors = parser.Validate(object); - EXPECT_EQ(validation_errors.size(), 0) << "Validation errors were: " << validation_errors.size(); - - auto mechanism = parser.Parse(object); - EXPECT_EQ(mechanism.reactions.user_defined.size(), 2); - - EXPECT_EQ(mechanism.reactions.user_defined[0].gas_phase, "gas"); - EXPECT_EQ(mechanism.reactions.user_defined[0].name, "my user defined"); - EXPECT_EQ(mechanism.reactions.user_defined[0].scaling_factor, 12.3); - EXPECT_EQ(mechanism.reactions.user_defined[0].reactants.size(), 1); - EXPECT_EQ(mechanism.reactions.user_defined[0].reactants[0].name, "B"); - EXPECT_EQ(mechanism.reactions.user_defined[0].reactants[0].coefficient, 1); - EXPECT_EQ(mechanism.reactions.user_defined[0].products.size(), 1); - EXPECT_EQ(mechanism.reactions.user_defined[0].products[0].name, "C"); - EXPECT_EQ(mechanism.reactions.user_defined[0].products[0].coefficient, 1); - EXPECT_EQ(mechanism.reactions.user_defined[0].unknown_properties.size(), 1); - EXPECT_EQ(mechanism.reactions.user_defined[0].unknown_properties["__comment"], "hi"); - - EXPECT_EQ(mechanism.reactions.user_defined[1].gas_phase, "gas"); - EXPECT_EQ(mechanism.reactions.user_defined[1].scaling_factor, 1); - EXPECT_EQ(mechanism.reactions.user_defined[1].reactants.size(), 2); - EXPECT_EQ(mechanism.reactions.user_defined[1].reactants[0].name, "B"); - EXPECT_EQ(mechanism.reactions.user_defined[1].reactants[0].coefficient, 1.2); - EXPECT_EQ(mechanism.reactions.user_defined[1].reactants[1].name, "A"); - EXPECT_EQ(mechanism.reactions.user_defined[1].reactants[1].coefficient, 0.5); - EXPECT_EQ(mechanism.reactions.user_defined[1].products.size(), 1); - EXPECT_EQ(mechanism.reactions.user_defined[1].products[0].name, "C"); - EXPECT_EQ(mechanism.reactions.user_defined[1].products[0].coefficient, 0.2); - } -} - -TEST(ParseUserDefined, DetectsUnknownSpecies) -{ - development::Parser parser; - - std::string path = "development_unit_configs/reactions/user_defined/unknown_species"; - std::vector extensions = { ".json", ".yaml" }; - - for (auto& extension : extensions) - { - YAML::Node object = parser.FileToYaml(path + extension); - - auto validation_errors = parser.Validate(object); - EXPECT_EQ(validation_errors.size(), 2); - - std::multiset expected = { ConfigParseStatus::ReactionRequiresUnknownSpecies, - ConfigParseStatus::RequestedSpeciesNotRegisteredInPhase }; - ; - std::multiset actual; - for (const auto& [status, message] : validation_errors) - { - actual.insert(status); - std::cout << message << " " << configParseStatusToString(status) << std::endl; - } - EXPECT_EQ(actual, expected); - } -} - -TEST(ParseUserDefined, DetectsBadReactionComponent) -{ - development::Parser parser; - - std::string path = "development_unit_configs/reactions/user_defined/bad_reaction_component"; - std::vector extensions = { ".json", ".yaml" }; - - for (auto& extension : extensions) - { - YAML::Node object = parser.FileToYaml(path + extension); - - auto validation_errors = parser.Validate(object); - EXPECT_EQ(validation_errors.size(), 3); - - std::multiset expected = { ConfigParseStatus::InvalidKey, - ConfigParseStatus::InvalidKey, - ConfigParseStatus::RequiredKeyNotFound }; - std::multiset actual; - for (const auto& [status, message] : validation_errors) - { - actual.insert(status); - std::cout << message << " " << configParseStatusToString(status) << std::endl; - } - EXPECT_EQ(actual, expected); - } -} - -TEST(ParseUserDefined, DetectsUnknownPhase) -{ - development::Parser parser; - - std::string path = "development_unit_configs/reactions/user_defined/missing_phase"; - std::vector extensions = { ".json", ".yaml" }; - - for (auto& extension : extensions) - { - YAML::Node object = parser.FileToYaml(path + extension); - - auto validation_errors = parser.Validate(object); - EXPECT_EQ(validation_errors.size(), 1); - - std::multiset expected = { ConfigParseStatus::UnknownPhase }; - std::multiset actual; - for (const auto& [status, message] : validation_errors) - { - actual.insert(status); - std::cout << message << " " << configParseStatusToString(status) << std::endl; - } - EXPECT_EQ(actual, expected); - } -} - -TEST(ValidateUserDefined, UnknownSpeciesAndUnknownPhaseFailsValidation) -{ - using namespace development; - - std::vector existing_species = { types::Species{ .name = "foo" }, - types::Species{ .name = "bar" }, - types::Species{ .name = "quiz" } }; - - std::vector existing_phases = { types::Phase{ .name = "gas" } }; - - YAML::Node reaction_node; - reaction_node["type"] = "USER_DEFINED"; - reaction_node["products"] = YAML::Load("[{ name: quiz }]"); - - // Unknown species triggers validation error - reaction_node["reactants"] = YAML::Load("[{ name: bar }, { name: ABC }]"); - - // Unknown gas phase name triggers validation error - reaction_node["gas phase"] = "Gaseous Phase"; - - UserDefinedParser parser; - Errors errors = parser.Validate(reaction_node, existing_species, existing_phases); - EXPECT_EQ(errors.size(), 2); - - std::multiset expected = { ConfigParseStatus::ReactionRequiresUnknownSpecies, - ConfigParseStatus::UnknownPhase }; - std::multiset actual; - for (const auto& [status, message] : errors) - { - actual.insert(status); - std::cout << message << " " << configParseStatusToString(status) << std::endl; - } - EXPECT_EQ(actual, expected); -} \ No newline at end of file diff --git a/test/unit/development/reactions/test_parse_wet_deposition.cpp b/test/unit/development/reactions/test_parse_wet_deposition.cpp deleted file mode 100644 index 015c4338..00000000 --- a/test/unit/development/reactions/test_parse_wet_deposition.cpp +++ /dev/null @@ -1,159 +0,0 @@ -#include -#include - -#include - -#include - -using namespace mechanism_configuration; - -TEST(ParseWetDeposition, ParseValidConfig) -{ - development::Parser parser; - - std::string path = "development_unit_configs/reactions/wet_deposition/valid"; - std::vector extensions = { ".json", ".yaml" }; - - for (auto& extension : extensions) - { - YAML::Node object = parser.FileToYaml(path + extension); - - auto validation_errors = parser.Validate(object); - EXPECT_EQ(validation_errors.size(), 0) << "Validation errors were: " << validation_errors.size(); - - auto mechanism = parser.Parse(object); - EXPECT_EQ(mechanism.reactions.wet_deposition.size(), 2); - - EXPECT_EQ(mechanism.reactions.wet_deposition[0].name, "rxn cloud"); - EXPECT_EQ(mechanism.reactions.wet_deposition[0].condensed_phase, "cloud"); - EXPECT_EQ(mechanism.reactions.wet_deposition[0].scaling_factor, 12.3); - EXPECT_EQ(mechanism.reactions.wet_deposition[0].unknown_properties.size(), 1); - EXPECT_EQ(mechanism.reactions.wet_deposition[0].unknown_properties["__comment"], "Tuxedo cats are the best"); - - EXPECT_EQ(mechanism.reactions.wet_deposition[1].name, "rxn cloud2"); - EXPECT_EQ(mechanism.reactions.wet_deposition[1].condensed_phase, "cloud"); - EXPECT_EQ(mechanism.reactions.wet_deposition[1].scaling_factor, 1); - } -} - -TEST(ParseWetDeposition, DetectsUnknownPhase) -{ - development::Parser parser; - - std::string path = "development_unit_configs/reactions/wet_deposition/missing_phase"; - std::vector extensions = { ".json", ".yaml" }; - - for (auto& extension : extensions) - { - YAML::Node object = parser.FileToYaml(path + extension); - - auto validation_errors = parser.Validate(object); - EXPECT_EQ(validation_errors.size(), 1); - - std::multiset expected = { ConfigParseStatus::UnknownPhase }; - std::multiset actual; - for (const auto& [status, message] : validation_errors) - { - actual.insert(status); - std::cout << message << " " << configParseStatusToString(status) << std::endl; - } - EXPECT_EQ(actual, expected); - } -} - -TEST(ValidateWetDeposition, ReturnsEmptyErrorsForValidReaction) -{ - std::vector existing_species; - development::types::Species species1; - species1.name = "A"; - existing_species.emplace_back(species1); - - std::vector existing_phases; - development::types::Phase phase1; - phase1.name = "cloud"; - existing_phases.emplace_back(phase1); - - YAML::Node reaction = YAML::Load(R"( - type: "WET_DEPOSITION" - "condensed phase": "cloud" - name: "rxn cloud" - "scaling factor": 12.3 - )"); - - development::WetDepositionParser parser; - auto errors = parser.Validate(reaction, existing_species, existing_phases); - EXPECT_TRUE(errors.empty()); -} - -TEST(ValidateWetDeposition, DetectsMissingRequiredType) -{ - std::vector existing_species; - std::vector existing_phases; - development::types::Phase phase1; - phase1.name = "cloud"; - existing_phases.emplace_back(phase1); - - YAML::Node reaction = YAML::Load(R"( - "condensed phase": "cloud" - name: "rxn cloud" - )"); - - development::WetDepositionParser parser; - auto errors = parser.Validate(reaction, existing_species, existing_phases); - EXPECT_EQ(errors.size(), 1); - - std::multiset expected = { ConfigParseStatus::RequiredKeyNotFound }; - std::multiset actual; - for (const auto& [status, message] : errors) - { - actual.insert(status); - std::cout << message << " " << configParseStatusToString(status) << std::endl; - } - EXPECT_EQ(actual, expected); -} - -TEST(ValidateWetDeposition, DetectsMissingRequiredCondensedPhase) -{ - std::vector existing_species; - std::vector existing_phases; - development::types::Phase phase1; - phase1.name = "cloud"; - existing_phases.emplace_back(phase1); - - YAML::Node reaction = YAML::Load(R"( - type: "WET_DEPOSITION" - name: "rxn cloud" - )"); - - development::WetDepositionParser parser; - auto errors = parser.Validate(reaction, existing_species, existing_phases); - EXPECT_EQ(errors.size(), 1); - - std::multiset expected = { ConfigParseStatus::RequiredKeyNotFound }; - std::multiset actual; - for (const auto& [status, message] : errors) - { - actual.insert(status); - std::cout << message << " " << configParseStatusToString(status) << std::endl; - } - EXPECT_EQ(actual, expected); -} - -TEST(ValidateWetDeposition, ValidatesWithOptionalScalingFactor) -{ - std::vector existing_species; - std::vector existing_phases; - development::types::Phase phase1; - phase1.name = "cloud"; - existing_phases.emplace_back(phase1); - - YAML::Node reaction = YAML::Load(R"( - type: "WET_DEPOSITION" - "condensed phase": "cloud" - "scaling factor": 5.7 - )"); - - development::WetDepositionParser parser; - auto errors = parser.Validate(reaction, existing_species, existing_phases); - EXPECT_TRUE(errors.empty()); -} diff --git a/test/unit/development/test_parse_phases.cpp b/test/unit/development/test_parse_phases.cpp deleted file mode 100644 index 9b4f52c4..00000000 --- a/test/unit/development/test_parse_phases.cpp +++ /dev/null @@ -1,501 +0,0 @@ -#include -#include - -#include -#include - -#include - -using namespace mechanism_configuration; - -TEST(ParsePhases, ParseValidConfig) -{ - development::Parser parser; - - std::string path = "development_unit_configs/phases/valid_phases"; - std::vector extensions = { ".json", ".yaml" }; - - for (auto& extension : extensions) - { - YAML::Node object = parser.FileToYaml(path + extension); - - auto validation_errors = parser.Validate(object); - EXPECT_EQ(validation_errors.size(), 0) << "Validation errors were: " << validation_errors.size(); - - auto mechanism = parser.Parse(object); - EXPECT_EQ(mechanism.species.size(), 3); - EXPECT_EQ(mechanism.phases.size(), 2); - - EXPECT_EQ(mechanism.phases[0].name, "gas"); - EXPECT_EQ(mechanism.phases[0].species.size(), 2); - EXPECT_EQ(mechanism.phases[0].species[0].name, "A"); - EXPECT_TRUE(mechanism.phases[0].species[0].diffusion_coefficient.has_value()); - EXPECT_DOUBLE_EQ(mechanism.phases[0].species[0].diffusion_coefficient.value(), 4.23e-7); - EXPECT_EQ(mechanism.phases[0].species[1].name, "B"); - EXPECT_FALSE(mechanism.phases[0].species[1].diffusion_coefficient.has_value()); - EXPECT_EQ(mechanism.phases[0].unknown_properties.size(), 1); - EXPECT_EQ(mechanism.phases[0].unknown_properties["__other"], "This is a comment."); - - EXPECT_EQ(mechanism.phases[1].name, "aqueous"); - EXPECT_EQ(mechanism.phases[1].species.size(), 1); - EXPECT_EQ(mechanism.phases[1].species[0].name, "C"); - EXPECT_TRUE(mechanism.phases[1].species[0].diffusion_coefficient.has_value()); - EXPECT_DOUBLE_EQ(mechanism.phases[1].species[0].diffusion_coefficient.value(), 4.23e-7); - EXPECT_EQ(mechanism.phases[1].unknown_properties.size(), 2); - EXPECT_EQ(mechanism.phases[1].unknown_properties["__other1"], "This is another comment."); - EXPECT_EQ(mechanism.phases[1].unknown_properties["__other2"], "This is again a comment."); - } -} - -TEST(ParsePhases, DetectsDuplicatePhases) -{ - development::Parser parser; - - std::string path = "development_unit_configs/phases/duplicate_phases"; - std::vector extensions = { ".json", ".yaml" }; - - for (auto& extension : extensions) - { - YAML::Node object = parser.FileToYaml(path + extension); - - auto validation_errors = parser.Validate(object); - EXPECT_EQ(validation_errors.size(), 2); - - for (const auto& [status, message] : validation_errors) - { - EXPECT_EQ(status, ConfigParseStatus::DuplicatePhasesDetected); - std::cout << message << " " << configParseStatusToString(status) << std::endl; - } - } -} - -TEST(ParsePhases, DetectsMissingRequiredKeys) -{ - development::Parser parser; - - std::string path = "development_unit_configs/phases/missing_required_key"; - std::vector extensions = { ".json", ".yaml" }; - - for (auto& extension : extensions) - { - YAML::Node object = parser.FileToYaml(path + extension); - - auto validation_errors = parser.Validate(object); - EXPECT_EQ(validation_errors.size(), 1); - - std::multiset expected = { ConfigParseStatus::RequiredKeyNotFound }; - std::multiset actual; - for (const auto& [status, message] : validation_errors) - { - actual.insert(status); - std::cout << message << " " << configParseStatusToString(status) << std::endl; - } - EXPECT_EQ(actual, expected); - } -} - -TEST(ParsePhases, DetectsInvalidKeys) -{ - development::Parser parser; - - std::string path = "development_unit_configs/phases/invalid_key"; - std::vector extensions = { ".json", ".yaml" }; - - for (auto& extension : extensions) - { - YAML::Node object = parser.FileToYaml(path + extension); - - auto validation_errors = parser.Validate(object); - EXPECT_EQ(validation_errors.size(), 1); - - std::multiset expected = { ConfigParseStatus::InvalidKey }; - std::multiset actual; - for (const auto& [status, message] : validation_errors) - { - actual.insert(status); - std::cout << message << " " << configParseStatusToString(status) << std::endl; - } - EXPECT_EQ(actual, expected); - } -} - -TEST(ParsePhases, DetectsPhaseRequestingUnknownSpecies) -{ - development::Parser parser; - - std::string path = "development_unit_configs/phases/unknown_species"; - std::vector extensions = { ".json", ".yaml" }; - - for (auto& extension : extensions) - { - YAML::Node object = parser.FileToYaml(path + extension); - - auto validation_errors = parser.Validate(object); - EXPECT_EQ(validation_errors.size(), 1); - - std::multiset expected = { ConfigParseStatus::PhaseRequiresUnknownSpecies }; - std::multiset actual; - for (const auto& [status, message] : validation_errors) - { - actual.insert(status); - std::cout << message << " " << configParseStatusToString(status) << std::endl; - } - EXPECT_EQ(actual, expected); - } -} - -TEST(ParsePhases, DetectsDuplicateSpeciesInPhase) -{ - development::Parser parser; - - std::string path = "development_unit_configs/phases/duplicate_species_in_phase"; - std::vector extensions = { ".json", ".yaml" }; - - for (auto& extension : extensions) - { - YAML::Node object = parser.FileToYaml(path + extension); - - auto validation_errors = parser.Validate(object); - EXPECT_EQ(validation_errors.size(), 2); - - for (const auto& [status, message] : validation_errors) - { - EXPECT_EQ(status, ConfigParseStatus::DuplicateSpeciesInPhaseDetected); - std::cout << message << " " << configParseStatusToString(status) << std::endl; - } - } -} - -TEST(ParsePhases, DetectsInvalidSpeciesObject) -{ - development::Parser parser; - - std::string path = "development_unit_configs/phases/invalid_species_object"; - std::vector extensions = { ".json", ".yaml" }; - - for (auto& extension : extensions) - { - YAML::Node object = parser.FileToYaml(path + extension); - - auto validation_errors = parser.Validate(object); - EXPECT_EQ(validation_errors.size(), 1); - - std::multiset expected = { ConfigParseStatus::RequiredKeyNotFound }; - std::multiset actual; - for (const auto& [status, message] : validation_errors) - { - actual.insert(status); - std::cout << message << " " << configParseStatusToString(status) << std::endl; - } - EXPECT_EQ(actual, expected); - } -} - -TEST(ParsePhases, CanParsePhaseSpeciesProperties) -{ - development::Parser parser; - - std::string path = "development_unit_configs/phases/phase_species_properties"; - std::vector extensions = { ".json", ".yaml" }; - - for (auto& extension : extensions) - { - YAML::Node object = parser.FileToYaml(path + extension); - - auto validation_errors = parser.Validate(object); - EXPECT_EQ(validation_errors.size(), 0) << "Validation errors were: " << validation_errors.size(); - - auto mechanism = parser.Parse(object); - EXPECT_EQ(mechanism.species.size(), 3); - EXPECT_EQ(mechanism.phases.size(), 1); - - const auto& phase = mechanism.phases[0]; - EXPECT_EQ(phase.name, "my phase"); - EXPECT_EQ(phase.species.size(), 3); - EXPECT_EQ(phase.unknown_properties.size(), 1); - EXPECT_EQ(phase.unknown_properties.at("__my custom phase property"), "custom value"); - - // Check first species with diffusion coefficient - EXPECT_EQ(phase.species[0].name, "foo"); - EXPECT_TRUE(phase.species[0].diffusion_coefficient.has_value()); - EXPECT_EQ(phase.species[0].diffusion_coefficient.value(), 4.23e-7); - EXPECT_EQ(phase.species[0].unknown_properties.size(), 0); - - // Check second species with custom properties - EXPECT_EQ(phase.species[1].name, "bar"); - EXPECT_FALSE(phase.species[1].diffusion_coefficient.has_value()); - EXPECT_EQ(phase.species[1].unknown_properties.size(), 2); - EXPECT_EQ(phase.species[1].unknown_properties.at("__custom property"), "0.5"); - EXPECT_EQ(phase.species[1].unknown_properties.at("__another custom property"), "value"); - - // Check third species (simple string format) - EXPECT_EQ(phase.species[2].name, "baz"); - EXPECT_FALSE(phase.species[2].diffusion_coefficient.has_value()); - EXPECT_EQ(phase.species[2].unknown_properties.size(), 0); - } -} - -TEST(ValidatePhases, ReturnsEmptyErrorsForValidPhases) -{ - std::vector existing_species; - development::types::Species species1; - species1.name = "A"; - existing_species.emplace_back(species1); - - development::types::Species species2; - species2.name = "B"; - existing_species.emplace_back(species2); - - YAML::Node phases_list = YAML::Load(R"( - - name: "gas" - species: - - name: "A" - - name: "B" - "diffusion coefficient [m2 s-1]": 1.5e-05 - - name: "aqueous" - species: - - name: "A" - "diffusion coefficient [m2 s-1]": 2.3e-06 - )"); - - auto errors = development::ValidatePhases(phases_list, existing_species); - EXPECT_TRUE(errors.empty()); -} - -TEST(ValidatePhases, DetectsMissingPhaseName) -{ - std::vector existing_species; - development::types::Species species1; - species1.name = "A"; - existing_species.emplace_back(species1); - - YAML::Node phases_list = YAML::Load(R"( - - species: - - name: "A" - - name: "aqueous" - species: - - name: "A" - )"); - - auto errors = development::ValidatePhases(phases_list, existing_species); - EXPECT_EQ(errors.size(), 1); - - std::multiset expected = { ConfigParseStatus::RequiredKeyNotFound }; - std::multiset actual; - for (const auto& [status, message] : errors) - { - actual.insert(status); - std::cout << message << " " << configParseStatusToString(status) << std::endl; - } - EXPECT_EQ(actual, expected); -} - -TEST(ValidatePhases, DetectsMissingSpeciesList) -{ - std::vector existing_species; - development::types::Species species1; - species1.name = "A"; - existing_species.emplace_back(species1); - - YAML::Node phases_list = YAML::Load(R"( - - name: "gas" - - name: "aqueous" - species: - - name: "A" - )"); - - auto errors = development::ValidatePhases(phases_list, existing_species); - EXPECT_EQ(errors.size(), 1); - - std::multiset expected = { ConfigParseStatus::RequiredKeyNotFound }; - std::multiset actual; - for (const auto& [status, message] : errors) - { - actual.insert(status); - std::cout << message << " " << configParseStatusToString(status) << std::endl; - } - EXPECT_EQ(actual, expected); -} - -TEST(ValidatePhases, DetectsInvalidKeysInPhase) -{ - std::vector existing_species; - development::types::Species species1; - species1.name = "A"; - existing_species.emplace_back(species1); - - YAML::Node phases_list = YAML::Load(R"( - - name: "gas" - SPECIES: - - name: "A" - )"); - - auto errors = development::ValidatePhases(phases_list, existing_species); - EXPECT_EQ(errors.size(), 2); - - std::multiset expected = { ConfigParseStatus::InvalidKey, ConfigParseStatus::RequiredKeyNotFound }; - std::multiset actual; - for (const auto& [status, message] : errors) - { - actual.insert(status); - std::cout << message << " " << configParseStatusToString(status) << std::endl; - } - EXPECT_EQ(actual, expected); -} - -TEST(ValidatePhases, DetectsMissingSpeciesNameInPhase) -{ - std::vector existing_species; - development::types::Species species1; - species1.name = "A"; - existing_species.emplace_back(species1); - - YAML::Node phases_list = YAML::Load(R"( - - name: "gas" - species: - - "diffusion coefficient [m2 s-1]": 1.5e-05 - - name: "A" - )"); - - auto errors = development::ValidatePhases(phases_list, existing_species); - EXPECT_EQ(errors.size(), 1); - - std::multiset expected = { ConfigParseStatus::RequiredKeyNotFound }; - std::multiset actual; - for (const auto& [status, message] : errors) - { - actual.insert(status); - std::cout << message << " " << configParseStatusToString(status) << std::endl; - } - EXPECT_EQ(actual, expected); -} - -TEST(ValidatePhases, DetectsInvalidKeysInSpecies) -{ - std::vector existing_species; - development::types::Species species1; - species1.name = "A"; - existing_species.emplace_back(species1); - - YAML::Node phases_list = YAML::Load(R"( - - name: "gas" - species: - - name: "A" - Coefficient: 4.23e-5 - )"); - - auto errors = development::ValidatePhases(phases_list, existing_species); - EXPECT_EQ(errors.size(), 1); - - std::multiset expected = { ConfigParseStatus::InvalidKey }; - std::multiset actual; - for (const auto& [status, message] : errors) - { - actual.insert(status); - std::cout << message << " " << configParseStatusToString(status) << std::endl; - } - EXPECT_EQ(actual, expected); -} - -TEST(ValidatePhases, DetectsDuplicateSpeciesInPhase) -{ - std::vector existing_species; - development::types::Species species1; - species1.name = "FOO"; - existing_species.emplace_back(species1); - - YAML::Node phases_list = YAML::Load(R"( - - name: "gas" - species: - - name: "FOO" - - name: "FOO" - "diffusion coefficient [m2 s-1]": 1.5e-05 - )"); - - auto errors = development::ValidatePhases(phases_list, existing_species); - EXPECT_EQ(errors.size(), 2); // Two entries for the duplicate species - - for (const auto& [status, message] : errors) - { - EXPECT_EQ(status, ConfigParseStatus::DuplicateSpeciesInPhaseDetected); - EXPECT_NE(message.find("FOO"), std::string::npos); // Error message should contain species name - } -} - -TEST(ValidatePhases, DetectsUnknownSpeciesInPhase) -{ - std::vector existing_species; - development::types::Species species1; - species1.name = "A"; - existing_species.emplace_back(species1); - - YAML::Node phases_list = YAML::Load(R"( - - name: "gas" - species: - - name: "A" - - name: "FOO" - )"); - - auto errors = development::ValidatePhases(phases_list, existing_species); - EXPECT_EQ(errors.size(), 1); - - std::multiset expected = { ConfigParseStatus::PhaseRequiresUnknownSpecies }; - std::multiset actual; - for (const auto& [status, message] : errors) - { - actual.insert(status); - std::cout << message << " " << configParseStatusToString(status) << std::endl; - } - EXPECT_EQ(actual, expected); -} - -TEST(ValidatePhases, DetectsDuplicatePhaseNames) -{ - std::vector existing_species; - development::types::Species species1; - species1.name = "A"; - existing_species.emplace_back(species1); - - development::types::Species species2; - species2.name = "B"; - existing_species.emplace_back(species2); - - YAML::Node phases_list = YAML::Load(R"( - - name: "gas" - species: - - name: "A" - - name: "aqueous" - species: - - name: "B" - - name: "gas" - species: - - name: "B" - )"); - - auto errors = development::ValidatePhases(phases_list, existing_species); - EXPECT_EQ(errors.size(), 2); // Two entries for the duplicate phase - - for (const auto& [status, message] : errors) - { - EXPECT_EQ(status, ConfigParseStatus::DuplicatePhasesDetected); - EXPECT_NE(message.find("gas"), std::string::npos); // Error message should contain phase name - } -} - -TEST(ValidatePhases, ValidatesAllSpeciesOptionalKeys) -{ - std::vector existing_species; - development::types::Species species1; - species1.name = "FOO"; - existing_species.emplace_back(species1); - - YAML::Node phases_list = YAML::Load(R"( - - name: "organic" - species: - - name: "FOO" - "diffusion coefficient [m2 s-1]": 1.46e-05 - )"); - - auto errors = development::ValidatePhases(phases_list, existing_species); - EXPECT_TRUE(errors.empty()); -} \ No newline at end of file diff --git a/test/unit/development/test_parse_species.cpp b/test/unit/development/test_parse_species.cpp deleted file mode 100644 index e6661a0c..00000000 --- a/test/unit/development/test_parse_species.cpp +++ /dev/null @@ -1,262 +0,0 @@ -#include -#include - -#include -#include - -#include - -using namespace mechanism_configuration; - -TEST(ParseSpecies, ParseValidConfig) -{ - development::Parser parser; - - std::string path = "development_unit_configs/species/valid_species"; - std::vector extensions = { ".json", ".yaml" }; - - for (auto& extension : extensions) - { - YAML::Node object = parser.FileToYaml(path + extension); - - auto validation_errors = parser.Validate(object); - EXPECT_EQ(validation_errors.size(), 0) << "Validation errors were: " << validation_errors.size(); - - auto mechanism = parser.Parse(object); - EXPECT_EQ(mechanism.species.size(), 3); - EXPECT_EQ(mechanism.species[0].name, "A"); - EXPECT_EQ(mechanism.species[0].unknown_properties.size(), 2); - EXPECT_EQ(mechanism.species[0].unknown_properties["__absolute tolerance"], "1.0e-30"); - EXPECT_EQ(mechanism.species[0].unknown_properties["__long name"], "ozone"); - EXPECT_EQ(mechanism.species[0].tracer_type.has_value(), false); - EXPECT_EQ(mechanism.species[0].is_third_body.has_value(), true); - EXPECT_EQ(mechanism.species[0].is_third_body.value(), true); - - EXPECT_EQ(mechanism.species[1].name, "H2O2"); - EXPECT_EQ(mechanism.species[1].henrys_law_constant_298.has_value(), true); - EXPECT_EQ(mechanism.species[1].henrys_law_constant_298.value(), 1.011596348); - EXPECT_EQ(mechanism.species[1].henrys_law_constant_exponential_factor.has_value(), true); - EXPECT_EQ(mechanism.species[1].henrys_law_constant_exponential_factor.value(), 6340); - EXPECT_EQ(mechanism.species[1].diffusion_coefficient.has_value(), true); - EXPECT_EQ(mechanism.species[1].diffusion_coefficient.value(), 1.46e-05); - EXPECT_EQ(mechanism.species[1].n_star.has_value(), true); - EXPECT_EQ(mechanism.species[1].n_star.value(), 1.74); - EXPECT_EQ(mechanism.species[1].molecular_weight.has_value(), true); - EXPECT_EQ(mechanism.species[1].molecular_weight.value(), 0.0340147); - EXPECT_EQ(mechanism.species[1].density.has_value(), true); - EXPECT_EQ(mechanism.species[1].density.value(), 1000.0); - EXPECT_EQ(mechanism.species[1].constant_concentration.has_value(), true); - EXPECT_EQ(mechanism.species[1].constant_concentration.value(), 2.5e19); - EXPECT_EQ(mechanism.species[1].unknown_properties.size(), 1); - EXPECT_EQ(mechanism.species[1].unknown_properties["__absolute tolerance"], "1.0e-10"); - - EXPECT_EQ(mechanism.species[2].name, "aerosol stuff"); - EXPECT_EQ(mechanism.species[2].molecular_weight.has_value(), true); - EXPECT_EQ(mechanism.species[2].molecular_weight.value(), 0.5); - EXPECT_EQ(mechanism.species[2].density.has_value(), true); - EXPECT_EQ(mechanism.species[2].density.value(), 1000.0); - EXPECT_EQ(mechanism.species[2].constant_mixing_ratio.has_value(), true); - EXPECT_EQ(mechanism.species[2].constant_mixing_ratio.value(), 1.0e-6); - EXPECT_EQ(mechanism.species[2].unknown_properties.size(), 1); - EXPECT_EQ(mechanism.species[2].unknown_properties["__absolute tolerance"], "1.0e-20"); - } -} - -TEST(ParseSpecies, DetectsDuplicateSpecies) -{ - development::Parser parser; - - std::string path = "development_unit_configs/species/duplicate_species"; - std::vector extensions = { ".json", ".yaml" }; - - for (auto& extension : extensions) - { - YAML::Node object = parser.FileToYaml(path + extension); - - auto validation_errors = parser.Validate(object); - EXPECT_EQ(validation_errors.size(), 4); - - for (const auto& [status, message] : validation_errors) - { - EXPECT_EQ(status, ConfigParseStatus::DuplicateSpeciesDetected); - std::cout << message << " " << configParseStatusToString(status) << std::endl; - } - } -} - -TEST(ParseSpecies, DetectsMissingRequiredKeys) -{ - development::Parser parser; - - std::string path = "development_unit_configs/species/missing_required_key"; - std::vector extensions = { ".json", ".yaml" }; - - for (auto& extension : extensions) - { - YAML::Node object = parser.FileToYaml(path + extension); - - auto validation_errors = parser.Validate(object); - EXPECT_EQ(validation_errors.size(), 2); - - std::multiset expected = { ConfigParseStatus::RequiredKeyNotFound, ConfigParseStatus::InvalidKey }; - std::multiset actual; - for (const auto& [status, message] : validation_errors) - { - actual.insert(status); - std::cout << message << " " << configParseStatusToString(status) << std::endl; - } - EXPECT_EQ(actual, expected); - } -} - -TEST(ParseSpecies, DetectsInvalidKeys) -{ - development::Parser parser; - - std::string path = "development_unit_configs/species/invalid_key"; - std::vector extensions = { ".json", ".yaml" }; - - for (auto& extension : extensions) - { - YAML::Node object = parser.FileToYaml(path + extension); - - auto validation_errors = parser.Validate(object); - EXPECT_EQ(validation_errors.size(), 1); - - std::multiset expected = { ConfigParseStatus::InvalidKey }; - std::multiset actual; - for (const auto& [status, message] : validation_errors) - { - actual.insert(status); - std::cout << message << " " << configParseStatusToString(status) << std::endl; - } - EXPECT_EQ(actual, expected); - } -} - -TEST(ValidateSpecies, ReturnsEmptyErrorsForValidSpecies) -{ - YAML::Node species_list = YAML::Load(R"( - - "name": "A" - "absolute tolerance": "1.0e-30" - "is third body": true - - "name": "B" - "molecular weight [kg mol-1]": 0.034 - "density [kg m-3]": 1000.0 - )"); - - auto errors = development::ValidateSpecies(species_list); - EXPECT_TRUE(errors.empty()); -} - -TEST(ValidateSpecies, DetectsMissingNameKey) -{ - YAML::Node species_list = YAML::Load(R"( - - "absolute tolerance": "1.0e-30" - "is third body": true - - "name": "B" - "molecular weight [kg mol-1]": 0.034 - )"); - - auto errors = development::ValidateSpecies(species_list); - EXPECT_FALSE(errors.empty()); - EXPECT_EQ(errors.size(), 1); - - std::multiset expected = { ConfigParseStatus::RequiredKeyNotFound }; - std::multiset actual; - for (const auto& [status, message] : errors) - { - actual.insert(status); - std::cout << message << " " << configParseStatusToString(status) << std::endl; - } - EXPECT_EQ(actual, expected); -} - -TEST(ValidateSpecies, DetectsInvalidKeysInSpecies) -{ - YAML::Node species_list = YAML::Load(R"( - - "name": "A" - "Absolute Tolerance": 1.0e-30 - - "name": "B" - "absolute tolerance": 1.0e-30 - )"); - - auto errors = development::ValidateSpecies(species_list); - EXPECT_EQ(errors.size(), 1); - - std::multiset expected = { ConfigParseStatus::InvalidKey }; - std::multiset actual; - for (const auto& [status, message] : errors) - { - actual.insert(status); - std::cout << message << " " << configParseStatusToString(status) << std::endl; - } - EXPECT_EQ(actual, expected); -} - -TEST(ValidateSpecies, DetectsDuplicateSpeciesNames) -{ - YAML::Node species_list = YAML::Load(R"( - - "name": "A" - "absolute tolerance": "1.0e-30" - - "name": "B" - "molecular weight [kg mol-1]": 0.034 - - "name": "A" - "density [kg m-3]": 1000.0 - )"); - - auto errors = development::ValidateSpecies(species_list); - EXPECT_EQ(errors.size(), 2); - - std::multiset expected = { ConfigParseStatus::DuplicateSpeciesDetected, - ConfigParseStatus::DuplicateSpeciesDetected }; - std::multiset actual; - for (const auto& [status, message] : errors) - { - actual.insert(status); - EXPECT_NE(message.find("A"), std::string::npos); // Error message should contain species "name" - std::cout << message << " " << configParseStatusToString(status) << std::endl; - } - EXPECT_EQ(actual, expected); -} - -TEST(ValidateSpecies, DetectsMultipleDuplicateSpecies) -{ - YAML::Node species_list = YAML::Load(R"( - - "name": "A" - - "name": "B" - - "name": "A" - - "name": "C" - - "name": "B" - )"); - - auto errors = development::ValidateSpecies(species_list); - EXPECT_EQ(errors.size(), 4); // 2 for "A" duplicates + 2 for "B" duplicates - - for (const auto& [status, message] : errors) - { - EXPECT_EQ(status, ConfigParseStatus::DuplicateSpeciesDetected); - std::cout << message << " " << configParseStatusToString(status) << std::endl; - } -} - -TEST(ValidateSpecies, ValidatesAllOptionalKeys) -{ - YAML::Node species_list = YAML::Load(R"( - - "name": "CompleteSpecies" - "absolute tolerance": "1.0e-30" - "diffusion coefficient [m2 s-1]": 1.46e-05 - "molecular weight [kg mol-1]": 0.0340147 - "HLC(298K) [mol m-3 Pa-1]": 1.011596348 - "HLC exponential factor [K]": 6340 - "N star": 1.74 - "density [kg m-3]": 1000.0 - "tracer type": "CHEM" - "constant concentration [mol m-3]": 2.5e19 - "constant mixing ratio [mol mol-1]": 1.0e-6 - "is third body": true - )"); - - auto errors = development::ValidateSpecies(species_list); - EXPECT_TRUE(errors.empty()); -} \ No newline at end of file diff --git a/test/unit/test_validate.cpp b/test/unit/test_validate.cpp new file mode 100644 index 00000000..583913c8 --- /dev/null +++ b/test/unit/test_validate.cpp @@ -0,0 +1,123 @@ +// Copyright (C) 2023–2026 University Corporation for Atmospheric Research +// University of Illinois at Urbana-Champaign +// SPDX-License-Identifier: Apache-2.0 + +#include + +#include + +using namespace mechanism_configuration; + +namespace +{ + types::Species species(const std::string& name) + { + types::Species s; + s.name = name; + return s; + } + types::PhaseSpecies phase_species(const std::string& name) + { + types::PhaseSpecies ps; + ps.name = name; + return ps; + } + types::ReactionComponent component(const std::string& name) + { + types::ReactionComponent c; + c.name = name; + return c; + } + + // gas phase {A, B}, aqueous phase {C}; species A, B, C. + Mechanism BaseMechanism() + { + Mechanism m; + m.species = { species("A"), species("B"), species("C") }; + types::Phase gas; + gas.name = "gas"; + gas.species = { phase_species("A"), phase_species("B") }; + types::Phase aqueous; + aqueous.name = "aqueous"; + aqueous.species = { phase_species("C") }; + m.phases = { gas, aqueous }; + return m; + } + + bool HasCode(const Errors& errors, ErrorCode code) + { + for (const auto& [c, m] : errors) + if (c == code) + return true; + return false; + } +} // namespace + +// An in-code mechanism (never parsed from a file) can be validated. +TEST(Validate, AcceptsValidInCodeMechanism) +{ + Mechanism m = BaseMechanism(); + types::Arrhenius rxn; + rxn.gas_phase = "gas"; + rxn.reactants = { component("A") }; + rxn.products = { component("B") }; + m.reactions.arrhenius = { rxn }; + + EXPECT_TRUE(Validate(m).empty()); +} + +TEST(Validate, DetectsUnknownSpeciesInReaction) +{ + Mechanism m = BaseMechanism(); + types::Arrhenius rxn; + rxn.gas_phase = "gas"; + rxn.reactants = { component("Z") }; // not in the species list + m.reactions.arrhenius = { rxn }; + + auto errors = Validate(m); + EXPECT_TRUE(HasCode(errors, ErrorCode::ReactionRequiresUnknownSpecies)); +} + +TEST(Validate, DetectsReactantNotInReactionPhase) +{ + Mechanism m = BaseMechanism(); + types::Arrhenius rxn; + rxn.gas_phase = "gas"; + rxn.reactants = { component("C") }; // C is known, but only in the aqueous phase + m.reactions.arrhenius = { rxn }; + + auto errors = Validate(m); + EXPECT_TRUE(HasCode(errors, ErrorCode::RequestedSpeciesNotRegisteredInPhase)); +} + +// Products may reference species from any phase. +TEST(Validate, AllowsCrossPhaseProduct) +{ + Mechanism m = BaseMechanism(); + types::Arrhenius rxn; + rxn.gas_phase = "gas"; + rxn.reactants = { component("A") }; + rxn.products = { component("C") }; // C lives in aqueous; allowed as a product + m.reactions.arrhenius = { rxn }; + + EXPECT_TRUE(Validate(m).empty()); +} + +TEST(Validate, DetectsDuplicateSpecies) +{ + Mechanism m = BaseMechanism(); + m.species.push_back(species("A")); // duplicate + + EXPECT_TRUE(HasCode(Validate(m), ErrorCode::DuplicateSpeciesDetected)); +} + +TEST(Validate, DetectsUnknownPhase) +{ + Mechanism m = BaseMechanism(); + types::Arrhenius rxn; + rxn.gas_phase = "stratosphere"; // no such phase + rxn.reactants = { component("A") }; + m.reactions.arrhenius = { rxn }; + + EXPECT_TRUE(HasCode(Validate(m), ErrorCode::UnknownPhase)); +} diff --git a/test/unit/v0/test_arrhenius_config.cpp b/test/unit/v0/test_arrhenius_config.cpp index d3f2267e..f32fa65d 100644 --- a/test/unit/v0/test_arrhenius_config.cpp +++ b/test/unit/v0/test_arrhenius_config.cpp @@ -1,6 +1,10 @@ -#include -#include -#include +// Copyright (C) 2023–2026 University Corporation for Atmospheric Research +// University of Illinois at Urbana-Champaign +// SPDX-License-Identifier: Apache-2.0 + +#include "detail/constants.hpp" +#include "detail/conversions.hpp" +#include "detail/v0/parser.hpp" #include @@ -15,31 +19,31 @@ TEST(ArrheniusConfig, DetectsInvalidConfig) std::string file = "./v0_unit_configs/arrhenius/missing_reactants/config" + extension; auto parsed = parser.Parse(file); EXPECT_FALSE(parsed); - EXPECT_EQ(parsed.errors.size(), 1); - EXPECT_EQ(parsed.errors[0].first, ConfigParseStatus::RequiredKeyNotFound); - for (auto& error : parsed.errors) + EXPECT_EQ(parsed.error().size(), 1); + EXPECT_EQ(parsed.error()[0].first, ErrorCode::RequiredKeyNotFound); + for (auto& error : parsed.error()) { - std::cout << error.second << " " << configParseStatusToString(error.first) << std::endl; + std::cout << error.second << " " << ErrorCodeToString(error.first) << std::endl; } file = "./v0_unit_configs/arrhenius/missing_products/config" + extension; parsed = parser.Parse(file); EXPECT_FALSE(parsed); - EXPECT_EQ(parsed.errors.size(), 1); - EXPECT_EQ(parsed.errors[0].first, ConfigParseStatus::RequiredKeyNotFound); - for (auto& error : parsed.errors) + EXPECT_EQ(parsed.error().size(), 1); + EXPECT_EQ(parsed.error()[0].first, ErrorCode::RequiredKeyNotFound); + for (auto& error : parsed.error()) { - std::cout << error.second << " " << configParseStatusToString(error.first) << std::endl; + std::cout << error.second << " " << ErrorCodeToString(error.first) << std::endl; } file = "./v0_unit_configs/arrhenius/mutually_exclusive/config" + extension; parsed = parser.Parse(file); EXPECT_FALSE(parsed); - EXPECT_EQ(parsed.errors.size(), 1); - EXPECT_EQ(parsed.errors[0].first, ConfigParseStatus::MutuallyExclusiveOption); - for (auto& error : parsed.errors) + EXPECT_EQ(parsed.error().size(), 1); + EXPECT_EQ(parsed.error()[0].first, ErrorCode::MutuallyExclusiveOption); + for (auto& error : parsed.error()) { - std::cout << error.second << " " << configParseStatusToString(error.first) << std::endl; + std::cout << error.second << " " << ErrorCodeToString(error.first) << std::endl; } } } @@ -54,17 +58,17 @@ TEST(ArrheniusConfig, ParseConfig) std::string file = "./v0_unit_configs/arrhenius/valid/config" + extension; auto parsed = parser.Parse(file); EXPECT_TRUE(parsed); - v0::types::Mechanism mechanism = *parsed; + Mechanism mechanism = *parsed; // first reaction { EXPECT_EQ(mechanism.reactions.arrhenius[0].reactants.size(), 2); - EXPECT_EQ(mechanism.reactions.arrhenius[0].reactants[0].species_name, "foo"); - EXPECT_EQ(mechanism.reactions.arrhenius[0].reactants[1].species_name, "quz"); + EXPECT_EQ(mechanism.reactions.arrhenius[0].reactants[0].name, "foo"); + EXPECT_EQ(mechanism.reactions.arrhenius[0].reactants[1].name, "quz"); EXPECT_EQ(mechanism.reactions.arrhenius[0].products.size(), 2); - EXPECT_EQ(mechanism.reactions.arrhenius[0].products[0].species_name, "bar"); + EXPECT_EQ(mechanism.reactions.arrhenius[0].products[0].name, "bar"); EXPECT_EQ(mechanism.reactions.arrhenius[0].products[0].coefficient, 1.0); - EXPECT_EQ(mechanism.reactions.arrhenius[0].products[1].species_name, "baz"); + EXPECT_EQ(mechanism.reactions.arrhenius[0].products[1].name, "baz"); EXPECT_EQ(mechanism.reactions.arrhenius[0].products[1].coefficient, 3.2); EXPECT_EQ( mechanism.reactions.arrhenius[0].A, 1.0 * conversions::MolesM3ToMoleculesCm3 * conversions::MolesM3ToMoleculesCm3); @@ -77,12 +81,12 @@ TEST(ArrheniusConfig, ParseConfig) // second reaction { EXPECT_EQ(mechanism.reactions.arrhenius[1].reactants.size(), 2); - EXPECT_EQ(mechanism.reactions.arrhenius[1].reactants[0].species_name, "bar"); - EXPECT_EQ(mechanism.reactions.arrhenius[1].reactants[1].species_name, "baz"); + EXPECT_EQ(mechanism.reactions.arrhenius[1].reactants[0].name, "bar"); + EXPECT_EQ(mechanism.reactions.arrhenius[1].reactants[1].name, "baz"); EXPECT_EQ(mechanism.reactions.arrhenius[1].products.size(), 2); - EXPECT_EQ(mechanism.reactions.arrhenius[1].products[0].species_name, "bar"); + EXPECT_EQ(mechanism.reactions.arrhenius[1].products[0].name, "bar"); EXPECT_EQ(mechanism.reactions.arrhenius[1].products[0].coefficient, 0.5); - EXPECT_EQ(mechanism.reactions.arrhenius[1].products[1].species_name, "foo"); + EXPECT_EQ(mechanism.reactions.arrhenius[1].products[1].name, "foo"); EXPECT_EQ(mechanism.reactions.arrhenius[1].products[1].coefficient, 1.0); EXPECT_EQ(mechanism.reactions.arrhenius[1].A, 32.1 * conversions::MolesM3ToMoleculesCm3); EXPECT_EQ(mechanism.reactions.arrhenius[1].B, -2.3); @@ -94,12 +98,12 @@ TEST(ArrheniusConfig, ParseConfig) // third reaction { EXPECT_EQ(mechanism.reactions.arrhenius[2].reactants.size(), 2); - EXPECT_EQ(mechanism.reactions.arrhenius[2].reactants[0].species_name, "bar"); - EXPECT_EQ(mechanism.reactions.arrhenius[2].reactants[1].species_name, "baz"); + EXPECT_EQ(mechanism.reactions.arrhenius[2].reactants[0].name, "bar"); + EXPECT_EQ(mechanism.reactions.arrhenius[2].reactants[1].name, "baz"); EXPECT_EQ(mechanism.reactions.arrhenius[2].products.size(), 2); - EXPECT_EQ(mechanism.reactions.arrhenius[2].products[0].species_name, "bar"); + EXPECT_EQ(mechanism.reactions.arrhenius[2].products[0].name, "bar"); EXPECT_EQ(mechanism.reactions.arrhenius[2].products[0].coefficient, 0.5); - EXPECT_EQ(mechanism.reactions.arrhenius[2].products[1].species_name, "foo"); + EXPECT_EQ(mechanism.reactions.arrhenius[2].products[1].name, "foo"); EXPECT_EQ(mechanism.reactions.arrhenius[2].products[1].coefficient, 1.0); EXPECT_EQ(mechanism.reactions.arrhenius[2].A, 32.1 * conversions::MolesM3ToMoleculesCm3); EXPECT_EQ(mechanism.reactions.arrhenius[2].B, -2.3); @@ -119,13 +123,13 @@ TEST(ArrheniusConfig, DetectsNonstandardKeys) std::string file = "./v0_unit_configs/arrhenius/contains_nonstandard_key/config" + extension; auto parsed = parser.Parse(file); EXPECT_FALSE(parsed); - EXPECT_EQ(parsed.errors.size(), 3); - EXPECT_EQ(parsed.errors[0].first, ConfigParseStatus::InvalidKey); - EXPECT_EQ(parsed.errors[1].first, ConfigParseStatus::InvalidKey); - EXPECT_EQ(parsed.errors[2].first, ConfigParseStatus::InvalidKey); - for (auto& error : parsed.errors) + EXPECT_EQ(parsed.error().size(), 3); + EXPECT_EQ(parsed.error()[0].first, ErrorCode::InvalidKey); + EXPECT_EQ(parsed.error()[1].first, ErrorCode::InvalidKey); + EXPECT_EQ(parsed.error()[2].first, ErrorCode::InvalidKey); + for (auto& error : parsed.error()) { - std::cout << error.second << " " << configParseStatusToString(error.first) << std::endl; + std::cout << error.second << " " << ErrorCodeToString(error.first) << std::endl; } } } @@ -139,11 +143,11 @@ TEST(ArrheniusConfig, DetectsNonstandardProductCoefficient) std::string file = "./v0_unit_configs/arrhenius/nonstandard_product_coef/config" + extension; auto parsed = parser.Parse(file); EXPECT_FALSE(parsed); - EXPECT_EQ(parsed.errors.size(), 1); - EXPECT_EQ(parsed.errors[0].first, ConfigParseStatus::InvalidKey); - for (auto& error : parsed.errors) + EXPECT_EQ(parsed.error().size(), 1); + EXPECT_EQ(parsed.error()[0].first, ErrorCode::InvalidKey); + for (auto& error : parsed.error()) { - std::cout << error.second << " " << configParseStatusToString(error.first) << std::endl; + std::cout << error.second << " " << ErrorCodeToString(error.first) << std::endl; } } } @@ -157,11 +161,11 @@ TEST(ArrheniusConfig, DetectsNonstandardReactantCoefficient) std::string file = "./v0_unit_configs/arrhenius/nonstandard_reactant_coef/config" + extension; auto parsed = parser.Parse(file); EXPECT_FALSE(parsed); - EXPECT_EQ(parsed.errors.size(), 1); - EXPECT_EQ(parsed.errors[0].first, ConfigParseStatus::InvalidKey); - for (auto& error : parsed.errors) + EXPECT_EQ(parsed.error().size(), 1); + EXPECT_EQ(parsed.error()[0].first, ErrorCode::InvalidKey); + for (auto& error : parsed.error()) { - std::cout << error.second << " " << configParseStatusToString(error.first) << std::endl; + std::cout << error.second << " " << ErrorCodeToString(error.first) << std::endl; } } } diff --git a/test/unit/v0/test_branched_config.cpp b/test/unit/v0/test_branched_config.cpp index 507d55d2..574f5df0 100644 --- a/test/unit/v0/test_branched_config.cpp +++ b/test/unit/v0/test_branched_config.cpp @@ -1,6 +1,10 @@ -#include -#include -#include +// Copyright (C) 2023–2026 University Corporation for Atmospheric Research +// University of Illinois at Urbana-Champaign +// SPDX-License-Identifier: Apache-2.0 + +#include "detail/constants.hpp" +#include "detail/conversions.hpp" +#include "detail/v0/parser.hpp" #include @@ -15,43 +19,43 @@ TEST(BranchedConfig, DetectsInvalidConfig) std::string file = "./v0_unit_configs/branched/missing_reactants/config" + extension; auto parsed = parser.Parse(file); EXPECT_FALSE(parsed); - EXPECT_EQ(parsed.errors.size(), 5); - EXPECT_EQ(parsed.errors[0].first, ConfigParseStatus::RequiredKeyNotFound); - EXPECT_EQ(parsed.errors[1].first, ConfigParseStatus::RequiredKeyNotFound); - EXPECT_EQ(parsed.errors[2].first, ConfigParseStatus::RequiredKeyNotFound); - EXPECT_EQ(parsed.errors[3].first, ConfigParseStatus::RequiredKeyNotFound); - EXPECT_EQ(parsed.errors[4].first, ConfigParseStatus::RequiredKeyNotFound); - for (auto& error : parsed.errors) + EXPECT_EQ(parsed.error().size(), 5); + EXPECT_EQ(parsed.error()[0].first, ErrorCode::RequiredKeyNotFound); + EXPECT_EQ(parsed.error()[1].first, ErrorCode::RequiredKeyNotFound); + EXPECT_EQ(parsed.error()[2].first, ErrorCode::RequiredKeyNotFound); + EXPECT_EQ(parsed.error()[3].first, ErrorCode::RequiredKeyNotFound); + EXPECT_EQ(parsed.error()[4].first, ErrorCode::RequiredKeyNotFound); + for (auto& error : parsed.error()) { - std::cout << error.second << " " << configParseStatusToString(error.first) << std::endl; + std::cout << error.second << " " << ErrorCodeToString(error.first) << std::endl; } file = "./v0_unit_configs/branched/missing_alkoxy_products/config" + extension; parsed = parser.Parse(file); EXPECT_FALSE(parsed); - EXPECT_EQ(parsed.errors.size(), 5); - EXPECT_EQ(parsed.errors[0].first, ConfigParseStatus::RequiredKeyNotFound); - EXPECT_EQ(parsed.errors[1].first, ConfigParseStatus::RequiredKeyNotFound); - EXPECT_EQ(parsed.errors[2].first, ConfigParseStatus::RequiredKeyNotFound); - EXPECT_EQ(parsed.errors[3].first, ConfigParseStatus::RequiredKeyNotFound); - EXPECT_EQ(parsed.errors[4].first, ConfigParseStatus::RequiredKeyNotFound); - for (auto& error : parsed.errors) + EXPECT_EQ(parsed.error().size(), 5); + EXPECT_EQ(parsed.error()[0].first, ErrorCode::RequiredKeyNotFound); + EXPECT_EQ(parsed.error()[1].first, ErrorCode::RequiredKeyNotFound); + EXPECT_EQ(parsed.error()[2].first, ErrorCode::RequiredKeyNotFound); + EXPECT_EQ(parsed.error()[3].first, ErrorCode::RequiredKeyNotFound); + EXPECT_EQ(parsed.error()[4].first, ErrorCode::RequiredKeyNotFound); + for (auto& error : parsed.error()) { - std::cout << error.second << " " << configParseStatusToString(error.first) << std::endl; + std::cout << error.second << " " << ErrorCodeToString(error.first) << std::endl; } file = "./v0_unit_configs/branched/missing_nitrate_products/config" + extension; parsed = parser.Parse(file); EXPECT_FALSE(parsed); - EXPECT_EQ(parsed.errors.size(), 5); - EXPECT_EQ(parsed.errors[1].first, ConfigParseStatus::RequiredKeyNotFound); - EXPECT_EQ(parsed.errors[2].first, ConfigParseStatus::RequiredKeyNotFound); - EXPECT_EQ(parsed.errors[3].first, ConfigParseStatus::RequiredKeyNotFound); - EXPECT_EQ(parsed.errors[4].first, ConfigParseStatus::RequiredKeyNotFound); - EXPECT_EQ(parsed.errors[0].first, ConfigParseStatus::RequiredKeyNotFound); - for (auto& error : parsed.errors) + EXPECT_EQ(parsed.error().size(), 5); + EXPECT_EQ(parsed.error()[1].first, ErrorCode::RequiredKeyNotFound); + EXPECT_EQ(parsed.error()[2].first, ErrorCode::RequiredKeyNotFound); + EXPECT_EQ(parsed.error()[3].first, ErrorCode::RequiredKeyNotFound); + EXPECT_EQ(parsed.error()[4].first, ErrorCode::RequiredKeyNotFound); + EXPECT_EQ(parsed.error()[0].first, ErrorCode::RequiredKeyNotFound); + for (auto& error : parsed.error()) { - std::cout << error.second << " " << configParseStatusToString(error.first) << std::endl; + std::cout << error.second << " " << ErrorCodeToString(error.first) << std::endl; } } } @@ -66,28 +70,28 @@ TEST(BranchedConfig, ParseConfig) std::string file = "./v0_unit_configs/branched/valid/config" + extension; auto parsed = parser.Parse(file); EXPECT_TRUE(parsed); - v0::types::Mechanism mechanism = *parsed; + Mechanism mechanism = *parsed; auto& process_vector = mechanism.reactions.branched; EXPECT_EQ(process_vector.size(), 2); // first reaction EXPECT_EQ(process_vector[0].reactants.size(), 2); - EXPECT_EQ(process_vector[0].reactants[0].species_name, "foo"); + EXPECT_EQ(process_vector[0].reactants[0].name, "foo"); EXPECT_EQ(process_vector[0].reactants[0].coefficient, 1.0); - EXPECT_EQ(process_vector[0].reactants[1].species_name, "quz"); + EXPECT_EQ(process_vector[0].reactants[1].name, "quz"); EXPECT_EQ(process_vector[0].reactants[1].coefficient, 2.0); EXPECT_EQ(process_vector[0].X, 12.3 * std::pow(conversions::MolesM3ToMoleculesCm3, 2)); EXPECT_EQ(process_vector[0].Y, 42.3); EXPECT_EQ(process_vector[0].a0, 1.0e-5); EXPECT_EQ(process_vector[0].n, 3); EXPECT_EQ(process_vector[0].alkoxy_products.size(), 2); - EXPECT_EQ(process_vector[0].alkoxy_products[0].species_name, "bar"); + EXPECT_EQ(process_vector[0].alkoxy_products[0].name, "bar"); EXPECT_EQ(process_vector[0].alkoxy_products[0].coefficient, 1.0); - EXPECT_EQ(process_vector[0].alkoxy_products[1].species_name, "baz"); + EXPECT_EQ(process_vector[0].alkoxy_products[1].name, "baz"); EXPECT_EQ(process_vector[0].alkoxy_products[1].coefficient, 3.2); EXPECT_EQ(process_vector[0].nitrate_products.size(), 1); - EXPECT_EQ(process_vector[0].nitrate_products[0].species_name, "quz"); + EXPECT_EQ(process_vector[0].nitrate_products[0].name, "quz"); EXPECT_EQ(process_vector[0].nitrate_products[0].coefficient, 1.0); // second reaction @@ -96,17 +100,17 @@ TEST(BranchedConfig, ParseConfig) EXPECT_EQ(process_vector[1].a0, 0.423); EXPECT_EQ(process_vector[1].alkoxy_products.size(), 1); EXPECT_EQ(process_vector[1].alkoxy_products[0].coefficient, 1.0); - EXPECT_EQ(process_vector[1].alkoxy_products[0].species_name, "baz"); + EXPECT_EQ(process_vector[1].alkoxy_products[0].name, "baz"); EXPECT_EQ(process_vector[1].n, 6); EXPECT_EQ(process_vector[1].nitrate_products.size(), 2); EXPECT_EQ(process_vector[1].nitrate_products[0].coefficient, 0.5); - EXPECT_EQ(process_vector[1].nitrate_products[0].species_name, "bar"); + EXPECT_EQ(process_vector[1].nitrate_products[0].name, "bar"); EXPECT_EQ(process_vector[1].nitrate_products[1].coefficient, 1.0); - EXPECT_EQ(process_vector[1].nitrate_products[1].species_name, "foo"); + EXPECT_EQ(process_vector[1].nitrate_products[1].name, "foo"); EXPECT_EQ(process_vector[1].reactants.size(), 2); - EXPECT_EQ(process_vector[1].reactants[0].species_name, "bar"); + EXPECT_EQ(process_vector[1].reactants[0].name, "bar"); EXPECT_EQ(process_vector[1].reactants[0].coefficient, 1.0); - EXPECT_EQ(process_vector[1].reactants[1].species_name, "baz"); + EXPECT_EQ(process_vector[1].reactants[1].name, "baz"); EXPECT_EQ(process_vector[1].reactants[1].coefficient, 1.0); } } @@ -120,12 +124,12 @@ TEST(BranchedConfig, DetectsNonstandardKeys) std::string file = "./v0_unit_configs/branched/contains_nonstandard_key/config" + extension; auto parsed = parser.Parse(file); EXPECT_FALSE(parsed); - EXPECT_EQ(parsed.errors.size(), 2); - EXPECT_EQ(parsed.errors[0].first, ConfigParseStatus::InvalidKey); - EXPECT_EQ(parsed.errors[1].first, ConfigParseStatus::InvalidKey); - for (auto& error : parsed.errors) + EXPECT_EQ(parsed.error().size(), 2); + EXPECT_EQ(parsed.error()[0].first, ErrorCode::InvalidKey); + EXPECT_EQ(parsed.error()[1].first, ErrorCode::InvalidKey); + for (auto& error : parsed.error()) { - std::cout << error.second << " " << configParseStatusToString(error.first) << std::endl; + std::cout << error.second << " " << ErrorCodeToString(error.first) << std::endl; } } } @@ -139,21 +143,21 @@ TEST(BranchedConfig, DetectsNonstandardProductCoefficient) std::string file = "./v0_unit_configs/branched/nonstandard_alkoxy_product_coef/config" + extension; auto parsed = parser.Parse(file); EXPECT_FALSE(parsed); - EXPECT_EQ(parsed.errors.size(), 1); - EXPECT_EQ(parsed.errors[0].first, ConfigParseStatus::InvalidKey); - for (auto& error : parsed.errors) + EXPECT_EQ(parsed.error().size(), 1); + EXPECT_EQ(parsed.error()[0].first, ErrorCode::InvalidKey); + for (auto& error : parsed.error()) { - std::cout << error.second << " " << configParseStatusToString(error.first) << std::endl; + std::cout << error.second << " " << ErrorCodeToString(error.first) << std::endl; } file = "./v0_unit_configs/branched/nonstandard_nitrate_product_coef/config" + extension; parsed = parser.Parse(file); EXPECT_FALSE(parsed); - EXPECT_EQ(parsed.errors.size(), 1); - EXPECT_EQ(parsed.errors[0].first, ConfigParseStatus::InvalidKey); - for (auto& error : parsed.errors) + EXPECT_EQ(parsed.error().size(), 1); + EXPECT_EQ(parsed.error()[0].first, ErrorCode::InvalidKey); + for (auto& error : parsed.error()) { - std::cout << error.second << " " << configParseStatusToString(error.first) << std::endl; + std::cout << error.second << " " << ErrorCodeToString(error.first) << std::endl; } } } @@ -167,11 +171,11 @@ TEST(BranchedConfig, DetectsNonstandardReactantCoefficient) std::string file = "./v0_unit_configs/branched/nonstandard_reactant_coef/config" + extension; auto parsed = parser.Parse(file); EXPECT_FALSE(parsed); - EXPECT_EQ(parsed.errors.size(), 1); - EXPECT_EQ(parsed.errors[0].first, ConfigParseStatus::InvalidKey); - for (auto& error : parsed.errors) + EXPECT_EQ(parsed.error().size(), 1); + EXPECT_EQ(parsed.error()[0].first, ErrorCode::InvalidKey); + for (auto& error : parsed.error()) { - std::cout << error.second << " " << configParseStatusToString(error.first) << std::endl; + std::cout << error.second << " " << ErrorCodeToString(error.first) << std::endl; } } } \ No newline at end of file diff --git a/test/unit/v0/test_emission_config.cpp b/test/unit/v0/test_emission_config.cpp index 6096d466..c753ed68 100644 --- a/test/unit/v0/test_emission_config.cpp +++ b/test/unit/v0/test_emission_config.cpp @@ -1,5 +1,9 @@ -#include -#include +// Copyright (C) 2023–2026 University Corporation for Atmospheric Research +// University of Illinois at Urbana-Champaign +// SPDX-License-Identifier: Apache-2.0 + +#include "detail/constants.hpp" +#include "detail/v0/parser.hpp" #include @@ -14,21 +18,21 @@ TEST(EmissionConfig, DetectsInvalidConfig) std::string file = "./v0_unit_configs/emission/missing_products/config" + extension; auto parsed = parser.Parse(file); EXPECT_FALSE(parsed); - EXPECT_EQ(parsed.errors.size(), 1); - EXPECT_EQ(parsed.errors[0].first, ConfigParseStatus::RequiredKeyNotFound); - for (auto& error : parsed.errors) + EXPECT_EQ(parsed.error().size(), 1); + EXPECT_EQ(parsed.error()[0].first, ErrorCode::RequiredKeyNotFound); + for (auto& error : parsed.error()) { - std::cout << error.second << " " << configParseStatusToString(error.first) << std::endl; + std::cout << error.second << " " << ErrorCodeToString(error.first) << std::endl; } file = "./v0_unit_configs/emission/missing_MUSICA_name/config" + extension; parsed = parser.Parse(file); EXPECT_FALSE(parsed); - EXPECT_EQ(parsed.errors.size(), 1); - EXPECT_EQ(parsed.errors[0].first, ConfigParseStatus::RequiredKeyNotFound); - for (auto& error : parsed.errors) + EXPECT_EQ(parsed.error().size(), 1); + EXPECT_EQ(parsed.error()[0].first, ErrorCode::RequiredKeyNotFound); + for (auto& error : parsed.error()) { - std::cout << error.second << " " << configParseStatusToString(error.first) << std::endl; + std::cout << error.second << " " << ErrorCodeToString(error.first) << std::endl; } } } @@ -43,7 +47,7 @@ TEST(EmissionConfig, ParseConfig) std::string file = "./v0_unit_configs/emission/valid/config" + extension; auto parsed = parser.Parse(file); EXPECT_TRUE(parsed); - v0::types::Mechanism mechanism = *parsed; + Mechanism mechanism = *parsed; auto& process_vector = mechanism.reactions.user_defined; EXPECT_EQ(process_vector.size(), 2); @@ -52,7 +56,7 @@ TEST(EmissionConfig, ParseConfig) { EXPECT_EQ(process_vector[0].reactants.size(), 0); EXPECT_EQ(process_vector[0].products.size(), 1); - EXPECT_EQ(process_vector[0].products[0].species_name, "foo"); + EXPECT_EQ(process_vector[0].products[0].name, "foo"); EXPECT_EQ(process_vector[0].products[0].coefficient, 1.0); EXPECT_EQ(process_vector[0].name, "EMIS.foo"); EXPECT_EQ(process_vector[0].scaling_factor, 1.0); @@ -62,7 +66,7 @@ TEST(EmissionConfig, ParseConfig) { EXPECT_EQ(process_vector[1].reactants.size(), 0); EXPECT_EQ(process_vector[1].products.size(), 1); - EXPECT_EQ(process_vector[1].products[0].species_name, "bar"); + EXPECT_EQ(process_vector[1].products[0].name, "bar"); EXPECT_EQ(process_vector[1].products[0].coefficient, 1.0); EXPECT_EQ(process_vector[1].name, "EMIS.bar"); EXPECT_EQ(process_vector[1].scaling_factor, 2.5); @@ -79,11 +83,11 @@ TEST(EmissionConfig, DetectsNonstandardKeys) std::string file = "./v0_unit_configs/emission/contains_nonstandard_key/config" + extension; auto parsed = parser.Parse(file); EXPECT_FALSE(parsed); - EXPECT_EQ(parsed.errors.size(), 1); - EXPECT_EQ(parsed.errors[0].first, ConfigParseStatus::InvalidKey); - for (auto& error : parsed.errors) + EXPECT_EQ(parsed.error().size(), 1); + EXPECT_EQ(parsed.error()[0].first, ErrorCode::InvalidKey); + for (auto& error : parsed.error()) { - std::cout << error.second << " " << configParseStatusToString(error.first) << std::endl; + std::cout << error.second << " " << ErrorCodeToString(error.first) << std::endl; } } } \ No newline at end of file diff --git a/test/unit/v0/test_first_order_loss_config.cpp b/test/unit/v0/test_first_order_loss_config.cpp index d24f42cd..60fab0a5 100644 --- a/test/unit/v0/test_first_order_loss_config.cpp +++ b/test/unit/v0/test_first_order_loss_config.cpp @@ -1,5 +1,9 @@ -#include -#include +// Copyright (C) 2023–2026 University Corporation for Atmospheric Research +// University of Illinois at Urbana-Champaign +// SPDX-License-Identifier: Apache-2.0 + +#include "detail/constants.hpp" +#include "detail/v0/parser.hpp" #include @@ -14,21 +18,21 @@ TEST(FirstOrderLossConfig, DetectsInvalidConfig) std::string file = "./v0_unit_configs/first_order_loss/missing_reactants/config" + extension; auto parsed = parser.Parse(file); EXPECT_FALSE(parsed); - EXPECT_EQ(parsed.errors.size(), 1); - EXPECT_EQ(parsed.errors[0].first, ConfigParseStatus::RequiredKeyNotFound); - for (auto& error : parsed.errors) + EXPECT_EQ(parsed.error().size(), 1); + EXPECT_EQ(parsed.error()[0].first, ErrorCode::RequiredKeyNotFound); + for (auto& error : parsed.error()) { - std::cout << error.second << " " << configParseStatusToString(error.first) << std::endl; + std::cout << error.second << " " << ErrorCodeToString(error.first) << std::endl; } file = "./v0_unit_configs/first_order_loss/missing_MUSICA_name/config" + extension; parsed = parser.Parse(file); EXPECT_FALSE(parsed); - EXPECT_EQ(parsed.errors.size(), 1); - EXPECT_EQ(parsed.errors[0].first, ConfigParseStatus::RequiredKeyNotFound); - for (auto& error : parsed.errors) + EXPECT_EQ(parsed.error().size(), 1); + EXPECT_EQ(parsed.error()[0].first, ErrorCode::RequiredKeyNotFound); + for (auto& error : parsed.error()) { - std::cout << error.second << " " << configParseStatusToString(error.first) << std::endl; + std::cout << error.second << " " << ErrorCodeToString(error.first) << std::endl; } } } @@ -43,7 +47,7 @@ TEST(FirstOrderLossConfig, ParseConfig) std::string file = "./v0_unit_configs/first_order_loss/valid/config" + extension; auto parsed = parser.Parse(file); EXPECT_TRUE(parsed); - v0::types::Mechanism mechanism = *parsed; + Mechanism mechanism = *parsed; auto& process_vector = mechanism.reactions.user_defined; EXPECT_EQ(process_vector.size(), 2); @@ -52,7 +56,7 @@ TEST(FirstOrderLossConfig, ParseConfig) { EXPECT_EQ(process_vector[0].reactants.size(), 1); EXPECT_EQ(process_vector[0].products.size(), 0); - EXPECT_EQ(process_vector[0].reactants[0].species_name, "foo"); + EXPECT_EQ(process_vector[0].reactants[0].name, "foo"); EXPECT_EQ(process_vector[0].name, "LOSS.foo"); EXPECT_EQ(process_vector[0].scaling_factor, 1.0); } @@ -61,7 +65,7 @@ TEST(FirstOrderLossConfig, ParseConfig) { EXPECT_EQ(process_vector[1].reactants.size(), 1); EXPECT_EQ(process_vector[1].products.size(), 0); - EXPECT_EQ(process_vector[1].reactants[0].species_name, "bar"); + EXPECT_EQ(process_vector[1].reactants[0].name, "bar"); EXPECT_EQ(process_vector[1].name, "LOSS.bar"); EXPECT_EQ(process_vector[1].scaling_factor, 2.5); } @@ -77,11 +81,11 @@ TEST(FirstOrderLossConfig, DetectsNonstandardKeys) std::string file = "./v0_unit_configs/first_order_loss/contains_nonstandard_key/config" + extension; auto parsed = parser.Parse(file); EXPECT_FALSE(parsed); - EXPECT_EQ(parsed.errors.size(), 1); - EXPECT_EQ(parsed.errors[0].first, ConfigParseStatus::InvalidKey); - for (auto& error : parsed.errors) + EXPECT_EQ(parsed.error().size(), 1); + EXPECT_EQ(parsed.error()[0].first, ErrorCode::InvalidKey); + for (auto& error : parsed.error()) { - std::cout << error.second << " " << configParseStatusToString(error.first) << std::endl; + std::cout << error.second << " " << ErrorCodeToString(error.first) << std::endl; } } } \ No newline at end of file diff --git a/test/unit/v0/test_photolysis_config.cpp b/test/unit/v0/test_photolysis_config.cpp index a5a0d47f..afb82a3f 100644 --- a/test/unit/v0/test_photolysis_config.cpp +++ b/test/unit/v0/test_photolysis_config.cpp @@ -1,5 +1,9 @@ -#include -#include +// Copyright (C) 2023–2026 University Corporation for Atmospheric Research +// University of Illinois at Urbana-Champaign +// SPDX-License-Identifier: Apache-2.0 + +#include "detail/constants.hpp" +#include "detail/v0/parser.hpp" #include @@ -14,31 +18,31 @@ TEST(PhotolysisConfig, DetectsInvalidConfig) std::string file = "./v0_unit_configs/photolysis/missing_reactants/config" + extension; auto parsed = parser.Parse(file); EXPECT_FALSE(parsed); - EXPECT_EQ(parsed.errors.size(), 1); - EXPECT_EQ(parsed.errors[0].first, ConfigParseStatus::RequiredKeyNotFound); - for (auto& error : parsed.errors) + EXPECT_EQ(parsed.error().size(), 1); + EXPECT_EQ(parsed.error()[0].first, ErrorCode::RequiredKeyNotFound); + for (auto& error : parsed.error()) { - std::cout << error.second << " " << configParseStatusToString(error.first) << std::endl; + std::cout << error.second << " " << ErrorCodeToString(error.first) << std::endl; } file = "./v0_unit_configs/photolysis/missing_products/config" + extension; parsed = parser.Parse(file); EXPECT_FALSE(parsed); - EXPECT_EQ(parsed.errors.size(), 1); - EXPECT_EQ(parsed.errors[0].first, ConfigParseStatus::RequiredKeyNotFound); - for (auto& error : parsed.errors) + EXPECT_EQ(parsed.error().size(), 1); + EXPECT_EQ(parsed.error()[0].first, ErrorCode::RequiredKeyNotFound); + for (auto& error : parsed.error()) { - std::cout << error.second << " " << configParseStatusToString(error.first) << std::endl; + std::cout << error.second << " " << ErrorCodeToString(error.first) << std::endl; } file = "./v0_unit_configs/photolysis/missing_MUSICA_name/config" + extension; parsed = parser.Parse(file); EXPECT_FALSE(parsed); - EXPECT_EQ(parsed.errors.size(), 1); - EXPECT_EQ(parsed.errors[0].first, ConfigParseStatus::RequiredKeyNotFound); - for (auto& error : parsed.errors) + EXPECT_EQ(parsed.error().size(), 1); + EXPECT_EQ(parsed.error()[0].first, ErrorCode::RequiredKeyNotFound); + for (auto& error : parsed.error()) { - std::cout << error.second << " " << configParseStatusToString(error.first) << std::endl; + std::cout << error.second << " " << ErrorCodeToString(error.first) << std::endl; } } } @@ -53,7 +57,7 @@ TEST(PhotolysisConfig, ParseConfig) std::string file = "./v0_unit_configs/photolysis/valid/config" + extension; auto parsed = parser.Parse(file); EXPECT_TRUE(parsed); - v0::types::Mechanism mechanism = *parsed; + Mechanism mechanism = *parsed; auto& process_vector = mechanism.reactions.user_defined; EXPECT_EQ(process_vector.size(), 2); @@ -61,11 +65,11 @@ TEST(PhotolysisConfig, ParseConfig) // first reaction { EXPECT_EQ(process_vector[0].reactants.size(), 1); - EXPECT_EQ(process_vector[0].reactants[0].species_name, "foo"); + EXPECT_EQ(process_vector[0].reactants[0].name, "foo"); EXPECT_EQ(process_vector[0].products.size(), 2); - EXPECT_EQ(process_vector[0].products[0].species_name, "bar"); + EXPECT_EQ(process_vector[0].products[0].name, "bar"); EXPECT_EQ(process_vector[0].products[0].coefficient, 1.0); - EXPECT_EQ(process_vector[0].products[1].species_name, "baz"); + EXPECT_EQ(process_vector[0].products[1].name, "baz"); EXPECT_EQ(process_vector[0].products[1].coefficient, 3.2); EXPECT_EQ(process_vector[0].name, "PHOTO.jfoo"); EXPECT_EQ(process_vector[0].scaling_factor, 1.0); @@ -74,11 +78,11 @@ TEST(PhotolysisConfig, ParseConfig) // second reaction { EXPECT_EQ(process_vector[1].reactants.size(), 1); - EXPECT_EQ(process_vector[1].reactants[0].species_name, "bar"); + EXPECT_EQ(process_vector[1].reactants[0].name, "bar"); EXPECT_EQ(process_vector[1].products.size(), 2); - EXPECT_EQ(process_vector[1].products[0].species_name, "bar"); + EXPECT_EQ(process_vector[1].products[0].name, "bar"); EXPECT_EQ(process_vector[1].products[0].coefficient, 0.5); - EXPECT_EQ(process_vector[1].products[1].species_name, "foo"); + EXPECT_EQ(process_vector[1].products[1].name, "foo"); EXPECT_EQ(process_vector[1].products[1].coefficient, 1.0); EXPECT_EQ(process_vector[1].name, "PHOTO.jbar"); EXPECT_EQ(process_vector[1].scaling_factor, 2.5); @@ -95,11 +99,11 @@ TEST(PhotolysisConfig, DetectsNonstandardKeys) std::string file = "./v0_unit_configs/photolysis/contains_nonstandard_key/config" + extension; auto parsed = parser.Parse(file); EXPECT_FALSE(parsed); - EXPECT_EQ(parsed.errors.size(), 1); - EXPECT_EQ(parsed.errors[0].first, ConfigParseStatus::InvalidKey); - for (auto& error : parsed.errors) + EXPECT_EQ(parsed.error().size(), 1); + EXPECT_EQ(parsed.error()[0].first, ErrorCode::InvalidKey); + for (auto& error : parsed.error()) { - std::cout << error.second << " " << configParseStatusToString(error.first) << std::endl; + std::cout << error.second << " " << ErrorCodeToString(error.first) << std::endl; } } } @@ -113,11 +117,11 @@ TEST(PhotolysisConfig, DetectsNonstandardProductCoefficient) std::string file = "./v0_unit_configs/photolysis/nonstandard_product_coef/config" + extension; auto parsed = parser.Parse(file); EXPECT_FALSE(parsed); - EXPECT_EQ(parsed.errors.size(), 1); - EXPECT_EQ(parsed.errors[0].first, ConfigParseStatus::InvalidKey); - for (auto& error : parsed.errors) + EXPECT_EQ(parsed.error().size(), 1); + EXPECT_EQ(parsed.error()[0].first, ErrorCode::InvalidKey); + for (auto& error : parsed.error()) { - std::cout << error.second << " " << configParseStatusToString(error.first) << std::endl; + std::cout << error.second << " " << ErrorCodeToString(error.first) << std::endl; } } } @@ -131,11 +135,11 @@ TEST(PhotolysisConfig, DetectsNonstandardReactantCoefficient) std::string file = "./v0_unit_configs/photolysis/nonstandard_reactant_coef/config" + extension; auto parsed = parser.Parse(file); EXPECT_FALSE(parsed); - EXPECT_EQ(parsed.errors.size(), 1); - EXPECT_EQ(parsed.errors[0].first, ConfigParseStatus::InvalidKey); - for (auto& error : parsed.errors) + EXPECT_EQ(parsed.error().size(), 1); + EXPECT_EQ(parsed.error()[0].first, ErrorCode::InvalidKey); + for (auto& error : parsed.error()) { - std::cout << error.second << " " << configParseStatusToString(error.first) << std::endl; + std::cout << error.second << " " << ErrorCodeToString(error.first) << std::endl; } } } \ No newline at end of file diff --git a/test/unit/v0/test_species_config.cpp b/test/unit/v0/test_species_config.cpp index 7cbd29dc..04e936bf 100644 --- a/test/unit/v0/test_species_config.cpp +++ b/test/unit/v0/test_species_config.cpp @@ -1,5 +1,9 @@ -#include -#include +// Copyright (C) 2023–2026 University Corporation for Atmospheric Research +// University of Illinois at Urbana-Champaign +// SPDX-License-Identifier: Apache-2.0 + +#include "detail/constants.hpp" +#include "detail/v0/parser.hpp" #include @@ -17,12 +21,12 @@ TEST(SpeciesConfig, ValidSpeciesConfig) EXPECT_TRUE(parsed); if (!parsed) { - for (auto& error : parsed.errors) + for (auto& error : parsed.error()) { std::cerr << error.second << std::endl; } } - v0::types::Mechanism mechanism = *parsed; + Mechanism mechanism = *parsed; auto& species_vector = mechanism.species; EXPECT_EQ(species_vector.size(), 4); diff --git a/test/unit/v0/test_surface_config.cpp b/test/unit/v0/test_surface_config.cpp index d9cdf227..bff6b80d 100644 --- a/test/unit/v0/test_surface_config.cpp +++ b/test/unit/v0/test_surface_config.cpp @@ -1,5 +1,9 @@ -#include -#include +// Copyright (C) 2023–2026 University Corporation for Atmospheric Research +// University of Illinois at Urbana-Champaign +// SPDX-License-Identifier: Apache-2.0 + +#include "detail/constants.hpp" +#include "detail/v0/parser.hpp" #include @@ -14,31 +18,31 @@ TEST(SurfaceConfig, DetectsInvalidConfig) std::string file = "./v0_unit_configs/surface/missing_reactants/config" + extension; auto parsed = parser.Parse(file); EXPECT_FALSE(parsed); - EXPECT_EQ(parsed.errors.size(), 1); - EXPECT_EQ(parsed.errors[0].first, ConfigParseStatus::RequiredKeyNotFound); - for (auto& error : parsed.errors) + EXPECT_EQ(parsed.error().size(), 1); + EXPECT_EQ(parsed.error()[0].first, ErrorCode::RequiredKeyNotFound); + for (auto& error : parsed.error()) { - std::cout << error.second << " " << configParseStatusToString(error.first) << std::endl; + std::cout << error.second << " " << ErrorCodeToString(error.first) << std::endl; } file = "./v0_unit_configs/surface/missing_products/config" + extension; parsed = parser.Parse(file); EXPECT_FALSE(parsed); - EXPECT_EQ(parsed.errors.size(), 1); - EXPECT_EQ(parsed.errors[0].first, ConfigParseStatus::RequiredKeyNotFound); - for (auto& error : parsed.errors) + EXPECT_EQ(parsed.error().size(), 1); + EXPECT_EQ(parsed.error()[0].first, ErrorCode::RequiredKeyNotFound); + for (auto& error : parsed.error()) { - std::cout << error.second << " " << configParseStatusToString(error.first) << std::endl; + std::cout << error.second << " " << ErrorCodeToString(error.first) << std::endl; } file = "./v0_unit_configs/surface/missing_MUSICA_name/config" + extension; parsed = parser.Parse(file); EXPECT_FALSE(parsed); - EXPECT_EQ(parsed.errors.size(), 1); - EXPECT_EQ(parsed.errors[0].first, ConfigParseStatus::RequiredKeyNotFound); - for (auto& error : parsed.errors) + EXPECT_EQ(parsed.error().size(), 1); + EXPECT_EQ(parsed.error()[0].first, ErrorCode::RequiredKeyNotFound); + for (auto& error : parsed.error()) { - std::cout << error.second << " " << configParseStatusToString(error.first) << std::endl; + std::cout << error.second << " " << ErrorCodeToString(error.first) << std::endl; } } } @@ -53,43 +57,43 @@ TEST(SurfaceConfig, ParseConfig) std::string file = "./v0_unit_configs/surface/valid/config" + extension; auto parsed = parser.Parse(file); EXPECT_TRUE(parsed); - v0::types::Mechanism mechanism = *parsed; + Mechanism mechanism = *parsed; auto& process_vector = mechanism.reactions.surface; EXPECT_EQ(process_vector.size(), 2); // first reaction { - EXPECT_EQ(process_vector[0].gas_phase_species.species_name, "foo"); + EXPECT_EQ(process_vector[0].gas_phase_species.name, "foo"); EXPECT_EQ(process_vector[0].gas_phase_products.size(), 2); - EXPECT_EQ(process_vector[0].gas_phase_products[0].species_name, "bar"); + EXPECT_EQ(process_vector[0].gas_phase_products[0].name, "bar"); EXPECT_EQ(process_vector[0].gas_phase_products[0].coefficient, 1.0); - EXPECT_EQ(process_vector[0].gas_phase_products[1].species_name, "baz"); + EXPECT_EQ(process_vector[0].gas_phase_products[1].name, "baz"); EXPECT_EQ(process_vector[0].gas_phase_products[1].coefficient, 3.2); EXPECT_EQ(process_vector[0].name, "SURF.kfoo"); EXPECT_EQ(process_vector[0].reaction_probability, 1.0); auto it = std::find_if( mechanism.species.begin(), mechanism.species.end(), - [](const v0::types::Species& species) { return species.name == "foo"; }); + [](const types::Species& species) { return species.name == "foo"; }); ASSERT_NE(it, mechanism.species.end()); EXPECT_EQ(it->diffusion_coefficient, 2.3e-4); } // second reaction { - EXPECT_EQ(process_vector[1].gas_phase_species.species_name, "bar"); + EXPECT_EQ(process_vector[1].gas_phase_species.name, "bar"); EXPECT_EQ(process_vector[1].gas_phase_products.size(), 2); - EXPECT_EQ(process_vector[1].gas_phase_products[0].species_name, "bar"); + EXPECT_EQ(process_vector[1].gas_phase_products[0].name, "bar"); EXPECT_EQ(process_vector[1].gas_phase_products[0].coefficient, 0.5); - EXPECT_EQ(process_vector[1].gas_phase_products[1].species_name, "foo"); + EXPECT_EQ(process_vector[1].gas_phase_products[1].name, "foo"); EXPECT_EQ(process_vector[1].gas_phase_products[1].coefficient, 1.0); EXPECT_EQ(process_vector[1].name, "SURF.kbar"); EXPECT_EQ(process_vector[1].reaction_probability, 0.5); auto it = std::find_if( mechanism.species.begin(), mechanism.species.end(), - [](const v0::types::Species& species) { return species.name == "bar"; }); + [](const types::Species& species) { return species.name == "bar"; }); ASSERT_NE(it, mechanism.species.end()); EXPECT_EQ(it->diffusion_coefficient, 0.4e-5); } @@ -105,11 +109,11 @@ TEST(SurfaceConfig, DetectsNonstandardKeys) std::string file = "./v0_unit_configs/surface/contains_nonstandard_key/config" + extension; auto parsed = parser.Parse(file); EXPECT_FALSE(parsed); - EXPECT_EQ(parsed.errors.size(), 1); - EXPECT_EQ(parsed.errors[0].first, ConfigParseStatus::InvalidKey); - for (auto& error : parsed.errors) + EXPECT_EQ(parsed.error().size(), 1); + EXPECT_EQ(parsed.error()[0].first, ErrorCode::InvalidKey); + for (auto& error : parsed.error()) { - std::cout << error.second << " " << configParseStatusToString(error.first) << std::endl; + std::cout << error.second << " " << ErrorCodeToString(error.first) << std::endl; } } } @@ -123,11 +127,11 @@ TEST(SurfaceConfig, DetectsNonstandardProductCoefficient) std::string file = "./v0_unit_configs/surface/nonstandard_product_coef/config" + extension; auto parsed = parser.Parse(file); EXPECT_FALSE(parsed); - EXPECT_EQ(parsed.errors.size(), 1); - EXPECT_EQ(parsed.errors[0].first, ConfigParseStatus::InvalidKey); - for (auto& error : parsed.errors) + EXPECT_EQ(parsed.error().size(), 1); + EXPECT_EQ(parsed.error()[0].first, ErrorCode::InvalidKey); + for (auto& error : parsed.error()) { - std::cout << error.second << " " << configParseStatusToString(error.first) << std::endl; + std::cout << error.second << " " << ErrorCodeToString(error.first) << std::endl; } } } \ No newline at end of file diff --git a/test/unit/v0/test_ternary_chemical_activation_config.cpp b/test/unit/v0/test_ternary_chemical_activation_config.cpp index 5d3dcb9e..c85edf72 100644 --- a/test/unit/v0/test_ternary_chemical_activation_config.cpp +++ b/test/unit/v0/test_ternary_chemical_activation_config.cpp @@ -1,6 +1,10 @@ -#include -#include -#include +// Copyright (C) 2023–2026 University Corporation for Atmospheric Research +// University of Illinois at Urbana-Champaign +// SPDX-License-Identifier: Apache-2.0 + +#include "detail/constants.hpp" +#include "detail/conversions.hpp" +#include "detail/v0/parser.hpp" #include @@ -15,21 +19,21 @@ TEST(TernaryChemicalActivationConfig, DetectsInvalidConfig) std::string file = "./v0_unit_configs/ternary_chemical_activation/missing_reactants/config" + extension; auto parsed = parser.Parse(file); EXPECT_FALSE(parsed); - EXPECT_EQ(parsed.errors.size(), 1); - EXPECT_EQ(parsed.errors[0].first, ConfigParseStatus::RequiredKeyNotFound); - for (auto& error : parsed.errors) + EXPECT_EQ(parsed.error().size(), 1); + EXPECT_EQ(parsed.error()[0].first, ErrorCode::RequiredKeyNotFound); + for (auto& error : parsed.error()) { - std::cout << error.second << " " << configParseStatusToString(error.first) << std::endl; + std::cout << error.second << " " << ErrorCodeToString(error.first) << std::endl; } file = "./v0_unit_configs/ternary_chemical_activation/missing_products/config" + extension; parsed = parser.Parse(file); EXPECT_FALSE(parsed); - EXPECT_EQ(parsed.errors.size(), 1); - EXPECT_EQ(parsed.errors[0].first, ConfigParseStatus::RequiredKeyNotFound); - for (auto& error : parsed.errors) + EXPECT_EQ(parsed.error().size(), 1); + EXPECT_EQ(parsed.error()[0].first, ErrorCode::RequiredKeyNotFound); + for (auto& error : parsed.error()) { - std::cout << error.second << " " << configParseStatusToString(error.first) << std::endl; + std::cout << error.second << " " << ErrorCodeToString(error.first) << std::endl; } } } @@ -44,7 +48,7 @@ TEST(TernaryChemicalActivationConfig, ParseConfig) std::string file = "./v0_unit_configs/ternary_chemical_activation/valid/config" + extension; auto parsed = parser.Parse(file); EXPECT_TRUE(parsed); - v0::types::Mechanism mechanism = *parsed; + Mechanism mechanism = *parsed; auto& process_vector = mechanism.reactions.ternary_chemical_activation; EXPECT_EQ(process_vector.size(), 2); @@ -52,14 +56,14 @@ TEST(TernaryChemicalActivationConfig, ParseConfig) // first reaction { EXPECT_EQ(process_vector[0].reactants.size(), 2); - EXPECT_EQ(process_vector[0].reactants[0].species_name, "foo"); + EXPECT_EQ(process_vector[0].reactants[0].name, "foo"); EXPECT_EQ(process_vector[0].reactants[0].coefficient, 1.0); - EXPECT_EQ(process_vector[0].reactants[1].species_name, "quz"); + EXPECT_EQ(process_vector[0].reactants[1].name, "quz"); EXPECT_EQ(process_vector[0].reactants[1].coefficient, 2.0); EXPECT_EQ(process_vector[0].products.size(), 2); - EXPECT_EQ(process_vector[0].products[0].species_name, "bar"); + EXPECT_EQ(process_vector[0].products[0].name, "bar"); EXPECT_EQ(process_vector[0].products[0].coefficient, 1.0); - EXPECT_EQ(process_vector[0].products[1].species_name, "baz"); + EXPECT_EQ(process_vector[0].products[1].name, "baz"); EXPECT_EQ(process_vector[0].products[1].coefficient, 3.2); EXPECT_EQ(process_vector[0].k0_A, 1.0 * std::pow(conversions::MolesM3ToMoleculesCm3, 3)); EXPECT_EQ(process_vector[0].k0_B, 0.0); @@ -74,12 +78,12 @@ TEST(TernaryChemicalActivationConfig, ParseConfig) // second reaction { EXPECT_EQ(process_vector[1].reactants.size(), 2); - EXPECT_EQ(process_vector[1].reactants[0].species_name, "bar"); - EXPECT_EQ(process_vector[1].reactants[1].species_name, "baz"); + EXPECT_EQ(process_vector[1].reactants[0].name, "bar"); + EXPECT_EQ(process_vector[1].reactants[1].name, "baz"); EXPECT_EQ(process_vector[1].products.size(), 2); - EXPECT_EQ(process_vector[1].products[0].species_name, "bar"); + EXPECT_EQ(process_vector[1].products[0].name, "bar"); EXPECT_EQ(process_vector[1].products[0].coefficient, 0.5); - EXPECT_EQ(process_vector[1].products[1].species_name, "foo"); + EXPECT_EQ(process_vector[1].products[1].name, "foo"); EXPECT_EQ(process_vector[1].products[1].coefficient, 1.0); EXPECT_EQ(process_vector[1].k0_A, 32.1 * std::pow(conversions::MolesM3ToMoleculesCm3, 2)); EXPECT_EQ(process_vector[1].k0_B, -2.3); @@ -102,18 +106,18 @@ TEST(TernaryChemicalActivationConfig, DetectsNonstandardKeys) std::string file = "./v0_unit_configs/ternary_chemical_activation/contains_nonstandard_key/config" + extension; auto parsed = parser.Parse(file); EXPECT_FALSE(parsed); - EXPECT_EQ(parsed.errors.size(), 8); - EXPECT_EQ(parsed.errors[0].first, ConfigParseStatus::InvalidKey); - EXPECT_EQ(parsed.errors[1].first, ConfigParseStatus::InvalidKey); - EXPECT_EQ(parsed.errors[2].first, ConfigParseStatus::InvalidKey); - EXPECT_EQ(parsed.errors[3].first, ConfigParseStatus::InvalidKey); - EXPECT_EQ(parsed.errors[4].first, ConfigParseStatus::InvalidKey); - EXPECT_EQ(parsed.errors[5].first, ConfigParseStatus::InvalidKey); - EXPECT_EQ(parsed.errors[6].first, ConfigParseStatus::InvalidKey); - EXPECT_EQ(parsed.errors[7].first, ConfigParseStatus::InvalidKey); - for (auto& error : parsed.errors) + EXPECT_EQ(parsed.error().size(), 8); + EXPECT_EQ(parsed.error()[0].first, ErrorCode::InvalidKey); + EXPECT_EQ(parsed.error()[1].first, ErrorCode::InvalidKey); + EXPECT_EQ(parsed.error()[2].first, ErrorCode::InvalidKey); + EXPECT_EQ(parsed.error()[3].first, ErrorCode::InvalidKey); + EXPECT_EQ(parsed.error()[4].first, ErrorCode::InvalidKey); + EXPECT_EQ(parsed.error()[5].first, ErrorCode::InvalidKey); + EXPECT_EQ(parsed.error()[6].first, ErrorCode::InvalidKey); + EXPECT_EQ(parsed.error()[7].first, ErrorCode::InvalidKey); + for (auto& error : parsed.error()) { - std::cout << error.second << " " << configParseStatusToString(error.first) << std::endl; + std::cout << error.second << " " << ErrorCodeToString(error.first) << std::endl; } } } @@ -127,11 +131,11 @@ TEST(TernaryChemicalActivationConfig, DetectsNonstandardProductCoefficient) std::string file = "./v0_unit_configs/ternary_chemical_activation/nonstandard_product_coef/config" + extension; auto parsed = parser.Parse(file); EXPECT_FALSE(parsed); - EXPECT_EQ(parsed.errors.size(), 1); - EXPECT_EQ(parsed.errors[0].first, ConfigParseStatus::InvalidKey); - for (auto& error : parsed.errors) + EXPECT_EQ(parsed.error().size(), 1); + EXPECT_EQ(parsed.error()[0].first, ErrorCode::InvalidKey); + for (auto& error : parsed.error()) { - std::cout << error.second << " " << configParseStatusToString(error.first) << std::endl; + std::cout << error.second << " " << ErrorCodeToString(error.first) << std::endl; } } } @@ -145,11 +149,11 @@ TEST(TernaryChemicalActivationConfig, DetectsNonstandardReactantCoefficient) std::string file = "./v0_unit_configs/ternary_chemical_activation/nonstandard_reactant_coef/config" + extension; auto parsed = parser.Parse(file); EXPECT_FALSE(parsed); - EXPECT_EQ(parsed.errors.size(), 1); - EXPECT_EQ(parsed.errors[0].first, ConfigParseStatus::InvalidKey); - for (auto& error : parsed.errors) + EXPECT_EQ(parsed.error().size(), 1); + EXPECT_EQ(parsed.error()[0].first, ErrorCode::InvalidKey); + for (auto& error : parsed.error()) { - std::cout << error.second << " " << configParseStatusToString(error.first) << std::endl; + std::cout << error.second << " " << ErrorCodeToString(error.first) << std::endl; } } } \ No newline at end of file diff --git a/test/unit/v0/test_troe_config.cpp b/test/unit/v0/test_troe_config.cpp index b854955a..e26c8b74 100644 --- a/test/unit/v0/test_troe_config.cpp +++ b/test/unit/v0/test_troe_config.cpp @@ -1,6 +1,10 @@ -#include -#include -#include +// Copyright (C) 2023–2026 University Corporation for Atmospheric Research +// University of Illinois at Urbana-Champaign +// SPDX-License-Identifier: Apache-2.0 + +#include "detail/constants.hpp" +#include "detail/conversions.hpp" +#include "detail/v0/parser.hpp" #include @@ -15,21 +19,21 @@ TEST(TroeConfig, DetectsInvalidConfig) std::string file = "./v0_unit_configs/troe/missing_reactants/config" + extension; auto parsed = parser.Parse(file); EXPECT_FALSE(parsed); - EXPECT_EQ(parsed.errors.size(), 1); - EXPECT_EQ(parsed.errors[0].first, ConfigParseStatus::RequiredKeyNotFound); - for (auto& error : parsed.errors) + EXPECT_EQ(parsed.error().size(), 1); + EXPECT_EQ(parsed.error()[0].first, ErrorCode::RequiredKeyNotFound); + for (auto& error : parsed.error()) { - std::cout << error.second << " " << configParseStatusToString(error.first) << std::endl; + std::cout << error.second << " " << ErrorCodeToString(error.first) << std::endl; } file = "./v0_unit_configs/troe/missing_products/config" + extension; parsed = parser.Parse(file); EXPECT_FALSE(parsed); - EXPECT_EQ(parsed.errors.size(), 1); - EXPECT_EQ(parsed.errors[0].first, ConfigParseStatus::RequiredKeyNotFound); - for (auto& error : parsed.errors) + EXPECT_EQ(parsed.error().size(), 1); + EXPECT_EQ(parsed.error()[0].first, ErrorCode::RequiredKeyNotFound); + for (auto& error : parsed.error()) { - std::cout << error.second << " " << configParseStatusToString(error.first) << std::endl; + std::cout << error.second << " " << ErrorCodeToString(error.first) << std::endl; } } } @@ -44,7 +48,7 @@ TEST(TroeConfig, ParseConfig) std::string file = "./v0_unit_configs/troe/valid/config" + extension; auto parsed = parser.Parse(file); EXPECT_TRUE(parsed); - v0::types::Mechanism mechanism = *parsed; + Mechanism mechanism = *parsed; auto& process_vector = mechanism.reactions.troe; EXPECT_EQ(process_vector.size(), 2); @@ -52,14 +56,14 @@ TEST(TroeConfig, ParseConfig) // first reaction { EXPECT_EQ(process_vector[0].reactants.size(), 2); - EXPECT_EQ(process_vector[0].reactants[0].species_name, "foo"); + EXPECT_EQ(process_vector[0].reactants[0].name, "foo"); EXPECT_EQ(process_vector[0].reactants[0].coefficient, 1.0); - EXPECT_EQ(process_vector[0].reactants[1].species_name, "quz"); + EXPECT_EQ(process_vector[0].reactants[1].name, "quz"); EXPECT_EQ(process_vector[0].reactants[1].coefficient, 2.0); EXPECT_EQ(process_vector[0].products.size(), 2); - EXPECT_EQ(process_vector[0].products[0].species_name, "bar"); + EXPECT_EQ(process_vector[0].products[0].name, "bar"); EXPECT_EQ(process_vector[0].products[0].coefficient, 1.0); - EXPECT_EQ(process_vector[0].products[1].species_name, "baz"); + EXPECT_EQ(process_vector[0].products[1].name, "baz"); EXPECT_EQ(process_vector[0].products[1].coefficient, 3.2); EXPECT_EQ(process_vector[0].k0_A, 1.0 * std::pow(conversions::MolesM3ToMoleculesCm3, 3)); EXPECT_EQ(process_vector[0].k0_B, 0.0); @@ -74,12 +78,12 @@ TEST(TroeConfig, ParseConfig) // second reaction { EXPECT_EQ(process_vector[1].reactants.size(), 2); - EXPECT_EQ(process_vector[1].reactants[0].species_name, "bar"); - EXPECT_EQ(process_vector[1].reactants[1].species_name, "baz"); + EXPECT_EQ(process_vector[1].reactants[0].name, "bar"); + EXPECT_EQ(process_vector[1].reactants[1].name, "baz"); EXPECT_EQ(process_vector[1].products.size(), 2); - EXPECT_EQ(process_vector[1].products[0].species_name, "bar"); + EXPECT_EQ(process_vector[1].products[0].name, "bar"); EXPECT_EQ(process_vector[1].products[0].coefficient, 0.5); - EXPECT_EQ(process_vector[1].products[1].species_name, "foo"); + EXPECT_EQ(process_vector[1].products[1].name, "foo"); EXPECT_EQ(process_vector[1].products[1].coefficient, 1.0); EXPECT_EQ(process_vector[1].k0_A, 32.1 * std::pow(conversions::MolesM3ToMoleculesCm3, 2)); EXPECT_EQ(process_vector[1].k0_B, -2.3); @@ -102,18 +106,18 @@ TEST(TroeConfig, DetectsNonstandardKeys) std::string file = "./v0_unit_configs/troe/contains_nonstandard_key/config" + extension; auto parsed = parser.Parse(file); EXPECT_FALSE(parsed); - EXPECT_EQ(parsed.errors.size(), 8); - EXPECT_EQ(parsed.errors[0].first, ConfigParseStatus::InvalidKey); - EXPECT_EQ(parsed.errors[1].first, ConfigParseStatus::InvalidKey); - EXPECT_EQ(parsed.errors[2].first, ConfigParseStatus::InvalidKey); - EXPECT_EQ(parsed.errors[3].first, ConfigParseStatus::InvalidKey); - EXPECT_EQ(parsed.errors[4].first, ConfigParseStatus::InvalidKey); - EXPECT_EQ(parsed.errors[5].first, ConfigParseStatus::InvalidKey); - EXPECT_EQ(parsed.errors[6].first, ConfigParseStatus::InvalidKey); - EXPECT_EQ(parsed.errors[7].first, ConfigParseStatus::InvalidKey); - for (auto& error : parsed.errors) + EXPECT_EQ(parsed.error().size(), 8); + EXPECT_EQ(parsed.error()[0].first, ErrorCode::InvalidKey); + EXPECT_EQ(parsed.error()[1].first, ErrorCode::InvalidKey); + EXPECT_EQ(parsed.error()[2].first, ErrorCode::InvalidKey); + EXPECT_EQ(parsed.error()[3].first, ErrorCode::InvalidKey); + EXPECT_EQ(parsed.error()[4].first, ErrorCode::InvalidKey); + EXPECT_EQ(parsed.error()[5].first, ErrorCode::InvalidKey); + EXPECT_EQ(parsed.error()[6].first, ErrorCode::InvalidKey); + EXPECT_EQ(parsed.error()[7].first, ErrorCode::InvalidKey); + for (auto& error : parsed.error()) { - std::cout << error.second << " " << configParseStatusToString(error.first) << std::endl; + std::cout << error.second << " " << ErrorCodeToString(error.first) << std::endl; } } } @@ -127,11 +131,11 @@ TEST(TroeConfig, DetectsNonstandardProductCoefficient) std::string file = "./v0_unit_configs/troe/nonstandard_product_coef/config" + extension; auto parsed = parser.Parse(file); EXPECT_FALSE(parsed); - EXPECT_EQ(parsed.errors.size(), 1); - EXPECT_EQ(parsed.errors[0].first, ConfigParseStatus::InvalidKey); - for (auto& error : parsed.errors) + EXPECT_EQ(parsed.error().size(), 1); + EXPECT_EQ(parsed.error()[0].first, ErrorCode::InvalidKey); + for (auto& error : parsed.error()) { - std::cout << error.second << " " << configParseStatusToString(error.first) << std::endl; + std::cout << error.second << " " << ErrorCodeToString(error.first) << std::endl; } } } @@ -145,11 +149,11 @@ TEST(TroeConfig, DetectsNonstandardReactantCoefficient) std::string file = "./v0_unit_configs/troe/nonstandard_reactant_coef/config" + extension; auto parsed = parser.Parse(file); EXPECT_FALSE(parsed); - EXPECT_EQ(parsed.errors.size(), 1); - EXPECT_EQ(parsed.errors[0].first, ConfigParseStatus::InvalidKey); - for (auto& error : parsed.errors) + EXPECT_EQ(parsed.error().size(), 1); + EXPECT_EQ(parsed.error()[0].first, ErrorCode::InvalidKey); + for (auto& error : parsed.error()) { - std::cout << error.second << " " << configParseStatusToString(error.first) << std::endl; + std::cout << error.second << " " << ErrorCodeToString(error.first) << std::endl; } } } \ No newline at end of file diff --git a/test/unit/v0/test_tunneling_config.cpp b/test/unit/v0/test_tunneling_config.cpp index e9bfbb4c..c2b86f63 100644 --- a/test/unit/v0/test_tunneling_config.cpp +++ b/test/unit/v0/test_tunneling_config.cpp @@ -1,6 +1,10 @@ -#include -#include -#include +// Copyright (C) 2023–2026 University Corporation for Atmospheric Research +// University of Illinois at Urbana-Champaign +// SPDX-License-Identifier: Apache-2.0 + +#include "detail/constants.hpp" +#include "detail/conversions.hpp" +#include "detail/v0/parser.hpp" #include @@ -15,21 +19,21 @@ TEST(TunnelingConfig, DetectsInvalidConfig) std::string file = "./v0_unit_configs/tunneling/missing_reactants/config" + extension; auto parsed = parser.Parse(file); EXPECT_FALSE(parsed); - EXPECT_EQ(parsed.errors.size(), 1); - EXPECT_EQ(parsed.errors[0].first, ConfigParseStatus::RequiredKeyNotFound); - for (auto& error : parsed.errors) + EXPECT_EQ(parsed.error().size(), 1); + EXPECT_EQ(parsed.error()[0].first, ErrorCode::RequiredKeyNotFound); + for (auto& error : parsed.error()) { - std::cout << error.second << " " << configParseStatusToString(error.first) << std::endl; + std::cout << error.second << " " << ErrorCodeToString(error.first) << std::endl; } file = "./v0_unit_configs/tunneling/missing_products/config" + extension; parsed = parser.Parse(file); EXPECT_FALSE(parsed); - EXPECT_EQ(parsed.errors.size(), 1); - EXPECT_EQ(parsed.errors[0].first, ConfigParseStatus::RequiredKeyNotFound); - for (auto& error : parsed.errors) + EXPECT_EQ(parsed.error().size(), 1); + EXPECT_EQ(parsed.error()[0].first, ErrorCode::RequiredKeyNotFound); + for (auto& error : parsed.error()) { - std::cout << error.second << " " << configParseStatusToString(error.first) << std::endl; + std::cout << error.second << " " << ErrorCodeToString(error.first) << std::endl; } } } @@ -44,7 +48,7 @@ TEST(TunnelingConfig, ParseConfig) std::string file = "./v0_unit_configs/tunneling/valid/config" + extension; auto parsed = parser.Parse(file); EXPECT_TRUE(parsed); - v0::types::Mechanism mechanism = *parsed; + Mechanism mechanism = *parsed; auto& process_vector = mechanism.reactions.tunneling; EXPECT_EQ(process_vector.size(), 2); @@ -52,14 +56,14 @@ TEST(TunnelingConfig, ParseConfig) // first reaction { EXPECT_EQ(process_vector[0].reactants.size(), 2); - EXPECT_EQ(process_vector[0].reactants[0].species_name, "foo"); + EXPECT_EQ(process_vector[0].reactants[0].name, "foo"); EXPECT_EQ(process_vector[0].reactants[0].coefficient, 1.0); - EXPECT_EQ(process_vector[0].reactants[1].species_name, "quz"); + EXPECT_EQ(process_vector[0].reactants[1].name, "quz"); EXPECT_EQ(process_vector[0].reactants[1].coefficient, 2.0); EXPECT_EQ(process_vector[0].products.size(), 2); - EXPECT_EQ(process_vector[0].products[0].species_name, "bar"); + EXPECT_EQ(process_vector[0].products[0].name, "bar"); EXPECT_EQ(process_vector[0].products[0].coefficient, 1.0); - EXPECT_EQ(process_vector[0].products[1].species_name, "baz"); + EXPECT_EQ(process_vector[0].products[1].name, "baz"); EXPECT_EQ(process_vector[0].products[1].coefficient, 3.2); EXPECT_EQ(process_vector[0].A, 1.0 * std::pow(conversions::MolesM3ToMoleculesCm3, 2)); EXPECT_EQ(process_vector[0].B, 0.0); @@ -69,12 +73,12 @@ TEST(TunnelingConfig, ParseConfig) // second reaction { EXPECT_EQ(process_vector[1].reactants.size(), 2); - EXPECT_EQ(process_vector[1].reactants[0].species_name, "bar"); - EXPECT_EQ(process_vector[1].reactants[1].species_name, "baz"); + EXPECT_EQ(process_vector[1].reactants[0].name, "bar"); + EXPECT_EQ(process_vector[1].reactants[1].name, "baz"); EXPECT_EQ(process_vector[1].products.size(), 2); - EXPECT_EQ(process_vector[1].products[0].species_name, "bar"); + EXPECT_EQ(process_vector[1].products[0].name, "bar"); EXPECT_EQ(process_vector[1].products[0].coefficient, 0.5); - EXPECT_EQ(process_vector[1].products[1].species_name, "foo"); + EXPECT_EQ(process_vector[1].products[1].name, "foo"); EXPECT_EQ(process_vector[1].products[1].coefficient, 1.0); EXPECT_EQ(process_vector[1].A, 32.1 * conversions::MolesM3ToMoleculesCm3); EXPECT_EQ(process_vector[1].B, -2.3); @@ -92,11 +96,11 @@ TEST(TunnelingConfig, DetectsNonstandardKeys) std::string file = "./v0_unit_configs/tunneling/contains_nonstandard_key/config" + extension; auto parsed = parser.Parse(file); EXPECT_FALSE(parsed); - EXPECT_EQ(parsed.errors.size(), 1); - EXPECT_EQ(parsed.errors[0].first, ConfigParseStatus::InvalidKey); - for (auto& error : parsed.errors) + EXPECT_EQ(parsed.error().size(), 1); + EXPECT_EQ(parsed.error()[0].first, ErrorCode::InvalidKey); + for (auto& error : parsed.error()) { - std::cout << error.second << " " << configParseStatusToString(error.first) << std::endl; + std::cout << error.second << " " << ErrorCodeToString(error.first) << std::endl; } } } @@ -110,11 +114,11 @@ TEST(TunnelingConfig, DetectsNonstandardProductCoefficient) std::string file = "./v0_unit_configs/tunneling/nonstandard_product_coef/config" + extension; auto parsed = parser.Parse(file); EXPECT_FALSE(parsed); - EXPECT_EQ(parsed.errors.size(), 1); - EXPECT_EQ(parsed.errors[0].first, ConfigParseStatus::InvalidKey); - for (auto& error : parsed.errors) + EXPECT_EQ(parsed.error().size(), 1); + EXPECT_EQ(parsed.error()[0].first, ErrorCode::InvalidKey); + for (auto& error : parsed.error()) { - std::cout << error.second << " " << configParseStatusToString(error.first) << std::endl; + std::cout << error.second << " " << ErrorCodeToString(error.first) << std::endl; } } } @@ -128,11 +132,11 @@ TEST(TunnelingConfig, DetectsNonstandardReactantCoefficient) std::string file = "./v0_unit_configs/tunneling/nonstandard_reactant_coef/config" + extension; auto parsed = parser.Parse(file); EXPECT_FALSE(parsed); - EXPECT_EQ(parsed.errors.size(), 1); - EXPECT_EQ(parsed.errors[0].first, ConfigParseStatus::InvalidKey); - for (auto& error : parsed.errors) + EXPECT_EQ(parsed.error().size(), 1); + EXPECT_EQ(parsed.error()[0].first, ErrorCode::InvalidKey); + for (auto& error : parsed.error()) { - std::cout << error.second << " " << configParseStatusToString(error.first) << std::endl; + std::cout << error.second << " " << ErrorCodeToString(error.first) << std::endl; } } } \ No newline at end of file diff --git a/test/unit/v0/test_user_defined_config.cpp b/test/unit/v0/test_user_defined_config.cpp index e72803ad..7cf1d13c 100644 --- a/test/unit/v0/test_user_defined_config.cpp +++ b/test/unit/v0/test_user_defined_config.cpp @@ -1,5 +1,9 @@ -#include -#include +// Copyright (C) 2023–2026 University Corporation for Atmospheric Research +// University of Illinois at Urbana-Champaign +// SPDX-License-Identifier: Apache-2.0 + +#include "detail/constants.hpp" +#include "detail/v0/parser.hpp" #include @@ -14,31 +18,31 @@ TEST(UserDefinedConfig, DetectsInvalidConfig) std::string file = "./v0_unit_configs/user_defined/missing_reactants/config" + extension; auto parsed = parser.Parse(file); EXPECT_FALSE(parsed); - EXPECT_EQ(parsed.errors.size(), 1); - EXPECT_EQ(parsed.errors[0].first, ConfigParseStatus::RequiredKeyNotFound); - for (auto& error : parsed.errors) + EXPECT_EQ(parsed.error().size(), 1); + EXPECT_EQ(parsed.error()[0].first, ErrorCode::RequiredKeyNotFound); + for (auto& error : parsed.error()) { - std::cout << error.second << " " << configParseStatusToString(error.first) << std::endl; + std::cout << error.second << " " << ErrorCodeToString(error.first) << std::endl; } file = "./v0_unit_configs/user_defined/missing_products/config" + extension; parsed = parser.Parse(file); EXPECT_FALSE(parsed); - EXPECT_EQ(parsed.errors.size(), 1); - EXPECT_EQ(parsed.errors[0].first, ConfigParseStatus::RequiredKeyNotFound); - for (auto& error : parsed.errors) + EXPECT_EQ(parsed.error().size(), 1); + EXPECT_EQ(parsed.error()[0].first, ErrorCode::RequiredKeyNotFound); + for (auto& error : parsed.error()) { - std::cout << error.second << " " << configParseStatusToString(error.first) << std::endl; + std::cout << error.second << " " << ErrorCodeToString(error.first) << std::endl; } file = "./v0_unit_configs/user_defined/missing_MUSICA_name/config" + extension; parsed = parser.Parse(file); EXPECT_FALSE(parsed); - EXPECT_EQ(parsed.errors.size(), 1); - EXPECT_EQ(parsed.errors[0].first, ConfigParseStatus::RequiredKeyNotFound); - for (auto& error : parsed.errors) + EXPECT_EQ(parsed.error().size(), 1); + EXPECT_EQ(parsed.error()[0].first, ErrorCode::RequiredKeyNotFound); + for (auto& error : parsed.error()) { - std::cout << error.second << " " << configParseStatusToString(error.first) << std::endl; + std::cout << error.second << " " << ErrorCodeToString(error.first) << std::endl; } } } @@ -53,7 +57,7 @@ TEST(UserDefinedConfig, ParseConfig) std::string file = "./v0_unit_configs/user_defined/valid/config" + extension; auto parsed = parser.Parse(file); EXPECT_TRUE(parsed); - v0::types::Mechanism mechanism = *parsed; + Mechanism mechanism = *parsed; auto& process_vector = mechanism.reactions.user_defined; EXPECT_EQ(process_vector.size(), 2); @@ -63,14 +67,14 @@ TEST(UserDefinedConfig, ParseConfig) // first reaction { EXPECT_EQ(process_vector[0].reactants.size(), 2); - EXPECT_EQ(process_vector[0].reactants[0].species_name, "foo"); + EXPECT_EQ(process_vector[0].reactants[0].name, "foo"); EXPECT_EQ(process_vector[0].reactants[0].coefficient, 1.0); - EXPECT_EQ(process_vector[0].reactants[1].species_name, "bar"); + EXPECT_EQ(process_vector[0].reactants[1].name, "bar"); EXPECT_EQ(process_vector[0].reactants[1].coefficient, 2.0); EXPECT_EQ(process_vector[0].products.size(), 2); - EXPECT_EQ(process_vector[0].products[0].species_name, "baz"); + EXPECT_EQ(process_vector[0].products[0].name, "baz"); EXPECT_EQ(process_vector[0].products[0].coefficient, 1.4); - EXPECT_EQ(process_vector[0].products[1].species_name, "foo"); + EXPECT_EQ(process_vector[0].products[1].name, "foo"); EXPECT_EQ(process_vector[0].products[1].coefficient, 1.0); EXPECT_EQ(process_vector[0].name, "USER.foo"); EXPECT_EQ(process_vector[0].scaling_factor, 1.0); @@ -79,10 +83,10 @@ TEST(UserDefinedConfig, ParseConfig) // second reaction { EXPECT_EQ(process_vector[1].reactants.size(), 1); - EXPECT_EQ(process_vector[1].reactants[0].species_name, "foo"); + EXPECT_EQ(process_vector[1].reactants[0].name, "foo"); EXPECT_EQ(process_vector[1].reactants[0].coefficient, 2.0); EXPECT_EQ(process_vector[1].products.size(), 1); - EXPECT_EQ(process_vector[1].products[0].species_name, "bar"); + EXPECT_EQ(process_vector[1].products[0].name, "bar"); EXPECT_EQ(process_vector[1].products[0].coefficient, 1.0); EXPECT_EQ(process_vector[1].name, "USER.bar"); EXPECT_EQ(process_vector[1].scaling_factor, 2.5); @@ -99,11 +103,11 @@ TEST(UserDefinedConfig, DetectsNonstandardKeys) std::string file = "./v0_unit_configs/user_defined/contains_nonstandard_key/config" + extension; auto parsed = parser.Parse(file); EXPECT_FALSE(parsed); - EXPECT_EQ(parsed.errors.size(), 1); - EXPECT_EQ(parsed.errors[0].first, ConfigParseStatus::InvalidKey); - for (auto& error : parsed.errors) + EXPECT_EQ(parsed.error().size(), 1); + EXPECT_EQ(parsed.error()[0].first, ErrorCode::InvalidKey); + for (auto& error : parsed.error()) { - std::cout << error.second << " " << configParseStatusToString(error.first) << std::endl; + std::cout << error.second << " " << ErrorCodeToString(error.first) << std::endl; } } } @@ -117,11 +121,11 @@ TEST(UserDefinedConfig, DetectsNonstandardProductCoefficient) std::string file = "./v0_unit_configs/user_defined/nonstandard_product_coef/config" + extension; auto parsed = parser.Parse(file); EXPECT_FALSE(parsed); - EXPECT_EQ(parsed.errors.size(), 1); - EXPECT_EQ(parsed.errors[0].first, ConfigParseStatus::InvalidKey); - for (auto& error : parsed.errors) + EXPECT_EQ(parsed.error().size(), 1); + EXPECT_EQ(parsed.error()[0].first, ErrorCode::InvalidKey); + for (auto& error : parsed.error()) { - std::cout << error.second << " " << configParseStatusToString(error.first) << std::endl; + std::cout << error.second << " " << ErrorCodeToString(error.first) << std::endl; } } } @@ -135,11 +139,11 @@ TEST(UserDefinedConfig, DetectsNonstandardReactantCoefficient) std::string file = "./v0_unit_configs/user_defined/nonstandard_reactant_coef/config" + extension; auto parsed = parser.Parse(file); EXPECT_FALSE(parsed); - EXPECT_EQ(parsed.errors.size(), 1); - EXPECT_EQ(parsed.errors[0].first, ConfigParseStatus::InvalidKey); - for (auto& error : parsed.errors) + EXPECT_EQ(parsed.error().size(), 1); + EXPECT_EQ(parsed.error()[0].first, ErrorCode::InvalidKey); + for (auto& error : parsed.error()) { - std::cout << error.second << " " << configParseStatusToString(error.first) << std::endl; + std::cout << error.second << " " << ErrorCodeToString(error.first) << std::endl; } } } diff --git a/test/unit/v1/file_configs/test_parse_from_file_configs.cpp b/test/unit/v1/file_configs/test_parse_from_file_configs.cpp index 65581477..dd0be2c9 100644 --- a/test/unit/v1/file_configs/test_parse_from_file_configs.cpp +++ b/test/unit/v1/file_configs/test_parse_from_file_configs.cpp @@ -2,8 +2,8 @@ // University of Illinois at Urbana-Champaign // SPDX-License-Identifier: Apache-2.0 -#include -#include +#include +#include #include @@ -21,8 +21,7 @@ const std::string configBase = "test/unit/v1/file_configs/configs/"; TEST(ParseFromFileConfigs, TwoSpeciesSets) { - v1::Parser parser; - auto parsed = parser.Parse(configBase + "two_species_sets/main.json"); + auto parsed = Parse(configBase + "two_species_sets/main.json"); ASSERT_TRUE(parsed); auto& mechanism = *parsed; @@ -49,8 +48,7 @@ TEST(ParseFromFileConfigs, TwoSpeciesSets) TEST(ParseFromFileConfigs, TwoPhasesSets) { - v1::Parser parser; - auto parsed = parser.Parse(configBase + "two_phases_sets/main.json"); + auto parsed = Parse(configBase + "two_phases_sets/main.json"); ASSERT_TRUE(parsed); auto& mechanism = *parsed; @@ -70,14 +68,13 @@ TEST(ParseFromFileConfigs, TwoPhasesSets) TEST(ParseFromFileConfigs, MissingPhaseSet) { - v1::Parser parser; - auto parsed = parser.Parse(configBase + "missing_phase_set/main.json"); + auto parsed = Parse(configBase + "missing_phase_set/main.json"); EXPECT_FALSE(parsed); - ASSERT_EQ(parsed.errors.size(), 1); - EXPECT_EQ(parsed.errors[0].first, ConfigParseStatus::RequiredKeyNotFound); - for (const auto& error : parsed.errors) - std::cout << error.second << " " << configParseStatusToString(error.first) << "\n"; + ASSERT_EQ(parsed.error().size(), 1); + EXPECT_EQ(parsed.error()[0].first, ErrorCode::RequiredKeyNotFound); + for (const auto& error : parsed.error()) + std::cout << error.second << " " << ErrorCodeToString(error.first) << "\n"; } // ── missing_reaction_set ────────────────────────────────────────────────────── @@ -85,8 +82,7 @@ TEST(ParseFromFileConfigs, MissingPhaseSet) TEST(ParseFromFileConfigs, MissingReactionSet) { - v1::Parser parser; - auto parsed = parser.Parse(configBase + "missing_reaction_set/main.json"); + auto parsed = Parse(configBase + "missing_reaction_set/main.json"); ASSERT_TRUE(parsed); auto& mechanism = *parsed; @@ -95,33 +91,31 @@ TEST(ParseFromFileConfigs, MissingReactionSet) } // ── missing_species_set ─────────────────────────────────────────────────────── -// "species" key absent from main.json : RequiredKeyNotFound from ValidateSchema +// "species" key absent from main.json : RequiredKeyNotFound from CheckSchema TEST(ParseFromFileConfigs, MissingSpeciesSet) { - v1::Parser parser; - auto parsed = parser.Parse(configBase + "missing_species_set/main.json"); + auto parsed = Parse(configBase + "missing_species_set/main.json"); EXPECT_FALSE(parsed); - ASSERT_EQ(parsed.errors.size(), 1); - EXPECT_EQ(parsed.errors[0].first, ConfigParseStatus::RequiredKeyNotFound); - for (const auto& error : parsed.errors) - std::cout << error.second << " " << configParseStatusToString(error.first) << "\n"; + ASSERT_EQ(parsed.error().size(), 1); + EXPECT_EQ(parsed.error()[0].first, ErrorCode::RequiredKeyNotFound); + for (const auto& error : parsed.error()) + std::cout << error.second << " " << ErrorCodeToString(error.first) << "\n"; } // ── version_mismatch ────────────────────────────────────────────────────────── -// version "1.3.0" : minor != 1 for file-list format : InvalidVersion +// version "1.0.0" : file-list layout requires minor >= 1 (v1.1+) : InvalidVersion TEST(ParseFromFileConfigs, VersionMismatch) { - v1::Parser parser; - auto parsed = parser.Parse(configBase + "version_mismatch/main.json"); + auto parsed = Parse(configBase + "version_mismatch/main.json"); EXPECT_FALSE(parsed); - ASSERT_EQ(parsed.errors.size(), 1); - EXPECT_EQ(parsed.errors[0].first, ConfigParseStatus::InvalidVersion); - for (const auto& error : parsed.errors) - std::cout << error.second << " " << configParseStatusToString(error.first) << "\n"; + ASSERT_EQ(parsed.error().size(), 1); + EXPECT_EQ(parsed.error()[0].first, ErrorCode::InvalidVersion); + for (const auto& error : parsed.error()) + std::cout << error.second << " " << ErrorCodeToString(error.first) << "\n"; } // ── mixed_inline_species ────────────────────────────────────────────────────── @@ -129,8 +123,7 @@ TEST(ParseFromFileConfigs, VersionMismatch) TEST(ParseFromFileConfigs, MixedInlineSpecies) { - v1::Parser parser; - auto parsed = parser.Parse(configBase + "mixed_inline_species/main.json"); + auto parsed = Parse(configBase + "mixed_inline_species/main.json"); ASSERT_TRUE(parsed); auto& mechanism = *parsed; @@ -152,8 +145,7 @@ TEST(ParseFromFileConfigs, MixedInlineSpecies) TEST(ParseFromFileConfigs, MixedInlineReactions) { - v1::Parser parser; - auto parsed = parser.Parse(configBase + "mixed_inline_reactions/main.json"); + auto parsed = Parse(configBase + "mixed_inline_reactions/main.json"); ASSERT_TRUE(parsed); auto& mechanism = *parsed; @@ -173,14 +165,13 @@ TEST(ParseFromFileConfigs, MixedInlineReactions) TEST(ParseFromFileConfigs, DuplicateSpeciesSet) { - v1::Parser parser; - auto parsed = parser.Parse(configBase + "duplicate_species_set/main.json"); + auto parsed = Parse(configBase + "duplicate_species_set/main.json"); EXPECT_FALSE(parsed); - ASSERT_EQ(parsed.errors.size(), 6); - for (const auto& error : parsed.errors) + ASSERT_EQ(parsed.error().size(), 6); + for (const auto& error : parsed.error()) { - EXPECT_EQ(error.first, ConfigParseStatus::DuplicateSpeciesDetected); - std::cout << error.second << " " << configParseStatusToString(error.first) << "\n"; + EXPECT_EQ(error.first, ErrorCode::DuplicateSpeciesDetected); + std::cout << error.second << " " << ErrorCodeToString(error.first) << "\n"; } } diff --git a/test/unit/v1/reactions/test_parse_arrhenius.cpp b/test/unit/v1/reactions/test_parse_arrhenius.cpp index 0ae897ae..44261204 100644 --- a/test/unit/v1/reactions/test_parse_arrhenius.cpp +++ b/test/unit/v1/reactions/test_parse_arrhenius.cpp @@ -1,4 +1,8 @@ -#include +// Copyright (C) 2023–2026 University Corporation for Atmospheric Research +// University of Illinois at Urbana-Champaign +// SPDX-License-Identifier: Apache-2.0 + +#include #include @@ -6,13 +10,12 @@ using namespace mechanism_configuration; TEST(ParserBase, CanParseValidArrheniusReaction) { - v1::Parser parser; std::vector extensions = { ".json", ".yaml" }; for (auto& extension : extensions) { - auto parsed = parser.Parse(std::string("v1_unit_configs/reactions/arrhenius/valid") + extension); + auto parsed = Parse(std::string("v1_unit_configs/reactions/arrhenius/valid") + extension); EXPECT_TRUE(parsed); - v1::types::Mechanism mechanism = *parsed; + Mechanism mechanism = *parsed; EXPECT_EQ(mechanism.reactions.arrhenius.size(), 3); @@ -24,12 +27,12 @@ TEST(ParserBase, CanParseValidArrheniusReaction) EXPECT_EQ(mechanism.reactions.arrhenius[0].D, 63.4); EXPECT_EQ(mechanism.reactions.arrhenius[0].E, -1.3); EXPECT_EQ(mechanism.reactions.arrhenius[0].reactants.size(), 1); - EXPECT_EQ(mechanism.reactions.arrhenius[0].reactants[0].species_name, "A"); + EXPECT_EQ(mechanism.reactions.arrhenius[0].reactants[0].name, "A"); EXPECT_EQ(mechanism.reactions.arrhenius[0].reactants[0].coefficient, 1); EXPECT_EQ(mechanism.reactions.arrhenius[0].products.size(), 2); - EXPECT_EQ(mechanism.reactions.arrhenius[0].products[0].species_name, "B"); + EXPECT_EQ(mechanism.reactions.arrhenius[0].products[0].name, "B"); EXPECT_EQ(mechanism.reactions.arrhenius[0].products[0].coefficient, 1.2); - EXPECT_EQ(mechanism.reactions.arrhenius[0].products[1].species_name, "C"); + EXPECT_EQ(mechanism.reactions.arrhenius[0].products[1].name, "C"); EXPECT_EQ(mechanism.reactions.arrhenius[0].products[1].coefficient, 0.3); EXPECT_EQ(mechanism.reactions.arrhenius[0].unknown_properties.size(), 1); EXPECT_EQ(mechanism.reactions.arrhenius[0].unknown_properties["__solver_param"], "0.1"); @@ -42,12 +45,12 @@ TEST(ParserBase, CanParseValidArrheniusReaction) EXPECT_EQ(mechanism.reactions.arrhenius[1].D, 6.4); EXPECT_EQ(mechanism.reactions.arrhenius[1].E, -0.3); EXPECT_EQ(mechanism.reactions.arrhenius[1].reactants.size(), 2); - EXPECT_EQ(mechanism.reactions.arrhenius[1].reactants[0].species_name, "A"); + EXPECT_EQ(mechanism.reactions.arrhenius[1].reactants[0].name, "A"); EXPECT_EQ(mechanism.reactions.arrhenius[1].reactants[0].coefficient, 2); - EXPECT_EQ(mechanism.reactions.arrhenius[1].reactants[1].species_name, "B"); + EXPECT_EQ(mechanism.reactions.arrhenius[1].reactants[1].name, "B"); EXPECT_EQ(mechanism.reactions.arrhenius[1].reactants[1].coefficient, 0.1); EXPECT_EQ(mechanism.reactions.arrhenius[1].products.size(), 1); - EXPECT_EQ(mechanism.reactions.arrhenius[1].products[0].species_name, "C"); + EXPECT_EQ(mechanism.reactions.arrhenius[1].products[0].name, "C"); EXPECT_EQ(mechanism.reactions.arrhenius[1].products[0].coefficient, 0.5); EXPECT_EQ(mechanism.reactions.arrhenius[1].products[0].unknown_properties.size(), 1); EXPECT_EQ(mechanism.reactions.arrhenius[1].products[0].unknown_properties["__optional thing"], "hello"); @@ -60,83 +63,79 @@ TEST(ParserBase, CanParseValidArrheniusReaction) EXPECT_EQ(mechanism.reactions.arrhenius[2].D, 300); EXPECT_EQ(mechanism.reactions.arrhenius[2].E, 0); EXPECT_EQ(mechanism.reactions.arrhenius[2].reactants.size(), 1); - EXPECT_EQ(mechanism.reactions.arrhenius[2].reactants[0].species_name, "A"); + EXPECT_EQ(mechanism.reactions.arrhenius[2].reactants[0].name, "A"); EXPECT_EQ(mechanism.reactions.arrhenius[2].reactants[0].coefficient, 1); EXPECT_EQ(mechanism.reactions.arrhenius[2].products.size(), 1); - EXPECT_EQ(mechanism.reactions.arrhenius[2].products[0].species_name, "C"); + EXPECT_EQ(mechanism.reactions.arrhenius[2].products[0].name, "C"); EXPECT_EQ(mechanism.reactions.arrhenius[2].products[0].coefficient, 1); } } TEST(ParserBase, ArrheniusDetectsUnknownSpecies) { - v1::Parser parser; std::vector extensions = { ".json", ".yaml" }; for (auto& extension : extensions) { std::string file = std::string("v1_unit_configs/reactions/arrhenius/unknown_species") + extension; - auto parsed = parser.Parse(file); + auto parsed = Parse(file); EXPECT_FALSE(parsed); - EXPECT_EQ(parsed.errors.size(), 1); - EXPECT_EQ(parsed.errors[0].first, ConfigParseStatus::ReactionRequiresUnknownSpecies); - for (auto& error : parsed.errors) + EXPECT_EQ(parsed.error().size(), 2); + EXPECT_EQ(parsed.error()[0].first, ErrorCode::ReactionRequiresUnknownSpecies); + for (auto& error : parsed.error()) { - std::cout << error.second << " " << configParseStatusToString(error.first) << std::endl; + std::cout << error.second << " " << ErrorCodeToString(error.first) << std::endl; } } } TEST(ParserBase, ArrheniusDetectsMutuallyExclusiveOptions) { - v1::Parser parser; std::vector extensions = { ".json", ".yaml" }; for (auto& extension : extensions) { std::string file = std::string("v1_unit_configs/reactions/arrhenius/mutually_exclusive") + extension; - auto parsed = parser.Parse(file); + auto parsed = Parse(file); EXPECT_FALSE(parsed); - EXPECT_EQ(parsed.errors.size(), 1); - EXPECT_EQ(parsed.errors[0].first, ConfigParseStatus::MutuallyExclusiveOption); - for (auto& error : parsed.errors) + EXPECT_EQ(parsed.error().size(), 1); + EXPECT_EQ(parsed.error()[0].first, ErrorCode::MutuallyExclusiveOption); + for (auto& error : parsed.error()) { - std::cout << error.second << " " << configParseStatusToString(error.first) << std::endl; + std::cout << error.second << " " << ErrorCodeToString(error.first) << std::endl; } } } TEST(ParserBase, ArrheniusDetectsBadReactionComponent) { - v1::Parser parser; std::vector extensions = { ".json", ".yaml" }; for (auto& extension : extensions) { std::string file = std::string("v1_unit_configs/reactions/arrhenius/bad_reaction_component") + extension; - auto parsed = parser.Parse(file); + auto parsed = Parse(file); EXPECT_FALSE(parsed); - EXPECT_EQ(parsed.errors.size(), 2); - EXPECT_EQ(parsed.errors[0].first, ConfigParseStatus::RequiredKeyNotFound); - EXPECT_EQ(parsed.errors[1].first, ConfigParseStatus::InvalidKey); - for (auto& error : parsed.errors) + EXPECT_EQ(parsed.error().size(), 2); + EXPECT_EQ(parsed.error()[0].first, ErrorCode::RequiredKeyNotFound); + EXPECT_EQ(parsed.error()[1].first, ErrorCode::InvalidKey); + for (auto& error : parsed.error()) { - std::cout << error.second << " " << configParseStatusToString(error.first) << std::endl; + std::cout << error.second << " " << ErrorCodeToString(error.first) << std::endl; } } } TEST(ParserBase, ArrheniusDetectsUnknownPhase) { - v1::Parser parser; std::vector extensions = { ".json", ".yaml" }; for (auto& extension : extensions) { std::string file = std::string("v1_unit_configs/reactions/arrhenius/missing_phase") + extension; - auto parsed = parser.Parse(file); + auto parsed = Parse(file); EXPECT_FALSE(parsed); - EXPECT_EQ(parsed.errors.size(), 1); - EXPECT_EQ(parsed.errors[0].first, ConfigParseStatus::UnknownPhase); - for (auto& error : parsed.errors) + EXPECT_EQ(parsed.error().size(), 1); + EXPECT_EQ(parsed.error()[0].first, ErrorCode::UnknownPhase); + for (auto& error : parsed.error()) { - std::cout << error.second << " " << configParseStatusToString(error.first) << std::endl; + std::cout << error.second << " " << ErrorCodeToString(error.first) << std::endl; } } -} \ No newline at end of file +} diff --git a/test/unit/v1/reactions/test_parse_branched.cpp b/test/unit/v1/reactions/test_parse_branched.cpp index ec8de691..ea201cbf 100644 --- a/test/unit/v1/reactions/test_parse_branched.cpp +++ b/test/unit/v1/reactions/test_parse_branched.cpp @@ -1,4 +1,8 @@ -#include +// Copyright (C) 2023–2026 University Corporation for Atmospheric Research +// University of Illinois at Urbana-Champaign +// SPDX-License-Identifier: Apache-2.0 + +#include #include @@ -6,13 +10,12 @@ using namespace mechanism_configuration; TEST(ParserBase, CanParseValidBranchedReaction) { - v1::Parser parser; std::vector extensions = { ".json", ".yaml" }; for (auto& extension : extensions) { - auto parsed = parser.Parse(std::string("v1_unit_configs/reactions/branched/valid") + extension); + auto parsed = Parse(std::string("v1_unit_configs/reactions/branched/valid") + extension); EXPECT_TRUE(parsed); - v1::types::Mechanism mechanism = *parsed; + Mechanism mechanism = *parsed; EXPECT_EQ(mechanism.reactions.branched.size(), 1); @@ -23,17 +26,17 @@ TEST(ParserBase, CanParseValidBranchedReaction) EXPECT_EQ(mechanism.reactions.branched[0].a0, 0.15); EXPECT_EQ(mechanism.reactions.branched[0].n, 9); EXPECT_EQ(mechanism.reactions.branched[0].reactants.size(), 1); - EXPECT_EQ(mechanism.reactions.branched[0].reactants[0].species_name, "A"); + EXPECT_EQ(mechanism.reactions.branched[0].reactants[0].name, "A"); EXPECT_EQ(mechanism.reactions.branched[0].reactants[0].coefficient, 1); EXPECT_EQ(mechanism.reactions.branched[0].nitrate_products.size(), 1); - EXPECT_EQ(mechanism.reactions.branched[0].nitrate_products[0].species_name, "C"); + EXPECT_EQ(mechanism.reactions.branched[0].nitrate_products[0].name, "C"); EXPECT_EQ(mechanism.reactions.branched[0].nitrate_products[0].coefficient, 1.2); EXPECT_EQ(mechanism.reactions.branched[0].nitrate_products[0].unknown_properties.size(), 1); EXPECT_EQ(mechanism.reactions.branched[0].nitrate_products[0].unknown_properties["__thing"], "hi"); EXPECT_EQ(mechanism.reactions.branched[0].alkoxy_products.size(), 2); - EXPECT_EQ(mechanism.reactions.branched[0].alkoxy_products[0].species_name, "B"); + EXPECT_EQ(mechanism.reactions.branched[0].alkoxy_products[0].name, "B"); EXPECT_EQ(mechanism.reactions.branched[0].alkoxy_products[0].coefficient, 0.2); - EXPECT_EQ(mechanism.reactions.branched[0].alkoxy_products[1].species_name, "A"); + EXPECT_EQ(mechanism.reactions.branched[0].alkoxy_products[1].name, "A"); EXPECT_EQ(mechanism.reactions.branched[0].alkoxy_products[1].coefficient, 1.2); EXPECT_EQ(mechanism.reactions.branched[0].unknown_properties.size(), 1); EXPECT_EQ(mechanism.reactions.branched[0].unknown_properties["__comment"], "thing"); @@ -42,56 +45,52 @@ TEST(ParserBase, CanParseValidBranchedReaction) TEST(ParserBase, BranchedDetectsUnknownSpecies) { - v1::Parser parser; std::vector extensions = { ".json", ".yaml" }; for (auto& extension : extensions) { std::string file = std::string("v1_unit_configs/reactions/branched/unknown_species") + extension; - auto parsed = parser.Parse(file); + auto parsed = Parse(file); EXPECT_FALSE(parsed); - EXPECT_EQ(parsed.errors.size(), 1); - EXPECT_EQ(parsed.errors[0].first, ConfigParseStatus::ReactionRequiresUnknownSpecies); - for (auto& error : parsed.errors) + EXPECT_EQ(parsed.error().size(), 1); + EXPECT_EQ(parsed.error()[0].first, ErrorCode::ReactionRequiresUnknownSpecies); + for (auto& error : parsed.error()) { - std::cout << error.second << " " << configParseStatusToString(error.first) << std::endl; + std::cout << error.second << " " << ErrorCodeToString(error.first) << std::endl; } } } TEST(ParserBase, BranchedDetectsBadReactionComponent) { - v1::Parser parser; std::vector extensions = { ".json", ".yaml" }; for (auto& extension : extensions) { std::string file = std::string("v1_unit_configs/reactions/branched/bad_reaction_component") + extension; - auto parsed = parser.Parse(file); + auto parsed = Parse(file); EXPECT_FALSE(parsed); - EXPECT_EQ(parsed.errors.size(), 3); - EXPECT_EQ(parsed.errors[0].first, ConfigParseStatus::RequiredKeyNotFound); - EXPECT_EQ(parsed.errors[1].first, ConfigParseStatus::InvalidKey); - EXPECT_EQ(parsed.errors[2].first, ConfigParseStatus::ReactionRequiresUnknownSpecies); - for (auto& error : parsed.errors) + EXPECT_EQ(parsed.error().size(), 2); + EXPECT_EQ(parsed.error()[0].first, ErrorCode::RequiredKeyNotFound); + EXPECT_EQ(parsed.error()[1].first, ErrorCode::InvalidKey); + for (auto& error : parsed.error()) { - std::cout << error.second << " " << configParseStatusToString(error.first) << std::endl; + std::cout << error.second << " " << ErrorCodeToString(error.first) << std::endl; } } } TEST(ParserBase, BranchedDetectsUnknownPhase) { - v1::Parser parser; std::vector extensions = { ".json", ".yaml" }; for (auto& extension : extensions) { std::string file = std::string("v1_unit_configs/reactions/branched/missing_phase") + extension; - auto parsed = parser.Parse(file); + auto parsed = Parse(file); EXPECT_FALSE(parsed); - EXPECT_EQ(parsed.errors.size(), 1); - EXPECT_EQ(parsed.errors[0].first, ConfigParseStatus::UnknownPhase); - for (auto& error : parsed.errors) + EXPECT_EQ(parsed.error().size(), 1); + EXPECT_EQ(parsed.error()[0].first, ErrorCode::UnknownPhase); + for (auto& error : parsed.error()) { - std::cout << error.second << " " << configParseStatusToString(error.first) << std::endl; + std::cout << error.second << " " << ErrorCodeToString(error.first) << std::endl; } } -} \ No newline at end of file +} diff --git a/test/unit/v1/reactions/test_parse_emission.cpp b/test/unit/v1/reactions/test_parse_emission.cpp index 8a27759d..6f1cde84 100644 --- a/test/unit/v1/reactions/test_parse_emission.cpp +++ b/test/unit/v1/reactions/test_parse_emission.cpp @@ -1,4 +1,8 @@ -#include +// Copyright (C) 2023–2026 University Corporation for Atmospheric Research +// University of Illinois at Urbana-Champaign +// SPDX-License-Identifier: Apache-2.0 + +#include #include @@ -6,13 +10,12 @@ using namespace mechanism_configuration; TEST(ParserBase, CanParseValidEmissionReaction) { - v1::Parser parser; std::vector extensions = { ".json", ".yaml" }; for (auto& extension : extensions) { - auto parsed = parser.Parse(std::string("v1_unit_configs/reactions/emission/valid") + extension); + auto parsed = Parse(std::string("v1_unit_configs/reactions/emission/valid") + extension); EXPECT_TRUE(parsed); - v1::types::Mechanism mechanism = *parsed; + Mechanism mechanism = *parsed; EXPECT_EQ(mechanism.reactions.emission.size(), 2); @@ -20,7 +23,7 @@ TEST(ParserBase, CanParseValidEmissionReaction) EXPECT_EQ(mechanism.reactions.emission[0].name, "my emission"); EXPECT_EQ(mechanism.reactions.emission[0].scaling_factor, 12.3); EXPECT_EQ(mechanism.reactions.emission[0].products.size(), 1); - EXPECT_EQ(mechanism.reactions.emission[0].products[0].species_name, "B"); + EXPECT_EQ(mechanism.reactions.emission[0].products[0].name, "B"); EXPECT_EQ(mechanism.reactions.emission[0].products[0].coefficient, 1); EXPECT_EQ(mechanism.reactions.emission[0].unknown_properties.size(), 1); EXPECT_EQ(mechanism.reactions.emission[0].unknown_properties["__comment"], "Dr. Pepper outranks any other soda"); @@ -28,62 +31,59 @@ TEST(ParserBase, CanParseValidEmissionReaction) EXPECT_EQ(mechanism.reactions.emission[1].gas_phase, "gas"); EXPECT_EQ(mechanism.reactions.emission[1].scaling_factor, 1); EXPECT_EQ(mechanism.reactions.emission[1].products.size(), 1); - EXPECT_EQ(mechanism.reactions.emission[1].products[0].species_name, "B"); + EXPECT_EQ(mechanism.reactions.emission[1].products[0].name, "B"); EXPECT_EQ(mechanism.reactions.emission[1].products[0].coefficient, 1); } } TEST(ParserBase, EmissionDetectsUnknownSpecies) { - v1::Parser parser; std::vector extensions = { ".json", ".yaml" }; for (auto& extension : extensions) { std::string file = std::string("v1_unit_configs/reactions/emission/unknown_species") + extension; - auto parsed = parser.Parse(file); + auto parsed = Parse(file); EXPECT_FALSE(parsed); - EXPECT_EQ(parsed.errors.size(), 1); - EXPECT_EQ(parsed.errors[0].first, ConfigParseStatus::ReactionRequiresUnknownSpecies); - for (auto& error : parsed.errors) + EXPECT_EQ(parsed.error().size(), 1); + EXPECT_EQ(parsed.error()[0].first, ErrorCode::ReactionRequiresUnknownSpecies); + for (auto& error : parsed.error()) { - std::cout << error.second << " " << configParseStatusToString(error.first) << std::endl; + std::cout << error.second << " " << ErrorCodeToString(error.first) << std::endl; } } } TEST(ParserBase, EmissionDetectsBadReactionComponent) { - v1::Parser parser; std::vector extensions = { ".json", ".yaml" }; for (auto& extension : extensions) { std::string file = std::string("v1_unit_configs/reactions/emission/bad_reaction_component") + extension; - auto parsed = parser.Parse(file); + auto parsed = Parse(file); EXPECT_FALSE(parsed); - EXPECT_EQ(parsed.errors.size(), 2); - EXPECT_EQ(parsed.errors[0].first, ConfigParseStatus::RequiredKeyNotFound); - EXPECT_EQ(parsed.errors[1].first, ConfigParseStatus::InvalidKey); - for (auto& error : parsed.errors) + EXPECT_EQ(parsed.error().size(), 2); + EXPECT_EQ(parsed.error()[0].first, ErrorCode::RequiredKeyNotFound); + EXPECT_EQ(parsed.error()[1].first, ErrorCode::InvalidKey); + for (auto& error : parsed.error()) { - std::cout << error.second << " " << configParseStatusToString(error.first) << std::endl; + std::cout << error.second << " " << ErrorCodeToString(error.first) << std::endl; } } } TEST(ParserBase, EmissionDetectsUnknownPhase) { - v1::Parser parser; std::vector extensions = { ".json", ".yaml" }; for (auto& extension : extensions) { std::string file = std::string("v1_unit_configs/reactions/emission/missing_phase") + extension; - auto parsed = parser.Parse(file); + auto parsed = Parse(file); EXPECT_FALSE(parsed); - EXPECT_EQ(parsed.errors.size(), 1); - EXPECT_EQ(parsed.errors[0].first, ConfigParseStatus::UnknownPhase); - for (auto& error : parsed.errors) + EXPECT_EQ(parsed.error().size(), 1); + EXPECT_EQ(parsed.error()[0].first, ErrorCode::UnknownPhase); + for (auto& error : parsed.error()) { - std::cout << error.second << " " << configParseStatusToString(error.first) << std::endl; + std::cout << error.second << " " << ErrorCodeToString(error.first) << std::endl; } } -} \ No newline at end of file +} diff --git a/test/unit/v1/reactions/test_parse_first_order_loss.cpp b/test/unit/v1/reactions/test_parse_first_order_loss.cpp index 52df3133..de8f2238 100644 --- a/test/unit/v1/reactions/test_parse_first_order_loss.cpp +++ b/test/unit/v1/reactions/test_parse_first_order_loss.cpp @@ -1,4 +1,8 @@ -#include +// Copyright (C) 2023–2026 University Corporation for Atmospheric Research +// University of Illinois at Urbana-Champaign +// SPDX-License-Identifier: Apache-2.0 + +#include #include @@ -6,129 +10,120 @@ using namespace mechanism_configuration; TEST(ParserBase, CanParseValidFirstOrderLossReaction) { - v1::Parser parser; std::vector extensions = { ".json", ".yaml" }; for (auto& extension : extensions) { - auto parsed = parser.Parse(std::string("v1_unit_configs/reactions/first_order_loss/valid") + extension); + auto parsed = Parse(std::string("v1_unit_configs/reactions/first_order_loss/valid") + extension); EXPECT_TRUE(parsed); - v1::types::Mechanism mechanism = *parsed; + Mechanism mechanism = *parsed; EXPECT_EQ(mechanism.reactions.first_order_loss.size(), 2); EXPECT_EQ(mechanism.reactions.first_order_loss[0].gas_phase, "gas"); EXPECT_EQ(mechanism.reactions.first_order_loss[0].name, "my first order loss"); EXPECT_EQ(mechanism.reactions.first_order_loss[0].scaling_factor, 12.3); - EXPECT_EQ(mechanism.reactions.first_order_loss[0].reactants.size(), 1); - EXPECT_EQ(mechanism.reactions.first_order_loss[0].reactants[0].species_name, "C"); - EXPECT_EQ(mechanism.reactions.first_order_loss[0].reactants[0].coefficient, 1); + EXPECT_EQ(mechanism.reactions.first_order_loss[0].reactants.name, "C"); + EXPECT_EQ(mechanism.reactions.first_order_loss[0].reactants.coefficient, 1); EXPECT_EQ(mechanism.reactions.first_order_loss[0].unknown_properties.size(), 1); EXPECT_EQ( mechanism.reactions.first_order_loss[0].unknown_properties["__comment"], "Strawberries are the superior fruit"); EXPECT_EQ(mechanism.reactions.first_order_loss[1].gas_phase, "gas"); EXPECT_EQ(mechanism.reactions.first_order_loss[1].scaling_factor, 1); - EXPECT_EQ(mechanism.reactions.first_order_loss[1].reactants.size(), 1); - EXPECT_EQ(mechanism.reactions.first_order_loss[1].reactants[0].species_name, "C"); - EXPECT_EQ(mechanism.reactions.first_order_loss[1].reactants[0].coefficient, 1); + EXPECT_EQ(mechanism.reactions.first_order_loss[1].reactants.name, "C"); + EXPECT_EQ(mechanism.reactions.first_order_loss[1].reactants.coefficient, 1); } } TEST(ParserBase, FirstOrderLossDetectsUnknownSpecies) { - v1::Parser parser; std::vector extensions = { ".json", ".yaml" }; for (auto& extension : extensions) { std::string file = std::string("v1_unit_configs/reactions/first_order_loss/unknown_species") + extension; - auto parsed = parser.Parse(file); + auto parsed = Parse(file); EXPECT_FALSE(parsed); - EXPECT_EQ(parsed.errors.size(), 1); - EXPECT_EQ(parsed.errors[0].first, ConfigParseStatus::ReactionRequiresUnknownSpecies); - for (auto& error : parsed.errors) + EXPECT_EQ(parsed.error().size(), 1); + EXPECT_EQ(parsed.error()[0].first, ErrorCode::ReactionRequiresUnknownSpecies); + for (auto& error : parsed.error()) { - std::cout << error.second << " " << configParseStatusToString(error.first) << std::endl; + std::cout << error.second << " " << ErrorCodeToString(error.first) << std::endl; } } } TEST(ParserBase, FirstOrderLossDetectsBadReactionComponent) { - v1::Parser parser; std::vector extensions = { ".json", ".yaml" }; for (auto& extension : extensions) { std::string file = std::string("v1_unit_configs/reactions/first_order_loss/bad_reaction_component") + extension; - auto parsed = parser.Parse(file); + auto parsed = Parse(file); EXPECT_FALSE(parsed); - EXPECT_EQ(parsed.errors.size(), 2); - EXPECT_EQ(parsed.errors[0].first, ConfigParseStatus::RequiredKeyNotFound); - EXPECT_EQ(parsed.errors[1].first, ConfigParseStatus::InvalidKey); - for (auto& error : parsed.errors) + EXPECT_EQ(parsed.error().size(), 2); + EXPECT_EQ(parsed.error()[0].first, ErrorCode::RequiredKeyNotFound); + EXPECT_EQ(parsed.error()[1].first, ErrorCode::InvalidKey); + for (auto& error : parsed.error()) { - std::cout << error.second << " " << configParseStatusToString(error.first) << std::endl; + std::cout << error.second << " " << ErrorCodeToString(error.first) << std::endl; } } } TEST(ParserBase, FirstOrderLossDetectsUnknownPhase) { - v1::Parser parser; std::vector extensions = { ".json", ".yaml" }; for (auto& extension : extensions) { std::string file = std::string("v1_unit_configs/reactions/first_order_loss/missing_phase") + extension; - auto parsed = parser.Parse(file); + auto parsed = Parse(file); EXPECT_FALSE(parsed); - EXPECT_EQ(parsed.errors.size(), 1); - EXPECT_EQ(parsed.errors[0].first, ConfigParseStatus::UnknownPhase); - for (auto& error : parsed.errors) + EXPECT_EQ(parsed.error().size(), 1); + EXPECT_EQ(parsed.error()[0].first, ErrorCode::UnknownPhase); + for (auto& error : parsed.error()) { - std::cout << error.second << " " << configParseStatusToString(error.first) << std::endl; + std::cout << error.second << " " << ErrorCodeToString(error.first) << std::endl; } } } TEST(ParserBase, FirstOrderLossDetectsMoreThanOneSpecies) { - v1::Parser parser; std::vector extensions = { ".json", ".yaml" }; for (auto& extension : extensions) { std::string file = std::string("v1_unit_configs/reactions/first_order_loss/too_many_reactants") + extension; - auto parsed = parser.Parse(file); + auto parsed = Parse(file); EXPECT_FALSE(parsed); - EXPECT_EQ(parsed.errors.size(), 1); - EXPECT_EQ(parsed.errors[0].first, ConfigParseStatus::TooManyReactionComponents); - for (auto& error : parsed.errors) + EXPECT_EQ(parsed.error().size(), 1); + EXPECT_EQ(parsed.error()[0].first, ErrorCode::TooManyReactionComponents); + for (auto& error : parsed.error()) { - std::cout << error.second << " " << configParseStatusToString(error.first) << std::endl; + std::cout << error.second << " " << ErrorCodeToString(error.first) << std::endl; } } } TEST(ParserBase, CanParseValidFirstOrderLossReactionWithProducts) { - v1::Parser parser; std::vector extensions = { ".json", ".yaml" }; for (auto& extension : extensions) { - auto parsed = parser.Parse(std::string("v1_unit_configs/reactions/first_order_loss/products") + extension); + auto parsed = Parse(std::string("v1_unit_configs/reactions/first_order_loss/products") + extension); EXPECT_TRUE(parsed); - v1::types::Mechanism mechanism = *parsed; + Mechanism mechanism = *parsed; EXPECT_EQ(mechanism.reactions.first_order_loss.size(), 2); EXPECT_EQ(mechanism.reactions.first_order_loss[0].gas_phase, "gas"); EXPECT_EQ(mechanism.reactions.first_order_loss[0].name, "my first order loss"); EXPECT_EQ(mechanism.reactions.first_order_loss[0].scaling_factor, 12.3); - EXPECT_EQ(mechanism.reactions.first_order_loss[0].reactants.size(), 1); - EXPECT_EQ(mechanism.reactions.first_order_loss[0].reactants[0].species_name, "C"); - EXPECT_EQ(mechanism.reactions.first_order_loss[0].reactants[0].coefficient, 1); + EXPECT_EQ(mechanism.reactions.first_order_loss[0].reactants.name, "C"); + EXPECT_EQ(mechanism.reactions.first_order_loss[0].reactants.coefficient, 1); EXPECT_EQ(mechanism.reactions.first_order_loss[0].products.size(), 2); - EXPECT_EQ(mechanism.reactions.first_order_loss[0].products[0].species_name, "A"); + EXPECT_EQ(mechanism.reactions.first_order_loss[0].products[0].name, "A"); EXPECT_EQ(mechanism.reactions.first_order_loss[0].products[0].coefficient, 1); - EXPECT_EQ(mechanism.reactions.first_order_loss[0].products[1].species_name, "B"); + EXPECT_EQ(mechanism.reactions.first_order_loss[0].products[1].name, "B"); EXPECT_EQ(mechanism.reactions.first_order_loss[0].products[1].coefficient, 2); EXPECT_EQ(mechanism.reactions.first_order_loss[0].unknown_properties.size(), 1); EXPECT_EQ( @@ -136,8 +131,7 @@ TEST(ParserBase, CanParseValidFirstOrderLossReactionWithProducts) EXPECT_EQ(mechanism.reactions.first_order_loss[1].gas_phase, "gas"); EXPECT_EQ(mechanism.reactions.first_order_loss[1].scaling_factor, 1); - EXPECT_EQ(mechanism.reactions.first_order_loss[1].reactants.size(), 1); - EXPECT_EQ(mechanism.reactions.first_order_loss[1].reactants[0].species_name, "C"); - EXPECT_EQ(mechanism.reactions.first_order_loss[1].reactants[0].coefficient, 1); + EXPECT_EQ(mechanism.reactions.first_order_loss[1].reactants.name, "C"); + EXPECT_EQ(mechanism.reactions.first_order_loss[1].reactants.coefficient, 1); } -} \ No newline at end of file +} diff --git a/test/unit/v1/reactions/test_parse_lambda_rate_constant.cpp b/test/unit/v1/reactions/test_parse_lambda_rate_constant.cpp index 57ebfba0..b39a32a8 100644 --- a/test/unit/v1/reactions/test_parse_lambda_rate_constant.cpp +++ b/test/unit/v1/reactions/test_parse_lambda_rate_constant.cpp @@ -2,7 +2,7 @@ // University of Illinois at Urbana-Champaign // SPDX-License-Identifier: Apache-2.0 -#include +#include #include @@ -10,13 +10,12 @@ using namespace mechanism_configuration; TEST(ParserBase, CanParseValidLambdaRateConstantReaction) { - v1::Parser parser; std::vector extensions = { ".json", ".yaml" }; for (auto& extension : extensions) { - auto parsed = parser.Parse(std::string("v1_unit_configs/reactions/lambda_rate_constant/valid") + extension); + auto parsed = Parse(std::string("v1_unit_configs/reactions/lambda_rate_constant/valid") + extension); EXPECT_TRUE(parsed); - v1::types::Mechanism mechanism = *parsed; + Mechanism mechanism = *parsed; EXPECT_EQ(mechanism.reactions.lambda_rate_constant.size(), 2); @@ -26,10 +25,10 @@ TEST(ParserBase, CanParseValidLambdaRateConstantReaction) mechanism.reactions.lambda_rate_constant[0].lambda_function, "[](double T, double P) { return 1.2e-5 * exp(-500.0 / T); }"); EXPECT_EQ(mechanism.reactions.lambda_rate_constant[0].reactants.size(), 1); - EXPECT_EQ(mechanism.reactions.lambda_rate_constant[0].reactants[0].species_name, "B"); + EXPECT_EQ(mechanism.reactions.lambda_rate_constant[0].reactants[0].name, "B"); EXPECT_EQ(mechanism.reactions.lambda_rate_constant[0].reactants[0].coefficient, 1); EXPECT_EQ(mechanism.reactions.lambda_rate_constant[0].products.size(), 1); - EXPECT_EQ(mechanism.reactions.lambda_rate_constant[0].products[0].species_name, "C"); + EXPECT_EQ(mechanism.reactions.lambda_rate_constant[0].products[0].name, "C"); EXPECT_EQ(mechanism.reactions.lambda_rate_constant[0].products[0].coefficient, 1); EXPECT_EQ(mechanism.reactions.lambda_rate_constant[0].unknown_properties.size(), 1); EXPECT_EQ(mechanism.reactions.lambda_rate_constant[0].unknown_properties["__comment"], "hi"); @@ -38,66 +37,63 @@ TEST(ParserBase, CanParseValidLambdaRateConstantReaction) EXPECT_EQ(mechanism.reactions.lambda_rate_constant[1].name, ""); EXPECT_EQ(mechanism.reactions.lambda_rate_constant[1].lambda_function, "[](double T) { return 3.0e-4 * T; }"); EXPECT_EQ(mechanism.reactions.lambda_rate_constant[1].reactants.size(), 2); - EXPECT_EQ(mechanism.reactions.lambda_rate_constant[1].reactants[0].species_name, "B"); + EXPECT_EQ(mechanism.reactions.lambda_rate_constant[1].reactants[0].name, "B"); EXPECT_EQ(mechanism.reactions.lambda_rate_constant[1].reactants[0].coefficient, 1.2); - EXPECT_EQ(mechanism.reactions.lambda_rate_constant[1].reactants[1].species_name, "A"); + EXPECT_EQ(mechanism.reactions.lambda_rate_constant[1].reactants[1].name, "A"); EXPECT_EQ(mechanism.reactions.lambda_rate_constant[1].reactants[1].coefficient, 0.5); EXPECT_EQ(mechanism.reactions.lambda_rate_constant[1].products.size(), 1); - EXPECT_EQ(mechanism.reactions.lambda_rate_constant[1].products[0].species_name, "C"); + EXPECT_EQ(mechanism.reactions.lambda_rate_constant[1].products[0].name, "C"); EXPECT_EQ(mechanism.reactions.lambda_rate_constant[1].products[0].coefficient, 0.2); } } TEST(ParserBase, LambdaRateConstantDetectsUnknownSpecies) { - v1::Parser parser; std::vector extensions = { ".json", ".yaml" }; for (auto& extension : extensions) { std::string file = std::string("v1_unit_configs/reactions/lambda_rate_constant/unknown_species") + extension; - auto parsed = parser.Parse(file); + auto parsed = Parse(file); EXPECT_FALSE(parsed); - EXPECT_EQ(parsed.errors.size(), 1); - EXPECT_EQ(parsed.errors[0].first, ConfigParseStatus::ReactionRequiresUnknownSpecies); - for (auto& error : parsed.errors) + EXPECT_EQ(parsed.error().size(), 1); + EXPECT_EQ(parsed.error()[0].first, ErrorCode::ReactionRequiresUnknownSpecies); + for (auto& error : parsed.error()) { - std::cout << error.second << " " << configParseStatusToString(error.first) << std::endl; + std::cout << error.second << " " << ErrorCodeToString(error.first) << std::endl; } } } TEST(ParserBase, LambdaRateConstantDetectsBadReactionComponent) { - v1::Parser parser; std::vector extensions = { ".json", ".yaml" }; for (auto& extension : extensions) { std::string file = std::string("v1_unit_configs/reactions/lambda_rate_constant/bad_reaction_component") + extension; - auto parsed = parser.Parse(file); + auto parsed = Parse(file); EXPECT_FALSE(parsed); - EXPECT_EQ(parsed.errors.size(), 1); - EXPECT_EQ(parsed.errors[0].first, ConfigParseStatus::InvalidKey); - for (auto& error : parsed.errors) + EXPECT_EQ(parsed.error().size(), 1); + EXPECT_EQ(parsed.error()[0].first, ErrorCode::InvalidKey); + for (auto& error : parsed.error()) { - std::cout << error.second << " " << configParseStatusToString(error.first) << std::endl; + std::cout << error.second << " " << ErrorCodeToString(error.first) << std::endl; } } } TEST(ParserBase, LambdaRateConstantDetectsUnknownPhase) { - v1::Parser parser; std::vector extensions = { ".json", ".yaml" }; for (auto& extension : extensions) { std::string file = std::string("v1_unit_configs/reactions/lambda_rate_constant/missing_phase") + extension; - auto parsed = parser.Parse(file); + auto parsed = Parse(file); EXPECT_FALSE(parsed); - EXPECT_EQ(parsed.errors.size(), 1); - EXPECT_EQ(parsed.errors[0].first, ConfigParseStatus::UnknownPhase); - for (auto& error : parsed.errors) + EXPECT_EQ(parsed.error().size(), 1); + EXPECT_EQ(parsed.error()[0].first, ErrorCode::UnknownPhase); + for (auto& error : parsed.error()) { - std::cout << error.second << " " << configParseStatusToString(error.first) << std::endl; + std::cout << error.second << " " << ErrorCodeToString(error.first) << std::endl; } } } diff --git a/test/unit/v1/reactions/test_parse_photolysis.cpp b/test/unit/v1/reactions/test_parse_photolysis.cpp index ed7a4fb0..c36e91cc 100644 --- a/test/unit/v1/reactions/test_parse_photolysis.cpp +++ b/test/unit/v1/reactions/test_parse_photolysis.cpp @@ -1,4 +1,8 @@ -#include +// Copyright (C) 2023–2026 University Corporation for Atmospheric Research +// University of Illinois at Urbana-Champaign +// SPDX-License-Identifier: Apache-2.0 + +#include #include @@ -6,107 +10,100 @@ using namespace mechanism_configuration; TEST(ParserBase, CanParseValidPhotolysisReaction) { - v1::Parser parser; std::vector extensions = { ".json", ".yaml" }; for (auto& extension : extensions) { - auto parsed = parser.Parse(std::string("v1_unit_configs/reactions/photolysis/valid") + extension); + auto parsed = Parse(std::string("v1_unit_configs/reactions/photolysis/valid") + extension); EXPECT_TRUE(parsed); - v1::types::Mechanism mechanism = *parsed; + Mechanism mechanism = *parsed; EXPECT_EQ(mechanism.reactions.photolysis.size(), 2); EXPECT_EQ(mechanism.reactions.photolysis[0].gas_phase, "gas"); EXPECT_EQ(mechanism.reactions.photolysis[0].name, "my photolysis"); EXPECT_EQ(mechanism.reactions.photolysis[0].scaling_factor, 12.3); - EXPECT_EQ(mechanism.reactions.photolysis[0].reactants.size(), 1); - EXPECT_EQ(mechanism.reactions.photolysis[0].reactants[0].species_name, "B"); - EXPECT_EQ(mechanism.reactions.photolysis[0].reactants[0].coefficient, 1); + EXPECT_EQ(mechanism.reactions.photolysis[0].reactants.name, "B"); + EXPECT_EQ(mechanism.reactions.photolysis[0].reactants.coefficient, 1); EXPECT_EQ(mechanism.reactions.photolysis[0].products.size(), 1); - EXPECT_EQ(mechanism.reactions.photolysis[0].products[0].species_name, "C"); + EXPECT_EQ(mechanism.reactions.photolysis[0].products[0].name, "C"); EXPECT_EQ(mechanism.reactions.photolysis[0].products[0].coefficient, 1); EXPECT_EQ(mechanism.reactions.photolysis[0].unknown_properties.size(), 1); EXPECT_EQ(mechanism.reactions.photolysis[0].unknown_properties["__comment"], "hi"); EXPECT_EQ(mechanism.reactions.photolysis[1].gas_phase, "gas"); EXPECT_EQ(mechanism.reactions.photolysis[1].scaling_factor, 1); - EXPECT_EQ(mechanism.reactions.photolysis[1].reactants.size(), 1); - EXPECT_EQ(mechanism.reactions.photolysis[1].reactants[0].species_name, "B"); - EXPECT_EQ(mechanism.reactions.photolysis[1].reactants[0].coefficient, 1.2); + EXPECT_EQ(mechanism.reactions.photolysis[1].reactants.name, "B"); + EXPECT_EQ(mechanism.reactions.photolysis[1].reactants.coefficient, 1.2); EXPECT_EQ(mechanism.reactions.photolysis[1].products.size(), 1); - EXPECT_EQ(mechanism.reactions.photolysis[1].products[0].species_name, "C"); + EXPECT_EQ(mechanism.reactions.photolysis[1].products[0].name, "C"); EXPECT_EQ(mechanism.reactions.photolysis[1].products[0].coefficient, 0.2); } } TEST(ParserBase, PhotolysisDetectsUnknownSpecies) { - v1::Parser parser; std::vector extensions = { ".json", ".yaml" }; for (auto& extension : extensions) { std::string file = std::string("v1_unit_configs/reactions/photolysis/unknown_species") + extension; - auto parsed = parser.Parse(file); + auto parsed = Parse(file); EXPECT_FALSE(parsed); - EXPECT_EQ(parsed.errors.size(), 1); - EXPECT_EQ(parsed.errors[0].first, ConfigParseStatus::ReactionRequiresUnknownSpecies); - for (auto& error : parsed.errors) + EXPECT_EQ(parsed.error().size(), 1); + EXPECT_EQ(parsed.error()[0].first, ErrorCode::ReactionRequiresUnknownSpecies); + for (auto& error : parsed.error()) { - std::cout << error.second << " " << configParseStatusToString(error.first) << std::endl; + std::cout << error.second << " " << ErrorCodeToString(error.first) << std::endl; } } } TEST(ParserBase, PhotolysisDetectsBadReactionComponent) { - v1::Parser parser; std::vector extensions = { ".json", ".yaml" }; for (auto& extension : extensions) { std::string file = std::string("v1_unit_configs/reactions/photolysis/bad_reaction_component") + extension; - auto parsed = parser.Parse(file); + auto parsed = Parse(file); EXPECT_FALSE(parsed); - EXPECT_EQ(parsed.errors.size(), 1); - EXPECT_EQ(parsed.errors[0].first, ConfigParseStatus::InvalidKey); - for (auto& error : parsed.errors) + EXPECT_EQ(parsed.error().size(), 1); + EXPECT_EQ(parsed.error()[0].first, ErrorCode::InvalidKey); + for (auto& error : parsed.error()) { - std::cout << error.second << " " << configParseStatusToString(error.first) << std::endl; + std::cout << error.second << " " << ErrorCodeToString(error.first) << std::endl; } } } TEST(ParserBase, PhotolysisDetectsUnknownPhase) { - v1::Parser parser; std::vector extensions = { ".json", ".yaml" }; for (auto& extension : extensions) { std::string file = std::string("v1_unit_configs/reactions/photolysis/missing_phase") + extension; - auto parsed = parser.Parse(file); + auto parsed = Parse(file); EXPECT_FALSE(parsed); - EXPECT_EQ(parsed.errors.size(), 1); - EXPECT_EQ(parsed.errors[0].first, ConfigParseStatus::UnknownPhase); - for (auto& error : parsed.errors) + EXPECT_EQ(parsed.error().size(), 1); + EXPECT_EQ(parsed.error()[0].first, ErrorCode::UnknownPhase); + for (auto& error : parsed.error()) { - std::cout << error.second << " " << configParseStatusToString(error.first) << std::endl; + std::cout << error.second << " " << ErrorCodeToString(error.first) << std::endl; } } } TEST(ParserBase, PhotolysisDoesNotAcceptMoreThanOneReactant) { - v1::Parser parser; std::vector extensions = { ".json", ".yaml" }; for (auto& extension : extensions) { std::string file = std::string("v1_unit_configs/reactions/photolysis/more_than_one_reactant") + extension; - auto parsed = parser.Parse(file); + auto parsed = Parse(file); EXPECT_FALSE(parsed); - EXPECT_EQ(parsed.errors.size(), 1); - EXPECT_EQ(parsed.errors[0].first, ConfigParseStatus::TooManyReactionComponents); - for (auto& error : parsed.errors) + EXPECT_EQ(parsed.error().size(), 1); + EXPECT_EQ(parsed.error()[0].first, ErrorCode::TooManyReactionComponents); + for (auto& error : parsed.error()) { - std::cout << error.second << " " << configParseStatusToString(error.first) << std::endl; + std::cout << error.second << " " << ErrorCodeToString(error.first) << std::endl; } } -} \ No newline at end of file +} diff --git a/test/unit/v1/reactions/test_parse_surface.cpp b/test/unit/v1/reactions/test_parse_surface.cpp index a3380dd5..57262b67 100644 --- a/test/unit/v1/reactions/test_parse_surface.cpp +++ b/test/unit/v1/reactions/test_parse_surface.cpp @@ -1,4 +1,8 @@ -#include +// Copyright (C) 2023–2026 University Corporation for Atmospheric Research +// University of Illinois at Urbana-Champaign +// SPDX-License-Identifier: Apache-2.0 + +#include #include @@ -6,94 +10,90 @@ using namespace mechanism_configuration; TEST(ParserBase, CanParseValidSurfaceReaction) { - v1::Parser parser; std::vector extensions = { ".json", ".yaml" }; for (auto& extension : extensions) { - auto parsed = parser.Parse(std::string("v1_unit_configs/reactions/surface/valid") + extension); + auto parsed = Parse(std::string("v1_unit_configs/reactions/surface/valid") + extension); EXPECT_TRUE(parsed); - v1::types::Mechanism mechanism = *parsed; + Mechanism mechanism = *parsed; EXPECT_EQ(mechanism.reactions.surface.size(), 2); EXPECT_EQ(mechanism.reactions.surface[0].gas_phase, "gas"); EXPECT_EQ(mechanism.reactions.surface[0].name, "my surface"); EXPECT_EQ(mechanism.reactions.surface[0].reaction_probability, 2.0e-2); - EXPECT_EQ(mechanism.reactions.surface[0].gas_phase_species.species_name, "A"); + EXPECT_EQ(mechanism.reactions.surface[0].gas_phase_species.name, "A"); EXPECT_EQ(mechanism.reactions.surface[0].gas_phase_species.coefficient, 1); EXPECT_EQ(mechanism.reactions.surface[0].gas_phase_products.size(), 2); - EXPECT_EQ(mechanism.reactions.surface[0].gas_phase_products[0].species_name, "B"); + EXPECT_EQ(mechanism.reactions.surface[0].gas_phase_products[0].name, "B"); EXPECT_EQ(mechanism.reactions.surface[0].gas_phase_products[0].coefficient, 1); - EXPECT_EQ(mechanism.reactions.surface[0].gas_phase_products[1].species_name, "C"); + EXPECT_EQ(mechanism.reactions.surface[0].gas_phase_products[1].name, "C"); EXPECT_EQ(mechanism.reactions.surface[0].gas_phase_products[1].coefficient, 1); EXPECT_EQ(mechanism.reactions.surface[0].unknown_properties.size(), 1); EXPECT_EQ(mechanism.reactions.surface[0].unknown_properties["__comment"], "key lime pie is superior to all other pies"); EXPECT_EQ(mechanism.reactions.surface[1].gas_phase, "gas"); EXPECT_EQ(mechanism.reactions.surface[1].reaction_probability, 1.0); - EXPECT_EQ(mechanism.reactions.surface[1].gas_phase_species.species_name, "A"); + EXPECT_EQ(mechanism.reactions.surface[1].gas_phase_species.name, "A"); EXPECT_EQ(mechanism.reactions.surface[1].gas_phase_species.coefficient, 1); EXPECT_EQ(mechanism.reactions.surface[1].gas_phase_products.size(), 2); - EXPECT_EQ(mechanism.reactions.surface[1].gas_phase_products[0].species_name, "B"); + EXPECT_EQ(mechanism.reactions.surface[1].gas_phase_products[0].name, "B"); EXPECT_EQ(mechanism.reactions.surface[1].gas_phase_products[0].coefficient, 1); EXPECT_EQ(mechanism.reactions.surface[1].gas_phase_products[0].unknown_properties.size(), 1); EXPECT_EQ(mechanism.reactions.surface[1].gas_phase_products[0].unknown_properties["__optional thing"], "hello"); - EXPECT_EQ(mechanism.reactions.surface[1].gas_phase_products[1].species_name, "C"); + EXPECT_EQ(mechanism.reactions.surface[1].gas_phase_products[1].name, "C"); EXPECT_EQ(mechanism.reactions.surface[1].gas_phase_products[1].coefficient, 1); } } TEST(ParserBase, SurfaceDetectsUnknownSpecies) { - v1::Parser parser; std::vector extensions = { ".json", ".yaml" }; for (auto& extension : extensions) { std::string file = std::string("v1_unit_configs/reactions/surface/unknown_species") + extension; - auto parsed = parser.Parse(file); + auto parsed = Parse(file); EXPECT_FALSE(parsed); - EXPECT_EQ(parsed.errors.size(), 1); - EXPECT_EQ(parsed.errors[0].first, ConfigParseStatus::ReactionRequiresUnknownSpecies); - for (auto& error : parsed.errors) + EXPECT_EQ(parsed.error().size(), 1); + EXPECT_EQ(parsed.error()[0].first, ErrorCode::ReactionRequiresUnknownSpecies); + for (auto& error : parsed.error()) { - std::cout << error.second << " " << configParseStatusToString(error.first) << std::endl; + std::cout << error.second << " " << ErrorCodeToString(error.first) << std::endl; } } } TEST(ParserBase, SurfaceDetectsBadReactionComponent) { - v1::Parser parser; std::vector extensions = { ".json", ".yaml" }; for (auto& extension : extensions) { std::string file = std::string("v1_unit_configs/reactions/surface/bad_reaction_component") + extension; - auto parsed = parser.Parse(file); + auto parsed = Parse(file); EXPECT_FALSE(parsed); - EXPECT_EQ(parsed.errors.size(), 2); - EXPECT_EQ(parsed.errors[0].first, ConfigParseStatus::RequiredKeyNotFound); - EXPECT_EQ(parsed.errors[1].first, ConfigParseStatus::InvalidKey); - for (auto& error : parsed.errors) + EXPECT_EQ(parsed.error().size(), 2); + EXPECT_EQ(parsed.error()[0].first, ErrorCode::RequiredKeyNotFound); + EXPECT_EQ(parsed.error()[1].first, ErrorCode::InvalidKey); + for (auto& error : parsed.error()) { - std::cout << error.second << " " << configParseStatusToString(error.first) << std::endl; + std::cout << error.second << " " << ErrorCodeToString(error.first) << std::endl; } } } TEST(ParserBase, SurfaceDetectsUnknownGasPhase) { - v1::Parser parser; std::vector extensions = { ".json", ".yaml" }; for (auto& extension : extensions) { std::string file = std::string("v1_unit_configs/reactions/surface/missing_gas_phase") + extension; - auto parsed = parser.Parse(file); + auto parsed = Parse(file); EXPECT_FALSE(parsed); - EXPECT_EQ(parsed.errors.size(), 1); - EXPECT_EQ(parsed.errors[0].first, ConfigParseStatus::UnknownPhase); - for (auto& error : parsed.errors) + EXPECT_EQ(parsed.error().size(), 1); + EXPECT_EQ(parsed.error()[0].first, ErrorCode::UnknownPhase); + for (auto& error : parsed.error()) { - std::cout << error.second << " " << configParseStatusToString(error.first) << std::endl; + std::cout << error.second << " " << ErrorCodeToString(error.first) << std::endl; } } -} \ No newline at end of file +} diff --git a/test/unit/v1/reactions/test_parse_taylor_series.cpp b/test/unit/v1/reactions/test_parse_taylor_series.cpp index b1a5f3c9..0f9c28b7 100644 --- a/test/unit/v1/reactions/test_parse_taylor_series.cpp +++ b/test/unit/v1/reactions/test_parse_taylor_series.cpp @@ -1,4 +1,8 @@ -#include +// Copyright (C) 2023–2026 University Corporation for Atmospheric Research +// University of Illinois at Urbana-Champaign +// SPDX-License-Identifier: Apache-2.0 + +#include #include @@ -6,13 +10,12 @@ using namespace mechanism_configuration; TEST(ParserBase, CanParseValidTaylorSeriesReaction) { - v1::Parser parser; std::vector extensions = { ".json", ".yaml" }; for (auto& extension : extensions) { - auto parsed = parser.Parse(std::string("v1_unit_configs/reactions/taylor_series/valid") + extension); + auto parsed = Parse(std::string("v1_unit_configs/reactions/taylor_series/valid") + extension); EXPECT_TRUE(parsed); - v1::types::Mechanism mechanism = *parsed; + Mechanism mechanism = *parsed; EXPECT_EQ(mechanism.reactions.taylor_series.size(), 3); @@ -28,12 +31,12 @@ TEST(ParserBase, CanParseValidTaylorSeriesReaction) EXPECT_EQ(mechanism.reactions.taylor_series[0].taylor_coefficients[1], 2.0); EXPECT_EQ(mechanism.reactions.taylor_series[0].taylor_coefficients[2], 3.0); EXPECT_EQ(mechanism.reactions.taylor_series[0].reactants.size(), 1); - EXPECT_EQ(mechanism.reactions.taylor_series[0].reactants[0].species_name, "A"); + EXPECT_EQ(mechanism.reactions.taylor_series[0].reactants[0].name, "A"); EXPECT_EQ(mechanism.reactions.taylor_series[0].reactants[0].coefficient, 1); EXPECT_EQ(mechanism.reactions.taylor_series[0].products.size(), 2); - EXPECT_EQ(mechanism.reactions.taylor_series[0].products[0].species_name, "B"); + EXPECT_EQ(mechanism.reactions.taylor_series[0].products[0].name, "B"); EXPECT_EQ(mechanism.reactions.taylor_series[0].products[0].coefficient, 1.2); - EXPECT_EQ(mechanism.reactions.taylor_series[0].products[1].species_name, "C"); + EXPECT_EQ(mechanism.reactions.taylor_series[0].products[1].name, "C"); EXPECT_EQ(mechanism.reactions.taylor_series[0].products[1].coefficient, 0.3); EXPECT_EQ(mechanism.reactions.taylor_series[0].unknown_properties.size(), 1); EXPECT_EQ(mechanism.reactions.taylor_series[0].unknown_properties["__solver_param"], "0.1"); @@ -48,12 +51,12 @@ TEST(ParserBase, CanParseValidTaylorSeriesReaction) EXPECT_EQ(mechanism.reactions.taylor_series[1].taylor_coefficients.size(), 1); EXPECT_EQ(mechanism.reactions.taylor_series[1].taylor_coefficients[0], 10.5); EXPECT_EQ(mechanism.reactions.taylor_series[1].reactants.size(), 2); - EXPECT_EQ(mechanism.reactions.taylor_series[1].reactants[0].species_name, "A"); + EXPECT_EQ(mechanism.reactions.taylor_series[1].reactants[0].name, "A"); EXPECT_EQ(mechanism.reactions.taylor_series[1].reactants[0].coefficient, 2); - EXPECT_EQ(mechanism.reactions.taylor_series[1].reactants[1].species_name, "B"); + EXPECT_EQ(mechanism.reactions.taylor_series[1].reactants[1].name, "B"); EXPECT_EQ(mechanism.reactions.taylor_series[1].reactants[1].coefficient, 0.1); EXPECT_EQ(mechanism.reactions.taylor_series[1].products.size(), 1); - EXPECT_EQ(mechanism.reactions.taylor_series[1].products[0].species_name, "C"); + EXPECT_EQ(mechanism.reactions.taylor_series[1].products[0].name, "C"); EXPECT_EQ(mechanism.reactions.taylor_series[1].products[0].coefficient, 0.5); EXPECT_EQ(mechanism.reactions.taylor_series[1].products[0].unknown_properties.size(), 1); EXPECT_EQ(mechanism.reactions.taylor_series[1].products[0].unknown_properties["__optional thing"], "hello"); @@ -68,83 +71,79 @@ TEST(ParserBase, CanParseValidTaylorSeriesReaction) EXPECT_EQ(mechanism.reactions.taylor_series[2].taylor_coefficients.size(), 1); EXPECT_EQ(mechanism.reactions.taylor_series[2].taylor_coefficients[0], 1.0); EXPECT_EQ(mechanism.reactions.taylor_series[2].reactants.size(), 1); - EXPECT_EQ(mechanism.reactions.taylor_series[2].reactants[0].species_name, "A"); + EXPECT_EQ(mechanism.reactions.taylor_series[2].reactants[0].name, "A"); EXPECT_EQ(mechanism.reactions.taylor_series[2].reactants[0].coefficient, 1); EXPECT_EQ(mechanism.reactions.taylor_series[2].products.size(), 1); - EXPECT_EQ(mechanism.reactions.taylor_series[2].products[0].species_name, "C"); + EXPECT_EQ(mechanism.reactions.taylor_series[2].products[0].name, "C"); EXPECT_EQ(mechanism.reactions.taylor_series[2].products[0].coefficient, 1); } } TEST(ParserBase, TaylorSeriesDetectsUnknownSpecies) { - v1::Parser parser; std::vector extensions = { ".json", ".yaml" }; for (auto& extension : extensions) { std::string file = std::string("v1_unit_configs/reactions/taylor_series/unknown_species") + extension; - auto parsed = parser.Parse(file); + auto parsed = Parse(file); EXPECT_FALSE(parsed); - EXPECT_EQ(parsed.errors.size(), 1); - EXPECT_EQ(parsed.errors[0].first, ConfigParseStatus::ReactionRequiresUnknownSpecies); - for (auto& error : parsed.errors) + EXPECT_EQ(parsed.error().size(), 1); + EXPECT_EQ(parsed.error()[0].first, ErrorCode::ReactionRequiresUnknownSpecies); + for (auto& error : parsed.error()) { - std::cout << error.second << " " << configParseStatusToString(error.first) << std::endl; + std::cout << error.second << " " << ErrorCodeToString(error.first) << std::endl; } } } TEST(ParserBase, TaylorSeriesDetectsMutuallyExclusiveOptions) { - v1::Parser parser; std::vector extensions = { ".json", ".yaml" }; for (auto& extension : extensions) { std::string file = std::string("v1_unit_configs/reactions/taylor_series/mutually_exclusive") + extension; - auto parsed = parser.Parse(file); + auto parsed = Parse(file); EXPECT_FALSE(parsed); - EXPECT_EQ(parsed.errors.size(), 1); - EXPECT_EQ(parsed.errors[0].first, ConfigParseStatus::MutuallyExclusiveOption); - for (auto& error : parsed.errors) + EXPECT_EQ(parsed.error().size(), 1); + EXPECT_EQ(parsed.error()[0].first, ErrorCode::MutuallyExclusiveOption); + for (auto& error : parsed.error()) { - std::cout << error.second << " " << configParseStatusToString(error.first) << std::endl; + std::cout << error.second << " " << ErrorCodeToString(error.first) << std::endl; } } } TEST(ParserBase, TaylorSeriesDetectsBadReactionComponent) { - v1::Parser parser; std::vector extensions = { ".json", ".yaml" }; for (auto& extension : extensions) { std::string file = std::string("v1_unit_configs/reactions/taylor_series/bad_reaction_component") + extension; - auto parsed = parser.Parse(file); + auto parsed = Parse(file); EXPECT_FALSE(parsed); - EXPECT_EQ(parsed.errors.size(), 2); - EXPECT_EQ(parsed.errors[0].first, ConfigParseStatus::RequiredKeyNotFound); - EXPECT_EQ(parsed.errors[1].first, ConfigParseStatus::InvalidKey); - for (auto& error : parsed.errors) + EXPECT_EQ(parsed.error().size(), 2); + EXPECT_EQ(parsed.error()[0].first, ErrorCode::RequiredKeyNotFound); + EXPECT_EQ(parsed.error()[1].first, ErrorCode::InvalidKey); + for (auto& error : parsed.error()) { - std::cout << error.second << " " << configParseStatusToString(error.first) << std::endl; + std::cout << error.second << " " << ErrorCodeToString(error.first) << std::endl; } } } TEST(ParserBase, TaylorSeriesDetectsUnknownPhase) { - v1::Parser parser; std::vector extensions = { ".json", ".yaml" }; for (auto& extension : extensions) { std::string file = std::string("v1_unit_configs/reactions/taylor_series/missing_phase") + extension; - auto parsed = parser.Parse(file); + auto parsed = Parse(file); EXPECT_FALSE(parsed); - EXPECT_EQ(parsed.errors.size(), 1); - EXPECT_EQ(parsed.errors[0].first, ConfigParseStatus::UnknownPhase); - for (auto& error : parsed.errors) + EXPECT_EQ(parsed.error().size(), 1); + EXPECT_EQ(parsed.error()[0].first, ErrorCode::UnknownPhase); + for (auto& error : parsed.error()) { - std::cout << error.second << " " << configParseStatusToString(error.first) << std::endl; + std::cout << error.second << " " << ErrorCodeToString(error.first) << std::endl; } } -} \ No newline at end of file +} diff --git a/test/unit/v1/reactions/test_parse_ternary_chemical_activation.cpp b/test/unit/v1/reactions/test_parse_ternary_chemical_activation.cpp index c01ab4ae..f079b9ed 100644 --- a/test/unit/v1/reactions/test_parse_ternary_chemical_activation.cpp +++ b/test/unit/v1/reactions/test_parse_ternary_chemical_activation.cpp @@ -1,6 +1,10 @@ -#include -#include -#include +// Copyright (C) 2023–2026 University Corporation for Atmospheric Research +// University of Illinois at Urbana-Champaign +// SPDX-License-Identifier: Apache-2.0 + +#include "detail/constants.hpp" +#include "detail/conversions.hpp" +#include #include @@ -8,22 +12,21 @@ using namespace mechanism_configuration; TEST(TernaryChemicalActivationConfig, ParseValidConfig) { - v1::Parser parser; std::vector extensions = { ".json", ".yaml" }; for (auto& extension : extensions) { std::string file = "./v1_unit_configs/reactions/ternary_chemical_activation/valid/config" + extension; - auto parsed = parser.Parse(file); + auto parsed = Parse(file); if (!parsed) { - for (auto& error : parsed.errors) + for (auto& error : parsed.error()) { - std::cout << error.second << " " << configParseStatusToString(error.first) << std::endl; + std::cout << error.second << " " << ErrorCodeToString(error.first) << std::endl; } } EXPECT_TRUE(parsed); - v1::types::Mechanism mechanism = *parsed; + Mechanism mechanism = *parsed; auto& process_vector = mechanism.reactions.ternary_chemical_activation; EXPECT_EQ(process_vector.size(), 2); @@ -31,14 +34,14 @@ TEST(TernaryChemicalActivationConfig, ParseValidConfig) // first reaction { EXPECT_EQ(process_vector[0].reactants.size(), 2); - EXPECT_EQ(process_vector[0].reactants[0].species_name, "foo"); + EXPECT_EQ(process_vector[0].reactants[0].name, "foo"); EXPECT_EQ(process_vector[0].reactants[0].coefficient, 1.0); - EXPECT_EQ(process_vector[0].reactants[1].species_name, "quz"); + EXPECT_EQ(process_vector[0].reactants[1].name, "quz"); EXPECT_EQ(process_vector[0].reactants[1].coefficient, 2.0); EXPECT_EQ(process_vector[0].products.size(), 2); - EXPECT_EQ(process_vector[0].products[0].species_name, "bar"); + EXPECT_EQ(process_vector[0].products[0].name, "bar"); EXPECT_EQ(process_vector[0].products[0].coefficient, 1.0); - EXPECT_EQ(process_vector[0].products[1].species_name, "baz"); + EXPECT_EQ(process_vector[0].products[1].name, "baz"); EXPECT_EQ(process_vector[0].products[1].coefficient, 3.2); EXPECT_EQ(process_vector[0].k0_A, 1.0); EXPECT_EQ(process_vector[0].k0_B, 0.0); @@ -55,12 +58,12 @@ TEST(TernaryChemicalActivationConfig, ParseValidConfig) EXPECT_EQ(process_vector[1].unknown_properties.size(), 1); EXPECT_EQ(process_vector[1].unknown_properties["__optional thing"], "hello"); EXPECT_EQ(process_vector[1].reactants.size(), 2); - EXPECT_EQ(process_vector[1].reactants[0].species_name, "bar"); - EXPECT_EQ(process_vector[1].reactants[1].species_name, "baz"); + EXPECT_EQ(process_vector[1].reactants[0].name, "bar"); + EXPECT_EQ(process_vector[1].reactants[1].name, "baz"); EXPECT_EQ(process_vector[1].products.size(), 2); - EXPECT_EQ(process_vector[1].products[0].species_name, "bar"); + EXPECT_EQ(process_vector[1].products[0].name, "bar"); EXPECT_EQ(process_vector[1].products[0].coefficient, 0.5); - EXPECT_EQ(process_vector[1].products[1].species_name, "foo"); + EXPECT_EQ(process_vector[1].products[1].name, "foo"); EXPECT_EQ(process_vector[1].products[1].coefficient, 0.0); EXPECT_EQ(process_vector[1].k0_A, 32.1); EXPECT_EQ(process_vector[1].k0_B, -2.3); @@ -77,62 +80,59 @@ TEST(TernaryChemicalActivationConfig, ParseValidConfig) TEST(TernaryChemicalActivationConfig, DetectsNonStandardKey) { - v1::Parser parser; std::vector extensions = { ".json", ".yaml" }; for (auto& extension : extensions) { std::string file = "./v1_unit_configs/reactions/ternary_chemical_activation/contains_nonstandard_key/config" + extension; - auto parsed = parser.Parse(file); + auto parsed = Parse(file); EXPECT_FALSE(parsed); - EXPECT_EQ(parsed.errors.size(), 12); - EXPECT_EQ(parsed.errors[0].first, ConfigParseStatus::RequiredKeyNotFound); - EXPECT_EQ(parsed.errors[1].first, ConfigParseStatus::InvalidKey); - EXPECT_EQ(parsed.errors[2].first, ConfigParseStatus::RequiredKeyNotFound); - EXPECT_EQ(parsed.errors[3].first, ConfigParseStatus::InvalidKey); - EXPECT_EQ(parsed.errors[4].first, ConfigParseStatus::InvalidKey); - EXPECT_EQ(parsed.errors[5].first, ConfigParseStatus::InvalidKey); - EXPECT_EQ(parsed.errors[6].first, ConfigParseStatus::InvalidKey); - EXPECT_EQ(parsed.errors[7].first, ConfigParseStatus::InvalidKey); - EXPECT_EQ(parsed.errors[8].first, ConfigParseStatus::InvalidKey); - EXPECT_EQ(parsed.errors[9].first, ConfigParseStatus::InvalidKey); - EXPECT_EQ(parsed.errors[10].first, ConfigParseStatus::InvalidKey); - EXPECT_EQ(parsed.errors[11].first, ConfigParseStatus::InvalidKey); + EXPECT_EQ(parsed.error().size(), 12); + EXPECT_EQ(parsed.error()[0].first, ErrorCode::RequiredKeyNotFound); + EXPECT_EQ(parsed.error()[1].first, ErrorCode::InvalidKey); + EXPECT_EQ(parsed.error()[2].first, ErrorCode::RequiredKeyNotFound); + EXPECT_EQ(parsed.error()[3].first, ErrorCode::InvalidKey); + EXPECT_EQ(parsed.error()[4].first, ErrorCode::InvalidKey); + EXPECT_EQ(parsed.error()[5].first, ErrorCode::InvalidKey); + EXPECT_EQ(parsed.error()[6].first, ErrorCode::InvalidKey); + EXPECT_EQ(parsed.error()[7].first, ErrorCode::InvalidKey); + EXPECT_EQ(parsed.error()[8].first, ErrorCode::InvalidKey); + EXPECT_EQ(parsed.error()[9].first, ErrorCode::InvalidKey); + EXPECT_EQ(parsed.error()[10].first, ErrorCode::InvalidKey); + EXPECT_EQ(parsed.error()[11].first, ErrorCode::InvalidKey); - for (auto& error : parsed.errors) + for (auto& error : parsed.error()) { - std::cout << error.second << " " << configParseStatusToString(error.first) << std::endl; + std::cout << error.second << " " << ErrorCodeToString(error.first) << std::endl; } } } TEST(TernaryChemicalActivationConfig, DetectsMissingProducts) { - v1::Parser parser; std::vector extensions = { ".json", ".yaml" }; for (auto& extension : extensions) { std::string file = "./v1_unit_configs/reactions/ternary_chemical_activation/missing_products/config" + extension; - auto parsed = parser.Parse(file); + auto parsed = Parse(file); EXPECT_FALSE(parsed); - for (auto& error : parsed.errors) + for (auto& error : parsed.error()) { - std::cout << error.second << " " << configParseStatusToString(error.first) << std::endl; + std::cout << error.second << " " << ErrorCodeToString(error.first) << std::endl; } } } TEST(TernaryChemicalActivationConfig, DetectsMissingReactants) { - v1::Parser parser; std::vector extensions = { ".json", ".yaml" }; for (auto& extension : extensions) { std::string file = "./v1_unit_configs/reactions/ternary_chemical_activation/missing_reactants/config" + extension; - auto parsed = parser.Parse(file); + auto parsed = Parse(file); EXPECT_FALSE(parsed); - for (auto& error : parsed.errors) + for (auto& error : parsed.error()) { - std::cout << error.second << " " << configParseStatusToString(error.first) << std::endl; + std::cout << error.second << " " << ErrorCodeToString(error.first) << std::endl; } } } \ No newline at end of file diff --git a/test/unit/v1/reactions/test_parse_troe.cpp b/test/unit/v1/reactions/test_parse_troe.cpp index c2f3cc6f..8054e9d4 100644 --- a/test/unit/v1/reactions/test_parse_troe.cpp +++ b/test/unit/v1/reactions/test_parse_troe.cpp @@ -1,4 +1,8 @@ -#include +// Copyright (C) 2023–2026 University Corporation for Atmospheric Research +// University of Illinois at Urbana-Champaign +// SPDX-License-Identifier: Apache-2.0 + +#include #include @@ -6,13 +10,12 @@ using namespace mechanism_configuration; TEST(ParserBase, CanParseValidTroeReaction) { - v1::Parser parser; std::vector extensions = { ".json", ".yaml" }; for (auto& extension : extensions) { - auto parsed = parser.Parse(std::string("v1_unit_configs/reactions/troe/valid") + extension); + auto parsed = Parse(std::string("v1_unit_configs/reactions/troe/valid") + extension); EXPECT_TRUE(parsed); - v1::types::Mechanism mechanism = *parsed; + Mechanism mechanism = *parsed; EXPECT_EQ(mechanism.reactions.troe.size(), 2); @@ -26,10 +29,10 @@ TEST(ParserBase, CanParseValidTroeReaction) EXPECT_EQ(mechanism.reactions.troe[0].Fc, 0.6); EXPECT_EQ(mechanism.reactions.troe[0].N, 1.0); EXPECT_EQ(mechanism.reactions.troe[0].reactants.size(), 1); - EXPECT_EQ(mechanism.reactions.troe[0].reactants[0].species_name, "A"); + EXPECT_EQ(mechanism.reactions.troe[0].reactants[0].name, "A"); EXPECT_EQ(mechanism.reactions.troe[0].reactants[0].coefficient, 1); EXPECT_EQ(mechanism.reactions.troe[0].products.size(), 1); - EXPECT_EQ(mechanism.reactions.troe[0].products[0].species_name, "C"); + EXPECT_EQ(mechanism.reactions.troe[0].products[0].name, "C"); EXPECT_EQ(mechanism.reactions.troe[0].products[0].coefficient, 1); EXPECT_EQ(mechanism.reactions.troe[0].unknown_properties.size(), 1); if (extension == ".json") @@ -52,14 +55,14 @@ TEST(ParserBase, CanParseValidTroeReaction) EXPECT_EQ(mechanism.reactions.troe[1].Fc, 1.3); EXPECT_EQ(mechanism.reactions.troe[1].N, 32.1); EXPECT_EQ(mechanism.reactions.troe[1].reactants.size(), 1); - EXPECT_EQ(mechanism.reactions.troe[1].reactants[0].species_name, "C"); + EXPECT_EQ(mechanism.reactions.troe[1].reactants[0].name, "C"); EXPECT_EQ(mechanism.reactions.troe[1].reactants[0].coefficient, 1); EXPECT_EQ(mechanism.reactions.troe[1].products.size(), 2); - EXPECT_EQ(mechanism.reactions.troe[1].products[0].species_name, "A"); + EXPECT_EQ(mechanism.reactions.troe[1].products[0].name, "A"); EXPECT_EQ(mechanism.reactions.troe[1].products[0].coefficient, 0.2); EXPECT_EQ(mechanism.reactions.troe[1].products[0].unknown_properties.size(), 1); EXPECT_EQ(mechanism.reactions.troe[1].products[0].unknown_properties["__optional thing"], "hello"); - EXPECT_EQ(mechanism.reactions.troe[1].products[1].species_name, "B"); + EXPECT_EQ(mechanism.reactions.troe[1].products[1].name, "B"); EXPECT_EQ(mechanism.reactions.troe[1].products[1].coefficient, 1.2); EXPECT_EQ(mechanism.reactions.troe[1].products[1].unknown_properties.size(), 0); } @@ -67,55 +70,52 @@ TEST(ParserBase, CanParseValidTroeReaction) TEST(ParserBase, TroeDetectsUnknownSpecies) { - v1::Parser parser; std::vector extensions = { ".json", ".yaml" }; for (auto& extension : extensions) { std::string file = std::string("v1_unit_configs/reactions/troe/unknown_species") + extension; - auto parsed = parser.Parse(file); + auto parsed = Parse(file); EXPECT_FALSE(parsed); - EXPECT_EQ(parsed.errors.size(), 1); - EXPECT_EQ(parsed.errors[0].first, ConfigParseStatus::ReactionRequiresUnknownSpecies); - for (auto& error : parsed.errors) + EXPECT_EQ(parsed.error().size(), 1); + EXPECT_EQ(parsed.error()[0].first, ErrorCode::ReactionRequiresUnknownSpecies); + for (auto& error : parsed.error()) { - std::cout << error.second << " " << configParseStatusToString(error.first) << std::endl; + std::cout << error.second << " " << ErrorCodeToString(error.first) << std::endl; } } } TEST(ParserBase, TroeDetectsBadReactionComponent) { - v1::Parser parser; std::vector extensions = { ".json", ".yaml" }; for (auto& extension : extensions) { std::string file = std::string("v1_unit_configs/reactions/troe/bad_reaction_component") + extension; - auto parsed = parser.Parse(file); + auto parsed = Parse(file); EXPECT_FALSE(parsed); - EXPECT_EQ(parsed.errors.size(), 2); - EXPECT_EQ(parsed.errors[0].first, ConfigParseStatus::RequiredKeyNotFound); - EXPECT_EQ(parsed.errors[1].first, ConfigParseStatus::InvalidKey); - for (auto& error : parsed.errors) + EXPECT_EQ(parsed.error().size(), 2); + EXPECT_EQ(parsed.error()[0].first, ErrorCode::RequiredKeyNotFound); + EXPECT_EQ(parsed.error()[1].first, ErrorCode::InvalidKey); + for (auto& error : parsed.error()) { - std::cout << error.second << " " << configParseStatusToString(error.first) << std::endl; + std::cout << error.second << " " << ErrorCodeToString(error.first) << std::endl; } } } TEST(ParserBase, TroeDetectsUnknownPhase) { - v1::Parser parser; std::vector extensions = { ".json", ".yaml" }; for (auto& extension : extensions) { std::string file = std::string("v1_unit_configs/reactions/troe/missing_phase") + extension; - auto parsed = parser.Parse(file); + auto parsed = Parse(file); EXPECT_FALSE(parsed); - EXPECT_EQ(parsed.errors.size(), 1); - EXPECT_EQ(parsed.errors[0].first, ConfigParseStatus::UnknownPhase); - for (auto& error : parsed.errors) + EXPECT_EQ(parsed.error().size(), 1); + EXPECT_EQ(parsed.error()[0].first, ErrorCode::UnknownPhase); + for (auto& error : parsed.error()) { - std::cout << error.second << " " << configParseStatusToString(error.first) << std::endl; + std::cout << error.second << " " << ErrorCodeToString(error.first) << std::endl; } } -} \ No newline at end of file +} diff --git a/test/unit/v1/reactions/test_parse_tunneling.cpp b/test/unit/v1/reactions/test_parse_tunneling.cpp index 3c84fab2..ec142d1f 100644 --- a/test/unit/v1/reactions/test_parse_tunneling.cpp +++ b/test/unit/v1/reactions/test_parse_tunneling.cpp @@ -1,4 +1,8 @@ -#include +// Copyright (C) 2023–2026 University Corporation for Atmospheric Research +// University of Illinois at Urbana-Champaign +// SPDX-License-Identifier: Apache-2.0 + +#include #include @@ -6,13 +10,12 @@ using namespace mechanism_configuration; TEST(ParserBase, CanParseValidTunnelingReaction) { - v1::Parser parser; std::vector extensions = { ".json", ".yaml" }; for (auto& extension : extensions) { - auto parsed = parser.Parse(std::string("v1_unit_configs/reactions/tunneling/valid") + extension); + auto parsed = Parse(std::string("v1_unit_configs/reactions/tunneling/valid") + extension); EXPECT_TRUE(parsed); - v1::types::Mechanism mechanism = *parsed; + Mechanism mechanism = *parsed; EXPECT_EQ(mechanism.reactions.tunneling.size(), 2); @@ -21,10 +24,10 @@ TEST(ParserBase, CanParseValidTunnelingReaction) EXPECT_EQ(mechanism.reactions.tunneling[0].B, 1200.0); EXPECT_EQ(mechanism.reactions.tunneling[0].C, 1.0e8); EXPECT_EQ(mechanism.reactions.tunneling[0].reactants.size(), 1); - EXPECT_EQ(mechanism.reactions.tunneling[0].reactants[0].species_name, "B"); + EXPECT_EQ(mechanism.reactions.tunneling[0].reactants[0].name, "B"); EXPECT_EQ(mechanism.reactions.tunneling[0].reactants[0].coefficient, 1); EXPECT_EQ(mechanism.reactions.tunneling[0].products.size(), 1); - EXPECT_EQ(mechanism.reactions.tunneling[0].products[0].species_name, "C"); + EXPECT_EQ(mechanism.reactions.tunneling[0].products[0].name, "C"); EXPECT_EQ(mechanism.reactions.tunneling[0].products[0].coefficient, 1); EXPECT_EQ(mechanism.reactions.tunneling[1].name, "my tunneling"); @@ -33,14 +36,14 @@ TEST(ParserBase, CanParseValidTunnelingReaction) EXPECT_EQ(mechanism.reactions.tunneling[1].B, 0); EXPECT_EQ(mechanism.reactions.tunneling[1].C, 0); EXPECT_EQ(mechanism.reactions.tunneling[1].reactants.size(), 1); - EXPECT_EQ(mechanism.reactions.tunneling[1].reactants[0].species_name, "B"); + EXPECT_EQ(mechanism.reactions.tunneling[1].reactants[0].name, "B"); EXPECT_EQ(mechanism.reactions.tunneling[1].reactants[0].coefficient, 1); EXPECT_EQ(mechanism.reactions.tunneling[1].products.size(), 2); - EXPECT_EQ(mechanism.reactions.tunneling[1].products[0].species_name, "A"); + EXPECT_EQ(mechanism.reactions.tunneling[1].products[0].name, "A"); EXPECT_EQ(mechanism.reactions.tunneling[1].products[0].coefficient, 0.2); EXPECT_EQ(mechanism.reactions.tunneling[1].products[0].unknown_properties.size(), 1); EXPECT_EQ(mechanism.reactions.tunneling[1].products[0].unknown_properties["__optional thing"], "hello"); - EXPECT_EQ(mechanism.reactions.tunneling[1].products[1].species_name, "B"); + EXPECT_EQ(mechanism.reactions.tunneling[1].products[1].name, "B"); EXPECT_EQ(mechanism.reactions.tunneling[1].products[1].coefficient, 1.2); EXPECT_EQ(mechanism.reactions.tunneling[1].products[1].unknown_properties.size(), 0); } @@ -48,55 +51,52 @@ TEST(ParserBase, CanParseValidTunnelingReaction) TEST(ParserBase, TunnelingDetectsUnknownSpecies) { - v1::Parser parser; std::vector extensions = { ".json", ".yaml" }; for (auto& extension : extensions) { std::string file = std::string("v1_unit_configs/reactions/tunneling/unknown_species") + extension; - auto parsed = parser.Parse(file); + auto parsed = Parse(file); EXPECT_FALSE(parsed); - EXPECT_EQ(parsed.errors.size(), 1); - EXPECT_EQ(parsed.errors[0].first, ConfigParseStatus::ReactionRequiresUnknownSpecies); - for (auto& error : parsed.errors) + EXPECT_EQ(parsed.error().size(), 1); + EXPECT_EQ(parsed.error()[0].first, ErrorCode::ReactionRequiresUnknownSpecies); + for (auto& error : parsed.error()) { - std::cout << error.second << " " << configParseStatusToString(error.first) << std::endl; + std::cout << error.second << " " << ErrorCodeToString(error.first) << std::endl; } } } TEST(ParserBase, TunnelingDetectsBadReactionComponent) { - v1::Parser parser; std::vector extensions = { ".json", ".yaml" }; for (auto& extension : extensions) { std::string file = std::string("v1_unit_configs/reactions/tunneling/bad_reaction_component") + extension; - auto parsed = parser.Parse(file); + auto parsed = Parse(file); EXPECT_FALSE(parsed); - EXPECT_EQ(parsed.errors.size(), 2); - EXPECT_EQ(parsed.errors[0].first, ConfigParseStatus::RequiredKeyNotFound); - EXPECT_EQ(parsed.errors[1].first, ConfigParseStatus::InvalidKey); - for (auto& error : parsed.errors) + EXPECT_EQ(parsed.error().size(), 2); + EXPECT_EQ(parsed.error()[0].first, ErrorCode::RequiredKeyNotFound); + EXPECT_EQ(parsed.error()[1].first, ErrorCode::InvalidKey); + for (auto& error : parsed.error()) { - std::cout << error.second << " " << configParseStatusToString(error.first) << std::endl; + std::cout << error.second << " " << ErrorCodeToString(error.first) << std::endl; } } } TEST(ParserBase, TunnelingDetectsUnknownPhase) { - v1::Parser parser; std::vector extensions = { ".json", ".yaml" }; for (auto& extension : extensions) { std::string file = std::string("v1_unit_configs/reactions/tunneling/missing_phase") + extension; - auto parsed = parser.Parse(file); + auto parsed = Parse(file); EXPECT_FALSE(parsed); - EXPECT_EQ(parsed.errors.size(), 1); - EXPECT_EQ(parsed.errors[0].first, ConfigParseStatus::UnknownPhase); - for (auto& error : parsed.errors) + EXPECT_EQ(parsed.error().size(), 1); + EXPECT_EQ(parsed.error()[0].first, ErrorCode::UnknownPhase); + for (auto& error : parsed.error()) { - std::cout << error.second << " " << configParseStatusToString(error.first) << std::endl; + std::cout << error.second << " " << ErrorCodeToString(error.first) << std::endl; } } -} \ No newline at end of file +} diff --git a/test/unit/v1/reactions/test_parse_user_defined.cpp b/test/unit/v1/reactions/test_parse_user_defined.cpp index d561ec34..98bc7e2b 100644 --- a/test/unit/v1/reactions/test_parse_user_defined.cpp +++ b/test/unit/v1/reactions/test_parse_user_defined.cpp @@ -1,4 +1,8 @@ -#include +// Copyright (C) 2023–2026 University Corporation for Atmospheric Research +// University of Illinois at Urbana-Champaign +// SPDX-License-Identifier: Apache-2.0 + +#include #include @@ -6,13 +10,12 @@ using namespace mechanism_configuration; TEST(ParserBase, CanParseValidUserDefinedReaction) { - v1::Parser parser; std::vector extensions = { ".json", ".yaml" }; for (auto& extension : extensions) { - auto parsed = parser.Parse(std::string("v1_unit_configs/reactions/user_defined/valid") + extension); + auto parsed = Parse(std::string("v1_unit_configs/reactions/user_defined/valid") + extension); EXPECT_TRUE(parsed); - v1::types::Mechanism mechanism = *parsed; + Mechanism mechanism = *parsed; EXPECT_EQ(mechanism.reactions.user_defined.size(), 2); @@ -20,10 +23,10 @@ TEST(ParserBase, CanParseValidUserDefinedReaction) EXPECT_EQ(mechanism.reactions.user_defined[0].name, "my user defined"); EXPECT_EQ(mechanism.reactions.user_defined[0].scaling_factor, 12.3); EXPECT_EQ(mechanism.reactions.user_defined[0].reactants.size(), 1); - EXPECT_EQ(mechanism.reactions.user_defined[0].reactants[0].species_name, "B"); + EXPECT_EQ(mechanism.reactions.user_defined[0].reactants[0].name, "B"); EXPECT_EQ(mechanism.reactions.user_defined[0].reactants[0].coefficient, 1); EXPECT_EQ(mechanism.reactions.user_defined[0].products.size(), 1); - EXPECT_EQ(mechanism.reactions.user_defined[0].products[0].species_name, "C"); + EXPECT_EQ(mechanism.reactions.user_defined[0].products[0].name, "C"); EXPECT_EQ(mechanism.reactions.user_defined[0].products[0].coefficient, 1); EXPECT_EQ(mechanism.reactions.user_defined[0].unknown_properties.size(), 1); EXPECT_EQ(mechanism.reactions.user_defined[0].unknown_properties["__comment"], "hi"); @@ -31,66 +34,63 @@ TEST(ParserBase, CanParseValidUserDefinedReaction) EXPECT_EQ(mechanism.reactions.user_defined[1].gas_phase, "gas"); EXPECT_EQ(mechanism.reactions.user_defined[1].scaling_factor, 1); EXPECT_EQ(mechanism.reactions.user_defined[1].reactants.size(), 2); - EXPECT_EQ(mechanism.reactions.user_defined[1].reactants[0].species_name, "B"); + EXPECT_EQ(mechanism.reactions.user_defined[1].reactants[0].name, "B"); EXPECT_EQ(mechanism.reactions.user_defined[1].reactants[0].coefficient, 1.2); - EXPECT_EQ(mechanism.reactions.user_defined[1].reactants[1].species_name, "A"); + EXPECT_EQ(mechanism.reactions.user_defined[1].reactants[1].name, "A"); EXPECT_EQ(mechanism.reactions.user_defined[1].reactants[1].coefficient, 0.5); EXPECT_EQ(mechanism.reactions.user_defined[1].products.size(), 1); - EXPECT_EQ(mechanism.reactions.user_defined[1].products[0].species_name, "C"); + EXPECT_EQ(mechanism.reactions.user_defined[1].products[0].name, "C"); EXPECT_EQ(mechanism.reactions.user_defined[1].products[0].coefficient, 0.2); } } TEST(ParserBase, UserDefinedDetectsUnknownSpecies) { - v1::Parser parser; std::vector extensions = { ".json", ".yaml" }; for (auto& extension : extensions) { std::string file = std::string("v1_unit_configs/reactions/user_defined/unknown_species") + extension; - auto parsed = parser.Parse(file); + auto parsed = Parse(file); EXPECT_FALSE(parsed); - EXPECT_EQ(parsed.errors.size(), 1); - EXPECT_EQ(parsed.errors[0].first, ConfigParseStatus::ReactionRequiresUnknownSpecies); - for (auto& error : parsed.errors) + EXPECT_EQ(parsed.error().size(), 1); + EXPECT_EQ(parsed.error()[0].first, ErrorCode::ReactionRequiresUnknownSpecies); + for (auto& error : parsed.error()) { - std::cout << error.second << " " << configParseStatusToString(error.first) << std::endl; + std::cout << error.second << " " << ErrorCodeToString(error.first) << std::endl; } } } TEST(ParserBase, UserDefinedDetectsBadReactionComponent) { - v1::Parser parser; std::vector extensions = { ".json", ".yaml" }; for (auto& extension : extensions) { std::string file = std::string("v1_unit_configs/reactions/user_defined/bad_reaction_component") + extension; - auto parsed = parser.Parse(file); + auto parsed = Parse(file); EXPECT_FALSE(parsed); - EXPECT_EQ(parsed.errors.size(), 1); - EXPECT_EQ(parsed.errors[0].first, ConfigParseStatus::InvalidKey); - for (auto& error : parsed.errors) + EXPECT_EQ(parsed.error().size(), 1); + EXPECT_EQ(parsed.error()[0].first, ErrorCode::InvalidKey); + for (auto& error : parsed.error()) { - std::cout << error.second << " " << configParseStatusToString(error.first) << std::endl; + std::cout << error.second << " " << ErrorCodeToString(error.first) << std::endl; } } } TEST(ParserBase, UserDefinedDetectsUnknownPhase) { - v1::Parser parser; std::vector extensions = { ".json", ".yaml" }; for (auto& extension : extensions) { std::string file = std::string("v1_unit_configs/reactions/user_defined/missing_phase") + extension; - auto parsed = parser.Parse(file); + auto parsed = Parse(file); EXPECT_FALSE(parsed); - EXPECT_EQ(parsed.errors.size(), 1); - EXPECT_EQ(parsed.errors[0].first, ConfigParseStatus::UnknownPhase); - for (auto& error : parsed.errors) + EXPECT_EQ(parsed.error().size(), 1); + EXPECT_EQ(parsed.error()[0].first, ErrorCode::UnknownPhase); + for (auto& error : parsed.error()) { - std::cout << error.second << " " << configParseStatusToString(error.first) << std::endl; + std::cout << error.second << " " << ErrorCodeToString(error.first) << std::endl; } } } diff --git a/test/unit/v1/test_parse_phases.cpp b/test/unit/v1/test_parse_phases.cpp index e10f08ae..57364e5c 100644 --- a/test/unit/v1/test_parse_phases.cpp +++ b/test/unit/v1/test_parse_phases.cpp @@ -1,4 +1,8 @@ -#include +// Copyright (C) 2023–2026 University Corporation for Atmospheric Research +// University of Illinois at Urbana-Champaign +// SPDX-License-Identifier: Apache-2.0 + +#include #include @@ -6,13 +10,12 @@ using namespace mechanism_configuration; TEST(ParserBase, CanParseValidPhases) { - v1::Parser parser; std::vector extensions = { ".json", ".yaml" }; for (auto& extension : extensions) { - auto parsed = parser.Parse(std::string("v1_unit_configs/phases/valid_phases") + extension); + auto parsed = Parse(std::string("v1_unit_configs/phases/valid_phases") + extension); EXPECT_TRUE(parsed); - v1::types::Mechanism mechanism = *parsed; + Mechanism mechanism = *parsed; EXPECT_EQ(mechanism.species.size(), 3); EXPECT_EQ(mechanism.phases.size(), 2); @@ -34,103 +37,97 @@ TEST(ParserBase, CanParseValidPhases) TEST(ParserBase, DetectsDuplicatePhases) { - v1::Parser parser; std::vector extensions = { ".json", ".yaml" }; for (auto& extension : extensions) { std::string file = std::string("v1_unit_configs/phases/duplicate_phases") + extension; - auto parsed = parser.Parse(file); - EXPECT_FALSE(parsed); - EXPECT_EQ(parsed.errors.size(), 2); - EXPECT_EQ(parsed.errors[0].first, ConfigParseStatus::DuplicatePhasesDetected); - for (auto& error : parsed.errors) + auto parsed = Parse(file); + EXPECT_FALSE(parsed) << "Parsing should have failed due to duplicate phases, but it succeeded."; + EXPECT_EQ(parsed.error().size(), 2); + EXPECT_EQ(parsed.error()[0].first, ErrorCode::DuplicatePhasesDetected); + for (auto& error : parsed.error()) { - std::cout << error.second << " " << configParseStatusToString(error.first) << std::endl; + std::cout << error.second << " " << ErrorCodeToString(error.first) << std::endl; } } } TEST(ParserBase, DetectsMissingRequiredKeys) { - v1::Parser parser; std::vector extensions = { ".json", ".yaml" }; for (auto& extension : extensions) { std::string file = std::string("v1_unit_configs/phases/missing_required_key") + extension; - auto parsed = parser.Parse(file); + auto parsed = Parse(file); EXPECT_FALSE(parsed); - EXPECT_EQ(parsed.errors.size(), 1); - EXPECT_EQ(parsed.errors[0].first, ConfigParseStatus::RequiredKeyNotFound); - for (auto& error : parsed.errors) + EXPECT_EQ(parsed.error().size(), 1); + EXPECT_EQ(parsed.error()[0].first, ErrorCode::RequiredKeyNotFound); + for (auto& error : parsed.error()) { - std::cout << error.second << " " << configParseStatusToString(error.first) << std::endl; + std::cout << error.second << " " << ErrorCodeToString(error.first) << std::endl; } } } TEST(ParserBase, DetectsInvalidKeys) { - v1::Parser parser; std::vector extensions = { ".json", ".yaml" }; for (auto& extension : extensions) { std::string file = std::string("v1_unit_configs/phases/invalid_key") + extension; - auto parsed = parser.Parse(file); + auto parsed = Parse(file); EXPECT_FALSE(parsed); - EXPECT_EQ(parsed.errors.size(), 1); - EXPECT_EQ(parsed.errors[0].first, ConfigParseStatus::InvalidKey); - for (auto& error : parsed.errors) + EXPECT_EQ(parsed.error().size(), 1); + EXPECT_EQ(parsed.error()[0].first, ErrorCode::InvalidKey); + for (auto& error : parsed.error()) { - std::cout << error.second << " " << configParseStatusToString(error.first) << std::endl; + std::cout << error.second << " " << ErrorCodeToString(error.first) << std::endl; } } } TEST(ParserBase, DetectsPhaseRequestingUnknownSpecies) { - v1::Parser parser; std::vector extensions = { ".json", ".yaml" }; for (auto& extension : extensions) { std::string file = std::string("v1_unit_configs/phases/unknown_species") + extension; - auto parsed = parser.Parse(file); + auto parsed = Parse(file); EXPECT_FALSE(parsed); - EXPECT_EQ(parsed.errors.size(), 1); - EXPECT_EQ(parsed.errors[0].first, ConfigParseStatus::PhaseRequiresUnknownSpecies); - for (auto& error : parsed.errors) + EXPECT_EQ(parsed.error().size(), 1); + EXPECT_EQ(parsed.error()[0].first, ErrorCode::PhaseRequiresUnknownSpecies); + for (auto& error : parsed.error()) { - std::cout << error.second << " " << configParseStatusToString(error.first) << std::endl; + std::cout << error.second << " " << ErrorCodeToString(error.first) << std::endl; } } } TEST(ParserBase, DetectsDuplicateSpeciesInPhase) { - v1::Parser parser; std::vector extensions = { ".json", ".yaml" }; for (auto& extension : extensions) { std::string file = std::string("v1_unit_configs/phases/duplicate_species_in_phase") + extension; - auto parsed = parser.Parse(file); + auto parsed = Parse(file); EXPECT_FALSE(parsed); - EXPECT_EQ(parsed.errors.size(), 1); - EXPECT_EQ(parsed.errors[0].first, ConfigParseStatus::DuplicateSpeciesInPhaseDetected); - for (auto& error : parsed.errors) + EXPECT_EQ(parsed.error().size(), 2); + EXPECT_EQ(parsed.error()[0].first, ErrorCode::DuplicateSpeciesInPhaseDetected); + for (auto& error : parsed.error()) { - std::cout << error.second << " " << configParseStatusToString(error.first) << std::endl; + std::cout << error.second << " " << ErrorCodeToString(error.first) << std::endl; } } } TEST(ParserBase, CanParsePhaseSpeciesProperties) { - v1::Parser parser; std::vector extensions = { ".json", ".yaml" }; for (auto& extension : extensions) { - auto parsed = parser.Parse(std::string("v1_unit_configs/phases/phase_species_properties") + extension); + auto parsed = Parse(std::string("v1_unit_configs/phases/phase_species_properties") + extension); EXPECT_TRUE(parsed); - v1::types::Mechanism mechanism = *parsed; + Mechanism mechanism = *parsed; EXPECT_EQ(mechanism.species.size(), 3); EXPECT_EQ(mechanism.phases.size(), 1); @@ -162,18 +159,17 @@ TEST(ParserBase, CanParsePhaseSpeciesProperties) TEST(ParserBase, DetectsInvalidSpeciesObject) { - v1::Parser parser; std::vector extensions = { ".json", ".yaml" }; for (auto& extension : extensions) { std::string file = std::string("v1_unit_configs/phases/invalid_species_object") + extension; - auto parsed = parser.Parse(file); + auto parsed = Parse(file); EXPECT_FALSE(parsed); - EXPECT_GE(parsed.errors.size(), 1); - EXPECT_EQ(parsed.errors[0].first, ConfigParseStatus::RequiredKeyNotFound); - for (auto& error : parsed.errors) + EXPECT_GE(parsed.error().size(), 1); + EXPECT_EQ(parsed.error()[0].first, ErrorCode::RequiredKeyNotFound); + for (auto& error : parsed.error()) { - std::cout << error.second << " " << configParseStatusToString(error.first) << std::endl; + std::cout << error.second << " " << ErrorCodeToString(error.first) << std::endl; } } -} \ No newline at end of file +} diff --git a/test/unit/v1/test_parse_species.cpp b/test/unit/v1/test_parse_species.cpp index a0110d81..e3827a4b 100644 --- a/test/unit/v1/test_parse_species.cpp +++ b/test/unit/v1/test_parse_species.cpp @@ -1,4 +1,8 @@ -#include +// Copyright (C) 2023–2026 University Corporation for Atmospheric Research +// University of Illinois at Urbana-Champaign +// SPDX-License-Identifier: Apache-2.0 + +#include #include @@ -6,13 +10,12 @@ using namespace mechanism_configuration; TEST(ParserBase, CanParseValidSpecies) { - v1::Parser parser; std::vector extensions = { ".json", ".yaml" }; for (auto& extension : extensions) { - auto parsed = parser.Parse(std::string("v1_unit_configs/species/valid_species") + extension); + auto parsed = Parse(std::string("v1_unit_configs/species/valid_species") + extension); EXPECT_TRUE(parsed); - v1::types::Mechanism mechanism = *parsed; + Mechanism mechanism = *parsed; EXPECT_EQ(mechanism.species.size(), 3); EXPECT_EQ(mechanism.species[0].name, "A"); @@ -42,58 +45,55 @@ TEST(ParserBase, CanParseValidSpecies) TEST(ParserBase, DetectsDuplicateSpecies) { - v1::Parser parser; std::vector extensions = { ".json", ".yaml" }; for (auto& extension : extensions) { std::string file = std::string("v1_unit_configs/species/duplicate_species") + extension; - auto parsed = parser.Parse(file); + auto parsed = Parse(file); EXPECT_FALSE(parsed); - EXPECT_EQ(parsed.errors.size(), 4); - EXPECT_EQ(parsed.errors[0].first, ConfigParseStatus::DuplicateSpeciesDetected); - EXPECT_EQ(parsed.errors[1].first, ConfigParseStatus::DuplicateSpeciesDetected); - EXPECT_EQ(parsed.errors[2].first, ConfigParseStatus::DuplicateSpeciesDetected); - EXPECT_EQ(parsed.errors[3].first, ConfigParseStatus::DuplicateSpeciesDetected); - for (auto& error : parsed.errors) + EXPECT_EQ(parsed.error().size(), 4); + EXPECT_EQ(parsed.error()[0].first, ErrorCode::DuplicateSpeciesDetected); + EXPECT_EQ(parsed.error()[1].first, ErrorCode::DuplicateSpeciesDetected); + EXPECT_EQ(parsed.error()[2].first, ErrorCode::DuplicateSpeciesDetected); + EXPECT_EQ(parsed.error()[3].first, ErrorCode::DuplicateSpeciesDetected); + for (auto& error : parsed.error()) { - std::cout << error.second << " " << configParseStatusToString(error.first) << std::endl; + std::cout << error.second << " " << ErrorCodeToString(error.first) << std::endl; } } } TEST(ParserBase, DetectsMissingRequiredKeys) { - v1::Parser parser; std::vector extensions = { ".json", ".yaml" }; for (auto& extension : extensions) { std::string file = std::string("v1_unit_configs/species/missing_required_key") + extension; - auto parsed = parser.Parse(file); + auto parsed = Parse(file); EXPECT_FALSE(parsed); - EXPECT_EQ(parsed.errors.size(), 2); - EXPECT_EQ(parsed.errors[0].first, ConfigParseStatus::RequiredKeyNotFound); - EXPECT_EQ(parsed.errors[1].first, ConfigParseStatus::InvalidKey); - for (auto& error : parsed.errors) + EXPECT_EQ(parsed.error().size(), 2); + EXPECT_EQ(parsed.error()[0].first, ErrorCode::RequiredKeyNotFound); + EXPECT_EQ(parsed.error()[1].first, ErrorCode::InvalidKey); + for (auto& error : parsed.error()) { - std::cout << error.second << " " << configParseStatusToString(error.first) << std::endl; + std::cout << error.second << " " << ErrorCodeToString(error.first) << std::endl; } } } TEST(ParserBase, DetectsInvalidKeys) { - v1::Parser parser; std::vector extensions = { ".json", ".yaml" }; for (auto& extension : extensions) { std::string file = std::string("v1_unit_configs/species/invalid_key") + extension; - auto parsed = parser.Parse(file); + auto parsed = Parse(file); EXPECT_FALSE(parsed); - EXPECT_EQ(parsed.errors.size(), 1); - EXPECT_EQ(parsed.errors[0].first, ConfigParseStatus::InvalidKey); - for (auto& error : parsed.errors) + EXPECT_EQ(parsed.error().size(), 1); + EXPECT_EQ(parsed.error()[0].first, ErrorCode::InvalidKey); + for (auto& error : parsed.error()) { - std::cout << error.second << " " << configParseStatusToString(error.first) << std::endl; + std::cout << error.second << " " << ErrorCodeToString(error.first) << std::endl; } } } diff --git a/test/unit/v1/v1_unit_configs/reactions/aqueous_equilibrium/bad_reaction_component.json b/test/unit/v1/v1_unit_configs/reactions/aqueous_equilibrium/bad_reaction_component.json deleted file mode 100644 index 7dc11217..00000000 --- a/test/unit/v1/v1_unit_configs/reactions/aqueous_equilibrium/bad_reaction_component.json +++ /dev/null @@ -1,53 +0,0 @@ -{ - "version": "1.0.0", - "name": "Bad reaction component", - "species": [ - { - "name": "A" - }, - { - "name": "B" - }, - { - "name": "C" - }, - { - "name": "H2O" - } - ], - "phases": [ - { - "name": "aqueous", - "species": [ - "A", - "B", - "C", - "H2O" - ] - } - ], - "reactions": [ - { - "type": "AQUEOUS_EQUILIBRIUM", - "condensed phase": "aqueous", - "condensed-phase water": "H2O", - "k_reverse": 0.32, - "reactants": [ - { - "Species name": "A", - "coefficient": 2 - } - ], - "products": [ - { - "Species name": "B", - "coefficient": 1 - }, - { - "Species name": "C", - "coefficient": 1 - } - ] - } - ] -} \ No newline at end of file diff --git a/test/unit/v1/v1_unit_configs/reactions/aqueous_equilibrium/bad_reaction_component.yaml b/test/unit/v1/v1_unit_configs/reactions/aqueous_equilibrium/bad_reaction_component.yaml deleted file mode 100644 index bb52eae7..00000000 --- a/test/unit/v1/v1_unit_configs/reactions/aqueous_equilibrium/bad_reaction_component.yaml +++ /dev/null @@ -1,27 +0,0 @@ -name: Bad reaction component -phases: -- name: aqueous - species: - - A - - B - - C - - H2O -reactions: -- condensed phase: aqueous - condensed-phase water: H2O - k_reverse: 0.32 - products: - - Species name: B - coefficient: 1 - - Species name: C - coefficient: 1 - reactants: - - Species name: A - coefficient: 2 - type: AQUEOUS_EQUILIBRIUM -species: -- name: A -- name: B -- name: C -- name: H2O -version: 1.0.0 diff --git a/test/unit/v1/v1_unit_configs/reactions/aqueous_equilibrium/missing_phase.json b/test/unit/v1/v1_unit_configs/reactions/aqueous_equilibrium/missing_phase.json deleted file mode 100644 index 98306c2c..00000000 --- a/test/unit/v1/v1_unit_configs/reactions/aqueous_equilibrium/missing_phase.json +++ /dev/null @@ -1,43 +0,0 @@ -{ - "version": "1.0.0", - "name": "Missing phase", - "species": [ - { - "name": "A" - }, - { - "name": "B" - }, - { - "name": "C" - }, - { - "name": "H2O" - } - ], - "phases": [], - "reactions": [ - { - "type": "AQUEOUS_EQUILIBRIUM", - "condensed phase": "aqueous", - "condensed-phase water": "H2O", - "k_reverse": 0.32, - "reactants": [ - { - "species name": "A", - "coefficient": 2 - } - ], - "products": [ - { - "species name": "B", - "coefficient": 1 - }, - { - "species name": "C", - "coefficient": 1 - } - ] - } - ] -} \ No newline at end of file diff --git a/test/unit/v1/v1_unit_configs/reactions/aqueous_equilibrium/missing_phase.yaml b/test/unit/v1/v1_unit_configs/reactions/aqueous_equilibrium/missing_phase.yaml deleted file mode 100644 index 8af9b72f..00000000 --- a/test/unit/v1/v1_unit_configs/reactions/aqueous_equilibrium/missing_phase.yaml +++ /dev/null @@ -1,21 +0,0 @@ -name: Missing phase -phases: [] -reactions: -- condensed phase: aqueous - condensed-phase water: H2O - k_reverse: 0.32 - products: - - coefficient: 1 - species name: B - - coefficient: 1 - species name: C - reactants: - - coefficient: 2 - species name: A - type: AQUEOUS_EQUILIBRIUM -species: -- name: A -- name: B -- name: C -- name: H2O -version: 1.0.0 diff --git a/test/unit/v1/v1_unit_configs/reactions/aqueous_equilibrium/unknown_species.json b/test/unit/v1/v1_unit_configs/reactions/aqueous_equilibrium/unknown_species.json deleted file mode 100644 index 9e4f8a94..00000000 --- a/test/unit/v1/v1_unit_configs/reactions/aqueous_equilibrium/unknown_species.json +++ /dev/null @@ -1,45 +0,0 @@ -{ - "version": "1.0.0", - "name": "Unknown species", - "species": [ - { - "name": "A" - }, - { - "name": "B" - } - ], - "phases": [ - { - "name": "aqueous", - "species": [ - "A", - "B" - ] - } - ], - "reactions": [ - { - "type": "AQUEOUS_EQUILIBRIUM", - "condensed phase": "aqueous", - "condensed-phase water": "H2O", - "k_reverse": 0.32, - "reactants": [ - { - "species name": "A", - "coefficient": 2 - } - ], - "products": [ - { - "species name": "B", - "coefficient": 1 - }, - { - "species name": "C", - "coefficient": 1 - } - ] - } - ] -} \ No newline at end of file diff --git a/test/unit/v1/v1_unit_configs/reactions/aqueous_equilibrium/unknown_species.yaml b/test/unit/v1/v1_unit_configs/reactions/aqueous_equilibrium/unknown_species.yaml deleted file mode 100644 index bf2108c1..00000000 --- a/test/unit/v1/v1_unit_configs/reactions/aqueous_equilibrium/unknown_species.yaml +++ /dev/null @@ -1,23 +0,0 @@ -name: Unknown species -phases: -- name: aqueous - species: - - A - - B -reactions: -- condensed phase: aqueous - condensed-phase water: H2O - k_reverse: 0.32 - products: - - coefficient: 1 - species name: B - - coefficient: 1 - species name: C - reactants: - - coefficient: 2 - species name: A - type: AQUEOUS_EQUILIBRIUM -species: -- name: A -- name: B -version: 1.0.0 diff --git a/test/unit/v1/v1_unit_configs/reactions/aqueous_equilibrium/valid.json b/test/unit/v1/v1_unit_configs/reactions/aqueous_equilibrium/valid.json deleted file mode 100644 index 829b06f3..00000000 --- a/test/unit/v1/v1_unit_configs/reactions/aqueous_equilibrium/valid.json +++ /dev/null @@ -1,79 +0,0 @@ -{ - "version": "1.0.0", - "name": "Valid aqueous equilibrium", - "species": [ - { - "name": "A" - }, - { - "name": "B" - }, - { - "name": "C" - }, - { - "name": "H2O" - } - ], - "phases": [ - { - "name": "aqueous", - "species": [ - "A", - "B", - "C", - "H2O" - ] - } - ], - "reactions": [ - { - "type": "AQUEOUS_EQUILIBRIUM", - "condensed phase": "aqueous", - "condensed-phase water": "H2O", - "A": 1.14e-2, - "C": 2300.0, - "k_reverse": 0.32, - "reactants": [ - { - "species name": "A", - "coefficient": 2 - } - ], - "products": [ - { - "species name": "B", - "coefficient": 1 - }, - { - "species name": "C", - "coefficient": 1 - } - ], - "name": "my aqueous eq", - "__comment": "GIF is pronounced with a hard g" - }, - { - "type": "AQUEOUS_EQUILIBRIUM", - "condensed phase": "aqueous", - "condensed-phase water": "H2O", - "k_reverse": 0.32, - "reactants": [ - { - "species name": "A", - "coefficient": 2 - } - ], - "products": [ - { - "species name": "B", - "coefficient": 1 - }, - { - "species name": "C", - "coefficient": 1 - } - ] - } - ] -} \ No newline at end of file diff --git a/test/unit/v1/v1_unit_configs/reactions/aqueous_equilibrium/valid.yaml b/test/unit/v1/v1_unit_configs/reactions/aqueous_equilibrium/valid.yaml deleted file mode 100644 index e2dd002b..00000000 --- a/test/unit/v1/v1_unit_configs/reactions/aqueous_equilibrium/valid.yaml +++ /dev/null @@ -1,43 +0,0 @@ -name: Valid aqueous equilibrium -phases: -- name: aqueous - species: - - A - - B - - C - - H2O -reactions: -- A: 0.0114 - C: 2300.0 - __comment: GIF is pronounced with a hard g - condensed phase: aqueous - condensed-phase water: H2O - k_reverse: 0.32 - name: my aqueous eq - products: - - coefficient: 1 - species name: B - - coefficient: 1 - species name: C - reactants: - - coefficient: 2 - species name: A - type: AQUEOUS_EQUILIBRIUM -- condensed phase: aqueous - condensed-phase water: H2O - k_reverse: 0.32 - products: - - coefficient: 1 - species name: B - - coefficient: 1 - species name: C - reactants: - - coefficient: 2 - species name: A - type: AQUEOUS_EQUILIBRIUM -species: -- name: A -- name: B -- name: C -- name: H2O -version: 1.0.0 diff --git a/test/unit/v1/v1_unit_configs/reactions/henrys_law/missing_phase.json b/test/unit/v1/v1_unit_configs/reactions/henrys_law/missing_phase.json deleted file mode 100644 index 6e9662f2..00000000 --- a/test/unit/v1/v1_unit_configs/reactions/henrys_law/missing_phase.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "version": "1.0.0", - "name": "Missing phase", - "species": [ - { - "name": "A" - }, - { - "name": "B" - }, - { - "name": "C" - } - ], - "phases": [ ], - "reactions": [ - { - "type": "HL_PHASE_TRANSFER", - "gas": { - "name": "gas", - "species": ["A"] - }, - "particle": { - "phase": "aqueous", - "solutes": ["B"], - "solvent": "H2O" - }, - "name": "my henry's law" - } - ] -} \ No newline at end of file diff --git a/test/unit/v1/v1_unit_configs/reactions/henrys_law/missing_phase.yaml b/test/unit/v1/v1_unit_configs/reactions/henrys_law/missing_phase.yaml deleted file mode 100644 index 16b37070..00000000 --- a/test/unit/v1/v1_unit_configs/reactions/henrys_law/missing_phase.yaml +++ /dev/null @@ -1,19 +0,0 @@ -version: 1.0.0 -name: Missing phase -species: - - name: A - - name: B - - name: C -phases: [] -reactions: - - type: HL_PHASE_TRANSFER - gas: - name: gas - species: - - A - particle: - phase: aqueous - solutes: - - B - solvent: H2O - name: my henry's law diff --git a/test/unit/v1/v1_unit_configs/reactions/henrys_law/solvent_species_not_registered_in_phase.json b/test/unit/v1/v1_unit_configs/reactions/henrys_law/solvent_species_not_registered_in_phase.json deleted file mode 100644 index 8e2ea836..00000000 --- a/test/unit/v1/v1_unit_configs/reactions/henrys_law/solvent_species_not_registered_in_phase.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "version": "1.0.0", - "name": "Solvent species in not registered in the corresponding phase", - "species": [ - { - "name": "A" - }, - { - "name": "B" - }, - { - "name": "C" - }, - { - "name": "H2O" - } - ], - "phases": [ - { - "name": "gas", - "species": [ - "A", - "B" - ] - }, - { - "name": "aqueous", - "species": [ - "H2O", - "C" - ] - } - ], - "reactions": [ - { - "type": "HL_PHASE_TRANSFER", - "gas": { - "name": "gas", - "species": ["A"] - }, - "particle": { - "phase": "aqueous", - "solutes": ["C"], - "solvent": "B" - }, - "name": "my henry's law", - "__comment": "hi" - } - ] -} \ No newline at end of file diff --git a/test/unit/v1/v1_unit_configs/reactions/henrys_law/solvent_species_not_registered_in_phase.yaml b/test/unit/v1/v1_unit_configs/reactions/henrys_law/solvent_species_not_registered_in_phase.yaml deleted file mode 100644 index 2c07bbcf..00000000 --- a/test/unit/v1/v1_unit_configs/reactions/henrys_law/solvent_species_not_registered_in_phase.yaml +++ /dev/null @@ -1,29 +0,0 @@ -version: "1.0.0" -name: "Solvent species in not registered in the corresponding phase" -species: - - name: "A" - - name: "B" - - name: "C" - - name: "H2O" -phases: - - name: "gas" - species: - - "A" - - "B" - - name: "aqueous" - species: - - "H2O" - - "C" -reactions: - - type: "HL_PHASE_TRANSFER" - gas: - name: "gas" - species: - - "A" - particle: - phase: "aqueous" - solutes: - - "C" - solvent: "B" - name: "my henry's law" - __comment: "hi" diff --git a/test/unit/v1/v1_unit_configs/reactions/henrys_law/species_not_found_in_gas_phase.json b/test/unit/v1/v1_unit_configs/reactions/henrys_law/species_not_found_in_gas_phase.json deleted file mode 100644 index 1d803b0f..00000000 --- a/test/unit/v1/v1_unit_configs/reactions/henrys_law/species_not_found_in_gas_phase.json +++ /dev/null @@ -1,44 +0,0 @@ -{ - "version": "1.0.0", - "name": "Gas species in reactions are not found in gas phase", - "species": [ - { - "name": "A" - }, - { - "name": "B" - }, - { - "name": "H2O" - } - ], - "phases": [ - { - "name": "gas", - "species": [ - "A" - ] - }, - { - "name": "aqueous", - "species": [ - "B", - "H2O" - ] - } - ], - "reactions": [ - { - "type": "HL_PHASE_TRANSFER", - "gas": { - "name": "gas", - "species": ["H2O"] - }, - "particle": { - "phase": "aqueous", - "solutes": ["B"], - "solvent": "H2O" - } - } - ] -} \ No newline at end of file diff --git a/test/unit/v1/v1_unit_configs/reactions/henrys_law/species_not_found_in_gas_phase.yaml b/test/unit/v1/v1_unit_configs/reactions/henrys_law/species_not_found_in_gas_phase.yaml deleted file mode 100644 index aecee3a8..00000000 --- a/test/unit/v1/v1_unit_configs/reactions/henrys_law/species_not_found_in_gas_phase.yaml +++ /dev/null @@ -1,25 +0,0 @@ -version: "1.0.0" -name: "Gas species in reactions are not found in gas phase" -species: - - name: "A" - - name: "B" - - name: "H2O" -phases: - - name: "gas" - species: - - "A" - - name: "aqueous" - species: - - "B" - - "H2O" -reactions: - - type: "HL_PHASE_TRANSFER" - gas: - name: "gas" - species: - - "H2O" - particle: - phase: "aqueous" - solutes: - - "B" - solvent: "H2O" diff --git a/test/unit/v1/v1_unit_configs/reactions/henrys_law/species_not_in_aqueous_phase.json b/test/unit/v1/v1_unit_configs/reactions/henrys_law/species_not_in_aqueous_phase.json deleted file mode 100644 index bef33e71..00000000 --- a/test/unit/v1/v1_unit_configs/reactions/henrys_law/species_not_in_aqueous_phase.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "version": "1.0.0", - "name": "Condensed phase arrhenius using species not in its requested condensed phase", - "species": [ - { - "name": "A" - }, - { - "name": "B" - }, - { - "name": "H2O" - } - ], - "phases": [ - { - "name": "gas", - "species": [ - "A", - "B" - ] - }, - { - "name": "aqueous", - "species": [ - "H2O" - ] - } - ], - "reactions": [ - { - "type": "HL_PHASE_TRANSFER", - "gas": { - "name": "gas", - "species": [ - "A" - ] - }, - "particle": { - "phase": "aqueous", - "solutes": [ - "B" - ], - "solvent": "H2O" - }, - "name": "my henry's law", - "__comment": "hi" - } - ] -} \ No newline at end of file diff --git a/test/unit/v1/v1_unit_configs/reactions/henrys_law/species_not_in_aqueous_phase.yaml b/test/unit/v1/v1_unit_configs/reactions/henrys_law/species_not_in_aqueous_phase.yaml deleted file mode 100644 index e6e925ac..00000000 --- a/test/unit/v1/v1_unit_configs/reactions/henrys_law/species_not_in_aqueous_phase.yaml +++ /dev/null @@ -1,27 +0,0 @@ -version: 1.0.0 -name: Condensed phase arrhenius using species not in its requested condensed phase -species: - - name: A - - name: B - - name: H2O -phases: - - name: gas - species: - - A - - B - - name: aqueous - species: - - H2O -reactions: - - type: HL_PHASE_TRANSFER - gas: - name: gas - species: - - A - particle: - phase: aqueous - solutes: - - B - solvent: H2O - name: my henry's law - __comment: hi diff --git a/test/unit/v1/v1_unit_configs/reactions/henrys_law/unknown_species.json b/test/unit/v1/v1_unit_configs/reactions/henrys_law/unknown_species.json deleted file mode 100644 index 0399c625..00000000 --- a/test/unit/v1/v1_unit_configs/reactions/henrys_law/unknown_species.json +++ /dev/null @@ -1,44 +0,0 @@ -{ - "version": "1.0.0", - "name": "Unknown species", - "species": [ - { - "name": "A" - }, - { - "name": "B" - }, - { - "name": "H2O" - } - ], - "phases": [ - { - "name": "gas", - "species": [ - "A" - ] - }, - { - "name": "aqueous", - "species": [ - "B", - "H2O" - ] - } - ], - "reactions": [ - { - "type": "HL_PHASE_TRANSFER", - "gas": { - "name": "gas", - "species": ["C"] - }, - "particle": { - "phase": "aqueous", - "solutes": ["B"], - "solvent": "H2O" - } - } - ] -} \ No newline at end of file diff --git a/test/unit/v1/v1_unit_configs/reactions/henrys_law/unknown_species.yaml b/test/unit/v1/v1_unit_configs/reactions/henrys_law/unknown_species.yaml deleted file mode 100644 index 308557e5..00000000 --- a/test/unit/v1/v1_unit_configs/reactions/henrys_law/unknown_species.yaml +++ /dev/null @@ -1,25 +0,0 @@ -version: 1.0.0 -name: Unknown species -species: - - name: A - - name: B - - name: H2O -phases: - - name: gas - species: - - A - - name: aqueous - species: - - B - - H2O -reactions: - - type: HL_PHASE_TRANSFER - gas: - name: gas - species: - - C - particle: - phase: aqueous - solutes: - - B - solvent: H2O diff --git a/test/unit/v1/v1_unit_configs/reactions/henrys_law/valid.json b/test/unit/v1/v1_unit_configs/reactions/henrys_law/valid.json deleted file mode 100644 index 9e14c186..00000000 --- a/test/unit/v1/v1_unit_configs/reactions/henrys_law/valid.json +++ /dev/null @@ -1,71 +0,0 @@ -{ - "version": "1.0.0", - "name": "Valid surface", - "species": [ - { - "name": "A" - }, - { - "name": "B" - }, - { - "name": "H2O" - }, - { - "name": "C" - } - ], - "phases": [ - { - "name": "gas", - "species": [ - "A" - ] - }, - { - "name": "aqueous", - "species": [ - "B", - "H2O", - "C" - ] - } - ], - "reactions": [ - { - "type": "HL_PHASE_TRANSFER", - "gas": { - "name": "gas", - "species": [ - "A" - ] - }, - "particle": { - "phase": "aqueous", - "solutes": [ - "B" - ], - "solvent": "H2O" - }, - "name": "my henry's law", - "__comment": "B condensed phase production (kg/m2/s)" - }, - { - "type": "HL_PHASE_TRANSFER", - "gas": { - "name": "gas", - "species": [ - "A" - ] - }, - "particle": { - "phase": "aqueous", - "solutes": [ - "B", - "C" - ], - "solvent": "H2O" - } - } - ] -} \ No newline at end of file diff --git a/test/unit/v1/v1_unit_configs/reactions/henrys_law/valid.yaml b/test/unit/v1/v1_unit_configs/reactions/henrys_law/valid.yaml deleted file mode 100644 index 5aab6050..00000000 --- a/test/unit/v1/v1_unit_configs/reactions/henrys_law/valid.yaml +++ /dev/null @@ -1,40 +0,0 @@ -version: 1.0.0 -name: Valid surface -species: - - name: A - - name: B - - name: H2O - - name: C -phases: - - name: gas - species: - - A - - name: aqueous - species: - - B - - H2O - - C -reactions: - - type: HL_PHASE_TRANSFER - gas: - name: gas - species: - - A - particle: - phase: aqueous - solutes: - - B - solvent: H2O - name: my henry's law - __comment: B condensed phase production (kg/m2/s) - - type: HL_PHASE_TRANSFER - gas: - name: gas - species: - - A - particle: - phase: aqueous - solutes: - - B - - C - solvent: H2O From f5f7c1f19708eea61b445f631ad088f6f550e6a9 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 17 Jun 2026 16:24:15 -0600 Subject: [PATCH 05/10] Auto-format code using Clang-Format (#277) Co-authored-by: GitHub Actions --- include/mechanism_configuration/types.hpp | 4 +- src/check_schema.cpp | 3 +- src/detail/v0/parser.hpp | 2 +- src/detail/v0/parser_types.hpp | 2 +- src/parse.cpp | 32 ++++++------ src/v0/arrhenius_parser.cpp | 7 ++- src/v0/branched_parser.cpp | 15 ++---- src/v0/emission_parser.cpp | 4 +- src/v0/first_order_loss_parser.cpp | 4 +- src/v0/parser.cpp | 7 +-- src/v0/photolysis_parser.cpp | 8 ++- src/v0/species_parser.cpp | 7 +-- src/v0/surface_parser.cpp | 4 +- src/v0/ternary_chemical_activation_parser.cpp | 6 +-- src/v0/troe_parser.cpp | 6 +-- src/v0/tunneling_parser.cpp | 4 +- src/v0/user_defined_reaction_parser.cpp | 8 ++- src/v1/parser.cpp | 30 +++++------ src/v1/reactions/arrhenius.cpp | 16 +++--- src/v1/reactions/branched.cpp | 19 +++---- src/v1/reactions/emission.cpp | 9 ++-- src/v1/reactions/first_order_loss.cpp | 9 ++-- src/v1/reactions/lambda_rate_constant.cpp | 9 ++-- src/v1/reactions/photolysis.cpp | 13 +++-- src/v1/reactions/surface.cpp | 20 ++++---- src/v1/reactions/taylor_series.cpp | 19 +++---- .../reactions/ternary_chemical_activation.cpp | 16 +++--- src/v1/reactions/troe.cpp | 16 +++--- src/v1/reactions/tunneling.cpp | 11 ++-- src/v1/reactions/user_defined.cpp | 13 +++-- src/v1/type_parsers.cpp | 9 ++-- src/v1/type_schema.cpp | 36 +++++++------ src/v1/utils.cpp | 9 ++-- src/validate.cpp | 51 +++++++++++-------- test/integration/test_v1_parser.cpp | 3 +- .../test_v1_read_from_file_configs.cpp | 4 +- ...test_parse_ternary_chemical_activation.cpp | 1 + 37 files changed, 212 insertions(+), 224 deletions(-) diff --git a/include/mechanism_configuration/types.hpp b/include/mechanism_configuration/types.hpp index fb568711..6a834f92 100644 --- a/include/mechanism_configuration/types.hpp +++ b/include/mechanism_configuration/types.hpp @@ -6,11 +6,11 @@ #include +#include #include #include #include #include -#include namespace mechanism_configuration::types { @@ -326,4 +326,4 @@ namespace mechanism_configuration::types std::vector lambda_rate_constant; }; -} // namespace mechanism_configuration +} // namespace mechanism_configuration::types diff --git a/src/check_schema.cpp b/src/check_schema.cpp index 8d7704c7..fcb50d70 100644 --- a/src/check_schema.cpp +++ b/src/check_schema.cpp @@ -2,9 +2,10 @@ // University of Illinois at Urbana-Champaign // SPDX-License-Identifier: Apache-2.0 -#include #include "detail/check_schema.hpp" +#include + #include namespace mechanism_configuration diff --git a/src/detail/v0/parser.hpp b/src/detail/v0/parser.hpp index bb63ab8c..a1dc58b0 100644 --- a/src/detail/v0/parser.hpp +++ b/src/detail/v0/parser.hpp @@ -9,9 +9,9 @@ #include +#include #include #include -#include namespace mechanism_configuration::v0 { diff --git a/src/detail/v0/parser_types.hpp b/src/detail/v0/parser_types.hpp index 9dae5f2f..353f52ca 100644 --- a/src/detail/v0/parser_types.hpp +++ b/src/detail/v0/parser_types.hpp @@ -5,8 +5,8 @@ #pragma once #include -#include #include +#include #include diff --git a/src/parse.cpp b/src/parse.cpp index 1da95e6d..56b0ab61 100644 --- a/src/parse.cpp +++ b/src/parse.cpp @@ -2,14 +2,14 @@ // University of Illinois at Urbana-Champaign // SPDX-License-Identifier: Apache-2.0 +#include "detail/v0/parser.hpp" +#include "detail/v1/parser.hpp" + #include #include #include #include -#include "detail/v0/parser.hpp" -#include "detail/v1/parser.hpp" - #include #include @@ -30,11 +30,12 @@ namespace mechanism_configuration { if (!std::filesystem::exists(config_path)) { - return std::unexpected( - Errors{ { ErrorCode::FileNotFound, mc_fmt::format("Configuration file '{}' does not exist.", config_path.string()) } }); + return std::unexpected(Errors{ + { ErrorCode::FileNotFound, mc_fmt::format("Configuration file '{}' does not exist.", config_path.string()) } }); } - if (std::filesystem::exists(config_path) && std::filesystem::is_directory(config_path)) { + if (std::filesystem::exists(config_path) && std::filesystem::is_directory(config_path)) + { return DetectedVersion{ Version(0, 0, 0), std::nullopt }; } @@ -45,8 +46,8 @@ namespace mechanism_configuration } catch (const YAML::Exception& e) { - return std::unexpected( - Errors{ { ErrorCode::UnexpectedError, mc_fmt::format("Failed to parse '{}': {}", config_path.string(), e.what()) } }); + return std::unexpected(Errors{ + { ErrorCode::UnexpectedError, mc_fmt::format("Failed to parse '{}': {}", config_path.string(), e.what()) } }); } // The version field is version-agnostic (it's how we dispatch), so read it literally @@ -73,18 +74,17 @@ namespace mechanism_configuration switch (version->version.major) { - case 0: - return v0::Parser{}.Parse(config_path); - case 1: - return v1::Parser{}.Parse(config_path); + case 0: return v0::Parser{}.Parse(config_path); + case 1: return v1::Parser{}.Parse(config_path); default: { // We only reach here after reading the version out of config_path, so it names a real // file and the version field has a location; point the error at it (path:line:col). - const std::string body = version->location - ? mc_fmt::format("{} error: Unsupported version number '{}'.", - *version->location, version->version.to_string()) - : mc_fmt::format("error: Unsupported version number '{}'.", version->version.to_string()); + const std::string body = + version->location + ? mc_fmt::format( + "{} error: Unsupported version number '{}'.", *version->location, version->version.to_string()) + : mc_fmt::format("error: Unsupported version number '{}'.", version->version.to_string()); return std::unexpected(Errors{ { ErrorCode::InvalidVersion, config_path.string() + ":" + body } }); } } diff --git a/src/v0/arrhenius_parser.cpp b/src/v0/arrhenius_parser.cpp index 1cbc3528..bba3b6e6 100644 --- a/src/v0/arrhenius_parser.cpp +++ b/src/v0/arrhenius_parser.cpp @@ -2,11 +2,11 @@ // University of Illinois at Urbana-Champaign // SPDX-License-Identifier: Apache-2.0 +#include "detail/check_schema.hpp" #include "detail/conversions.hpp" +#include "detail/v0/keys.hpp" #include "detail/v0/parser.hpp" #include "detail/v0/parser_types.hpp" -#include "detail/v0/keys.hpp" -#include "detail/check_schema.hpp" namespace mechanism_configuration::v0 { @@ -15,8 +15,7 @@ namespace mechanism_configuration::v0 Errors errors; std::vector required = { keys::TYPE, keys::REACTANTS, keys::PRODUCTS }; - std::vector optional = { keys::A, keys::B, keys::C, keys::D, - keys::E, keys::Ea, keys::MUSICA_NAME }; + std::vector optional = { keys::A, keys::B, keys::C, keys::D, keys::E, keys::Ea, keys::MUSICA_NAME }; auto validate = CheckSchema(object, required, optional); errors.insert(errors.end(), validate.begin(), validate.end()); diff --git a/src/v0/branched_parser.cpp b/src/v0/branched_parser.cpp index 534dbca4..2f1963f5 100644 --- a/src/v0/branched_parser.cpp +++ b/src/v0/branched_parser.cpp @@ -2,12 +2,12 @@ // University of Illinois at Urbana-Champaign // SPDX-License-Identifier: Apache-2.0 +#include "detail/check_schema.hpp" #include "detail/constants.hpp" #include "detail/conversions.hpp" +#include "detail/v0/keys.hpp" #include "detail/v0/parser.hpp" #include "detail/v0/parser_types.hpp" -#include "detail/v0/keys.hpp" -#include "detail/check_schema.hpp" namespace mechanism_configuration::v0 { @@ -15,14 +15,9 @@ namespace mechanism_configuration::v0 { Errors errors; - std::vector required = { keys::TYPE, - keys::REACTANTS, - keys::ALKOXY_PRODUCTS, - keys::NITRATE_PRODUCTS, - keys::X, - keys::Y, - keys::A0, - keys::n }; + std::vector required = { + keys::TYPE, keys::REACTANTS, keys::ALKOXY_PRODUCTS, keys::NITRATE_PRODUCTS, keys::X, keys::Y, keys::A0, keys::n + }; auto validate = CheckSchema(object, required, {}); errors.insert(errors.end(), validate.begin(), validate.end()); diff --git a/src/v0/emission_parser.cpp b/src/v0/emission_parser.cpp index 316aa304..e37b94fc 100644 --- a/src/v0/emission_parser.cpp +++ b/src/v0/emission_parser.cpp @@ -2,11 +2,11 @@ // University of Illinois at Urbana-Champaign // SPDX-License-Identifier: Apache-2.0 +#include "detail/check_schema.hpp" #include "detail/constants.hpp" +#include "detail/v0/keys.hpp" #include "detail/v0/parser.hpp" #include "detail/v0/parser_types.hpp" -#include "detail/v0/keys.hpp" -#include "detail/check_schema.hpp" namespace mechanism_configuration::v0 { diff --git a/src/v0/first_order_loss_parser.cpp b/src/v0/first_order_loss_parser.cpp index 00afb0cd..438e7651 100644 --- a/src/v0/first_order_loss_parser.cpp +++ b/src/v0/first_order_loss_parser.cpp @@ -2,11 +2,11 @@ // University of Illinois at Urbana-Champaign // SPDX-License-Identifier: Apache-2.0 +#include "detail/check_schema.hpp" #include "detail/constants.hpp" +#include "detail/v0/keys.hpp" #include "detail/v0/parser.hpp" #include "detail/v0/parser_types.hpp" -#include "detail/v0/keys.hpp" -#include "detail/check_schema.hpp" namespace mechanism_configuration::v0 { diff --git a/src/v0/parser.cpp b/src/v0/parser.cpp index 659da655..a221f6ca 100644 --- a/src/v0/parser.cpp +++ b/src/v0/parser.cpp @@ -2,12 +2,13 @@ // University of Illinois at Urbana-Champaign // SPDX-License-Identifier: Apache-2.0 +#include "detail/v0/parser.hpp" + +#include "detail/check_schema.hpp" #include "detail/constants.hpp" #include "detail/conversions.hpp" -#include "detail/v0/parser.hpp" -#include "detail/v0/parser_types.hpp" #include "detail/v0/keys.hpp" -#include "detail/check_schema.hpp" +#include "detail/v0/parser_types.hpp" #include diff --git a/src/v0/photolysis_parser.cpp b/src/v0/photolysis_parser.cpp index 25fa81b5..a71c75ed 100644 --- a/src/v0/photolysis_parser.cpp +++ b/src/v0/photolysis_parser.cpp @@ -2,11 +2,11 @@ // University of Illinois at Urbana-Champaign // SPDX-License-Identifier: Apache-2.0 +#include "detail/check_schema.hpp" #include "detail/constants.hpp" +#include "detail/v0/keys.hpp" #include "detail/v0/parser.hpp" #include "detail/v0/parser_types.hpp" -#include "detail/v0/keys.hpp" -#include "detail/check_schema.hpp" namespace mechanism_configuration::v0 { @@ -14,9 +14,7 @@ namespace mechanism_configuration::v0 { Errors errors; - std::vector required = { - keys::TYPE, keys::REACTANTS, keys::PRODUCTS, keys::MUSICA_NAME - }; + std::vector required = { keys::TYPE, keys::REACTANTS, keys::PRODUCTS, keys::MUSICA_NAME }; std::vector optional = { keys::SCALING_FACTOR }; auto validate = CheckSchema(object, required, optional); diff --git a/src/v0/species_parser.cpp b/src/v0/species_parser.cpp index 64069d6a..2484f1fe 100644 --- a/src/v0/species_parser.cpp +++ b/src/v0/species_parser.cpp @@ -2,10 +2,11 @@ // University of Illinois at Urbana-Champaign // SPDX-License-Identifier: Apache-2.0 -#include -#include "detail/v0/parser_types.hpp" -#include "detail/v0/keys.hpp" #include "detail/check_schema.hpp" +#include "detail/v0/keys.hpp" +#include "detail/v0/parser_types.hpp" + +#include namespace mechanism_configuration::v0 { diff --git a/src/v0/surface_parser.cpp b/src/v0/surface_parser.cpp index 9e849668..3e9eec75 100644 --- a/src/v0/surface_parser.cpp +++ b/src/v0/surface_parser.cpp @@ -2,11 +2,11 @@ // University of Illinois at Urbana-Champaign // SPDX-License-Identifier: Apache-2.0 +#include "detail/check_schema.hpp" #include "detail/constants.hpp" +#include "detail/v0/keys.hpp" #include "detail/v0/parser.hpp" #include "detail/v0/parser_types.hpp" -#include "detail/v0/keys.hpp" -#include "detail/check_schema.hpp" namespace mechanism_configuration::v0 { diff --git a/src/v0/ternary_chemical_activation_parser.cpp b/src/v0/ternary_chemical_activation_parser.cpp index 08e68765..89e5d56b 100644 --- a/src/v0/ternary_chemical_activation_parser.cpp +++ b/src/v0/ternary_chemical_activation_parser.cpp @@ -2,12 +2,12 @@ // University of Illinois at Urbana-Champaign // SPDX-License-Identifier: Apache-2.0 +#include "detail/check_schema.hpp" #include "detail/constants.hpp" #include "detail/conversions.hpp" +#include "detail/v0/keys.hpp" #include "detail/v0/parser.hpp" #include "detail/v0/parser_types.hpp" -#include "detail/v0/keys.hpp" -#include "detail/check_schema.hpp" namespace mechanism_configuration::v0 { @@ -17,7 +17,7 @@ namespace mechanism_configuration::v0 std::vector required = { keys::TYPE, keys::REACTANTS, keys::PRODUCTS }; std::vector optional = { keys::K0_A, keys::K0_B, keys::K0_C, keys::KINF_A, - keys::KINF_B, keys::KINF_C, keys::FC, keys::N }; + keys::KINF_B, keys::KINF_C, keys::FC, keys::N }; auto validate = CheckSchema(object, required, optional); errors.insert(errors.end(), validate.begin(), validate.end()); diff --git a/src/v0/troe_parser.cpp b/src/v0/troe_parser.cpp index 01111a73..fc2ad5a6 100644 --- a/src/v0/troe_parser.cpp +++ b/src/v0/troe_parser.cpp @@ -2,12 +2,12 @@ // University of Illinois at Urbana-Champaign // SPDX-License-Identifier: Apache-2.0 +#include "detail/check_schema.hpp" #include "detail/constants.hpp" #include "detail/conversions.hpp" +#include "detail/v0/keys.hpp" #include "detail/v0/parser.hpp" #include "detail/v0/parser_types.hpp" -#include "detail/v0/keys.hpp" -#include "detail/check_schema.hpp" namespace mechanism_configuration::v0 { @@ -17,7 +17,7 @@ namespace mechanism_configuration::v0 std::vector required = { keys::TYPE, keys::REACTANTS, keys::PRODUCTS }; std::vector optional = { keys::K0_A, keys::K0_B, keys::K0_C, keys::KINF_A, - keys::KINF_B, keys::KINF_C, keys::FC, keys::N }; + keys::KINF_B, keys::KINF_C, keys::FC, keys::N }; auto validate = CheckSchema(object, required, optional); errors.insert(errors.end(), validate.begin(), validate.end()); diff --git a/src/v0/tunneling_parser.cpp b/src/v0/tunneling_parser.cpp index 04b5182f..423b8a73 100644 --- a/src/v0/tunneling_parser.cpp +++ b/src/v0/tunneling_parser.cpp @@ -2,11 +2,11 @@ // University of Illinois at Urbana-Champaign // SPDX-License-Identifier: Apache-2.0 +#include "detail/check_schema.hpp" #include "detail/conversions.hpp" +#include "detail/v0/keys.hpp" #include "detail/v0/parser.hpp" #include "detail/v0/parser_types.hpp" -#include "detail/v0/keys.hpp" -#include "detail/check_schema.hpp" namespace mechanism_configuration::v0 { diff --git a/src/v0/user_defined_reaction_parser.cpp b/src/v0/user_defined_reaction_parser.cpp index f99654d8..858fce11 100644 --- a/src/v0/user_defined_reaction_parser.cpp +++ b/src/v0/user_defined_reaction_parser.cpp @@ -2,11 +2,11 @@ // University of Illinois at Urbana-Champaign // SPDX-License-Identifier: Apache-2.0 +#include "detail/check_schema.hpp" #include "detail/constants.hpp" +#include "detail/v0/keys.hpp" #include "detail/v0/parser.hpp" #include "detail/v0/parser_types.hpp" -#include "detail/v0/keys.hpp" -#include "detail/check_schema.hpp" namespace mechanism_configuration::v0 { @@ -14,9 +14,7 @@ namespace mechanism_configuration::v0 { Errors errors; - std::vector required = { - keys::TYPE, keys::REACTANTS, keys::PRODUCTS, keys::MUSICA_NAME - }; + std::vector required = { keys::TYPE, keys::REACTANTS, keys::PRODUCTS, keys::MUSICA_NAME }; std::vector optional = { keys::SCALING_FACTOR }; auto validate = CheckSchema(object, required, optional); diff --git a/src/v1/parser.cpp b/src/v1/parser.cpp index 02f8c61e..d5b01c1a 100644 --- a/src/v1/parser.cpp +++ b/src/v1/parser.cpp @@ -3,11 +3,13 @@ // SPDX-License-Identifier: Apache-2.0 #include "detail/v1/parser.hpp" + +#include "detail/check_schema.hpp" +#include "detail/v1/keys.hpp" #include "detail/v1/type_parsers.hpp" #include "detail/v1/type_schema.hpp" #include "detail/v1/utils.hpp" -#include "detail/check_schema.hpp" -#include "detail/v1/keys.hpp" + #include #include #include @@ -103,10 +105,9 @@ namespace mechanism_configuration::v1 { if (!std::filesystem::exists(config_path) || !std::filesystem::is_regular_file(config_path)) { - return std::unexpected( - Errors{ { ErrorCode::FileNotFound, - mc_fmt::format( - "Configuration file '{}' does not exist or is not a regular file.", config_path.string()) } }); + return std::unexpected(Errors{ + { ErrorCode::FileNotFound, + mc_fmt::format("Configuration file '{}' does not exist or is not a regular file.", config_path.string()) } }); } SetConfigPath(config_path.string()); @@ -118,9 +119,8 @@ namespace mechanism_configuration::v1 } catch (const std::exception& e) { - return std::unexpected( - Errors{ - { ErrorCode::UnexpectedError, mc_fmt::format("Failed to parse '{}': {}", config_path.string(), e.what()) } }); + return std::unexpected(Errors{ + { ErrorCode::UnexpectedError, mc_fmt::format("Failed to parse '{}': {}", config_path.string(), e.what()) } }); } Errors errors; @@ -188,9 +188,8 @@ namespace mechanism_configuration::v1 GetEntityFormat(object[std::string(keys::reactions)]) == EntityFormat::FileList); if (uses_filelist && version.minor < 1) { - errors.push_back( - { ErrorCode::InvalidVersion, - "File-list format requires minor version >= 1, got " + std::to_string(version.minor) + "." }); + errors.push_back({ ErrorCode::InvalidVersion, + "File-list format requires minor version >= 1, got " + std::to_string(version.minor) + "." }); AppendFilePath(config_path_, errors); return std::unexpected(std::move(errors)); } @@ -212,9 +211,7 @@ namespace mechanism_configuration::v1 { Errors errors; - std::vector required_keys = { - keys::version, keys::species, keys::phases, keys::reactions - }; + std::vector required_keys = { keys::version, keys::species, keys::phases, keys::reactions }; std::vector optional_keys = { keys::name }; // Return early if the required keys are not found @@ -292,7 +289,8 @@ namespace mechanism_configuration::v1 } catch (const std::exception& e) { - return std::unexpected(Errors{ { ErrorCode::UnexpectedError, mc_fmt::format("Failed to parse document: {}", e.what()) } }); + return std::unexpected( + Errors{ { ErrorCode::UnexpectedError, mc_fmt::format("Failed to parse document: {}", e.what()) } }); } return ValidateAndBuild(object); } diff --git a/src/v1/reactions/arrhenius.cpp b/src/v1/reactions/arrhenius.cpp index 498f6ace..e786de7c 100644 --- a/src/v1/reactions/arrhenius.cpp +++ b/src/v1/reactions/arrhenius.cpp @@ -2,15 +2,16 @@ // University of Illinois at Urbana-Champaign // SPDX-License-Identifier: Apache-2.0 +#include +#include +#include + +#include #include #include -#include #include #include #include -#include -#include -#include namespace mechanism_configuration { @@ -28,11 +29,8 @@ namespace mechanism_configuration const std::vector& existing_species, const std::vector& existing_phases) { - std::vector required_keys = { - keys::reactants, keys::products, keys::type, keys::gas_phase - }; - std::vector optional_keys = { keys::A, keys::B, keys::C, keys::D, - keys::E, keys::Ea, keys::name }; + std::vector required_keys = { keys::reactants, keys::products, keys::type, keys::gas_phase }; + std::vector optional_keys = { keys::A, keys::B, keys::C, keys::D, keys::E, keys::Ea, keys::name }; Errors errors; auto schema_errors = mechanism_configuration::CheckSchema(object, required_keys, optional_keys); diff --git a/src/v1/reactions/branched.cpp b/src/v1/reactions/branched.cpp index 34e117dd..a6a9a13c 100644 --- a/src/v1/reactions/branched.cpp +++ b/src/v1/reactions/branched.cpp @@ -2,14 +2,15 @@ // University of Illinois at Urbana-Champaign // SPDX-License-Identifier: Apache-2.0 -#include +#include +#include #include + +#include +#include #include #include #include -#include -#include -#include namespace mechanism_configuration { @@ -27,14 +28,10 @@ namespace mechanism_configuration const std::vector& existing_species, const std::vector& existing_phases) { - std::vector required_keys = { keys::type, - keys::gas_phase, - keys::reactants, - keys::alkoxy_products, - keys::nitrate_products }; - std::vector optional_keys = { - keys::name, keys::X, keys::Y, keys::a0, keys::n + std::vector required_keys = { + keys::type, keys::gas_phase, keys::reactants, keys::alkoxy_products, keys::nitrate_products }; + std::vector optional_keys = { keys::name, keys::X, keys::Y, keys::a0, keys::n }; Errors errors; diff --git a/src/v1/reactions/emission.cpp b/src/v1/reactions/emission.cpp index 2aecde92..c5e94aad 100644 --- a/src/v1/reactions/emission.cpp +++ b/src/v1/reactions/emission.cpp @@ -2,14 +2,15 @@ // University of Illinois at Urbana-Champaign // SPDX-License-Identifier: Apache-2.0 -#include +#include +#include #include + +#include +#include #include #include #include -#include -#include -#include namespace mechanism_configuration { diff --git a/src/v1/reactions/first_order_loss.cpp b/src/v1/reactions/first_order_loss.cpp index 95e92716..5fbed8a3 100644 --- a/src/v1/reactions/first_order_loss.cpp +++ b/src/v1/reactions/first_order_loss.cpp @@ -2,14 +2,15 @@ // University of Illinois at Urbana-Champaign // SPDX-License-Identifier: Apache-2.0 -#include +#include +#include #include + +#include +#include #include #include #include -#include -#include -#include namespace mechanism_configuration { diff --git a/src/v1/reactions/lambda_rate_constant.cpp b/src/v1/reactions/lambda_rate_constant.cpp index 692d1b6e..466b5ebe 100644 --- a/src/v1/reactions/lambda_rate_constant.cpp +++ b/src/v1/reactions/lambda_rate_constant.cpp @@ -2,14 +2,15 @@ // University of Illinois at Urbana-Champaign // SPDX-License-Identifier: Apache-2.0 -#include +#include +#include #include + +#include +#include #include #include #include -#include -#include -#include namespace mechanism_configuration { diff --git a/src/v1/reactions/photolysis.cpp b/src/v1/reactions/photolysis.cpp index 7722473d..8f66bd93 100644 --- a/src/v1/reactions/photolysis.cpp +++ b/src/v1/reactions/photolysis.cpp @@ -2,14 +2,15 @@ // University of Illinois at Urbana-Champaign // SPDX-License-Identifier: Apache-2.0 -#include +#include +#include #include + +#include +#include #include #include #include -#include -#include -#include namespace mechanism_configuration { @@ -27,9 +28,7 @@ namespace mechanism_configuration const std::vector& existing_species, const std::vector& existing_phases) { - std::vector required_keys = { - keys::reactants, keys::products, keys::type, keys::gas_phase - }; + std::vector required_keys = { keys::reactants, keys::products, keys::type, keys::gas_phase }; std::vector optional_keys = { keys::name, keys::scaling_factor }; Errors errors; diff --git a/src/v1/reactions/surface.cpp b/src/v1/reactions/surface.cpp index e0a12afa..c195dec5 100644 --- a/src/v1/reactions/surface.cpp +++ b/src/v1/reactions/surface.cpp @@ -2,14 +2,15 @@ // University of Illinois at Urbana-Champaign // SPDX-License-Identifier: Apache-2.0 -#include +#include +#include #include + +#include +#include #include #include #include -#include -#include -#include namespace mechanism_configuration { @@ -27,13 +28,10 @@ namespace mechanism_configuration const std::vector& existing_species, const std::vector& existing_phases) { - std::vector required_keys = { keys::gas_phase_products, - keys::gas_phase_species, - keys::type, - keys::gas_phase }; - std::vector optional_keys = { keys::name, - keys::reaction_probability, - keys::condensed_phase }; + std::vector required_keys = { + keys::gas_phase_products, keys::gas_phase_species, keys::type, keys::gas_phase + }; + std::vector optional_keys = { keys::name, keys::reaction_probability, keys::condensed_phase }; Errors errors; diff --git a/src/v1/reactions/taylor_series.cpp b/src/v1/reactions/taylor_series.cpp index df8e2867..d40c6c4e 100644 --- a/src/v1/reactions/taylor_series.cpp +++ b/src/v1/reactions/taylor_series.cpp @@ -2,15 +2,16 @@ // University of Illinois at Urbana-Champaign // SPDX-License-Identifier: Apache-2.0 +#include +#include +#include + +#include #include #include -#include #include #include #include -#include -#include -#include namespace mechanism_configuration { @@ -28,13 +29,9 @@ namespace mechanism_configuration const std::vector& existing_species, const std::vector& existing_phases) { - std::vector required_keys = { - keys::reactants, keys::products, keys::type, keys::gas_phase - }; - std::vector optional_keys = { keys::A, keys::B, - keys::C, keys::D, - keys::E, keys::Ea, - keys::name, keys::taylor_coefficients }; + std::vector required_keys = { keys::reactants, keys::products, keys::type, keys::gas_phase }; + std::vector optional_keys = { keys::A, keys::B, keys::C, keys::D, + keys::E, keys::Ea, keys::name, keys::taylor_coefficients }; Errors errors; auto schema_errors = mechanism_configuration::CheckSchema(object, required_keys, optional_keys); diff --git a/src/v1/reactions/ternary_chemical_activation.cpp b/src/v1/reactions/ternary_chemical_activation.cpp index 938bb663..8c3733f5 100644 --- a/src/v1/reactions/ternary_chemical_activation.cpp +++ b/src/v1/reactions/ternary_chemical_activation.cpp @@ -2,13 +2,14 @@ // University of Illinois at Urbana-Champaign // SPDX-License-Identifier: Apache-2.0 -#include +#include #include + +#include +#include #include #include #include -#include -#include namespace mechanism_configuration { @@ -26,12 +27,9 @@ namespace mechanism_configuration const std::vector& existing_species, const std::vector& existing_phases) { - std::vector required_keys = { - keys::reactants, keys::products, keys::type, keys::gas_phase - }; - std::vector optional_keys = { keys::name, keys::k0_A, keys::k0_B, - keys::k0_C, keys::kinf_A, keys::kinf_B, - keys::kinf_C, keys::Fc, keys::N }; + std::vector required_keys = { keys::reactants, keys::products, keys::type, keys::gas_phase }; + std::vector optional_keys = { keys::name, keys::k0_A, keys::k0_B, keys::k0_C, keys::kinf_A, + keys::kinf_B, keys::kinf_C, keys::Fc, keys::N }; Errors errors; auto schema_errors = mechanism_configuration::CheckSchema(object, required_keys, optional_keys); diff --git a/src/v1/reactions/troe.cpp b/src/v1/reactions/troe.cpp index bbe59213..d154fcb7 100644 --- a/src/v1/reactions/troe.cpp +++ b/src/v1/reactions/troe.cpp @@ -2,13 +2,14 @@ // University of Illinois at Urbana-Champaign // SPDX-License-Identifier: Apache-2.0 -#include +#include #include + +#include +#include #include #include #include -#include -#include namespace mechanism_configuration { @@ -26,12 +27,9 @@ namespace mechanism_configuration const std::vector& existing_species, const std::vector& existing_phases) { - std::vector required_keys = { - keys::reactants, keys::products, keys::type, keys::gas_phase - }; - std::vector optional_keys = { keys::name, keys::k0_A, keys::k0_B, - keys::k0_C, keys::kinf_A, keys::kinf_B, - keys::kinf_C, keys::Fc, keys::N }; + std::vector required_keys = { keys::reactants, keys::products, keys::type, keys::gas_phase }; + std::vector optional_keys = { keys::name, keys::k0_A, keys::k0_B, keys::k0_C, keys::kinf_A, + keys::kinf_B, keys::kinf_C, keys::Fc, keys::N }; Errors errors; auto schema_errors = mechanism_configuration::CheckSchema(object, required_keys, optional_keys); diff --git a/src/v1/reactions/tunneling.cpp b/src/v1/reactions/tunneling.cpp index a0608852..37a0bb5a 100644 --- a/src/v1/reactions/tunneling.cpp +++ b/src/v1/reactions/tunneling.cpp @@ -2,13 +2,14 @@ // University of Illinois at Urbana-Champaign // SPDX-License-Identifier: Apache-2.0 -#include +#include #include + +#include +#include #include #include #include -#include -#include namespace mechanism_configuration { @@ -26,9 +27,7 @@ namespace mechanism_configuration const std::vector& existing_species, const std::vector& existing_phases) { - std::vector required_keys = { - keys::reactants, keys::products, keys::type, keys::gas_phase - }; + std::vector required_keys = { keys::reactants, keys::products, keys::type, keys::gas_phase }; std::vector optional_keys = { keys::name, keys::A, keys::B, keys::C }; Errors errors; diff --git a/src/v1/reactions/user_defined.cpp b/src/v1/reactions/user_defined.cpp index 9418f4d0..e76a9cb3 100644 --- a/src/v1/reactions/user_defined.cpp +++ b/src/v1/reactions/user_defined.cpp @@ -2,14 +2,15 @@ // University of Illinois at Urbana-Champaign // SPDX-License-Identifier: Apache-2.0 -#include +#include +#include #include + +#include +#include #include #include #include -#include -#include -#include namespace mechanism_configuration { @@ -27,9 +28,7 @@ namespace mechanism_configuration const std::vector& existing_species, const std::vector& existing_phases) { - std::vector required_keys = { - keys::reactants, keys::products, keys::type, keys::gas_phase - }; + std::vector required_keys = { keys::reactants, keys::products, keys::type, keys::gas_phase }; std::vector optional_keys = { keys::name, keys::scaling_factor }; Errors errors; diff --git a/src/v1/type_parsers.cpp b/src/v1/type_parsers.cpp index 19c6e155..cdf54a2c 100644 --- a/src/v1/type_parsers.cpp +++ b/src/v1/type_parsers.cpp @@ -2,10 +2,12 @@ // University of Illinois at Urbana-Champaign // SPDX-License-Identifier: Apache-2.0 -#include "detail/v1/reaction_parsers.hpp" #include "detail/v1/type_parsers.hpp" -#include "detail/v1/utils.hpp" + #include "detail/v1/keys.hpp" +#include "detail/v1/reaction_parsers.hpp" +#include "detail/v1/utils.hpp" + #include namespace mechanism_configuration @@ -32,8 +34,7 @@ namespace mechanism_configuration if (object[keys::henrys_law_constant_298]) species.henrys_law_constant_298 = object[keys::henrys_law_constant_298].as(); if (object[keys::henrys_law_constant_exponential_factor]) - species.henrys_law_constant_exponential_factor = - object[keys::henrys_law_constant_exponential_factor].as(); + species.henrys_law_constant_exponential_factor = object[keys::henrys_law_constant_exponential_factor].as(); if (object[keys::n_star]) species.n_star = object[keys::n_star].as(); if (object[keys::density]) diff --git a/src/v1/type_schema.cpp b/src/v1/type_schema.cpp index 23d53312..a627c389 100644 --- a/src/v1/type_schema.cpp +++ b/src/v1/type_schema.cpp @@ -2,15 +2,15 @@ // University of Illinois at Urbana-Champaign // SPDX-License-Identifier: Apache-2.0 -#include -#include -#include +#include "detail/v1/type_schema.hpp" +#include "detail/check_schema.hpp" +#include "detail/v1/keys.hpp" #include "detail/v1/reaction_parsers.hpp" -#include "detail/v1/type_schema.hpp" #include "detail/v1/utils.hpp" -#include "detail/v1/keys.hpp" -#include "detail/check_schema.hpp" + +#include +#include #include #include @@ -23,16 +23,16 @@ namespace mechanism_configuration { const std::vector required_keys = { keys::name }; const std::vector optional_keys = { keys::absolute_tolerance, - keys::diffusion_coefficient, - keys::molecular_weight, - keys::henrys_law_constant_298, - keys::henrys_law_constant_exponential_factor, - keys::n_star, - keys::density, - keys::tracer_type, - keys::constant_concentration, - keys::constant_mixing_ratio, - keys::is_third_body }; + keys::diffusion_coefficient, + keys::molecular_weight, + keys::henrys_law_constant_298, + keys::henrys_law_constant_exponential_factor, + keys::n_star, + keys::density, + keys::tracer_type, + keys::constant_concentration, + keys::constant_mixing_ratio, + keys::is_third_body }; // Structural validation only. Duplicate-species detection (a semantic check) is performed // by the version-neutral ValidateSemantics. Errors errors; @@ -81,9 +81,7 @@ namespace mechanism_configuration const std::vector optional_keys = { keys::coefficient }; // A component's species reference may use the canonical `name` or the legacy // `species name` alias, but exactly one of them. - const std::vector> exactly_one_of = { - { keys::name, keys::species_name } - }; + const std::vector> exactly_one_of = { { keys::name, keys::species_name } }; Errors errors; diff --git a/src/v1/utils.cpp b/src/v1/utils.cpp index de3f94c0..09e9e2dc 100644 --- a/src/v1/utils.cpp +++ b/src/v1/utils.cpp @@ -2,12 +2,13 @@ // University of Illinois at Urbana-Champaign // SPDX-License-Identifier: Apache-2.0 -#include -#include - #include "detail/v1/utils.hpp" -#include "detail/v1/keys.hpp" + #include "detail/check_schema.hpp" +#include "detail/v1/keys.hpp" + +#include +#include #include #include diff --git a/src/validate.cpp b/src/validate.cpp index e94572a2..84772969 100644 --- a/src/validate.cpp +++ b/src/validate.cpp @@ -25,11 +25,8 @@ namespace mechanism_configuration } // Emits one error per occurrence of each name that appears more than once. - void ReportDuplicates( - const std::vector& refs, - ErrorCode code, - std::string_view what, - Errors& errors) + void + ReportDuplicates(const std::vector& refs, ErrorCode code, std::string_view what, Errors& errors) { std::unordered_map counts; for (const auto& ref : refs) @@ -63,9 +60,10 @@ namespace mechanism_configuration { registered.insert(ps.name); if (!species_names.contains(ps.name)) - errors.push_back({ ErrorCode::PhaseRequiresUnknownSpecies, - Message(ps.location, mc_fmt::format("Unknown species name '{}' found in '{}' phase.", - ps.name, phase.name)) }); + errors.push_back( + { ErrorCode::PhaseRequiresUnknownSpecies, + Message( + ps.location, mc_fmt::format("Unknown species name '{}' found in '{}' phase.", ps.name, phase.name)) }); } ReportDuplicates(phase.species, ErrorCode::DuplicateSpeciesInPhaseDetected, "species", errors); } @@ -78,27 +76,36 @@ namespace mechanism_configuration const bool phase_exists = phase_it != phase_species.end(); if (!phase_exists) errors.push_back({ ErrorCode::UnknownPhase, - Message(reaction.location, - mc_fmt::format("Unknown phase '{}' in '{}' reaction.", reaction.phase, reaction.type)) }); + Message( + reaction.location, + mc_fmt::format("Unknown phase '{}' in '{}' reaction.", reaction.phase, reaction.type)) }); for (const auto& reactant : reaction.reactants) { if (!species_names.contains(reactant.name)) - errors.push_back({ ErrorCode::ReactionRequiresUnknownSpecies, - Message(reactant.location, mc_fmt::format("Unknown species '{}' used in '{}' reaction.", - reactant.name, reaction.type)) }); + errors.push_back( + { ErrorCode::ReactionRequiresUnknownSpecies, + Message( + reactant.location, + mc_fmt::format("Unknown species '{}' used in '{}' reaction.", reactant.name, reaction.type)) }); else if (phase_exists && !phase_it->second.contains(reactant.name)) errors.push_back({ ErrorCode::RequestedSpeciesNotRegisteredInPhase, - Message(reactant.location, - mc_fmt::format("Species '{}' used in '{}' is not defined in the '{}' phase.", - reactant.name, reaction.type, reaction.phase)) }); + Message( + reactant.location, + mc_fmt::format( + "Species '{}' used in '{}' is not defined in the '{}' phase.", + reactant.name, + reaction.type, + reaction.phase)) }); } for (const auto& product : reaction.products) { if (!species_names.contains(product.name)) - errors.push_back({ ErrorCode::ReactionRequiresUnknownSpecies, - Message(product.location, mc_fmt::format("Unknown species '{}' used in '{}' reaction.", - product.name, reaction.type)) }); + errors.push_back( + { ErrorCode::ReactionRequiresUnknownSpecies, + Message( + product.location, + mc_fmt::format("Unknown species '{}' used in '{}' reaction.", product.name, reaction.type)) }); } } @@ -143,8 +150,10 @@ namespace mechanism_configuration } const auto& r = mechanism.reactions; - auto add = [&](std::string_view type, const std::string& phase, - std::vector reactants, std::vector products) + auto add = [&](std::string_view type, + const std::string& phase, + std::vector reactants, + std::vector products) { input.reactions.push_back(ReactionRefOf(type, phase, std::move(reactants), std::move(products))); }; for (const auto& x : r.arrhenius) diff --git a/test/integration/test_v1_parser.cpp b/test/integration/test_v1_parser.cpp index fe7658aa..5a23a58c 100644 --- a/test/integration/test_v1_parser.cpp +++ b/test/integration/test_v1_parser.cpp @@ -2,9 +2,10 @@ // University of Illinois at Urbana-Champaign // SPDX-License-Identifier: Apache-2.0 -#include #include "detail/v1/parser.hpp" +#include + #include #include diff --git a/test/integration/test_v1_read_from_file_configs.cpp b/test/integration/test_v1_read_from_file_configs.cpp index 2fca069e..86c926aa 100644 --- a/test/integration/test_v1_read_from_file_configs.cpp +++ b/test/integration/test_v1_read_from_file_configs.cpp @@ -15,8 +15,8 @@ using namespace mechanism_configuration; // Parse() resolves and merges them into one mechanism. TEST(V1FileConfigs, ParsesMultiFileConfiguration) { - for (const auto& main : { std::string("examples/v1/config/json/main.json"), - std::string("examples/v1/config/yaml/main.yaml") }) + for (const auto& main : + { std::string("examples/v1/config/json/main.json"), std::string("examples/v1/config/yaml/main.yaml") }) { auto parsed = Parse(main); if (!parsed) diff --git a/test/unit/v1/reactions/test_parse_ternary_chemical_activation.cpp b/test/unit/v1/reactions/test_parse_ternary_chemical_activation.cpp index f079b9ed..df198197 100644 --- a/test/unit/v1/reactions/test_parse_ternary_chemical_activation.cpp +++ b/test/unit/v1/reactions/test_parse_ternary_chemical_activation.cpp @@ -4,6 +4,7 @@ #include "detail/constants.hpp" #include "detail/conversions.hpp" + #include #include From a375b9793845fe92fed5b3322676abc7b384d33c Mon Sep 17 00:00:00 2001 From: Jiwon Gim <55209567+boulderdaze@users.noreply.github.com> Date: Wed, 24 Jun 2026 11:57:14 -0600 Subject: [PATCH 06/10] Add aerosol and cloud specific configurations (#279) * clean up the config file for cloud chemistry * distinguish between micm arrhenius and miam arrhneius * add miam struct and keys * code cleanup * Update test/integration/integration_configs/cam_clound_chemistry.json Co-authored-by: Kyle Shores --------- Co-authored-by: Kyle Shores --- .../mechanism_configuration/aerosol_types.hpp | 167 +++++++++++++ src/detail/v1/aerosol_keys.hpp | 90 +++++++ .../cam_clound_chemistry.json | 232 ++++++++++++++++++ 3 files changed, 489 insertions(+) create mode 100644 include/mechanism_configuration/aerosol_types.hpp create mode 100644 src/detail/v1/aerosol_keys.hpp create mode 100644 test/integration/integration_configs/cam_clound_chemistry.json diff --git a/include/mechanism_configuration/aerosol_types.hpp b/include/mechanism_configuration/aerosol_types.hpp new file mode 100644 index 00000000..e88c096a --- /dev/null +++ b/include/mechanism_configuration/aerosol_types.hpp @@ -0,0 +1,167 @@ +// Copyright (C) 2023–2026 University Corporation for Atmospheric Research +// University of Illinois at Urbana-Champaign +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include + +#include +#include +#include +#include +#include +#include + +namespace mechanism_configuration::types +{ + // ---------------------------------------- + // Rate constants + // ---------------------------------------- + + /// @brief Reference-temperature Arrhenius + /// f(T) = A * exp( C * (1/T0 - 1/T) ) (C = +Ea/R, positive) + struct ArrheniusReferenceTemperature + { + double A; ///< Value at the reference temperature T0 [units vary by use] + double C = 0.0; ///< Temperature-dependence parameter [K] (C = +Ea/R) + double T0 = 298.15; ///< Reference temperature [K] + }; + + /// @brief Equilibrium constants use the same reference-temperature form. + using EquilibriumConstant = ArrheniusReferenceTemperature; + + /// @brief Henry's law constant: HLC(T) = HLC_ref * exp( C * (1/T - 1/T0) ) + /// Same as ArrheniusReferenceTemperature but with the + /// opposite temperature trend (solubility rises as T falls) + struct HenryLawConstant + { + double HLC_ref; ///< Reference HLC at T0 [mol m-3 Pa-1] + double C = 0.0; ///< Temperature-dependence parameter [K] + double T0 = 298.15; ///< Reference temperature [K] + }; + + /// @brief A reaction rate constant parsed from config. + using RateConstant = std::variant>; + + // ---------------------------------------- + // Representations + // ---------------------------------------- + + struct UniformSection + { + std::string name; + std::vector phases; + double min_radius; ///< [m] + double max_radius; ///< [m] + }; + + struct SingleMomentMode + { + std::string name; + std::vector phases; + double geometric_mean_radius; ///< [m] + double geometric_standard_deviation; ///< dimensionless + }; + + struct TwoMomentMode + { + std::string name; + std::vector phases; + double geometric_standard_deviation; ///< dimensionless + }; + + using Representation = std::variant; + + // ---------------------------------------- + // Processes + // ---------------------------------------- + + struct DissolvedReaction + { + std::string phase; + std::string solvent; + std::vector reactants; + std::vector products; + /// @brief Rate constant per aerosol representation; keys are representation names. + std::map rate_constants; + }; + + struct DissolvedReversibleReaction + { + std::string phase; + std::string solvent; + std::vector reactants; + std::vector products; + /// @brief Per-representation forward / reverse rate constants; keys are representation names. + /// Supply exactly two of {forward, reverse, equilibrium} per representation; the third is derived. + std::map forward_rate_constants; + std::map reverse_rate_constants; + /// @brief Shared, intrinsic equilibrium constant (NOT per representation). + std::optional equilibrium_constant; + }; + + struct HenryLawPhaseTransfer + { + std::string gas_phase; + std::string gas_species; + std::string condensed_phase; + std::string condensed_species; + std::string solvent; + HenryLawConstant henry_law_constant; + HenryLawConstant henry_law_constant; + double diffusion_coefficient; ///< Gas-phase diffusion coefficient [m2 s-1] + double accommodation_coefficient; ///< Mass accommodation coefficient, dimensionless + }; + + using Process = std::variant; + + // ---------------------------------------- + // Constraints + // ---------------------------------------- + + struct HenryLawEquilibrium + { + std::string gas_phase; + std::string gas_species; + std::string condensed_phase; + std::string condensed_species; + std::string solvent; + HenryLawConstant henry_law_constant; + double solvent_molecular_weight; ///< [kg mol-1] + double solvent_density; ///< [kg m-3] + }; + + struct DissolvedEquilibrium + { + std::string phase; + std::string algebraic_species; + std::string solvent; + std::vector reactants; + std::vector products; + EquilibriumConstant equilibrium_constant; + }; + + struct LinearConstraintTerm + { + std::string phase; + std::string species; + double coefficient; + }; + + /// @brief RHS constant C of a LinearConstraint: G = sum(coeff_i * [species_i]) - C = 0 + /// Choose exactly one mode (mutually exclusive): + struct FixedConstant { double value = 0.0; }; ///< Fixed value [mol m-3], shared by all instances + struct DiagnoseFromState {}; ///< Computed per representation instance + + struct LinearConstraint + { + std::string algebraic_phase; + std::string algebraic_species; + std::vector terms; + std::variant constant = FixedConstant{ 0.0 }; + }; + + using Constraint = std::variant; + +} // namespace mechanism_configuration::types \ No newline at end of file diff --git a/src/detail/v1/aerosol_keys.hpp b/src/detail/v1/aerosol_keys.hpp new file mode 100644 index 00000000..c93825e3 --- /dev/null +++ b/src/detail/v1/aerosol_keys.hpp @@ -0,0 +1,90 @@ +// Copyright (C) 2023–2026 University Corporation for Atmospheric Research +// University of Illinois at Urbana-Champaign +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include + +namespace mechanism_configuration::v1::keys +{ + // ---------------------------------------- + // Top-level containers + // ---------------------------------------- + inline constexpr std::string_view aerosol_representations = "aerosol representations"; + inline constexpr std::string_view aerosol_processes = "aerosol processes"; + + // ---------------------------------------- + // Representations + // ---------------------------------------- + // also: name, phases + + inline constexpr std::string_view UniformSection_key = "UNIFORM_SECTION"; + inline constexpr std::string_view minimum_radius = "minimum radius [m]"; + inline constexpr std::string_view maximum_radius = "maximum radius [m]"; + + inline constexpr std::string_view SingleMomentMode_key = "SINGLE_MOMENT_MODE"; + inline constexpr std::string_view geometric_mean_radius = "geometric mean radius [m]"; + inline constexpr std::string_view geometric_standard_deviation = "geometric standard deviation [-]"; + + inline constexpr std::string_view TwoMomentMode_key = "TWO_MOMENT_MODE"; + // also: geometric_standard_deviation + + // ---------------------------------------- + // Rate constants + // ---------------------------------------- + inline constexpr std::string_view rate_constants = "rate constants"; + inline constexpr std::string_view forward_rate_constants = "forward rate constants"; + inline constexpr std::string_view reverse_rate_constants = "reverse rate constants"; + inline constexpr std::string_view equilibrium_constant = "equilibrium constant"; + inline constexpr std::string_view reference_temperature = "T0 [K]"; + + inline constexpr std::string_view henry_law_constant = "Henry's law constant"; + inline constexpr std::string_view HLC_ref = "HLC_ref [mol m-3 Pa-1]"; + inline constexpr std::string_view henry_law_C = "C [K]"; + + // ---------------------------------------- + // Processes + // ---------------------------------------- + inline constexpr std::string_view solvent = "solvent"; + + // HenryLawPhaseTransfer + // also: gas_phase, gas_phase_species, condensed_phase, condensed_phase_species, solvent, + // henry_law_constant, diffusion_coefficient + inline constexpr std::string_view HenryLawPhaseTransfer_key = "HENRY_LAW_PHASE_TRANSFER"; + inline constexpr std::string_view accommodation_coefficient = "accommodation coefficient [-]"; + + // DissolvedReaction + // also: condensed_phase, solvent, reactants, products, rate_constants + inline constexpr std::string_view DissolvedReaction_key = "DISSOLVED_REACTION"; + + // DissolvedReversibleReaction + // also: condensed_phase, solvent, reactants, products, + // forward_rate_constants, reverse_rate_constants, equilibrium_constant + inline constexpr std::string_view DissolvedReversibleReaction_key = "DISSOLVED_REVERSIBLE_REACTION"; + + // ---------------------------------------- + // Constraints + // ---------------------------------------- + // HenryLawEquilibrium + // also: gas_phase, gas_phase_species, condensed_phase, condensed_phase_species, solvent, + // henry_law_constant + inline constexpr std::string_view HenryLawEquilibrium_key = "HENRY_LAW_EQUILIBRIUM"; + inline constexpr std::string_view solvent_molecular_weight = "solvent molecular weight [kg mol-1]"; + inline constexpr std::string_view solvent_density = "solvent density [kg m-3]"; + + // DissolvedEquilibrium + // also: condensed_phase, solvent, reactants, products, equilibrium_constant + inline constexpr std::string_view DissolvedEquilibrium_key = "DISSOLVED_EQUILIBRIUM"; + inline constexpr std::string_view algebraic_species = "algebraic species"; + + // LinearConstraint + // also: name; terms carry coefficient and species + inline constexpr std::string_view LinearConstraint_key = "LINEAR_CONSTRAINT"; + inline constexpr std::string_view algebraic_phase = "algebraic phase"; + inline constexpr std::string_view terms = "terms"; + inline constexpr std::string_view phase = "phase"; + inline constexpr std::string_view constant = "constant [mol m-3]"; + inline constexpr std::string_view diagnose_from_state = "diagnose from state"; + +} // namespace mechanism_configuration::v1::keys diff --git a/test/integration/integration_configs/cam_clound_chemistry.json b/test/integration/integration_configs/cam_clound_chemistry.json new file mode 100644 index 00000000..829221b4 --- /dev/null +++ b/test/integration/integration_configs/cam_clound_chemistry.json @@ -0,0 +1,232 @@ +{ + "version": "1.2.0", + "name": "CAM Cloud Chemistry", + + "species": [ + { "name": "SO2", "molecular weight [kg mol-1]": 0.06407 }, + { "name": "H2O2", "molecular weight [kg mol-1]": 0.03401 }, + { "name": "O3", "molecular weight [kg mol-1]": 0.04800 }, + { "name": "Hp", "molecular weight [kg mol-1]": 0.00101 }, + { "name": "OHm", "molecular weight [kg mol-1]": 0.01701 }, + { "name": "HSO3m", "molecular weight [kg mol-1]": 0.08107 }, + { "name": "SO3mm", "molecular weight [kg mol-1]": 0.08007 }, + { "name": "SO4mm", "molecular weight [kg mol-1]": 0.09607 }, + { "name": "SO2OOHm", "molecular weight [kg mol-1]": 0.11307 }, + { "name": "H2O", "molecular weight [kg mol-1]": 0.01801 } + ], + + "phases": [ + { + "name": "gas", + "species": [ + { "name": "SO2", "diffusion coefficient [m2 s-1]": 1.28e-5 }, + { "name": "H2O2", "diffusion coefficient [m2 s-1]": 1.46e-5 }, + { "name": "O3", "diffusion coefficient [m2 s-1]": 1.48e-5 } + ] + }, + { + "name": "AQUEOUS", + "species": [ + "SO2", "H2O2", "O3", "Hp", "OHm", "HSO3m", "SO3mm", "SO4mm", "SO2OOHm", + { "name": "H2O", "density [kg m-3]": 997.0 } + ] + } + ], + + "reactions": [], + + "aerosol representations": [ + { + "type": "UNIFORM_SECTION", + "name": "CLOUD", + "phases": ["AQUEOUS"], + "minimum radius [m]": 1.0e-6, + "maximum radius [m]": 1.0e-5 + } + ], + + "aerosol processes": [ + { + "__comment": "Henry's Law Equilibrium: SO2(g) <-> SO2(aq)", + "type": "HENRY_LAW_EQUILIBRIUM", + "gas phase": "gas", + "gas-phase species": "SO2", + "condensed phase": "AQUEOUS", + "condensed-phase species": "SO2", + "solvent": "H2O", + "Henry's law constant": { + "HLC_ref [mol m-3 Pa-1]": 1.214e-2, + "C [K]": 3120.0, + "T0 [K]": 298.15 + } + }, + { + "__comment": "Henry's Law Equilibrium: H2O2(g) <-> H2O2(aq)", + "type": "HENRY_LAW_EQUILIBRIUM", + "gas phase": "gas", + "gas-phase species": "H2O2", + "condensed phase": "AQUEOUS", + "condensed-phase species": "H2O2", + "solvent": "H2O", + "Henry's law constant": { + "HLC_ref [mol m-3 Pa-1]": 7.306e2, + "C [K]": 6621.0, + "T0 [K]": 298.15 + } + }, + { + "__comment": "Henry's Law Equilibrium: O3(g) <-> O3(aq)", + "type": "HENRY_LAW_EQUILIBRIUM", + "gas phase": "gas", + "gas-phase species": "O3", + "condensed phase": "AQUEOUS", + "condensed-phase species": "O3", + "solvent": "H2O", + "Henry's law constant": { + "HLC_ref [mol m-3 Pa-1]": 1.135e-4, + "C [K]": 2560.0, + "T0 [K]": 298.15 + } + }, + { + "__comment": "R1a: HSO3- + H2O2_aq <-> SO2OOH- + H2O (reversible, Keq=1725)", + "__note": "k_fwd = c_H2O_M * 7.45e7/13 = 3.184e8; Keq=1725 (Lind & Kok 1986 / revised MIAM)", + "type": "DISSOLVED_REVERSIBLE_REACTION", + "condensed phase": "AQUEOUS", + "solvent": "H2O", + "reactants": [ + { "species": "HSO3m", "coefficient": 1 }, + { "species": "H2O2", "coefficient": 1 } + ], + "products": [ + { "species": "SO2OOHm", "coefficient": 1 }, + { "species": "H2O", "coefficient": 1 } + ], + "forward rate constants": { + "CLOUD": { "type": "ARRHENIUS", "A": 3.184e8, "C": 4430.0 } + }, + "equilibrium constant": { + "type": "ARRHENIUS_REFERENCE_TEMPERATURE", "A": 1725.0, "C [K]": 0.0, "T0 [K]": 298.15 + } + }, + { + "__comment": "R1b: SO2OOH- + H+ -> SO4-- (irreversible)", + "__note": "k = c_H2O_M * 2.4e6 = 1.333e8; Ea/R = 4430 K", + "type": "DISSOLVED_REACTION", + "condensed phase": "AQUEOUS", + "solvent": "H2O", + "reactants": [ + { "species name": "SO2OOHm", "coefficient": 1 }, + { "species name": "Hp", "coefficient": 1 } + ], + "products": [ + { "species name": "SO4mm", "coefficient": 1 } + ], + "rate constants": { + "CLOUD": { "type": "ARRHENIUS", "A": 1.333e8, "C": 4430.0} + } + }, + { + "__comment": "Kw: 2 H2O <-> H+ + OH-", + "type": "DISSOLVED_EQUILIBRIUM", + "condensed phase": "AQUEOUS", + "solvent": "H2O", + "reactants": [ + { "species": "H2O", "coefficient": 2 } + ], + "products": [ + { "species": "Hp", "coefficient": 1 }, + { "species": "OHm", "coefficient": 1 } + ], + "algebraic species": "OHm", + "equilibrium constant": { + "type": "ARRHENIUS_REFERENCE_TEMPERATURE", "A": 3.24e-18, "C [K]": 0.0, "T0 [K]": 298.15 + } + }, + { + "__comment": "Ka1: SO2(aq) <-> H+ + HSO3-", + "type": "DISSOLVED_EQUILIBRIUM", + "condensed phase": "AQUEOUS", + "solvent": "H2O", + "reactants": [ + { "species": "SO2", "coefficient": 1 } + ], + "products": [ + { "species": "Hp", "coefficient": 1 }, + { "species": "HSO3m", "coefficient": 1 } + ], + "algebraic species": "HSO3m", + "equilibrium constant": { + "type": "ARRHENIUS_REFERENCE_TEMPERATURE", "A": 3.06e-4, "C [K]": 2090.0, "T0 [K]": 298.15 + } + }, + { + "__comment": "Ka2: HSO3- <-> H+ + SO3--", + "type": "DISSOLVED_EQUILIBRIUM", + "condensed phase": "AQUEOUS", + "algebraic species": "SO3mm", + "solvent": "H2O", + "reactants": [ + { "species": "HSO3m", "coefficient": 1 } + ], + "products": [ + { "species": "Hp", "coefficient": 1 }, + { "species": "SO3mm", "coefficient": 1 } + ], + "equilibrium constant": { + "type": "ARRHENIUS_REFERENCE_TEMPERATURE", "A": 1.08e-9, "C [K]": 1120.0, "T0 [K]": 298.15 + } + }, + { + "__comment": "Mass conservation: total sulfur in reversible pool (includes SO2OOH-)", + "type": "LINEAR_CONSTRAINT", + "algebraic phase": "gas", + "algebraic species": "SO2", + "diagnose from state": true, + "terms": [ + { "phase": "gas", "species": "SO2", "coefficient": 1.0 }, + { "phase": "AQUEOUS", "species": "SO2", "coefficient": 1.0 }, + { "phase": "AQUEOUS", "species": "HSO3m", "coefficient": 1.0 }, + { "phase": "AQUEOUS", "species": "SO3mm", "coefficient": 1.0 }, + { "phase": "AQUEOUS", "species": "SO2OOHm", "coefficient": 1.0 } + ] + }, + { + "__comment": "Mass conservation: total H2O2", + "type": "LINEAR_CONSTRAINT", + "algebraic phase": "gas", + "algebraic species": "H2O2", + "diagnose from state": true, + "terms": [ + { "phase": "gas", "species": "H2O2", "coefficient": 1.0 }, + { "phase": "AQUEOUS", "species": "H2O2", "coefficient": 1.0 } + ] + }, + { + "__comment": "Mass conservation: total O3", + "type": "LINEAR_CONSTRAINT", + "algebraic phase": "gas", + "algebraic species": "O3", + "diagnose from state": true, + "terms": [ + { "phase": "gas", "species": "O3", "coefficient": 1.0 }, + { "phase": "AQUEOUS", "species": "O3", "coefficient": 1.0 } + ] + }, + { + "__comment": "Charge balance: H+ = OH- + HSO3- + 2 SO3-- + 2 SO4-- + SO2OOH-", + "type": "LINEAR_CONSTRAINT", + "algebraic phase": "AQUEOUS", + "algebraic species": "Hp", + "constant [mol m-3]": 0.0, + "terms": [ + { "phase": "AQUEOUS", "species": "Hp", "coefficient": 1.0 }, + { "phase": "AQUEOUS", "species": "OHm", "coefficient": -1.0 }, + { "phase": "AQUEOUS", "species": "HSO3m", "coefficient": -1.0 }, + { "phase": "AQUEOUS", "species": "SO3mm", "coefficient": -2.0 }, + { "phase": "AQUEOUS", "species": "SO4mm", "coefficient": -2.0 }, + { "phase": "AQUEOUS", "species": "SO2OOHm", "coefficient": -1.0 } + ] + } + ] +} From 04d2f08b2e46ad5f7df28890750947074d2cc489 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 24 Jun 2026 12:01:44 -0600 Subject: [PATCH 07/10] Auto-format code using Clang-Format (#280) Co-authored-by: GitHub Actions --- .../mechanism_configuration/aerosol_types.hpp | 23 +++++++++++-------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/include/mechanism_configuration/aerosol_types.hpp b/include/mechanism_configuration/aerosol_types.hpp index e88c096a..fcc0e25a 100644 --- a/include/mechanism_configuration/aerosol_types.hpp +++ b/include/mechanism_configuration/aerosol_types.hpp @@ -52,23 +52,23 @@ namespace mechanism_configuration::types { std::string name; std::vector phases; - double min_radius; ///< [m] - double max_radius; ///< [m] + double min_radius; ///< [m] + double max_radius; ///< [m] }; struct SingleMomentMode { std::string name; std::vector phases; - double geometric_mean_radius; ///< [m] - double geometric_standard_deviation; ///< dimensionless + double geometric_mean_radius; ///< [m] + double geometric_standard_deviation; ///< dimensionless }; struct TwoMomentMode { std::string name; std::vector phases; - double geometric_standard_deviation; ///< dimensionless + double geometric_standard_deviation; ///< dimensionless }; using Representation = std::variant; @@ -110,8 +110,8 @@ namespace mechanism_configuration::types std::string solvent; HenryLawConstant henry_law_constant; HenryLawConstant henry_law_constant; - double diffusion_coefficient; ///< Gas-phase diffusion coefficient [m2 s-1] - double accommodation_coefficient; ///< Mass accommodation coefficient, dimensionless + double diffusion_coefficient; ///< Gas-phase diffusion coefficient [m2 s-1] + double accommodation_coefficient; ///< Mass accommodation coefficient, dimensionless }; using Process = std::variant; @@ -151,8 +151,13 @@ namespace mechanism_configuration::types /// @brief RHS constant C of a LinearConstraint: G = sum(coeff_i * [species_i]) - C = 0 /// Choose exactly one mode (mutually exclusive): - struct FixedConstant { double value = 0.0; }; ///< Fixed value [mol m-3], shared by all instances - struct DiagnoseFromState {}; ///< Computed per representation instance + struct FixedConstant + { + double value = 0.0; + }; ///< Fixed value [mol m-3], shared by all instances + struct DiagnoseFromState + { + }; ///< Computed per representation instance struct LinearConstraint { From 6553bccf047bf9a2175cd64808f785a470a5a205 Mon Sep 17 00:00:00 2001 From: Kyle Shores Date: Mon, 29 Jun 2026 11:44:32 -0500 Subject: [PATCH 08/10] Fix code coverage (#283) * Fix code coverage to exclude third-party and system code Coverage was reporting ~30% because the lcov capture only excluded test/*, so the totals included the FetchContent dependencies built under build/_deps/ (yaml-cpp, googletest, optionally fmt) plus inlined system/libstdc++ headers. The denominator was dominated by untested third-party code, masking the project's real coverage. - Add _deps/* and /usr/* to the lcov EXCLUDE list in CMakeLists.txt (BASE_DIRECTORY only sets path display, it does not restrict capture). - Add codecov.yml with an ignore list as a backstop for Codecov's own path matching. Co-Authored-By: Claude Opus 4.8 (1M context) * Instrument the library for coverage (apply flags before add_subdirectory) The real cause of the low (~30%) coverage: append_coverage_compiler_flags() was called after add_subdirectory(src), so CMAKE_CXX_FLAGS only picked up the coverage flags for the test targets defined later. The src/ library was built without instrumentation, so it produced no .gcno/.gcda data and the report covered only a handful of header lines inlined into the test TUs (51 lines). Move the include + append_coverage_compiler_flags() ahead of add_subdirectory(src) so the library itself is instrumented. The setup_target_for_coverage_lcov() target definition stays in the test block. Co-Authored-By: Claude Opus 4.8 (1M context) * Drop Fortran-only flags from coverage compiler flags COVERAGE_COMPILER_FLAGS included -fcheck=bounds,do,pointer and -ffpe-trap=zero,overflow,invalid, which are gfortran-only. This is a CXX-only project, so cc1plus rejects them ("valid for Fortran but not for C++"). It went unnoticed because the flags were previously only applied to the gtest test targets (no -Werror); now that the library is instrumented (and built with -Werror), the warnings became errors. Co-Authored-By: Claude Opus 4.8 (1M context) --------- Co-authored-by: Claude Opus 4.8 (1M context) --- CMakeLists.txt | 20 +++++++++++++++++--- cmake/CodeCoverage.cmake | 2 +- codecov.yml | 21 +++++++++++++++++++++ 3 files changed, 39 insertions(+), 4 deletions(-) create mode 100644 codecov.yml diff --git a/CMakeLists.txt b/CMakeLists.txt index 66237b60..76a9a8ca 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -38,6 +38,19 @@ set(MECH_CONFIG_LIB_DIR ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}) include(cmake/dependencies.cmake) +################################################################################ +# Code coverage instrumentation +# +# These flags must be applied BEFORE add_subdirectory(src) so the library +# targets are compiled with coverage instrumentation. append_coverage_compiler_flags() +# only affects targets defined after it runs, so calling it later would leave the +# library uninstrumented and the report would cover almost nothing. + +if(PROJECT_IS_TOP_LEVEL AND MECH_CONFIG_ENABLE_TESTS AND MECH_CONFIG_ENABLE_COVERAGE) + include(cmake/CodeCoverage.cmake) + append_coverage_compiler_flags() +endif() + ################################################################################ # project source code @@ -49,12 +62,13 @@ add_subdirectory(src) if(PROJECT_IS_TOP_LEVEL AND MECH_CONFIG_ENABLE_TESTS) # Test code coverage if(MECH_CONFIG_ENABLE_COVERAGE) - include(cmake/CodeCoverage.cmake) - append_coverage_compiler_flags() setup_target_for_coverage_lcov( NAME coverage EXECUTABLE "ctest" -j 4 - EXCLUDE "${PROJECT_SOURCE_DIR}/test/*" + EXCLUDE + "${PROJECT_SOURCE_DIR}/test/*" + "${CMAKE_BINARY_DIR}/_deps/*" + "/usr/*" BASE_DIRECTORY "${PROJECT_SOURCE_DIR}/src" LCOV_ARGS --ignore-errors mismatch) endif() diff --git a/cmake/CodeCoverage.cmake b/cmake/CodeCoverage.cmake index 5bf7e6f3..896c1f67 100644 --- a/cmake/CodeCoverage.cmake +++ b/cmake/CodeCoverage.cmake @@ -158,7 +158,7 @@ elseif(NOT CMAKE_COMPILER_IS_GNUCXX) endif() endif() -set(COVERAGE_COMPILER_FLAGS "-g -O0 -fprofile-arcs -ftest-coverage -fcheck=bounds,do,pointer -ffpe-trap=zero,overflow,invalid" +set(COVERAGE_COMPILER_FLAGS "-g -O0 -fprofile-arcs -ftest-coverage" CACHE INTERNAL "") if(CMAKE_CXX_COMPILER_ID MATCHES "(GNU|Clang)") include(CheckCXXCompilerFlag) diff --git a/codecov.yml b/codecov.yml new file mode 100644 index 00000000..cc31710a --- /dev/null +++ b/codecov.yml @@ -0,0 +1,21 @@ +coverage: + status: + project: + default: + target: auto + threshold: 1% + patch: + default: + target: auto + +# Backstop in addition to the lcov --remove excludes in CMakeLists.txt. +# Keeps third-party and test code out of the coverage totals. +ignore: + - "test/**/*" + - "build/_deps/**/*" + - "**/_deps/**/*" + - "examples/**/*" + +comment: + layout: "reach, diff, flags, files" + behavior: default From fc9d358533c4c9d68392bdee483ca77dbeffd1db Mon Sep 17 00:00:00 2001 From: Kyle Shores Date: Tue, 30 Jun 2026 17:22:23 -0500 Subject: [PATCH 09/10] add parser accepting string config (#285) * add parser accepting string config * adding yaml test * changing default gas phase name to gas * using correct reaction array for each type * correcting tests * make fmt private --- include/mechanism_configuration/errors.hpp | 34 +--- .../mechanism_configuration.hpp | 1 - include/mechanism_configuration/parse.hpp | 2 + src/CMakeLists.txt | 4 +- src/check_schema.cpp | 3 +- src/detail/error_format.hpp | 41 +++++ src/parse.cpp | 26 ++- src/v0/emission_parser.cpp | 9 +- src/v0/first_order_loss_parser.cpp | 8 +- src/v0/parser.cpp | 2 +- src/v0/photolysis_parser.cpp | 13 +- src/v0/user_defined_reaction_parser.cpp | 2 +- src/v1/parser.cpp | 2 +- src/v1/reactions/arrhenius.cpp | 2 +- src/v1/reactions/first_order_loss.cpp | 2 +- src/v1/reactions/photolysis.cpp | 2 +- src/v1/reactions/surface.cpp | 2 +- src/v1/reactions/taylor_series.cpp | 2 +- src/v1/type_schema.cpp | 2 +- src/validate.cpp | 3 +- test/integration/test_parser.cpp | 152 ++++++++++++++++++ test/integration/test_v0_parser.cpp | 10 +- test/unit/v0/test_emission_config.cpp | 8 +- test/unit/v0/test_first_order_loss_config.cpp | 12 +- test/unit/v0/test_photolysis_config.cpp | 12 +- test/unit/v0/test_user_defined_config.cpp | 4 +- 26 files changed, 274 insertions(+), 86 deletions(-) create mode 100644 src/detail/error_format.hpp diff --git a/include/mechanism_configuration/errors.hpp b/include/mechanism_configuration/errors.hpp index a838f9ea..1c0fe948 100644 --- a/include/mechanism_configuration/errors.hpp +++ b/include/mechanism_configuration/errors.hpp @@ -4,8 +4,6 @@ #pragma once -#include - #include #include #include @@ -64,34 +62,4 @@ namespace mechanism_configuration } using Errors = std::vector>; -} // namespace mechanism_configuration - -#ifdef MECH_CONFIG_USE_FMT -template<> -struct fmt::formatter -{ - constexpr auto parse(fmt::format_parse_context& ctx) const - { - return ctx.begin(); - } - template - auto format(const mechanism_configuration::ErrorLocation& loc, FormatContext& ctx) const - { - return fmt::format_to(ctx.out(), "{}:{}", loc.line, loc.column); - } -}; -#else -template<> -struct std::formatter -{ - constexpr auto parse(std::format_parse_context& ctx) const - { - return ctx.begin(); - } - template - auto format(const mechanism_configuration::ErrorLocation& loc, FormatContext& ctx) const - { - return std::format_to(ctx.out(), "{}:{}", loc.line, loc.column); - } -}; -#endif \ No newline at end of file +} // namespace mechanism_configuration \ No newline at end of file diff --git a/include/mechanism_configuration/mechanism_configuration.hpp b/include/mechanism_configuration/mechanism_configuration.hpp index db2e42a5..8ba5d2cb 100644 --- a/include/mechanism_configuration/mechanism_configuration.hpp +++ b/include/mechanism_configuration/mechanism_configuration.hpp @@ -5,7 +5,6 @@ #pragma once #include -#include #include #include #include diff --git a/include/mechanism_configuration/parse.hpp b/include/mechanism_configuration/parse.hpp index ee3d3849..c1b334e3 100644 --- a/include/mechanism_configuration/parse.hpp +++ b/include/mechanism_configuration/parse.hpp @@ -9,6 +9,7 @@ #include #include +#include namespace mechanism_configuration { @@ -17,4 +18,5 @@ namespace mechanism_configuration /// or a directory of version-0 CAMP files. /// @return The parsed Mechanism, or all structural and semantic errors encountered. std::expected Parse(const std::filesystem::path& config_path); + std::expected ParseFromString(const std::string& config); } // namespace mechanism_configuration \ No newline at end of file diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index be92c6e0..38930860 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -13,8 +13,8 @@ add_library(musica::mechanism_configuration ALIAS mechanism_configuration) target_compile_features(mechanism_configuration PUBLIC cxx_std_23) if(MECH_CONFIG_USE_FMT) - target_compile_definitions(mechanism_configuration PUBLIC MECH_CONFIG_USE_FMT) - target_link_libraries(mechanism_configuration PUBLIC fmt::fmt) + target_compile_definitions(mechanism_configuration PRIVATE MECH_CONFIG_USE_FMT) + target_link_libraries(mechanism_configuration PRIVATE fmt::fmt) endif() set_target_properties(mechanism_configuration PROPERTIES diff --git a/src/check_schema.cpp b/src/check_schema.cpp index fcb50d70..9b7d82e2 100644 --- a/src/check_schema.cpp +++ b/src/check_schema.cpp @@ -3,8 +3,7 @@ // SPDX-License-Identifier: Apache-2.0 #include "detail/check_schema.hpp" - -#include +#include "detail/error_format.hpp" #include diff --git a/src/detail/error_format.hpp b/src/detail/error_format.hpp new file mode 100644 index 00000000..8339c0ea --- /dev/null +++ b/src/detail/error_format.hpp @@ -0,0 +1,41 @@ +// Copyright (C) 2023–2026 University Corporation for Atmospheric Research +// University of Illinois at Urbana-Champaign +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include +#include + +// Formatter for ErrorLocation. Kept internal (not in the public errors.hpp) so that +// fmt / is not pulled into the library's public interface. Only the .cpp +// files that build error-message strings need this, so it lives under src/detail. +#ifdef MECH_CONFIG_USE_FMT +template<> +struct fmt::formatter +{ + constexpr auto parse(fmt::format_parse_context& ctx) const + { + return ctx.begin(); + } + template + auto format(const mechanism_configuration::ErrorLocation& loc, FormatContext& ctx) const + { + return fmt::format_to(ctx.out(), "{}:{}", loc.line, loc.column); + } +}; +#else +template<> +struct std::formatter +{ + constexpr auto parse(std::format_parse_context& ctx) const + { + return ctx.begin(); + } + template + auto format(const mechanism_configuration::ErrorLocation& loc, FormatContext& ctx) const + { + return std::format_to(ctx.out(), "{}:{}", loc.line, loc.column); + } +}; +#endif diff --git a/src/parse.cpp b/src/parse.cpp index 56b0ab61..28cb709b 100644 --- a/src/parse.cpp +++ b/src/parse.cpp @@ -2,11 +2,11 @@ // University of Illinois at Urbana-Champaign // SPDX-License-Identifier: Apache-2.0 +#include "detail/error_format.hpp" #include "detail/v0/parser.hpp" #include "detail/v1/parser.hpp" #include -#include #include #include @@ -90,4 +90,28 @@ namespace mechanism_configuration } } + std::expected ParseFromString(const std::string& config) + { + // only v1 supports parsing from a string, so we must first detect the version from the string + YAML::Node object; + try + { + object = YAML::Load(config); + if (!object["version"]) + { + return std::unexpected(Errors{ { ErrorCode::InvalidVersion, "error: Unsupported version number '0.0.0'." } }); + } + const Version version(object["version"].as()); + if (version.major != 1) + { + return std::unexpected(Errors{ { ErrorCode::InvalidVersion, mc_fmt::format("error: Unsupported version number '{}'.", version.to_string()) } }); + } + return v1::Parser{}.Parse(config); + } + catch (const YAML::Exception& e) + { + return std::unexpected(Errors{ { ErrorCode::UnexpectedError, mc_fmt::format("Failed to parse configuration string: {}", e.what()) } }); + } + } + } // namespace mechanism_configuration diff --git a/src/v0/emission_parser.cpp b/src/v0/emission_parser.cpp index e37b94fc..7491bc0b 100644 --- a/src/v0/emission_parser.cpp +++ b/src/v0/emission_parser.cpp @@ -23,16 +23,15 @@ namespace mechanism_configuration::v0 { std::string species = object[keys::SPECIES].as(); YAML::Node products_object{}; - std::vector reactants; std::vector products; products.push_back({ .name = species, .coefficient = 1.0 }); double scaling_factor = object[keys::SCALING_FACTOR] ? object[keys::SCALING_FACTOR].as() : 1.0; - std::string name = "EMIS." + object[keys::MUSICA_NAME].as(); - types::UserDefined user_defined = { - .scaling_factor = scaling_factor, .reactants = reactants, .products = products, .name = name + std::string name = object[keys::MUSICA_NAME].as(); + types::Emission user_defined = { + .scaling_factor = scaling_factor, .products = products, .name = name }; - mechanism.reactions.user_defined.push_back(user_defined); + mechanism.reactions.emission.push_back(user_defined); } return errors; diff --git a/src/v0/first_order_loss_parser.cpp b/src/v0/first_order_loss_parser.cpp index 438e7651..66781f39 100644 --- a/src/v0/first_order_loss_parser.cpp +++ b/src/v0/first_order_loss_parser.cpp @@ -29,11 +29,11 @@ namespace mechanism_configuration::v0 reactants.push_back({ .name = species, .coefficient = 1.0 }); double scaling_factor = object[keys::SCALING_FACTOR] ? object[keys::SCALING_FACTOR].as() : 1.0; - std::string name = "LOSS." + object[keys::MUSICA_NAME].as(); - types::UserDefined user_defined = { - .scaling_factor = scaling_factor, .reactants = reactants, .products = products, .name = name + std::string name = object[keys::MUSICA_NAME].as(); + types::FirstOrderLoss user_defined = { + .scaling_factor = scaling_factor, .reactants = reactants[0], .products = products, .name = name }; - mechanism.reactions.user_defined.push_back(user_defined); + mechanism.reactions.first_order_loss.push_back(user_defined); } return errors; diff --git a/src/v0/parser.cpp b/src/v0/parser.cpp index a221f6ca..22e677b9 100644 --- a/src/v0/parser.cpp +++ b/src/v0/parser.cpp @@ -171,7 +171,7 @@ namespace mechanism_configuration::v0 // all species in version 0 are in the gas phase types::Phase gas_phase; - gas_phase.name = "GAS"; + gas_phase.name = "gas"; for (auto& species : mechanism.species) { types::PhaseSpecies phase_species; diff --git a/src/v0/photolysis_parser.cpp b/src/v0/photolysis_parser.cpp index a71c75ed..c24e790f 100644 --- a/src/v0/photolysis_parser.cpp +++ b/src/v0/photolysis_parser.cpp @@ -32,11 +32,14 @@ namespace mechanism_configuration::v0 double scaling_factor = object[keys::SCALING_FACTOR] ? object[keys::SCALING_FACTOR].as() : 1.0; - std::string name = "PHOTO." + object[keys::MUSICA_NAME].as(); - types::UserDefined user_defined = { - .scaling_factor = scaling_factor, .reactants = reactants, .products = products, .name = name - }; - mechanism.reactions.user_defined.push_back(user_defined); + if (!reactants.empty()) + { + std::string name = object[keys::MUSICA_NAME].as(); + types::Photolysis user_defined = { + .scaling_factor = scaling_factor, .reactants = reactants[0], .products = products, .name = name + }; + mechanism.reactions.photolysis.push_back(user_defined); + } } return errors; diff --git a/src/v0/user_defined_reaction_parser.cpp b/src/v0/user_defined_reaction_parser.cpp index 858fce11..c26a4f04 100644 --- a/src/v0/user_defined_reaction_parser.cpp +++ b/src/v0/user_defined_reaction_parser.cpp @@ -32,7 +32,7 @@ namespace mechanism_configuration::v0 double scaling_factor = object[keys::SCALING_FACTOR] ? object[keys::SCALING_FACTOR].as() : 1.0; - std::string name = "USER." + object[keys::MUSICA_NAME].as(); + std::string name = object[keys::MUSICA_NAME].as(); types::UserDefined user_defined = { .scaling_factor = scaling_factor, .reactants = reactants, .products = products, .name = name diff --git a/src/v1/parser.cpp b/src/v1/parser.cpp index d5b01c1a..9f62f8e3 100644 --- a/src/v1/parser.cpp +++ b/src/v1/parser.cpp @@ -5,13 +5,13 @@ #include "detail/v1/parser.hpp" #include "detail/check_schema.hpp" +#include "detail/error_format.hpp" #include "detail/v1/keys.hpp" #include "detail/v1/type_parsers.hpp" #include "detail/v1/type_schema.hpp" #include "detail/v1/utils.hpp" #include -#include #include #include diff --git a/src/v1/reactions/arrhenius.cpp b/src/v1/reactions/arrhenius.cpp index e786de7c..e35ec51a 100644 --- a/src/v1/reactions/arrhenius.cpp +++ b/src/v1/reactions/arrhenius.cpp @@ -3,11 +3,11 @@ // SPDX-License-Identifier: Apache-2.0 #include -#include #include #include #include +#include #include #include #include diff --git a/src/v1/reactions/first_order_loss.cpp b/src/v1/reactions/first_order_loss.cpp index 5fbed8a3..8a1d206f 100644 --- a/src/v1/reactions/first_order_loss.cpp +++ b/src/v1/reactions/first_order_loss.cpp @@ -3,10 +3,10 @@ // SPDX-License-Identifier: Apache-2.0 #include -#include #include #include +#include #include #include #include diff --git a/src/v1/reactions/photolysis.cpp b/src/v1/reactions/photolysis.cpp index 8f66bd93..7a020b8e 100644 --- a/src/v1/reactions/photolysis.cpp +++ b/src/v1/reactions/photolysis.cpp @@ -3,10 +3,10 @@ // SPDX-License-Identifier: Apache-2.0 #include -#include #include #include +#include #include #include #include diff --git a/src/v1/reactions/surface.cpp b/src/v1/reactions/surface.cpp index c195dec5..7927f5dd 100644 --- a/src/v1/reactions/surface.cpp +++ b/src/v1/reactions/surface.cpp @@ -3,10 +3,10 @@ // SPDX-License-Identifier: Apache-2.0 #include -#include #include #include +#include #include #include #include diff --git a/src/v1/reactions/taylor_series.cpp b/src/v1/reactions/taylor_series.cpp index d40c6c4e..7a8f821d 100644 --- a/src/v1/reactions/taylor_series.cpp +++ b/src/v1/reactions/taylor_series.cpp @@ -3,11 +3,11 @@ // SPDX-License-Identifier: Apache-2.0 #include -#include #include #include #include +#include #include #include #include diff --git a/src/v1/type_schema.cpp b/src/v1/type_schema.cpp index a627c389..354da33d 100644 --- a/src/v1/type_schema.cpp +++ b/src/v1/type_schema.cpp @@ -5,12 +5,12 @@ #include "detail/v1/type_schema.hpp" #include "detail/check_schema.hpp" +#include "detail/error_format.hpp" #include "detail/v1/keys.hpp" #include "detail/v1/reaction_parsers.hpp" #include "detail/v1/utils.hpp" #include -#include #include #include diff --git a/src/validate.cpp b/src/validate.cpp index 84772969..0a8f9b05 100644 --- a/src/validate.cpp +++ b/src/validate.cpp @@ -2,9 +2,10 @@ // University of Illinois at Urbana-Champaign // SPDX-License-Identifier: Apache-2.0 -#include #include +#include "detail/error_format.hpp" + #include #include #include diff --git a/test/integration/test_parser.cpp b/test/integration/test_parser.cpp index a6cb717e..2959bd2b 100644 --- a/test/integration/test_parser.cpp +++ b/test/integration/test_parser.cpp @@ -71,3 +71,155 @@ TEST(Parse, ParsesV0DirectoryConfiguration) if (parsed) EXPECT_EQ(parsed->version.major, 0); } + +TEST(Parse, ParsesV1JsonString) +{ + std::string config = R"( + { + "version": "1.0.0", + "species": [ + { + "name": "H2O", + } + ], + "phases": [ + { + "name": "gas", + "species": [ + { + "name": "H2O" + } + ] + } + ], + "reactions": [ + { + type: "ARRHENIUS", + "reactants": [ { "species name": "H2O" } ], + "products": [ { "species name": "H2O" } ], + "gas phase": "gas", + } + ] + } + )"; + auto parsed = ParseFromString(config); + EXPECT_TRUE(parsed); + if (parsed){ + EXPECT_EQ(parsed->version.major, 1); + EXPECT_EQ(parsed->species.size(), 1); + EXPECT_EQ(parsed->phases.size(), 1); + EXPECT_EQ(parsed->reactions.arrhenius.size(), 1); + } + else { + for (const auto& [code, message] : parsed.error()) + std::cout << message << " " << ErrorCodeToString(code) << std::endl; + } +} + +TEST(Parse, ParsesV11JsonString) +{ + std::string config = R"( + { + "version": "1.1.0", + "species": [ + { + "name": "H2O", + } + ], + "phases": [ + { + "name": "gas", + "species": [ + { + "name": "H2O" + } + ] + } + ], + "reactions": [ + { + type: "ARRHENIUS", + "reactants": [ { "species name": "H2O" } ], + "products": [ { "species name": "H2O" } ], + "gas phase": "gas", + } + ] + } + )"; + auto parsed = ParseFromString(config); + EXPECT_TRUE(parsed); + if (parsed){ + EXPECT_EQ(parsed->version.major, 1); + EXPECT_EQ(parsed->species.size(), 1); + EXPECT_EQ(parsed->phases.size(), 1); + EXPECT_EQ(parsed->reactions.arrhenius.size(), 1); + } + else { + for (const auto& [code, message] : parsed.error()) + std::cout << message << " " << ErrorCodeToString(code) << std::endl; + } +} + +TEST(Parse, ParsesV1YamlString) +{ + std::string config = R"( +version: 1.0.0 +species: + - name: H2O +phases: + - name: gas + species: + - name: H2O +reactions: + - type: ARRHENIUS + reactants: + - species name: H2O + products: + - species name: H2O + gas phase: gas + )"; + auto parsed = ParseFromString(config); + EXPECT_TRUE(parsed); + if (parsed){ + EXPECT_EQ(parsed->version.major, 1); + EXPECT_EQ(parsed->species.size(), 1); + EXPECT_EQ(parsed->phases.size(), 1); + EXPECT_EQ(parsed->reactions.arrhenius.size(), 1); + } + else { + for (const auto& [code, message] : parsed.error()) + std::cout << message << " " << ErrorCodeToString(code) << std::endl; + } +} + +TEST(Parse, ParsesV11YamlString) +{ + std::string config = R"( +version: 1.1.0 +species: + - name: H2O +phases: + - name: gas + species: + - name: H2O +reactions: + - type: ARRHENIUS + reactants: + - species name: H2O + products: + - species name: H2O + gas phase: gas + )"; + auto parsed = ParseFromString(config); + EXPECT_TRUE(parsed); + if (parsed){ + EXPECT_EQ(parsed->version.major, 1); + EXPECT_EQ(parsed->species.size(), 1); + EXPECT_EQ(parsed->phases.size(), 1); + EXPECT_EQ(parsed->reactions.arrhenius.size(), 1); + } + else { + for (const auto& [code, message] : parsed.error()) + std::cout << message << " " << ErrorCodeToString(code) << std::endl; + } +} \ No newline at end of file diff --git a/test/integration/test_v0_parser.cpp b/test/integration/test_v0_parser.cpp index 9ff1b36f..2a0279a7 100644 --- a/test/integration/test_v0_parser.cpp +++ b/test/integration/test_v0_parser.cpp @@ -20,7 +20,10 @@ TEST(V0Parser, ParsesFullV0Configuration) ASSERT_TRUE(parsed); Mechanism mechanism = *parsed; - EXPECT_EQ(mechanism.reactions.user_defined.size(), 4); + EXPECT_EQ(mechanism.reactions.user_defined.size(), 1); + EXPECT_EQ(mechanism.reactions.first_order_loss.size(), 1); + EXPECT_EQ(mechanism.reactions.emission.size(), 1); + EXPECT_EQ(mechanism.reactions.photolysis.size(), 1); EXPECT_EQ(mechanism.reactions.arrhenius.size(), 1); EXPECT_EQ(mechanism.reactions.troe.size(), 1); EXPECT_EQ(mechanism.reactions.ternary_chemical_activation.size(), 1); @@ -40,7 +43,10 @@ TEST(V0Parser, ConfigPathIsDirectory) Mechanism mechanism = *parsed; EXPECT_EQ(mechanism.version.major, 0); - EXPECT_EQ(mechanism.reactions.user_defined.size(), 4); + EXPECT_EQ(mechanism.reactions.user_defined.size(), 1); + EXPECT_EQ(mechanism.reactions.first_order_loss.size(), 1); + EXPECT_EQ(mechanism.reactions.emission.size(), 1); + EXPECT_EQ(mechanism.reactions.photolysis.size(), 1); EXPECT_EQ(mechanism.reactions.arrhenius.size(), 1); EXPECT_EQ(mechanism.reactions.troe.size(), 1); EXPECT_EQ(mechanism.reactions.ternary_chemical_activation.size(), 1); diff --git a/test/unit/v0/test_emission_config.cpp b/test/unit/v0/test_emission_config.cpp index c753ed68..2cf2ea10 100644 --- a/test/unit/v0/test_emission_config.cpp +++ b/test/unit/v0/test_emission_config.cpp @@ -49,26 +49,24 @@ TEST(EmissionConfig, ParseConfig) EXPECT_TRUE(parsed); Mechanism mechanism = *parsed; - auto& process_vector = mechanism.reactions.user_defined; + auto& process_vector = mechanism.reactions.emission; EXPECT_EQ(process_vector.size(), 2); // first reaction { - EXPECT_EQ(process_vector[0].reactants.size(), 0); EXPECT_EQ(process_vector[0].products.size(), 1); EXPECT_EQ(process_vector[0].products[0].name, "foo"); EXPECT_EQ(process_vector[0].products[0].coefficient, 1.0); - EXPECT_EQ(process_vector[0].name, "EMIS.foo"); + EXPECT_EQ(process_vector[0].name, "foo"); EXPECT_EQ(process_vector[0].scaling_factor, 1.0); } // second reaction { - EXPECT_EQ(process_vector[1].reactants.size(), 0); EXPECT_EQ(process_vector[1].products.size(), 1); EXPECT_EQ(process_vector[1].products[0].name, "bar"); EXPECT_EQ(process_vector[1].products[0].coefficient, 1.0); - EXPECT_EQ(process_vector[1].name, "EMIS.bar"); + EXPECT_EQ(process_vector[1].name, "bar"); EXPECT_EQ(process_vector[1].scaling_factor, 2.5); } } diff --git a/test/unit/v0/test_first_order_loss_config.cpp b/test/unit/v0/test_first_order_loss_config.cpp index 60fab0a5..5e3a60d9 100644 --- a/test/unit/v0/test_first_order_loss_config.cpp +++ b/test/unit/v0/test_first_order_loss_config.cpp @@ -49,24 +49,22 @@ TEST(FirstOrderLossConfig, ParseConfig) EXPECT_TRUE(parsed); Mechanism mechanism = *parsed; - auto& process_vector = mechanism.reactions.user_defined; + auto& process_vector = mechanism.reactions.first_order_loss; EXPECT_EQ(process_vector.size(), 2); // first reaction { - EXPECT_EQ(process_vector[0].reactants.size(), 1); EXPECT_EQ(process_vector[0].products.size(), 0); - EXPECT_EQ(process_vector[0].reactants[0].name, "foo"); - EXPECT_EQ(process_vector[0].name, "LOSS.foo"); + EXPECT_EQ(process_vector[0].reactants.name, "foo"); + EXPECT_EQ(process_vector[0].name, "foo"); EXPECT_EQ(process_vector[0].scaling_factor, 1.0); } // second reaction { - EXPECT_EQ(process_vector[1].reactants.size(), 1); EXPECT_EQ(process_vector[1].products.size(), 0); - EXPECT_EQ(process_vector[1].reactants[0].name, "bar"); - EXPECT_EQ(process_vector[1].name, "LOSS.bar"); + EXPECT_EQ(process_vector[1].reactants.name, "bar"); + EXPECT_EQ(process_vector[1].name, "bar"); EXPECT_EQ(process_vector[1].scaling_factor, 2.5); } } diff --git a/test/unit/v0/test_photolysis_config.cpp b/test/unit/v0/test_photolysis_config.cpp index afb82a3f..52585318 100644 --- a/test/unit/v0/test_photolysis_config.cpp +++ b/test/unit/v0/test_photolysis_config.cpp @@ -59,32 +59,30 @@ TEST(PhotolysisConfig, ParseConfig) EXPECT_TRUE(parsed); Mechanism mechanism = *parsed; - auto& process_vector = mechanism.reactions.user_defined; + auto& process_vector = mechanism.reactions.photolysis; EXPECT_EQ(process_vector.size(), 2); // first reaction { - EXPECT_EQ(process_vector[0].reactants.size(), 1); - EXPECT_EQ(process_vector[0].reactants[0].name, "foo"); + EXPECT_EQ(process_vector[0].reactants.name, "foo"); EXPECT_EQ(process_vector[0].products.size(), 2); EXPECT_EQ(process_vector[0].products[0].name, "bar"); EXPECT_EQ(process_vector[0].products[0].coefficient, 1.0); EXPECT_EQ(process_vector[0].products[1].name, "baz"); EXPECT_EQ(process_vector[0].products[1].coefficient, 3.2); - EXPECT_EQ(process_vector[0].name, "PHOTO.jfoo"); + EXPECT_EQ(process_vector[0].name, "jfoo"); EXPECT_EQ(process_vector[0].scaling_factor, 1.0); } // second reaction { - EXPECT_EQ(process_vector[1].reactants.size(), 1); - EXPECT_EQ(process_vector[1].reactants[0].name, "bar"); + EXPECT_EQ(process_vector[1].reactants.name, "bar"); EXPECT_EQ(process_vector[1].products.size(), 2); EXPECT_EQ(process_vector[1].products[0].name, "bar"); EXPECT_EQ(process_vector[1].products[0].coefficient, 0.5); EXPECT_EQ(process_vector[1].products[1].name, "foo"); EXPECT_EQ(process_vector[1].products[1].coefficient, 1.0); - EXPECT_EQ(process_vector[1].name, "PHOTO.jbar"); + EXPECT_EQ(process_vector[1].name, "jbar"); EXPECT_EQ(process_vector[1].scaling_factor, 2.5); } } diff --git a/test/unit/v0/test_user_defined_config.cpp b/test/unit/v0/test_user_defined_config.cpp index 7cf1d13c..3bebd65a 100644 --- a/test/unit/v0/test_user_defined_config.cpp +++ b/test/unit/v0/test_user_defined_config.cpp @@ -76,7 +76,7 @@ TEST(UserDefinedConfig, ParseConfig) EXPECT_EQ(process_vector[0].products[0].coefficient, 1.4); EXPECT_EQ(process_vector[0].products[1].name, "foo"); EXPECT_EQ(process_vector[0].products[1].coefficient, 1.0); - EXPECT_EQ(process_vector[0].name, "USER.foo"); + EXPECT_EQ(process_vector[0].name, "foo"); EXPECT_EQ(process_vector[0].scaling_factor, 1.0); } @@ -88,7 +88,7 @@ TEST(UserDefinedConfig, ParseConfig) EXPECT_EQ(process_vector[1].products.size(), 1); EXPECT_EQ(process_vector[1].products[0].name, "bar"); EXPECT_EQ(process_vector[1].products[0].coefficient, 1.0); - EXPECT_EQ(process_vector[1].name, "USER.bar"); + EXPECT_EQ(process_vector[1].name, "bar"); EXPECT_EQ(process_vector[1].scaling_factor, 2.5); } } From 6633a505c428562c3d511efec31887446c545b0a Mon Sep 17 00:00:00 2001 From: Kyle Shores Date: Tue, 30 Jun 2026 17:48:01 -0500 Subject: [PATCH 10/10] updating version (#287) --- CITATION.cff | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CITATION.cff b/CITATION.cff index c7dde219..f756f514 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -1,7 +1,7 @@ cff-version: 1.2.0 message: If you use this software, please cite it as below. title: Chemical Mechanism Configurations -version: v1.1.2 +version: v2.0.0 doi: "10.5281/zenodo.15116380" authors: - family-names: Dawson