From a31dda453fc618e62fbff68de9e122c502efa6f4 Mon Sep 17 00:00:00 2001 From: Kevin Nobel Date: Wed, 6 May 2026 08:20:21 +0000 Subject: [PATCH 1/2] Implement encoding for currently known atmospheric composition fields - Add handling of atmospheric composition params in composition concept - Add new atmospheric composition params to point-in-time and level matchers - Add chemId deduction - Add firstWavelength deduction - Remove constituentType deduction --- .../composition/compositionEncoding.h | 35 +++-- .../concepts/composition/compositionMatcher.h | 78 +++++++++- .../backend/concepts/level/levelMatcher.h | 10 +- .../point-in-time/pointInTimeMatcher.h | 2 +- .../{constituentType.h => chemId.h} | 72 ++++----- .../backend/deductions/firstWavelength.h | 145 ++++++++++++++++++ .../docs/doxygen/mars2grib.config.in | 3 +- .../section-recipes/impl/section4Recipes.h | 11 +- 8 files changed, 286 insertions(+), 70 deletions(-) rename src/metkit/mars2grib/backend/deductions/{constituentType.h => chemId.h} (56%) create mode 100644 src/metkit/mars2grib/backend/deductions/firstWavelength.h diff --git a/src/metkit/mars2grib/backend/concepts/composition/compositionEncoding.h b/src/metkit/mars2grib/backend/concepts/composition/compositionEncoding.h index 6a997cc1..228671e7 100644 --- a/src/metkit/mars2grib/backend/concepts/composition/compositionEncoding.h +++ b/src/metkit/mars2grib/backend/concepts/composition/compositionEncoding.h @@ -48,7 +48,8 @@ #include "metkit/mars2grib/utils/generalUtils.h" // Deductions -#include "metkit/mars2grib/backend/deductions/constituentType.h" +#include "metkit/mars2grib/backend/deductions/chemId.h" +#include "metkit/mars2grib/backend/deductions/firstWavelength.h" // Utils #include "metkit/config/LibMetkit.h" @@ -134,6 +135,7 @@ template void CompositionOp(const MarsDict_t& mars, const ParDict_t& par, const OptDict_t& opt, OutDict_t& out) { + using metkit::mars2grib::utils::dict_traits::get_or_throw; using metkit::mars2grib::utils::dict_traits::set_or_throw; using metkit::mars2grib::utils::exceptions::Mars2GribConceptException; @@ -143,25 +145,32 @@ void CompositionOp(const MarsDict_t& mars, const ParDict_t& par, const OptDict_t MARS2GRIB_LOG_CONCEPT(composition); - // ============================================================= - // Structural validation - // ============================================================= - /// @todo [owner: dgov][scope: concept][reason: completeness][prio: low] + // NOTE : Can also simply check if chemId is present, and if wavelength is present and set it. - // ============================================================= - // Variant-specific logic - // ============================================================= - if constexpr (Variant == CompositionType::Chem) { + if constexpr (Variant == CompositionType::AerosolOptical) { - // Structural validation - /// @todo [owner: dgov][scope: concept][reason: completeness][prio: low] + // Deductions + const auto chemId = deductions::resolve_ChemId_or_throw(mars, par, opt); + const auto firstWavelength = deductions::resolve_FirstWavelength_or_throw(mars, par, opt); + + // Encoding + set_or_throw(out, "enableChemSplit", true); + set_or_throw(out, "chemId", chemId); + set_or_throw(out, "firstWavelength", firstWavelength); + } + else if constexpr (Variant == CompositionType::Chem || Variant == CompositionType::Aerosol || Variant == CompositionType::ChemicalSource) { // Deductions - long constituentType = deductions::resolve_ConstituentType_or_throw(mars, par, opt); + const auto chemId = deductions::resolve_ChemId_or_throw(mars, par, opt); // Encoding - set_or_throw(out, "constituentType", constituentType); + set_or_throw(out, "enableChemSplit", true); + set_or_throw(out, "chemId", chemId); + } + else { + MARS2GRIB_CONCEPT_THROW(composition, "Concept variant is not implemented!"); } + } catch (...) { diff --git a/src/metkit/mars2grib/backend/concepts/composition/compositionMatcher.h b/src/metkit/mars2grib/backend/concepts/composition/compositionMatcher.h index 2a657c97..9365987a 100644 --- a/src/metkit/mars2grib/backend/concepts/composition/compositionMatcher.h +++ b/src/metkit/mars2grib/backend/concepts/composition/compositionMatcher.h @@ -7,22 +7,90 @@ #include "metkit/mars2grib/backend/concepts/composition/compositionEnum.h" #include "metkit/mars2grib/utils/dictionary_traits/dictionary_access_traits.h" #include "metkit/mars2grib/utils/generalUtils.h" +#include "metkit/mars2grib/utils/mars2gribExceptions.h" +#include "metkit/mars2grib/utils/paramMatcher.h" namespace metkit::mars2grib::backend::concepts_ { template std::size_t compositionMatcher(const MarsDict_t& mars, const OptDict_t& opt) { + using metkit::mars2grib::util::param_matcher::matchAny; + using metkit::mars2grib::util::param_matcher::range; + using metkit::mars2grib::utils::dict_traits::get_opt; + using metkit::mars2grib::utils::dict_traits::get_or_throw; using metkit::mars2grib::utils::dict_traits::has; + using metkit::mars2grib::utils::exceptions::Mars2GribMatcherException; - if (has(mars, "chem")) { - return static_cast(CompositionType::Chem); + const auto param = get_or_throw(mars, "param"); + + // TODO: This is the range for CAMS, there are some unmapped parameters that may need to be supported for ERA6, etc. + if (param < 400000 || param >= 500000) { + return compile_time_registry_engine::MISSING; } - if (has(mars, "wavelength")) { - return static_cast(CompositionType::Aerosol); + const auto chem = get_or_throw(mars, "chem"); + const auto hasWavelength = has(mars, "wavelength"); + + if (hasWavelength) { + if (matchAny(param, 457000)) { + if (matchAny(chem, range(900, 914), 918, 922, 923, range(933, 936))) { + return static_cast(CompositionType::AerosolOptical); + } + } else if (matchAny(param, 458000, 459000, 460000, 461000, 462000, 472000)) { + if (matchAny(chem, 922)) { + return static_cast(CompositionType::AerosolOptical); + } + } + } else { + if (matchAny(param, 401000)) { + if (matchAny(chem, range(900, 916))) { + return static_cast(CompositionType::Aerosol); + } + if (matchAny(chem, 2, 3, range(5, 24), range(26, 30), range(32, 50), 52, 53, range(55, 58), range(63, 80), 82, 83, 85, 86, range(99, 101), 107, 112, 159, 161, 169, range(173, 178), range(186, 204), 222, range(224, 231), 233, 311, 359, 404, 917)) { + return static_cast(CompositionType::Chem); + } + } else if (matchAny(param, 402000)) { + if (matchAny(chem, range(900, 917), 924)) { + return static_cast(CompositionType::Aerosol); + } + if (matchAny(chem, range(2, 24), range(26, 30), range(32, 50), 52, 53, range(55, 59), range(63, 80), 82, 83, 85, 86, range(99, 101), 107, 112, 118, 159, 161, 169, range(173, 178), range(186, 204), 222, range(224, 230), 233, 236, 311)) { + return static_cast(CompositionType::Chem); + } + } else if (matchAny(param, 406000, 407000, 410000, 411000, 451000)) { + if (matchAny(chem, range(901, 916))) { + return static_cast(CompositionType::Aerosol); + } + } else if (matchAny(param, 453000)) { + if (matchAny(chem, range(901, 916), 922)) { + return static_cast(CompositionType::Aerosol); + } + } else if (matchAny(param, 400000)) { + if (matchAny(chem, range(929, 931))) { + return static_cast(CompositionType::Aerosol); + } + } else if (matchAny(param, 444000)) { + if (matchAny(chem, 6, 8, 13, 15, 17, 19, 26, 27, 33)) { + return static_cast(CompositionType::Chem); + } + } else if (matchAny(param, 445000)) { + if (matchAny(chem, 6, 8, 13, 15, 17, 19, 27, 33, 236)) { + return static_cast(CompositionType::Chem); + } + } else if (matchAny(param, 479000)) { + if (matchAny(chem, 404)) { + return static_cast(CompositionType::Chem); + } + } else if (matchAny(param, 469000)) { + if (matchAny(chem, 2, 5, 9, 10, 12, 16, 18, 19, 42, range(45, 48), 52, 99, 100, 129, 224, 226, 233, 311, 933, 934)) { + return static_cast(CompositionType::ChemicalSource); + } + } } - return compile_time_registry_engine::MISSING; + throw Mars2GribMatcherException( + "compositionMatcher: matching logic is not implemented for param=" + std::to_string(param) + + ", chem=" + std::to_string(chem) + ", hasWavelength=" + (hasWavelength ? "true" : "false"), + Here()); } } // namespace metkit::mars2grib::backend::concepts_ diff --git a/src/metkit/mars2grib/backend/concepts/level/levelMatcher.h b/src/metkit/mars2grib/backend/concepts/level/levelMatcher.h index 3d23158c..1f1dd519 100644 --- a/src/metkit/mars2grib/backend/concepts/level/levelMatcher.h +++ b/src/metkit/mars2grib/backend/concepts/level/levelMatcher.h @@ -132,7 +132,7 @@ inline std::size_t matchSFC(const long param) { } // Chemical - if (matchAny(param, range(228080, 228085), range(233032, 233035), range(235062, 235064))) { + if (matchAny(param, range(228080, 228085), range(233032, 233035), range(235062, 235064), range(400000, 499999))) { return static_cast(LevelType::Surface); } @@ -163,7 +163,7 @@ inline std::size_t matchML(const long param) { using metkit::mars2grib::util::param_matcher::range; if (matchAny(param, range(21, 23), range(75, 77), range(129, 133), 135, 138, 152, range(155, 157), 203, - range(246, 248), range(162100, 162113), 260290, 260292, 260293)) { + range(246, 248), range(162100, 162113), 260290, 260292, 260293, range(400000, 499999))) { return static_cast(LevelType::Hybrid); } @@ -176,7 +176,7 @@ inline std::size_t matchPL(const long param, const long level) { using metkit::mars2grib::util::param_matcher::range; if (matchAny(param, 1, 2, 10, 60, 75, 76, range(129, 135), 138, 152, range(155, 157), 203, range(246, 248), 235100, - range(235129, 235133), 235135, 235138, 235152, 235155, 235157, 235203, 235246, 260290, 263107)) { + range(235129, 235133), 235135, 235138, 235152, 235155, 235157, 235203, 235246, 260290, 263107, range(400000, 499999))) { if (level >= 100) { return static_cast(LevelType::IsobaricInHpa); } @@ -193,7 +193,7 @@ inline std::size_t matchPT(const long param) { using metkit::mars2grib::util::param_matcher::matchAny; using metkit::mars2grib::util::param_matcher::range; - if (matchAny(param, 53, 54, 60, range(131, 133), 138, 155, 203, 235100, 235203, 237203, 238203, 239203)) { + if (matchAny(param, 53, 54, 60, range(131, 133), 138, 155, 203, 235100, 235203, 237203, 238203, 239203, range(400000, 499999))) { return static_cast(LevelType::Theta); } @@ -206,7 +206,7 @@ inline std::size_t matchPV(const long param) { using metkit::mars2grib::util::param_matcher::matchAny; using metkit::mars2grib::util::param_matcher::range; - if (matchAny(param, 3, 54, 129, range(131, 133), 203, 235098, 235269)) { + if (matchAny(param, 3, 54, 129, range(131, 133), 203, 235098, 235269, range(400000, 499999))) { return static_cast(LevelType::PotentialVorticity); } diff --git a/src/metkit/mars2grib/backend/concepts/point-in-time/pointInTimeMatcher.h b/src/metkit/mars2grib/backend/concepts/point-in-time/pointInTimeMatcher.h index 85fc7b42..17c546b8 100644 --- a/src/metkit/mars2grib/backend/concepts/point-in-time/pointInTimeMatcher.h +++ b/src/metkit/mars2grib/backend/concepts/point-in-time/pointInTimeMatcher.h @@ -49,7 +49,7 @@ std::size_t pointInTimeMatcher(const MarsDict_t& mars, const OptDict_t& opt) { } // Chemical products - if (matchAny(param, range(228083, 228085))) { + if (matchAny(param, range(228083, 228085), range(400000, 499999))) { return static_cast(PointInTimeType::Default); } diff --git a/src/metkit/mars2grib/backend/deductions/constituentType.h b/src/metkit/mars2grib/backend/deductions/chemId.h similarity index 56% rename from src/metkit/mars2grib/backend/deductions/constituentType.h rename to src/metkit/mars2grib/backend/deductions/chemId.h index 5d49b5f5..d08e2fcb 100644 --- a/src/metkit/mars2grib/backend/deductions/constituentType.h +++ b/src/metkit/mars2grib/backend/deductions/chemId.h @@ -1,5 +1,5 @@ /* - * (C) Copyright 2025- ECMWF and individual contributors. + * (C) Copyright 2026- ECMWF and individual contributors. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. @@ -9,29 +9,28 @@ */ /// -/// @file constituentType.h -/// @brief Deduction of the constituent (chemical species) type identifier. +/// @file chemId.h +/// @brief Deduction of the chemical identifier for composition encoding. /// /// This header defines deduction utilities used by the mars2grib backend -/// to resolve the **constituent / chemical species identifier** from -/// MARS metadata. +/// to resolve the **chemical identifier** from MARS metadata. /// /// The deduction retrieves the identifier directly from the MARS -/// dictionary and performs basic numeric validation before exposing -/// the value to the encoding layer. +/// dictionary and exposes it to the encoding layer without +/// transformation or interpretation. /// /// Deductions are responsible for: /// - extracting values from MARS, parameter, and option dictionaries -/// - applying explicit and minimal validation logic +/// - applying minimal, explicit deduction logic /// - returning strongly typed values to concept operations /// /// Deductions: /// - do NOT encode GRIB keys directly -/// - do NOT apply semantic inference or defaulting +/// - do NOT apply inference, defaulting, or consistency checks /// - do NOT perform GRIB table validation /// /// Error handling follows a strict fail-fast strategy: -/// - missing or invalid inputs cause immediate failure +/// - missing or malformed inputs cause immediate failure /// - errors are reported using domain-specific deduction exceptions /// - original errors are preserved via nested exception propagation /// @@ -43,9 +42,6 @@ /// Concept: /// - @ref compositionEncoding.h /// -/// Related deductions: -/// - @ref paramId.h -/// /// @ingroup mars2grib_backend_deductions /// #pragma once @@ -62,7 +58,7 @@ namespace metkit::mars2grib::backend::deductions { /// -/// @brief Resolve the constituent (chemical species) type identifier from input dictionaries. +/// @brief Resolve the chemical identifier from input dictionaries. /// /// @section Deduction contract /// - Reads: `mars["chem"]` @@ -70,17 +66,12 @@ namespace metkit::mars2grib::backend::deductions { /// - Side effects: logging (RESOLVE) /// - Failure mode: throws /// -/// This deduction resolves the constituent (chemical species) type -/// identifier by retrieving the mandatory MARS key `chem` and returning -/// its value as a `long`. -/// -/// A basic numeric validity check is applied. Only values in the -/// inclusive range `[0, 900]` are accepted. Values outside this range -/// result in a deduction failure. +/// This deduction resolves the chemical identifier by retrieving +/// the mandatory MARS key `chem` and returning its value as a `long`. /// -/// No semantic interpretation, normalization, or defaulting is applied. -/// The meaning of the identifier is defined by upstream MARS/GRIB -/// conventions. +/// No semantic interpretation, normalization, or validation is performed +/// beyond basic type conversion. The meaning of the chemical identifier is +/// defined by upstream metadata conventions. /// /// @tparam MarsDict_t /// Type of the MARS dictionary. Must support keyed access to `chem` @@ -93,7 +84,7 @@ namespace metkit::mars2grib::backend::deductions { /// Type of the options dictionary (unused by this deduction). /// /// @param[in] mars -/// MARS dictionary from which the constituent type identifier is resolved. +/// MARS dictionary from which the chemical identifier is resolved. /// /// @param[in] par /// Parameter dictionary (unused). @@ -102,50 +93,43 @@ namespace metkit::mars2grib::backend::deductions { /// Options dictionary (unused). /// /// @return -/// The resolved constituent (chemical species) type identifier. +/// The resolved chemical identifier. /// /// @throws metkit::mars2grib::utils::exceptions::Mars2GribDeductionException -/// If the key `chem` is missing, cannot be converted to `long`, if the -/// value is outside the accepted range, or if any unexpected error -/// occurs during deduction. +/// If the key `chem` is missing, cannot be converted to `long`, +/// or if any unexpected error occurs during deduction. /// /// @note -/// This deduction enforces conservative numeric validation and does -/// not consult chemical metadata tables or GRIB code tables. +/// This deduction performs presence-only validation and does not +/// consult chemical metadata or GRIB tables. /// template -long resolve_ConstituentType_or_throw(const MarsDict_t& mars, const ParDict_t& par, const OptDict_t& opt) { +long resolve_ChemId_or_throw(const MarsDict_t& mars, const ParDict_t& par, const OptDict_t& opt) { using metkit::mars2grib::utils::dict_traits::get_or_throw; using metkit::mars2grib::utils::exceptions::Mars2GribDeductionException; try { - // Retrieve mandatory MARS constituent type - long constituentType = get_or_throw(mars, "chem"); - - // Validate - if (constituentType < 0 || constituentType > 900) { - throw Mars2GribDeductionException( - "Invalid `constituentType`: value='" + std::to_string(constituentType) + "'", Here()); - } + // Retrieve mandatory MARS chemical identifier + long chemId = get_or_throw(mars, "chem"); // Emit RESOLVE log entry MARS2GRIB_LOG_RESOLVE([&]() { - std::string logMsg = "`constituentType` resolved from input dictionaries: value='"; - logMsg += std::to_string(constituentType); + std::string logMsg = "`chemId` resolved from input dictionaries: value='"; + logMsg += std::to_string(chemId); logMsg += "'"; return logMsg; }()); // Success exit point - return constituentType; + return chemId; } catch (...) { // Rethrow nested exceptions std::throw_with_nested( - Mars2GribDeductionException("Failed to resolve `constituentType` from input dictionaries", Here())); + Mars2GribDeductionException("Failed to resolve `chemId` from input dictionaries", Here())); }; // Remove compiler warning diff --git a/src/metkit/mars2grib/backend/deductions/firstWavelength.h b/src/metkit/mars2grib/backend/deductions/firstWavelength.h new file mode 100644 index 00000000..dc8cb86e --- /dev/null +++ b/src/metkit/mars2grib/backend/deductions/firstWavelength.h @@ -0,0 +1,145 @@ +/* + * (C) Copyright 2026- ECMWF and individual contributors. + * + * This software is licensed under the terms of the Apache Licence Version 2.0 + * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. + * In applying this licence, ECMWF does not waive the privileges and immunities + * granted to it by virtue of its status as an intergovernmental organisation nor + * does it submit to any jurisdiction. + */ + +/// +/// @file firstWavelength.h +/// @brief Deduction of the first wavelength in meters for composition encoding. +/// +/// This header defines deduction utilities used by the mars2grib backend +/// to resolve the **first wavelength** from MARS metadata. +/// +/// The deduction retrieves the wavelength from the MARS dictionary +/// (expressed in nanometers) and converts it to meters before exposing +/// the value to the encoding layer. +/// +/// Deductions are responsible for: +/// - extracting values from MARS, parameter, and option dictionaries +/// - applying explicit and minimal transformation logic +/// - returning strongly typed values to concept operations +/// +/// Deductions: +/// - do NOT encode GRIB keys directly +/// - do NOT apply inference, defaulting, or consistency checks +/// - do NOT perform GRIB table validation +/// +/// Error handling follows a strict fail-fast strategy: +/// - missing or malformed inputs cause immediate failure +/// - errors are reported using domain-specific deduction exceptions +/// - original errors are preserved via nested exception propagation +/// +/// Logging follows the mars2grib deduction policy: +/// - RESOLVE: value derived via deduction logic from input dictionaries +/// - OVERRIDE: value provided by parameter dictionary overriding deduction logic +/// +/// @section References +/// Concept: +/// - @ref compositionEncoding.h +/// +/// Related deductions: +/// - @ref chemId.h +/// +/// @ingroup mars2grib_backend_deductions +/// +#pragma once + +// System includes +#include + +// Core deduction includes +#include "metkit/config/LibMetkit.h" +#include "metkit/mars2grib/utils/generalUtils.h" +#include "metkit/mars2grib/utils/logUtils.h" +#include "metkit/mars2grib/utils/mars2gribExceptions.h" + +namespace metkit::mars2grib::backend::deductions { + +/// +/// @brief Resolve the first wavelength in meters from input dictionaries. +/// +/// @section Deduction contract +/// - Reads: `mars["wavelength"]` +/// - Writes: none +/// - Side effects: logging (RESOLVE) +/// - Failure mode: throws +/// +/// This deduction resolves the first wavelength by retrieving the +/// mandatory MARS key `wavelength` (expressed in nanometers) and +/// converting it to meters. +/// +/// The conversion follows: +/// \f$ \text{wavelength\_m} = \text{wavelength\_nm} \times 10^{-9} \f$ +/// +/// @tparam MarsDict_t +/// Type of the MARS dictionary. Must support keyed access to `wavelength` +/// and conversion to `long`. +/// +/// @tparam ParDict_t +/// Type of the parameter dictionary (unused by this deduction). +/// +/// @tparam OptDict_t +/// Type of the options dictionary (unused by this deduction). +/// +/// @param[in] mars +/// MARS dictionary from which the wavelength is resolved. +/// +/// @param[in] par +/// Parameter dictionary (unused). +/// +/// @param[in] opt +/// Options dictionary (unused). +/// +/// @return +/// The resolved wavelength in meters as a `double`. +/// +/// @throws metkit::mars2grib::utils::exceptions::Mars2GribDeductionException +/// If the key `wavelength` is missing, cannot be converted to `long`, +/// or if any unexpected error occurs during deduction. +/// +/// @note +/// This deduction assumes that the MARS `wavelength` value is expressed +/// in nanometers. Alternative units are not supported. +/// +template +double resolve_FirstWavelength_or_throw(const MarsDict_t& mars, const ParDict_t& par, const OptDict_t& opt) { + + using metkit::mars2grib::utils::dict_traits::get_or_throw; + using metkit::mars2grib::utils::exceptions::Mars2GribDeductionException; + + try { + + // Retrieve mandatory MARS wavelength (in nanometers) + long wavelengthInNanometers = get_or_throw(mars, "wavelength"); + + // Convert nanometers to meters + double wavelengthInMeters = static_cast(wavelengthInNanometers) / 1000000000.0; + + // Emit RESOLVE log entry + MARS2GRIB_LOG_RESOLVE([&]() { + std::string logMsg = "`firstWavelength` deduced from mars dictionary: "; + logMsg += std::to_string(wavelengthInMeters) + " [meters]"; + logMsg += " (from " + std::to_string(wavelengthInNanometers) + " [nanometers])"; + return logMsg; + }()); + + // Success exit point + return wavelengthInMeters; + } + catch (...) { + + // Rethrow nested exceptions + std::throw_with_nested( + Mars2GribDeductionException("Failed to resolve `firstWavelength` from input dictionaries", Here())); + }; + + // Remove compiler warning + mars2gribUnreachable(); +}; + +} // namespace metkit::mars2grib::backend::deductions diff --git a/src/metkit/mars2grib/docs/doxygen/mars2grib.config.in b/src/metkit/mars2grib/docs/doxygen/mars2grib.config.in index 001b3d7b..4e4bbd70 100644 --- a/src/metkit/mars2grib/docs/doxygen/mars2grib.config.in +++ b/src/metkit/mars2grib/docs/doxygen/mars2grib.config.in @@ -1137,13 +1137,14 @@ INPUT = \@MARS2GRIB_SOURCE_DIRECTORY@/utils/configConverter.h \ @MARS2GRIB_SOURCE_DIRECTORY@/backend/deductions/timeSpanInSeconds.h \ @MARS2GRIB_SOURCE_DIRECTORY@/backend/deductions/systemNumber.h \ @MARS2GRIB_SOURCE_DIRECTORY@/backend/deductions/resolution.h \ -@MARS2GRIB_SOURCE_DIRECTORY@/backend/deductions/constituentType.h \ @MARS2GRIB_SOURCE_DIRECTORY@/backend/deductions/experiment.h \ @MARS2GRIB_SOURCE_DIRECTORY@/backend/deductions/class.h \ @MARS2GRIB_SOURCE_DIRECTORY@/backend/deductions/subSetTrunc.h \ @MARS2GRIB_SOURCE_DIRECTORY@/backend/deductions/timeIncrementInSeconds.h \ @MARS2GRIB_SOURCE_DIRECTORY@/backend/deductions/laplacianOperator.h \ @MARS2GRIB_SOURCE_DIRECTORY@/backend/deductions/channel.h \ +@MARS2GRIB_SOURCE_DIRECTORY@/backend/deductions/chemId.h \ +@MARS2GRIB_SOURCE_DIRECTORY@/backend/deductions/firstWavelength.h \ @MARS2GRIB_SOURCE_DIRECTORY@/backend/deductions/level.h \ @MARS2GRIB_SOURCE_DIRECTORY@/backend/deductions/instrumentType.h \ @MARS2GRIB_SOURCE_DIRECTORY@/backend/deductions/derivedForecast.h \ diff --git a/src/metkit/mars2grib/frontend/resolution/section-recipes/impl/section4Recipes.h b/src/metkit/mars2grib/frontend/resolution/section-recipes/impl/section4Recipes.h index 498d24e6..5305399a 100644 --- a/src/metkit/mars2grib/frontend/resolution/section-recipes/impl/section4Recipes.h +++ b/src/metkit/mars2grib/frontend/resolution/section-recipes/impl/section4Recipes.h @@ -229,6 +229,15 @@ inline const Recipe S4_R78 = Select >(); +inline const Recipe S4_R80 = + make_recipe<79, + Select, + Select, + Select, + Select, + Select + >(); + inline const Recipe S4_R79 = make_recipe<79, Select, @@ -302,7 +311,7 @@ inline const Recipes Section4Recipes{ 4, &S4_R50, &S4_R45, &S4_R46, &S4_R85, &S4_R48, &S4_R49, &S4_R60, &S4_R61, - &S4_R76, &S4_R77, &S4_R78, &S4_R79, + &S4_R76, &S4_R77, &S4_R78, &S4_R79, &S4_R80, &S4_R99, &S4_R100, &S4_R103, &S4_R104, &S4_R142, &S4_R143 From 9dec8757eb7b43b9113ed6bd15a815f333fc550e Mon Sep 17 00:00:00 2001 From: Kevin Nobel Date: Wed, 6 May 2026 08:57:34 +0000 Subject: [PATCH 2/2] Run clang-format --- .../composition/compositionEncoding.h | 6 +-- .../concepts/composition/compositionMatcher.h | 41 +++++++++++++------ .../backend/concepts/level/levelMatcher.h | 6 ++- 3 files changed, 35 insertions(+), 18 deletions(-) diff --git a/src/metkit/mars2grib/backend/concepts/composition/compositionEncoding.h b/src/metkit/mars2grib/backend/concepts/composition/compositionEncoding.h index 228671e7..499c2d8f 100644 --- a/src/metkit/mars2grib/backend/concepts/composition/compositionEncoding.h +++ b/src/metkit/mars2grib/backend/concepts/composition/compositionEncoding.h @@ -158,10 +158,11 @@ void CompositionOp(const MarsDict_t& mars, const ParDict_t& par, const OptDict_t set_or_throw(out, "chemId", chemId); set_or_throw(out, "firstWavelength", firstWavelength); } - else if constexpr (Variant == CompositionType::Chem || Variant == CompositionType::Aerosol || Variant == CompositionType::ChemicalSource) { + else if constexpr (Variant == CompositionType::Chem || Variant == CompositionType::Aerosol || + Variant == CompositionType::ChemicalSource) { // Deductions - const auto chemId = deductions::resolve_ChemId_or_throw(mars, par, opt); + const auto chemId = deductions::resolve_ChemId_or_throw(mars, par, opt); // Encoding set_or_throw(out, "enableChemSplit", true); @@ -170,7 +171,6 @@ void CompositionOp(const MarsDict_t& mars, const ParDict_t& par, const OptDict_t else { MARS2GRIB_CONCEPT_THROW(composition, "Concept variant is not implemented!"); } - } catch (...) { diff --git a/src/metkit/mars2grib/backend/concepts/composition/compositionMatcher.h b/src/metkit/mars2grib/backend/concepts/composition/compositionMatcher.h index 9365987a..0e06491f 100644 --- a/src/metkit/mars2grib/backend/concepts/composition/compositionMatcher.h +++ b/src/metkit/mars2grib/backend/concepts/composition/compositionMatcher.h @@ -36,52 +36,67 @@ std::size_t compositionMatcher(const MarsDict_t& mars, const OptDict_t& opt) { if (matchAny(chem, range(900, 914), 918, 922, 923, range(933, 936))) { return static_cast(CompositionType::AerosolOptical); } - } else if (matchAny(param, 458000, 459000, 460000, 461000, 462000, 472000)) { + } + else if (matchAny(param, 458000, 459000, 460000, 461000, 462000, 472000)) { if (matchAny(chem, 922)) { return static_cast(CompositionType::AerosolOptical); } } - } else { + } + else { if (matchAny(param, 401000)) { if (matchAny(chem, range(900, 916))) { return static_cast(CompositionType::Aerosol); } - if (matchAny(chem, 2, 3, range(5, 24), range(26, 30), range(32, 50), 52, 53, range(55, 58), range(63, 80), 82, 83, 85, 86, range(99, 101), 107, 112, 159, 161, 169, range(173, 178), range(186, 204), 222, range(224, 231), 233, 311, 359, 404, 917)) { + if (matchAny(chem, 2, 3, range(5, 24), range(26, 30), range(32, 50), 52, 53, range(55, 58), range(63, 80), + 82, 83, 85, 86, range(99, 101), 107, 112, 159, 161, 169, range(173, 178), range(186, 204), 222, + range(224, 231), 233, 311, 359, 404, 917)) { return static_cast(CompositionType::Chem); } - } else if (matchAny(param, 402000)) { + } + else if (matchAny(param, 402000)) { if (matchAny(chem, range(900, 917), 924)) { return static_cast(CompositionType::Aerosol); } - if (matchAny(chem, range(2, 24), range(26, 30), range(32, 50), 52, 53, range(55, 59), range(63, 80), 82, 83, 85, 86, range(99, 101), 107, 112, 118, 159, 161, 169, range(173, 178), range(186, 204), 222, range(224, 230), 233, 236, 311)) { + if (matchAny(chem, range(2, 24), range(26, 30), range(32, 50), 52, 53, range(55, 59), range(63, 80), 82, 83, + 85, 86, range(99, 101), 107, 112, 118, 159, 161, 169, range(173, 178), range(186, 204), 222, + range(224, 230), 233, 236, 311)) { return static_cast(CompositionType::Chem); } - } else if (matchAny(param, 406000, 407000, 410000, 411000, 451000)) { + } + else if (matchAny(param, 406000, 407000, 410000, 411000, 451000)) { if (matchAny(chem, range(901, 916))) { return static_cast(CompositionType::Aerosol); } - } else if (matchAny(param, 453000)) { + } + else if (matchAny(param, 453000)) { if (matchAny(chem, range(901, 916), 922)) { return static_cast(CompositionType::Aerosol); } - } else if (matchAny(param, 400000)) { + } + else if (matchAny(param, 400000)) { if (matchAny(chem, range(929, 931))) { return static_cast(CompositionType::Aerosol); } - } else if (matchAny(param, 444000)) { + } + else if (matchAny(param, 444000)) { if (matchAny(chem, 6, 8, 13, 15, 17, 19, 26, 27, 33)) { return static_cast(CompositionType::Chem); } - } else if (matchAny(param, 445000)) { + } + else if (matchAny(param, 445000)) { if (matchAny(chem, 6, 8, 13, 15, 17, 19, 27, 33, 236)) { return static_cast(CompositionType::Chem); } - } else if (matchAny(param, 479000)) { + } + else if (matchAny(param, 479000)) { if (matchAny(chem, 404)) { return static_cast(CompositionType::Chem); } - } else if (matchAny(param, 469000)) { - if (matchAny(chem, 2, 5, 9, 10, 12, 16, 18, 19, 42, range(45, 48), 52, 99, 100, 129, 224, 226, 233, 311, 933, 934)) { + } + else if (matchAny(param, 469000)) { + if (matchAny(chem, 2, 5, 9, 10, 12, 16, 18, 19, 42, range(45, 48), 52, 99, 100, 129, 224, 226, 233, 311, + 933, 934)) { return static_cast(CompositionType::ChemicalSource); } } diff --git a/src/metkit/mars2grib/backend/concepts/level/levelMatcher.h b/src/metkit/mars2grib/backend/concepts/level/levelMatcher.h index 1f1dd519..434ed1ce 100644 --- a/src/metkit/mars2grib/backend/concepts/level/levelMatcher.h +++ b/src/metkit/mars2grib/backend/concepts/level/levelMatcher.h @@ -176,7 +176,8 @@ inline std::size_t matchPL(const long param, const long level) { using metkit::mars2grib::util::param_matcher::range; if (matchAny(param, 1, 2, 10, 60, 75, 76, range(129, 135), 138, 152, range(155, 157), 203, range(246, 248), 235100, - range(235129, 235133), 235135, 235138, 235152, 235155, 235157, 235203, 235246, 260290, 263107, range(400000, 499999))) { + range(235129, 235133), 235135, 235138, 235152, 235155, 235157, 235203, 235246, 260290, 263107, + range(400000, 499999))) { if (level >= 100) { return static_cast(LevelType::IsobaricInHpa); } @@ -193,7 +194,8 @@ inline std::size_t matchPT(const long param) { using metkit::mars2grib::util::param_matcher::matchAny; using metkit::mars2grib::util::param_matcher::range; - if (matchAny(param, 53, 54, 60, range(131, 133), 138, 155, 203, 235100, 235203, 237203, 238203, 239203, range(400000, 499999))) { + if (matchAny(param, 53, 54, 60, range(131, 133), 138, 155, 203, 235100, 235203, 237203, 238203, 239203, + range(400000, 499999))) { return static_cast(LevelType::Theta); }