Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
54d39e6
clean up the config file for cloud chemistry
boulderdaze Jun 23, 2026
d8a9d51
distinguish between micm arrhenius and miam arrhneius
boulderdaze Jun 23, 2026
e6a6f30
add miam struct and keys
boulderdaze Jun 24, 2026
5bee7cb
code cleanup
boulderdaze Jun 24, 2026
d2e6a89
Update test/integration/integration_configs/cam_clound_chemistry.json
boulderdaze Jun 24, 2026
8f57804
add headers
boulderdaze Jun 24, 2026
65cd40e
Merge branch '271-add-miam-config' into 271-add-miam-parser
boulderdaze Jun 24, 2026
8ad3b8c
merge main
boulderdaze Jun 24, 2026
557d8b2
Add parsers
boulderdaze Jun 24, 2026
0fb6d3d
replace species with name to reuse the general parser
boulderdaze Jun 25, 2026
01629df
remove duplicate functions
boulderdaze Jun 26, 2026
b3b4b01
gas diffusion coefficient
boulderdaze Jun 26, 2026
cd913cc
support reading diffusion coefficieint form phases species
boulderdaze Jun 26, 2026
f4033f5
support reading solvent molecular weight and density
boulderdaze Jun 26, 2026
4f27093
add integration test
boulderdaze Jun 26, 2026
8d72d0f
remove unit
boulderdaze Jun 26, 2026
a904c87
add validation for aerosol
boulderdaze Jun 26, 2026
26edebd
flattening aerosol into semantics input
boulderdaze Jun 26, 2026
c334c5a
density should be onwed by species, not phase species
boulderdaze Jun 26, 2026
15180e9
differentiate validate gas/aerosol
boulderdaze Jun 26, 2026
9336659
code clean up after adding validation for aerosol
boulderdaze Jun 26, 2026
09287c7
construct aerosol instead of constructing representation and processe…
boulderdaze Jun 27, 2026
170833b
code clean up
boulderdaze Jun 27, 2026
534eabb
add unit tests
boulderdaze Jun 27, 2026
238ca18
cleanup comments
boulderdaze Jun 27, 2026
8f0fe4e
resolve merge conflict
boulderdaze Jul 6, 2026
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
Original file line number Diff line number Diff line change
Expand Up @@ -95,12 +95,12 @@
"condensed phase": "AQUEOUS",
"solvent": "H2O",
"reactants": [
{ "species": "HSO3m", "coefficient": 1 },
{ "species": "H2O2", "coefficient": 1 }
{ "name": "HSO3m", "coefficient": 1 },
{ "name": "H2O2", "coefficient": 1 }
],
"products": [
{ "species": "SO2OOHm", "coefficient": 1 },
{ "species": "H2O", "coefficient": 1 }
{ "name": "SO2OOHm", "coefficient": 1 },
{ "name": "H2O", "coefficient": 1 }
],
"forward rate constants": {
"CLOUD": { "type": "ARRHENIUS", "A": 3.184e8, "C": 4430.0 }
Expand All @@ -116,11 +116,11 @@
"condensed phase": "AQUEOUS",
"solvent": "H2O",
"reactants": [
{ "species name": "SO2OOHm", "coefficient": 1 },
{ "species name": "Hp", "coefficient": 1 }
{ "name": "SO2OOHm", "coefficient": 1 },
{ "name": "Hp", "coefficient": 1 }
],
"products": [
{ "species name": "SO4mm", "coefficient": 1 }
{ "name": "SO4mm", "coefficient": 1 }
],
"rate constants": {
"CLOUD": { "type": "ARRHENIUS", "A": 1.333e8, "C": 4430.0}
Expand All @@ -132,11 +132,11 @@
"condensed phase": "AQUEOUS",
"solvent": "H2O",
"reactants": [
{ "species": "H2O", "coefficient": 2 }
{ "name": "H2O", "coefficient": 2 }
],
"products": [
{ "species": "Hp", "coefficient": 1 },
{ "species": "OHm", "coefficient": 1 }
{ "name": "Hp", "coefficient": 1 },
{ "name": "OHm", "coefficient": 1 }
],
"algebraic species": "OHm",
"equilibrium constant": {
Expand All @@ -149,11 +149,11 @@
"condensed phase": "AQUEOUS",
"solvent": "H2O",
"reactants": [
{ "species": "SO2", "coefficient": 1 }
{ "name": "SO2", "coefficient": 1 }
],
"products": [
{ "species": "Hp", "coefficient": 1 },
{ "species": "HSO3m", "coefficient": 1 }
{ "name": "Hp", "coefficient": 1 },
{ "name": "HSO3m", "coefficient": 1 }
],
"algebraic species": "HSO3m",
"equilibrium constant": {
Expand All @@ -167,11 +167,11 @@
"algebraic species": "SO3mm",
"solvent": "H2O",
"reactants": [
{ "species": "HSO3m", "coefficient": 1 }
{ "name": "HSO3m", "coefficient": 1 }
],
"products": [
{ "species": "Hp", "coefficient": 1 },
{ "species": "SO3mm", "coefficient": 1 }
{ "name": "Hp", "coefficient": 1 },
{ "name": "SO3mm", "coefficient": 1 }
],
"equilibrium constant": {
"type": "ARRHENIUS_REFERENCE_TEMPERATURE", "A": 1.08e-9, "C [K]": 1120.0, "T0 [K]": 298.15
Expand All @@ -184,11 +184,11 @@
"algebraic species": "SO2",
"diagnose from state": true,
"terms": [
{ "phase": "gas", "species": "SO2", "coefficient": 1.0 },
{ "phase": "AQUEOUS", "species": "SO2", "coefficient": 1.0 },
{ "phase": "AQUEOUS", "species": "HSO3m", "coefficient": 1.0 },
{ "phase": "AQUEOUS", "species": "SO3mm", "coefficient": 1.0 },
{ "phase": "AQUEOUS", "species": "SO2OOHm", "coefficient": 1.0 }
{ "phase": "gas", "name": "SO2", "coefficient": 1.0 },
{ "phase": "AQUEOUS", "name": "SO2", "coefficient": 1.0 },
{ "phase": "AQUEOUS", "name": "HSO3m", "coefficient": 1.0 },
{ "phase": "AQUEOUS", "name": "SO3mm", "coefficient": 1.0 },
{ "phase": "AQUEOUS", "name": "SO2OOHm", "coefficient": 1.0 }
]
},
{
Expand All @@ -198,8 +198,8 @@
"algebraic species": "H2O2",
"diagnose from state": true,
"terms": [
{ "phase": "gas", "species": "H2O2", "coefficient": 1.0 },
{ "phase": "AQUEOUS", "species": "H2O2", "coefficient": 1.0 }
{ "phase": "gas", "name": "H2O2", "coefficient": 1.0 },
{ "phase": "AQUEOUS", "name": "H2O2", "coefficient": 1.0 }
]
},
{
Expand All @@ -209,8 +209,8 @@
"algebraic species": "O3",
"diagnose from state": true,
"terms": [
{ "phase": "gas", "species": "O3", "coefficient": 1.0 },
{ "phase": "AQUEOUS", "species": "O3", "coefficient": 1.0 }
{ "phase": "gas", "name": "O3", "coefficient": 1.0 },
{ "phase": "AQUEOUS", "name": "O3", "coefficient": 1.0 }
]
},
{
Expand All @@ -220,12 +220,12 @@
"algebraic species": "Hp",
"constant [mol m-3]": 0.0,
"terms": [
{ "phase": "AQUEOUS", "species": "Hp", "coefficient": 1.0 },
{ "phase": "AQUEOUS", "species": "OHm", "coefficient": -1.0 },
{ "phase": "AQUEOUS", "species": "HSO3m", "coefficient": -1.0 },
{ "phase": "AQUEOUS", "species": "SO3mm", "coefficient": -2.0 },
{ "phase": "AQUEOUS", "species": "SO4mm", "coefficient": -2.0 },
{ "phase": "AQUEOUS", "species": "SO2OOHm", "coefficient": -1.0 }
{ "phase": "AQUEOUS", "name": "Hp", "coefficient": 1.0 },
{ "phase": "AQUEOUS", "name": "OHm", "coefficient": -1.0 },
{ "phase": "AQUEOUS", "name": "HSO3m", "coefficient": -1.0 },
{ "phase": "AQUEOUS", "name": "SO3mm", "coefficient": -2.0 },
{ "phase": "AQUEOUS", "name": "SO4mm", "coefficient": -2.0 },
{ "phase": "AQUEOUS", "name": "SO2OOHm", "coefficient": -1.0 }
]
}
]
Expand Down
22 changes: 15 additions & 7 deletions include/mechanism_configuration/aerosol_types.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,6 @@ namespace mechanism_configuration::types
double T0 = 298.15; ///< Reference temperature [K]
};

/// @brief Equilibrium constants use the same reference-temperature form.
using EquilibriumConstant = ArrheniusReferenceTemperature;

/// @brief Henry's law constant: HLC(T) = HLC_ref * exp( C * (1/T - 1/T0) )
/// Same as ArrheniusReferenceTemperature but with the
/// opposite temperature trend (solubility rises as T falls)
Expand Down Expand Up @@ -98,7 +95,7 @@ namespace mechanism_configuration::types
std::map<std::string, RateConstant> forward_rate_constants;
std::map<std::string, RateConstant> reverse_rate_constants;
/// @brief Shared, intrinsic equilibrium constant (NOT per representation).
std::optional<EquilibriumConstant> equilibrium_constant;
std::optional<ArrheniusReferenceTemperature> equilibrium_constant;
};

struct HenryLawPhaseTransfer
Expand All @@ -109,7 +106,6 @@ namespace mechanism_configuration::types
std::string condensed_species;
std::string solvent;
HenryLawConstant henry_law_constant;
HenryLawConstant henry_law_constant;
double diffusion_coefficient; ///< Gas-phase diffusion coefficient [m2 s-1]
double accommodation_coefficient; ///< Mass accommodation coefficient, dimensionless
};
Expand Down Expand Up @@ -139,13 +135,13 @@ namespace mechanism_configuration::types
std::string solvent;
std::vector<ReactionComponent> reactants;
std::vector<ReactionComponent> products;
EquilibriumConstant equilibrium_constant;
ArrheniusReferenceTemperature equilibrium_constant;
};

