diff --git a/.github/workflows/mac.yml b/.github/workflows/mac.yml index 9e9bc0e..d3160bb 100644 --- a/.github/workflows/mac.yml +++ b/.github/workflows/mac.yml @@ -7,38 +7,13 @@ concurrency: cancel-in-progress: true jobs: - xcode_macos_12: - if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name - runs-on: macos-12 - strategy: - matrix: - # all available versions of xcode: https://github.com/actions/runner-images/blob/main/images/macos/macos-12-Readme.md#xcode - xcode: ['13.1', '14.1'] - build_type: [Debug, Release] - env: - DEVELOPER_DIR: /Applications/Xcode_${{ matrix.xcode }}.app/Contents/Developer - - steps: - - uses: actions/checkout@v3 - - - name: Run Cmake - run: cmake -S . -B build -D CMAKE_BUILD_TYPE=${{ matrix.build_type }} - - - name: Build - run: cmake --build build --parallel 10 - - - name: Run tests - run: | - cd build - ctest -C ${{ matrix.build_type }} --rerun-failed --output-on-failure . --verbose -j 10 - xcode_macos_13: if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name runs-on: macos-13 strategy: matrix: # all available versions of xcode: https://github.com/actions/runner-images/blob/main/images/macos/macos-13-Readme.md#xcode - xcode: ['14.1', '15.0'] + xcode: ['15.0'] build_type: [Debug, Release] env: DEVELOPER_DIR: /Applications/Xcode_${{ matrix.xcode }}.app/Contents/Developer @@ -63,7 +38,6 @@ jobs: strategy: matrix: compiler: - - { cpp: g++-11, c: gcc-11} - { cpp: g++-12, c: gcc-12} - { cpp: clang++, c: clang} build_type: [Debug, Release] diff --git a/examples/full_configuration.json b/examples/full_configuration.json index 47358e0..c411c92 100644 --- a/examples/full_configuration.json +++ b/examples/full_configuration.json @@ -128,10 +128,6 @@ "A": 1.14e-2, "C": 2300.0, "k_reverse": 0.32, - "ion pair": { - "first": { "species name": "A"}, - "second": { "species name": "B"} - }, "reactants": [ { "species name": "A", @@ -212,10 +208,6 @@ { "species name": "H2O2_aq", "coefficient": 1 - }, - { - "species name": "H2O_aq", - "coefficient": 1 } ], "products": [ @@ -367,7 +359,6 @@ }, { "type": "WET_DEPOSITION", - "gas phase": "gas", "aerosol phase": "cloud", "name": "rxn cloud", "scaling factor": 12.3 diff --git a/include/open_atmos/mechanism_configuration/validation.hpp b/include/open_atmos/mechanism_configuration/validation.hpp index ccb8ab6..e547545 100644 --- a/include/open_atmos/mechanism_configuration/validation.hpp +++ b/include/open_atmos/mechanism_configuration/validation.hpp @@ -101,6 +101,13 @@ namespace open_atmos const std::string Photolysis_key = "PHOTOLYSIS"; const std::string scaling_factor = "scaling factor"; + // Condensed Phae Photolysis + const std::string CondensedPhasePhotolysis_key = "CONDENSED_PHASE_PHOTOLYSIS"; + // also + // scaling factor + // aerosol phase + // aerosol-phase water + // Emissions const std::string Emission_key = "EMISSION"; // also scaling factor @@ -117,10 +124,21 @@ namespace open_atmos // A // C const std::string k_reverse = "k_reverse"; - const std::string ion_pair = "ion pair"; - // ion pair - const std::string first = "first"; - const std::string second = "second"; + + // Wet Deposition + const std::string WetDeposition_key = "WET_DEPOSITION"; + // also + // scaling factor + // aerosol phase + + // Henry's Law Phase Transfer + const std::string HenrysLaw_key = "HL_PHASE_TRANSFER"; + const std::string gas_phase_species = "gas-phase species"; + const std::string aerosol_phase_species = "aerosol-phase species"; + // also + // gas phase + // aerosol phase + // aerosol-phase water } keys; @@ -198,6 +216,12 @@ namespace open_atmos const std::vector optional_keys{ keys.name, keys.scaling_factor }; } photolysis; + struct CondensedPhasePhotolysis + { + const std::vector required_keys{ keys.reactants, keys.products, keys.type, keys.aerosol_phase, keys.aerosol_phase_water }; + const std::vector optional_keys{ keys.name, keys.scaling_factor }; + } condensed_phase_photolysis; + struct Emission { const std::vector required_keys{ keys.products, keys.type, keys.gas_phase }; @@ -210,16 +234,22 @@ namespace open_atmos const std::vector optional_keys{ keys.name, keys.scaling_factor }; } first_order_loss; + struct WetDeposition + { + const std::vector required_keys{ keys.aerosol_phase, keys.type }; + const std::vector optional_keys{ keys.name, keys.scaling_factor }; + } wet_deposition; + + struct HenrysLaw + { + const std::vector required_keys{ keys.type, keys.gas_phase, keys.gas_phase_species, keys.aerosol_phase, keys.aerosol_phase_species, keys.aerosol_phase_water }; + const std::vector optional_keys{ keys.name }; + } henrys_law; + struct AqueousEquilibrium { const std::vector required_keys{ keys.type, keys.reactants, keys.products, keys.aerosol_phase, keys.aerosol_phase_water, keys.k_reverse }; - const std::vector optional_keys{ keys.name, keys.A, keys.C, keys.ion_pair }; + const std::vector optional_keys{ keys.name, keys.A, keys.C }; } aqueous_equilibrium; - - struct IonPair - { - const std::vector required_keys{ keys.first, keys.second }; - const std::vector optional_keys{}; - } ion_pair; } // namespace validation } // namespace open_atmos \ No newline at end of file diff --git a/include/open_atmos/types.hpp b/include/open_atmos/types.hpp index 1496490..9a7fac5 100644 --- a/include/open_atmos/types.hpp +++ b/include/open_atmos/types.hpp @@ -186,7 +186,7 @@ namespace open_atmos struct Photolysis { /// @brief Scaling factor to apply to user-provided rate constants - double scaling_factor_{ 1.0 }; + double scaling_factor{ 1.0 }; /// @brief A list of reactants std::vector reactants; /// @brief A list of products @@ -199,10 +199,28 @@ namespace open_atmos std::unordered_map unknown_properties; }; - struct Emission + struct CondensedPhasePhotolysis { /// @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 aerosol phase this reaction takes place in + std::string aerosol_phase; + /// @brief An identifier indicating the species label of aqueous phase water + std::string aerosol_phase_water; + /// @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 @@ -216,7 +234,7 @@ namespace open_atmos struct FirstOrderLoss { /// @brief Scaling factor to apply to user-provided rate constants - double scaling_factor_{ 1.0 }; + double scaling_factor{ 1.0 }; /// @brief A list of reactants std::vector reactants; /// @brief An identifier, optional, uniqueness not enforced @@ -226,7 +244,6 @@ namespace open_atmos /// @brief Unknown properties, prefixed with two underscores (__) std::unordered_map unknown_properties; }; - struct AqueousEquilibrium { /// @brief An identifier, optional, uniqueness not enforced @@ -241,8 +258,6 @@ namespace open_atmos std::vector reactants; /// @brief A list of products std::vector products; - /// @brief Optional ion pairs - std::optional> ion_pair; /// @brief Pre-exponential factor (s-1) double A{ 1 }; /// @brief A constant @@ -253,18 +268,51 @@ namespace open_atmos 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 indicating which aerosol phase this reaction takes place in + std::string aerosol_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 An identifier indicating which gas phase this reaction takes place in + std::string gas_phase; + /// @brief An identifier indicating which gas phase species this reaction involves + std::string gas_phase_species; + /// @brief An identifier indicating which aerosol phase this reaction takes place in + std::string aerosol_phase; + /// @brief An identifier indicating the species label of aqueous phase water + std::string aerosol_phase_water; + /// @brief An identifier indicating which aerosol phase species this reaction involves + std::string aerosol_phase_species; + /// @brief Unknown properties, prefixed with two underscores (__) + std::unordered_map unknown_properties; + }; + struct Reactions { std::vector arrhenius; - std::vector condensed_phase_arrhenius; - std::vector troe; std::vector branched; - std::vector tunneling; - std::vector surface; - std::vector photolysis; + std::vector condensed_phase_arrhenius; + std::vector condensed_phase_photolysis; std::vector emission; std::vector first_order_loss; std::vector aqueous_equilibrium; + std::vector wet_deposition; + std::vector henrys_law; + std::vector photolysis; + std::vector surface; + std::vector troe; + std::vector tunneling; }; struct Mechanism diff --git a/src/parser.cpp b/src/parser.cpp index c6e753b..b1d1308 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -1025,7 +1025,7 @@ namespace open_atmos if (object.contains(validation::keys.scaling_factor)) { - photolysis.scaling_factor_ = object[validation::keys.scaling_factor].get(); + photolysis.scaling_factor = object[validation::keys.scaling_factor].get(); } if (object.contains(validation::keys.name)) @@ -1078,6 +1078,114 @@ namespace open_atmos return { status, photolysis }; } + /// @brief Parses a photolysis reaction + /// @param object A json object that should have information containing arrhenius parameters + /// @param existing_species A list of species configured in a mechanism + /// @param existing_phases A list of phases configured in a mechanism + /// @return A pair indicating parsing success and a struct of Photolysis parameters + std::pair + ParseCondensedPhasePhotolysis(const json& object, const std::vector existing_species, const std::vector existing_phases) + { + ConfigParseStatus status = ConfigParseStatus::Success; + types::CondensedPhasePhotolysis condensed_phase_photolysis; + + status = ValidateSchema(object, validation::condensed_phase_photolysis.required_keys, validation::photolysis.optional_keys); + if (status == ConfigParseStatus::Success) + { + std::vector products{}; + for (const auto& reactant : object[validation::keys.products]) + { + auto product_parse = ParseReactionComponent(reactant); + status = product_parse.first; + if (status != ConfigParseStatus::Success) + { + break; + } + products.push_back(product_parse.second); + } + + std::vector reactants{}; + for (const auto& reactant : object[validation::keys.reactants]) + { + auto reactant_parse = ParseReactionComponent(reactant); + status = reactant_parse.first; + if (status != ConfigParseStatus::Success) + { + break; + } + reactants.push_back(reactant_parse.second); + } + + if (object.contains(validation::keys.scaling_factor)) + { + condensed_phase_photolysis.scaling_factor_ = object[validation::keys.scaling_factor].get(); + } + + if (object.contains(validation::keys.name)) + { + condensed_phase_photolysis.name = object[validation::keys.name].get(); + } + + auto comments = GetComments(object, validation::condensed_phase_photolysis.required_keys, validation::photolysis.optional_keys); + + std::unordered_map unknown_properties; + for (const auto& key : comments) + { + std::string val = object[key].dump(); + unknown_properties[key] = val; + } + + std::string aerosol_phase = object[validation::keys.aerosol_phase].get(); + std::string aerosol_phase_water = object[validation::keys.aerosol_phase_water].get(); + + std::vector requested_species; + for (const auto& spec : products) + { + requested_species.push_back(spec.species_name); + } + for (const auto& spec : reactants) + { + requested_species.push_back(spec.species_name); + } + requested_species.push_back(aerosol_phase_water); + + if (status == ConfigParseStatus::Success && RequiresUnknownSpecies(requested_species, existing_species)) + { + status = ConfigParseStatus::ReactionRequiresUnknownSpecies; + } + + if (status == ConfigParseStatus::Success && reactants.size() > 1) + { + status = ConfigParseStatus::TooManyReactionComponents; + } + + auto phase_it = std::find_if( + existing_phases.begin(), existing_phases.end(), [&aerosol_phase](const types::Phase& phase) { return phase.name == aerosol_phase; }); + + if (phase_it != existing_phases.end()) + { + // check if all of the species for this reaction are actually in the aerosol phase + std::vector aerosol_phase_species = { (*phase_it).species.begin(), (*phase_it).species.end() }; + if (status == ConfigParseStatus::Success && RequiresUnknownSpecies(requested_species, aerosol_phase_species)) + { + status = ConfigParseStatus::RequestedAerosolSpeciesNotIncludedInAerosolPhase; + } + } + else + { + status = ConfigParseStatus::UnknownPhase; + } + + condensed_phase_photolysis.aerosol_phase = aerosol_phase; + condensed_phase_photolysis.aerosol_phase_water = aerosol_phase_water; + condensed_phase_photolysis.products = products; + condensed_phase_photolysis.reactants = reactants; + condensed_phase_photolysis.unknown_properties = unknown_properties; + } + + return { status, condensed_phase_photolysis }; + } + /// @brief Parses a emission reaction /// @param object A json object that should have information containing arrhenius parameters /// @param existing_species A list of species configured in a mechanism @@ -1106,7 +1214,7 @@ namespace open_atmos if (object.contains(validation::keys.scaling_factor)) { - emission.scaling_factor_ = object[validation::keys.scaling_factor].get(); + emission.scaling_factor = object[validation::keys.scaling_factor].get(); } if (object.contains(validation::keys.name)) @@ -1177,7 +1285,7 @@ namespace open_atmos if (object.contains(validation::keys.scaling_factor)) { - first_order_loss.scaling_factor_ = object[validation::keys.scaling_factor].get(); + first_order_loss.scaling_factor = object[validation::keys.scaling_factor].get(); } if (object.contains(validation::keys.name)) @@ -1326,24 +1434,6 @@ namespace open_atmos status = ConfigParseStatus::UnknownPhase; } - if (status == ConfigParseStatus::Success && object.contains(validation::keys.ion_pair)) { - const auto& ion_pair_object = object[validation::keys.ion_pair]; - status = ValidateSchema(ion_pair_object, validation::ion_pair.required_keys, validation::ion_pair.optional_keys); - auto first_parse = ParseReactionComponent(ion_pair_object[validation::keys.first]); - if (first_parse.first != ConfigParseStatus::Success) { - status = first_parse.first; - } - else { - auto second_parse = ParseReactionComponent(ion_pair_object[validation::keys.second]); - if (second_parse.first != ConfigParseStatus::Success) { - status = second_parse.first; - } - else { - aqueous_equilibrium.ion_pair = std::array{first_parse.second, second_parse.second}; - } - } - } - aqueous_equilibrium.aerosol_phase = aerosol_phase; aqueous_equilibrium.aerosol_phase_water = aerosol_phase_water; aqueous_equilibrium.products = products; @@ -1353,6 +1443,138 @@ namespace open_atmos return { status, aqueous_equilibrium }; } + + /// @brief Parses a wet deposition reaction + /// @param object A json object that should have information containing arrhenius parameters + /// @param existing_species A list of species configured in a mechanism + /// @param existing_phases A list of phases configured in a mechanism + /// @return A pair indicating parsing success and a struct of First Order Loss parameters + std::pair + ParseWetDeposition(const json& object, const std::vector existing_species, const std::vector existing_phases) + { + ConfigParseStatus status = ConfigParseStatus::Success; + types::WetDeposition wet_deposition; + + status = ValidateSchema(object, validation::wet_deposition.required_keys, validation::wet_deposition.optional_keys); + if (status == ConfigParseStatus::Success) + { + if (object.contains(validation::keys.scaling_factor)) + { + wet_deposition.scaling_factor = object[validation::keys.scaling_factor].get(); + } + + if (object.contains(validation::keys.name)) + { + wet_deposition.name = object[validation::keys.name].get(); + } + + auto comments = GetComments(object, validation::wet_deposition.required_keys, validation::wet_deposition.optional_keys); + + std::unordered_map unknown_properties; + for (const auto& key : comments) + { + std::string val = object[key].dump(); + unknown_properties[key] = val; + } + + std::string aerosol_phase = object[validation::keys.aerosol_phase].get(); + + // check if aerosol phase exists + auto it = std::find_if(existing_phases.begin(), existing_phases.end(), [&aerosol_phase](const auto& phase) { return phase.name == aerosol_phase; }); + if (status == ConfigParseStatus::Success && it == existing_phases.end()) + { + status = ConfigParseStatus::UnknownPhase; + } + + wet_deposition.aerosol_phase = aerosol_phase; + wet_deposition.unknown_properties = unknown_properties; + } + + return { status, wet_deposition }; + } + + /// @brief Parses a first order loss reaction + /// @param object A json object that should have information containing arrhenius parameters + /// @param existing_species A list of species configured in a mechanism + /// @param existing_phases A list of phases configured in a mechanism + /// @return A pair indicating parsing success and a struct of First Order Loss parameters + std::pair + ParseHenrysLaw(const json& object, const std::vector existing_species, const std::vector existing_phases) + { + ConfigParseStatus status = ConfigParseStatus::Success; + types::HenrysLaw henrys_law; + + status = ValidateSchema(object, validation::henrys_law.required_keys, validation::henrys_law.optional_keys); + if (status == ConfigParseStatus::Success) + { + std::string gas_phase = object[validation::keys.gas_phase].get(); + std::string gas_phase_species = object[validation::keys.gas_phase_species].get(); + std::string aerosol_phase = object[validation::keys.aerosol_phase].get(); + std::string aerosol_phase_species = object[validation::keys.aerosol_phase_species].get(); + std::string aerosol_phase_water = object[validation::keys.aerosol_phase_water].get(); + + if (object.contains(validation::keys.name)) + { + henrys_law.name = object[validation::keys.name].get(); + } + + auto comments = GetComments(object, validation::henrys_law.required_keys, validation::henrys_law.optional_keys); + + std::unordered_map unknown_properties; + for (const auto& key : comments) + { + std::string val = object[key].dump(); + unknown_properties[key] = val; + } + + std::vector requested_species; + requested_species.push_back(gas_phase_species); + requested_species.push_back(aerosol_phase_species); + requested_species.push_back(aerosol_phase_water); + + std::vector requested_aerosol_species; + requested_aerosol_species.push_back(aerosol_phase_species); + requested_aerosol_species.push_back(aerosol_phase_water); + + if (status == ConfigParseStatus::Success && RequiresUnknownSpecies(requested_species, existing_species)) + { + status = ConfigParseStatus::ReactionRequiresUnknownSpecies; + } + + auto it = std::find_if(existing_phases.begin(), existing_phases.end(), [&gas_phase](const auto& phase) { return phase.name == gas_phase; }); + if (status == ConfigParseStatus::Success && it == existing_phases.end()) + { + status = ConfigParseStatus::UnknownPhase; + } + + auto phase_it = std::find_if( + existing_phases.begin(), existing_phases.end(), [&aerosol_phase](const types::Phase& phase) { return phase.name == aerosol_phase; }); + + if (phase_it != existing_phases.end()) + { + // check if all of the species for this reaction are actually in the aerosol phase + std::vector aerosol_phase_species = { (*phase_it).species.begin(), (*phase_it).species.end() }; + if (status == ConfigParseStatus::Success && RequiresUnknownSpecies(requested_aerosol_species, aerosol_phase_species)) + { + status = ConfigParseStatus::RequestedAerosolSpeciesNotIncludedInAerosolPhase; + } + } + else + { + status = ConfigParseStatus::UnknownPhase; + } + + henrys_law.gas_phase = gas_phase; + henrys_law.gas_phase_species = gas_phase_species; + henrys_law.aerosol_phase = aerosol_phase; + henrys_law.aerosol_phase_species = aerosol_phase_species; + henrys_law.aerosol_phase_water = aerosol_phase_water; + henrys_law.unknown_properties = unknown_properties; + } + + return { status, henrys_law }; + } + /// @brief Parses all reactions /// @param objects A json object that should contain only valid reactions /// @param existing_species A list of spcecies configured for a mechanism @@ -1437,6 +1659,16 @@ namespace open_atmos } reactions.photolysis.push_back(photolysis_parse.second); } + else if (type == validation::keys.CondensedPhasePhotolysis_key) + { + auto condensed_phase_photolysis_parse = ParseCondensedPhasePhotolysis(object, existing_species, existing_phases); + status = condensed_phase_photolysis_parse.first; + if (status != ConfigParseStatus::Success) + { + break; + } + reactions.condensed_phase_photolysis.push_back(condensed_phase_photolysis_parse.second); + } else if (type == validation::keys.Emission_key) { auto emission_parse = ParseEmission(object, existing_species, existing_phases); @@ -1467,6 +1699,26 @@ namespace open_atmos } reactions.aqueous_equilibrium.push_back(aqueous_equilibrium_parse.second); } + else if (type == validation::keys.WetDeposition_key) + { + auto wet_deposition_parse = ParseWetDeposition(object, existing_species, existing_phases); + status = wet_deposition_parse.first; + if (status != ConfigParseStatus::Success) + { + break; + } + reactions.wet_deposition.push_back(wet_deposition_parse.second); + } + else if (type == validation::keys.HenrysLaw_key) + { + auto henrys_law_parse = ParseHenrysLaw(object, existing_species, existing_phases); + status = henrys_law_parse.first; + if (status != ConfigParseStatus::Success) + { + break; + } + reactions.henrys_law.push_back(henrys_law_parse.second); + } } return { status, reactions }; diff --git a/test/integration/test_json_parser.cpp b/test/integration/test_json_parser.cpp index 4d9e034..d0148b5 100644 --- a/test/integration/test_json_parser.cpp +++ b/test/integration/test_json_parser.cpp @@ -13,15 +13,20 @@ TEST(JsonParser, ParsesFullConfiguration) EXPECT_EQ(mechanism.species.size(), 11); EXPECT_EQ(mechanism.phases.size(), 4); EXPECT_EQ(mechanism.reactions.arrhenius.size(), 2); - EXPECT_EQ(mechanism.reactions.condensed_phase_arrhenius.size(), 2); - EXPECT_EQ(mechanism.reactions.troe.size(), 1); EXPECT_EQ(mechanism.reactions.branched.size(), 1); + EXPECT_EQ(mechanism.reactions.condensed_phase_arrhenius.size(), 2); EXPECT_EQ(mechanism.reactions.tunneling.size(), 1); EXPECT_EQ(mechanism.reactions.surface.size(), 1); EXPECT_EQ(mechanism.reactions.photolysis.size(), 1); + 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.aqueous_equilibrium.size(), 1); + EXPECT_EQ(mechanism.reactions.henrys_law.size(), 1); + EXPECT_EQ(mechanism.reactions.photolysis.size(), 1); + EXPECT_EQ(mechanism.reactions.surface.size(), 1); + EXPECT_EQ(mechanism.reactions.troe.size(), 1); + EXPECT_EQ(mechanism.reactions.tunneling.size(), 1); } TEST(JsonParser, ParserReportsBadFiles) diff --git a/test/unit/CMakeLists.txt b/test/unit/CMakeLists.txt index 87c7d64..fa30a42 100644 --- a/test/unit/CMakeLists.txt +++ b/test/unit/CMakeLists.txt @@ -9,8 +9,10 @@ include(test_util) create_standard_test(NAME parse_arrhenius SOURCES test_parse_arrhenius.cpp) create_standard_test(NAME parse_branched SOURCES test_parse_branched.cpp) create_standard_test(NAME parse_condensed_phase_arrhenius SOURCES test_parse_condensed_phase_arrhenius.cpp) +create_standard_test(NAME parse_condensed_phase_photolysis SOURCES test_parse_condensed_phase_photolysis.cpp) create_standard_test(NAME parse_emission SOURCES test_parse_emission.cpp) create_standard_test(NAME parse_first_order_loss SOURCES test_parse_first_order_loss.cpp) +create_standard_test(NAME parse_henrys_law SOURCES test_parse_henrys_law.cpp) create_standard_test(NAME parse_phases SOURCES test_parse_phases.cpp) create_standard_test(NAME parse_photolysis SOURCES test_parse_photolysis.cpp) create_standard_test(NAME parse_species SOURCES test_parse_species.cpp) @@ -18,6 +20,7 @@ create_standard_test(NAME parse_surface SOURCES test_parse_surface.cpp) create_standard_test(NAME parse_troe SOURCES test_parse_troe.cpp) create_standard_test(NAME parse_tunneling SOURCES test_parse_tunneling.cpp) create_standard_test(NAME parse_aqueous_equilibrium SOURCES test_parse_aqueous_equilibrium.cpp) +create_standard_test(NAME parse_wet_deposition SOURCES test_parse_wet_deposition.cpp) ################################################################################ # Copy test data diff --git a/test/unit/test_parse_aqueous_equilibrium.cpp b/test/unit/test_parse_aqueous_equilibrium.cpp index b508dfc..132e0d0 100644 --- a/test/unit/test_parse_aqueous_equilibrium.cpp +++ b/test/unit/test_parse_aqueous_equilibrium.cpp @@ -26,8 +26,6 @@ TEST(JsonParser, CanParseValidAqueousEquilibriumReaction) EXPECT_EQ(mechanism.reactions.aqueous_equilibrium[0].products[0].coefficient, 1); EXPECT_EQ(mechanism.reactions.aqueous_equilibrium[0].products[1].species_name, "C"); EXPECT_EQ(mechanism.reactions.aqueous_equilibrium[0].products[1].coefficient, 1); - EXPECT_EQ(mechanism.reactions.aqueous_equilibrium[0].ion_pair.value()[0].species_name, "A"); - EXPECT_EQ(mechanism.reactions.aqueous_equilibrium[0].ion_pair.value()[1].species_name, "B"); 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\""); @@ -35,7 +33,6 @@ TEST(JsonParser, CanParseValidAqueousEquilibriumReaction) EXPECT_EQ(mechanism.reactions.aqueous_equilibrium[1].aerosol_phase_water, "H2O_aq"); 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].ion_pair.has_value(), false); 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].species_name, "A"); @@ -66,11 +63,4 @@ TEST(JsonParser, AqueousEquilibriumDetectsUnknownPhase) JsonParser parser; auto [status, mechanism] = parser.Parse(std::string("unit_configs/reactions/aqueous_equilibrium/missing_phase.json")); EXPECT_EQ(status, ConfigParseStatus::UnknownPhase); -} - -TEST(JsonParser, AqueousEquilibriumDetectsInvalidIonPair) -{ - JsonParser parser; - auto [status, mechanism] = parser.Parse(std::string("unit_configs/reactions/aqueous_equilibrium/invalid_ion_pair.json")); - EXPECT_EQ(status, ConfigParseStatus::InvalidIonPair); } \ No newline at end of file diff --git a/test/unit/test_parse_condensed_phase_photolysis.cpp b/test/unit/test_parse_condensed_phase_photolysis.cpp new file mode 100644 index 0000000..acaf4eb --- /dev/null +++ b/test/unit/test_parse_condensed_phase_photolysis.cpp @@ -0,0 +1,79 @@ +#include + +#include + +using namespace open_atmos::mechanism_configuration; + +TEST(JsonParser, CanParseValidCondensedPhasePhotolysisReaction) +{ + JsonParser parser; + auto [status, mechanism] = parser.Parse(std::string("unit_configs/reactions/condensed_phase_photolysis/valid.json")); + EXPECT_EQ(status, ConfigParseStatus::Success); + + EXPECT_EQ(mechanism.reactions.condensed_phase_photolysis.size(), 2); + + EXPECT_EQ(mechanism.reactions.condensed_phase_photolysis[0].aerosol_phase, "aqueous aerosol"); + EXPECT_EQ(mechanism.reactions.condensed_phase_photolysis[0].aerosol_phase_water, "H2O_aq"); + 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.size(), 1); + EXPECT_EQ(mechanism.reactions.condensed_phase_photolysis[0].reactants[0].species_name, "B"); + EXPECT_EQ(mechanism.reactions.condensed_phase_photolysis[0].reactants[0].coefficient, 1); + EXPECT_EQ(mechanism.reactions.condensed_phase_photolysis[0].products.size(), 1); + EXPECT_EQ(mechanism.reactions.condensed_phase_photolysis[0].products[0].species_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].aerosol_phase, "aqueous aerosol"); + EXPECT_EQ(mechanism.reactions.condensed_phase_photolysis[1].aerosol_phase_water, "H2O_aq"); + EXPECT_EQ(mechanism.reactions.condensed_phase_photolysis[1].scaling_factor_, 1); + EXPECT_EQ(mechanism.reactions.condensed_phase_photolysis[1].reactants.size(), 1); + EXPECT_EQ(mechanism.reactions.condensed_phase_photolysis[1].reactants[0].species_name, "B"); + EXPECT_EQ(mechanism.reactions.condensed_phase_photolysis[1].reactants[0].coefficient, 1.2); + EXPECT_EQ(mechanism.reactions.condensed_phase_photolysis[1].products.size(), 1); + EXPECT_EQ(mechanism.reactions.condensed_phase_photolysis[1].products[0].species_name, "C"); + EXPECT_EQ(mechanism.reactions.condensed_phase_photolysis[1].products[0].coefficient, 0.2); +} + +TEST(JsonParser, CondensedPhasePhotolysisDetectsUnknownSpecies) +{ + JsonParser parser; + auto [status, mechanism] = parser.Parse(std::string("unit_configs/reactions/condensed_phase_photolysis/unknown_species.json")); + EXPECT_EQ(status, ConfigParseStatus::ReactionRequiresUnknownSpecies); +} + +TEST(JsonParser, CondensedPhasePhotolysisDetectsBadReactionComponent) +{ + JsonParser parser; + auto [status, mechanism] = parser.Parse(std::string("unit_configs/reactions/condensed_phase_photolysis/bad_reaction_component.json")); + EXPECT_EQ(status, ConfigParseStatus::InvalidKey); +} + +TEST(JsonParser, CondensedPhasePhotolysisDetectsUnknownPhase) +{ + JsonParser parser; + auto [status, mechanism] = parser.Parse(std::string("unit_configs/reactions/condensed_phase_photolysis/missing_phase.json")); + EXPECT_EQ(status, ConfigParseStatus::UnknownPhase); +} + +TEST(JsonParser, CondensedPhasePhotolysisDoesNotAcceptMoreThanOneReactant) +{ + JsonParser parser; + auto [status, mechanism] = parser.Parse(std::string("unit_configs/reactions/condensed_phase_photolysis/more_than_one_reactant.json")); + EXPECT_EQ(status, ConfigParseStatus::TooManyReactionComponents); +} + +TEST(JsonParser, CondensedPhasePhotolysisDetectsWhenRequestedSpeciesAreNotInAerosolPhase) +{ + JsonParser parser; + auto [status, mechanism] = parser.Parse(std::string("unit_configs/reactions/condensed_phase_photolysis/species_not_in_aerosol_phase.json")); + EXPECT_EQ(status, ConfigParseStatus::RequestedAerosolSpeciesNotIncludedInAerosolPhase); +} + +TEST(JsonParser, CondensedPhaseArrheniusDetectsUnknownAerosolPhaseWater) +{ + JsonParser parser; + auto [status, mechanism] = parser.Parse(std::string("unit_configs/reactions/condensed_phase_photolysis/missing_aerosol_phase_water.json")); + EXPECT_EQ(status, ConfigParseStatus::ReactionRequiresUnknownSpecies); +} \ No newline at end of file diff --git a/test/unit/test_parse_emission.cpp b/test/unit/test_parse_emission.cpp index fbe6424..0ce87ab 100644 --- a/test/unit/test_parse_emission.cpp +++ b/test/unit/test_parse_emission.cpp @@ -14,7 +14,7 @@ TEST(JsonParser, CanParseValidEmissionReaction) 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].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].coefficient, 1); @@ -22,7 +22,7 @@ TEST(JsonParser, CanParseValidEmissionReaction) 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].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].coefficient, 1); diff --git a/test/unit/test_parse_first_order_loss.cpp b/test/unit/test_parse_first_order_loss.cpp index 30de586..f6226f6 100644 --- a/test/unit/test_parse_first_order_loss.cpp +++ b/test/unit/test_parse_first_order_loss.cpp @@ -14,7 +14,7 @@ TEST(JsonParser, CanParseValidFirstOrderLossReaction) 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].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); @@ -22,7 +22,7 @@ TEST(JsonParser, CanParseValidFirstOrderLossReaction) 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].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); diff --git a/test/unit/test_parse_henrys_law.cpp b/test/unit/test_parse_henrys_law.cpp new file mode 100644 index 0000000..2e0aabd --- /dev/null +++ b/test/unit/test_parse_henrys_law.cpp @@ -0,0 +1,59 @@ +#include + +#include + +using namespace open_atmos::mechanism_configuration; + +TEST(JsonParser, CanParseValidHenrysLawReaction) +{ + JsonParser parser; + auto [status, mechanism] = parser.Parse(std::string("unit_configs/reactions/henrys_law/valid.json")); + EXPECT_EQ(status, ConfigParseStatus::Success); + + 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_phase, "gas"); + EXPECT_EQ(mechanism.reactions.henrys_law[0].gas_phase_species, "A"); + EXPECT_EQ(mechanism.reactions.henrys_law[0].aerosol_phase, "aqueous aerosol"); + EXPECT_EQ(mechanism.reactions.henrys_law[0].aerosol_phase_species, "B"); + EXPECT_EQ(mechanism.reactions.henrys_law[0].aerosol_phase_water, "H2O_aq"); + EXPECT_EQ(mechanism.reactions.henrys_law[0].unknown_properties.size(), 1); + EXPECT_EQ(mechanism.reactions.henrys_law[0].unknown_properties["__comment"], "\"hi\""); + + EXPECT_EQ(mechanism.reactions.henrys_law[1].name, ""); + EXPECT_EQ(mechanism.reactions.henrys_law[1].gas_phase, "gas"); + EXPECT_EQ(mechanism.reactions.henrys_law[1].gas_phase_species, "A"); + EXPECT_EQ(mechanism.reactions.henrys_law[1].aerosol_phase, "aqueous aerosol"); + EXPECT_EQ(mechanism.reactions.henrys_law[1].aerosol_phase_species, "B"); + EXPECT_EQ(mechanism.reactions.henrys_law[1].aerosol_phase_water, "H2O_aq"); + EXPECT_EQ(mechanism.reactions.henrys_law[1].unknown_properties.size(), 0); +} + +TEST(JsonParser, HenrysLawDetectsUnknownSpecies) +{ + JsonParser parser; + auto [status, mechanism] = parser.Parse(std::string("unit_configs/reactions/henrys_law/unknown_species.json")); + EXPECT_EQ(status, ConfigParseStatus::ReactionRequiresUnknownSpecies); +} + +TEST(JsonParser, HenrysLawDetectsUnknownPhase) +{ + JsonParser parser; + auto [status, mechanism] = parser.Parse(std::string("unit_configs/reactions/henrys_law/missing_phase.json")); + EXPECT_EQ(status, ConfigParseStatus::UnknownPhase); +} + +TEST(JsonParser, HenrysLawDetectsUnknownAerosolPhaseWater) +{ + JsonParser parser; + auto [status, mechanism] = parser.Parse(std::string("unit_configs/reactions/condensed_phase_arrhenius/missing_aerosol_phase_water.json")); + EXPECT_EQ(status, ConfigParseStatus::ReactionRequiresUnknownSpecies); +} + +TEST(JsonParser, HenrysLawDetectsWhenRequestedSpeciesAreNotInAerosolPhase) +{ + JsonParser parser; + auto [status, mechanism] = parser.Parse(std::string("unit_configs/reactions/condensed_phase_arrhenius/species_not_in_aerosol_phase.json")); + EXPECT_EQ(status, ConfigParseStatus::RequestedAerosolSpeciesNotIncludedInAerosolPhase); +} \ No newline at end of file diff --git a/test/unit/test_parse_photolysis.cpp b/test/unit/test_parse_photolysis.cpp index eff3e9d..1089126 100644 --- a/test/unit/test_parse_photolysis.cpp +++ b/test/unit/test_parse_photolysis.cpp @@ -14,7 +14,7 @@ TEST(JsonParser, CanParseValidPhotolysisReaction) 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].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); @@ -25,7 +25,7 @@ TEST(JsonParser, CanParseValidPhotolysisReaction) 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].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); diff --git a/test/unit/test_parse_wet_deposition.cpp b/test/unit/test_parse_wet_deposition.cpp new file mode 100644 index 0000000..3b1bd1e --- /dev/null +++ b/test/unit/test_parse_wet_deposition.cpp @@ -0,0 +1,31 @@ +#include + +#include + +using namespace open_atmos::mechanism_configuration; + +TEST(JsonParser, CanParseValidWetDepositionReaction) +{ + JsonParser parser; + auto [status, mechanism] = parser.Parse(std::string("unit_configs/reactions/wet_deposition/valid.json")); + EXPECT_EQ(status, ConfigParseStatus::Success); + + 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].aerosol_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].aerosol_phase, "cloud"); + EXPECT_EQ(mechanism.reactions.wet_deposition[1].scaling_factor, 1); +} + +TEST(JsonParser, WetDepositionDetectsUnknownPhase) +{ + JsonParser parser; + auto [status, mechanism] = parser.Parse(std::string("unit_configs/reactions/wet_deposition/missing_phase.json")); + EXPECT_EQ(status, ConfigParseStatus::UnknownPhase); +} \ No newline at end of file diff --git a/test/unit/unit_configs/reactions/aqueous_equilibrium/bad_reaction_component.json b/test/unit/unit_configs/reactions/aqueous_equilibrium/bad_reaction_component.json index 03f3729..dddaf02 100644 --- a/test/unit/unit_configs/reactions/aqueous_equilibrium/bad_reaction_component.json +++ b/test/unit/unit_configs/reactions/aqueous_equilibrium/bad_reaction_component.json @@ -32,10 +32,6 @@ "aerosol phase": "aerosol", "aerosol-phase water": "H2O_aq", "k_reverse": 0.32, - "ion pair": { - "first": { "species name": "A"}, - "second": { "species name": "B"} - }, "reactants": [ { "Species name": "A", diff --git a/test/unit/unit_configs/reactions/aqueous_equilibrium/missing_phase.json b/test/unit/unit_configs/reactions/aqueous_equilibrium/missing_phase.json index 93d295b..c7e6d52 100644 --- a/test/unit/unit_configs/reactions/aqueous_equilibrium/missing_phase.json +++ b/test/unit/unit_configs/reactions/aqueous_equilibrium/missing_phase.json @@ -22,10 +22,6 @@ "aerosol phase": "aerosol", "aerosol-phase water": "H2O_aq", "k_reverse": 0.32, - "ion pair": { - "first": { "species name": "A"}, - "second": { "species name": "B"} - }, "reactants": [ { "species name": "A", diff --git a/test/unit/unit_configs/reactions/aqueous_equilibrium/unknown_species.json b/test/unit/unit_configs/reactions/aqueous_equilibrium/unknown_species.json index 97d7a81..6a766df 100644 --- a/test/unit/unit_configs/reactions/aqueous_equilibrium/unknown_species.json +++ b/test/unit/unit_configs/reactions/aqueous_equilibrium/unknown_species.json @@ -24,10 +24,6 @@ "aerosol phase": "aerosol", "aerosol-phase water": "H2O_aq", "k_reverse": 0.32, - "ion pair": { - "first": { "species name": "A"}, - "second": { "species name": "B"} - }, "reactants": [ { "species name": "A", diff --git a/test/unit/unit_configs/reactions/aqueous_equilibrium/valid.json b/test/unit/unit_configs/reactions/aqueous_equilibrium/valid.json index 758b8ac..8011b7c 100644 --- a/test/unit/unit_configs/reactions/aqueous_equilibrium/valid.json +++ b/test/unit/unit_configs/reactions/aqueous_equilibrium/valid.json @@ -34,10 +34,6 @@ "A": 1.14e-2, "C": 2300.0, "k_reverse": 0.32, - "ion pair": { - "first": { "species name": "A"}, - "second": { "species name": "B"} - }, "reactants": [ { "species name": "A", diff --git a/test/unit/unit_configs/reactions/condensed_phase_photolysis/bad_reaction_component.json b/test/unit/unit_configs/reactions/condensed_phase_photolysis/bad_reaction_component.json new file mode 100644 index 0000000..de78eb2 --- /dev/null +++ b/test/unit/unit_configs/reactions/condensed_phase_photolysis/bad_reaction_component.json @@ -0,0 +1,48 @@ +{ + "version": "1.0.0", + "name": "Bad reaction component", + "species": [ + { + "name": "A" + }, + { + "name": "B" + }, + { + "name": "C" + }, + { + "name": "H2O_aq" + } + ], + "phases": [ + { + "name": "aqueous aerosol", + "species": [ + "A", + "B", + "C", + "H2O_aq" + ] + } + ], + "reactions": [ + { + "type": "CONDENSED_PHASE_PHOTOLYSIS", + "aerosol phase": "aqueous aerosol", + "aerosol-phase water": "H2O_aq", + "reactants": [ + { + "species name": "A", + "Coefficient": 1.2 + } + ], + "products": [ + { + "species name": "B", + "coefficient": 0.2 + } + ] + } + ] +} \ No newline at end of file diff --git a/test/unit/unit_configs/reactions/condensed_phase_photolysis/missing_aerosol_phase_water.json b/test/unit/unit_configs/reactions/condensed_phase_photolysis/missing_aerosol_phase_water.json new file mode 100644 index 0000000..659654d --- /dev/null +++ b/test/unit/unit_configs/reactions/condensed_phase_photolysis/missing_aerosol_phase_water.json @@ -0,0 +1,48 @@ +{ + "version": "1.0.0", + "name": "Missing condensed phase arrhenius aerosol phase water", + "species": [ + { + "name": "A" + }, + { + "name": "B" + }, + { + "name": "C" + }, + { + "name": "H2O_aq" + } + ], + "phases": [ + { + "name": "aqueous aerosol", + "species": [ + "A", + "B", + "C", + "H2O_aq" + ] + } + ], + "reactions": [ + { + "type": "CONDENSED_PHASE_PHOTOLYSIS", + "aerosol phase": "aqueous aerosol", + "aerosol-phase water": "H2O_a", + "reactants": [ + { + "species name": "B", + "coefficient": 1.2 + } + ], + "products": [ + { + "species name": "C", + "coefficient": 0.2 + } + ] + } + ] +} \ No newline at end of file diff --git a/test/unit/unit_configs/reactions/condensed_phase_photolysis/missing_phase.json b/test/unit/unit_configs/reactions/condensed_phase_photolysis/missing_phase.json new file mode 100644 index 0000000..0de7a16 --- /dev/null +++ b/test/unit/unit_configs/reactions/condensed_phase_photolysis/missing_phase.json @@ -0,0 +1,38 @@ +{ + "version": "1.0.0", + "name": "Missing phase", + "species": [ + { + "name": "A" + }, + { + "name": "B" + }, + { + "name": "C" + }, + { + "name": "H2O_aq" + } + ], + "phases": [ ], + "reactions": [ + { + "type": "CONDENSED_PHASE_PHOTOLYSIS", + "aerosol phase": "aqueous aerosol", + "aerosol-phase water": "H2O_aq", + "reactants": [ + { + "species name": "B", + "coefficient": 1.2 + } + ], + "products": [ + { + "species name": "C", + "coefficient": 0.2 + } + ] + } + ] +} \ No newline at end of file diff --git a/test/unit/unit_configs/reactions/condensed_phase_photolysis/more_than_one_reactant.json b/test/unit/unit_configs/reactions/condensed_phase_photolysis/more_than_one_reactant.json new file mode 100644 index 0000000..54530f1 --- /dev/null +++ b/test/unit/unit_configs/reactions/condensed_phase_photolysis/more_than_one_reactant.json @@ -0,0 +1,50 @@ +{ + "version": "1.0.0", + "name": "more than one reactant", + "species": [ + { + "name": "A" + }, + { + "name": "B" + }, + { + "name": "C" + }, + { + "name": "H2O_aq" + } + ], + "phases": [ + { + "name": "aqueous aerosol", + "species": [ + "A", + "B", + "C", + "H2O_aq" + ] + } + ], + "reactions": [ + { + "type": "CONDENSED_PHASE_PHOTOLYSIS", + "aerosol phase": "aqueous aerosol", + "aerosol-phase water": "H2O_aq", + "reactants": [ + { + "species name": "A" + }, + { + "species name": "B" + } + ], + "products": [ + { + "species name": "C", + "coefficient": 0.2 + } + ] + } + ] +} \ No newline at end of file diff --git a/test/unit/unit_configs/reactions/aqueous_equilibrium/invalid_ion_pair.json b/test/unit/unit_configs/reactions/condensed_phase_photolysis/species_not_in_aerosol_phase.json similarity index 63% rename from test/unit/unit_configs/reactions/aqueous_equilibrium/invalid_ion_pair.json rename to test/unit/unit_configs/reactions/condensed_phase_photolysis/species_not_in_aerosol_phase.json index 936b7a4..ad9ad21 100644 --- a/test/unit/unit_configs/reactions/aqueous_equilibrium/invalid_ion_pair.json +++ b/test/unit/unit_configs/reactions/condensed_phase_photolysis/species_not_in_aerosol_phase.json @@ -1,6 +1,6 @@ { "version": "1.0.0", - "name": "Valid aqueous equilibrium", + "name": "Condensed phase photolysis using species not in its requested aerosol phase", "species": [ { "name": "A" @@ -17,10 +17,9 @@ ], "phases": [ { - "name": "aerosol", + "name": "aqueous aerosol", "species": [ "A", - "B", "C", "H2O_aq" ] @@ -28,28 +27,23 @@ ], "reactions": [ { - "type": "AQUEOUS_EQUILIBRIUM", - "aerosol phase": "aerosol", + "type": "CONDENSED_PHASE_PHOTOLYSIS", + "aerosol phase": "aqueous aerosol", "aerosol-phase water": "H2O_aq", - "k_reverse": 0.32, - "ion pair": { - "first": { "species name": "A"}, - "second": { "species name": "B"} - }, "reactants": [ { "species name": "A", - "coefficient": 2 + "coefficient": 1 } ], "products": [ { "species name": "B", - "coefficient": 1 + "coefficient": 1.2 }, { "species name": "C", - "coefficient": 1 + "coefficient": 0.3 } ] } diff --git a/test/unit/unit_configs/reactions/condensed_phase_photolysis/unknown_species.json b/test/unit/unit_configs/reactions/condensed_phase_photolysis/unknown_species.json new file mode 100644 index 0000000..49a1124 --- /dev/null +++ b/test/unit/unit_configs/reactions/condensed_phase_photolysis/unknown_species.json @@ -0,0 +1,40 @@ +{ + "version": "1.0.0", + "name": "Unknown species", + "species": [ + { + "name": "A" + }, + { + "name": "B" + } + ], + "phases": [ + { + "name": "aqueous aerosol", + "species": [ + "A", + "B" + ] + } + ], + "reactions": [ + { + "type": "CONDENSED_PHASE_PHOTOLYSIS", + "aerosol phase": "aqueous aerosol", + "aerosol-phase water": "H2O_aq", + "reactants": [ + { + "species name": "A", + "coefficient": 1.2 + } + ], + "products": [ + { + "species name": "B", + "coefficient": 0.2 + } + ] + } + ] +} \ No newline at end of file diff --git a/test/unit/unit_configs/reactions/condensed_phase_photolysis/valid.json b/test/unit/unit_configs/reactions/condensed_phase_photolysis/valid.json new file mode 100644 index 0000000..1a907f8 --- /dev/null +++ b/test/unit/unit_configs/reactions/condensed_phase_photolysis/valid.json @@ -0,0 +1,68 @@ +{ + "version": "1.0.0", + "name": "Valid surface", + "species": [ + { + "name": "A" + }, + { + "name": "B" + }, + { + "name": "C" + }, + { + "name": "H2O_aq" + } + ], + "phases": [ + { + "name": "aqueous aerosol", + "species": [ + "A", + "B", + "C", + "H2O_aq" + ] + } + ], + "reactions": [ + { + "type": "CONDENSED_PHASE_PHOTOLYSIS", + "aerosol phase": "aqueous aerosol", + "aerosol-phase water": "H2O_aq", + "__comment": "hi", + "reactants": [ + { + "species name": "B", + "coefficient": 1 + } + ], + "products": [ + { + "species name": "C", + "coefficient": 1 + } + ], + "name": "my condensed phase photolysis", + "scaling factor": 12.3 + }, + { + "type": "CONDENSED_PHASE_PHOTOLYSIS", + "aerosol phase": "aqueous aerosol", + "aerosol-phase water": "H2O_aq", + "reactants": [ + { + "species name": "B", + "coefficient": 1.2 + } + ], + "products": [ + { + "species name": "C", + "coefficient": 0.2 + } + ] + } + ] +} \ No newline at end of file diff --git a/test/unit/unit_configs/reactions/henrys_law/missing_aerosol_phase_water.json b/test/unit/unit_configs/reactions/henrys_law/missing_aerosol_phase_water.json new file mode 100644 index 0000000..f1e6976 --- /dev/null +++ b/test/unit/unit_configs/reactions/henrys_law/missing_aerosol_phase_water.json @@ -0,0 +1,46 @@ +{ + "version": "1.0.0", + "name": "Missing condensed phase arrhenius aerosol phase water", + "species": [ + { + "name": "A" + }, + { + "name": "B" + }, + { + "name": "C" + }, + { + "name": "H2O_aq" + } + ], + "phases": [ + { + "name": "aqueous aerosol", + "species": [ + "A", + "B", + "C", + "H2O_aq" + ] + } + ], + "reactions": [ + { + "type": "CONDENSED_PHASE_ARRHENIUS", + "aerosol phase": "aqueous aerosol", + "aerosol-phase water": "H2O_a", + "reactants": [ + { + "species name": "A" + } + ], + "products": [ + { + "species name": "C" + } + ] + } + ] +} \ No newline at end of file diff --git a/test/unit/unit_configs/reactions/henrys_law/missing_phase.json b/test/unit/unit_configs/reactions/henrys_law/missing_phase.json new file mode 100644 index 0000000..ca368c9 --- /dev/null +++ b/test/unit/unit_configs/reactions/henrys_law/missing_phase.json @@ -0,0 +1,27 @@ +{ + "version": "1.0.0", + "name": "Missing phase", + "species": [ + { + "name": "A" + }, + { + "name": "B" + }, + { + "name": "C" + } + ], + "phases": [ ], + "reactions": [ + { + "type": "HL_PHASE_TRANSFER", + "gas phase": "gas", + "gas-phase species": "H2O2", + "aerosol phase": "aqueous aerosol", + "aerosol-phase species": "H2O2_aq", + "aerosol-phase water": "H2O_aq", + "name": "my henry's law" + } + ] +} \ No newline at end of file diff --git a/test/unit/unit_configs/reactions/henrys_law/species_not_in_aerosol_phase.json b/test/unit/unit_configs/reactions/henrys_law/species_not_in_aerosol_phase.json new file mode 100644 index 0000000..b7a8795 --- /dev/null +++ b/test/unit/unit_configs/reactions/henrys_law/species_not_in_aerosol_phase.json @@ -0,0 +1,101 @@ +{ + "version": "1.0.0", + "name": "Condensed phase arrhenius using species not in its requested aerosol phase", + "species": [ + { + "name": "A" + }, + { + "name": "B" + }, + { + "name": "C" + }, + { + "name": "H2O_aq" + } + ], + "phases": [ + { + "name": "aqueous aerosol", + "species": [ + "A", + "C", + "H2O_aq" + ] + } + ], + "reactions": [ + { + "type": "CONDENSED_PHASE_ARRHENIUS", + "aerosol phase": "aqueous aerosol", + "aerosol-phase water": "H2O_aq", + "reactants": [ + { + "species name": "A", + "coefficient": 1 + } + ], + "products": [ + { + "species name": "B", + "coefficient": 1.2 + }, + { + "species 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", + "aerosol phase": "aqueous aerosol", + "aerosol-phase water": "H2O_aq", + "reactants": [ + { + "species name": "A", + "coefficient": 2 + }, + { + "species name": "B", + "coefficient": 0.1 + } + ], + "products": [ + { + "species 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", + "aerosol phase": "aqueous aerosol", + "aerosol-phase water": "H2O_aq", + "reactants": [ + { + "species name": "A" + } + ], + "products": [ + { + "species name": "C" + } + ] + } + ] +} \ No newline at end of file diff --git a/test/unit/unit_configs/reactions/henrys_law/unknown_species.json b/test/unit/unit_configs/reactions/henrys_law/unknown_species.json new file mode 100644 index 0000000..b3a1f90 --- /dev/null +++ b/test/unit/unit_configs/reactions/henrys_law/unknown_species.json @@ -0,0 +1,40 @@ +{ + "version": "1.0.0", + "name": "Unknown species", + "species": [ + { + "name": "A" + }, + { + "name": "B" + }, + { + "name": "H2O_aq" + } + ], + "phases": [ + { + "name": "gas", + "species": [ + "A" + ] + }, + { + "name": "aqueous aerosol", + "species": [ + "B", + "H2O_aq" + ] + } + ], + "reactions": [ + { + "type": "HL_PHASE_TRANSFER", + "gas phase": "gas", + "gas-phase species": "C", + "aerosol phase": "aqueous aerosol", + "aerosol-phase species": "B", + "aerosol-phase water": "H2O_aq" + } + ] +} \ No newline at end of file diff --git a/test/unit/unit_configs/reactions/henrys_law/valid.json b/test/unit/unit_configs/reactions/henrys_law/valid.json new file mode 100644 index 0000000..92001f3 --- /dev/null +++ b/test/unit/unit_configs/reactions/henrys_law/valid.json @@ -0,0 +1,50 @@ +{ + "version": "1.0.0", + "name": "Valid surface", + "species": [ + { + "name": "A" + }, + { + "name": "B" + }, + { + "name": "H2O_aq" + } + ], + "phases": [ + { + "name": "gas", + "species": [ + "A" + ] + }, + { + "name": "aqueous aerosol", + "species": [ + "B", + "H2O_aq" + ] + } + ], + "reactions": [ + { + "type": "HL_PHASE_TRANSFER", + "gas phase": "gas", + "gas-phase species": "A", + "aerosol phase": "aqueous aerosol", + "aerosol-phase species": "B", + "aerosol-phase water": "H2O_aq", + "name": "my henry's law", + "__comment": "hi" + }, + { + "type": "HL_PHASE_TRANSFER", + "gas phase": "gas", + "gas-phase species": "A", + "aerosol phase": "aqueous aerosol", + "aerosol-phase species": "B", + "aerosol-phase water": "H2O_aq" + } + ] +} \ No newline at end of file diff --git a/test/unit/unit_configs/reactions/photolysis/more_than_one_reactant.json b/test/unit/unit_configs/reactions/photolysis/more_than_one_reactant.json index 5a77825..a036923 100644 --- a/test/unit/unit_configs/reactions/photolysis/more_than_one_reactant.json +++ b/test/unit/unit_configs/reactions/photolysis/more_than_one_reactant.json @@ -1,6 +1,6 @@ { "version": "1.0.0", - "name": "Valid surface", + "name": "more than one reactant", "species": [ { "name": "A" diff --git a/test/unit/unit_configs/reactions/photolysis/valid.json b/test/unit/unit_configs/reactions/photolysis/valid.json index 3f1c047..91c2de4 100644 --- a/test/unit/unit_configs/reactions/photolysis/valid.json +++ b/test/unit/unit_configs/reactions/photolysis/valid.json @@ -1,6 +1,6 @@ { "version": "1.0.0", - "name": "Valid surface", + "name": "Valid photolysis", "species": [ { "name": "A" diff --git a/test/unit/unit_configs/reactions/wet_deposition/missing_phase.json b/test/unit/unit_configs/reactions/wet_deposition/missing_phase.json new file mode 100644 index 0000000..bc25732 --- /dev/null +++ b/test/unit/unit_configs/reactions/wet_deposition/missing_phase.json @@ -0,0 +1,24 @@ +{ + "version": "1.0.0", + "name": "Missing phase", + "species": [ + { + "name": "A" + }, + { + "name": "B" + }, + { + "name": "C" + } + ], + "phases": [ + ], + "reactions": [ + { + "type": "WET_DEPOSITION", + "aerosol phase": "cloud", + "name": "rxn cloud" + } + ] +} \ No newline at end of file diff --git a/test/unit/unit_configs/reactions/wet_deposition/valid.json b/test/unit/unit_configs/reactions/wet_deposition/valid.json new file mode 100644 index 0000000..0ad861c --- /dev/null +++ b/test/unit/unit_configs/reactions/wet_deposition/valid.json @@ -0,0 +1,39 @@ +{ + "version": "1.0.0", + "name": "Valid wet deposition", + "species": [ + { + "name": "A" + }, + { + "name": "B" + }, + { + "name": "C" + } + ], + "phases": [ + { + "name": "cloud", + "species": [ + "A", + "B", + "C" + ] + } + ], + "reactions": [ + { + "type": "WET_DEPOSITION", + "aerosol phase": "cloud", + "name": "rxn cloud", + "scaling factor": 12.3, + "__comment": "Tuxedo cats are the best" + }, + { + "type": "WET_DEPOSITION", + "aerosol phase": "cloud", + "name": "rxn cloud2" + } + ] +} \ No newline at end of file