Merge pull request #68 from tboudreaux/refactor/useComposition

Refactor Network and EOS modules to use composition module
This commit is contained in:
2025-06-17 09:53:52 -04:00
committed by GitHub
28 changed files with 1529 additions and 916 deletions

View File

@@ -1,3 +1,4 @@
species_weight_dep = declare_dependency( species_weight_dep = declare_dependency(
include_directories: include_directories('include'), include_directories: include_directories('include'),
) )
message('✅ SERiF species_weight dependency declared')

View File

@@ -106,7 +106,7 @@ $(function(){initNavTree('annotated.html',''); initResizable(true); });
<div class="levels">[detail level <span onclick="javascript:dynsection.toggleLevel(1);">1</span><span onclick="javascript:dynsection.toggleLevel(2);">2</span><span onclick="javascript:dynsection.toggleLevel(3);">3</span><span onclick="javascript:dynsection.toggleLevel(4);">4</span>]</div><table class="directory"> <div class="levels">[detail level <span onclick="javascript:dynsection.toggleLevel(1);">1</span><span onclick="javascript:dynsection.toggleLevel(2);">2</span><span onclick="javascript:dynsection.toggleLevel(3);">3</span><span onclick="javascript:dynsection.toggleLevel(4);">4</span>]</div><table class="directory">
<tr id="row_0_" class="even"><td class="entry"><span style="width:0px;display:inline-block;">&#160;</span><span id="arr_0_" class="arrow" onclick="dynsection.toggleFolder('0_')">&#9660;</span><span class="icona"><span class="icon">N</span></span><a class="el" href="namespaceserif.html" target="_self">serif</a></td><td class="desc"></td></tr> <tr id="row_0_" class="even"><td class="entry"><span style="width:0px;display:inline-block;">&#160;</span><span id="arr_0_" class="arrow" onclick="dynsection.toggleFolder('0_')">&#9660;</span><span class="icona"><span class="icon">N</span></span><a class="el" href="namespaceserif.html" target="_self">serif</a></td><td class="desc"></td></tr>
<tr id="row_0_0_" class="odd"><td class="entry"><span style="width:16px;display:inline-block;">&#160;</span><span id="arr_0_0_" class="arrow" onclick="dynsection.toggleFolder('0_0_')">&#9660;</span><span class="icona"><span class="icon">N</span></span><a class="el" href="namespaceserif_1_1composition.html" target="_self">composition</a></td><td class="desc"></td></tr> <tr id="row_0_0_" class="odd"><td class="entry"><span style="width:16px;display:inline-block;">&#160;</span><span id="arr_0_0_" class="arrow" onclick="dynsection.toggleFolder('0_0_')">&#9660;</span><span class="icona"><span class="icon">N</span></span><a class="el" href="namespaceserif_1_1composition.html" target="_self">composition</a></td><td class="desc"></td></tr>
<tr id="row_0_0_0_" class="even"><td class="entry"><span style="width:48px;display:inline-block;">&#160;</span><span class="icona"><span class="icon">C</span></span><a class="el" href="classserif_1_1composition_1_1_composition.html" target="_self">Composition</a></td><td class="desc"></td></tr> <tr id="row_0_0_0_" class="even"><td class="entry"><span style="width:48px;display:inline-block;">&#160;</span><span class="icona"><span class="icon">C</span></span><a class="el" href="classserif_1_1composition_1_1_composition.html" target="_self">Composition</a></td><td class="desc">Manages the composition of elements </td></tr>
<tr id="row_0_0_1_" class="odd"><td class="entry"><span style="width:48px;display:inline-block;">&#160;</span><span class="icona"><span class="icon">C</span></span><a class="el" href="structserif_1_1composition_1_1_composition_entry.html" target="_self">CompositionEntry</a></td><td class="desc">Represents an entry in the composition with a symbol and mass fraction </td></tr> <tr id="row_0_0_1_" class="odd"><td class="entry"><span style="width:48px;display:inline-block;">&#160;</span><span class="icona"><span class="icon">C</span></span><a class="el" href="structserif_1_1composition_1_1_composition_entry.html" target="_self">CompositionEntry</a></td><td class="desc">Represents an entry in the composition with a symbol and mass fraction </td></tr>
<tr id="row_0_0_2_" class="even"><td class="entry"><span style="width:48px;display:inline-block;">&#160;</span><span class="icona"><span class="icon">C</span></span><a class="el" href="structserif_1_1composition_1_1_global_composition.html" target="_self">GlobalComposition</a></td><td class="desc">Represents the global composition of a system. This tends to be used after finalize and is primarily for internal use </td></tr> <tr id="row_0_0_2_" class="even"><td class="entry"><span style="width:48px;display:inline-block;">&#160;</span><span class="icona"><span class="icon">C</span></span><a class="el" href="structserif_1_1composition_1_1_global_composition.html" target="_self">GlobalComposition</a></td><td class="desc">Represents the global composition of a system. This tends to be used after finalize and is primarily for internal use </td></tr>
<tr id="row_0_1_" class="odd"><td class="entry"><span style="width:16px;display:inline-block;">&#160;</span><span id="arr_0_1_" class="arrow" onclick="dynsection.toggleFolder('0_1_')">&#9660;</span><span class="icona"><span class="icon">N</span></span><a class="el" href="namespaceserif_1_1constant.html" target="_self">constant</a></td><td class="desc"></td></tr> <tr id="row_0_1_" class="odd"><td class="entry"><span style="width:16px;display:inline-block;">&#160;</span><span id="arr_0_1_" class="arrow" onclick="dynsection.toggleFolder('0_1_')">&#9660;</span><span class="icona"><span class="icon">N</span></span><a class="el" href="namespaceserif_1_1constant.html" target="_self">constant</a></td><td class="desc"></td></tr>

View File

@@ -10,12 +10,10 @@
<body> <body>
<a href="4_d_s_t_a_r_types_8h.html"/> <a href="4_d_s_t_a_r_types_8h.html"/>
<a href="4_d_s_t_a_r_types_8h_source.html"/> <a href="4_d_s_t_a_r_types_8h_source.html"/>
<a href="_2_users_2tboudreaux_2_programming_2_s_e_ri_f_2src_2composition_2public_2composition_8h-example.html"/>
<a href="_2_users_2tboudreaux_2_programming_2_s_e_ri_f_2src_2network_2public_2approx8_8h-example.html"/> <a href="_2_users_2tboudreaux_2_programming_2_s_e_ri_f_2src_2network_2public_2approx8_8h-example.html"/>
<a href="_2_users_2tboudreaux_2_programming_2_s_e_ri_f_2src_2polytrope_2solver_2public_2poly_solver_8h-example.html"/> <a href="_2_users_2tboudreaux_2_programming_2_s_e_ri_f_2src_2polytrope_2solver_2public_2poly_solver_8h-example.html"/>
<a href="____init_____8py.html"/> <a href="____init_____8py.html"/>
<a href="____init_____8py_source.html"/> <a href="____init_____8py_source.html"/>
<a href="_constructing-example.html"/>
<a href="_e_o_sio_8cpp.html"/> <a href="_e_o_sio_8cpp.html"/>
<a href="_e_o_sio_8cpp_source.html"/> <a href="_e_o_sio_8cpp_source.html"/>
<a href="_e_o_sio_8h.html"/> <a href="_e_o_sio_8h.html"/>

View File

@@ -64,11 +64,11 @@ var NAVTREE =
var NAVTREEINDEX = var NAVTREEINDEX =
[ [
"4_d_s_t_a_r_types_8h.html", "4_d_s_t_a_r_types_8h.html",
"classserif_1_1polytrope_1_1_g_m_r_e_s_inverter.html#a698ccfa71e87e381b6c0a4d7a081a776", "classserif_1_1polytrope_1_1_g_m_r_e_s_inverter.html#a78c5540e756ad46201097cc83d90d356",
"classserif_1_1polytrope_1_1poly_m_f_e_m_utils_1_1_nonlinear_power_integrator.html#ac636b3bdb45524d65d2a3aa1b6e43c7b", "classserif_1_1probe_1_1_log_manager.html",
"dir_daf60af48849bf958020a18d83ad56ea.html", "dir_e296cd0c311faef12afe540130b9e3be.html",
"namespaceserif_1_1polytrope_1_1poly_m_f_e_m_utils.html#ac43f5dda296efc47fbdbd351f2f4bf00", "namespaceserif_1_1polytrope_1_1polycoeff.html",
"structserif_1_1eos_1_1helmholtz_1_1_h_e_l_m_table.html" "structserif_1_1eos_1_1helmholtz_1_1_h_e_l_m_table.html#a0333b97d0f0498b86718cc20cb812e2c"
]; ];
var SYNCONMSG = 'click to disable panel synchronization'; var SYNCONMSG = 'click to disable panel synchronization';

View File

@@ -2,12 +2,10 @@ var NAVTREEINDEX0 =
{ {
"4_d_s_t_a_r_types_8h.html":[4,0,1,11,0,0], "4_d_s_t_a_r_types_8h.html":[4,0,1,11,0,0],
"4_d_s_t_a_r_types_8h_source.html":[4,0,1,11,0,0], "4_d_s_t_a_r_types_8h_source.html":[4,0,1,11,0,0],
"_2_users_2tboudreaux_2_programming_2_s_e_ri_f_2src_2composition_2public_2composition_8h-example.html":[5,0], "_2_users_2tboudreaux_2_programming_2_s_e_ri_f_2src_2network_2public_2approx8_8h-example.html":[5,0],
"_2_users_2tboudreaux_2_programming_2_s_e_ri_f_2src_2network_2public_2approx8_8h-example.html":[5,2], "_2_users_2tboudreaux_2_programming_2_s_e_ri_f_2src_2polytrope_2solver_2public_2poly_solver_8h-example.html":[5,1],
"_2_users_2tboudreaux_2_programming_2_s_e_ri_f_2src_2polytrope_2solver_2public_2poly_solver_8h-example.html":[5,3],
"____init_____8py.html":[4,0,1,9,6,0], "____init_____8py.html":[4,0,1,9,6,0],
"____init_____8py_source.html":[4,0,1,9,6,0], "____init_____8py_source.html":[4,0,1,9,6,0],
"_constructing-example.html":[5,1],
"_e_o_sio_8cpp.html":[4,0,1,3,0,0], "_e_o_sio_8cpp.html":[4,0,1,3,0,0],
"_e_o_sio_8cpp_source.html":[4,0,1,3,0,0], "_e_o_sio_8cpp_source.html":[4,0,1,3,0,0],
"_e_o_sio_8h.html":[4,0,1,3,1,0], "_e_o_sio_8h.html":[4,0,1,3,1,0],
@@ -249,5 +247,7 @@ var NAVTREEINDEX0 =
"classserif_1_1polytrope_1_1_g_m_r_e_s_inverter.html#a26e52db2e259ceb0efc74a188a0626df":[3,0,0,5,3,0], "classserif_1_1polytrope_1_1_g_m_r_e_s_inverter.html#a26e52db2e259ceb0efc74a188a0626df":[3,0,0,5,3,0],
"classserif_1_1polytrope_1_1_g_m_r_e_s_inverter.html#a56eb2c60f01e499c905ccf1f9c1766dc":[2,0,3,6,4,4], "classserif_1_1polytrope_1_1_g_m_r_e_s_inverter.html#a56eb2c60f01e499c905ccf1f9c1766dc":[2,0,3,6,4,4],
"classserif_1_1polytrope_1_1_g_m_r_e_s_inverter.html#a56eb2c60f01e499c905ccf1f9c1766dc":[3,0,0,5,3,4], "classserif_1_1polytrope_1_1_g_m_r_e_s_inverter.html#a56eb2c60f01e499c905ccf1f9c1766dc":[3,0,0,5,3,4],
"classserif_1_1polytrope_1_1_g_m_r_e_s_inverter.html#a698ccfa71e87e381b6c0a4d7a081a776":[2,0,3,6,4,2] "classserif_1_1polytrope_1_1_g_m_r_e_s_inverter.html#a698ccfa71e87e381b6c0a4d7a081a776":[2,0,3,6,4,2],
"classserif_1_1polytrope_1_1_g_m_r_e_s_inverter.html#a698ccfa71e87e381b6c0a4d7a081a776":[3,0,0,5,3,2],
"classserif_1_1polytrope_1_1_g_m_r_e_s_inverter.html#a78c5540e756ad46201097cc83d90d356":[2,0,3,6,4,1]
}; };

View File

@@ -2,7 +2,7 @@
Here are the classes, structs, unions and interfaces with brief descriptions\+:\begin{DoxyCompactList} Here are the classes, structs, unions and interfaces with brief descriptions\+:\begin{DoxyCompactList}
\item\contentsline{section}{\mbox{\hyperlink{classserif_1_1network_1_1approx8_1_1_approx8_network}{serif\+::network\+::approx8\+::\+Approx8\+Network}} \\*Class for the Approx8 nuclear reaction network }{\pageref{classserif_1_1network_1_1approx8_1_1_approx8_network}}{} \item\contentsline{section}{\mbox{\hyperlink{classserif_1_1network_1_1approx8_1_1_approx8_network}{serif\+::network\+::approx8\+::\+Approx8\+Network}} \\*Class for the Approx8 nuclear reaction network }{\pageref{classserif_1_1network_1_1approx8_1_1_approx8_network}}{}
\item\contentsline{section}{\mbox{\hyperlink{classapprox8_test}{approx8\+Test}} }{\pageref{classapprox8_test}}{} \item\contentsline{section}{\mbox{\hyperlink{classapprox8_test}{approx8\+Test}} }{\pageref{classapprox8_test}}{}
\item\contentsline{section}{\mbox{\hyperlink{classserif_1_1composition_1_1_composition}{serif\+::composition\+::\+Composition}} }{\pageref{classserif_1_1composition_1_1_composition}}{} \item\contentsline{section}{\mbox{\hyperlink{classserif_1_1composition_1_1_composition}{serif\+::composition\+::\+Composition}} \\*Manages the composition of elements }{\pageref{classserif_1_1composition_1_1_composition}}{}
\item\contentsline{section}{\mbox{\hyperlink{structserif_1_1composition_1_1_composition_entry}{serif\+::composition\+::\+Composition\+Entry}} \\*Represents an entry in the composition with a symbol and mass fraction }{\pageref{structserif_1_1composition_1_1_composition_entry}}{} \item\contentsline{section}{\mbox{\hyperlink{structserif_1_1composition_1_1_composition_entry}{serif\+::composition\+::\+Composition\+Entry}} \\*Represents an entry in the composition with a symbol and mass fraction }{\pageref{structserif_1_1composition_1_1_composition_entry}}{}
\item\contentsline{section}{\mbox{\hyperlink{classcomposition_test}{composition\+Test}} \\*Test suite for the composition class }{\pageref{classcomposition_test}}{} \item\contentsline{section}{\mbox{\hyperlink{classcomposition_test}{composition\+Test}} \\*Test suite for the composition class }{\pageref{classcomposition_test}}{}
\item\contentsline{section}{\mbox{\hyperlink{classconfig_test}{config\+Test}} \\*Test suite for the Config class }{\pageref{classconfig_test}}{} \item\contentsline{section}{\mbox{\hyperlink{classconfig_test}{config\+Test}} \\*Test suite for the Config class }{\pageref{classconfig_test}}{}

View File

@@ -447,8 +447,6 @@
\input{resource_manager_test_8cpp} \input{resource_manager_test_8cpp}
\input{resource_manager_test_8cpp_source} \input{resource_manager_test_8cpp_source}
\chapter{Examples} \chapter{Examples}
\input{_2_users_2tboudreaux_2_programming_2_s_e_ri_f_2src_2composition_2public_2composition_8h-example}
\input{_constructing-example}
\input{_2_users_2tboudreaux_2_programming_2_s_e_ri_f_2src_2network_2public_2approx8_8h-example} \input{_2_users_2tboudreaux_2_programming_2_s_e_ri_f_2src_2network_2public_2approx8_8h-example}
\input{_2_users_2tboudreaux_2_programming_2_s_e_ri_f_2src_2polytrope_2solver_2public_2poly_solver_8h-example} \input{_2_users_2tboudreaux_2_programming_2_s_e_ri_f_2src_2polytrope_2solver_2public_2poly_solver_8h-example}
%--- End generated contents --- %--- End generated contents ---