struct LinearConstraintTerm
{
std::string phase;
std::string species;
std::string name;
double coefficient;
};

Expand All @@ -169,4 +165,16 @@ namespace mechanism_configuration::types

using Constraint = std::variant<HenryLawEquilibrium, DissolvedEquilibrium, LinearConstraint>;

// ----------------------------------------
// Container
// ----------------------------------------

/// @brief Collection of parsed aerosol entries
struct Aerosol
{
std::vector<Representation> representations;
std::vector<Process> processes;
std::vector<Constraint> constraints;
};

} // namespace mechanism_configuration::types
1 change: 1 addition & 0 deletions include/mechanism_configuration/errors.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ namespace mechanism_configuration
ReactionRequiresUnknownSpecies,
UnknownSpecies,
UnknownPhase,
UnknownAerosolRepresentation,
RequestedSpeciesNotRegisteredInPhase,
TooManyReactionComponents,
InvalidVersion,
Expand Down
8 changes: 5 additions & 3 deletions include/mechanism_configuration/mechanism.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

#pragma once

#include <mechanism_configuration/aerosol_types.hpp>
#include <mechanism_configuration/types.hpp>

#include <filesystem>
Expand All @@ -14,9 +15,8 @@

namespace mechanism_configuration
{
// Trying to build on linux for the python release, I learned that glibc had a bug which defined
// a macro called major and minor. This caused a conflict with the Version struct. To fix this, I
// undefine the macros before defining the struct and then redefine them after the struct.
// glibc defines `major` and `minor` as macros, which conflict with the `Version` struct fields.
// Temporarily undefine the macros before the struct definition and restore them afterward.
// https://stackoverflow.com/a/22253389/5217293
#pragma push_macro("major")
#undef major
Expand Down Expand Up @@ -87,6 +87,8 @@ namespace mechanism_configuration
/// @brief Represents a collection of different reaction types, each stored in a vector
/// corresponding to a specific mechanism
types::Reactions reactions;
/// @brief Aerosol representations, processes, and constraints
types::Aerosol aerosol;
/// @brief Version of the mechanism configuration format used, in major.minor.patch format
Version version;
/// @brief Relative tolerance for solver (optional, default: 1e-6)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

#pragma once

#include <mechanism_configuration/aerosol_types.hpp>
#include <mechanism_configuration/errors.hpp>
#include <mechanism_configuration/mechanism.hpp>
#include <mechanism_configuration/parse.hpp>
Expand Down
1 change: 1 addition & 0 deletions include/mechanism_configuration/types.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ namespace mechanism_configuration::types
{
std::string name;
std::optional<double> diffusion_coefficient;
std::optional<double> density;
Comment thread
K20shores marked this conversation as resolved.
/// @brief Unknown properties, prefixed with two underscores (__)
std::unordered_map<std::string, std::string> unknown_properties;
};
Expand Down
43 changes: 31 additions & 12 deletions include/mechanism_configuration/validate.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,15 @@

namespace mechanism_configuration
{
// Intermediate over which all semantic validation runs. Both a parsed document and an
// in-code Mechanism produce one of these and hand it to ValidateSemantics, so the rules
// live in exactly one place. A parsed document fills in source locations (so errors carry
// line:col); an in-code Mechanism leaves them empty. The domain types stay location-free.

// Intermediate over which the core semantic validation (species, phases, gas-phase reactions)
// runs. Both a parsed document and an in-code Mechanism lower into one of these and hand it to
// ValidateSemantics, so those rules live in exactly one place. A parsed document fills in source
// locations (so errors carry line:col); an in-code Mechanism leaves them empty.
//
// Aerosol cross-references are validated separately by ValidateAerosolModel, which works on the
// domain structs directly because it needs phase membership and optional-property values that
// this name-only view cannot carry.
Comment thread
K20shores marked this conversation as resolved.
namespace semantics
{
struct NamedRef
Expand Down Expand Up @@ -79,17 +84,31 @@ namespace mechanism_configuration
std::vector<ReactionRef> reactions;
std::optional<EmissionsRef> emissions; // nullopt only when there's no emissions at all
};

} // namespace semantics

/// @brief The single home for the mechanism's semantic rules. Errors include `line:col`
/// for any element whose source location was supplied.
/// @brief The single home for the core (species / phase / gas-phase reaction) semantic rules.
/// Errors include `line:col` for any element whose source location was supplied.
Errors ValidateSemantics(const semantics::Input& input);

/// @brief Validates the semantic invariants of a canonical Mechanism, independent of how it
/// was produced (parsed from any version, or constructed in code). Convenience wrapper
/// that builds a location-free semantics::Input and calls ValidateSemantics.
///
/// Structural/deserialization concerns (YAML keys, types, formatting) are the responsibility
/// of the version-specific parsers and are not repeated here.
/// @brief Validates a Mechanism's species, phases, and gas-phase reactions by
/// converting them to a location-free semantics::Input and running
/// ValidateSemantics.
Errors ValidateGasModel(const Mechanism& mechanism);

/// @brief Validates aerosol cross-references against the mechanism's species and phases.
///
/// Checks phase/species references, representation-keyed rate-constant maps, and
/// required definition-derived properties. These validations require full domain
/// information unavailable to ValidateSemantics. Returns no errors if the mechanism
/// has no aerosol section.
Errors ValidateAerosolModel(const Mechanism& mechanism);

/// @brief Validates the semantic invariants of a canonical Mechanism, regardless of whether it
/// was parsed or constructed in code. Combines ValidateGasModel and
/// ValidateAerosolModel, returning all validation errors.
///
/// Excludes structural/deserialization validation, which is handled by version-specific parsers.
Errors Validate(const Mechanism& mechanism);

} // namespace mechanism_configuration
8 changes: 5 additions & 3 deletions src/detail/v1/aerosol_keys.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ namespace mechanism_configuration::v1::keys

