feat(libcomposition): SERiF now uses libcomposition instead of internal composition module

This commit is contained in:
2025-06-21 12:26:02 -04:00
parent acf7ac0b56
commit 1b26404a86
35 changed files with 77 additions and 12904 deletions

View File

@@ -1,206 +0,0 @@
#include <gtest/gtest.h>
#include <stdexcept>
#include <string>
#include <algorithm>
#include "atomicSpecies.h"
#include "composition.h"
#include "config.h"
std::string EXAMPLE_FILENAME = std::string(getenv("MESON_SOURCE_ROOT")) + "/tests/config/example.yaml";
/**
* @brief Test suite for the composition class.
*/
class compositionTest : public ::testing::Test {};
/**
* @brief Test the constructor of the composition class.
*/
TEST_F(compositionTest, isotopeMasses) {
EXPECT_NO_THROW(chemSpecies::species.at("H-1"));
EXPECT_DOUBLE_EQ(chemSpecies::species.at("H-1").mass(), 1.007825031898);
EXPECT_DOUBLE_EQ(chemSpecies::species.at("He-3").mass(), 3.0160293219700001);
EXPECT_DOUBLE_EQ(chemSpecies::species.at("He-4").mass(),4.0026032541300003);
}
TEST_F(compositionTest, constructor) {
fourdst::config::Config::getInstance().loadConfig(EXAMPLE_FILENAME);
EXPECT_NO_THROW(serif::composition::Composition comp);
}
TEST_F(compositionTest, registerSymbol) {
fourdst::config::Config::getInstance().loadConfig(EXAMPLE_FILENAME);
serif::composition::Composition comp;
EXPECT_NO_THROW(comp.registerSymbol("H-1"));
EXPECT_NO_THROW(comp.registerSymbol("He-4"));
EXPECT_THROW(comp.registerSymbol("H-19"), std::runtime_error);
EXPECT_THROW(comp.registerSymbol("He-21"), std::runtime_error);
std::set<std::string> registeredSymbols = comp.getRegisteredSymbols();
EXPECT_TRUE(registeredSymbols.find("H-1") != registeredSymbols.end());
EXPECT_TRUE(registeredSymbols.find("He-4") != registeredSymbols.end());
EXPECT_TRUE(registeredSymbols.find("H-19") == registeredSymbols.end());
EXPECT_TRUE(registeredSymbols.find("He-21") == registeredSymbols.end());
}
TEST_F(compositionTest, setGetComposition) {
fourdst::config::Config::getInstance().loadConfig(EXAMPLE_FILENAME);
serif::composition::Composition comp;
comp.registerSymbol("H-1");
comp.registerSymbol("He-4");
EXPECT_DOUBLE_EQ(comp.setMassFraction("H-1", 0.5), 0.0);
EXPECT_DOUBLE_EQ(comp.setMassFraction("He-4", 0.5), 0.0);
EXPECT_DOUBLE_EQ(comp.setMassFraction("H-1", 0.6), 0.5);
EXPECT_DOUBLE_EQ(comp.setMassFraction("He-4", 0.4), 0.5);
EXPECT_NO_THROW(comp.finalize());
EXPECT_DOUBLE_EQ(comp.getMassFraction("H-1"), 0.6);
EXPECT_THROW(comp.setMassFraction("He-3", 0.3), std::runtime_error);
EXPECT_NO_THROW(comp.setMassFraction({"H-1", "He-4"}, {0.5, 0.5}));
EXPECT_THROW(auto r = comp.getComposition("H-1"), std::runtime_error);
EXPECT_TRUE(comp.finalize());
EXPECT_DOUBLE_EQ(comp.getComposition("H-1").first.mass_fraction(), 0.5);
EXPECT_NO_THROW(comp.setMassFraction({"H-1", "He-4"}, {0.6, 0.6}));
EXPECT_FALSE(comp.finalize());
EXPECT_THROW(auto r = comp.getComposition("H-1"), std::runtime_error);
}
TEST_F(compositionTest, setGetNumberFraction) {
fourdst::config::Config::getInstance().loadConfig(EXAMPLE_FILENAME);
serif::composition::Composition comp;
comp.registerSymbol("H-1", false);
comp.registerSymbol("He-4", false);
EXPECT_DOUBLE_EQ(comp.setNumberFraction("H-1", 0.5), 0.0);
EXPECT_DOUBLE_EQ(comp.setNumberFraction("He-4", 0.5), 0.0);
EXPECT_DOUBLE_EQ(comp.setNumberFraction("H-1", 0.6), 0.5);
EXPECT_DOUBLE_EQ(comp.setNumberFraction("He-4", 0.4), 0.5);
EXPECT_NO_THROW(comp.finalize());
EXPECT_DOUBLE_EQ(comp.getNumberFraction("H-1"), 0.6);
EXPECT_THROW(comp.setNumberFraction("He-3", 0.3), std::runtime_error);
}
TEST_F(compositionTest, subset) {
fourdst::config::Config::getInstance().loadConfig(EXAMPLE_FILENAME);
serif::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());
std::vector<std::string> symbols = {"H-1"};
serif::composition::Composition subsetComp = comp.subset(symbols, "norm");
EXPECT_TRUE(subsetComp.finalize());
EXPECT_DOUBLE_EQ(subsetComp.getMassFraction("H-1"), 1.0);
}
TEST_F(compositionTest, finalizeWithNormalization) {
fourdst::config::Config::getInstance().loadConfig(EXAMPLE_FILENAME);
serif::composition::Composition comp;
comp.registerSymbol("H-1");
comp.registerSymbol("He-4");
comp.setMassFraction("H-1", 0.3);
comp.setMassFraction("He-4", 0.3);
EXPECT_TRUE(comp.finalize(true));
EXPECT_DOUBLE_EQ(comp.getMassFraction("H-1"), 0.5);
EXPECT_DOUBLE_EQ(comp.getMassFraction("He-4"), 0.5);
}
TEST_F(compositionTest, finalizeWithoutNormalization) {
fourdst::config::Config::getInstance().loadConfig(EXAMPLE_FILENAME);
serif::composition::Composition comp;
comp.registerSymbol("H-1");
comp.registerSymbol("He-4");
comp.setMassFraction("H-1", 0.5);
comp.setMassFraction("He-4", 0.5);
EXPECT_TRUE(comp.finalize(false));
EXPECT_DOUBLE_EQ(comp.getMassFraction("H-1"), 0.5);
EXPECT_DOUBLE_EQ(comp.getMassFraction("He-4"), 0.5);
}
TEST_F(compositionTest, getComposition) {
fourdst::config::Config::getInstance().loadConfig(EXAMPLE_FILENAME);
serif::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());
auto compositionEntry = comp.getComposition("H-1");
EXPECT_DOUBLE_EQ(compositionEntry.first.mass_fraction(), 0.6);
EXPECT_DOUBLE_EQ(compositionEntry.second.meanParticleMass, 1.4382769310381101);
EXPECT_DOUBLE_EQ(compositionEntry.second.specificNumberDensity, 1.0/1.4382769310381101);
}
TEST_F(compositionTest, setCompositionMode) {
fourdst::config::Config::getInstance().loadConfig(EXAMPLE_FILENAME);
serif::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_DOUBLE_EQ(comp.getMassFraction("H-1"), 0.6);
EXPECT_DOUBLE_EQ(comp.getMassFraction("He-4"), 0.4);
EXPECT_NO_THROW(comp.setCompositionMode(false));
EXPECT_NO_THROW(comp.setNumberFraction("H-1", 0.9));
EXPECT_NO_THROW(comp.setNumberFraction("He-4", 0.1));
EXPECT_THROW(comp.setCompositionMode(true), std::runtime_error);
EXPECT_NO_THROW(comp.finalize());
EXPECT_NO_THROW(comp.setCompositionMode(true));
}
TEST_F(compositionTest, hasSymbol) {
fourdst::config::Config::getInstance().loadConfig(EXAMPLE_FILENAME);
serif::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) {
fourdst::config::Config::getInstance().loadConfig(EXAMPLE_FILENAME);
serif::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());
serif::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());
serif::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);
serif::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);
}

