From b7be48260de46552b6a87200809dfa70ab665d60 Mon Sep 17 00:00:00 2001 From: Kyle Shores Date: Tue, 23 Jan 2024 09:48:08 -0600 Subject: [PATCH] dropping to c++17, using optional for ion pair --- examples/full_configuration.json | 6 +- .../mechanism_configuration/parser.hpp | 3 +- include/open_atmos/types.hpp | 4 +- src/CMakeLists.txt | 2 +- src/parser.cpp | 24 ++++---- test/unit/test_parse_aqueous_equilibrium.cpp | 53 ++++++++--------- .../bad_reaction_component.json | 32 +++++++++-- .../aqueous_equilibrium/invalid_ion_pair.json | 57 +++++++++++++++++++ .../aqueous_equilibrium/missing_phase.json | 23 ++++++-- .../mutually_exclusive.json | 39 ------------- .../aqueous_equilibrium/unknown_species.json | 22 +++++-- .../reactions/aqueous_equilibrium/valid.json | 8 +-- 12 files changed, 172 insertions(+), 101 deletions(-) create mode 100644 test/unit/unit_configs/reactions/aqueous_equilibrium/invalid_ion_pair.json delete mode 100644 test/unit/unit_configs/reactions/aqueous_equilibrium/mutually_exclusive.json diff --git a/examples/full_configuration.json b/examples/full_configuration.json index ab62899..47358e0 100644 --- a/examples/full_configuration.json +++ b/examples/full_configuration.json @@ -76,7 +76,10 @@ "species": [ "H2O2_aq", "H2O_aq", - "ethanol_aq" + "ethanol_aq", + "A", + "B", + "C" ] }, { @@ -120,7 +123,6 @@ }, { "type": "AQUEOUS_EQUILIBRIUM", - "gas phase": "gas", "aerosol phase": "aqueous aerosol", "aerosol-phase water": "H2O_aq", "A": 1.14e-2, diff --git a/include/open_atmos/mechanism_configuration/parser.hpp b/include/open_atmos/mechanism_configuration/parser.hpp index aba0668..86e2a80 100644 --- a/include/open_atmos/mechanism_configuration/parser.hpp +++ b/include/open_atmos/mechanism_configuration/parser.hpp @@ -35,7 +35,8 @@ namespace open_atmos ReactionRequiresUnknownSpecies, UnknownPhase, RequestedAerosolSpeciesNotIncludedInAerosolPhase, - TooManyReactionComponents + TooManyReactionComponents, + InvalidIonPair }; std::string configParseStatusToString(const ConfigParseStatus &status); diff --git a/include/open_atmos/types.hpp b/include/open_atmos/types.hpp index d6db58a..1496490 100644 --- a/include/open_atmos/types.hpp +++ b/include/open_atmos/types.hpp @@ -8,6 +8,8 @@ #include #include #include +#include + namespace open_atmos { @@ -240,7 +242,7 @@ namespace open_atmos /// @brief A list of products std::vector products; /// @brief Optional ion pairs - std::array ion_pair; + std::optional> ion_pair; /// @brief Pre-exponential factor (s-1) double A{ 1 }; /// @brief A constant diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 861f1b9..7d6e7e3 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -5,7 +5,7 @@ configure_file(version.hpp.in ${PROJECT_SOURCE_DIR}/include/open_atmos/mechanism add_library(mechanism_configuration) add_library(open_atmos::mechanism_configuration ALIAS mechanism_configuration) -target_compile_features(mechanism_configuration PUBLIC cxx_std_20) +target_compile_features(mechanism_configuration PUBLIC cxx_std_17) target_sources(mechanism_configuration PRIVATE diff --git a/src/parser.cpp b/src/parser.cpp index cd4d21a..c6e753b 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -32,6 +32,7 @@ namespace open_atmos case ConfigParseStatus::UnknownPhase: return "UnknownPhase"; case ConfigParseStatus::RequestedAerosolSpeciesNotIncludedInAerosolPhase: return "RequestedAerosolSpeciesNotIncludedInAerosolPhase"; case ConfigParseStatus::TooManyReactionComponents: return "TooManyReactionComponents"; + case ConfigParseStatus::InvalidIonPair: return "InvalidIonPair"; default: return "Unknown"; } } @@ -137,7 +138,7 @@ namespace open_atmos // now, anything left must be standard comment starting with __ for (auto& key : remaining) { - if (!key.starts_with("__")) + if (key.find("__") == std::string::npos) { std::cerr << "Non-standard key '" << key << "' found in object" << object << std::endl; @@ -1325,22 +1326,21 @@ namespace open_atmos status = ConfigParseStatus::UnknownPhase; } - 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); - if (status == ConfigParseStatus::Success) { + 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 { - aqueous_equilibrium.ion_pair[0] = first_parse.second; - } - 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[1] = second_parse.second; + 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}; + } } } diff --git a/test/unit/test_parse_aqueous_equilibrium.cpp b/test/unit/test_parse_aqueous_equilibrium.cpp index e105c05..b508dfc 100644 --- a/test/unit/test_parse_aqueous_equilibrium.cpp +++ b/test/unit/test_parse_aqueous_equilibrium.cpp @@ -26,8 +26,8 @@ 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[0].species_name, "A"); - EXPECT_EQ(mechanism.reactions.aqueous_equilibrium[0].ion_pair[1].species_name, "B"); + 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,6 +35,7 @@ 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"); @@ -46,30 +47,30 @@ TEST(JsonParser, CanParseValidAqueousEquilibriumReaction) EXPECT_EQ(mechanism.reactions.aqueous_equilibrium[1].products[1].coefficient, 1); } -// TEST(JsonParser, AqueousEquilibriumDetectsUnknownSpecies) -// { -// JsonParser parser; -// auto [status, mechanism] = parser.Parse(std::string("unit_configs/reactions/aqueous_equilibrium/unknown_species.json")); -// EXPECT_EQ(status, ConfigParseStatus::ReactionRequiresUnknownSpecies); -// } +TEST(JsonParser, AqueousEquilibriumDetectsUnknownSpecies) +{ + JsonParser parser; + auto [status, mechanism] = parser.Parse(std::string("unit_configs/reactions/aqueous_equilibrium/unknown_species.json")); + EXPECT_EQ(status, ConfigParseStatus::ReactionRequiresUnknownSpecies); +} -// TEST(JsonParser, AqueousEquilibriumDetectsMutuallyExclusiveOptions) -// { -// JsonParser parser; -// auto [status, mechanism] = parser.Parse(std::string("unit_configs/reactions/aqueous_equilibrium/mutually_exclusive.json")); -// EXPECT_EQ(status, ConfigParseStatus::MutuallyExclusiveOption); -// } +TEST(JsonParser, AqueousEquilibriumDetectsBadReactionComponent) +{ + JsonParser parser; + auto [status, mechanism] = parser.Parse(std::string("unit_configs/reactions/aqueous_equilibrium/bad_reaction_component.json")); + EXPECT_EQ(status, ConfigParseStatus::RequiredKeyNotFound); +} -// TEST(JsonParser, AqueousEquilibriumDetectsBadReactionComponent) -// { -// JsonParser parser; -// auto [status, mechanism] = parser.Parse(std::string("unit_configs/reactions/aqueous_equilibrium/bad_reaction_component.json")); -// EXPECT_EQ(status, ConfigParseStatus::RequiredKeyNotFound); -// } +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, AqueousEquilibriumDetectsUnknownPhase) -// { -// JsonParser parser; -// auto [status, mechanism] = parser.Parse(std::string("unit_configs/reactions/aqueous_equilibrium/missing_phase.json")); -// EXPECT_EQ(status, ConfigParseStatus::UnknownPhase); -// } \ No newline at end of file +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/unit_configs/reactions/aqueous_equilibrium/bad_reaction_component.json b/test/unit/unit_configs/reactions/aqueous_equilibrium/bad_reaction_component.json index 97197b6..03f3729 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 @@ -7,29 +7,49 @@ }, { "name": "B" + }, + { + "name": "C" + }, + { + "name": "H2O_aq" } ], "phases": [ { - "name": "gas", + "name": "aerosol", "species": [ "A", - "B" + "B", + "C", + "H2O_aq" ] } ], "reactions": [ { - "type": "ARRHENIUS", - "gas phase": "gas", + "type": "AQUEOUS_EQUILIBRIUM", + "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" + "Species name": "A", + "coefficient": 2 } ], "products": [ { - "species name": "B" + "Species name": "B", + "coefficient": 1 + }, + { + "Species name": "C", + "coefficient": 1 } ] } diff --git a/test/unit/unit_configs/reactions/aqueous_equilibrium/invalid_ion_pair.json b/test/unit/unit_configs/reactions/aqueous_equilibrium/invalid_ion_pair.json new file mode 100644 index 0000000..936b7a4 --- /dev/null +++ b/test/unit/unit_configs/reactions/aqueous_equilibrium/invalid_ion_pair.json @@ -0,0 +1,57 @@ +{ + "version": "1.0.0", + "name": "Valid aqueous equilibrium", + "species": [ + { + "name": "A" + }, + { + "name": "B" + }, + { + "name": "C" + }, + { + "name": "H2O_aq" + } + ], + "phases": [ + { + "name": "aerosol", + "species": [ + "A", + "B", + "C", + "H2O_aq" + ] + } + ], + "reactions": [ + { + "type": "AQUEOUS_EQUILIBRIUM", + "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", + "coefficient": 2 + } + ], + "products": [ + { + "species name": "B", + "coefficient": 1 + }, + { + "species name": "C", + "coefficient": 1 + } + ] + } + ] +} \ No newline at end of file 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 1bd0485..93d295b 100644 --- a/test/unit/unit_configs/reactions/aqueous_equilibrium/missing_phase.json +++ b/test/unit/unit_configs/reactions/aqueous_equilibrium/missing_phase.json @@ -10,21 +10,36 @@ }, { "name": "C" + }, + { + "name": "H2O_aq" } ], "phases": [ ], "reactions": [ { - "type": "ARRHENIUS", - "gas phase": "gas", + "type": "AQUEOUS_EQUILIBRIUM", + "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" + "species name": "A", + "coefficient": 2 } ], "products": [ { - "species name": "C" + "species name": "B", + "coefficient": 1 + }, + { + "species name": "C", + "coefficient": 1 } ] } diff --git a/test/unit/unit_configs/reactions/aqueous_equilibrium/mutually_exclusive.json b/test/unit/unit_configs/reactions/aqueous_equilibrium/mutually_exclusive.json deleted file mode 100644 index 61db970..0000000 --- a/test/unit/unit_configs/reactions/aqueous_equilibrium/mutually_exclusive.json +++ /dev/null @@ -1,39 +0,0 @@ -{ - "version": "1.0.0", - "name": "Mutually Exclusive", - "species": [ - { - "name": "A" - }, - { - "name": "B" - } - ], - "phases": [ - { - "name": "gas", - "species": [ - "A", - "B" - ] - } - ], - "reactions": [ - { - "type": "ARRHENIUS", - "gas phase": "gas", - "reactants": [ - { - "species name": "A" - } - ], - "products": [ - { - "species name": "B" - } - ], - "C": 10, - "Ea": 0.5 - } - ] -} \ No newline at end of file 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 a92afa3..97d7a81 100644 --- a/test/unit/unit_configs/reactions/aqueous_equilibrium/unknown_species.json +++ b/test/unit/unit_configs/reactions/aqueous_equilibrium/unknown_species.json @@ -11,7 +11,7 @@ ], "phases": [ { - "name": "gas", + "name": "aerosol", "species": [ "A", "B" @@ -20,16 +20,28 @@ ], "reactions": [ { - "type": "ARRHENIUS", - "gas phase": "gas", + "type": "AQUEOUS_EQUILIBRIUM", + "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" + "species name": "A", + "coefficient": 2 } ], "products": [ { - "species name": "C" + "species name": "B", + "coefficient": 1 + }, + { + "species name": "C", + "coefficient": 1 } ] } diff --git a/test/unit/unit_configs/reactions/aqueous_equilibrium/valid.json b/test/unit/unit_configs/reactions/aqueous_equilibrium/valid.json index c63a7dc..758b8ac 100644 --- a/test/unit/unit_configs/reactions/aqueous_equilibrium/valid.json +++ b/test/unit/unit_configs/reactions/aqueous_equilibrium/valid.json @@ -8,6 +8,9 @@ { "name": "B" }, + { + "name": "C" + }, { "name": "H2O_aq" } @@ -18,6 +21,7 @@ "species": [ "A", "B", + "C", "H2O_aq" ] } @@ -58,10 +62,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",