inline constexpr std::string_view SingleMomentMode_key = "SINGLE_MOMENT_MODE";
inline constexpr std::string_view geometric_mean_radius = "geometric mean radius [m]";
inline constexpr std::string_view geometric_standard_deviation = "geometric standard deviation [-]";
inline constexpr std::string_view geometric_standard_deviation = "geometric standard deviation";

inline constexpr std::string_view TwoMomentMode_key = "TWO_MOMENT_MODE";
// also: geometric_standard_deviation
Expand All @@ -39,6 +39,8 @@ namespace mechanism_configuration::v1::keys
inline constexpr std::string_view equilibrium_constant = "equilibrium constant";
inline constexpr std::string_view reference_temperature = "T0 [K]";

inline constexpr std::string_view ArrheniusReferenceTemperature_key = "ARRHENIUS_REFERENCE_TEMPERATURE";

inline constexpr std::string_view henry_law_constant = "Henry's law constant";
inline constexpr std::string_view HLC_ref = "HLC_ref [mol m-3 Pa-1]";
inline constexpr std::string_view henry_law_C = "C [K]";
Expand All @@ -52,7 +54,7 @@ namespace mechanism_configuration::v1::keys
// also: gas_phase, gas_phase_species, condensed_phase, condensed_phase_species, solvent,
// henry_law_constant, diffusion_coefficient
inline constexpr std::string_view HenryLawPhaseTransfer_key = "HENRY_LAW_PHASE_TRANSFER";
inline constexpr std::string_view accommodation_coefficient = "accommodation coefficient [-]";
inline constexpr std::string_view accommodation_coefficient = "accommodation coefficient";

// DissolvedReaction
// also: condensed_phase, solvent, reactants, products, rate_constants
Expand All @@ -79,7 +81,7 @@ namespace mechanism_configuration::v1::keys
inline constexpr std::string_view algebraic_species = "algebraic species";

// LinearConstraint
// also: name; terms carry coefficient and species
// also: name; terms carry coefficient and name
inline constexpr std::string_view LinearConstraint_key = "LINEAR_CONSTRAINT";
inline constexpr std::string_view algebraic_phase = "algebraic phase";
inline constexpr std::string_view terms = "terms";
Expand Down
Loading
Loading