Loading...
Searching...
No Matches
composition.cpp
Go to the documentation of this file.
/* ***********************************************************************
//
// Copyright (C) 2025 -- The 4D-STAR Collaboration
// File Author: Emily Boudreaux
// Last Modified: October 6, 2025
//
// 4DSSE is free software; you can use it and/or modify
// it under the terms and restrictions the GNU General Library Public
// License version 3 (GPLv3) as published by the Free Software Foundation.
//
// 4DSSE is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU Library General Public License for more details.
//
// You should have received a copy of the GNU Library General Public License
// along with this software; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// *********************************************************************** */
#include "quill/LogMacros.h"
#include <stdexcept>
#include <unordered_map>
#include <vector>
#include <ranges>
#include <algorithm>
#include <set>
#include <string>
#include <utility>
#include "fourdst/atomic/atomicSpecies.h"
#include "fourdst/atomic/species.h"
#include "fourdst/composition/composition.h"
#include <numeric>
#include "fourdst/composition/utils/composition_hash.h"
#include "fourdst/composition/utils.h"
#include "fourdst/composition/exceptions/exceptions_composition.h"
namespace {
void throw_unknown_symbol(quill::Logger* logger, const std::string& symbol) {
LOG_ERROR(logger, "Symbol {} is not a valid species symbol (not in the species database)", symbol);
throw fourdst::composition::exceptions::UnknownSymbolError("Symbol " + symbol + " is not a valid species symbol (not in the species database)");
}
void throw_unregistered_symbol(quill::Logger* logger, const std::string& symbol) {
LOG_ERROR(logger, "Symbol {} is not registered in the composition.", symbol);
throw fourdst::composition::exceptions::UnregisteredSymbolError("Symbol " + symbol + " is not registered in the composition.");
}
}
namespace fourdst::composition {
Composition::Composition(
const std::set<std::string>& symbols
) : Composition(symbols | std::ranges::to<std::vector>()) {}
Composition::Composition(
const std::set<atomic::Species> &species
) : Composition(species | std::ranges::to<std::vector>()) {}
Composition::Composition(
const std::unordered_set<std::string> &symbols
) : Composition(symbols | std::ranges::to<std::vector>()) {}
Composition::Composition(
const std::unordered_set<atomic::Species> &species
) : Composition(species | std::ranges::to<std::vector>()) {}
Composition::Composition(
const std::vector<std::string>& symbols
) : Composition(symbolVectorToSpeciesVector(symbols)) {}
Composition::Composition(
const std::vector<atomic::Species> &species
) {
m_species = species;
std::ranges::sort(m_species, [&](const atomic::Species& a, const atomic::Species& b) {
return a < b;
});
const auto last = std::ranges::unique(m_species).begin();
m_species.erase(last, m_species.end());
m_molarAbundances.resize(m_species.size(), 0.0);
}
Composition::Composition(
const std::vector<std::string>& symbols,
const std::vector<double>& molarAbundances
) : Composition(symbolVectorToSpeciesVector(symbols), molarAbundances) {}
Composition::Composition(
const std::set<std::string> &symbols,
const std::vector<double> &molarAbundances
) : Composition(symbolVectorToSpeciesVector(symbols | std::ranges::to<std::vector>()), molarAbundances) {}
Composition::Composition(
const std::unordered_map<std::string, double> &symbolMolarAbundances
) : Composition(
symbolMolarAbundances | std::views::keys | std::ranges::to<std::vector>(),
symbolMolarAbundances | std::views::values | std::ranges::to<std::vector>()
) {}
Composition::Composition(
const std::map<std::string, double> &symbolMolarAbundances
) : Composition(
symbolMolarAbundances | std::views::keys | std::ranges::to<std::vector>(),
symbolMolarAbundances | std::views::values | std::ranges::to<std::vector>()
) {}
Composition::Composition(
const std::unordered_map<atomic::Species, double> &speciesMolarAbundances
) : Composition(
speciesMolarAbundances | std::views::keys | std::ranges::to<std::vector>(),
speciesMolarAbundances | std::views::values | std::ranges::to<std::vector>()
) {}
Composition::Composition(
const std::map<atomic::Species, double> &speciesMolarAbundances
) : Composition(
speciesMolarAbundances | std::views::keys | std::ranges::to<std::vector>(),
speciesMolarAbundances | std::views::values | std::ranges::to<std::vector>()
) {}
Composition::Composition(
const std::vector<atomic::Species> &species,
const std::vector<double> &molarAbundances
) {
if (__builtin_expect(species.size() != molarAbundances.size(), 0)) {
LOG_CRITICAL(getLogger(), "The number of species and molarAbundances must be equal (got {} species and {} molarAbundances).", species.size(), molarAbundances.size());
throw exceptions::InvalidCompositionError("The number of species and fractions must be equal. Got " + std::to_string(species.size()) + " species and " + std::to_string(molarAbundances.size()) + " fractions.");
}
const size_t numSpecies = species.size();
m_species.reserve(numSpecies);
m_molarAbundances.reserve(numSpecies);
for (size_t i = 0; i < numSpecies; ++i) {
m_species.push_back(species[i]);
if (__builtin_expect(molarAbundances[i] < 0.0, 0)) {
LOG_CRITICAL(getLogger(), "Molar abundance for species {} is negative (y = {}). Molar abundances must be non-negative.", species[i].name(), molarAbundances[i]);
throw exceptions::InvalidCompositionError("Molar abundance for species " + std::string(species[i].name()) + " is negative (y = " + std::to_string(molarAbundances[i]) + "). Molar abundances must be non-negative.");
}
m_molarAbundances.push_back(molarAbundances[i]);
}
auto combined = std::views::zip(m_species, m_molarAbundances);
std::ranges::sort(combined, [](const auto& a, const auto& b) -> bool {
const auto& spA = std::get<0>(a);
const auto& spB = std::get<0>(b);
if (spA != spB) {
return spA < spB;
}
return std::get<1>(a) > std::get<1>(b);
});
auto [first, last] = std::ranges::unique(combined, [](const auto& a, const auto& b) {
return std::get<0>(a) == std::get<0>(b);
});
const auto newEndIndex = std::distance(combined.begin(), first);
m_species.erase(m_species.begin() + newEndIndex, m_species.end());
m_molarAbundances.erase(m_molarAbundances.begin() + newEndIndex, m_molarAbundances.end());
}
Composition::Composition(const Composition &composition) {
m_species = composition.m_species;
m_molarAbundances = composition.m_molarAbundances;
}
Composition::Composition(const CompositionAbstract &composition) {
for (const auto& species : composition.getRegisteredSpecies()) {
registerSpecies(species);
setMolarAbundance(species, composition.getMolarAbundance(species));
}
}
Composition& Composition::operator=(
const Composition &other
) {
if (this != &other) {
m_species = other.m_species;
m_molarAbundances = other.m_molarAbundances;
}
m_cache.clear();
return *this;
}
Composition & Composition::operator=(const CompositionAbstract &other) {
m_species.clear();
m_molarAbundances.clear();
m_cache.clear();
for (const auto& species : other.getRegisteredSpecies()) {
registerSpecies(species);
setMolarAbundance(species, other.getMolarAbundance(species));
}
return *this;
}
std::unique_ptr<CompositionAbstract> Composition::clone() const {
return std::make_unique<Composition>(*this);
}
//------------------------------------------
// Registration methods
//------------------------------------------
void Composition::registerSymbol(
const std::string& symbol
) {
const auto result = getSpecies(symbol);
if (!result) {
throw_unknown_symbol(getLogger(), symbol);
}
registerSpecies(result.value());
}
void Composition::registerSymbol(
const std::vector<std::string>& symbols
) {
registerSpecies(symbolVectorToSpeciesVector(symbols));
}
void Composition::registerSpecies(
const atomic::Species &species
) noexcept {
if (const auto it = std::ranges::lower_bound(m_species, species); it == m_species.end() || *it != species) {
const auto index = std::distance(m_species.begin(), it);
m_species.insert(it, species);
m_molarAbundances.insert(m_molarAbundances.begin() + index, 0.0);
m_cache.clear();
}
}
void Composition::registerSpecies(
const std::vector<atomic::Species> &species
) noexcept {
// We do not simply call registerSpecies(species) here as that would have a complexity of O(n^2) due to constantly
// reinserting into the vector. Rather we build the vector once and then sort it
if (species.empty()) return;
const size_t total_size = m_species.size() + species.size();
m_species.reserve(total_size);
m_molarAbundances.reserve(total_size);
for (const auto& sp : species) {
m_species.push_back(sp);
m_molarAbundances.push_back(0.0);
}
auto combined = std::views::zip(m_species, m_molarAbundances);
std::ranges::sort(combined, [](const auto& a, const auto& b) {
const auto& speciesA = std::get<0>(a);
const auto& speciesB = std::get<0>(b);
if (speciesA != speciesB) {
return speciesA < speciesB;
}
return std::get<1>(a) > std::get<1>(b);
});
auto [first, last] = std::ranges::unique(combined, [](const auto& a, const auto& b) {
return std::get<0>(a) == std::get<0>(b);
});
const auto newEndIndex = std::distance(combined.begin(), first);
m_species.erase(m_species.begin() + newEndIndex, m_species.end());
m_molarAbundances.erase(m_molarAbundances.begin() + newEndIndex, m_molarAbundances.end());
m_cache.clear();
}
std::set<std::string> Composition::getRegisteredSymbols() const noexcept {
std::set<std::string> symbols;
for (const auto& species : m_species) {
symbols.insert(std::string(species.name()));
}
return symbols;
}
const std::vector<atomic::Species> &Composition::getRegisteredSpecies() const noexcept {
return m_species;
}
//------------------------------------------
// Molar abundance setters
//------------------------------------------
void Composition::setMolarAbundance(
const std::string &symbol,
const double &molar_abundance
) {
const auto species = getSpecies(symbol);
if (__builtin_expect(!species, 0)) {
throw_unknown_symbol(getLogger(), symbol);
}
setMolarAbundance(species.value(), molar_abundance);
}
void Composition::setMolarAbundance(
const atomic::Species &species,
const double &molar_abundance
) {
if (__builtin_expect(molar_abundance < 0.0, 0)) {
LOG_ERROR(getLogger(), "Molar abundance must be non-negative for symbol {}. Currently it is {}.", species.name(), molar_abundance);
throw exceptions::InvalidCompositionError("Molar abundance must be non-negative, got " + std::to_string(molar_abundance) + " for symbol " + std::string(species.name()) + ".");
}
const std::expected<std::ptrdiff_t, SpeciesIndexLookupError> speciesIndexResult = findSpeciesIndex(species);
if (__builtin_expect(!speciesIndexResult, 0)) {
throw_unregistered_symbol(getLogger(), std::string(species.name()));
}
assert(static_cast<size_t>(speciesIndexResult.value()) < m_molarAbundances.size());
m_molarAbundances[speciesIndexResult.value()] = molar_abundance;
m_cache.clear();
}
void Composition::setMolarAbundance(
const std::vector<std::string> &symbols,
const std::vector<double> &molar_abundances
) {
setMolarAbundance(symbolVectorToSpeciesVector(symbols), molar_abundances);
}
void Composition::setMolarAbundance(
const std::set<std::string> &symbols,
const std::vector<double> &molar_abundances
) {
setMolarAbundance(symbolVectorToSpeciesVector(symbols | std::ranges::to<std::vector>()), molar_abundances);
}
void Composition::setMolarAbundance(
const std::set<atomic::Species> &species,
const std::vector<double> &molar_abundances
) {
setMolarAbundance(species | std::ranges::to<std::vector>(), molar_abundances);
}
void Composition::setMolarAbundance(
const std::vector<atomic::Species> &species,
const std::vector<double> &molar_abundances
) {
if (__builtin_expect(species.size() != molar_abundances.size(), 0)) {
LOG_CRITICAL(getLogger(), "The number of species and molar_abundances must be equal (got {} species and {} molar_abundances).", species.size(), molar_abundances.size());
throw exceptions::InvalidCompositionError("The number of species and fractions must be equal. Got " + std::to_string(species.size()) + " species and " + std::to_string(molar_abundances.size()) + " fractions.");
}
if (species.empty()) return;
if (species.size() == m_species.size()) {
if (species == m_species) {
for (const auto& [sp, y] : std::views::zip(species, molar_abundances)) {
if (__builtin_expect(y < 0.0, 0)) {
LOG_ERROR(getLogger(), "Molar abundance must be non-negative. Instead got {} for species {}.", y, sp.name());
throw exceptions::InvalidCompositionError("Molar abundance must be non-negative. Instead got " + std::to_string(y) + " for species " + std::string(sp.name()) + ".");
}
}
m_molarAbundances = molar_abundances;
m_cache.clear();
return;
}
}
for (size_t i = 0; i < species.size(); ++i) {
const double y = molar_abundances[i];
const auto& sp = species[i];
if (__builtin_expect(y < 0.0, 0)) {
LOG_CRITICAL(getLogger(), "Molar abundance must be non-negative. Instead got {} for species {}.", y, sp.name());
throw exceptions::InvalidCompositionError("Molar abundance must be non-negative. Instead got " + std::to_string(y) + " for species " + std::string(sp.name()) + ".");
}
const std::expected<std::ptrdiff_t, SpeciesIndexLookupError> speciesIndexResult = findSpeciesIndex(sp);
if (__builtin_expect(!speciesIndexResult, 0)) {
throw_unregistered_symbol(getLogger(), std::string(sp.name()));
}
const std::ptrdiff_t speciesIndex = speciesIndexResult.value();
m_molarAbundances[speciesIndex] = y;
}
m_cache.clear();
}
//------------------------------------------
// Fraction and abundance getters
//------------------------------------------
double Composition::getMassFraction(const std::string& symbol) const {
const auto species = getSpecies(symbol);
if (!species) {
throw_unknown_symbol(getLogger(), symbol);
}
return getMassFraction(species.value());
}
double Composition::getMassFraction(
const atomic::Species &species
) const {
const std::expected<std::ptrdiff_t, SpeciesIndexLookupError> speciesIndexResult = findSpeciesIndex(species);
if (!speciesIndexResult) {
throw_unregistered_symbol(getLogger(), std::string(species.name()));
}
double totalMass = 0;
double speciesMass = 0;
for (const auto& [sp, y] : *this) {
const double contrib = y * sp.mass();
totalMass += contrib;
if (sp == species) {
speciesMass = contrib;
}
}
return speciesMass / totalMass;
}
std::unordered_map<atomic::Species, double> Composition::getMassFraction() const noexcept {
std::unordered_map<atomic::Species, double> mass_fractions;
for (const auto &species: *this | std::views::keys) {
mass_fractions.emplace(species, getMassFraction(species));
}
return mass_fractions;
}
double Composition::getNumberFraction(
const std::string& symbol
) const {
const auto species = getSpecies(symbol);
if (!species) {
throw_unknown_symbol(getLogger(), symbol);
}
return getNumberFraction(species.value());
}
double Composition::getNumberFraction(
const atomic::Species &species
) const {
const std::expected<std::ptrdiff_t, SpeciesIndexLookupError> speciesIndexResult = findSpeciesIndex(species);
if (!speciesIndexResult) {
throw_unregistered_symbol(getLogger(), std::string(species.name()));
}
const std::ptrdiff_t speciesIndex = speciesIndexResult.value();
const double total_moles_per_gram = std::accumulate(
m_molarAbundances.begin(),
m_molarAbundances.end(),
0.0
);
return m_molarAbundances[speciesIndex] / total_moles_per_gram;
}
std::unordered_map<atomic::Species, double> Composition::getNumberFraction() const noexcept {
std::unordered_map<atomic::Species, double> number_fractions;
for (const auto &species: m_species) {
number_fractions.emplace(species, getNumberFraction(species));
}
return number_fractions;
}
double Composition::getMolarAbundance(
const std::string &symbol
) const {
const auto species = getSpecies(symbol);
if (!species) {
throw_unknown_symbol(getLogger(), symbol);
}
return getMolarAbundance(species.value());
}
double Composition::getMolarAbundance(
const atomic::Species &species
) const {
const std::expected<std::ptrdiff_t, SpeciesIndexLookupError> speciesIndexResult = findSpeciesIndex(species);
if (!speciesIndexResult) {
throw_unregistered_symbol(getLogger(), std::string(species.name()));
}
const std::ptrdiff_t speciesIndex = speciesIndexResult.value();
return m_molarAbundances[speciesIndex];
}
//------------------------------------------
// Derived property getters
//------------------------------------------
double Composition::getMeanParticleMass() const noexcept {
double totalMass = 0.0;
double totalMoles = 0.0;
for (size_t i = 0; i < m_species.size(); ++i) {
totalMoles += m_molarAbundances[i];
totalMass += m_molarAbundances[i] * m_species[i].mass();
}
return totalMass / totalMoles;
}
double Composition::getElectronAbundance() const noexcept {
double Ye = 0.0;
for (const auto& [species, y] : *this) {
Ye += species.z() * y;
}
return Ye;
}
CanonicalComposition Composition::getCanonicalComposition(
) const {
using namespace fourdst::atomic;
if (m_cache.canonicalComp.has_value()) {
return m_cache.canonicalComp.value(); // Short circuit if we have cached the canonical composition
}
CanonicalComposition canonicalComposition;
static const std::unordered_set<Species> canonicalH = {H_1, H_2, H_3, H_4, H_5, H_6, H_7};
static const std::unordered_set<Species> canonicalHe = {He_3, He_4, He_5, He_6, He_7, He_8, He_9, He_10};
for (const auto& symbol : canonicalH) {
if (contains(symbol)) {
canonicalComposition.X += getMassFraction(symbol);
}
}
for (const auto& symbol : canonicalHe) {
if (contains(symbol)) {
canonicalComposition.Y += getMassFraction(symbol);
}
}
for (const auto& species : m_species) {
if (canonicalH.contains(species) || canonicalHe.contains(species)) {
continue; // Skip canonical H and He symbols
}
canonicalComposition.Z += getMassFraction(species);
}
// ReSharper disable once CppTooWideScopeInitStatement
const double Z = 1.0 - (canonicalComposition.X + canonicalComposition.Y);
if (std::abs(Z - canonicalComposition.Z) > 1e-16) {
LOG_ERROR(getLogger(), "Validation composition Z (X-Y = {}) is different than canonical composition Z ({}) (∑a_i where a_i != H/He).", Z, canonicalComposition.Z);
throw exceptions::InvalidCompositionError("Validation composition Z (X-Y = " + std::to_string(Z) + ") is different than canonical composition Z (" + std::to_string(canonicalComposition.Z) + ") (∑a_i where a_i != H/He).");
}
m_cache.canonicalComp = canonicalComposition;
return canonicalComposition;
}
//------------------------------------------
// Vector getters
//------------------------------------------
std::vector<double> Composition::getMassFractionVector() const noexcept {
if (m_cache.massFractions.has_value()) {
return m_cache.massFractions.value(); // Short circuit if we have cached the mass fractions
}
std::vector<double> massFractionVector;
massFractionVector.reserve(m_molarAbundances.size());
for (const auto &species: m_species) {
massFractionVector.push_back(getMassFraction(species));
}
m_cache.massFractions = massFractionVector; // Cache the result
return massFractionVector;
}
std::vector<double> Composition::getNumberFractionVector() const noexcept {
if (m_cache.numberFractions.has_value()) {
return m_cache.numberFractions.value(); // Short circuit if we have cached the number fractions
}
std::vector<double> numberFractionVector;
numberFractionVector.reserve(m_molarAbundances.size());
for (const auto &species: m_species) {
numberFractionVector.push_back(getNumberFraction(species));
}
m_cache.numberFractions = numberFractionVector; // Cache the result
return numberFractionVector;
}
std::vector<double> Composition::getMolarAbundanceVector() const noexcept {
return m_molarAbundances;
}
//------------------------------------------
// Species index getters and lookups
//------------------------------------------
size_t Composition::getSpeciesIndex(
const std::string &symbol
) const {
const auto species = getSpecies(symbol);
if (!species) {
throw_unknown_symbol(getLogger(), symbol);
}
return getSpeciesIndex(species.value());
}
size_t Composition::getSpeciesIndex(
const atomic::Species &species
) const {
std::expected<std::ptrdiff_t, SpeciesIndexLookupError> speciesIndexResult = findSpeciesIndex(species);
if (!speciesIndexResult) {
switch (speciesIndexResult.error()) {
case SpeciesIndexLookupError::NO_REGISTERED_SPECIES:
[[fallthrough]];
case SpeciesIndexLookupError::SPECIES_NOT_FOUND:
throw_unregistered_symbol(getLogger(), std::string(species.name()));
default:
throw std::logic_error("Unhandled SpeciesIndexLookupError in Composition::getSpeciesIndex");
}
}
return static_cast<size_t>(speciesIndexResult.value());
}
atomic::Species Composition::getSpeciesAtIndex(
const size_t index
) const {
if (index >= m_species.size()) {
LOG_ERROR(getLogger(), "Index {} is out of bounds for registered species (size {}).", index, m_species.size());
throw std::out_of_range("Index " + std::to_string(index) + " is out of bounds for registered species (size " + std::to_string(m_species.size()) + ").");
}
return m_species[index];
}
//------------------------------------------
// Utility methods
//------------------------------------------
std::size_t Composition::hash() const {
if (m_cache.hash.has_value()) {
return m_cache.hash.value();
}
std::size_t hash = utils::CompositionHash::hash_exact(*this);
m_cache.hash = hash;
return hash;
}
bool Composition::contains(
const atomic::Species &species
) const noexcept {
return std::ranges::binary_search(m_species, species);
}
bool Composition::contains(
const std::string &symbol
) const {
const auto species = getSpecies(symbol);
if (!species) {
throw_unknown_symbol(getLogger(), symbol);
}
return contains(species.value());
}
size_t Composition::size() const noexcept {
return m_species.size();
}
std::expected<std::ptrdiff_t, Composition::SpeciesIndexLookupError> Composition::findSpeciesIndex(const atomic::Species &species) const noexcept {
if (m_species.empty()) return std::unexpected(SpeciesIndexLookupError::NO_REGISTERED_SPECIES);
const auto it = std::ranges::lower_bound(m_species, species);
if (it == m_species.end() || *it != species) {
return std::unexpected(SpeciesIndexLookupError::SPECIES_NOT_FOUND);
}
return std::distance(m_species.begin(), it);
}
std::vector<atomic::Species> Composition::symbolVectorToSpeciesVector(const std::vector<std::string> &symbols) {
std::vector<atomic::Species> species;
species.reserve(symbols.size());
for (const auto& symbol : symbols) {
const auto speciesResult = getSpecies(symbol);
if (!speciesResult) {
throw_unknown_symbol(getLogger(), symbol);
}
species.push_back(speciesResult.value());
}
return species;
}
//------------------------------------------
// Stream operator
//------------------------------------------
std::ostream& operator<<(
std::ostream& os,
const Composition& composition
) {
os << "Composition(Mass Fractions => [";
size_t count = 0;
for (const auto &species : composition.m_species) {
os << species << ": " << composition.getMassFraction(species);
if (count < composition.size() - 1) {
os << ", ";
}
count++;
}
os << "])";
return os;
}
} // namespace fourdst::composition
atomicSpecies.h
fourdst::composition::CompositionAbstract
Abstract base class for chemical composition representations.
Definition composition_abstract.h:36
fourdst::composition::CompositionAbstract::getMolarAbundance
virtual double getMolarAbundance(const std::string &symbol) const =0
Get the molar abundance for a given symbol.
fourdst::composition::CompositionAbstract::getRegisteredSpecies
virtual const std::vector< atomic::Species > & getRegisteredSpecies() const noexcept=0
Get all registered atomic species in the composition.
fourdst::composition::Composition::m_cache
CompositionCache m_cache
Cache for computed properties to avoid redundant calculations.
Definition composition.h:167
fourdst::composition::Composition::getSpeciesIndex
size_t getSpeciesIndex(const std::string &symbol) const override
get the index in the sorted vector representation for a given symbol
Definition composition.cpp:639
fourdst::composition::Composition::contains
bool contains(const atomic::Species &species) const noexcept override
Checks if a given species is present in the composition.
Definition composition.cpp:693
fourdst::composition::Composition::getNumberFraction
std::unordered_map< atomic::Species, double > getNumberFraction() const noexcept override
Gets the number fractions of all species in the composition.
Definition composition.cpp:496
fourdst::composition::Composition::Composition
Composition()=default
Default constructor.
fourdst::composition::Composition::setMolarAbundance
void setMolarAbundance(const std::string &symbol, const double &molar_abundance)
Sets the molar abundance for a given symbol.
Definition composition.cpp:321
fourdst::composition::Composition::registerSpecies
void registerSpecies(const atomic::Species &species) noexcept
Registers a new species by extracting its symbol.
Definition composition.cpp:251
fourdst::composition::Composition::registerSymbol
void registerSymbol(const std::string &symbol)
Registers a new symbol for inclusion in the composition.
Definition composition.cpp:234
fourdst::composition::Composition::getRegisteredSymbols
std::set< std::string > getRegisteredSymbols() const noexcept override
Gets the registered symbols.
Definition composition.cpp:304
fourdst::composition::Composition::symbolVectorToSpeciesVector
static std::vector< atomic::Species > symbolVectorToSpeciesVector(const std::vector< std::string > &symbols)
Definition composition.cpp:725
fourdst::composition::Composition::getLogger
static quill::Logger * getLogger()
Gets the logger instance for the Composition class. This is static to ensure that all composition obj...
Definition composition.h:156
fourdst::composition::Composition::operator=
Composition & operator=(Composition const &other)
Assignment operator.
Definition composition.cpp:204
fourdst::composition::Composition::clone
std::unique_ptr< CompositionAbstract > clone() const override
Definition composition.cpp:226
fourdst::composition::Composition::hash
std::size_t hash() const override
Definition composition.cpp:684
fourdst::composition::Composition::getElectronAbundance
double getElectronAbundance() const noexcept override
Compute the electron abundance of the composition.
Definition composition.cpp:543
fourdst::composition::Composition::size
size_t size() const noexcept override
Gets the number of registered species in the composition.
Definition composition.cpp:709
fourdst::composition::Composition::getMassFraction
std::unordered_map< atomic::Species, double > getMassFraction() const noexcept override
Gets the mass fractions of all species in the composition.
Definition composition.cpp:460
fourdst::composition::Composition::m_species
std::vector< atomic::Species > m_species
Definition composition.h:164
fourdst::composition::Composition::getCanonicalComposition
CanonicalComposition getCanonicalComposition() const
Compute the canonical composition (X, Y, Z) of the composition.
Definition composition.cpp:552
fourdst::composition::Composition::m_molarAbundances
std::vector< double > m_molarAbundances
Definition composition.h:165
fourdst::composition::Composition::getMolarAbundanceVector
std::vector< double > getMolarAbundanceVector() const noexcept override
Get a uniform vector representation of the molar abundances stored in the composition object sorted s...
Definition composition.cpp:631
fourdst::composition::Composition::getMolarAbundance
double getMolarAbundance(const std::string &symbol) const override
Gets the molar abundances of all species in the composition.
Definition composition.cpp:504
fourdst::composition::Composition::findSpeciesIndex
std::expected< std::ptrdiff_t, SpeciesIndexLookupError > findSpeciesIndex(const atomic::Species &species) const noexcept
Definition composition.cpp:713
fourdst::composition::Composition::getNumberFractionVector
std::vector< double > getNumberFractionVector() const noexcept override
Get a uniform vector representation of the number fractions stored in the composition object sorted s...
Definition composition.cpp:614
fourdst::composition::Composition::getSpeciesAtIndex
atomic::Species getSpeciesAtIndex(size_t index) const override
Get the species at a given index in the sorted vector representation.
Definition composition.cpp:668
fourdst::composition::Composition::SpeciesIndexLookupError::SPECIES_NOT_FOUND
@ SPECIES_NOT_FOUND
Definition composition.h:148
fourdst::composition::Composition::SpeciesIndexLookupError::NO_REGISTERED_SPECIES
@ NO_REGISTERED_SPECIES
Definition composition.h:147
fourdst::composition::Composition::getRegisteredSpecies
const std::vector< atomic::Species > & getRegisteredSpecies() const noexcept override
Get a set of all species that are registered in the composition.
Definition composition.cpp:312
fourdst::composition::Composition::getMassFractionVector
std::vector< double > getMassFractionVector() const noexcept override
Get a uniform vector representation of the mass fraction stored in the composition object sorted such...
Definition composition.cpp:596
fourdst::composition::Composition::getMeanParticleMass
double getMeanParticleMass() const noexcept override
Compute the mean particle mass of the composition.
Definition composition.cpp:530
fourdst::composition::exceptions::InvalidCompositionError
Exception thrown when a composition is in an invalid or inconsistent state.
Definition exceptions_composition.h:42
fourdst::composition::exceptions::UnknownSymbolError
Exception thrown when an unknown symbol is encountered.
Definition exceptions_composition.h:78
fourdst::composition::exceptions::UnregisteredSymbolError
Exception thrown when a symbol is used that has not been registered.
Definition exceptions_composition.h:52
composition.h
composition_hash.h
exceptions_composition.h
fourdst::atomic
Contains canonical information about atomic species and elements used by 4D-STAR.
fourdst::atomic::H_7
static const Species H_7("H-7", "H", 5, 6, 1, 7, 940.0, "B-", 23062.0, 652.0, "/2+#", "n ?", 7.052749, 1078.0)
fourdst::atomic::H_2
static const Species H_2("H-2", "H", 0, 1, 1, 2, 1112.2831, "B-", std::numeric_limits< double >::quiet_NaN(), std::numeric_limits< double >::infinity(), "+*", "S=0.0145 78", 2.014101777844, 1.5e-05)
fourdst::atomic::H_6
static const Species H_6("H-6", "H", 4, 5, 1, 6, 961.6395, "B-", 24283.6294, 294.0, "-#", "?;3n ?", 6.044955437, 272.816)
fourdst::atomic::He_10
static const Species He_10("He-10", "He", 6, 8, 2, 10, 2995.134, "B-", 16144.5191, 260.0, "+", "n=100", 10.052815306, 99.676)
fourdst::atomic::He_9
static const Species He_9("He-9", "He", 5, 7, 2, 9, 3349.038, "B-", 15980.9213, 2.5, "/2(+)", "=100", 9.043946414, 50.259)
fourdst::atomic::species
static const std::unordered_map< std::string, const Species & > species
Map of species names to their corresponding Species objects.
Definition species.h:3579
fourdst::atomic::He_8
static const Species He_8("He-8", "He", 4, 6, 2, 8, 3924.521, "B-", 10663.8784, 119.5, "+", "-=100;B-n=16 1;B-t=0.9 1", 8.033934388, 0.095)
fourdst::atomic::He_3
static const Species He_3("He-3", "He", -1, 1, 2, 3, 2572.68044, "B-", -13736.0, std::numeric_limits< double >::infinity(), "/2+*", "S=0.0002 2", 3.01602932197, 6e-05)
fourdst::atomic::H_1
static const Species H_1("H-1", "H", -1, 0, 1, 1, 0.0, "B-", std::numeric_limits< double >::quiet_NaN(), std::numeric_limits< double >::infinity(), "/2+*", "S=99.9855 78", 1.007825031898, 1.4e-05)
fourdst::atomic::H_5
static const Species H_5("H-5", "H", 3, 4, 1, 5, 1336.3592, "B-", 21661.2131, 86.0, "1/2+)", "n=100", 5.035311492, 96.02)
fourdst::atomic::He_7
static const Species He_7("He-7", "He", 3, 5, 2, 7, 4123.0578, "B-", 11166.0229, 2.51, "3/2)-", "=100", 7.027990652, 8.115)
fourdst::atomic::He_4
static const Species He_4("He-4", "He", 0, 2, 2, 4, 7073.9156, "B-", -22898.274, std::numeric_limits< double >::infinity(), "+", "S=99.9998 2", 4.00260325413, 0.00016)
fourdst::atomic::He_5
static const Species He_5("He-5", "He", 1, 3, 2, 5, 5512.1325, "B-", -447.6529, 602.0, "/2-", "=100", 5.012057224, 21.47)
fourdst::atomic::H_3
static const Species H_3("H-3", "H", 1, 2, 1, 3, 2827.2654, "B-", 18.59202, 388789632.0, "/2+*", "-=100", 3.01604928132, 8e-05)
fourdst::atomic::He_6
static const Species He_6("He-6", "He", 2, 4, 2, 6, 4878.5199, "B-", 3505.2147, 806.92, "+", "-=100;B-d=0.000278 18", 6.018885889, 0.057)
fourdst::atomic::H_4
static const Species H_4("H-4", "H", 2, 3, 1, 4, 1720.4491, "B-", 22196.2131, 139.0, "-", "=100", 4.026431867, 107.354)
fourdst::composition
Utilities and types for representing and manipulating chemical compositions.
fourdst::composition::operator<<
std::ostream & operator<<(std::ostream &os, const Composition &composition)
Definition composition.cpp:746
fourdst::composition::getSpecies
std::optional< fourdst::atomic::Species > getSpecies(const std::string &symbol)
Definition utils.cpp:189
species.h
fourdst::atomic::Species
Represents an atomic species (isotope) with its fundamental physical properties.
Definition atomicSpecies.h:52
fourdst::atomic::Species::name
std::string_view name() const
Gets the name of the species.
Definition atomicSpecies.h:211
fourdst::composition::CanonicalComposition
Represents the canonical (X, Y, Z) composition of stellar material.
Definition composition.h:46
fourdst::composition::CanonicalComposition::Y
double Y
Mass fraction of Helium.
Definition composition.h:48
fourdst::composition::CanonicalComposition::X
double X
Mass fraction of Hydrogen.
Definition composition.h:47
fourdst::composition::CanonicalComposition::Z
double Z
Mass fraction of Metals.
Definition composition.h:49
fourdst::composition::utils::CompositionHash::hash_exact
static uint64_t hash_exact(const CompositionT &comp)
Definition composition_hash.h:18
utils.h