Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
05614f8
Add a SpinerEosDependsRhoSie constructor that takes an existing eos a…
buechlerm Apr 8, 2026
9c668ef
Add AI disclaimer
buechlerm Apr 8, 2026
983fdf2
Docuemnt the constructor
buechlerm Apr 8, 2026
828d4e3
Add concepts for has_cv nad has_gamma
buechlerm Apr 13, 2026
678a907
Add some more concepts
buechlerm Apr 14, 2026
946a34d
Finish bulk modulus and associated derivatives
buechlerm May 4, 2026
cdb063f
Fix abar access and other logic
buechlerm May 4, 2026
4b6a120
add a test for initializing with eospac
buechlerm May 4, 2026
b25a5e7
Fix test and update documentation
buechlerm May 4, 2026
a1955e6
Add an example of the custom eos to spiner process
buechlerm May 4, 2026
7bf7bd7
Move and rename claude plan
buechlerm May 4, 2026
58e6667
Formated files, but maybe not the correct clang-format version
buechlerm May 4, 2026
9aa7b65
Add ai notice in example program
buechlerm May 6, 2026
ea3be96
Add a changelog entry
buechlerm May 6, 2026
672cb1f
Moved method detection helpers to base/eos_concepts.hpp
buechlerm May 29, 2026
b627b93
Add method verification for bounds
buechlerm May 29, 2026
47d5450
add appropriate agentic disclaimer in eos_concepts.hpp
buechlerm May 29, 2026
67482ec
Create generic finite difference algorithm
buechlerm Jun 1, 2026
2474442
Fix errors using the finite difference
buechlerm Jun 1, 2026
6ee5dc6
Convert one more block to using generic central difference
buechlerm Jun 1, 2026
3b334e8
Add evaluateion of min/max rho and min temperature to begining of the…
buechlerm Jun 2, 2026
6986300
add a general finite difference with bounds
buechlerm Jun 4, 2026
58bf318
Fixtemplate parameter
buechlerm Jun 4, 2026
857d1ef
Fix typos
buechlerm Jun 4, 2026
5989a70
Add generic EOS-to-Spiner constructors for RhoT
buechlerm Jun 5, 2026
77c316c
Merge testing of the rho_t and rho_sie constructors into 1 file
buechlerm Jun 5, 2026
367d4c4
Actually add the merged test file
buechlerm Jun 5, 2026
5b90ab6
Apply formating
buechlerm Jun 5, 2026
de20e4e
Correct the licence date
buechlerm Jun 5, 2026
5715148
Fix inconsistencies between spinerTableGridParams and sesame2spiner
buechlerm Jun 8, 2026
363d32f
Apply formatting
buechlerm Jun 8, 2026
bc5ab8a
Update licence date in sesame2spiner/generate_files.{cpp,hpp}
buechlerm Jun 8, 2026
fbd3f83
Add blank line at the end of eos_concepts.hpp
buechlerm Jun 8, 2026
6899a13
Use first order forward and backward difference on the boundaries
buechlerm Jun 8, 2026
c70a76d
Try to improve description on choice of rho_sie vs rho_temp
buechlerm Jun 8, 2026
48385a3
Merge branch 'main' into buechler/spiner_constructor
Yurlungur Jun 9, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
## Current develop

