From 85e89692e1ad5e8c55751e7e70b656d0dd0a0f48 Mon Sep 17 00:00:00 2001 From: Emily Boudreaux Date: Mon, 14 Jul 2025 11:29:04 -0400 Subject: [PATCH] feat(composition): added species queries and < > operators for species based on mass --- meson.build | 2 +- .../fourdst/composition/atomicSpecies.h | 8 ++ .../include/fourdst/composition/composition.h | 111 ++++++++++++++++++ src/composition/lib/composition.cpp | 63 ++++++++++ tests/composition/compositionTest.cpp | 11 ++ 5 files changed, 194 insertions(+), 1 deletion(-) diff --git a/meson.build b/meson.build index 7b67e8d..986a868 100644 --- a/meson.build +++ b/meson.build @@ -18,7 +18,7 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # *********************************************************************** # -project('libcomposition', 'cpp', version: 'v1.3.0', default_options: ['cpp_std=c++23'], meson_version: '>=1.5.0') +project('libcomposition', 'cpp', version: 'v1.4.0', default_options: ['cpp_std=c++23'], meson_version: '>=1.5.0') # Add default visibility for all C++ targets add_project_arguments('-fvisibility=default', language: 'cpp') diff --git a/src/composition/include/fourdst/composition/atomicSpecies.h b/src/composition/include/fourdst/composition/atomicSpecies.h index 9155b32..7700516 100644 --- a/src/composition/include/fourdst/composition/atomicSpecies.h +++ b/src/composition/include/fourdst/composition/atomicSpecies.h @@ -144,6 +144,8 @@ namespace fourdst::atomic { friend bool operator==(const Species& lhs, const Species& rhs); friend bool operator!=(const Species& lhs, const Species& rhs); + friend bool operator<(const Species& lhs, const Species& rhs); + friend bool operator>(const Species& lhs, const Species& rhs); }; inline bool operator==(const Species& lhs, const Species& rhs) { return (lhs.m_name == rhs.m_name); @@ -151,6 +153,12 @@ namespace fourdst::atomic { inline bool operator!=(const Species& lhs, const Species& rhs) { return (lhs.m_name != rhs.m_name); } + inline bool operator<(const Species& lhs, const Species& rhs) { + return (lhs.m_atomicMass < rhs.m_atomicMass); + } + inline bool operator>(const Species& lhs, const Species& rhs) { + return (lhs.m_atomicMass > rhs.m_atomicMass); + } inline double convert_jpi_to_double(const std::string& jpi_string) { std::string s = jpi_string; diff --git a/src/composition/include/fourdst/composition/composition.h b/src/composition/include/fourdst/composition/composition.h index f43155c..7d75686 100644 --- a/src/composition/include/fourdst/composition/composition.h +++ b/src/composition/include/fourdst/composition/composition.h @@ -348,12 +348,50 @@ namespace fourdst::composition { */ void registerSymbol(const std::vector& symbols, bool massFracMode=true); + /** + * @brief Register a new species (will extract the symbol from the species). + * @param species The species to register. + * @param massFracMode True if mass fraction mode, false if number fraction mode. + * *Example Usage:* + * @code + * #include "fourdst/atomic/species.h" + * + * Composition comp; + * comp.registerSpecies(H_1); + * + * #@endcode + */ + void registerSpecies(const fourdst::atomic::Species& species, bool massFracMode=true); + + + /** + * @brief Register a vector of new species (will extract the symbol from the species). + * @param species The vector of species to register. + * @param massFracMode True if mass fraction mode, false if number fraction mode. + * *Example Usage:* + * @code + * #include "fourdst/atomic/species.h" + * + * Composition comp; + * comp.registerSpecies({H_1, He_4, O_16}, false); // Will now be in number fraction mode. + * + * #@endcode + */ + void registerSpecies(const std::vector& species, bool massFracMode=true); + + /** * @brief Gets the registered symbols. * @return A set of registered symbols. */ [[nodiscard]] std::set getRegisteredSymbols() const; + /** + * @brief Get a set of all species that are registered in the composition. + * @return species that are registered in the composition. + */ + [[nodiscard]] std::set getRegisteredSpecies() const; + /** * @brief Sets the mass fraction for a given symbol. * @param symbol The symbol to set the mass fraction for. @@ -382,6 +420,28 @@ namespace fourdst::composition { */ std::vector setMassFraction(const std::vector& symbols, const std::vector& mass_fractions); + /** + * @brief Sets the mass fraction for a given species. + * @param species Species to set the mass fraction for. + * @param mass_fraction Mass fraction to set for the species. + * @return The previous mass fraction that was set for the species. + * + * @throws std::runtime_error if the species is not registered or if the composition is in number fraction mode. + * @throws std::logic_error if the mass fraction is not between 0 and 1. + */ + double setMassFraction(const fourdst::atomic::Species& species, const double& mass_fraction); + + /** + * @brief Sets the mass fraction for multiple species. + * @param species The vector of species to set the mass fractions for. + * @param mass_fractions The vector of mass fractions corresponding to the species. + * @return A vector of mass fractions that were set. + * + * @throws std::runtime_error if the species are not registered or if the composition is in number fraction mode. + * @throws std::logic_error if any mass fraction is not between 0 and 1. + */ + std::vector setMassFraction(const std::vector& species, const std::vector& mass_fractions); + /** * @brief Sets the number fraction for a given symbol. * @param symbol The symbol to set the number fraction for. @@ -398,6 +458,28 @@ namespace fourdst::composition { */ std::vector setNumberFraction(const std::vector& symbols, const std::vector& number_fractions); + /** + * @brief Sets the number fraction for a given species. + * @param species The species to set the number fraction for. + * @param number_fraction The number fraction to set for the species. + * @return The previous number fraction that was set for the species. + * + * @throws std::runtime_error if the species is not registered or if the composition is in mass fraction mode. + * @throws std::logic_error if the number fraction is not between 0 and 1. + */ + double setNumberFraction(const fourdst::atomic::Species& species, const double& number_fraction); + + /** + * @brief Sets the number fraction for multiple species. + * @param species The vector of species to set the number fractions for. + * @param number_fractions The vector of number fractions corresponding to the species. + * @return The vector of number fractions that were set. + * + * @throws std::runtime_error if the species are not registered or if the composition is in mass fraction mode. + * @throws std::logic_error if any number fraction is not between 0 and 1. + */ + std::vector setNumberFraction(const std::vector& species, const std::vector& number_fractions); + /** * @brief Mix two compositions together with a given fraction. * @param other The other composition to mix with. @@ -418,6 +500,15 @@ namespace fourdst::composition { */ [[nodiscard]] double getMassFraction(const std::string& symbol) const; + /** + * @brief Gets the mass fraction for a given isotope. + * @param species The isotope to get the mass fraction for. + * @return The mass fraction for the given isotope. + * + * @throws std::runtime_error if the isotope is not registered in the composition. + */ + [[nodiscard]] double getMassFraction(const fourdst::atomic::Species& species) const; + /** * @brief Gets the number fraction for a given symbol. * @param symbol The symbol to get the number fraction for. @@ -425,6 +516,15 @@ namespace fourdst::composition { */ [[nodiscard]] double getNumberFraction(const std::string& symbol) const; + /** + * @brief Gets the number fraction for a given isotope. + * @param species The isotope to get the number fraction for. + * @return The number fraction for the given isotope. + * + * @throws std::runtime_error if the isotope is not registered in the composition. + */ + [[nodiscard]] double getNumberFraction(const fourdst::atomic::Species& species) const; + /** * @brief Gets the number fractions of all compositions. * @return An unordered map of compositions with their number fractions. @@ -438,6 +538,15 @@ namespace fourdst::composition { */ [[nodiscard]] double getMolarAbundance(const std::string& symbol) const; + /** + * @brief Gets the molar abundance for a given isotope. + * @param species The isotope to get the molar abundance for. + * @return The molar abundance for the given isotope. + * + * @throws std::runtime_error if the isotope is not registered in the composition. + */ + [[nodiscard]] double getMolarAbundance(const fourdst::atomic::Species& species) const; + /** * @brief Gets the composition entry and global composition for a given symbol. * @param symbol The symbol to get the composition for. @@ -445,6 +554,8 @@ namespace fourdst::composition { */ [[nodiscard]] std::pair getComposition(const std::string& symbol) const; + [[nodiscard]] std::pair getComposition(const fourdst::atomic::Species& species) const; + /** * @brief Gets all composition entries and the global composition. * @return A pair containing an unordered map of CompositionEntries and the GlobalComposition. diff --git a/src/composition/lib/composition.cpp b/src/composition/lib/composition.cpp index 479877c..0c526bc 100644 --- a/src/composition/lib/composition.cpp +++ b/src/composition/lib/composition.cpp @@ -234,10 +234,28 @@ namespace fourdst::composition { } } + void Composition::registerSpecies(const fourdst::atomic::Species &species, bool massFracMode) { + registerSymbol(std::string(species.name())); + } + + void Composition::registerSpecies(const std::vector &species, bool massFracMode) { + for (const auto& s : species) { + registerSpecies(s, massFracMode); + } + } + std::set Composition::getRegisteredSymbols() const { return m_registeredSymbols; } + std::set Composition::getRegisteredSpecies() const { + std::set result; + for (const auto& entry : m_compositions | std::views::values) { + result.insert(entry.isotope()); + } + return result; + } + void Composition::validateComposition(const std::vector& fractions) const { if (!isValidComposition(fractions)) { LOG_ERROR(m_logger, "Invalid composition."); @@ -299,6 +317,20 @@ namespace fourdst::composition { return old_mass_fractions; } + double Composition::setMassFraction(const fourdst::atomic::Species &species, const double &mass_fraction) { + return setMassFraction(std::string(species.name()), mass_fraction); + } + + std::vector Composition::setMassFraction(const std::vector &species, + const std::vector &mass_fractions) { + std::vector old_mass_fractions; + old_mass_fractions.reserve(species.size()); + for (const auto& spec : species) { + old_mass_fractions.push_back(setMassFraction(spec, mass_fractions[&spec - &species[0]])); + } + return old_mass_fractions; + } + double Composition::setNumberFraction(const std::string& symbol, const double& number_fraction) { if (!m_registeredSymbols.contains(symbol)) { LOG_ERROR(m_logger, "Symbol {} is not registered.", symbol); @@ -336,6 +368,20 @@ namespace fourdst::composition { return old_number_fractions; } + double Composition::setNumberFraction(const fourdst::atomic::Species &species, const double &number_fraction) { + return setNumberFraction(std::string(species.name()), number_fraction); + } + + std::vector Composition::setNumberFraction(const std::vector &species, + const std::vector &number_fractions) { + std::vector old_number_fractions; + old_number_fractions.reserve(species.size()); + for (const auto& spec : species) { + old_number_fractions.push_back(setNumberFraction(spec, number_fractions[&spec - &species[0]])); + } + return old_number_fractions; + } + bool Composition::finalize(const bool norm) { bool finalized = false; if (m_massFracMode) { @@ -474,6 +520,10 @@ namespace fourdst::composition { } } + double Composition::getMassFraction(const fourdst::atomic::Species &species) const { + return getMassFraction(std::string(species.name())); + } + std::unordered_map Composition::getMassFraction() const { std::unordered_map mass_fractions; for (const auto &symbol: m_compositions | std::views::keys) { @@ -499,6 +549,10 @@ namespace fourdst::composition { } } + double Composition::getNumberFraction(const fourdst::atomic::Species &species) const { + return getNumberFraction(std::string(species.name())); + } + std::unordered_map Composition::getNumberFraction() const { std::unordered_map number_fractions; for (const auto &symbol: m_compositions | std::views::keys) { @@ -520,6 +574,10 @@ namespace fourdst::composition { } + double Composition::getMolarAbundance(const fourdst::atomic::Species &species) const { + return getMolarAbundance(std::string(species.name())); + } + std::pair Composition::getComposition(const std::string& symbol) const { if (!m_finalized) { LOG_ERROR(m_logger, "Composition has not been finalized."); @@ -532,6 +590,11 @@ namespace fourdst::composition { return {m_compositions.at(symbol), {m_specificNumberDensity, m_meanParticleMass}}; } + std::pair Composition::getComposition( + const fourdst::atomic::Species &species) const { + return getComposition(std::string(species.name())); + } + std::pair, GlobalComposition> Composition::getComposition() const { if (!m_finalized) { LOG_ERROR(m_logger, "Composition has not been finalized."); diff --git a/tests/composition/compositionTest.cpp b/tests/composition/compositionTest.cpp index 22c9020..d201843 100644 --- a/tests/composition/compositionTest.cpp +++ b/tests/composition/compositionTest.cpp @@ -241,3 +241,14 @@ TEST_F(compositionTest, molarAbundance) { EXPECT_DOUBLE_EQ(comp1.getMolarAbundance("He-4"), 0.5/fourdst::atomic::He_4.mass()); } +TEST_F(compositionTest, getRegisteredSpecies) { + fourdst::composition::Composition comp; + comp.registerSpecies({fourdst::atomic::Be_7, fourdst::atomic::H_1, fourdst::atomic::He_4}, true); + auto registeredSpecies = comp.getRegisteredSpecies(); + EXPECT_TRUE(registeredSpecies.contains(fourdst::atomic::H_1)); + EXPECT_TRUE(registeredSpecies.contains(fourdst::atomic::He_4)); + EXPECT_FALSE(registeredSpecies.contains(fourdst::atomic::Li_6)); + auto it1 = registeredSpecies.begin(); + EXPECT_EQ(*it1, fourdst::atomic::H_1); +} +