feat(composition): added species queries and < > operators for species based on mass

This commit is contained in:
2025-07-14 11:29:04 -04:00
parent 684e3e7b5a
commit 85e89692e1
5 changed files with 194 additions and 1 deletions

View File

@@ -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')

View File

@@ -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;

View File

@@ -348,12 +348,50 @@ namespace fourdst::composition {
*/
void registerSymbol(const std::vector<std::string>& 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<fourdst::atomic::Species>& species, bool massFracMode=true);
/**
* @brief Gets the registered symbols.
* @return A set of registered symbols.
*/
[[nodiscard]] std::set<std::string> 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<fourdst::atomic::Species> 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<double> setMassFraction(const std::vector<std::string>& symbols, const std::vector<double>& 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<double> setMassFraction(const std::vector<fourdst::atomic::Species>& species, const std::vector<double>& 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<double> setNumberFraction(const std::vector<std::string>& symbols, const std::vector<double>& 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<double> setNumberFraction(const std::vector<fourdst::atomic::Species>& species, const std::vector<double>& 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<CompositionEntry, GlobalComposition> getComposition(const std::string& symbol) const;
[[nodiscard]] std::pair<CompositionEntry, GlobalComposition> 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.

View File

@@ -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<fourdst::atomic::Species> &species, bool massFracMode) {
for (const auto& s : species) {
registerSpecies(s, massFracMode);
}
}
std::set<std::string> Composition::getRegisteredSymbols() const {
return m_registeredSymbols;
}
std::set<fourdst::atomic::Species> Composition::getRegisteredSpecies() const {
std::set<fourdst::atomic::Species> result;
for (const auto& entry : m_compositions | std::views::values) {
result.insert(entry.isotope());
}
return result;
}
void Composition::validateComposition(const std::vector<double>& 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<double> Composition::setMassFraction(const std::vector<fourdst::atomic::Species> &species,
const std::vector<double> &mass_fractions) {
std::vector<double> 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<double> Composition::setNumberFraction(const std::vector<fourdst::atomic::Species> &species,
const std::vector<double> &number_fractions) {
std::vector<double> 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<std::string, double> Composition::getMassFraction() const {
std::unordered_map<std::string, double> 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<std::string, double> Composition::getNumberFraction() const {
std::unordered_map<std::string, double> 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<CompositionEntry, GlobalComposition> 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<CompositionEntry, GlobalComposition> Composition::getComposition(
const fourdst::atomic::Species &species) const {
return getComposition(std::string(species.name()));
}
std::pair<std::unordered_map<std::string, CompositionEntry>, GlobalComposition> Composition::getComposition() const {
if (!m_finalized) {
LOG_ERROR(m_logger, "Composition has not been finalized.");

View File

@@ -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);
}