Add emissions configuration schema (inventories, species maps, sources) to mechanism v1#281
Conversation
Adds a new emissions configuration schema under mechanism_configuration::emissions::v1, parallel to the existing chemistry schema. This is the MC side of the MIEM config pipeline described in NCAR/miem#272. New public API: ParseEmissions(path) / ParseEmissions(string) → std::expected<EmissionsConfig, Errors> EmissionsConfig holds inventories, species maps, regridding settings, and a list of SourceDescriptors. Musica's translator will resolve these into miem::Source structs and drive miem::EmissionsBuilder. Load-time validation covers all v1 invariants: kind/version dispatch, cross-reference checks (inventory and species map names), duplicate source names, duplicate (category, hierarchy) pairs, scaling factor sums ≤ 1.0, and hard rejections for mode: online, vertical injection: plume, and regridding type: scrip (none supported in v1). Note for MC maintainers: yaml-cpp is currently linked PUBLIC in src/CMakeLists.txt, which causes it to leak into downstream consumers. Demoting it to PRIVATE (and moving the three public headers that include yaml-cpp into src/internal/) would be a clean follow-up. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #281 +/- ##
==========================================
+ Coverage 88.93% 88.96% +0.03%
==========================================
Files 38 39 +1
Lines 1627 1949 +322
==========================================
+ Hits 1447 1734 +287
- Misses 180 215 +35
🚀 New features to boost your workflow:
|
|
Next steps (for context)... This PR is the first of three pieces. Once merged, the plan is:
Flagging so reviewers know the public types in |
K20shores
left a comment
There was a problem hiding this comment.
We want the description of emissions to be agnostic of the miem tool. I think it would be better to include a new section in the mechanism object called Emissions and put all created structs into that.
This would mean our v1.x format would have a new keyword, emissions, which essentially takes lines 5-end of examples/emissions/v1/emissions.yaml and indents it under the emissions key.
I guess I'll think about this a bit longer before adding more specific comments.
boulderdaze
left a comment
There was a problem hiding this comment.
Would you mind updating the PR title? We include PR titles in the release notes, so we prefer them to be more descriptive and easier to read
Aligns with the library convention where all public headers live directly under include/mechanism_configuration/ without a version subdirectory. The v1 version is still expressed in the namespace and source layout. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…er, or file Addresses K20shores' review of #281: - Emissions types moved into mechanism_configuration::types (types.hpp) - EmissionsConfig added as std::optional<types::EmissionsConfig> on Mechanism - emissions: key parsed as an optional section by the main v1 Parse() call - Standalone ParseEmissions() API and emissions::v1 namespace removed - data_root and shell expansion dropped for JSON parity - Examples updated: emissions.yaml gone; full_configuration.yaml gains an emissions: section - Tests routed through Parse() instead of the old standalone parser Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The public Parse() only accepted a filesystem::path, so passing a std::string content literal silently converted to a path and failed with FileNotFound. Dispatches to v1::Parser for version 1 documents. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ser for string tests
ResolveFileConfig only forwarded species/phases/reactions into the
combined node; the emissions: map was silently dropped so file-based
parses never saw it. Added explicit copy of the emissions key alongside
the existing version/name handling.
Reverted the public Parse(std::string) overload added in the previous
commit — it broke existing callers that passed std::string file paths
(they started routing to the content parser instead of the path
parser). String-based emission tests now use v1::Parser{} directly,
consistent with how the existing integration tests work.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
K20shores
left a comment
There was a problem hiding this comment.
Getting there, a couple of more changes. We also need to be able to call Validate and have the emissions be checked. It would be nice. After adding the validation code (which probably involves expanding the semantic refernces to work with emissions) please also update test/unit/test_validate.cpp so that it does an in-code check of emissions
… check emissions in Validate() Addresses K20shores' second review round on #281: - inventories/species maps changed from YAML-key-is-name maps to lists of objects with an explicit `name` field; Inventory/SpeciesMap structs gained a name field and EmissionsConfig fields moved from unordered_map to vector to match - Emissions parsing moved out of src/v1/parser.cpp into its own src/detail/v1/emissions_parser.hpp + src/v1/emissions_parser.cpp, mirroring the existing CheckXSchema/ParseX split used by species/phases/reactions - Parser::Build() no longer takes an emissions parameter; emissions are parsed and assigned after Build() in ValidateAndBuild - Validate() now checks emissions semantics (duplicate inventory/ species-map/source names, duplicate (category, hierarchy) pairs, unknown inventory/species-map references, scaling-factor sums) for in-code Mechanisms, not just YAML parses — extended semantics::Input with EmissionsRef/SpeciesMapRef/SourceRef and added the checks to ValidateSemantics. This also tightens behavior: a source referencing an unknown inventory/species-map is now always rejected, even when the inventories/species maps section is entirely absent (previously silently accepted in that case) - full_configuration.json gained a matching emissions block (had none before); full_configuration.yaml and all emissions test fixtures updated to the new list shape - test_validate.cpp gained 9 in-code emissions cases Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
|
Re: needing One deliberate tightening worth flagging: a source referencing an unknown inventory/species-map is now always rejected, even if that section is entirely absent from the config. Previously that combination silently passed. Let me know if you'd rather it stay permissive there. |
boulderdaze
left a comment
There was a problem hiding this comment.
Looks good to me. I don't have any additional comments beyond the ones already mentioned
K20shores
left a comment
There was a problem hiding this comment.
This seems good to me. I think in the future we may add some validation to check that species are mapped to valid species defined in the mechanism, but we probably don't need to require that check yet. This looks good to me
Resolves the include-order conflict in src/v1/parser.cpp and adds the detail/error_format.hpp include to emissions_parser.cpp, which was added on this branch before main's ErrorLocation formatter was moved out of the public errors.hpp header.
|
Merged main into this branch to resolve the conflict that popped up after approval — it was trivial: both branches had added a new That merge also pulled in main's refactor moving the |
|
Thank you both @boulderdaze @K20shores for reviewing this one! |
Summary
Closes #272.
Adds a new
emissions::v1namespace to MechanismConfiguration thatparses YAML-based emissions configs for consumption by MUSICA/MIEM.
What's new
include/mechanism_configuration/emissions/v1/types.hpp— public types(
EmissionsConfig,SourceDescriptor,Inventory,SpeciesMap, etc.)include/mechanism_configuration/emissions/v1/parse.hpp— public API:ParseEmissions(path)andParseEmissions(string)src/emissions/v1/parser.cpp— full implementation (yaml-cpp private,not exposed in headers); supports
${VAR}/${VAR:-default}env varexpansion in
data rootErrorCodevalues inerrors.hpp/errors.cpphandling
Design notes
Follows the existing v1 chemistry parser pattern:
std::expected<T, Errors>return type,
ErrorCodeenum errors, yaml-cpp kept private to the library.Three intentional differences from the MICM parser shape are noted for
reviewers:
Parse(YAML::Node)overload — emissions configs are always file/stringentry points
CheckSchema()/Build()split — validation and constructionare a single pass
emissions::v1::types(deeper namespace) to avoid collisionwith
mechanism_configuration::typesAside for MC maintainers
While reviewing this I noticed that yaml-cpp headers currently leak into
MC's public headers in a few places (direct
YAML::Nodeparameters onpublic APIs). This isn't blocking for MIEM (MIEM only links against MUSICA,
not MC directly), but it could cause issues for downstream consumers. Flagging
here in case the maintainers want to address it in a follow-up.
Test plan
-DMECH_CONFIG_USE_FMT=ON(Intel LLVM,no
<format>header)