View File

@@ -1,23 +0,0 @@
# Test files for const
test_sources = [
'compositionTest.cpp',
]
foreach test_file : test_sources
exe_name = test_file.split('.')[0]
message('Building test: ' + exe_name)
# Create an executable target for each test
test_exe = executable(
exe_name,
test_file,
dependencies: [gtest_dep, species_weight_dep, gtest_main, composition_dep],
install_rpath: '@loader_path/../../src' # Ensure runtime library path resolves correctly
)
# Add the executable as a test
test(
exe_name,
test_exe,
env: ['MESON_SOURCE_ROOT=' + meson.project_source_root(), 'MESON_BUILD_ROOT=' + meson.project_build_root()])
endforeach

View File

@@ -1,91 +0,0 @@
#include "composition.h"
#include "config.h"
#include <string>
int main(int argv, char* argc[]) {
std::string pathToConfigFile;
if (argv == 2) {
pathToConfigFile = argc[1];
} else {
pathToConfigFile = "config.json";
}
fourdst::config::Config::getInstance().loadConfig(pathToConfigFile);
serif::composition::Composition comp;
std::vector<std::string> symbols = {"H-1", "He-4"};
comp.registerSymbol(symbols);
comp.setMassFraction("H-1", 0.7);
comp.setMassFraction("He-4", 0.3);
comp.finalize();
std::cout << "=== Mass Fraction Mode ===" << std::endl;
std::cout << "\tH-1 Mass Frac: " << comp.getMassFraction("H-1") << std::endl;
std::cout << "\tH-1 Number Frac: " << comp.getNumberFraction("H-1") << std::endl;
std::cout << "\tHe-4 Mass Frac: " << comp.getMassFraction("He-4") << std::endl;
std::cout << "\tHe-4 Number Frac: " << comp.getNumberFraction("He-4") << std::endl;
std::cout << "\tMass Frac Sum: " << comp.getMassFraction("H-1") + comp.getMassFraction("He-4") << std::endl;
std::cout << "\tNumber Frac Sum: " << comp.getNumberFraction("H-1") + comp.getNumberFraction("He-4") << std::endl;
serif::composition::Composition comp2;
comp2.registerSymbol(symbols, false);
comp2.setNumberFraction("H-1", comp.getNumberFraction("H-1"));
comp2.setNumberFraction("He-4", comp.getNumberFraction("He-4"));
comp2.finalize();
std::cout << "=== Number Fraction Mode ===" << std::endl;
std::cout << "\tH-1 Mass Frac: " << comp2.getMassFraction("H-1") << std::endl;
std::cout << "\tH-1 Number Frac: " << comp2.getNumberFraction("H-1") << std::endl;
std::cout << "\tHe-4 Mass Frac: " << comp2.getMassFraction("He-4") << std::endl;
std::cout << "\tHe-4 Number Frac: " << comp2.getNumberFraction("He-4") << std::endl;
std::cout << "\tMass Frac Sum: " << comp2.getMassFraction("H-1") + comp2.getMassFraction("He-4") << std::endl;
std::cout << "\tNumber Frac Sum: " << comp2.getNumberFraction("H-1") + comp2.getNumberFraction("He-4") << std::endl;
std::vector<std::string> symbols3 = {
"H-1",
"He-3",
"He-4",
"Li-6",
"Li-7",
"O-16",
"C-12",
"Fe-56",
"Ne-20",
"N-14",
"Mg-24",
"Si-28",
"S-32",
"Ca-40",
};
std::vector<double> mass_fractions = {
0.71243,
1e-5,
0.27,
1e-11,
1e-9,
0.009,
0.003,
0.0014,
0.0015,
0.001,
0.0006,
0.0006,
0.0004,
0.00006
};
serif::composition::Composition comp3(symbols3, mass_fractions, true);
std::cout << "=== Mass Fraction Mode ===" << std::endl;
double massFracSum = 0.0;
double numberFracSum = 0.0;
for (const auto& symbol : symbols3) {
std::cout << "\t" << symbol << " Mass Frac: " << comp3.getMassFraction(symbol) << std::endl;
std::cout << "\t" << symbol << " Number Frac: " << comp3.getNumberFraction(symbol) << std::endl;
massFracSum += comp3.getMassFraction(symbol);
numberFracSum += comp3.getNumberFraction(symbol);
}
std::cout << "\tMass Frac Sum: " << massFracSum << std::endl;
std::cout << "\tNumber Frac Sum: " << numberFracSum << std::endl;
return 0;
}