View File

@@ -29,4 +29,4 @@ composition_dep = declare_dependency(
) )
# Make headers accessible # Make headers accessible
install_headers(composition_headers, subdir : '4DSSE/composition') install_headers(composition_headers, subdir : 'SERiF/composition')

File diff suppressed because it is too large Load Diff

View File

@@ -18,8 +18,7 @@
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// //
// *********************************************************************** */ // *********************************************************************** */
#ifndef COMPOSITION_H #pragma once
#define COMPOSITION_H
#include <iostream> #include <iostream>
#include <string> #include <string>
@@ -34,6 +33,20 @@
#include "atomicSpecies.h" #include "atomicSpecies.h"
namespace serif::composition { namespace serif::composition {
struct CanonicalComposition {
double X = 0.0; ///< Mass fraction of Hydrogen.
double Y = 0.0; ///< Mass fraction of Helium.
double Z = 0.0; ///< Mass fraction of Metals.
friend std::ostream& operator<<(std::ostream& os, const CanonicalComposition& composition) {
os << "<CanonicalComposition: "
<< "X = " << composition.X << ", "
<< "Y = " << composition.Y << ", "
<< "Z = " << composition.Z << ">";
return os;
}
};
/** /**
* @brief Represents the global composition of a system. This tends to be used after finalize and is primarily for internal use. * @brief Represents the global composition of a system. This tends to be used after finalize and is primarily for internal use.
*/ */
@@ -68,7 +81,7 @@ namespace serif::composition {
* @brief Constructs a CompositionEntry with the given symbol and mode. * @brief Constructs a CompositionEntry with the given symbol and mode.
* @param symbol The chemical symbol of the species. * @param symbol The chemical symbol of the species.
* @param massFracMode True if mass fraction mode, false if number fraction mode. * @param massFracMode True if mass fraction mode, false if number fraction mode.
* @example * *Example Usage:*
* @code * @code
* CompositionEntry entry("H", true); * CompositionEntry entry("H", true);
* @endcode * @endcode
@@ -185,13 +198,13 @@ namespace serif::composition {
* - The only exception to the finalize rule is if the compositon was constructed with symbols and mass fractions at instantiation time. In this case, the composition is automatically finalized. * - The only exception to the finalize rule is if the compositon was constructed with symbols and mass fractions at instantiation time. In this case, the composition is automatically finalized.
* however, this means that the composition passed to the constructor must be valid. * however, this means that the composition passed to the constructor must be valid.
* *
* @example Constructing a finalized composition with symbols and mass fractions: * *Example Usage:* Constructing a finalized composition with symbols and mass fractions:
* @code * @code
* std::vector<std::string> symbols = {"H", "He"}; * std::vector<std::string> symbols = {"H", "He"};
* std::vector<double> mass_fractions = {0.7, 0.3}; * std::vector<double> mass_fractions = {0.7, 0.3};
* Composition comp(symbols, mass_fractions); * Composition comp(symbols, mass_fractions);
* @endcode * @endcode
* @example Constructing a composition with symbols and finalizing it later: * *Example Usage:* Constructing a composition with symbols and finalizing it later:
* @code * @code
* std::vector<std::string> symbols = {"H", "He"}; * std::vector<std::string> symbols = {"H", "He"};
* Composition comp(symbols); * Composition comp(symbols);
@@ -220,7 +233,7 @@ namespace serif::composition {
* @param symbol The symbol to check. * @param symbol The symbol to check.
* @return True if the symbol is valid, false otherwise. * @return True if the symbol is valid, false otherwise.
*/ */
bool isValidSymbol(const std::string& symbol) const; static bool isValidSymbol(const std::string& symbol);
/** /**
* @brief Checks if the given mass fractions are valid. * @brief Checks if the given mass fractions are valid.
@@ -271,31 +284,31 @@ namespace serif::composition {
/** /**
* @brief Constructs a Composition with the given symbols. * @brief Constructs a Composition with the given symbols.
* @param symbols The symbols to initialize the composition with. * @param symbols The symbols to initialize the composition with.
* @example * *Example Usage:*
* @code * @code
* std::vector<std::string> symbols = {"H", "O"}; * std::vector<std::string> symbols = {"H", "O"};
* Composition comp(symbols); * Composition comp(symbols);
* @endcode * @endcode
*/ */
Composition(const std::vector<std::string>& symbols); explicit Composition(const std::vector<std::string>& symbols);
/** /**
* @brief Constructs a Composition with the given symbols as a set. * @brief Constructs a Composition with the given symbols as a set.
* @param symbols The symbols to initialize the composition with. * @param symbols The symbols to initialize the composition with.
* @example * *Example Usage:*
* @code * @code
* std::set<std::string> symbols = {"H", "O"}; * std::set<std::string> symbols = {"H", "O"};
* Composition comp(symbols); * Composition comp(symbols);
* @endcode * @endcode
*/ */
Composition(const std::set<std::string>& symbols); explicit 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.
* @param mass_fractions The mass fractions corresponding to the symbols. * @param mass_fractions The mass fractions corresponding to the symbols.
* @param massFracMode True if mass fraction mode, false if number fraction mode. * @param massFracMode True if mass fraction mode, false if number fraction mode.
* @example * *Example Usage:*
* @code * @code
* std::vector<std::string> symbols = {"H", "O"}; * std::vector<std::string> symbols = {"H", "O"};
* std::vector<double> mass_fractions = {0.1, 0.9}; * std::vector<double> mass_fractions = {0.1, 0.9};
@@ -304,11 +317,19 @@ namespace serif::composition {
*/ */
Composition(const std::vector<std::string>& symbols, const std::vector<double>& mass_fractions, bool massFracMode=true); Composition(const std::vector<std::string>& symbols, const std::vector<double>& mass_fractions, bool massFracMode=true);
/**
* @brief Constructs a Composition from another Composition.
* @param composition The Composition to copy.
*/
Composition(const Composition& composition);
Composition& operator=(Composition const& other);
/** /**
* @brief Registers a new symbol. * @brief Registers a new symbol.
* @param symbol The symbol to register. * @param symbol The symbol to register.
* @param massFracMode True if mass fraction mode, false if number fraction mode. * @param massFracMode True if mass fraction mode, false if number fraction mode.
* @example * *Example Usage:*
* @code * @code
* Composition comp; * Composition comp;
* comp.registerSymbol("H"); * comp.registerSymbol("H");
@@ -320,7 +341,7 @@ namespace serif::composition {
* @brief Registers multiple new symbols. * @brief Registers multiple new symbols.
* @param symbols The symbols to register. * @param symbols The symbols to register.
* @param massFracMode True if mass fraction mode, false if number fraction mode. * @param massFracMode True if mass fraction mode, false if number fraction mode.
* @example * *Example Usage:*
* @code * @code
* std::vector<std::string> symbols = {"H", "O"}; * std::vector<std::string> symbols = {"H", "O"};
* Composition comp; * Composition comp;
@@ -333,14 +354,14 @@ namespace serif::composition {
* @brief Gets the registered symbols. * @brief Gets the registered symbols.
* @return A set of registered symbols. * @return A set of registered symbols.
*/ */
std::set<std::string> getRegisteredSymbols() const; [[nodiscard]] std::set<std::string> getRegisteredSymbols() const;
/** /**
* @brief Sets the mass fraction for a given symbol. * @brief Sets the mass fraction for a given symbol.
* @param symbol The symbol to set the mass fraction for. * @param symbol The symbol to set the mass fraction for.
* @param mass_fraction The mass fraction to set. * @param mass_fraction The mass fraction to set.
* @return The mass fraction that was set. * @return The mass fraction that was set.
* @example * *Example Usage:*
* @code * @code
* Composition comp; * Composition comp;
* comp.setMassFraction("H", 0.1); * comp.setMassFraction("H", 0.1);
@@ -353,7 +374,7 @@ namespace serif::composition {
* @param symbols The symbols to set the mass fraction for. * @param symbols The symbols to set the mass fraction for.
* @param mass_fractions The mass fractions corresponding to the symbols. * @param mass_fractions The mass fractions corresponding to the symbols.
* @return A vector of mass fractions that were set. * @return A vector of mass fractions that were set.
* @example * *Example Usage:*
* @code * @code
* std::vector<std::string> symbols = {"H", "O"}; * std::vector<std::string> symbols = {"H", "O"};
* std::vector<double> mass_fractions = {0.1, 0.9}; * std::vector<double> mass_fractions = {0.1, 0.9};
@@ -390,40 +411,52 @@ namespace serif::composition {
* @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.
*/ */
std::unordered_map<std::string, double> getMassFraction() const; [[nodiscard]] std::unordered_map<std::string, double> getMassFraction() const;
/** /**
* @brief Gets the mass fraction for a given symbol. * @brief Gets the mass fraction for a given symbol.
* @param symbol The symbol to get the mass fraction for. * @param symbol The symbol to get the mass fraction for.
* @return The mass fraction for the given symbol. * @return The mass fraction for the given symbol.
*/ */
double getMassFraction(const std::string& symbol) const; [[nodiscard]] double getMassFraction(const std::string& symbol) const;
/** /**
* @brief Gets the number fraction for a given symbol. * @brief Gets the number fraction for a given symbol.
* @param symbol The symbol to get the number fraction for. * @param symbol The symbol to get the number fraction for.
* @return The number fraction for the given symbol. * @return The number fraction for the given symbol.
*/ */
double getNumberFraction(const std::string& symbol) const; [[nodiscard]] double getNumberFraction(const std::string& symbol) const;
/** /**
* @brief Gets the number fractions of all compositions. * @brief Gets the number fractions of all compositions.
* @return An unordered map of compositions with their number fractions. * @return An unordered map of compositions with their number fractions.
*/ */
std::unordered_map<std::string, double> getNumberFraction() const; [[nodiscard]] std::unordered_map<std::string, double> getNumberFraction() const;
/** /**
* @brief Gets the composition entry and global composition for a given symbol. * @brief Gets the composition entry and global composition for a given symbol.
* @param symbol The symbol to get the composition for. * @param symbol The symbol to get the composition for.
* @return A pair containing the CompositionEntry and GlobalComposition for the given symbol. * @return A pair containing the CompositionEntry and GlobalComposition for the given symbol.
*/ */
std::pair<CompositionEntry, GlobalComposition> getComposition(const std::string& symbol) const; [[nodiscard]] std::pair<CompositionEntry, GlobalComposition> getComposition(const std::string& symbol) const;
/** /**
* @brief Gets all composition entries and the global composition. * @brief Gets all composition entries and the global composition.
* @return A pair containing an unordered map of CompositionEntries and the GlobalComposition. * @return A pair containing an unordered map of CompositionEntries and the GlobalComposition.
*/ */
std::pair<std::unordered_map<std::string, CompositionEntry>, GlobalComposition> getComposition() const; [[nodiscard]] std::pair<std::unordered_map<std::string, CompositionEntry>, GlobalComposition> getComposition() const;
/**
* @brief Compute the mean particle mass of the composition.
* @return Mean particle mass in g.
*/
[[nodiscard]] double getMeanParticleMass() const;
/**
* @brief Compute the mean atomic mass number of the composition.
* @return Mean atomic mass number.
*/
[[nodiscard]] double getMeanAtomicNumber() const;
/** /**
* @brief Gets a subset of the composition. * @brief Gets a subset of the composition.
@@ -446,6 +479,16 @@ namespace serif::composition {
*/ */
void setCompositionMode(bool massFracMode); void setCompositionMode(bool massFracMode);
/**
* @brief Gets the current canonical composition (X, Y, Z).
* @param harsh If true, this will throw an error if X-Y != Z where Z is computed as the sum of all other elements.
* @return True if mass fraction mode, false if number fraction mode.
*
* @throws std::runtime_error if the composition is not finalized or if the canonical composition cannot be computed.
* @throws std::runtime_error if harsh is true and the canonical composition is not valid.
*/
[[nodiscard]] CanonicalComposition getCanonicalComposition(bool harsh=false) const;
/** /**
* @brief Overloaded output stream operator for Composition. * @brief Overloaded output stream operator for Composition.
* @param os The output stream. * @param os The output stream.
@@ -463,6 +506,4 @@ namespace serif::composition {
Composition operator+(const Composition& other) const; Composition operator+(const Composition& other) const;
}; };
}; // namespace serif::composition }; // namespace serif::composition
#endif // COMPOSITION_H

View File

@@ -1,15 +1,18 @@
# Define the library # Define the library
eos_sources = files( eos_sources = files(
'private/helm.cpp', 'private/helm.cpp',
'private/EOSio.cpp' 'private/EOSio.cpp',
'private/EOS.cpp'
) )
eos_headers = files( eos_headers = files(
'public/helm.h', 'public/helm.h',
'public/EOSio.h' 'public/EOSio.h',
'public/EOS.h'
) )
dependencies = [ dependencies = [
composition_dep,
const_dep, const_dep,
quill_dep, quill_dep,
probe_dep, probe_dep,

64
src/eos/private/EOS.cpp Normal file
View File

@@ -0,0 +1,64 @@
#include "EOS.h"
#include "EOSio.h"
#include "helm.h"
#include <string>
namespace serif::eos {
EOS::EOS(const EOSio& reader) : m_reader(reader) {}
EOS::EOS(const std::string& filename, const EOSFormat format) : m_reader(EOSio(filename, format)) {}
EOSOutput EOS::get(const EOSInput& in) {
EOSOutput output;
if (getFormat() == EOSFormat::HELM) {
helmholtz::HELMEOSInput q;
q.T = in.temperature; // Temperature in K
q.rho = in.density; // Density in g/cm^3
q.abar = in.composition.getMeanParticleMass(); // Mean atomic mass in g
q.zbar = in.composition.getMeanAtomicNumber(); // Mean atomic number (dimensionless)
helmholtz::HELMEOSOutput tempOutput;
tempOutput = helmholtz::get_helm_EOS(q, *std::get<std::unique_ptr<helmholtz::HELMTable>>(m_reader.getTable()));
output.electronFraction = tempOutput.ye;
output.electronChemicalPotential = tempOutput.etaele;
output.neutronExcessFraction = tempOutput.xnefer;
// --- Pressure Variables ---
output.pressure.total = tempOutput.ptot;
output.pressure.gas = tempOutput.pgas;
output.pressure.radiation = tempOutput.ptot;
output.pressure.dDensity = tempOutput.dpresdd;
output.pressure.dTemperature = tempOutput.dpresdt;
output.pressure.dMeanAtomicMassNumber = tempOutput.dpresda;
output.pressure.dMeanAtomicNumber = tempOutput.dpresdz;
// --- Energy Variables ---
output.energy.total = tempOutput.etot;
output.energy.gas = tempOutput.egas;
output.energy.radiation = tempOutput.erad;
output.energy.dDensity = tempOutput.denerdd;
output.energy.dTemperature = tempOutput.denerdt;
output.energy.dMeanAtomicMassNumber = tempOutput.denerda;
output.energy.dMeanAtomicNumber = tempOutput.denerdz;
// --- Entropy Variables ---
output.entropy.total = tempOutput.stot;
output.entropy.gas = tempOutput.sgas;
output.entropy.radiation = tempOutput.srad;
output.entropy.dDensity = tempOutput.dentrdd;
output.entropy.dTemperature = tempOutput.dentrdt;
output.entropy.dMeanAtomicMassNumber = tempOutput.dentrda;
output.entropy.dMeanAtomicNumber = tempOutput.dentrdz;
}
return output;
}
EOSFormat EOS::getFormat() const {
return m_reader.getFormat();
}
const EOSio& EOS::getReader() const {
return m_reader;
}
}

View File

@@ -28,25 +28,32 @@
#include <string> #include <string>
namespace serif::eos { namespace serif::eos {
EOSio::EOSio(const std::string &filename) : m_filename(filename) { EOSio::EOSio(const std::string &filename, const EOSFormat format) : m_filename(filename), m_format(format){
load(); load();
} }
std::string EOSio::getFormat() const { EOSio::EOSio(const EOSio &other) {
m_filename = other.m_filename;
m_format = other.m_format;
load();
}
EOSFormat EOSio::getFormat() const {
return m_format; return m_format;
} }
std::string EOSio::getFormatName() const {
return FormatStringLookup.at(m_format);
}
EOSTable& EOSio::getTable() { EOSTable& EOSio::getTable() {
return m_table; return m_table;
} }
void EOSio::load() { void EOSio::load() {
// Load the EOS table from the file if (m_format == EOSFormat::HELM) {
// For now, just set the format to HELM
m_format = "helm";
if (m_format == "helm") {
loadHelm(); loadHelm();
} }
} }

View File

@@ -240,7 +240,7 @@ namespace serif::eos::helmholtz {
ion, radiation, electron-positron and Coulomb interaction ion, radiation, electron-positron and Coulomb interaction
and returns the calculated quantities in the input and returns the calculated quantities in the input
***/ ***/
serif::eos::helmholtz::EOS get_helm_EOS(serif::eos::helmholtz::EOSInput &q, const serif::eos::helmholtz::HELMTable &table) { serif::eos::helmholtz::HELMEOSOutput get_helm_EOS(serif::eos::helmholtz::HELMEOSInput &q, const serif::eos::helmholtz::HELMTable &table) {
serif::config::Config& config = serif::config::Config::getInstance(); serif::config::Config& config = serif::config::Config::getInstance();
auto logFile = config.get<std::string>("EOS:Helm:LogFile", "log"); auto logFile = config.get<std::string>("EOS:Helm:LogFile", "log");
serif::probe::LogManager& logManager = serif::probe::LogManager::getInstance(); serif::probe::LogManager& logManager = serif::probe::LogManager::getInstance();
@@ -829,7 +829,7 @@ namespace serif::eos::helmholtz {
double csound = clight * sqrt(gamma1/z); double csound = clight * sqrt(gamma1/z);
// package in q: // package in q:
serif::eos::helmholtz::EOS eos; serif::eos::helmholtz::HELMEOSOutput eos;
eos.ptot = ptot; eos.etot = etot; eos.stot = stot; eos.ptot = ptot; eos.etot = etot; eos.stot = stot;
eos.pgas = pgas; eos.egas = egas; eos.sgas = sgas; eos.pgas = pgas; eos.egas = egas; eos.sgas = sgas;
eos.prad = prad; eos.erad = erad; eos.srad = srad; eos.prad = prad; eos.erad = erad; eos.srad = srad;

266
src/eos/public/EOS.h Normal file
View File

@@ -0,0 +1,266 @@
#pragma once
#include "EOSio.h"
#include "helm.h"
#include <string>
#include "composition.h"
#include <iomanip>
namespace serif::eos {
/**
* @brief Input parameters for an EOS calculation.
*
* This struct holds the necessary physical conditions (composition, density, temperature)
* required to query the Equation of State.
*/
struct EOSInput {
serif::composition::Composition composition; ///< The composition of the system.
double density; ///< The density of the system in cgs (g/cm^3).
double temperature; ///< The temperature of the system in cgs (K).
friend std::ostream& operator<<(std::ostream& os, const EOSInput& input) {
os << "<EOSInput: "
<< "Density: " << input.density << " g/cm^3, "
<< "Temperature: " << input.temperature << " K, "
<< "Composition: " << input.composition << ">";
return os;
}
};
/**
* @brief Represents a thermodynamic parameter and its derivatives.
*
* This struct stores a specific thermodynamic quantity (e.g., pressure, energy, entropy),
* its breakdown into gas and radiation components, and its partial derivatives
* with respect to density, temperature, mean atomic mass number, and mean atomic number.
* All values are in cgs units unless otherwise specified.
*/
struct EOSParameter {
explicit EOSParameter(std::string name_)
: total(), gas(), radiation(),
dDensity(), dTemperature(),
dMeanAtomicMassNumber(),
dMeanAtomicNumber(),
name(std::move(name_)) {}
double total; ///< Total value of the parameter (gas + radiation) (cgs).
double gas; ///< Gas contribution to the parameter (cgs).
double radiation; ///< Radiation contribution to the parameter (cgs).
double dDensity; ///< Derivative of the total parameter with respect to density (cgs units / (g/cm^3)).
double dTemperature; ///< Derivative of the total parameter with respect to temperature (cgs units / K).
double dMeanAtomicMassNumber; ///< Derivative of the total parameter with respect to mean atomic mass number (Abar) (cgs units / (g/mol)).
double dMeanAtomicNumber; ///< Derivative of the total parameter with respect to mean atomic number (Zbar) (cgs units / dimensionless).
std::string name; ///< Name of the parameter (e.g., "Pressure", "Energy", "Entropy").
friend std::ostream& operator<<(std::ostream& os, const EOSParameter& param) {
os << std::setprecision(5) << "<EOSParameter (" << param.name << "): " << param.total << " (gas: " << param.gas
<< ", radiation: " << param.radiation << ") "
<< "d/dRho: " << param.dDensity << ", d/dT: " << param.dTemperature
<< ", d/dAbar: " << param.dMeanAtomicMassNumber
<< ", d/dZbar: " << param.dMeanAtomicNumber << ">";
return os;
}
};
/**
* @brief Output from an EOS calculation.
*
* This struct contains various thermodynamic quantities and their derivatives
* calculated by the EOS for a given set of input conditions.
* It includes fundamental properties like electron fraction and chemical potential,
* as well as detailed breakdowns of pressure, energy, and entropy.
* Additionally, it provides methods to calculate derived quantities like
* susceptibilities, sound speed, adiabatic gradients, and specific heats.
*/
struct EOSOutput {
double electronFraction{}; ///< Electron fraction (ye), dimensionless.
double electronChemicalPotential{}; ///< Electron chemical potential (eta_e) in cgs (erg/g).
double neutronExcessFraction{}; ///< Neutron excess fraction (xnefer), dimensionless.
EOSParameter pressure {"pressure"}; ///< Pressure output data, including total, gas, radiation, and derivatives.
EOSParameter energy {"energy"}; ///< Internal energy output data, including total, gas, radiation, and derivatives.
EOSParameter entropy {"entropy"}; ///< Entropy output data, including total, gas, radiation, and derivatives.
/**
* @brief Calculates the temperature susceptibility (chi_T).
* @return Temperature susceptibility, dimensionless.
* @note Placeholder: Actual calculation needs to be implemented based on available EOS derivatives.
* Typically, chi_T = (d ln P / d ln T)_rho.
*/
double chiTemperature();
/**
* @brief Calculates the density susceptibility (chi_rho).
* @return Density susceptibility, dimensionless.
* @note Placeholder: Actual calculation needs to be implemented based on available EOS derivatives.
* Typically, chi_rho = (d ln P / d ln rho)_T.
*/
double chiRho();
/**
* @brief Calculates the adiabatic sound speed.
* @return Sound speed in cgs (cm/s).
* @note Placeholder: Actual calculation needs to be implemented based on available EOS derivatives.
* Typically, c_s^2 = gamma1 * P / rho.
*/
double soundSpeed();
/**
* @brief Calculates the adiabatic temperature gradient (nabla_ad).
* @return Adiabatic gradient, dimensionless.
* @note Placeholder: Actual calculation needs to be implemented based on available EOS derivatives.
* Typically, nabla_ad = (P * chi_T) / (rho * T * c_p * chi_rho).
*/
double adiabaticGradient();
/**
* @brief Calculates the first adiabatic index (Gamma1).
* @return First adiabatic index, dimensionless.
* @note Placeholder: Actual calculation needs to be implemented based on available EOS derivatives.
* Typically, Gamma1 = (d ln P / d ln rho)_S.
*/
double gamma1();
/**
* @brief Calculates the second adiabatic index (Gamma2).
* @return Second adiabatic index, dimensionless.
* @note Placeholder: Actual calculation needs to be implemented based on available EOS derivatives.
* Typically, Gamma2 / (Gamma2 - 1) = (d ln P / d ln T)_S.
*/
double gamma2();
/**
* @brief Calculates the third adiabatic index (Gamma3).
* @return Third adiabatic index, dimensionless.
* @note Placeholder: Actual calculation needs to be implemented based on available EOS derivatives.
* Typically, Gamma3 - 1 = (d ln T / d ln rho)_S.
*/
double gamma3();
/**
* @brief Calculates the specific heat capacity at constant volume (c_v).
* @return Specific heat capacity at constant volume in cgs (erg/K/g).
* @note Placeholder: Actual calculation needs to be implemented based on available EOS derivatives.
* Typically, c_v = (dE/dT)_rho.
*/
double specificHeatCapacityAtConstantVolume();
/**
* @brief Calculates the specific heat capacity at constant pressure (c_p).
* @return Specific heat capacity at constant pressure in cgs (erg/K/g).
* @note Placeholder: Actual calculation needs to be implemented based on available EOS derivatives.
* Typically, c_p = c_v + (T / rho^2) * ( (d P / d T)_rho^2 / (d P / d rho)_T ).
*/
double specificHeatCapacityAtConstantPressure();
/**
* @brief Returns the format of the EOS data used to generate this output.
* @return The EOSFormat enum value (currently only EOSFormat::HELM).
*/
EOSFormat EOSFormat() const;
friend std::ostream& operator<<(std::ostream& os, const EOSOutput& output) {
os << "EOSOutput:\n"
<< "\tElectron Fraction: " << output.electronFraction << "\n"
<< "\tElectron Chemical Potential: " << output.electronChemicalPotential << "\n"
<< "\tNeutron Excess Fraction: " << output.neutronExcessFraction << "\n\t"
<< output.pressure << "\n\t"
<< output.energy << "\n\t"
<< output.entropy;
return os;
}
};
/**
* @class EOS
* @brief Main class for accessing Equation of State data.
*
* This class provides an interface to an underlying EOS table (e.g., Helmholtz EOS).
* It handles loading the EOS data and provides a method to retrieve thermodynamic
* properties for given physical conditions.
*
* @example
* @code
* #include "EOS.h"
* #include "composition.h" // For serif::composition::Composition
* #include <iostream>
*
* int main() {
* try {
* // Initialize EOS from a Helmholtz table file
* serif::eos::EOS helmEOS("path/to/helm_table.dat", serif::eos::EOSFormat::HELM);
*
* // Define input conditions
* serif::eos::EOSInput input;
* input.density = 1.0e6; // g/cm^3
* input.temperature = 1.0e7; // K
* // Assuming a simple composition (e.g., pure Helium-4 for demonstration)
* // In a real scenario, initialize Composition properly.
* // For example, if Composition has a constructor like:
* // Composition(const std::map<std::pair<int, int>, double>& mass_fractions);
* // std::map<std::pair<int, int>, double> he4_mass_fraction = {{{2, 4}, 1.0}};
* // input.composition = serif::composition::Composition(he4_mass_fraction);
* // For now, let's assume Composition can be default constructed or set up simply:
* input.composition.addSpecies(2, 4, 1.0); // Z=2, A=4 (He-4), mass fraction 1.0
*
* // Get EOS output
* serif::eos::EOSOutput output = helmEOS.get(input);
*
* // Access results
* std::cout << "Pressure (total): " << output.pressure.total << " dyne/cm^2" << std::endl;
* std::cout << "Energy (total): " << output.energy.total << " erg/g" << std::endl;
* std::cout << "Entropy (total): " << output.entropy.total << " erg/K/g" << std::endl;
* std::cout << "Electron fraction: " << output.electronFraction << std::endl;
*
* // Example of accessing derivatives
* std::cout << "dP/dRho: " << output.pressure.dDensity << std::endl;
* std::cout << "dE/dT: " << output.energy.dTemperature << std::endl;
*
* } catch (const std::exception& e) {
* std::cerr << "An error occurred: " << e.what() << std::endl;
* return 1;
* }
* return 0;
* }
* @endcode
*/
class EOS {
public:
/**
* @brief Constructs an EOS object by loading data from a file.
* @param filename The path to the EOS data file.
* @param format The format of the EOS data file (e.g., EOSFormat::HELM).
* @throw std::runtime_error If the file cannot be opened or read, or if the format is unsupported.
*/
explicit EOS(const std::string& filename, EOSFormat format=EOSFormat::HELM);
/**
* @brief Constructs an EOS object from an existing EOSio reader.
* @param reader An EOSio object that has already loaded the EOS data.
*/
explicit EOS(const EOSio& reader);
/**
* @brief Default destructor.
*/
~EOS() = default;
/**
* @brief Retrieves thermodynamic properties for the given input conditions.
* @param in An EOSInput struct containing the density, temperature, and composition.
* @return An EOSOutput struct containing the calculated thermodynamic properties.
* @throw std::runtime_error If the underlying EOS calculation fails (e.g., out of table bounds for Helmholtz).
*
* This method queries the loaded EOS table (e.g., Helmholtz) using the provided
* density, temperature, and composition (mean atomic mass Abar, mean atomic number Zbar).
* It populates and returns an EOSOutput struct with various thermodynamic quantities
* such as pressure, energy, entropy, their derivatives, electron fraction, etc.
*/
[[nodiscard]] EOSOutput get(const EOSInput& in);
/**
* @brief Gets the format of the loaded EOS data.
* @return The EOSFormat enum value.
*/
[[nodiscard]] EOSFormat getFormat() const;
/**
* @brief Gets a constant reference to the internal EOSio reader.
* @return A const reference to the EOSio object.
*/
[[nodiscard]] const EOSio& getReader() const;
private:
EOSio m_reader; ///< The EOS I/O handler responsible for reading and storing EOS table data.
};
}

View File

@@ -22,15 +22,20 @@
#include <string> #include <string>
#include <variant> #include <variant>
#include <memory> #include <memory>
#include <unordered_map>
#include "helm.h" #include "helm.h"
namespace serif::eos { namespace serif::eos {
enum EOSFormat {
HELM, ///< Helmholtz EOS format.
};
static inline std::unordered_map<EOSFormat, std::string> FormatStringLookup = {
{HELM, "Helmholtz"}
};
// EOS table format includes // EOS table format includes
using EOSTable = std::variant< using EOSTable = std::variant<std::unique_ptr<serif::eos::helmholtz::HELMTable>>;
std::unique_ptr<serif::eos::helmholtz::HELMTable>
>;
/** /**
* @class EOSio * @class EOSio
@@ -41,16 +46,19 @@ namespace serif::eos {
* *
* Example usage: * Example usage:
* @code * @code
* EosIO eosIO("path/to/file"); * EOSio eosReader("path/to/file");
* std::string format = eosIO.getFormat(); * std::string format = eosReader.getFormatName();
* EOSTable& table = eosIO.getTable(); * EOSTable& table = eosReader.getTable();
* @endcode * @endcode
*
* @note The default format used for reading tables is HELM
* @note Currently only the HELM format is implemented
*/ */
class EOSio { class EOSio {
private: private:
std::string m_filename; ///< The filename of the EOS table. std::string m_filename; ///< The filename of the EOS table.
bool m_loaded = false; ///< Flag indicating if the table is loaded. bool m_loaded = false; ///< Flag indicating if the table is loaded.
std::string m_format; ///< The format of the EOS table. EOSFormat m_format;
EOSTable m_table; ///< The EOS table data. EOSTable m_table; ///< The EOS table data.
/** /**
@@ -66,8 +74,15 @@ namespace serif::eos {
/** /**
* @brief Constructs an EosIO object with the given filename. * @brief Constructs an EosIO object with the given filename.
* @param filename The filename of the EOS table. * @param filename The filename of the EOS table.
* @param format The EOS file format (currently only HELM)
*/ */
explicit EOSio(const std::string &filename); explicit EOSio(const std::string &filename, EOSFormat format = EOSFormat::HELM);
/**
* @brief Explicit copy constructor
* @param other The EOSio to be copied
*/
EOSio(const EOSio& other);
/** /**
* @brief Default destructor. * @brief Default destructor.
@@ -75,10 +90,12 @@ namespace serif::eos {
~EOSio() = default; ~EOSio() = default;
/** /**
* @brief Gets the format of the EOS table. * @brief Gets the format name (as a string) of the EOS table.
* @return The format of the EOS table as a string. * @return The format of the EOS table as a string.
*/ */
[[nodiscard]] std::string getFormat() const; [[nodiscard]] std::string getFormatName() const;
[[nodiscard]] EOSFormat getFormat() const;
/** /**
* @brief Gets the EOS table. * @brief Gets the EOS table.
@@ -87,6 +104,8 @@ namespace serif::eos {
[[nodiscard]] EOSTable& getTable(); [[nodiscard]] EOSTable& getTable();
[[nodiscard]] std::string getFilename() const { return m_filename; } [[nodiscard]] std::string getFilename() const { return m_filename; }
bool isLoaded() const { return m_loaded; }
}; };
} }

View File

@@ -169,18 +169,18 @@ namespace serif::eos::helmholtz {
}; };
/** /**
* @struct EOSInput * @struct HELMEOSInput
* @brief Structure to hold the input parameters for the EOS calculation. * @brief Structure to hold the input parameters for the EOS calculation.
*/ */
struct EOSInput struct HELMEOSInput
{ {
double T; ///< Temperature. double T; ///< Temperature.
double rho; ///< Density. double rho; ///< Density.
double abar; ///< Mean atomic mass. double abar; ///< Mean atomic mass.
double zbar; ///< Mean atomic number. double zbar; ///< Mean atomic number.
friend std::ostream& operator<<(std::ostream& os, const helmholtz::EOSInput& eosInput) { friend std::ostream& operator<<(std::ostream& os, const helmholtz::HELMEOSInput& eosInput) {
os << "EOSInput Data:\n"; os << "HELMEOSInput Data:\n";
os << " Temperature: " << eosInput.T << "\n"; os << " Temperature: " << eosInput.T << "\n";
os << " Density: " << eosInput.rho << "\n"; os << " Density: " << eosInput.rho << "\n";
os << " Mean Atomic Mass: " << eosInput.abar << "\n"; os << " Mean Atomic Mass: " << eosInput.abar << "\n";
@@ -194,7 +194,7 @@ namespace serif::eos::helmholtz {
* @struct EOS * @struct EOS
* @brief Structure to hold the output parameters and derivatives of the EOS calculation. * @brief Structure to hold the output parameters and derivatives of the EOS calculation.
*/ */
struct EOS struct HELMEOSOutput
{ {
// output // output
double ye, etaele, xnefer; // double ye, etaele, xnefer; //
@@ -212,7 +212,7 @@ namespace serif::eos::helmholtz {
double gamma1, gamma2, gamma3, cV, cP; // derived quantities double gamma1, gamma2, gamma3, cV, cP; // derived quantities
double dse, dpe, dsp; // Maxwell relations double dse, dpe, dsp; // Maxwell relations
friend std::ostream& operator<<(std::ostream& os, const helmholtz::EOS& eos) { friend std::ostream& operator<<(std::ostream& os, const helmholtz::HELMEOSOutput& eos) {
os << "EOS Data:\n" << std::setw(20) << std::left; os << "EOS Data:\n" << std::setw(20) << std::left;
os << " Electron Fraction: " << std::format("{0:24.16e}",eos.ye) << "\n"; os << " Electron Fraction: " << std::format("{0:24.16e}",eos.ye) << "\n";
os << " Electron Chemical Potential: " << std::format("{0:24.16e}",eos.etaele) << "\n"; os << " Electron Chemical Potential: " << std::format("{0:24.16e}",eos.etaele) << "\n";
@@ -379,7 +379,7 @@ namespace serif::eos::helmholtz {
* @param table HELMTable structure containing the table data. * @param table HELMTable structure containing the table data.
* @return EOS structure containing the calculated quantities. * @return EOS structure containing the calculated quantities.
*/ */
EOS get_helm_EOS(EOSInput &q, const HELMTable &table); HELMEOSOutput get_helm_EOS(HELMEOSInput &q, const HELMTable &table);
} }

View File

@@ -15,7 +15,9 @@ dependencies = [
quill_dep, quill_dep,
mfem_dep, mfem_dep,
config_dep, config_dep,
probe_dep probe_dep,
species_weight_dep,
composition_dep,
] ]
# Define the libnetwork library so it can be linked against by other parts of the build system # Define the libnetwork library so it can be linked against by other parts of the build system

View File

@@ -31,7 +31,7 @@
#include "approx8.h" #include "approx8.h"
#include "network.h" #include "network.h"
/* Nuclear reaction network in cgs units based on Frank Timmes' "aprox8". /* Nuclear reaction network in cgs units based on Frank Timmes' "approx8".
At this time it does neither screening nor neutrino losses. It includes At this time it does neither screening nor neutrino losses. It includes
the following 8 isotopes: the following 8 isotopes:
@@ -78,7 +78,7 @@ namespace serif::network::approx8{
using namespace boost::numeric::odeint; using namespace boost::numeric::odeint;
//helper functions //helper functions
// a function to multilpy two arrays and then sum the resulting elements: sum(a*b) // a function to multiply two arrays and then sum the resulting elements: sum(a*b)
double sum_product( const vec7 &a, const vec7 &b){ double sum_product( const vec7 &a, const vec7 &b){
if (a.size() != b.size()) { if (a.size() != b.size()) {
throw std::runtime_error("Error: array size mismatch in sum_product"); throw std::runtime_error("Error: array size mismatch in sum_product");
@@ -96,8 +96,8 @@ namespace serif::network::approx8{
// this function returns an array of the T9 terms in that order, where T9 is the temperatures in GigaKelvin // this function returns an array of the T9 terms in that order, where T9 is the temperatures in GigaKelvin
vec7 get_T9_array(const double &T) { vec7 get_T9_array(const double &T) {
vec7 arr; vec7 arr;
double T9=1e-9*T; const double T9=1e-9*T;
double T913=pow(T9,1./3.); const double T913=pow(T9,1./3.);
arr[0]=1; arr[0]=1;
arr[1]=1/T9; arr[1]=1/T9;
@@ -117,125 +117,125 @@ namespace serif::network::approx8{
// p + p -> d; this, like some of the other rates, this is a composite of multiple fits // p + p -> d; this, like some of the other rates, this is a composite of multiple fits
double pp_rate(const vec7 &T9) { double pp_rate(const vec7 &T9) {
vec7 a1 = {-34.78630, 0,-3.511930, 3.100860, -0.1983140, 1.262510e-2, -1.025170}; constexpr vec7 a1 = {-34.78630, 0,-3.511930, 3.100860, -0.1983140, 1.262510e-2, -1.025170};
vec7 a2 = { -4.364990e+1,-2.460640e-3,-2.750700,-4.248770e-1,1.598700e-2,-6.908750e-4,-2.076250e-1}; constexpr vec7 a2 = { -4.364990e+1,-2.460640e-3,-2.750700,-4.248770e-1,1.598700e-2,-6.908750e-4,-2.076250e-1};
return rate_fit(T9,a1) + rate_fit(T9,a2); return rate_fit(T9,a1) + rate_fit(T9,a2);
} }
// p + d -> he3 // p + d -> he3
double dp_rate(const vec7 &T9) { double dp_rate(const vec7 &T9) {
vec7 a1 = {7.528980, 0, -3.720800, 0.8717820, 0, 0,-0.6666670}; constexpr vec7 a1 = {7.528980, 0, -3.720800, 0.8717820, 0, 0,-0.6666670};
vec7 a2 = {8.935250, 0, -3.720800, 0.1986540, 0, 0, 0.3333330}; constexpr vec7 a2 = {8.935250, 0, -3.720800, 0.1986540, 0, 0, 0.3333330};
return rate_fit(T9,a1) + rate_fit(T9,a2); return rate_fit(T9,a1) + rate_fit(T9,a2);
} }
// he3 + he3 -> he4 + 2p // he3 + he3 -> he4 + 2p
double he3he3_rate(const vec7 &T9){ double he3he3_rate(const vec7 &T9){
vec7 a = {2.477880e+01,0,-12.27700,-0.1036990,-6.499670e-02,1.681910e-02,-6.666670e-01}; constexpr vec7 a = {2.477880e+01,0,-12.27700,-0.1036990,-6.499670e-02,1.681910e-02,-6.666670e-01};
return rate_fit(T9,a); return rate_fit(T9,a);
} }
// he3(he3,2p)he4 // he3(he3,2p)he4
double he3he4_rate(const vec7 &T9){ double he3he4_rate(const vec7 &T9){
vec7 a1 = {1.560990e+01,0.000000e+00,-1.282710e+01,-3.082250e-02,-6.546850e-01,8.963310e-02,-6.666670e-01}; constexpr vec7 a1 = {1.560990e+01,0.000000e+00,-1.282710e+01,-3.082250e-02,-6.546850e-01,8.963310e-02,-6.666670e-01};
vec7 a2 = {1.770750e+01,0.000000e+00,-1.282710e+01,-3.812600e+00,9.422850e-02,-3.010180e-03,1.333330e+00}; constexpr vec7 a2 = {1.770750e+01,0.000000e+00,-1.282710e+01,-3.812600e+00,9.422850e-02,-3.010180e-03,1.333330e+00};
return rate_fit(T9,a1) + rate_fit(T9,a2); return rate_fit(T9,a1) + rate_fit(T9,a2);
} }
// he4 + he4 + he4 -> c12 // he4 + he4 + he4 -> c12
double triple_alpha_rate(const vec7 &T9){ double triple_alpha_rate(const vec7 &T9){
vec7 a1 = {-9.710520e-01,0.000000e+00,-3.706000e+01,2.934930e+01,-1.155070e+02,-1.000000e+01,-1.333330e+00}; constexpr vec7 a1 = {-9.710520e-01,0.000000e+00,-3.706000e+01,2.934930e+01,-1.155070e+02,-1.000000e+01,-1.333330e+00};
vec7 a2 = {-1.178840e+01,-1.024460e+00,-2.357000e+01,2.048860e+01,-1.298820e+01,-2.000000e+01,-2.166670e+00}; constexpr vec7 a2 = {-1.178840e+01,-1.024460e+00,-2.357000e+01,2.048860e+01,-1.298820e+01,-2.000000e+01,-2.166670e+00};
vec7 a3 = {-2.435050e+01,-4.126560e+00,-1.349000e+01,2.142590e+01,-1.347690e+00,8.798160e-02,-1.316530e+01}; constexpr vec7 a3 = {-2.435050e+01,-4.126560e+00,-1.349000e+01,2.142590e+01,-1.347690e+00,8.798160e-02,-1.316530e+01};
return rate_fit(T9,a1) + rate_fit(T9,a2) + rate_fit(T9,a3); return rate_fit(T9,a1) + rate_fit(T9,a2) + rate_fit(T9,a3);
} }
// c12 + p -> n13 // c12 + p -> n13
double c12p_rate(const vec7 &T9){ double c12p_rate(const vec7 &T9){
vec7 a1={1.714820e+01,0.000000e+00,-1.369200e+01,-2.308810e-01,4.443620e+00,-3.158980e+00,-6.666670e-01}; constexpr vec7 a1={1.714820e+01,0.000000e+00,-1.369200e+01,-2.308810e-01,4.443620e+00,-3.158980e+00,-6.666670e-01};
vec7 a2={1.754280e+01,-3.778490e+00,-5.107350e+00,-2.241110e+00,1.488830e-01,0.000000e+00,-1.500000e+00}; constexpr vec7 a2={1.754280e+01,-3.778490e+00,-5.107350e+00,-2.241110e+00,1.488830e-01,0.000000e+00,-1.500000e+00};
return rate_fit(T9,a1) + rate_fit(T9,a2); return rate_fit(T9,a1) + rate_fit(T9,a2);
} }
// c12 + he4 -> o16 // c12 + he4 -> o16
double c12a_rate(const vec7 &T9){ double c12a_rate(const vec7 &T9){
vec7 a1={6.965260e+01,-1.392540e+00,5.891280e+01,-1.482730e+02,9.083240e+00,-5.410410e-01,7.035540e+01}; constexpr vec7 a1={6.965260e+01,-1.392540e+00,5.891280e+01,-1.482730e+02,9.083240e+00,-5.410410e-01,7.035540e+01};
vec7 a2={2.546340e+02,-1.840970e+00,1.034110e+02,-4.205670e+02,6.408740e+01,-1.246240e+01,1.373030e+02}; constexpr vec7 a2={2.546340e+02,-1.840970e+00,1.034110e+02,-4.205670e+02,6.408740e+01,-1.246240e+01,1.373030e+02};
return rate_fit(T9,a1) + rate_fit(T9,a2); return rate_fit(T9,a1) + rate_fit(T9,a2);
} }
// n14(p,g)o15 - o15 + p -> c12 + he4 // n14(p,g)o15 - o15 + p -> c12 + he4
double n14p_rate(const vec7 &T9){ double n14p_rate(const vec7 &T9){
vec7 a1={1.701000e+01,0.000000e+00,-1.519300e+01,-1.619540e-01,-7.521230e+00,-9.875650e-01,-6.666670e-01}; constexpr vec7 a1={1.701000e+01,0.000000e+00,-1.519300e+01,-1.619540e-01,-7.521230e+00,-9.875650e-01,-6.666670e-01};
vec7 a2={2.011690e+01,0.000000e+00,-1.519300e+01,-4.639750e+00,9.734580e+00,-9.550510e+00,3.333330e-01}; constexpr vec7 a2={2.011690e+01,0.000000e+00,-1.519300e+01,-4.639750e+00,9.734580e+00,-9.550510e+00,3.333330e-01};
vec7 a3={7.654440e+00,-2.998000e+00,0.000000e+00,0.000000e+00,0.000000e+00,0.000000e+00,-1.500000e+00}; constexpr vec7 a3={7.654440e+00,-2.998000e+00,0.000000e+00,0.000000e+00,0.000000e+00,0.000000e+00,-1.500000e+00};
vec7 a4={6.735780e+00,-4.891000e+00,0.000000e+00,0.000000e+00,0.000000e+00,0.000000e+00,6.820000e-02}; constexpr vec7 a4={6.735780e+00,-4.891000e+00,0.000000e+00,0.000000e+00,0.000000e+00,0.000000e+00,6.820000e-02};
return rate_fit(T9,a1) + rate_fit(T9,a2) + rate_fit(T9,a3) + rate_fit(T9,a4); return rate_fit(T9,a1) + rate_fit(T9,a2) + rate_fit(T9,a3) + rate_fit(T9,a4);
} }
// n14(a,g)f18 assumed to go on to ne20 // n14(a,g)f18 assumed to go on to ne20
double n14a_rate(const vec7 &T9){ double n14a_rate(const vec7 &T9){
vec7 a1={2.153390e+01,0.000000e+00,-3.625040e+01,0.000000e+00,0.000000e+00,-5.000000e+00,-6.666670e-01}; constexpr vec7 a1={2.153390e+01,0.000000e+00,-3.625040e+01,0.000000e+00,0.000000e+00,-5.000000e+00,-6.666670e-01};
vec7 a2={1.968380e-01,-5.160340e+00,0.000000e+00,0.000000e+00,0.000000e+00,0.000000e+00,-1.500000e+00}; constexpr vec7 a2={1.968380e-01,-5.160340e+00,0.000000e+00,0.000000e+00,0.000000e+00,0.000000e+00,-1.500000e+00};
vec7 a3={1.389950e+01,-1.096560e+01,-5.622700e+00,0.000000e+00,0.000000e+00,0.000000e+00,-1.500000e+00}; constexpr vec7 a3={1.389950e+01,-1.096560e+01,-5.622700e+00,0.000000e+00,0.000000e+00,0.000000e+00,-1.500000e+00};
return rate_fit(T9,a1) + rate_fit(T9,a2) + rate_fit(T9,a3); return rate_fit(T9,a1) + rate_fit(T9,a2) + rate_fit(T9,a3);
} }
// n15(p,a)c12 (CNO I) // n15(p,a)c12 (CNO I)
double n15pa_rate(const vec7 &T9){ double n15pa_rate(const vec7 &T9){
vec7 a1 = {2.747640e+01,0.000000e+00,-1.525300e+01,1.593180e+00,2.447900e+00,-2.197080e+00,-6.666670e-01}; constexpr vec7 a1 = {2.747640e+01,0.000000e+00,-1.525300e+01,1.593180e+00,2.447900e+00,-2.197080e+00,-6.666670e-01};
vec7 a2 = {-4.873470e+00,-2.021170e+00,0.000000e+00,3.084970e+01,-8.504330e+00,-1.544260e+00,-1.500000e+00}; constexpr vec7 a2 = {-4.873470e+00,-2.021170e+00,0.000000e+00,3.084970e+01,-8.504330e+00,-1.544260e+00,-1.500000e+00};
vec7 a3 = {2.089720e+01,-7.406000e+00,0.000000e+00,0.000000e+00,0.000000e+00,0.000000e+00,-1.500000e+00}; constexpr vec7 a3 = {2.089720e+01,-7.406000e+00,0.000000e+00,0.000000e+00,0.000000e+00,0.000000e+00,-1.500000e+00};
vec7 a4 = {-6.575220e+00,-1.163800e+00,0.000000e+00,2.271050e+01,-2.907070e+00,2.057540e-01,-1.500000e+00}; constexpr vec7 a4 = {-6.575220e+00,-1.163800e+00,0.000000e+00,2.271050e+01,-2.907070e+00,2.057540e-01,-1.500000e+00};
return rate_fit(T9,a1) + rate_fit(T9,a2) + rate_fit(T9,a3) + rate_fit(T9,a4); return rate_fit(T9,a1) + rate_fit(T9,a2) + rate_fit(T9,a3) + rate_fit(T9,a4);
} }
// n15(p,g)o16 (CNO II) // n15(p,g)o16 (CNO II)
double n15pg_rate(const vec7 &T9){ double n15pg_rate(const vec7 &T9){
vec7 a1 = {2.001760e+01,0.000000e+00,-1.524000e+01,3.349260e-01,4.590880e+00,-4.784680e+00,-6.666670e-01}; constexpr vec7 a1 = {2.001760e+01,0.000000e+00,-1.524000e+01,3.349260e-01,4.590880e+00,-4.784680e+00,-6.666670e-01};
vec7 a2 = {6.590560e+00,-2.923150e+00,0.000000e+00,0.000000e+00,0.000000e+00,0.000000e+00,-1.500000e+00}; constexpr vec7 a2 = {6.590560e+00,-2.923150e+00,0.000000e+00,0.000000e+00,0.000000e+00,0.000000e+00,-1.500000e+00};
vec7 a3 = {1.454440e+01,-1.022950e+01,0.000000e+00,0.000000e+00,4.590370e-02,0.000000e+00,-1.500000e+00}; constexpr vec7 a3 = {1.454440e+01,-1.022950e+01,0.000000e+00,0.000000e+00,4.590370e-02,0.000000e+00,-1.500000e+00};
return rate_fit(T9,a1) + rate_fit(T9,a2) + rate_fit(T9,a3); return rate_fit(T9,a1) + rate_fit(T9,a2) + rate_fit(T9,a3);
} }
double n15pg_frac(const vec7 &T9){ double n15pg_frac(const vec7 &T9){
double f1=n15pg_rate(T9); const double f1=n15pg_rate(T9);
double f2=n15pa_rate(T9); const double f2=n15pa_rate(T9);
return f1/(f1+f2); return f1/(f1+f2);
} }
// o16(p,g)f17 then f17 -> o17(p,a)n14 // o16(p,g)f17 then f17 -> o17(p,a)n14
double o16p_rate(const vec7 &T9){ double o16p_rate(const vec7 &T9){
vec7 a={1.909040e+01,0.000000e+00,-1.669600e+01,-1.162520e+00,2.677030e-01,-3.384110e-02,-6.666670e-01}; constexpr vec7 a={1.909040e+01,0.000000e+00,-1.669600e+01,-1.162520e+00,2.677030e-01,-3.384110e-02,-6.666670e-01};
return rate_fit(T9,a); return rate_fit(T9,a);
} }
// o16(a,g)ne20 // o16(a,g)ne20
double o16a_rate(const vec7 &T9){ double o16a_rate(const vec7 &T9){
vec7 a1={2.390300e+01,0.000000e+00,-3.972620e+01,-2.107990e-01,4.428790e-01,-7.977530e-02,-6.666670e-01}; constexpr vec7 a1={2.390300e+01,0.000000e+00,-3.972620e+01,-2.107990e-01,4.428790e-01,-7.977530e-02,-6.666670e-01};
vec7 a2={3.885710e+00,-1.035850e+01,0.000000e+00,0.000000e+00,0.000000e+00,0.000000e+00,-1.500000e+00}; constexpr vec7 a2={3.885710e+00,-1.035850e+01,0.000000e+00,0.000000e+00,0.000000e+00,0.000000e+00,-1.500000e+00};
vec7 a3={9.508480e+00,-1.276430e+01,0.000000e+00,-3.659250e+00,7.142240e-01,-1.075080e-03,-1.500000e+00}; constexpr vec7 a3={9.508480e+00,-1.276430e+01,0.000000e+00,-3.659250e+00,7.142240e-01,-1.075080e-03,-1.500000e+00};
return rate_fit(T9,a1) + rate_fit(T9,a2) + rate_fit(T9,a3); return rate_fit(T9,a1) + rate_fit(T9,a2) + rate_fit(T9,a3);
} }
// ne20(a,g)mg24 // ne20(a,g)mg24
double ne20a_rate(const vec7 &T9){ double ne20a_rate(const vec7 &T9){
vec7 a1={2.450580e+01,0.000000e+00,-4.625250e+01,5.589010e+00,7.618430e+00,-3.683000e+00,-6.666670e-01}; constexpr vec7 a1={2.450580e+01,0.000000e+00,-4.625250e+01,5.589010e+00,7.618430e+00,-3.683000e+00,-6.666670e-01};
vec7 a2={-3.870550e+01,-2.506050e+00,0.000000e+00,0.000000e+00,0.000000e+00,0.000000e+00,-1.500000e+00}; constexpr vec7 a2={-3.870550e+01,-2.506050e+00,0.000000e+00,0.000000e+00,0.000000e+00,0.000000e+00,-1.500000e+00};
vec7 a3={1.983070e+00,-9.220260e+00,0.000000e+00,0.000000e+00,0.000000e+00,0.000000e+00,-1.500000e+00}; constexpr vec7 a3={1.983070e+00,-9.220260e+00,0.000000e+00,0.000000e+00,0.000000e+00,0.000000e+00,-1.500000e+00};
vec7 a4={-8.798270e+00,-1.278090e+01,0.000000e+00,1.692290e+01,-2.573250e+00,2.089970e-01,-1.500000e+00}; constexpr vec7 a4={-8.798270e+00,-1.278090e+01,0.000000e+00,1.692290e+01,-2.573250e+00,2.089970e-01,-1.500000e+00};
return rate_fit(T9,a1) + rate_fit(T9,a2) + rate_fit(T9,a3) + rate_fit(T9,a4); return rate_fit(T9,a1) + rate_fit(T9,a2) + rate_fit(T9,a3) + rate_fit(T9,a4);
} }
// c12(c12,a)ne20 // c12(c12,a)ne20
double c12c12_rate(const vec7 &T9){ double c12c12_rate(const vec7 &T9){
vec7 a={6.128630e+01,0.000000e+00,-8.416500e+01,-1.566270e+00,-7.360840e-02,-7.279700e-02,-6.666670e-01}; constexpr vec7 a={6.128630e+01,0.000000e+00,-8.416500e+01,-1.566270e+00,-7.360840e-02,-7.279700e-02,-6.666670e-01};
return rate_fit(T9,a); return rate_fit(T9,a);
} }
// c12(o16,a)mg24 // c12(o16,a)mg24
double c12o16_rate(const vec7 &T9){ double c12o16_rate(const vec7 &T9){
vec7 a={4.853410e+01,3.720400e-01,-1.334130e+02,5.015720e+01,-3.159870e+00,1.782510e-02,-2.370270e+01}; constexpr vec7 a={4.853410e+01,3.720400e-01,-1.334130e+02,5.015720e+01,-3.159870e+00,1.782510e-02,-2.370270e+01};
return rate_fit(T9,a); return rate_fit(T9,a);
} }
@@ -244,209 +244,211 @@ namespace serif::network::approx8{
// a Jacobian matrix for implicit solvers // a Jacobian matrix for implicit solvers
void Jacobian::operator() ( const vector_type &y, matrix_type &J, double /* t */, vector_type &dfdt ) { void Jacobian::operator() ( const vector_type &y, matrix_type &J, double /* t */, vector_type &dfdt ) const {
serif::constant::Constants& constants = serif::constant::Constants::getInstance(); serif::constant::Constants& constants = serif::constant::Constants::getInstance();
const double avo = constants.get("N_a").value; const double avo = constants.get("N_a").value;
const double clight = constants.get("c").value; const double clight = constants.get("c").value;
// EOS // EOS
vec7 T9=get_T9_array(y[Net::itemp]); const vec7 T9=get_T9_array(y[Approx8Net::iTemp]);
// evaluate rates once per call // evaluate rates once per call
double rpp=pp_rate(T9); const double rpp=pp_rate(T9);
double r33=he3he3_rate(T9); const double r33=he3he3_rate(T9);
double r34=he3he4_rate(T9); const double r34=he3he4_rate(T9);
double r3a=triple_alpha_rate(T9); const double r3a=triple_alpha_rate(T9);
double rc12p=c12p_rate(T9); const double rc12p=c12p_rate(T9);
double rc12a=c12a_rate(T9); const double rc12a=c12a_rate(T9);
double rn14p=n14p_rate(T9); const double rn14p=n14p_rate(T9);
double rn14a=n14a_rate(T9); const double rn14a=n14a_rate(T9);
double ro16p=o16p_rate(T9); const double ro16p=o16p_rate(T9);
double ro16a=o16a_rate(T9); const double ro16a=o16a_rate(T9);
double rne20a=ne20a_rate(T9); const double rne20a=ne20a_rate(T9);
double r1212=c12c12_rate(T9); const double r1212=c12c12_rate(T9);
double r1216=c12o16_rate(T9); const double r1216=c12o16_rate(T9);
double pfrac=n15pg_frac(T9); const double pFrac=n15pg_frac(T9);
double afrac=1-pfrac; const double aFrac=1-pFrac;
double yh1 = y[Net::ih1]; const double yh1 = y[Approx8Net::ih1];
double yhe3 = y[Net::ihe3]; const double yhe3 = y[Approx8Net::ihe3];
double yhe4 = y[Net::ihe4]; const double yhe4 = y[Approx8Net::ihe4];
double yc12 = y[Net::ic12]; const double yc12 = y[Approx8Net::ic12];
double yn14 = y[Net::in14]; const double yn14 = y[Approx8Net::in14];
double yo16 = y[Net::io16]; const double yo16 = y[Approx8Net::io16];
double yne20 = y[Net::ine20]; const double yne20 = y[Approx8Net::ine20];
// zero all elements to begin // zero all elements to begin
for (int i=0; i < Net::nvar; i++) { for (int i=0; i < Approx8Net::nVar; i++) {
for (int j=0; j < Net::nvar; j++) { for (int j=0; j < Approx8Net::nVar; j++) {
J(i,j)=0.0; J(i,j)=0.0;
} }
} }
// h1 jacobian elements // h1 jacobian elements
J(Net::ih1,Net::ih1) = -3*yh1*rpp - 2*yc12*rc12p -2*yn14*rn14p -2*yo16*ro16p; J(Approx8Net::ih1,Approx8Net::ih1) = -3*yh1*rpp - 2*yc12*rc12p -2*yn14*rn14p -2*yo16*ro16p;
J(Net::ih1,Net::ihe3) = 2*yhe3*r33 - yhe4*r34; J(Approx8Net::ih1,Approx8Net::ihe3) = 2*yhe3*r33 - yhe4*r34;
J(Net::ih1,Net::ihe4) = -yhe3*r34; J(Approx8Net::ih1,Approx8Net::ihe4) = -yhe3*r34;
J(Net::ih1,Net::ic12) = -2*yh1*rc12p; J(Approx8Net::ih1,Approx8Net::ic12) = -2*yh1*rc12p;
J(Net::ih1,Net::in14) = -2*yh1*rn14p; J(Approx8Net::ih1,Approx8Net::in14) = -2*yh1*rn14p;
J(Net::ih1,Net::io16) = -2*yh1*ro16p; J(Approx8Net::ih1,Approx8Net::io16) = -2*yh1*ro16p;
// he3 jacobian elements // he3 jacobian elements
J(Net::ihe3,Net::ih1) = yh1*rpp; J(Approx8Net::ihe3,Approx8Net::ih1) = yh1*rpp;
J(Net::ihe3,Net::ihe3) = -2*yhe3*r33 - yhe4*r34; J(Approx8Net::ihe3,Approx8Net::ihe3) = -2*yhe3*r33 - yhe4*r34;
J(Net::ihe3,Net::ihe4) = -yhe3*r34; J(Approx8Net::ihe3,Approx8Net::ihe4) = -yhe3*r34;
// he4 jacobian elements // he4 jacobian elements
J(Net::ihe4,Net::ih1) = yn14*afrac*rn14p + yo16*ro16p; J(Approx8Net::ihe4,Approx8Net::ih1) = yn14*aFrac*rn14p + yo16*ro16p;
J(Net::ihe4,Net::ihe3) = yhe3*r33 - yhe4*r34; J(Approx8Net::ihe4,Approx8Net::ihe3) = yhe3*r33 - yhe4*r34;
J(Net::ihe4,Net::ihe4) = yhe3*r34 - 1.5*yhe4*yhe4*r3a - yc12*rc12a - 1.5*yn14*rn14a - yo16*ro16a - yne20*rne20a; J(Approx8Net::ihe4,Approx8Net::ihe4) = yhe3*r34 - 1.5*yhe4*yhe4*r3a - yc12*rc12a - 1.5*yn14*rn14a - yo16*ro16a - yne20*rne20a;
J(Net::ihe4,Net::ic12) = -yhe4*rc12a + yc12*r1212 + yo16*r1216; J(Approx8Net::ihe4,Approx8Net::ic12) = -yhe4*rc12a + yc12*r1212 + yo16*r1216;
J(Net::ihe4,Net::in14) = yh1*afrac*rn14p - 1.5*yhe4*rn14a; J(Approx8Net::ihe4,Approx8Net::in14) = yh1*aFrac*rn14p - 1.5*yhe4*rn14a;
J(Net::ihe4,Net::io16) = yh1*ro16p - yhe4*ro16a + yc12*r1216; J(Approx8Net::ihe4,Approx8Net::io16) = yh1*ro16p - yhe4*ro16a + yc12*r1216;
J(Net::ihe4,Net::ine20) = -yhe4*rne20a; J(Approx8Net::ihe4,Approx8Net::ine20) = -yhe4*rne20a;
// c12 jacobian elements // c12 jacobian elements
J(Net::ic12,Net::ih1) = -yc12*rc12p + yn14*afrac*rn14p; J(Approx8Net::ic12,Approx8Net::ih1) = -yc12*rc12p + yn14*aFrac*rn14p;
J(Net::ic12,Net::ihe4) = 0.5*yhe4*yhe4*r3a - yhe4*rc12a; J(Approx8Net::ic12,Approx8Net::ihe4) = 0.5*yhe4*yhe4*r3a - yhe4*rc12a;
J(Net::ic12,Net::ic12) = -yh1*rc12p - yhe4*rc12a - yo16*r1216 - 2*yc12*r1212; J(Approx8Net::ic12,Approx8Net::ic12) = -yh1*rc12p - yhe4*rc12a - yo16*r1216 - 2*yc12*r1212;
J(Net::ic12,Net::in14) = yh1*yn14*afrac*rn14p; J(Approx8Net::ic12,Approx8Net::in14) = yh1*yn14*aFrac*rn14p;
J(Net::ic12,Net::io16) = -yc12*r1216; J(Approx8Net::ic12,Approx8Net::io16) = -yc12*r1216;
// n14 jacobian elements // n14 jacobian elements
J(Net::in14,Net::ih1) = yc12*rc12p - yn14*rn14p + yo16*ro16p; J(Approx8Net::in14,Approx8Net::ih1) = yc12*rc12p - yn14*rn14p + yo16*ro16p;
J(Net::in14,Net::ihe4) = -yn14*rn14a; J(Approx8Net::in14,Approx8Net::ihe4) = -yn14*rn14a;
J(Net::in14,Net::ic12) = yh1*rc12p; J(Approx8Net::in14,Approx8Net::ic12) = yh1*rc12p;
J(Net::in14,Net::in14) = -yh1*rn14p - yhe4*rn14a; J(Approx8Net::in14,Approx8Net::in14) = -yh1*rn14p - yhe4*rn14a;
J(Net::in14,Net::io16) = yo16*ro16p; J(Approx8Net::in14,Approx8Net::io16) = yo16*ro16p;
// o16 jacobian elements // o16 jacobian elements
J(Net::io16,Net::ih1) = yn14*pfrac*rn14p - yo16*ro16p; J(Approx8Net::io16,Approx8Net::ih1) = yn14*pFrac*rn14p - yo16*ro16p;
J(Net::io16,Net::ihe4) = yc12*rc12a - yo16*ro16a; J(Approx8Net::io16,Approx8Net::ihe4) = yc12*rc12a - yo16*ro16a;
J(Net::io16,Net::ic12) = yhe4*rc12a - yo16*r1216; J(Approx8Net::io16,Approx8Net::ic12) = yhe4*rc12a - yo16*r1216;
J(Net::io16,Net::in14) = yh1*pfrac*rn14p; J(Approx8Net::io16,Approx8Net::in14) = yh1*pFrac*rn14p;
J(Net::io16,Net::io16) = yh1*ro16p - yc12*r1216 -yhe4*ro16a; J(Approx8Net::io16,Approx8Net::io16) = yh1*ro16p - yc12*r1216 -yhe4*ro16a;
// ne20 jacobian elements // ne20 jacobian elements
J(Net::ine20,Net::ihe4) = yn14*rn14a + yo16*ro16a - yne20*rne20a; J(Approx8Net::ine20,Approx8Net::ihe4) = yn14*rn14a + yo16*ro16a - yne20*rne20a;
J(Net::ine20,Net::ic12) = yc12*r1212; J(Approx8Net::ine20,Approx8Net::ic12) = yc12*r1212;
J(Net::ine20,Net::in14) = yhe4*rn14a; J(Approx8Net::ine20,Approx8Net::in14) = yhe4*rn14a;
J(Net::ine20,Net::io16) = yo16*ro16a; J(Approx8Net::ine20,Approx8Net::io16) = yo16*ro16a;
J(Net::ine20,Net::ine20) = -yhe4*rne20a; J(Approx8Net::ine20,Approx8Net::ine20) = -yhe4*rne20a;
// mg24 jacobian elements // mg24 jacobian elements
J(Net::img24,Net::ihe4) = yne20*rne20a; J(Approx8Net::img24,Approx8Net::ihe4) = yne20*rne20a;
J(Net::img24,Net::ic12) = yo16*r1216; J(Approx8Net::img24,Approx8Net::ic12) = yo16*r1216;
J(Net::img24,Net::io16) = yc12*r1216; J(Approx8Net::img24,Approx8Net::io16) = yc12*r1216;
J(Net::img24,Net::ine20) = yhe4*rne20a; J(Approx8Net::img24,Approx8Net::ine20) = yhe4*rne20a;
// energy accountings // energy accounting
for (int j=0; j<Net::niso; j++) { for (int j=0; j<Approx8Net::nIso; j++) {
for (int i=0; i<Net::niso; i++) { for (int i=0; i<Approx8Net::nIso; i++) {
J(Net::iener,j) += J(i,j)*Net::mion[i]; J(Approx8Net::iEnergy,j) += J(i,j)*Approx8Net::mIon[i];
} }
J(Net::iener,j) *= -avo*clight*clight; J(Approx8Net::iEnergy,j) *= -avo*clight*clight;
} }
} }
void ODE::operator() ( const vector_type &y, vector_type &dydt, double /* t */) { void ODE::operator() ( const vector_type &y, vector_type &dydt, double /* t */) const {
serif::constant::Constants& constants = serif::constant::Constants::getInstance(); const serif::constant::Constants& constants = serif::constant::Constants::getInstance();
const double avo = constants.get("N_a").value; const double avo = constants.get("N_a").value;
const double clight = constants.get("c").value; const double clight = constants.get("c").value;
// EOS // EOS
double T=y[Net::itemp]; const double T = y[Approx8Net::iTemp];
double den=y[Net::iden]; const double den = y[Approx8Net::iDensity];
vec7 T9=get_T9_array(T); const vec7 T9=get_T9_array(T);
// rates // rates
double rpp=den*pp_rate(T9); const double rpp=den*pp_rate(T9);
double r33=den*he3he3_rate(T9); const double r33=den*he3he3_rate(T9);
double r34=den*he3he4_rate(T9); const double r34=den*he3he4_rate(T9);
double r3a=den*den*triple_alpha_rate(T9); const double r3a=den*den*triple_alpha_rate(T9);
double rc12p=den*c12p_rate(T9); const double rc12p=den*c12p_rate(T9);
double rc12a=den*c12a_rate(T9); const double rc12a=den*c12a_rate(T9);
double rn14p=den*n14p_rate(T9); const double rn14p=den*n14p_rate(T9);
double rn14a=n14a_rate(T9); const double rn14a=n14a_rate(T9);
double ro16p=den*o16p_rate(T9); const double ro16p=den*o16p_rate(T9);
double ro16a=den*o16a_rate(T9); const double ro16a=den*o16a_rate(T9);
double rne20a=den*ne20a_rate(T9); const double rne20a=den*ne20a_rate(T9);
double r1212=den*c12c12_rate(T9); const double r1212=den*c12c12_rate(T9);
double r1216=den*c12o16_rate(T9); const double r1216=den*c12o16_rate(T9);
double pfrac=n15pg_frac(T9); const double pFrac=n15pg_frac(T9);
double afrac=1-pfrac; const double aFrac=1-pFrac;
double yh1 = y[Net:: ih1]; const double yh1 = y[Approx8Net:: ih1];
double yhe3 = y[Net:: ihe3]; const double yhe3 = y[Approx8Net:: ihe3];
double yhe4 = y[Net:: ihe4]; const double yhe4 = y[Approx8Net:: ihe4];
double yc12 = y[Net:: ic12]; const double yc12 = y[Approx8Net:: ic12];
double yn14 = y[Net:: in14]; const double yn14 = y[Approx8Net:: in14];
double yo16 = y[Net:: io16]; const double yo16 = y[Approx8Net:: io16];
double yne20 = y[Net::ine20]; const double yne20 = y[Approx8Net::ine20];
dydt[Net::ih1] = -1.5*yh1*yh1*rpp;
dydt[Net::ih1] += yhe3*yhe3*r33;
dydt[Net::ih1] += -yhe3*yhe4*r34;
dydt[Net::ih1] += -2*yh1*yc12*rc12p;
dydt[Net::ih1] += -2*yh1*yn14*rn14p;
dydt[Net::ih1] += -2*yh1*yo16*ro16p;
dydt[Net::ihe3] = 0.5*yh1*yh1*rpp;
dydt[Net::ihe3] += -yhe3*yhe3*r33;
dydt[Net::ihe3] += -yhe3*yhe4*r34;
dydt[Net::ihe4] = 0.5*yhe3*yhe3*r33;
dydt[Net::ihe4] += yhe3*yhe4*r34;
dydt[Net::ihe4] += -yhe4*yc12*rc12a;
dydt[Net::ihe4] += yh1*yn14*afrac*rn14p;
dydt[Net::ihe4] += yh1*yo16*ro16p;
dydt[Net::ihe4] += -0.5*yhe4*yhe4*yhe4*r3a;
dydt[Net::ihe4] += -yhe4*yo16*ro16a;
dydt[Net::ihe4] += 0.5*yc12*yc12*r1212;
dydt[Net::ihe4] += yc12*yo16*r1216;
dydt[Net::ihe4] += -yhe4*yne20*rne20a;
dydt[Net::ic12] = (1./6.)*yhe4*yhe4*yhe4*r3a; dydt[Approx8Net::ih1] = -1.5*yh1*yh1*rpp;
dydt[Net::ic12] += -yhe4*yc12*rc12a; dydt[Approx8Net::ih1] += yhe3*yhe3*r33;
dydt[Net::ic12] += -yh1*yc12*rc12p; dydt[Approx8Net::ih1] += -yhe3*yhe4*r34;
dydt[Net::ic12] += yh1*yn14*afrac*rn14p; dydt[Approx8Net::ih1] += -2*yh1*yc12*rc12p;
dydt[Net::ic12] += -yc12*yc12*r1212; dydt[Approx8Net::ih1] += -2*yh1*yn14*rn14p;
dydt[Net::ic12] += -yc12*yo16*r1216; dydt[Approx8Net::ih1] += -2*yh1*yo16*ro16p;
dydt[Net::in14] = yh1*yc12*rc12p; dydt[Approx8Net::ihe3] = 0.5*yh1*yh1*rpp;
dydt[Net::in14] += -yh1*yn14*rn14p; dydt[Approx8Net::ihe3] += -yhe3*yhe3*r33;
dydt[Net::in14] += yh1*yo16*ro16p; dydt[Approx8Net::ihe3] += -yhe3*yhe4*r34;
dydt[Net::in14] += -yhe4*yn14*rn14a;
dydt[Net::io16] = yhe4*yc12*rc12a;
dydt[Net::io16] += yh1*yn14*pfrac*rn14p;
dydt[Net::io16] += -yh1*yo16*ro16p;
dydt[Net::io16] += -yc12*yo16*r1216;
dydt[Net::io16] += -yhe4*yo16*ro16a;
dydt[Net::ine20] = 0.5*yc12*yc12*r1212; dydt[Approx8Net::ihe4] = 0.5*yhe3*yhe3*r33;
dydt[Net::ine20] += yhe4*yn14*rn14a; dydt[Approx8Net::ihe4] += yhe3*yhe4*r34;
dydt[Net::ine20] += yhe4*yo16*ro16a; dydt[Approx8Net::ihe4] += -yhe4*yc12*rc12a;
dydt[Net::ine20] += -yhe4*yne20*rne20a; dydt[Approx8Net::ihe4] += yh1*yn14*aFrac*rn14p;
dydt[Approx8Net::ihe4] += yh1*yo16*ro16p;
dydt[Approx8Net::ihe4] += -0.5*yhe4*yhe4*yhe4*r3a;
dydt[Approx8Net::ihe4] += -yhe4*yo16*ro16a;
dydt[Approx8Net::ihe4] += 0.5*yc12*yc12*r1212;
dydt[Approx8Net::ihe4] += yc12*yo16*r1216;
dydt[Approx8Net::ihe4] += -yhe4*yne20*rne20a;
dydt[Net::img24] = yc12*yo16*r1216; dydt[Approx8Net::ic12] = (1./6.)*yhe4*yhe4*yhe4*r3a;
dydt[Net::img24] += yhe4*yne20*rne20a; dydt[Approx8Net::ic12] += -yhe4*yc12*rc12a;
dydt[Approx8Net::ic12] += -yh1*yc12*rc12p;
dydt[Approx8Net::ic12] += yh1*yn14*aFrac*rn14p;
dydt[Approx8Net::ic12] += -yc12*yc12*r1212;
dydt[Approx8Net::ic12] += -yc12*yo16*r1216;
dydt[Net::itemp] = 0.; dydt[Approx8Net::in14] = yh1*yc12*rc12p;
dydt[Net::iden] = 0.; dydt[Approx8Net::in14] += -yh1*yn14*rn14p;
dydt[Approx8Net::in14] += yh1*yo16*ro16p;
dydt[Approx8Net::in14] += -yhe4*yn14*rn14a;
dydt[Approx8Net::io16] = yhe4*yc12*rc12a;
dydt[Approx8Net::io16] += yh1*yn14*pFrac*rn14p;
dydt[Approx8Net::io16] += -yh1*yo16*ro16p;
dydt[Approx8Net::io16] += -yc12*yo16*r1216;
dydt[Approx8Net::io16] += -yhe4*yo16*ro16a;
dydt[Approx8Net::ine20] = 0.5*yc12*yc12*r1212;
dydt[Approx8Net::ine20] += yhe4*yn14*rn14a;
dydt[Approx8Net::ine20] += yhe4*yo16*ro16a;
dydt[Approx8Net::ine20] += -yhe4*yne20*rne20a;
dydt[Approx8Net::img24] = yc12*yo16*r1216;
dydt[Approx8Net::img24] += yhe4*yne20*rne20a;
dydt[Approx8Net::iTemp] = 0.;
dydt[Approx8Net::iDensity] = 0.;
// energy accounting // energy accounting
double enuc = 0.; double eNuc = 0.;
for (int i=0; i<Net::niso; i++) { for (int i=0; i<Approx8Net::nIso; i++) {
enuc += Net::mion[i]*dydt[i]; eNuc += Approx8Net::mIon[i]*dydt[i];
} }
dydt[Net::iener] = -enuc*avo*clight*clight; dydt[Approx8Net::iEnergy] = -eNuc*avo*clight*clight;
} }
Approx8Network::Approx8Network() : Network(APPROX8) {}
NetOut Approx8Network::evaluate(const NetIn &netIn) { NetOut Approx8Network::evaluate(const NetIn &netIn) {
m_y = convert_netIn(netIn); m_y = convert_netIn(netIn);
m_tmax = netIn.tmax; m_tMax = netIn.tMax;
m_dt0 = netIn.dt0; m_dt0 = netIn.dt0;
const double stiff_abs_tol = m_config.get<double>("Network:Approx8:Stiff:AbsTol", 1.0e-6); const double stiff_abs_tol = m_config.get<double>("Network:Approx8:Stiff:AbsTol", 1.0e-6);
@@ -463,7 +465,7 @@ namespace serif::network::approx8{
std::make_pair(ODE(), Jacobian()), std::make_pair(ODE(), Jacobian()),
m_y, m_y,
0.0, 0.0,
m_tmax, m_tMax,
m_dt0 m_dt0
); );
@@ -474,31 +476,33 @@ namespace serif::network::approx8{
ODE(), ODE(),
m_y, m_y,
0.0, 0.0,
m_tmax, m_tMax,
m_dt0 m_dt0
); );
} }
double ysum = 0.0; double ySum = 0.0;
for (int i = 0; i < Net::niso; i++) { for (int i = 0; i < Approx8Net::nIso; i++) {
m_y[i] *= Net::aion[i]; m_y[i] *= Approx8Net::aIon[i];
ysum += m_y[i]; ySum += m_y[i];
} }
for (int i = 0; i < Net::niso; i++) { for (int i = 0; i < Approx8Net::nIso; i++) {
m_y[i] /= ysum; m_y[i] /= ySum;
} }
NetOut netOut; NetOut netOut;
std::vector<double> outComposition; std::vector<double> outComposition;
outComposition.reserve(Net::nvar); outComposition.reserve(Approx8Net::nVar);
for (int i = 0; i < Net::niso; i++) { for (int i = 0; i < Approx8Net::nIso; i++) {
outComposition.push_back(m_y[i]); outComposition.push_back(m_y[i]);
} }
netOut.energy = m_y[Net::iener]; netOut.energy = m_y[Approx8Net::iEnergy];
netOut.composition = outComposition;
netOut.num_steps = num_steps; netOut.num_steps = num_steps;
const std::vector<std::string> symbols = {"H-1", "He-3", "He-4", "C-12", "N-14", "O-16", "Ne-20", "Mg-24"};
netOut.composition = serif::composition::Composition(symbols, outComposition);
return netOut; return netOut;
} }
@@ -507,31 +511,26 @@ namespace serif::network::approx8{
} }
vector_type Approx8Network::convert_netIn(const NetIn &netIn) { vector_type Approx8Network::convert_netIn(const NetIn &netIn) {
if (netIn.composition.size() != Net::niso) { vector_type y(Approx8Net::nVar, 0.0);
LOG_ERROR(m_logger, "Error: composition size mismatch in convert_netIn"); y[Approx8Net::ih1] = netIn.composition.getMassFraction("H-1");
throw std::runtime_error("Error: composition size mismatch in convert_netIn"); y[Approx8Net::ihe3] = netIn.composition.getMassFraction("He-3");
} y[Approx8Net::ihe4] = netIn.composition.getMassFraction("He-4");
y[Approx8Net::ic12] = netIn.composition.getMassFraction("C-12");
y[Approx8Net::in14] = netIn.composition.getMassFraction("N-14");
y[Approx8Net::io16] = netIn.composition.getMassFraction("O-16");
y[Approx8Net::ine20] = netIn.composition.getMassFraction("Ne-20");
y[Approx8Net::img24] = netIn.composition.getMassFraction("Mg-24");
y[Approx8Net::iTemp] = netIn.temperature;
y[Approx8Net::iDensity] = netIn.density;
y[Approx8Net::iEnergy] = netIn.energy;
vector_type y(Net::nvar, 0.0); double ySum = 0.0;
y[Net::ih1] = netIn.composition[0]; for (int i = 0; i < Approx8Net::nIso; i++) {
y[Net::ihe3] = netIn.composition[1]; y[i] /= Approx8Net::aIon[i];
y[Net::ihe4] = netIn.composition[2]; ySum += y[i];
y[Net::ic12] = netIn.composition[3];
y[Net::in14] = netIn.composition[4];
y[Net::io16] = netIn.composition[5];
y[Net::ine20] = netIn.composition[6];
y[Net::img24] = netIn.composition[7];
y[Net::itemp] = netIn.temperature;
y[Net::iden] = netIn.density;
y[Net::iener] = netIn.energy;
double ysum = 0.0;
for (int i = 0; i < Net::niso; i++) {
y[i] /= Net::aion[i];
ysum += y[i];
} }
for (int i = 0; i < Net::niso; i++) { for (int i = 0; i < Approx8Net::nIso; i++) {
y[i] /= ysum; y[i] /= ySum;
} }
return y; return y;

View File

@@ -19,18 +19,50 @@
// //
// *********************************************************************** */ // *********************************************************************** */
#include "network.h" #include "network.h"
#include "approx8.h"
#include "probe.h" #include "probe.h"
#include "quill/LogMacros.h" #include "quill/LogMacros.h"
namespace serif::network { namespace serif::network {
Network::Network() : Network::Network(const NetworkFormat format) :
m_config(serif::config::Config::getInstance()), m_config(serif::config::Config::getInstance()),
m_logManager(serif::probe::LogManager::getInstance()), m_logManager(serif::probe::LogManager::getInstance()),
m_logger(m_logManager.getLogger("log")) { m_logger(m_logManager.getLogger("log")),
m_format(format) {
if (format == NetworkFormat::UNKNOWN) {
LOG_ERROR(m_logger, "nuclearNetwork::Network::Network() called with UNKNOWN format");
throw std::runtime_error("nuclearNetwork::Network::Network() called with UNKNOWN format");
}
} }
NetworkFormat Network::getFormat() const {
return m_format;
}
NetworkFormat Network::setFormat(const NetworkFormat format) {
const NetworkFormat oldFormat = m_format;
m_format = format;
return oldFormat;
}
NetOut Network::evaluate(const NetIn &netIn) { NetOut Network::evaluate(const NetIn &netIn) {
// You can throw an exception here or log a warning if it should never be used. NetOut netOut;
LOG_ERROR(m_logger, "nuclearNetwork::Network::evaluate() is not implemented"); switch (m_format) {
throw std::runtime_error("nuclearNetwork::Network::evaluate() is not implemented"); case APPROX8: {
approx8::Approx8Network network;
netOut = network.evaluate(netIn);
break;
}
case UNKNOWN: {
LOG_ERROR(m_logger, "Network format {} is not implemented.", FormatStringLookup.at(m_format));
throw std::runtime_error("Network format not implemented.");
}
default: {
LOG_ERROR(m_logger, "Unknown network format.");
throw std::runtime_error("Unknown network format.");
}
}
return netOut;
} }
} }

View File

@@ -31,54 +31,55 @@
* @brief Header file for the Approx8 nuclear reaction network. * @brief Header file for the Approx8 nuclear reaction network.
* *
* This file contains the definitions and declarations for the Approx8 nuclear reaction network. * This file contains the definitions and declarations for the Approx8 nuclear reaction network.
* The network is based on Frank Timmes' "aprox8" and includes 8 isotopes and various nuclear reactions. * The network is based on Frank Timmes' "approx8" and includes 8 isotopes and various nuclear reactions.
* The rates are evaluated using a fitting function with coefficients from reaclib.jinaweb.org. * The rates are evaluated using a fitting function with coefficients from reaclib.jinaweb.org.
*/ */
/**
* @typedef vector_type
* @brief Alias for a vector of doubles using Boost uBLAS.
*/
typedef boost::numeric::ublas::vector< double > vector_type;
/**
* @typedef matrix_type
* @brief Alias for a matrix of doubles using Boost uBLAS.
*/
typedef boost::numeric::ublas::matrix< double > matrix_type;
/**
* @typedef vec7
* @brief Alias for a std::array of 7 doubles.
*/
typedef std::array<double,7> vec7;
namespace serif::network::approx8{ namespace serif::network::approx8{
/**
* @typedef vector_type
* @brief Alias for a vector of doubles using Boost uBLAS.
*/
typedef boost::numeric::ublas::vector< double > vector_type;
/**
* @typedef matrix_type
* @brief Alias for a matrix of doubles using Boost uBLAS.
*/
typedef boost::numeric::ublas::matrix< double > matrix_type;
/**
* @typedef vec7
* @brief Alias for a std::array of 7 doubles.
*/
typedef std::array<double,7> vec7;
using namespace boost::numeric::odeint; using namespace boost::numeric::odeint;
/** /**
* @struct Net * @struct Approx8Net
* @brief Contains constants and arrays related to the nuclear network. * @brief Contains constants and arrays related to the nuclear network.
*/ */
struct Net{ struct Approx8Net{
const static int ih1=0; static constexpr int ih1=0;
const static int ihe3=1; static constexpr int ihe3=1;
const static int ihe4=2; static constexpr int ihe4=2;
const static int ic12=3; static constexpr int ic12=3;
const static int in14=4; static constexpr int in14=4;
const static int io16=5; static constexpr int io16=5;
const static int ine20=6; static constexpr int ine20=6;
const static int img24=7; static constexpr int img24=7;
const static int itemp=img24+1; static constexpr int iTemp=img24+1;
const static int iden =itemp+1; static constexpr int iDensity =iTemp+1;
const static int iener=iden+1; static constexpr int iEnergy=iDensity+1;
const static int niso=img24+1; // number of isotopes static constexpr int nIso=img24+1; // number of isotopes
const static int nvar=iener+1; // number of variables static constexpr int nVar=iEnergy+1; // number of variables
static constexpr std::array<int,niso> aion = { static constexpr std::array<int,nIso> aIon = {
1, 1,
3, 3,
4, 4,
@@ -89,7 +90,7 @@ namespace serif::network::approx8{
24 24
}; };
static constexpr std::array<double,niso> mion = { static constexpr std::array<double,nIso> mIon = {
1.67262164e-24, 1.67262164e-24,
5.00641157e-24, 5.00641157e-24,
6.64465545e-24, 6.64465545e-24,
@@ -270,10 +271,9 @@ namespace serif::network::approx8{
* @brief Calculates the Jacobian matrix. * @brief Calculates the Jacobian matrix.
* @param y State vector. * @param y State vector.
* @param J Jacobian matrix. * @param J Jacobian matrix.
* @param t Time.
* @param dfdt Derivative of the state vector. * @param dfdt Derivative of the state vector.
*/ */
void operator() ( const vector_type &y, matrix_type &J, double /* t */, vector_type &dfdt ); void operator() ( const vector_type &y, matrix_type &J, double /* t */, vector_type &dfdt ) const;
}; };
/** /**
@@ -285,23 +285,24 @@ namespace serif::network::approx8{
* @brief Calculates the derivatives of the state vector. * @brief Calculates the derivatives of the state vector.
* @param y State vector. * @param y State vector.
* @param dydt Derivative of the state vector. * @param dydt Derivative of the state vector.
* @param t Time.
*/ */
void operator() ( const vector_type &y, vector_type &dydt, double /* t */); void operator() ( const vector_type &y, vector_type &dydt, double /* t */) const;
}; };
/** /**
* @class Approx8Network * @class Approx8Network
* @brief Class for the Approx8 nuclear reaction network. * @brief Class for the Approx8 nuclear reaction network.
*/ */
class Approx8Network : public Network { class Approx8Network final : public Network {
public: public:
Approx8Network();
/** /**
* @brief Evaluates the nuclear network. * @brief Evaluates the nuclear network.
* @param netIn Input parameters for the network. * @param netIn Input parameters for the network.
* @return Output results from the network. * @return Output results from the network.
*/ */
virtual NetOut evaluate(const NetIn &netIn); NetOut evaluate(const NetIn &netIn) override;
/** /**
* @brief Sets whether the solver should use a stiff method. * @brief Sets whether the solver should use a stiff method.
@@ -313,11 +314,11 @@ namespace serif::network::approx8{
* @brief Checks if the solver is using a stiff method. * @brief Checks if the solver is using a stiff method.
* @return Boolean indicating if a stiff method is being used. * @return Boolean indicating if a stiff method is being used.
*/ */
bool isStiff() { return m_stiff; } bool isStiff() const { return m_stiff; }
private: private:
vector_type m_y; vector_type m_y;
double m_tmax; double m_tMax = 0;
double m_dt0; double m_dt0 = 0;
bool m_stiff = false; bool m_stiff = false;
/** /**
@@ -325,7 +326,8 @@ namespace serif::network::approx8{
* @param netIn Input parameters for the network. * @param netIn Input parameters for the network.
* @return Internal state vector. * @return Internal state vector.
*/ */
vector_type convert_netIn(const NetIn &netIn); static vector_type convert_netIn(const NetIn &netIn);
}; };
} // namespace nnApprox8 } // namespace nnApprox8

View File

@@ -25,15 +25,27 @@
#include "probe.h" #include "probe.h"
#include "config.h" #include "config.h"
#include "quill/Logger.h" #include "quill/Logger.h"
#include "composition.h"
#include <unordered_map>
namespace serif::network { namespace serif::network {
enum NetworkFormat {
APPROX8, ///< Approx8 nuclear reaction network format.
UNKNOWN,
};
static inline std::unordered_map<NetworkFormat, std::string> FormatStringLookup = {
{APPROX8, "Approx8"},
{UNKNOWN, "Unknown"}
};
/** /**
* @struct NetIn * @struct NetIn
* @brief Input structure for the network evaluation. * @brief Input structure for the network evaluation.
* *
* This structure holds the input parameters required for the network evaluation. * This structure holds the input parameters required for the network evaluation.
* *
* Example usage: * Example usage:
* @code * @code
* nuclearNetwork::NetIn netIn; * nuclearNetwork::NetIn netIn;
@@ -46,8 +58,8 @@ namespace serif::network {
* @endcode * @endcode
*/ */
struct NetIn { struct NetIn {
std::vector<double> composition; ///< Composition of the network serif::composition::Composition composition; ///< Composition of the network
double tmax; ///< Maximum time double tMax; ///< Maximum time
double dt0; ///< Initial time step double dt0; ///< Initial time step
double temperature; ///< Temperature in Kelvin double temperature; ///< Temperature in Kelvin
double density; ///< Density in g/cm^3 double density; ///< Density in g/cm^3
@@ -69,7 +81,7 @@ namespace serif::network {
* @endcode * @endcode
*/ */
struct NetOut { struct NetOut {
std::vector<double> composition; ///< Composition of the network after evaluation serif::composition::Composition composition; ///< Composition of the network after evaluation
int num_steps; ///< Number of steps taken in the evaluation int num_steps; ///< Number of steps taken in the evaluation
double energy; ///< Energy in ergs after evaluation double energy; ///< Energy in ergs after evaluation
}; };
@@ -90,9 +102,12 @@ namespace serif::network {
*/ */
class Network { class Network {
public: public:
Network(); explicit Network(const NetworkFormat format = NetworkFormat::APPROX8);
virtual ~Network() = default; virtual ~Network() = default;
NetworkFormat getFormat() const;
NetworkFormat setFormat(const NetworkFormat format);
/** /**
* @brief Evaluate the network based on the input parameters. * @brief Evaluate the network based on the input parameters.
* *
@@ -105,6 +120,10 @@ namespace serif::network {
serif::config::Config& m_config; ///< Configuration instance serif::config::Config& m_config; ///< Configuration instance
serif::probe::LogManager& m_logManager; ///< Log manager instance serif::probe::LogManager& m_logManager; ///< Log manager instance
quill::Logger* m_logger; ///< Logger instance quill::Logger* m_logger; ///< Logger instance
NetworkFormat m_format; ///< Format of the network
}; };
} // namespace nuclearNetwork } // namespace nuclearNetwork

View File

@@ -34,7 +34,7 @@ void register_eos_bindings(pybind11::module &eos_submodule) {
}, py::return_value_policy::reference_internal, // IMPORTANT: Keep this policy! }, py::return_value_policy::reference_internal, // IMPORTANT: Keep this policy!
"Get the EOS table data.") "Get the EOS table data.")
.def("__repr__", [](const serif::eos::EOSio &eos) { .def("__repr__", [](const serif::eos::EOSio &eos) {
return "<EOSio(filename='" + eos.getFilename() + "', format='" + eos.getFormat() + "')>"; return "<EOSio(filename='" + eos.getFilename() + "', format='" + eos.getFormatName() + "')>";
}); });
py::class_<serif::eos::EOSTable>(eos_submodule, "EOSTable"); py::class_<serif::eos::EOSTable>(eos_submodule, "EOSTable");
@@ -88,64 +88,64 @@ void register_eos_bindings(pybind11::module &eos_submodule) {
); );
}, py::return_value_policy::reference_internal); // Keep parent 'table' alive }, py::return_value_policy::reference_internal); // Keep parent 'table' alive
py::class_<serif::eos::helmholtz::EOS>(eos_submodule, "EOS") py::class_<serif::eos::helmholtz::HELMEOSOutput>(eos_submodule, "EOS")
.def(py::init<>()) .def(py::init<>())
.def_readonly("ye", &serif::eos::helmholtz::EOS::ye) .def_readonly("ye", &serif::eos::helmholtz::HELMEOSOutput::ye)
.def_readonly("etaele", &serif::eos::helmholtz::EOS::etaele) .def_readonly("etaele", &serif::eos::helmholtz::HELMEOSOutput::etaele)
.def_readonly("xnefer", &serif::eos::helmholtz::EOS::xnefer) .def_readonly("xnefer", &serif::eos::helmholtz::HELMEOSOutput::xnefer)
.def_readonly("ptot", &serif::eos::helmholtz::EOS::ptot) .def_readonly("ptot", &serif::eos::helmholtz::HELMEOSOutput::ptot)
.def_readonly("pgas", &serif::eos::helmholtz::EOS::pgas) .def_readonly("pgas", &serif::eos::helmholtz::HELMEOSOutput::pgas)
.def_readonly("prad", &serif::eos::helmholtz::EOS::prad) .def_readonly("prad", &serif::eos::helmholtz::HELMEOSOutput::prad)
.def_readonly("etot", &serif::eos::helmholtz::EOS::etot) .def_readonly("etot", &serif::eos::helmholtz::HELMEOSOutput::etot)
.def_readonly("egas", &serif::eos::helmholtz::EOS::egas) .def_readonly("egas", &serif::eos::helmholtz::HELMEOSOutput::egas)
.def_readonly("erad", &serif::eos::helmholtz::EOS::erad) .def_readonly("erad", &serif::eos::helmholtz::HELMEOSOutput::erad)
.def_readonly("stot", &serif::eos::helmholtz::EOS::stot) .def_readonly("stot", &serif::eos::helmholtz::HELMEOSOutput::stot)
.def_readonly("sgas", &serif::eos::helmholtz::EOS::sgas) .def_readonly("sgas", &serif::eos::helmholtz::HELMEOSOutput::sgas)
.def_readonly("srad", &serif::eos::helmholtz::EOS::srad) .def_readonly("srad", &serif::eos::helmholtz::HELMEOSOutput::srad)
.def_readonly("dpresdd", &serif::eos::helmholtz::EOS::dpresdd) .def_readonly("dpresdd", &serif::eos::helmholtz::HELMEOSOutput::dpresdd)
.def_readonly("dpresdt", &serif::eos::helmholtz::EOS::dpresdt) .def_readonly("dpresdt", &serif::eos::helmholtz::HELMEOSOutput::dpresdt)
.def_readonly("dpresda", &serif::eos::helmholtz::EOS::dpresda) .def_readonly("dpresda", &serif::eos::helmholtz::HELMEOSOutput::dpresda)
.def_readonly("dpresdz", &serif::eos::helmholtz::EOS::dpresdz) .def_readonly("dpresdz", &serif::eos::helmholtz::HELMEOSOutput::dpresdz)
// TODO: Finish adding all the derivatives to the bound class
.def_readonly("dentrdd", &serif::eos::helmholtz::EOS::dentrdd)
.def_readonly("dentrdt", &serif::eos::helmholtz::EOS::dentrdt)
.def_readonly("dentrda", &serif::eos::helmholtz::EOS::dentrda)
.def_readonly("dentrdz", &serif::eos::helmholtz::EOS::dentrdz)
.def_readonly("denerdd", &serif::eos::helmholtz::EOS::denerdd) .def_readonly("dentrdd", &serif::eos::helmholtz::HELMEOSOutput::dentrdd)
.def_readonly("denerdt", &serif::eos::helmholtz::EOS::denerdt) .def_readonly("dentrdt", &serif::eos::helmholtz::HELMEOSOutput::dentrdt)
.def_readonly("denerda", &serif::eos::helmholtz::EOS::denerda) .def_readonly("dentrda", &serif::eos::helmholtz::HELMEOSOutput::dentrda)
.def_readonly("denerdz", &serif::eos::helmholtz::EOS::denerdz) .def_readonly("dentrdz", &serif::eos::helmholtz::HELMEOSOutput::dentrdz)
.def_readonly("chiT", &serif::eos::helmholtz::EOS::chiT) .def_readonly("denerdd", &serif::eos::helmholtz::HELMEOSOutput::denerdd)
.def_readonly("chiRho", &serif::eos::helmholtz::EOS::chiRho) .def_readonly("denerdt", &serif::eos::helmholtz::HELMEOSOutput::denerdt)
.def_readonly("csound", &serif::eos::helmholtz::EOS::csound) .def_readonly("denerda", &serif::eos::helmholtz::HELMEOSOutput::denerda)
.def_readonly("grad_ad", &serif::eos::helmholtz::EOS::grad_ad) .def_readonly("denerdz", &serif::eos::helmholtz::HELMEOSOutput::denerdz)
.def_readonly("gamma1", &serif::eos::helmholtz::EOS::gamma1)
.def_readonly("gamma2", &serif::eos::helmholtz::EOS::gamma2)
.def_readonly("gamma3", &serif::eos::helmholtz::EOS::gamma3)
.def_readonly("cV", &serif::eos::helmholtz::EOS::cV)
.def_readonly("cP", &serif::eos::helmholtz::EOS::cP)
.def_readonly("dse", &serif::eos::helmholtz::EOS::dse)
.def_readonly("dpe", &serif::eos::helmholtz::EOS::dpe)
.def_readonly("dsp", &serif::eos::helmholtz::EOS::dsp)
.def("__repr__", [](const serif::eos::helmholtz::EOS &eos) { .def_readonly("chiT", &serif::eos::helmholtz::HELMEOSOutput::chiT)
.def_readonly("chiRho", &serif::eos::helmholtz::HELMEOSOutput::chiRho)
.def_readonly("csound", &serif::eos::helmholtz::HELMEOSOutput::csound)
.def_readonly("grad_ad", &serif::eos::helmholtz::HELMEOSOutput::grad_ad)
.def_readonly("gamma1", &serif::eos::helmholtz::HELMEOSOutput::gamma1)
.def_readonly("gamma2", &serif::eos::helmholtz::HELMEOSOutput::gamma2)
.def_readonly("gamma3", &serif::eos::helmholtz::HELMEOSOutput::gamma3)
.def_readonly("cV", &serif::eos::helmholtz::HELMEOSOutput::cV)
.def_readonly("cP", &serif::eos::helmholtz::HELMEOSOutput::cP)
.def_readonly("dse", &serif::eos::helmholtz::HELMEOSOutput::dse)
.def_readonly("dpe", &serif::eos::helmholtz::HELMEOSOutput::dpe)
.def_readonly("dsp", &serif::eos::helmholtz::HELMEOSOutput::dsp)
.def("__repr__", [](const serif::eos::helmholtz::HELMEOSOutput &eos) {
return "<EOS (output from helmholtz eos)>"; return "<EOS (output from helmholtz eos)>";
}); });
py::class_<serif::eos::helmholtz::EOSInput>(eos_submodule, "EOSInput") py::class_<serif::eos::helmholtz::HELMEOSInput>(eos_submodule, "HELMEOSInput")
.def(py::init<>()) .def(py::init<>())
.def_readwrite("T", &serif::eos::helmholtz::EOSInput::T) .def_readwrite("T", &serif::eos::helmholtz::HELMEOSInput::T)
.def_readwrite("rho", &serif::eos::helmholtz::EOSInput::rho) .def_readwrite("rho", &serif::eos::helmholtz::HELMEOSInput::rho)
.def_readwrite("abar", &serif::eos::helmholtz::EOSInput::abar) .def_readwrite("abar", &serif::eos::helmholtz::HELMEOSInput::abar)
.def_readwrite("zbar", &serif::eos::helmholtz::EOSInput::zbar) .def_readwrite("zbar", &serif::eos::helmholtz::HELMEOSInput::zbar)
.def("__repr__", [](const serif::eos::helmholtz::EOSInput &input) { .def("__repr__", [](const serif::eos::helmholtz::HELMEOSInput &input) {
return "<EOSInput(T=" + std::to_string(input.T) + return "<HELMEOSInput(T=" + std::to_string(input.T) +
", rho=" + std::to_string(input.rho) + ", rho=" + std::to_string(input.rho) +
", abar=" + std::to_string(input.abar) + ", abar=" + std::to_string(input.abar) +
", zbar=" + std::to_string(input.zbar) + ")>"; ", zbar=" + std::to_string(input.zbar) + ")>";

View File

@@ -1,5 +1,4 @@
#include <gtest/gtest.h> #include <gtest/gtest.h>
#include <iostream>
#include <memory> #include <memory>
#include <string> #include <string>
#include <sstream> #include <sstream>
@@ -7,9 +6,11 @@
#include "helm.h" #include "helm.h"
#include "resourceManager.h" #include "resourceManager.h"
#include "config.h" #include "config.h"
#include "composition.h"
#include "EOS.h"
/** /**
* @file constTest.cpp * @file eosTest.cpp
* @brief Unit tests for the const class. * @brief Unit tests for the const class.
*/ */
@@ -26,44 +27,43 @@ std::string TEST_CONFIG = std::string(getenv("MESON_SOURCE_ROOT")) + "/tests/tes
TEST_F(eosTest, read_helm_table) { TEST_F(eosTest, read_helm_table) {
serif::config::Config::getInstance().loadConfig(TEST_CONFIG); serif::config::Config::getInstance().loadConfig(TEST_CONFIG);
serif::resource::ResourceManager& rm = serif::resource::ResourceManager::getInstance(); const serif::resource::ResourceManager& rm = serif::resource::ResourceManager::getInstance();
auto& eos = std::get<std::unique_ptr<serif::eos::EOSio>>(rm.getResource("eos:helm")); auto& eos = std::get<std::unique_ptr<serif::eos::EOSio>>(rm.getResource("eos:helm"));
auto& table = eos->getTable(); const auto& table = eos->getTable();
auto& helmTable = *std::get<std::unique_ptr<serif::eos::helmholtz::HELMTable>>(table); const auto& helmTable = *std::get<std::unique_ptr<serif::eos::helmholtz::HELMTable>>(table);
std::stringstream ss; std::stringstream ss;
ss << helmTable; ss << helmTable;
EXPECT_EQ(ss.str(), "HELMTable Data:\n imax: 541, jmax: 201\n Temperature Range: [1000, 1e+13]\n Density Range: [1e-12, 1e+15]\n"); EXPECT_EQ(ss.str(), "HELMTable Data:\n imax: 541, jmax: 201\n Temperature Range: [1000, 1e+13]\n Density Range: [1e-12, 1e+15]\n");
} }
TEST_F(eosTest, get_helm_EOS) { TEST_F(eosTest, get_helm_EOS) {
constexpr int nel=3;
double xMass[nel], aIon[nel], zIon[nel];
serif::eos::helmholtz::HELMEOSInput eos1;
const int nel=3; xMass[0] = 0.75; aIon[0] = 1.0; zIon[0] = 1.0;
double xmass[nel], aion[nel], zion[nel]; xMass[1] = 0.23; aIon[1] = 4.0; zIon[1] = 2.0;
serif::eos::helmholtz::EOSInput eos1; xMass[2] = 0.02; aIon[2] = 12.0; zIon[2] = 6.0;
xmass[0] = 0.75; aion[0] = 1.0; zion[0] = 1.0;
xmass[1] = 0.23; aion[1] = 4.0; zion[1] = 2.0;
xmass[2] = 0.02; aion[2] = 12.0; zion[2] = 6.0;
eos1.T = 1.0e8; eos1.T = 1.0e8;
eos1.rho = 1.0e6; eos1.rho = 1.0e6;
double asum = 0.0; double aSum = 0.0;
double zsum = 0.0; double zSum = 0.0;
for (int i=0; i<nel; i++) { for (int i=0; i<nel; i++) {
asum += xmass[i]/aion[i]; aSum += xMass[i]/aIon[i];
zsum += xmass[i]*zion[i]/aion[i]; zSum += xMass[i]*zIon[i]/aIon[i];
} }
eos1.abar = 1.0/asum; eos1.abar = 1.0/aSum;
eos1.zbar = eos1.abar*zsum; eos1.zbar = eos1.abar*zSum;
serif::resource::ResourceManager& rm = serif::resource::ResourceManager::getInstance(); serif::resource::ResourceManager& rm = serif::resource::ResourceManager::getInstance();
auto& eos = std::get<std::unique_ptr<serif::eos::EOSio>>(rm.getResource("eos:helm")); auto& eos = std::get<std::unique_ptr<serif::eos::EOSio>>(rm.getResource("eos:helm"));
auto& table = eos->getTable(); auto& table = eos->getTable();
auto& helmTable = *std::get<std::unique_ptr<serif::eos::helmholtz::HELMTable>>(table); auto& helmTable = *std::get<std::unique_ptr<serif::eos::helmholtz::HELMTable>>(table);
serif::eos::helmholtz::EOS helmEos = get_helm_EOS(eos1, helmTable); serif::eos::helmholtz::HELMEOSOutput helmEos = get_helm_EOS(eos1, helmTable);
const double absErr = 1e-12; constexpr double absErr = 1e-12;
//Check composition info //Check composition info
EXPECT_NEAR( helmEos.ye, 8.75e-01, absErr); EXPECT_NEAR( helmEos.ye, 8.75e-01, absErr);
@@ -85,3 +85,44 @@ TEST_F(eosTest, get_helm_EOS) {
EXPECT_NEAR( helmEos.dpe, 0, absErr); EXPECT_NEAR( helmEos.dpe, 0, absErr);
EXPECT_NEAR( helmEos.dsp, 0, absErr); EXPECT_NEAR( helmEos.dsp, 0, absErr);
} }
TEST_F(eosTest, eos_using_composition) {
serif::composition::Composition composition;
composition.registerSymbol({
"H-1",
"He-4",
"C-12",
"O-16",
"Ne-20",
"Fe-56",
"N-14",
"Si-28",
"Mg-24"
}, true);
composition.setMassFraction("H-1", 0.75);
composition.setMassFraction("He-4", 0.23);
composition.setMassFraction("C-12", 0.0044);
composition.setMassFraction("O-16", 0.0096);
composition.setMassFraction("Ne-20", 0.002);
composition.setMassFraction("Fe-56", 0.0018);
composition.setMassFraction("N-14", 0.001);
composition.setMassFraction("Si-28", 0.0008);
composition.setMassFraction("Mg-24", 0.0004);
composition.finalize();
serif::resource::ResourceManager& rm = serif::resource::ResourceManager::getInstance();
auto& EOSio = std::get<std::unique_ptr<serif::eos::EOSio>>(rm.getResource("eos:helm"));
serif::eos::EOS EOS(*EOSio);
serif::eos::EOSInput eosInput;
eosInput.temperature = 1.0e8; // Temperature in K
eosInput.density = 1.0e6; // Density in g/cm^3
eosInput.composition = composition; // Set the composition
serif::eos::EOSOutput eosOutput;
EXPECT_NO_THROW(eosOutput = EOS.get(eosInput));
eosOutput = EOS.get(eosInput);
constexpr double absErr = 1e-8;
EXPECT_NEAR(eosOutput.pressure.total, 6.9548533046915791E+22, absErr);
}

View File

@@ -3,6 +3,16 @@ test_sources = [
'eosTest.cpp', 'eosTest.cpp',
] ]
dependencies = [
gtest_dep,
eos_dep,
gtest_main,
resourceManager_dep,
config_dep,
composition_dep,
]
foreach test_file : test_sources foreach test_file : test_sources
exe_name = test_file.split('.')[0] exe_name = test_file.split('.')[0]
message('Building test: ' + exe_name) message('Building test: ' + exe_name)
@@ -11,7 +21,7 @@ foreach test_file : test_sources
test_exe = executable( test_exe = executable(
exe_name, exe_name,
test_file, test_file,
dependencies: [gtest_dep, eos_dep, gtest_main, resourceManager_dep, config_dep], dependencies: dependencies,
install_rpath: '@loader_path/../../src' # Ensure runtime library path resolves correctly install_rpath: '@loader_path/../../src' # Ensure runtime library path resolves correctly
) )

View File

@@ -4,6 +4,7 @@
#include "approx8.h" #include "approx8.h"
#include "config.h" #include "config.h"
#include "network.h" #include "network.h"
#include "composition.h"
#include <vector> #include <vector>
@@ -32,19 +33,31 @@ TEST_F(approx8Test, evaluate) {
serif::network::NetIn netIn; serif::network::NetIn netIn;
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<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"};
netIn.composition = comp; serif::composition::Composition composition;
composition.registerSymbol(symbols, true);
composition.setMassFraction(symbols, comp);
bool isFinalized = composition.finalize(true);
EXPECT_TRUE(isFinalized);
netIn.composition = composition;
netIn.temperature = 1e7; netIn.temperature = 1e7;
netIn.density = 1e2; netIn.density = 1e2;
netIn.energy = 0.0; netIn.energy = 0.0;
netIn.tmax = 3.15e17; netIn.tMax = 3.15e17;
netIn.dt0 = 1e12; netIn.dt0 = 1e12;
serif::network::NetOut netOut; serif::network::NetOut netOut;
EXPECT_NO_THROW(netOut = network.evaluate(netIn)); EXPECT_NO_THROW(netOut = network.evaluate(netIn));
EXPECT_DOUBLE_EQ(netOut.composition[serif::network::approx8::Net::ih1], 0.50166260916650918); double energyFraction = netOut.energy / 1.6433051127589775E+18;
EXPECT_DOUBLE_EQ(netOut.composition[serif::network::approx8::Net::ihe4],0.48172270591286032); double H1MassFraction = netOut.composition.getMassFraction("H-1")/ 0.50166262445895604;
EXPECT_DOUBLE_EQ(netOut.energy, 1.6433049870528356e+18); double He4MassFraction = netOut.composition.getMassFraction("He-4") / 0.48172273720971226;
double relError = 1e-8;
EXPECT_NEAR(H1MassFraction, 1.0, relError);
EXPECT_NEAR(He4MassFraction, 1.0, relError);
EXPECT_NEAR(energyFraction, 1.0, relError);
} }

View File

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

View File

@@ -48,7 +48,7 @@ TEST_F(resourceManagerTest, getResource) {
const serif::resource::types::Resource &r = rm.getResource(name); const serif::resource::types::Resource &r = rm.getResource(name);
// BREAKPOINT(); // BREAKPOINT();
const auto &eos = std::get<std::unique_ptr<serif::eos::EOSio>>(r); const auto &eos = std::get<std::unique_ptr<serif::eos::EOSio>>(r);
EXPECT_EQ("helm", eos->getFormat()); EXPECT_EQ("Helmholtz", eos->getFormatName());
serif::eos::EOSTable &table = eos->getTable(); serif::eos::EOSTable &table = eos->getTable();
// -- Extract the Helm table from the EOSTable // -- Extract the Helm table from the EOSTable