From 5baa671ddde30fce229d2859195cd0c8d9ead6a7 Mon Sep 17 00:00:00 2001 From: Emily Boudreaux Date: Sun, 12 Oct 2025 10:21:28 -0400 Subject: [PATCH] docs(libcomposition): added more docstrings --- .../composition/composition_abstract.h | 138 ++++++++++++++++++ .../include/fourdst/composition/elements.h | 31 ++++ .../include/fourdst/composition/species.h | 25 +++- tests/composition/compositionTest.cpp | 132 ++++++++++++++++- 4 files changed, 321 insertions(+), 5 deletions(-) diff --git a/src/composition/include/fourdst/composition/composition_abstract.h b/src/composition/include/fourdst/composition/composition_abstract.h index 8da4851..2d87c12 100644 --- a/src/composition/include/fourdst/composition/composition_abstract.h +++ b/src/composition/include/fourdst/composition/composition_abstract.h @@ -6,39 +6,177 @@ #include #include +/** + * @brief Abstract base class for chemical composition representations. + * + * The purpose of this class is to define a standard interface for all composition types. + * Children of this class are responsible for implementing the setter methods, but any + * object that is a child of CompositionAbstract will always have these getter methods. + * + * This ensures that all derived composition classes provide a consistent API for querying + * composition properties, regardless of how the data is set or stored. + * + * @par Example + * @code + * class MyComposition : public CompositionAbstract { + * // ...implement all pure virtual methods... + * }; + * + * MyComposition comp; + * if (comp.hasSymbol("H")) { + * double mf = comp.getMassFraction("H"); + * } + * std::set symbols = comp.getRegisteredSymbols(); + * @endcode + */ class CompositionAbstract { public: + /** + * @brief Virtual destructor. + */ virtual ~CompositionAbstract() = default; + + /** + * @brief Check if a chemical symbol is registered in the composition. + * @param symbol The chemical symbol to check (e.g., "H", "He"). + * @return True if the symbol is present, false otherwise. + */ [[nodiscard]] virtual bool hasSymbol(const std::string& symbol) const = 0; + + /** + * @brief Check if a species is registered in the composition. + * @param species The atomic species to check. + * @return True if the species is present, false otherwise. + */ [[nodiscard]] virtual bool hasSpecies(const fourdst::atomic::Species& species) const = 0; + /** + * @brief Check if the composition contains the given species. + * @param species The atomic species to check. + * @return True if the species is contained, false otherwise. + */ [[nodiscard]] virtual bool contains(const fourdst::atomic::Species& species) const = 0; + /** + * @brief Get all registered chemical symbols in the composition. + * @return A set of registered chemical symbols. + */ [[nodiscard]] virtual std::set getRegisteredSymbols() const = 0; + + /** + * @brief Get all registered atomic species in the composition. + * @return A set of registered atomic species. + */ [[nodiscard]] virtual std::set getRegisteredSpecies() const = 0; + /** + * @brief Get the mass fraction for all registered symbols. + * @return An unordered map from symbol to mass fraction. + */ [[nodiscard]] virtual std::unordered_map getMassFraction() const = 0; + + /** + * @brief Get the number fraction for all registered symbols. + * @return An unordered map from symbol to number fraction. + */ [[nodiscard]] virtual std::unordered_map getNumberFraction() const = 0; + /** + * @brief Get the mass fraction for a given symbol. + * @param symbol The chemical symbol. + * @return The mass fraction for the symbol. + */ [[nodiscard]] virtual double getMassFraction(const std::string& symbol) const = 0; + + /** + * @brief Get the mass fraction for a given species. + * @param species The atomic species. + * @return The mass fraction for the species. + */ [[nodiscard]] virtual double getMassFraction(const fourdst::atomic::Species& species) const = 0; + /** + * @brief Get the number fraction for a given symbol. + * @param symbol The chemical symbol. + * @return The number fraction for the symbol. + */ [[nodiscard]] virtual double getNumberFraction(const std::string& symbol) const = 0; + + /** + * @brief Get the number fraction for a given species. + * @param species The atomic species. + * @return The number fraction for the species. + */ [[nodiscard]] virtual double getNumberFraction(const fourdst::atomic::Species& species) const = 0; + /** + * @brief Get the molar abundance for a given symbol. + * @param symbol The chemical symbol. + * @return The molar abundance for the symbol. + */ [[nodiscard]] virtual double getMolarAbundance(const std::string& symbol) const = 0; + + /** + * @brief Get the molar abundance for a given species. + * @param species The atomic species. + * @return The molar abundance for the species. + */ [[nodiscard]] virtual double getMolarAbundance(const fourdst::atomic::Species& species) const = 0; + /** + * @brief Get the mean particle mass of the composition. + * @return The mean particle mass. + */ [[nodiscard]] virtual double getMeanParticleMass() const = 0; + + /** + * @brief Get the mean atomic number of the composition. + * @return The mean atomic number. + */ [[nodiscard]] virtual double getMeanAtomicNumber() const = 0; + + /** + * @brief Get the electron abundance of the composition. + * @return The electron abundance. + */ [[nodiscard]] virtual double getElectronAbundance() const = 0; + /** + * @brief Get the mass fraction as a vector. + * @return A vector of mass fractions for all species. + */ [[nodiscard]] virtual std::vector getMassFractionVector() const = 0; + + /** + * @brief Get the number fraction as a vector. + * @return A vector of number fractions for all species. + */ [[nodiscard]] virtual std::vector getNumberFractionVector() const = 0; + + /** + * @brief Get the molar abundance as a vector. + * @return A vector of molar abundances for all species. + */ [[nodiscard]] virtual std::vector getMolarAbundanceVector() const = 0; + /** + * @brief Get the index of a species by symbol. + * @param symbol The chemical symbol. + * @return The index of the species. + */ [[nodiscard]] virtual size_t getSpeciesIndex(const std::string& symbol) const = 0; + + /** + * @brief Get the index of a species. + * @param species The atomic species. + * @return The index of the species. + */ [[nodiscard]] virtual size_t getSpeciesIndex(const fourdst::atomic::Species& species) const = 0; + /** + * @brief Get the species at a given index. + * @param index The index of the species. + * @return The atomic species at the specified index. + */ [[nodiscard]] virtual fourdst::atomic::Species getSpeciesAtIndex(size_t index) const = 0; }; \ No newline at end of file diff --git a/src/composition/include/fourdst/composition/elements.h b/src/composition/include/fourdst/composition/elements.h index acd3912..647c458 100644 --- a/src/composition/include/fourdst/composition/elements.h +++ b/src/composition/include/fourdst/composition/elements.h @@ -4,7 +4,27 @@ #include #include +/** + * @file elements.h + * @brief Provides mappings between atomic numbers and element symbols for the periodic table. + * + * This header defines lookup tables for converting between atomic numbers (Z) and their corresponding + * chemical element symbols, and vice versa. These maps are useful for parsing, displaying, or validating + * chemical compositions in scientific applications. + */ + namespace fourdst::atomic { + + /** + * @brief Maps atomic number (Z) to element symbol. + * + * This map allows lookup of the chemical symbol for a given atomic number. + * + * @par Example + * @code + * std::string symbol = fourdst::atomic::element_symbol_map.at(8); // symbol == "O" + * @endcode + */ static const std::unordered_map element_symbol_map = { {1u, "H"}, {2u, "He"}, @@ -125,6 +145,17 @@ namespace fourdst::atomic { {117u, "Ts"}, {118u, "Og"} }; + + /** + * @brief Maps element symbol to atomic number (Z). + * + * This map allows lookup of the atomic number for a given chemical symbol. + * + * @par Example + * @code + * uint8_t z = fourdst::atomic::symbol_element_map.at("Fe"); // z == 26 + * @endcode + */ static const std::unordered_map symbol_element_map = { {"H", 1u}, {"He", 2u}, diff --git a/src/composition/include/fourdst/composition/species.h b/src/composition/include/fourdst/composition/species.h index e969d97..240b4b2 100644 --- a/src/composition/include/fourdst/composition/species.h +++ b/src/composition/include/fourdst/composition/species.h @@ -3570,6 +3570,12 @@ namespace fourdst::atomic { static const Species Og_295("Og-295", "Og", 59, 177, 118, 295, 7076.0, "B-", std::numeric_limits::quiet_NaN(), 680.0, "", "~100", 295.216178, 703.0); // Create a map from species name (e.g., "H-1") to a pointer to the species object. + /** + * @brief Map of species names to their corresponding Species objects. + * + * @details This unordered map allows for quick lookup of species by their string identifiers. All Species are stored + * as constant references to ensure immutability and efficient access. + */ static const std::unordered_map species = { {"n-1", n_1}, {"H-1", H_1}, @@ -7130,14 +7136,25 @@ namespace fourdst::atomic { {"Og-294", Og_294}, {"Og-295", Og_295}, }; - - // Create an enum to represent possible error types when looking up species. + + /** + * @brief Error types for species lookup. + * @par Types + * - ELEMENT_SYMBOL_NOT_FOUND: The element symbol corresponding to the provided atomic number (Z) was not found. + * - SPECIES_SYMBOL_NOT_FOUND: The species symbol constructed from the element symbol and mass was not found. + */ enum class SpeciesErrorType { ELEMENT_SYMBOL_NOT_FOUND, SPECIES_SYMBOL_NOT_FOUND }; - - // Function to look up a species by its atomic number (Z) and mass number (A). + + /** + * @breif Convert atomic mass (A) and atomic number (Z) to a Species object. + * @param a The atomic mass number. + * @param z the atomic number. + * @return A std::expected containing the Species object if found, or a SpeciesErrorType error if not found. + * @note This function is noexcept and will not throw exceptions. The only possible exception is a bad_alloc from std::string operations and this is unrecoverable. + */ inline std::expected az_to_species(const int a, const int z) noexcept { if (!element_symbol_map.contains(static_cast(z))) { return std::unexpected(SpeciesErrorType::ELEMENT_SYMBOL_NOT_FOUND); diff --git a/tests/composition/compositionTest.cpp b/tests/composition/compositionTest.cpp index 8e0deee..576147d 100644 --- a/tests/composition/compositionTest.cpp +++ b/tests/composition/compositionTest.cpp @@ -430,12 +430,28 @@ TEST_F(compositionTest, getRegisteredSpecies) { EXPECT_EQ(*it1, fourdst::atomic::H_1); } +/** + * @brief Tests the az_to_species utility for correct species lookup and error handling. + * @details This test checks that az_to_species returns the correct Species for valid (A,Z) pairs, + * and the correct error codes for invalid atomic number or element number. + * @par What this test proves: + * - az_to_species correctly maps valid (A,Z) to Species. + * - az_to_species returns appropriate error codes for invalid input. + */ TEST_F(compositionTest, getSpeciesFromAZ) { EXPECT_EQ(fourdst::atomic::O_12, fourdst::atomic::az_to_species(12, 8)); EXPECT_EQ(fourdst::atomic::SpeciesErrorType::SPECIES_SYMBOL_NOT_FOUND, fourdst::atomic::az_to_species(120, 38).error()); EXPECT_EQ(fourdst::atomic::SpeciesErrorType::ELEMENT_SYMBOL_NOT_FOUND, fourdst::atomic::az_to_species(120, 500).error()); } +/** + * @brief Tests constructors that take vectors and sets of symbols. + * @details This test verifies that the Composition can be constructed from a vector or set of symbols, + * and that the resulting object correctly registers those symbols. + * @par What this test proves: + * - Constructors accepting std::vector and std::set of symbols work as expected. + * - Registered symbols are correctly tracked. + */ TEST_F(compositionTest, constructorWithSymbolsVectorAndSet) { fourdst::config::Config::getInstance().loadConfig(EXAMPLE_FILENAME); std::vector vs = {"H-1", "He-4"}; @@ -450,6 +466,14 @@ TEST_F(compositionTest, constructorWithSymbolsVectorAndSet) { EXPECT_TRUE(compSet.hasSymbol("He-4")); } +/** + * @brief Tests constructors that take symbols and fractions for both mass and number fraction modes. + * @details This test verifies that the Composition can be constructed directly from vectors of symbols and fractions, + * and that the resulting mass and number fractions are correct. It also checks conversions between modes. + * @par What this test proves: + * - Constructors for both mass and number fraction modes work as expected. + * - Conversion between mass and number fraction modes is correct. + */ TEST_F(compositionTest, constructorWithSymbolsAndFractionsMassAndNumber) { fourdst::config::Config::getInstance().loadConfig(EXAMPLE_FILENAME); using fourdst::composition::Composition; @@ -482,6 +506,15 @@ TEST_F(compositionTest, constructorWithSymbolsAndFractionsMassAndNumber) { EXPECT_NEAR(compN.getMassFraction("He-4"), xHe, 1e-12); } +/** + * @brief Tests registering symbols via vector, single Species, and mode mismatch error. + * @details This test checks that symbols can be registered via a vector, that registering by Species works, + * and that attempting to register a symbol with a mismatched mode throws the correct exception. + * @par What this test proves: + * - registerSymbol works with vectors. + * - registerSpecies works with single Species. + * - Mode mismatch throws CompositionModeError. + */ TEST_F(compositionTest, registerSymbolVectorAndSingleSpeciesAndModeMismatch) { fourdst::config::Config::getInstance().loadConfig(EXAMPLE_FILENAME); using fourdst::composition::Composition; @@ -503,6 +536,14 @@ TEST_F(compositionTest, registerSymbolVectorAndSingleSpeciesAndModeMismatch) { EXPECT_THROW(comp3.registerSymbol("He-4", false), fourdst::composition::exceptions::CompositionModeError); } +/** + * @brief Tests setMassFraction overloads for Species and vectors. + * @details This test verifies that setMassFraction works for both single Species and vectors of Species, + * and that the returned old values are correct. + * @par What this test proves: + * - setMassFraction overloads work as expected. + * - Old values are returned correctly. + */ TEST_F(compositionTest, setMassFractionBySpeciesAndVector) { fourdst::config::Config::getInstance().loadConfig(EXAMPLE_FILENAME); using fourdst::composition::Composition; @@ -532,6 +573,14 @@ TEST_F(compositionTest, setMassFractionBySpeciesAndVector) { EXPECT_NEAR(comp.getMassFraction(He_4), 0.4, 1e-12); } +/** + * @brief Tests setNumberFraction overloads for symbols and Species. + * @details This test verifies that setNumberFraction works for both single symbols/Species and vectors, + * and that the returned old values are correct. + * @par What this test proves: + * - setNumberFraction overloads work as expected. + * - Old values are returned correctly. + */ TEST_F(compositionTest, setNumberFractionOverloads) { fourdst::config::Config::getInstance().loadConfig(EXAMPLE_FILENAME); using fourdst::composition::Composition; @@ -564,6 +613,13 @@ TEST_F(compositionTest, setNumberFractionOverloads) { EXPECT_NEAR(comp.getNumberFraction(He_4), 0.4, 1e-12); } +/** + * @brief Tests error cases for mixing compositions. + * @details This test checks that mixing with a non-finalized composition or with invalid fractions throws the correct exceptions. + * @par What this test proves: + * - Mixing with a non-finalized composition throws CompositionNotFinalizedError. + * - Mixing with invalid fractions throws InvalidCompositionError. + */ TEST_F(compositionTest, mixErrorCases) { fourdst::config::Config::getInstance().loadConfig(EXAMPLE_FILENAME); using fourdst::composition::Composition; @@ -581,6 +637,14 @@ TEST_F(compositionTest, mixErrorCases) { EXPECT_THROW(static_cast(a.mix(b, 1.1)), fourdst::composition::exceptions::InvalidCompositionError); } +/** + * @brief Tests getMassFraction and getNumberFraction maps and Species overloads. + * @details This test verifies that the getter methods for mass and number fractions return correct maps, + * and that overloads for Species work as expected. + * @par What this test proves: + * - getMassFraction and getNumberFraction return correct maps. + * - Overloads for Species work as expected. + */ TEST_F(compositionTest, getMassAndNumberFractionMapsAndSpeciesOverloads) { fourdst::config::Config::getInstance().loadConfig(EXAMPLE_FILENAME); using fourdst::composition::Composition; @@ -611,6 +675,13 @@ TEST_F(compositionTest, getMassAndNumberFractionMapsAndSpeciesOverloads) { EXPECT_NEAR(comp.getNumberFraction(fourdst::atomic::He_4), 0.3, 1e-12); } +/** + * @brief Tests mean atomic number and electron abundance calculations. + * @details This test verifies that getElectronAbundance and getMeanAtomicNumber return correct values + * based on the composition. + * @par What this test proves: + * - getElectronAbundance and getMeanAtomicNumber are calculated correctly. + */ TEST_F(compositionTest, meanAtomicNumberAndElectronAbundance) { fourdst::config::Config::getInstance().loadConfig(EXAMPLE_FILENAME); using fourdst::atomic::species; @@ -635,6 +706,14 @@ TEST_F(compositionTest, meanAtomicNumberAndElectronAbundance) { EXPECT_NEAR(comp.getMeanAtomicNumber(), expectedZ, 1e-12); } +/** + * @brief Tests canonical composition and caching behavior. + * @details This test verifies that getCanonicalComposition returns correct X, Y, Z values, + * and that repeated calls use the cached result. + * @par What this test proves: + * - getCanonicalComposition returns correct canonical values. + * - Caching works as expected. + */ TEST_F(compositionTest, canonicalCompositionAndCaching) { fourdst::config::Config::getInstance().loadConfig(EXAMPLE_FILENAME); using fourdst::composition::Composition; @@ -664,6 +743,14 @@ TEST_F(compositionTest, canonicalCompositionAndCaching) { EXPECT_NEAR(canon3.Z, 0.05, 1e-12); } +/** + * @brief Tests vector getters, indexing, and species-at-index functionality. + * @details This test verifies that the vector getters for mass, number, and molar abundance fractions + * return correct values, and that species can be accessed by index. + * @par What this test proves: + * - Vector getters return correct values. + * - Indexing and species-at-index work as expected. + */ TEST_F(compositionTest, vectorsAndIndexingAndSpeciesAtIndex) { fourdst::config::Config::getInstance().loadConfig(EXAMPLE_FILENAME); using fourdst::composition::Composition; @@ -719,6 +806,13 @@ TEST_F(compositionTest, vectorsAndIndexingAndSpeciesAtIndex) { EXPECT_NEAR(av[iO], 0.2/species.at("O-16").mass(), 1e-12); } +/** + * @brief Tests contains method and pre-finalization guards. + * @details This test verifies that contains throws before finalization and works correctly after. + * @par What this test proves: + * - contains throws before finalize. + * - contains works as expected after finalize. + */ TEST_F(compositionTest, containsAndPreFinalizationGuards) { fourdst::config::Config::getInstance().loadConfig(EXAMPLE_FILENAME); fourdst::composition::Composition comp; @@ -732,6 +826,14 @@ TEST_F(compositionTest, containsAndPreFinalizationGuards) { EXPECT_FALSE(comp.contains(fourdst::atomic::Li_6)); } +/** + * @brief Tests subset method with "none" normalization and normalization flow. + * @details This test verifies that subset with "none" does not normalize by default, + * and that normalization can be forced with finalize(true). + * @par What this test proves: + * - subset with "none" does not normalize by default. + * - finalize(true) normalizes the subset. + */ TEST_F(compositionTest, subsetNoneMethodAndNormalizationFlow) { fourdst::config::Config::getInstance().loadConfig(EXAMPLE_FILENAME); fourdst::composition::Composition comp; @@ -750,6 +852,12 @@ TEST_F(compositionTest, subsetNoneMethodAndNormalizationFlow) { EXPECT_NEAR(sub.getMassFraction("He-4"), 0.3/(0.5+0.3), 1e-12); } +/** + * @brief Tests copy constructor and assignment operator for independence. + * @details This test verifies that copies of a Composition object are independent of the original. + * @par What this test proves: + * - Copy constructor and assignment operator create independent objects. + */ TEST_F(compositionTest, copyConstructorAndAssignmentIndependence) { fourdst::config::Config::getInstance().loadConfig(EXAMPLE_FILENAME); using fourdst::composition::Composition; @@ -772,6 +880,13 @@ TEST_F(compositionTest, copyConstructorAndAssignmentIndependence) { EXPECT_NEAR(assigned.getMassFraction("He-4"), 0.4, 1e-12); } +/** + * @brief Tests getComposition by Species and retrieval of all entries. + * @details This test verifies that getComposition works for both single Species and all entries, + * and that the returned values are correct. + * @par What this test proves: + * - getComposition works for both single Species and all entries. + */ TEST_F(compositionTest, getCompositionBySpeciesAndAllEntries) { fourdst::config::Config::getInstance().loadConfig(EXAMPLE_FILENAME); using fourdst::composition::Composition; @@ -791,6 +906,14 @@ TEST_F(compositionTest, getCompositionBySpeciesAndAllEntries) { EXPECT_NEAR(all.second.meanParticleMass, comp.getMeanParticleMass(), 1e-15); } +/** + * @brief Tests iteration over composition and out-of-range index access. + * @details This test verifies that begin/end iteration covers all entries, + * and that accessing an out-of-range index throws an exception. + * @par What this test proves: + * - Iteration covers all entries. + * - Out-of-range index throws std::out_of_range. + */ TEST_F(compositionTest, iterationBeginEndAndIndexOutOfRange) { fourdst::config::Config::getInstance().loadConfig(EXAMPLE_FILENAME); fourdst::composition::Composition comp; @@ -809,6 +932,14 @@ TEST_F(compositionTest, iterationBeginEndAndIndexOutOfRange) { EXPECT_THROW(static_cast(comp.getSpeciesAtIndex(100)), std::out_of_range); } +/** + * @brief Tests inheritance from CompositionAbstract and overriding a getter. + * @details This test defines a derived class that overrides getMolarAbundance, + * and verifies that the override works and other getters are inherited. + * @par What this test proves: + * - Derived classes can override getters. + * - All CompositionAbstract children have the standard getter interface. + */ TEST_F(compositionTest, abstractBase) { class UnrestrictedComposition : public fourdst::composition::Composition { private: @@ -841,4 +972,3 @@ TEST_F(compositionTest, abstractBase) { ASSERT_DOUBLE_EQ(uComp.getMassFraction("He-4"), comp.getMassFraction("He-4")); } -