# fourdst::libcomposition: libcomposition: A Modern C++ Library for Chemical Compositions

Loading...
Searching...
No Matches
libcomposition: A Modern C++ Library for Chemical Compositions

# 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!

meson setup builddir

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>
#include "fourdst/composition/composition.h"
int main() {
// 1. Create a composition object
fourdst::composition::Composition comp;
// 2. Register the symbols you want to use
comp.registerSymbol("H-1");
comp.registerSymbol("He-4");
// 3. Set their mass fractions
comp.setMassFraction("H-1", 0.75);
comp.setMassFraction("He-4", 0.25);
// 4. Finalize the composition to validate it and compute global properties
if (comp.finalize()) {
std::cout << "Composition finalized successfully!" << std::endl;
std::cout << "H-1 Mass Fraction: " << comp.getMassFraction("H-1") << std::endl;
std::cout << "Mean Particle Mass: " << comp.getMeanParticleMass() << " g/mol" << std::endl;
} else {
std::cerr << "Failed to finalize composition." << std::endl;
}
return 0;
}
fourdst::composition::Composition
Manages a collection of chemical species and their abundances.
Definition composition.h:97
fourdst::composition::Composition::registerSymbol
void registerSymbol(const std::string &symbol)
Registers a new symbol for inclusion in the composition.
Definition composition.cpp:178
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:251
fourdst::composition::Composition::getMeanParticleMass
double getMeanParticleMass() const noexcept override
Compute the mean particle mass of the composition.
Definition composition.cpp:311
composition.h

#### 2. Number Fraction Composition and Mode Switching

The library can also work with number (mole) fractions and switch between modes.

#include "fourdst/composition/composition.h"
#include "fourdst/composition/exceptions/exceptions_composition.h"
void number_fraction_example() {
fourdst::composition::Composition comp;
// Register symbols in number fraction mode
comp.registerSymbol("H-1", false); // massFracMode = false
comp.registerSymbol("He-4", false);
comp.setNumberFraction("H-1", 0.9);
comp.setNumberFraction("He-4", 0.1);
if (comp.finalize()) {
// We can get number fractions directly
std::cout << "He-4 Number Fraction: " << comp.getNumberFraction("He-4") << std::endl;
// Or get the equivalent mass fraction
std::cout << "He-4 Mass Fraction: " << comp.getMassFraction("He-4") << std::endl;
// Switch the entire composition to mass fraction mode
comp.setCompositionMode(true); // true for mass fraction mode
// Now, getting the mass fraction is a direct lookup
std::cout << "He-4 Mass Fraction (after mode switch): " << comp.getMassFraction("He-4") << std::endl;
}
}
fourdst::composition::Composition::getNumberFraction
double getNumberFraction(const std::string &symbol) const override
Gets the number fraction for a given symbol. See the overload for species-based lookup for more detai...
Definition composition.cpp:260
exceptions_composition.h

#### 3. Mixing Two Compositions

You can easily mix two compositions. The library handles the union of all species.

#include "fourdst/composition/composition.h"
void mixing_example() {
// Composition 1: Pure Hydrogen
fourdst::composition::Composition comp1({"H-1"}, {1.0});
// Composition 2: Pure Helium
fourdst::composition::Composition comp2({"He-4"}, {1.0});
// Mix them with a 50/50 ratio using the '+' operator
fourdst::composition::Composition mixed = comp1 + comp2;
// Mix them with a 75/25 ratio using the mix() method
// 0.75 of comp1, 0.25 of comp2
fourdst::composition::Composition mixed2 = comp1.mix(comp2, 0.75);
std::cout << "50/50 Mix H-1: " << mixed.getMassFraction("H-1") << std::endl; // -> 0.5
std::cout << "75/25 Mix H-1: " << mixed2.getMassFraction("H-1") << std::endl; // -> 0.75
}

#### 4. Error Handling

The library uses exceptions to report errors. Always wrap calls in a `try-catch` block for robust code.

#include "fourdst/composition/composition.h"
#include "fourdst/composition/exceptions/exceptions_composition.h"
void error_example() {
fourdst::composition::Composition comp;
comp.registerSymbol("H-1");
comp.setMassFraction("H-1", 1.0);
try {
// This will throw, because the composition is not finalized yet.
double mass = comp.getMassFraction("H-1");
} catch (const fourdst::composition::exceptions::CompositionNotFinalizedError& e) {
std::cerr << "Caught expected error: " << e.what() << std::endl;
}
try {
// This will throw, because "Li-6" was never registered.
comp.setMassFraction("Li-6", 0.1);
} catch (const fourdst::composition::exceptions::UnregisteredSymbolError& e) {
std::cerr << "Caught expected error: " << e.what() << std::endl;
}
}
fourdst::composition::exceptions::CompositionError::what
const char * what() const noexcept override
Returns the error message.
Definition exceptions_composition.h:32
fourdst::composition::exceptions::UnregisteredSymbolError
Exception thrown when a symbol is used that has not been registered.
Definition exceptions_composition.h:51

#### 5. Accessing Atomic Data

You can directly access the static database of all known species.

#include "fourdst/composition/species.h" // Provides static instances like H_1
#include "fourdst/composition/atomicSpecies.h" // Provides the main 'species' map
void data_example() {
// Access via the map
const auto& fe56 = fourdst::atomic::species.at("Fe-56");
std::cout << "Fe-56 mass: " << fe56->mass() << std::endl;
// Access via the static instance
std::cout << "H-1 spin: " << fourdst::atomic::H_1.spin() << std::endl;
std::cout << "F-18 half-life: " << fourdst::atomic::F_18.halfLife() << " s" << std::endl;
}
fourdst::atomic::F_18
static const Species F_18("F-18", "F", 0, 9, 9, 18, 7631.6383, "B-", -4444.5049, 6584.04, "+", "+=100", 18.000937324, 0.497)
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::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)

# 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.