Skip to content

Commit

Permalink
Merge pull request #36 from open-atmos/parse_wet_deposition
Browse files Browse the repository at this point in the history
Parse wet deposition
  • Loading branch information
K20shores authored Jan 23, 2024
2 parents fe81f91 + 5ad59ba commit ef7f3a0
Show file tree
Hide file tree
Showing 11 changed files with 191 additions and 13 deletions.
1 change: 0 additions & 1 deletion examples/full_configuration.json
Original file line number Diff line number Diff line change
Expand Up @@ -358,7 +358,6 @@
},
{
"type": "WET_DEPOSITION",
"gas phase": "gas",
"aerosol phase": "cloud",
"name": "rxn cloud",
"scaling factor": 12.3
Expand Down
12 changes: 12 additions & 0 deletions include/open_atmos/mechanism_configuration/validation.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,12 @@ namespace open_atmos
const std::string FirstOrderLoss_key = "FIRST_ORDER_LOSS";
// also scaling factor

// 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";
Expand Down Expand Up @@ -219,6 +225,12 @@ namespace open_atmos
const std::vector<std::string> optional_keys{ keys.name, keys.scaling_factor };
} first_order_loss;

struct WetDeposition
{
const std::vector<std::string> required_keys{ keys.aerosol_phase, keys.type };
const std::vector<std::string> optional_keys{ keys.name, keys.scaling_factor };
} wet_deposition;

struct HenrysLaw
{
const std::vector<std::string> required_keys{ keys.type, keys.gas_phase, keys.gas_phase_species, keys.aerosol_phase, keys.aerosol_phase_species, keys.aerosol_phase_water };
Expand Down
19 changes: 16 additions & 3 deletions include/open_atmos/types.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,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<ReactionComponent> reactants;
/// @brief A list of products
Expand Down Expand Up @@ -216,7 +216,7 @@ namespace open_atmos
struct Emission
{
/// @brief Scaling factor to apply to user-provided rate constants
double scaling_factor_{ 1.0 };
double scaling_factor{ 1.0 };
/// @brief A list of products
std::vector<ReactionComponent> products;
/// @brief An identifier, optional, uniqueness not enforced
Expand All @@ -230,7 +230,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<ReactionComponent> reactants;
/// @brief An identifier, optional, uniqueness not enforced
Expand All @@ -241,6 +241,18 @@ namespace open_atmos
std::unordered_map<std::string, std::string> 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<std::string, std::string> unknown_properties;
};

struct HenrysLaw
{
/// @brief An identifier, optional, uniqueness not enforced
Expand All @@ -267,6 +279,7 @@ namespace open_atmos
std::vector<types::CondensedPhasePhotolysis> condensed_phase_photolysis;
std::vector<types::Emission> emission;
std::vector<types::FirstOrderLoss> first_order_loss;
std::vector<types::WetDeposition> wet_deposition;
std::vector<types::HenrysLaw> henrys_law;
std::vector<types::Photolysis> photolysis;
std::vector<types::Surface> surface;
Expand Down
65 changes: 62 additions & 3 deletions src/parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1024,7 +1024,7 @@ namespace open_atmos

if (object.contains(validation::keys.scaling_factor))
{
photolysis.scaling_factor_ = object[validation::keys.scaling_factor].get<double>();
photolysis.scaling_factor = object[validation::keys.scaling_factor].get<double>();
}

if (object.contains(validation::keys.name))
Expand Down Expand Up @@ -1213,7 +1213,7 @@ namespace open_atmos

if (object.contains(validation::keys.scaling_factor))
{
emission.scaling_factor_ = object[validation::keys.scaling_factor].get<double>();
emission.scaling_factor = object[validation::keys.scaling_factor].get<double>();
}

if (object.contains(validation::keys.name))
Expand Down Expand Up @@ -1284,7 +1284,7 @@ namespace open_atmos

if (object.contains(validation::keys.scaling_factor))
{
first_order_loss.scaling_factor_ = object[validation::keys.scaling_factor].get<double>();
first_order_loss.scaling_factor = object[validation::keys.scaling_factor].get<double>();
}

if (object.contains(validation::keys.name))
Expand Down Expand Up @@ -1332,6 +1332,55 @@ namespace open_atmos
return { status, first_order_loss };
}

/// @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<ConfigParseStatus, types::WetDeposition>
ParseWetDeposition(const json& object, const std::vector<types::Species> existing_species, const std::vector<types::Phase> 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<double>();
}

if (object.contains(validation::keys.name))
{
wet_deposition.name = object[validation::keys.name].get<std::string>();
}

auto comments = GetComments(object, validation::wet_deposition.required_keys, validation::wet_deposition.optional_keys);

std::unordered_map<std::string, std::string> 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>();

// 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
Expand Down Expand Up @@ -1528,6 +1577,16 @@ namespace open_atmos
}
reactions.first_order_loss.push_back(first_order_loss_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);
Expand Down
1 change: 1 addition & 0 deletions test/unit/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ create_standard_test(NAME parse_species SOURCES test_parse_species.cpp)
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_wet_deposition SOURCES test_parse_wet_deposition.cpp)

################################################################################
# Copy test data
Expand Down
4 changes: 2 additions & 2 deletions test/unit/test_parse_emission.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,15 @@ 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);
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].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);
Expand Down
4 changes: 2 additions & 2 deletions test/unit/test_parse_first_order_loss.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,15 @@ 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);
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].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);
Expand Down
4 changes: 2 additions & 2 deletions test/unit/test_parse_photolysis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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);
Expand Down
31 changes: 31 additions & 0 deletions test/unit/test_parse_wet_deposition.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#include <gtest/gtest.h>

#include <open_atmos/mechanism_configuration/parser.hpp>

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);
}
24 changes: 24 additions & 0 deletions test/unit/unit_configs/reactions/wet_deposition/missing_phase.json
Original file line number Diff line number Diff line change
@@ -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"
}
]
}
39 changes: 39 additions & 0 deletions test/unit/unit_configs/reactions/wet_deposition/valid.json
Original file line number Diff line number Diff line change
@@ -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"
}
]
}

0 comments on commit ef7f3a0

Please sign in to comment.