Introduction
libcomposition
is a modern C++23 library designed for the creation, manipulation, and analysis of chemical compositions, with a focus on astrophysical applications. It provides a robust and user-friendly interface for handling material compositions defined by mass or number fractions.
Key Features
- Dual-Mode Operation: Natively supports compositions defined by mass fraction or number fraction.
- Rich Atomic Database: Includes a comprehensive, header-only database of isotopic properties (mass, half-life, spin, etc.) generated from the AME2020 and NUBASE2020 evaluations.
- Type Safety and Error Handling: Utilizes a clear exception hierarchy to report errors, such as using an unregistered isotope or accessing data from a non-validated composition.
- Powerful Functionality: Core features include mixing, subsetting, and on-the-fly conversion between mass and number fractions.
- Easy Integration: Designed for seamless integration with other projects using the Meson build system and
pkg-config
.
Installation
libcomposition
uses the Meson build system. A C++23 compatible compiler is required.
Build Steps
Setup the build directory:
The first step is to use meson to set up an out of source build. Note that this means that you can have multiple builds configured and cleanly seperated!
Compile the library:
meson by default uses ninja to compile so it should be very fast; however, gcc is very slow when compiling the species database so that migth take some time (clang tends to be very fast for this).
meson compile -C builddir
Install the library:
This will also install a pkg-config file!
sudo meson install -C builddir
Build Options
You can enable the generation of a pkg-config
file during the setup step, which simplifies linking the library in other projects. by default this is true; it can be useful to disable this when using some build system orgestrator (such as meson-python).
# Enable pkg-config file generation
meson setup builddir -Dpkg-config=true
Usage
Linking with pkg-config
If you installed libcomposition
with the pkg-config
option enabled, you can get the necessary compiler and linker flags easily:
# Get compiler flags (include paths)
pkg-config --cflags fourdst_composition
# Get linker flags (library paths and names)
pkg-config --libs fourdst_composition
Example compilation command:
g++ my_app.cpp $(pkg-config --cflags --libs fourdst_composition) -o my_app
C++ Usage Examples
1. Basic Mass Fraction Composition
The most common use case is defining a composition by mass fractions (X, Y, Z).
#include <iostream>
int main() {
std::cout << "Composition finalized successfully!" << std::endl;
std::cout <<
"H-1 Mass Fraction: " << comp.
getMassFraction(
"H-1") << std::endl;
} else {
std::cerr << "Failed to finalize composition." << std::endl;
}
return 0;
}
Manages a collection of chemical species and their abundances.
void registerSymbol(const std::string &symbol, bool massFracMode=true)
Registers a new symbol for inclusion in the composition.
double setMassFraction(const std::string &symbol, const double &mass_fraction)
Sets the mass fraction for a given symbol.
double getMeanParticleMass() const
Compute the mean particle mass of the composition.
bool finalize(bool norm=false)
Finalizes the composition, making it ready for querying.
std::unordered_map< std::string, double > getMassFraction() const
Gets the mass fractions of all species in the composition.
2. Number Fraction Composition and Mode Switching
The library can also work with number (mole) fractions and switch between modes.
void number_fraction_example() {
std::cout <<
"He-4 Number Fraction: " << comp.
getNumberFraction(
"He-4") << std::endl;
std::cout <<
"He-4 Mass Fraction: " << comp.
getMassFraction(
"He-4") << std::endl;
std::cout <<
"He-4 Mass Fraction (after mode switch): " << comp.
getMassFraction(
"He-4") << std::endl;
}
}
void setCompositionMode(bool massFracMode)
Sets the composition mode (mass fraction vs. number fraction).
double setNumberFraction(const std::string &symbol, const double &number_fraction)
Sets the number fraction for a given symbol.
double getNumberFraction(const std::string &symbol) const
Gets the number fraction for a given symbol.
3. Mixing Two Compositions
You can easily mix two compositions. The library handles the union of all species.
void mixing_example() {
std::cout <<
"50/50 Mix H-1: " << mixed.
getMassFraction(
"H-1") << std::endl;
std::cout <<
"75/25 Mix H-1: " << mixed2.
getMassFraction(
"H-1") << std::endl;
}
Composition mix(const Composition &other, double fraction) const
Mixes this composition with another to produce a new composition.
4. Error Handling
The library uses exceptions to report errors. Always wrap calls in a try-catch
block for robust code.
void error_example() {
try {
std::cerr <<
"Caught expected error: " << e.
what() << std::endl;
}
try {
std::cerr <<
"Caught expected error: " << e.
what() << std::endl;
}
}
const char * what() const noexcept override
Returns the error message.
Exception thrown when an operation is attempted on a composition that has not been finalized.
Exception thrown when a symbol is used that has not been registered.
5. Accessing Atomic Data
You can directly access the static database of all known species.
void data_example() {
std::cout << "Fe-56 mass: " << fe56->mass() << std::endl;
}
static const Species F_18("F-18", "F", 0, 9, 9, 18, 7631.6383, "B-", -4444.5049, 6584.04, "+", "+=100", 18.000937324, 0.497)
static const std::unordered_map< std::string, const Species & > species
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)
Testing
libcomposition
is tested using the GoogleTest framework. The test suite provides high coverage of the library's functionality.
Test Coverage Includes:
- Atomic Data Validation: Spot checks on isotopic properties (mass, half-life, spin) for a wide range of elements to ensure the underlying data files are parsed and represented correctly.
- Core
Composition
Workflow: Verification of object construction, symbol registration (for both valid and invalid symbols), and the complete workflow of setting and getting both mass and number fractions.
- Finalization Logic: Ensures that
finalize()
is a required step before querying data. Tests the validation logic for compositions that sum to 1.0 and the auto-normalization feature (finalize(true)
).
- Advanced Features: Dedicated tests for
mix()
, subset()
, setCompositionMode()
, and the calculation of derived quantities like getMolarAbundance()
and getMeanAtomicNumber()
.
- Exception Handling: Confirms that invalid operations (e.g., using an unregistered symbol, mixing un-finalized compositions) correctly throw exceptions from the
fourdst::composition::exceptions
hierarchy.
API Reference
For a complete list of all classes, methods, and functions, please see the **Namespaces** and **Classes** sections of this documentation.