Files
libcomposition/src/composition/public/composition.h

455 lines
19 KiB
C++

#ifndef COMPOSITION_H
#define COMPOSITION_H
#include <iostream>
#include <string>
#include <unordered_map>
#include <set>
#include <utility>
#include "probe.h"
#include "config.h"
#include "atomicSpecies.h"
namespace composition{
/**
* @brief Represents the global composition of a system. This tends to be used after finalize and is primarily for internal use.
*/
struct GlobalComposition {
double specificNumberDensity; ///< The specific number density of the composition (\sum_{i} X_i m_i. Where X_i is the number fraction of the ith species and m_i is the mass of the ith species).
double meanParticleMass; ///< The mean particle mass of the composition (\sum_{i} \frac{n_i}{m_i}. where n_i is the number fraction of the ith species and m_i is the mass of the ith species).
// Overload the output stream operator for GlobalComposition
friend std::ostream& operator<<(std::ostream& os, const GlobalComposition& comp) {
os << "Global Composition: \n";
os << "\tSpecific Number Density: " << comp.specificNumberDensity << "\n";
os << "\tMean Particle Mass: " << comp.meanParticleMass << "\n";
return os;
}
};
/**
* @brief Represents an entry in the composition with a symbol and mass fraction.
*/
struct CompositionEntry {
std::string m_symbol; ///< The chemical symbol of the species.
chemSpecies::Species m_isotope; ///< The isotope of the species.
bool m_massFracMode = true; ///< The mode of the composition entry. True if mass fraction, false if number fraction.
double m_massFraction = 0.0; ///< The mass fraction of the species.
double m_numberFraction = 0.0; ///< The number fraction of the species.
double m_relAbundance = 0.0; ///< The relative abundance of the species for converting between mass and number fractions.
bool m_initialized = false; ///< True if the composition entry has been initialized.
/**
* @brief Default constructor.
*/
CompositionEntry();
/**
* @brief Constructs a CompositionEntry with the given symbol and mode.
* @param symbol The chemical symbol of the species.
* @param massFracMode True if mass fraction mode, false if number fraction mode.
* @example
* @code
* CompositionEntry entry("H", true);
* @endcode
*/
CompositionEntry(const std::string& symbol, bool massFracMode=true);
/**
* @brief Copy constructor.
* @param entry The CompositionEntry to copy.
*/
CompositionEntry(const CompositionEntry& entry);
/**
* @brief Sets the species for the composition entry.
* @param symbol The chemical symbol of the species.
*/
void setSpecies(const std::string& symbol);
/**
* @brief Gets the chemical symbol of the species.
* @return The chemical symbol of the species.
*/
std::string symbol() const;
/**
* @brief Gets the mass fraction of the species.
* @return The mass fraction of the species.
*/
double mass_fraction() const;
/**
* @brief Gets the mass fraction of the species given the mean molar mass.
* @param meanMolarMass The mean molar mass.
* @return The mass fraction of the species.
*/
double mass_fraction(double meanMolarMass) const;
/**
* @brief Gets the number fraction of the species.
* @return The number fraction of the species.
*/
double number_fraction() const;
/**
* @brief Gets the number fraction of the species given the total moles.
* @param totalMoles The total moles.
* @return The number fraction of the species.
*/
double number_fraction(double totalMoles) const;
/**
* @brief Gets the relative abundance of the species.
* @return The relative abundance of the species.
*/
double rel_abundance() const;
/**
* @brief Gets the isotope of the species.
* @return The isotope of the species.
*/
chemSpecies::Species isotope() const;
/**
* @brief Gets the mode of the composition entry.
* @return True if mass fraction mode, false if number fraction mode.
*/
bool getMassFracMode() const;
/**
* @brief Sets the mass fraction of the species.
* @param mass_fraction The mass fraction to set.
*/
void setMassFraction(double mass_fraction);
/**
* @brief Sets the number fraction of the species.
* @param number_fraction The number fraction to set.
*/
void setNumberFraction(double number_fraction);
/**
* @brief Sets the mode to mass fraction mode.
* @param meanMolarMass The mean molar mass.
* @return True if the mode was successfully set, false otherwise.
*/
bool setMassFracMode(double meanMolarMass);
/**
* @brief Sets the mode to number fraction mode.
* @param totalMoles The total moles.
* @return True if the mode was successfully set, false otherwise.
*/
bool setNumberFracMode(double totalMoles);
/**
* @brief Overloaded output stream operator for CompositionEntry.
* @param os The output stream.
* @param entry The CompositionEntry to output.
* @return The output stream.
*/
friend std::ostream& operator<<(std::ostream& os, const CompositionEntry& entry) {
os << "<" << entry.m_symbol << " : m_frac = " << entry.mass_fraction() << ">";
return os;
}
};
/**
* @brief Manages the composition of elements.
* @details The composition is a collection of elements with their respective mass fractions.
* The general purpose of this class is to provide a standardized interface for managing the composition of
* any part of 4DSSE. There are a few rules when using this class.
* - Only species in the atomicSpecies.h database can be used. There are 1000s (All species from AME2020) in there so it should not be a problem.
* - Before a mass fraction can be set with a particular instance of Composition, the symbol must be registered. (i.e. register He-3 before setting its mass fraction)
* - Before any composition information can be retrived (e.g. getComposition), the composition must be finalized (call to .finalize()). This checks if the total mass fraction sums to approximatly 1 (within 1 part in 10^8)
* - Any changes made to the composition after finalization will "unfinalize" the composition. This means that the composition must be finalized again before any information can be retrived.
* - The mass fraction of any individual species must be no more than 1 and no less than 0.
* - The only exception to the finalize rule is if the compositon was constructed with symbols and mass fractions at instantiation time. In this case, the composition is automatically finalized.
* however, this means that the composition passed to the constructor must be valid.
*
* @example Constructing a finalized composition with symbols and mass fractions:
* @code
* std::vector<std::string> symbols = {"H", "He"};
* std::vector<double> mass_fractions = {0.7, 0.3};
* Composition comp(symbols, mass_fractions);
* @endcode
* @example Constructing a composition with symbols and finalizing it later:
* @code
* std::vector<std::string> symbols = {"H", "He"};
* Composition comp(symbols);
* comp.setComposition("H", 0.7);
* comp.setComposition("He", 0.3);
* comp.finalize();
* @endcode
*/
class Composition {
private:
Probe::LogManager& m_logManager = Probe::LogManager::getInstance();
quill::Logger* m_logger = m_logManager.getLogger("log");
bool m_finalized = false; ///< True if the composition is finalized.
double m_specificNumberDensity = 0.0; ///< The specific number density of the composition (\sum_{i} X_i m_i. Where X_i is the number fraction of the ith species and m_i is the mass of the ith species).
double m_meanParticleMass = 0.0; ///< The mean particle mass of the composition (\sum_{i} \frac{n_i}{m_i}. where n_i is the number fraction of the ith species and m_i is the mass of the ith species).
bool m_massFracMode = true; ///< True if mass fraction mode, false if number fraction mode.
std::set<std::string> m_registeredSymbols; ///< The registered symbols.
std::unordered_map<std::string, CompositionEntry> m_compositions; ///< The compositions.
/**
* @brief Checks if the given symbol is valid.
* @details A symbol is valid if it is in the atomic species database (species in atomicSpecies.h). These include all the isotopes from AME2020.
* @param symbol The symbol to check.
* @return True if the symbol is valid, false otherwise.
*/
bool isValidSymbol(const std::string& symbol) const;
/**
* @brief Checks if the given mass fractions are valid.
* @param mass_fractions The mass fractions to check.
* @return True if the mass fractions are valid, false otherwise.
*/
bool isValidComposition(const std::vector<double>& fractions) const;
/**
* @brief Validates the given mass fractions.
* @param mass_fractions The mass fractions to validate.
* @throws std::invalid_argument if the mass fractions are invalid.
*/
void validateComposition(const std::vector<double>& fractions) const;
/**
* @brief Finalizes the composition in mass fraction mode.
* @param norm If true, the composition will be normalized to sum to 1.
* @return True if the composition is successfully finalized, false otherwise.
*/
bool finalizeMassFracMode(bool norm);
/**
* @brief Finalizes the composition in number fraction mode.
* @param norm If true, the composition will be normalized to sum to 1.
* @return True if the composition is successfully finalized, false otherwise.
*/
bool finalizeNumberFracMode(bool norm);
public:
/**
* @brief Default constructor.
*/
Composition() = default;
/**
* @brief Default destructor.
*/
~Composition() = default;
/**
* @brief Finalizes the composition.
* @param norm If true, the composition will be normalized to sum to 1 [Default False]
* @return True if the composition is successfully finalized, false otherwise.
*/
bool finalize(bool norm=false);
/**
* @brief Constructs a Composition with the given symbols.
* @param symbols The symbols to initialize the composition with.
* @example
* @code
* std::vector<std::string> symbols = {"H", "O"};
* Composition comp(symbols);
* @endcode
*/
Composition(const std::vector<std::string>& symbols);
/**
* @brief Constructs a Composition with the given symbols as a set.
* @param symbols The symbols to initialize the composition with.
* @example
* @code
* std::set<std::string> symbols = {"H", "O"};
* Composition comp(symbols);
* @endcode
*/
Composition(const std::set<std::string>& symbols);
/**
* @brief Constructs a Composition with the given symbols and mass fractions.
* @param symbols The symbols to initialize the composition with.
* @param mass_fractions The mass fractions corresponding to the symbols.
* @param massFracMode True if mass fraction mode, false if number fraction mode.
* @example
* @code
* std::vector<std::string> symbols = {"H", "O"};
* std::vector<double> mass_fractions = {0.1, 0.9};
* Composition comp(symbols, mass_fractions);
* @endcode
*/
Composition(const std::vector<std::string>& symbols, const std::vector<double>& mass_fractions, bool massFracMode=true);
/**
* @brief Registers a new symbol.
* @param symbol The symbol to register.
* @param massFracMode True if mass fraction mode, false if number fraction mode.
* @example
* @code
* Composition comp;
* comp.registerSymbol("H");
* @endcode
*/
void registerSymbol(const std::string& symbol, bool massFracMode=true);
/**
* @brief Registers multiple new symbols.
* @param symbols The symbols to register.
* @param massFracMode True if mass fraction mode, false if number fraction mode.
* @example
* @code
* std::vector<std::string> symbols = {"H", "O"};
* Composition comp;
* comp.registerSymbol(symbols);
* @endcode
*/
void registerSymbol(const std::vector<std::string>& symbols, bool massFracMode=true);
/**
* @brief Gets the registered symbols.
* @return A set of registered symbols.
*/
std::set<std::string> getRegisteredSymbols() const;
/**
* @brief Sets the mass fraction for a given symbol.
* @param symbol The symbol to set the mass fraction for.
* @param mass_fraction The mass fraction to set.
* @return The mass fraction that was set.
* @example
* @code
* Composition comp;
* comp.setMassFraction("H", 0.1);
* @endcode
*/
double setMassFraction(const std::string& symbol, const double& mass_fraction);
/**
* @brief Sets the mass fraction for multiple symbols.
* @param symbols The symbols to set the mass fraction for.
* @param mass_fractions The mass fractions corresponding to the symbols.
* @return A vector of mass fractions that were set.
* @example
* @code
* std::vector<std::string> symbols = {"H", "O"};
* std::vector<double> mass_fractions = {0.1, 0.9};
* Composition comp;
* comp.setMassFraction(symbols, mass_fractions);
* @endcode
*/
std::vector<double> setMassFraction(const std::vector<std::string>& symbols, 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.
* @param number_fraction The number fraction to set.
* @return The number fraction that was set.
*/
double setNumberFraction(const std::string& symbol, const double& number_fraction);
/**
* @brief Sets the number fraction for multiple symbols.
* @param symbols The symbols to set the number fraction for.
* @param number_fractions The number fractions corresponding to the symbols.
* @return A vector of number fractions that were set.
*/
std::vector<double> setNumberFraction(const std::vector<std::string>& symbols, const std::vector<double>& number_fractions);
/**
* @brief Mix two compositions together with a given fraction.
* @param other The other composition to mix with.
* @param fraction The fraction of the other composition to mix with. This is the fraction of the other composition wrt. to the current. i.e. fraction=1 would mean that 50% of the new composition is from the other and 50% from the current).
*/
Composition mix(const Composition& other, double fraction) const;
/**
* @brief Gets the mass fractions of all compositions.
* @return An unordered map of compositions with their mass fractions.
*/
std::unordered_map<std::string, double> getMassFraction() const;
/**
* @brief Gets the mass fraction for a given symbol.
* @param symbol The symbol to get the mass fraction for.
* @return The mass fraction for the given symbol.
*/
double getMassFraction(const std::string& symbol) const;
/**
* @brief Gets the number fraction for a given symbol.
* @param symbol The symbol to get the number fraction for.
* @return The number fraction for the given symbol.
*/
double getNumberFraction(const std::string& symbol) const;
/**
* @brief Gets the number fractions of all compositions.
* @return An unordered map of compositions with their number fractions.
*/
std::unordered_map<std::string, double> getNumberFraction() const;
/**
* @brief Gets the composition entry and global composition for a given symbol.
* @param symbol The symbol to get the composition for.
* @return A pair containing the CompositionEntry and GlobalComposition for the given symbol.
*/
std::pair<CompositionEntry, GlobalComposition> getComposition(const std::string& symbol) const;
/**
* @brief Gets all composition entries and the global composition.
* @return A pair containing an unordered map of CompositionEntries and the GlobalComposition.
*/
std::pair<std::unordered_map<std::string, CompositionEntry>, GlobalComposition> getComposition() const;
/**
* @brief Gets a subset of the composition.
* @param symbols The symbols to include in the subset.
* @param method The method to use for the subset (default is "norm").
* @return A Composition object containing the subset.
*/
Composition subset(const std::vector<std::string>& symbols, std::string method="norm") const;
/**
* @brief Check if a symbol is registered.
* @param symbol The symbol to check.
* @return True if the symbol is registered, false otherwise.
*/
bool hasSymbol(const std::string& symbol) const;
/**
* @brief Sets the composition mode.
* @param massFracMode True if mass fraction mode, false if number fraction mode.
*/
void setCompositionMode(bool massFracMode);
/**
* @brief Overloaded output stream operator for Composition.
* @param os The output stream.
* @param composition The Composition to output.
* @return The output stream.
*/
friend std::ostream& operator<<(std::ostream& os, const Composition& composition);
// Overload the + operator to call mix with a fraction of 0.5
/**
* @brief Overloads the + operator to mix two compositions together with a fraction of 0.5.
* @param other The other composition to mix with.
* @return The mixed composition.
*/
Composition operator+(const Composition& other) const;
};
};
#endif // COMPOSITION_H