### Added (new features/APIs/variables/...)
- [[PR632]](https://github.com/lanl/singularity-eos/pull/632) Added generic constructors to SpinerEOSDependsRhoSie and SpinerEOSDependsRhoT that build tables from any EOS object.
- [[PR623]](https://github.com/lanl/singularity-eos/pull/623) Expanded the sesame2spiner syntax to support multiple material definitions in one input file.
- [[PR618]](https://github.com/lanl/singularity-eos/pull/618) Add PTDerivativesFromPreferred for computing derivatives of a mixture in a cell
- [[PR630]](https://github.com/lanl/singularity-eos/pull/630) Thread execution spaces through vector API.
Expand Down
76 changes: 76 additions & 0 deletions doc/sphinx/src/examples.rst
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,82 @@ internal energy to evaluate at.
The example demonstrates how to call the pressure, energy, and
thermodynamic derivatives of a table at that point in phase space.

Custom EOS to SpinerEOS
-------------------------

The ``examples/custom_eos_to_spiner.cpp`` example demonstrates how to
tabulate a custom EOS implementation into ``SpinerEOS`` format using
Comment thread
buechlerm marked this conversation as resolved.
the generic constructor. This is useful when you have your own EOS
physics model and want to improve performance through table
interpolation or enable GPU portability.

The example creates a simple Mie-Gruneisen-like EOS class that provides
the minimal required interface:

.. code-block:: cpp

class CustomHostEOS {
public:
// Minimal required interface
Real InternalEnergyFromDensityTemperature(Real rho, Real T) const;
Real TemperatureFromDensityInternalEnergy(Real rho, Real sie) const;
Real PressureFromDensityTemperature(Real rho, Real T) const;

// Optional: improves derivative accuracy
Real GruneisenParamFromDensityTemperature(Real rho, Real T) const;

// Optional: material properties
Real MeanAtomicMass() const;
Real MeanAtomicNumber() const;
};

It then demonstrates how to tabulate this custom EOS:

.. code-block:: cpp

CustomHostEOS custom_eos(rho0, C0, s, Gamma0, Cv);

// Set up grid parameters
SpinerTableGridParams params;
params.rhoMin = 1.0;
params.rhoMax = 20.0;
params.TMin = 300.0;
params.TMax = 50000.0;
params.numRhoPerDecade = 50;

// Construct SpinerEOS from custom EOS
SpinerEOSDependsRhoSie spiner_eos(custom_eos, params);

// Use tabulated EOS
Real P = spiner_eos.PressureFromDensityTemperature(rho, T);

The example verifies that the tabulated EOS matches the original custom
EOS with interpolation errors typically less than 1%. The resulting
``SpinerEOS`` can be used in production simulations for better
performance, on GPUs via ``GetOnDevice()``, and with mixed-cell closure
models.

.. note::

The example uses ``SpinerEOSDependsRhoSie``, but you can also use
Comment thread
buechlerm marked this conversation as resolved.
``SpinerEOSDependsRhoT`` with the same parameters (just omit sie bounds):

.. code-block:: cpp

// For RhoT variant (simpler, less memory)
SpinerEOSDependsRhoT spiner_eos(custom_eos, params);

Choose RhoT if you primarily use (ρ,T) lookups, or RhoSie if you need
both (ρ,T) and (ρ,sie) lookups. Both use identical construction logic
for (ρ,T) tables.

This approach is particularly valuable for:

- Converting analytical models to tables for performance
- Integrating custom physics with codes that expect tabulated EOS
- Creating GPU-portable versions of host code EOS implementations
- Re-gridding existing tables to different resolutions

Plugins
----------

Expand Down
209 changes: 209 additions & 0 deletions doc/sphinx/src/models.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1720,6 +1720,215 @@ constructor for ``SpinerEOSDependsRhoSie`` is identical.
``SpinerEOS`` model does **not** support the
``MeanAtomicProperties`` struct.

Constructing SpinerEOS from a Generic EOS
'''''''''''''''''''''''''''''''''''''''''''

``SpinerEOSDependsRhoSie`` can also be constructed directly from any
analytic or tabulated EOS object, allowing you to tabulate any equation
of state into the high-performance Spiner format in memory. This is
useful for converting analytic models (like ``IdealGas``, ``Gruneisen``,
etc.) into tabulated form, or for creating custom resolution tables
from existing EOS models.

The constructor has the signature:

.. code-block:: cpp

template <typename EOS>
SpinerEOSDependsRhoSie(const EOS &source_eos,
const SpinerTableGridParams &params,
bool reproducibility_mode = false);

where ``source_eos`` is any EOS object that provides the standard
singularity-eos interface (at minimum:
``TemperatureFromDensityInternalEnergy``,
``InternalEnergyFromDensityTemperature``,
``PressureFromDensityTemperature``, and
``PressureFromDensityInternalEnergy``). The ``params`` struct controls
the grid construction and material properties.

The ``SpinerTableGridParams`` struct contains grid parameters that match
the options available in ``sesame2spiner``:

.. code-block:: cpp

struct SpinerTableGridParams {
// Density bounds
Real rhoMin, rhoMax;
int numRho = -1; // -1 means use numRhoPerDecade
int numRhoPerDecade = 350;

// Temperature bounds
Real TMin, TMax;
int numT = -1; // -1 means use numTPerDecade
int numTPerDecade = 100;

// Specific internal energy bounds
Real sieMin, sieMax;
int numSie = -1; // -1 means use numSiePerDecade
int numSiePerDecade = 100;

// Material properties
int matid = 0;
Real Abar = NaN; // defaults from source EOS if available
Real Zbar = NaN;
Real rhoNormal = NaN; // defaults to geometric mean of bounds

// Piecewise grid options (see Piecewise Spiner Grids section)
bool piecewiseRho = true;
bool piecewiseT = true;
bool piecewiseSie = true;
Real rhoCoarseFactorLo = 3.0;
Real rhoCoarseFactorHi = 5.0;
Real TCoarseFactor = 1.5;
Real sieCoarseFactor = 1.5;
Real rhoFineDiameterDecades = 1.5;
Real TSplitPoint = 1e4;

// Advanced options
Real shrinklRhoBounds = 0.0;
Real shrinklTBounds = 0.0;
Real shrinkleBounds = 0.0;
Real strictlyPositiveMinRho = 1e-8;
Real strictlyPositiveMinT = 1e-2;
};

Defaults follow the ``sesame2spiner`` tool conventions. The grid
construction automatically handles offset computation for negative
values (especially important for specific internal energy).

Example usage:

.. code-block:: cpp

#include <singularity-eos/eos/eos.hpp>

// Create an analytic EOS
constexpr Real Cv = 2.0;
constexpr Real gm1 = 0.4;
IdealGas ideal(gm1, Cv);

// Set up grid parameters
SpinerTableGridParams params;
params.rhoMin = 1e-3;
params.rhoMax = 1e3;
params.TMin = 1e2;
params.TMax = 1e5;
params.sieMin = Cv * params.TMin;
params.sieMax = Cv * params.TMax;
params.matid = 1001;
params.numRhoPerDecade = 100; // optional: finer resolution

// Construct SpinerEOS from the IdealGas
SpinerEOSDependsRhoSie spiner_eos(ideal, params);

// Use like any other SpinerEOS
Real P = spiner_eos.PressureFromDensityTemperature(rho, T);
Real T_out = spiner_eos.TemperatureFromDensityInternalEnergy(rho, sie);

.. note::

This constructor only supports ``TableSplit::Total``. Electron-only
and ion-cold splits are not available for generic EOS, as these
require additional physics that generic EOS models may not provide.
Comment thread
buechlerm marked this conversation as resolved.

.. note::

The constructor automatically detects and uses optional EOS methods
when available to improve accuracy:

- ``GruneisenParamFromDensityTemperature`` or
``GruneisenParamFromDensityInternalEnergy`` for computing dP/dE
- ``SpecificHeatFromDensityTemperature`` or
``SpecificHeatFromDensityInternalEnergy`` for computing dT/dE
- ``PressureFromDensityInternalEnergy`` for direct pressure lookups
(otherwise uses chain rule conversions)

If these methods are not provided, derivatives are computed via centered
finite differences. Bulk modulus is always computed consistently from
derivatives using the internal ``calcBMod_()`` method.

Material properties (``MeanAtomicMass()`` and ``MeanAtomicNumber()``)
are automatically extracted from the source EOS if available and not
specified in ``params``.

Constructing SpinerEOSDependsRhoT from a Generic EOS
'''''''''''''''''''''''''''''''''''''''''''''''''''''

``SpinerEOSDependsRhoT`` also supports construction from any analytic or
tabulated EOS object using the same ``SpinerTableGridParams`` struct. The
RhoT variant is simpler and more memory-efficient than RhoSie, storing only
(ρ,T)-indexed tables rather than both (ρ,T) and (ρ,sie) tables.

The constructor signature is identical to RhoSie:

.. code-block:: cpp

template <typename EOS>
SpinerEOSDependsRhoT(const EOS &source_eos,
const SpinerTableGridParams &params,
bool reproducibility_mode = false);

The same ``SpinerTableGridParams`` struct is used for both constructors.
RhoT-specific notes:

- The ``sieMin``, ``sieMax``, ``numSie``, ``numSiePerDecade``,
``piecewiseSie``, and ``sieCoarseFactor`` parameters are ignored
(only relevant for RhoSie)
- All other parameters work identically

Example usage:

.. code-block:: cpp

#include <singularity-eos/eos/eos.hpp>

// Create an analytic EOS
constexpr Real Cv = 2.0;
constexpr Real gm1 = 0.4;
IdealGas ideal(gm1, Cv);

// Set up grid parameters (same struct as RhoSie)
SpinerTableGridParams params;
params.rhoMin = 1e-3;
params.rhoMax = 1e3;
params.TMin = 1e2;
params.TMax = 1e5;
params.matid = 1001;
params.numRhoPerDecade = 100;

// Construct SpinerEOSDependsRhoT
SpinerEOSDependsRhoT spiner_eos(ideal, params);

// Use like any other SpinerEOSDependsRhoT
Real P = spiner_eos.PressureFromDensityTemperature(rho, T);
Real sie = spiner_eos.InternalEnergyFromDensityTemperature(rho, T);
Real T_inv = spiner_eos.TemperatureFromDensityInternalEnergy(rho, sie);

.. note::

**Choosing between RhoT and RhoSie**:

- Use ``SpinerEOSDependsRhoT`` when:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we mention something about accuracy of root finds vs lookups?

- Your code primarily uses (ρ,T) lookups
- Memory efficiency is important
- You rarely require direct (ρ,sie) queries

- Use ``SpinerEOSDependsRhoSie`` when:
- Your code frequently uses both (ρ,T) and (ρ,sie) lookups
- You want direct P(ρ,sie) evaluation without additional inversion or root-finding steps
- You're using mixed-cell closure models (PTE, etc.) that naturally operate in (ρ,sie)

In general, SpinerEOSDependsRhoT is the more natural representation for EOS tables tabulated in (ρ,T), while SpinerEOSDependsRhoSie can provide better performance when frequent (ρ,sie) evaluations are required. The optimal choice depends on the access patterns and closure algorithms used by a particular application.

.. note::

Like RhoSie, the RhoT constructor automatically detects optional EOS
methods (``GruneisenParamFromDensityTemperature``,
``SpecificHeatFromDensityTemperature``, etc.) and uses them when available.
Otherwise, finite differences are used. Material properties are
automatically extracted from the source EOS.

Additionally Spiner EOS models support mass fraction lookups of the form

.. code-block:: cpp
Expand Down
2 changes: 2 additions & 0 deletions example/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ if(SINGULARITY_USE_SPINER_WITH_HDF5)
target_link_libraries(map_pt_space PRIVATE singularity-eos::singularity-eos)
add_executable(pte_2mat pte_2mat.cpp)
target_link_libraries(pte_2mat PRIVATE singularity-eos::singularity-eos)
add_executable(custom_eos_to_spiner custom_eos_to_spiner.cpp)
target_link_libraries(custom_eos_to_spiner PRIVATE singularity-eos::singularity-eos)
endif()

if(SINGULARITY_USE_EOSPAC AND SINGULARITY_USE_SPINER_WITH_HDF5)
Expand Down
Loading
Loading