feat(composition): added mix method to combine compositions. Also overloaded the + operator to mix with an assumed fraction of 50/50
This commit is contained in:
@@ -124,6 +124,12 @@ Composition::Composition(const std::vector<std::string>& symbols) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Composition::Composition(const std::set<std::string>& symbols) {
|
||||||
|
for (const auto& symbol : symbols) {
|
||||||
|
registerSymbol(symbol);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Composition::Composition(const std::vector<std::string>& symbols, const std::vector<double>& fractions, bool massFracMode) : m_massFracMode(massFracMode) {
|
Composition::Composition(const std::vector<std::string>& symbols, const std::vector<double>& fractions, bool massFracMode) : m_massFracMode(massFracMode) {
|
||||||
if (symbols.size() != fractions.size()) {
|
if (symbols.size() != fractions.size()) {
|
||||||
LOG_ERROR(m_logger, "The number of symbols and fractions must be equal.");
|
LOG_ERROR(m_logger, "The number of symbols and fractions must be equal.");
|
||||||
@@ -363,6 +369,35 @@ bool Composition::finalizeNumberFracMode(bool norm) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Composition Composition::mix(const Composition& other, double fraction) const {
|
||||||
|
if (!m_finalized || !other.m_finalized) {
|
||||||
|
LOG_ERROR(m_logger, "Compositions have not both been finalized.");
|
||||||
|
throw std::runtime_error("Compositions have not been finalized (Consider running .finalize()).");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fraction < 0.0 || fraction > 1.0) {
|
||||||
|
LOG_ERROR(m_logger, "Fraction must be between 0 and 1.");
|
||||||
|
throw std::runtime_error("Fraction must be between 0 and 1.");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::set<std::string> mixedSymbols = other.getRegisteredSymbols();
|
||||||
|
// Get the union of the two sets
|
||||||
|
mixedSymbols.insert(m_registeredSymbols.begin(), m_registeredSymbols.end());
|
||||||
|
|
||||||
|
Composition mixedComposition(mixedSymbols);
|
||||||
|
for (const auto& symbol : mixedSymbols) {
|
||||||
|
double thisMassFrac, otherMassFrac = 0.0;
|
||||||
|
|
||||||
|
thisMassFrac = hasSymbol(symbol) ? getMassFraction(symbol) : 0.0;
|
||||||
|
otherMassFrac = other.hasSymbol(symbol) ? other.getMassFraction(symbol) : 0.0;
|
||||||
|
|
||||||
|
double massFraction = fraction * thisMassFrac + otherMassFrac * (1-fraction);
|
||||||
|
mixedComposition.setMassFraction(symbol, massFraction);
|
||||||
|
}
|
||||||
|
mixedComposition.finalize();
|
||||||
|
return mixedComposition;
|
||||||
|
}
|
||||||
|
|
||||||
double Composition::getMassFraction(const std::string& symbol) const {
|
double Composition::getMassFraction(const std::string& symbol) const {
|
||||||
if (!m_finalized) {
|
if (!m_finalized) {
|
||||||
LOG_ERROR(m_logger, "Composition has not been finalized.");
|
LOG_ERROR(m_logger, "Composition has not been finalized.");
|
||||||
@@ -476,8 +511,26 @@ void Composition::setCompositionMode(bool massFracMode) {
|
|||||||
}
|
}
|
||||||
if (!okay) {
|
if (!okay) {
|
||||||
LOG_ERROR(m_logger, "Composition mode could not be set.");
|
LOG_ERROR(m_logger, "Composition mode could not be set.");
|
||||||
throw std::runtime_error("Composition mode could not be set.");
|
throw std::runtime_error("Composition mode could not be set due to an unknown error.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m_massFracMode = massFracMode;
|
m_massFracMode = massFracMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Composition::hasSymbol(const std::string& symbol) const {
|
||||||
|
return m_compositions.count(symbol) > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// OVERLOADS
|
||||||
|
|
||||||
|
Composition Composition::operator+(const Composition& other) const {
|
||||||
|
return mix(other, 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ostream& composition::operator<<(std::ostream& os, const Composition& composition) {
|
||||||
|
os << "Composition: \n";
|
||||||
|
for (const auto& [symbol, entry] : composition.m_compositions) {
|
||||||
|
os << entry << "\n";
|
||||||
|
}
|
||||||
|
return os;
|
||||||
|
}
|
||||||
@@ -267,6 +267,17 @@ namespace composition{
|
|||||||
*/
|
*/
|
||||||
Composition(const std::vector<std::string>& symbols);
|
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.
|
* @brief Constructs a Composition with the given symbols and mass fractions.
|
||||||
* @param symbols The symbols to initialize the composition with.
|
* @param symbols The symbols to initialize the composition with.
|
||||||
@@ -356,6 +367,13 @@ namespace composition{
|
|||||||
*/
|
*/
|
||||||
std::vector<double> setNumberFraction(const std::vector<std::string>& symbols, const std::vector<double>& number_fractions);
|
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.
|
* @brief Gets the mass fractions of all compositions.
|
||||||
* @return An unordered map of compositions with their mass fractions.
|
* @return An unordered map of compositions with their mass fractions.
|
||||||
@@ -403,6 +421,13 @@ namespace composition{
|
|||||||
*/
|
*/
|
||||||
Composition subset(const std::vector<std::string>& symbols, std::string method="norm") const;
|
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.
|
* @brief Sets the composition mode.
|
||||||
* @param massFracMode True if mass fraction mode, false if number fraction mode.
|
* @param massFracMode True if mass fraction mode, false if number fraction mode.
|
||||||
@@ -415,13 +440,15 @@ namespace composition{
|
|||||||
* @param composition The Composition to output.
|
* @param composition The Composition to output.
|
||||||
* @return The output stream.
|
* @return The output stream.
|
||||||
*/
|
*/
|
||||||
friend std::ostream& operator<<(std::ostream& os, const Composition& composition) {
|
friend std::ostream& operator<<(std::ostream& os, const Composition& composition);
|
||||||
os << "Composition: \n";
|
|
||||||
for (const auto& [symbol, entry] : composition.m_compositions) {
|
// Overload the + operator to call mix with a fraction of 0.5
|
||||||
os << entry << "\n";
|
/**
|
||||||
}
|
* @brief Overloads the + operator to mix two compositions together with a fraction of 0.5.
|
||||||
return os;
|
* @param other The other composition to mix with.
|
||||||
}
|
* @return The mixed composition.
|
||||||
|
*/
|
||||||
|
Composition operator+(const Composition& other) const;
|
||||||
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -162,3 +162,45 @@ TEST_F(compositionTest, setCompositionMode) {
|
|||||||
EXPECT_NO_THROW(comp.finalize());
|
EXPECT_NO_THROW(comp.finalize());
|
||||||
EXPECT_NO_THROW(comp.setCompositionMode(true));
|
EXPECT_NO_THROW(comp.setCompositionMode(true));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(compositionTest, hasSymbol) {
|
||||||
|
Config::getInstance().loadConfig(EXAMPLE_FILENAME);
|
||||||
|
composition::Composition comp;
|
||||||
|
comp.registerSymbol("H-1");
|
||||||
|
comp.registerSymbol("He-4");
|
||||||
|
comp.setMassFraction("H-1", 0.6);
|
||||||
|
comp.setMassFraction("He-4", 0.4);
|
||||||
|
EXPECT_NO_THROW(comp.finalize());
|
||||||
|
|
||||||
|
EXPECT_TRUE(comp.hasSymbol("H-1"));
|
||||||
|
EXPECT_TRUE(comp.hasSymbol("He-4"));
|
||||||
|
EXPECT_FALSE(comp.hasSymbol("H-2"));
|
||||||
|
EXPECT_FALSE(comp.hasSymbol("He-3"));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(compositionTest, mix) {
|
||||||
|
Config::getInstance().loadConfig(EXAMPLE_FILENAME);
|
||||||
|
composition::Composition comp1;
|
||||||
|
comp1.registerSymbol("H-1");
|
||||||
|
comp1.registerSymbol("He-4");
|
||||||
|
comp1.setMassFraction("H-1", 0.6);
|
||||||
|
comp1.setMassFraction("He-4", 0.4);
|
||||||
|
EXPECT_NO_THROW(comp1.finalize());
|
||||||
|
|
||||||
|
composition::Composition comp2;
|
||||||
|
comp2.registerSymbol("H-1");
|
||||||
|
comp2.registerSymbol("He-4");
|
||||||
|
comp2.setMassFraction("H-1", 0.4);
|
||||||
|
comp2.setMassFraction("He-4", 0.6);
|
||||||
|
EXPECT_NO_THROW(comp2.finalize());
|
||||||
|
|
||||||
|
composition::Composition mixedComp = comp1 + comp2;
|
||||||
|
EXPECT_TRUE(mixedComp.finalize());
|
||||||
|
EXPECT_DOUBLE_EQ(mixedComp.getMassFraction("H-1"), 0.5);
|
||||||
|
EXPECT_DOUBLE_EQ(mixedComp.getMassFraction("He-4"), 0.5);
|
||||||
|
|
||||||
|
composition::Composition mixedComp2 = comp1.mix(comp2, 0.25);
|
||||||
|
EXPECT_TRUE(mixedComp2.finalize());
|
||||||
|
EXPECT_DOUBLE_EQ(mixedComp2.getMassFraction("H-1"), 0.45);
|
||||||
|
EXPECT_DOUBLE_EQ(mixedComp2.getMassFraction("He-4"), 0.55);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user