View File

@@ -1,2 +0,0 @@
Composition:
Tracked: "H-1"

View File

@@ -1 +0,0 @@
executable('composition_sandbox', 'comp.cpp', dependencies: [composition_dep, config_dep])

View File

@@ -87,7 +87,7 @@ TEST_F(eosTest, get_helm_EOS) {
}
TEST_F(eosTest, eos_using_composition) {
serif::composition::Composition composition;
fourdst::composition::Composition composition;
composition.registerSymbol({
"H-1",
"He-4",

View File

@@ -9,9 +9,6 @@ subdir('probe')
subdir('eos')
subdir('resource')
subdir('network')
subdir('composition')
subdir('poly')
# Subdirectories for sandbox tests
subdir('composition_sandbox')

View File

@@ -35,7 +35,7 @@ TEST_F(approx8Test, evaluate) {
std::vector<double> comp = {0.708, 2.94e-5, 0.276, 0.003, 0.0011, 9.62e-3, 1.62e-3, 5.16e-4};
std::vector<std::string> symbols = {"H-1", "He-3", "He-4", "C-12", "N-14", "O-16", "Ne-20", "Mg-24"};
serif::composition::Composition composition;
fourdst::composition::Composition composition;
composition.registerSymbol(symbols, true);
composition.setMassFraction(symbols, comp);
bool isFinalized = composition.finalize(true);

View File

@@ -11,7 +11,7 @@ foreach test_file : test_sources
test_exe = executable(
exe_name,
test_file,
dependencies: [gtest_dep, gtest_main, network_dep, species_weight_dep, composition_dep],
dependencies: [gtest_dep, gtest_main, network_dep, composition_dep],
include_directories: include_directories('../../src/network/public'),
link_with: libnetwork, # Link the dobj library
install_rpath: '@loader_path/../../src' # Ensure runtime library path resolves correctly