Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Parse wet deposition #36

Merged
merged 3 commits into from
Jan 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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"
}
]
}
Loading