fix(GridFire): changes based on ref report

This commit is contained in:
2026-04-20 12:37:53 -04:00
parent f4d988fa25
commit 3a22792fd1
17 changed files with 291 additions and 68 deletions

1
.gitignore vendored
View File

@@ -132,3 +132,4 @@ meson-boost-test/
cross/python_includes cross/python_includes
*.whl *.whl
*.pdf

View File

@@ -152,25 +152,6 @@ the same for the other shared object file (make sure to count the duplicate rpat
We also include a script at `pip_install_mac_patch.sh` which will do this automatically for you. We also include a script at `pip_install_mac_patch.sh` which will do this automatically for you.
## Automatic Build and Installation ## Automatic Build and Installation
### Script Build and Installation Instructions
The easiest way to build GridFire is using the `install.sh` or `install-tui.sh`
scripts in the root directory. To use these scripts, simply run:
```bash
./install.sh
# or
./install-tui.sh
```
The regular installation script will select a standard "ideal" set of build
options for you. If you want more control over the build options, you can use
the `install-tui.sh` script, which will provide a text-based user interface to
select the build options you want.
Generally, both are intended to be easy to use and will prompt you
automatically to install any missing dependencies.
### Currently, known good platforms ### Currently, known good platforms
The installation script has been tested and found to work on clean The installation script has been tested and found to work on clean
installations of the following platforms: installations of the following platforms:
@@ -179,11 +160,6 @@ installations of the following platforms:
- Ubuntu 25.04 (aarch64) - Ubuntu 25.04 (aarch64)
- Ubuntu 22.04 (X86_64) - Ubuntu 22.04 (X86_64)
> **Note:** On Ubuntu 22.04 the user needs to install boost libraries manually
> as the versions in the Ubuntu repositories
> are too old. The installer automatically detects this and will instruct the
> user in how to do this.
## Manual Build Instructions ## Manual Build Instructions
### Prerequisites ### Prerequisites
@@ -197,8 +173,6 @@ These only need to be manually installed if the user is not making use of the
- CMake 3.20 or newer - CMake 3.20 or newer
- ninja 1.10.0 or newer - ninja 1.10.0 or newer
- Python packages: `meson-python>=0.15.0` - Python packages: `meson-python>=0.15.0`
- Boost libraries (>= 1.83.0) installed system-wide (or at least findable by
meson with pkg-config)
#### Optional #### Optional
- dialog (used by the `install.sh` script, not needed if using pip or meson - dialog (used by the `install.sh` script, not needed if using pip or meson
@@ -206,15 +180,10 @@ These only need to be manually installed if the user is not making use of the
- pip (used by the `install.sh` script or by calling pip directly, not needed - pip (used by the `install.sh` script or by calling pip directly, not needed
if using meson directly) if using meson directly)
> **Note:** Boost is the only external library dependency used by GridFire directly.
> **Note:** Windows is not supported at this time and *there are no plans to > **Note:** Windows is not supported at this time and *there are no plans to
> support it in the future*. Windows users are encouraged to use WSL2 or a > support it in the future*. Windows users are encouraged to use WSL2 or a
> Linux VM. > Linux VM.
> **Note:** If `install-tui.sh` is not able to find a usable version of boost
> it will provide directions to fetch, compile, and install a usable version.
### Install Scripts ### Install Scripts
GridFire ships with an installer (`install.sh`) which is intended to make the GridFire ships with an installer (`install.sh`) which is intended to make the
process of installation both easier and more repeatable. process of installation both easier and more repeatable.
@@ -447,7 +416,6 @@ likely to be one of adding new `EngineViews`.
| View Name | Purpose | Algorithm / Reference | When to Use | | View Name | Purpose | Algorithm / Reference | When to Use |
|----------------------------------|-----------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------| |----------------------------------|-----------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------|
| AdaptiveEngineView | Dynamically culls low-flow species and reactions during runtime | Iterative flux thresholding to remove reactions below a flow threshold | Large networks to reduce computational cost |
| DefinedEngineView | Restricts the network to a user-specified subset of species and reactions | Static network masking based on user-provided species/reaction lists | Targeted pathway studies or code-to-code comparisons | | DefinedEngineView | Restricts the network to a user-specified subset of species and reactions | Static network masking based on user-provided species/reaction lists | Targeted pathway studies or code-to-code comparisons |
| FileDefinedEngineView | Load a defined engine view from a file using some parser | Same as DefinedEngineView but loads from a file | Same as DefinedEngineView | | FileDefinedEngineView | Load a defined engine view from a file using some parser | Same as DefinedEngineView but loads from a file | Same as DefinedEngineView |
| MultiscalePartitioningEngineView | Partitions the network into fast and slow subsets based on reaction timescales | Network partitioning following Hix & Thielemann Silicon Burning I & II (DOI:10.1086/177016,10.1086/306692) | Stiff, multi-scale networks requiring tailored integration | | MultiscalePartitioningEngineView | Partitions the network into fast and slow subsets based on reaction timescales | Network partitioning following Hix & Thielemann Silicon Burning I & II (DOI:10.1086/177016,10.1086/306692) | Stiff, multi-scale networks requiring tailored integration |
@@ -523,7 +491,7 @@ A `NetOut` struct contains
- The total specific energy lost to neutrinos while evolving to `tMax` (`NetOut::total_neutrino_loss`) [erg/g] - The total specific energy lost to neutrinos while evolving to `tMax` (`NetOut::total_neutrino_loss`) [erg/g]
- The total flux of neutrinos while evolving to `tMax` (`NetOut::total_neutrino_flux`) - The total flux of neutrinos while evolving to `tMax` (`NetOut::total_neutrino_flux`)
### CVODESolverStrategy ### PointSolver
We use the CVODE module from [SUNDIALS](https://computing.llnl.gov/projects/sundials/cvode) as our primary numerical We use the CVODE module from [SUNDIALS](https://computing.llnl.gov/projects/sundials/cvode) as our primary numerical
solver. Specifically we use the BDF linear multistep method from that which includes advanced adaptive timestepping. solver. Specifically we use the BDF linear multistep method from that which includes advanced adaptive timestepping.

View File

@@ -8,7 +8,8 @@ cvode_cmake_options.add_cmake_defines({
'BUILD_STATIC_LIBS' : 'ON', 'BUILD_STATIC_LIBS' : 'ON',
'EXAMPLES_ENABLE_C' : 'OFF', 'EXAMPLES_ENABLE_C' : 'OFF',
'CMAKE_POSITION_INDEPENDENT_CODE': true, 'CMAKE_POSITION_INDEPENDENT_CODE': true,
'CMAKE_PLATFORM_NO_VERSIONED_SONAME': 'ON' 'CMAKE_PLATFORM_NO_VERSIONED_SONAME': 'ON',
'SUNDIALS_LOGGING_LEVEL': 1
}) })

View File

@@ -9,7 +9,8 @@ kinsol_cmake_options.add_cmake_defines({
'BUILD_STATIC_LIBS' : 'ON', 'BUILD_STATIC_LIBS' : 'ON',
'EXAMPLES_ENABLE_C' : 'OFF', 'EXAMPLES_ENABLE_C' : 'OFF',
'CMAKE_POSITION_INDEPENDENT_CODE': true, 'CMAKE_POSITION_INDEPENDENT_CODE': true,
'CMAKE_PLATFORM_NO_VERSIONED_SONAME': 'ON' 'CMAKE_PLATFORM_NO_VERSIONED_SONAME': 'ON',
'SUNDIALS_LOGGING_LEVEL': 1
}) })
kinsol_cmake_options.add_cmake_defines({ kinsol_cmake_options.add_cmake_defines({

View File

@@ -70,6 +70,7 @@ struct AdaptiveEngineViewScratchPad final : AbstractScratchPad {
/// @brief Flag indicating whether the scratchpad has been initialized. /// @brief Flag indicating whether the scratchpad has been initialized.
bool has_initialized = false; bool has_initialized = false;
/// @brief Vector of species currently active in the adaptive network. /// @brief Vector of species currently active in the adaptive network.
std::vector<fourdst::atomic::Species> active_species; std::vector<fourdst::atomic::Species> active_species;

View File

@@ -103,6 +103,9 @@ struct MultiscalePartitioningEngineViewScratchPad final : AbstractScratchPad {
/// @brief Flag indicating whether the scratchpad has been initialized. /// @brief Flag indicating whether the scratchpad has been initialized.
bool has_initialized = false; bool has_initialized = false;
/// @breif User configurable parameter to control flux coupling threshold used
double flux_coupling_threshold = 5.0;
/// @brief Vector of QSE groups representing equilibrium clusters. /// @brief Vector of QSE groups representing equilibrium clusters.
std::vector<QSEGroup> qse_groups; std::vector<QSEGroup> qse_groups;

View File

@@ -1,3 +1,4 @@
#pragma once #pragma once
#include "gridfire/io/generative/python.h" #include "gridfire/io/generative/python.h"
#include "gridfire/io/generative/mesa.h"

View File

@@ -0,0 +1,17 @@
#pragma once
#include "fourdst/atomic/atomicSpecies.h"
#include "gridfire/reaction/reaction.h"
#include "gridfire/engine/engine_abstract.h"
#include <format>
namespace gridfire::io::generative {
std::string get_mesa_iso_name(const fourdst::atomic::Species& species);
bool is_proton(const fourdst::atomic::Species& species);
bool is_alpha(const fourdst::atomic::Species& species);
bool is_neutron(const fourdst::atomic::Species& species);
std::string get_mesa_reaction_name(const reaction::Reaction& reaction);
std::string export_engine_to_mesa_net(const engine::DynamicEngine& engine, engine::scratch::StateBlob& ctx, bool skip_weak);
}

View File

@@ -37,5 +37,5 @@ configure_file(
output : 'config.h', output : 'config.h',
configuration : conf_data, configuration : conf_data,
install : do_install_version_file, install : do_install_version_file,
install_dir : get_option('includedir') / '/gridfire/utils' install_dir : get_option('includedir') / 'gridfire/utils'
) )

View File

@@ -1337,7 +1337,8 @@ namespace gridfire::engine {
const double rho, const double rho,
const QSEGroup &group const QSEGroup &group
) const { ) const {
constexpr double FLUX_RATIO_THRESHOLD = 5; auto* state = scratch::get_state<scratch::MultiscalePartitioningEngineViewScratchPad, true>(ctx);
double FLUX_RATIO_THRESHOLD = state->flux_coupling_threshold;
const std::unordered_set<Species> algebraic_group_members( const std::unordered_set<Species> algebraic_group_members(
group.algebraic_species.begin(), group.algebraic_species.begin(),
@@ -1484,8 +1485,8 @@ namespace gridfire::engine {
const double diff_total = std::abs(total_prod - total_dest); const double diff_total = std::abs(total_prod - total_dest);
bool total_balanced = (mean_total > 0) && ((diff_total / mean_total) < 0.05); bool total_balanced = (mean_total > 0) && ((diff_total / mean_total) < 0.05);
// Check 2: Charged-Particle Balance (The "Neutron-Exclusion" Check) // Check 2: Charged-Particle Balance
// Only valid if there IS charged flow (avoid 0/0 success) // Only valid if there IS charged flow
const double mean_charged = (charged_prod + charged_dest) / 2.0; const double mean_charged = (charged_prod + charged_dest) / 2.0;
const double diff_charged = std::abs(charged_prod - charged_dest); const double diff_charged = std::abs(charged_prod - charged_dest);
bool charged_balanced = (mean_charged > 0) && ((diff_charged / mean_charged) < 0.05); bool charged_balanced = (mean_charged > 0) && ((diff_charged / mean_charged) < 0.05);

View File

@@ -0,0 +1,155 @@
#include "gridfire/io/generative/mesa.h"
#include "gridfire/engine/engine_abstract.h"
#include "gridfire/reaction/reaction.h"
#include "fourdst/atomic/atomicSpecies.h"
#include "gridfire/utils/config.h"
#include <sstream>
#include <string>
#include <vector>
#include <algorithm>
#include <chrono>
#include <cctype>
namespace gridfire::io::generative {
std::string get_mesa_iso_name(const fourdst::atomic::Species& species) {
auto name = std::string(species.name());
std::ranges::transform(name, name.begin(), ::tolower);
name.erase(std::ranges::remove(name, '-').begin(), name.end());
if (name == "p") return "h1";
if (name == "n" || name == "n1") return "neut";
if (name == "d") return "h2";
if (name == "t") return "h3";
if (name == "a") return "he4";
return name;
}
bool is_proton(const fourdst::atomic::Species& s) { return get_mesa_iso_name(s) == "h1"; }
bool is_alpha(const fourdst::atomic::Species& s) { return get_mesa_iso_name(s) == "he4"; }
bool is_neutron(const fourdst::atomic::Species& s) { return get_mesa_iso_name(s) == "neut"; }
std::string get_mesa_reaction_name(const reaction::Reaction& reaction) {
std::vector<fourdst::atomic::Species> react_sorted = reaction.reactants();
std::vector<fourdst::atomic::Species> prod_sorted = reaction.products();
auto sort_species = [](std::vector<fourdst::atomic::Species>& list) {
std::ranges::sort(list, [](const auto& a, const auto& b) {
if (a.z() != b.z()) return a.z() < b.z();
return a.a() < b.a();
});
};
sort_species(react_sorted);
sort_species(prod_sorted);
if (react_sorted.size() == 1 && prod_sorted.size() == 1) {
if (reaction.type() == reaction::ReactionType::WEAK ||
reaction.type() == reaction::ReactionType::REACLIB_WEAK ||
reaction.type() == reaction::ReactionType::LOGICAL_REACLIB_WEAK) {
return "r_" + get_mesa_iso_name(react_sorted[0]) + "_wk_" + get_mesa_iso_name(prod_sorted[0]);
}
}
if (react_sorted.size() == 2 && prod_sorted.size() == 1) {
std::string x, cap;
if (is_proton(react_sorted[0]) || is_proton(react_sorted[1])) {
cap = "pg";
x = is_proton(react_sorted[0]) ? get_mesa_iso_name(react_sorted[1]) : get_mesa_iso_name(react_sorted[0]);
}
else if (is_alpha(react_sorted[0]) || is_alpha(react_sorted[1])) {
cap = "ag";
x = is_alpha(react_sorted[0]) ? get_mesa_iso_name(react_sorted[1]) : get_mesa_iso_name(react_sorted[0]);
}
else if (is_neutron(react_sorted[0]) || is_neutron(react_sorted[1])) {
cap = "ng";
x = is_neutron(react_sorted[0]) ? get_mesa_iso_name(react_sorted[1]) : get_mesa_iso_name(react_sorted[0]);
}
if (!cap.empty()) return "r_" + x + "_" + cap + "_" + get_mesa_iso_name(prod_sorted[0]);
}
if (react_sorted.size() == 1 && prod_sorted.size() == 2) {
std::string x, em;
if (is_proton(prod_sorted[0]) || is_proton(prod_sorted[1])) {
em = "gp";
x = is_proton(prod_sorted[0]) ? get_mesa_iso_name(prod_sorted[1]) : get_mesa_iso_name(prod_sorted[0]);
}
else if (is_alpha(prod_sorted[0]) || is_alpha(prod_sorted[1])) {
em = "ga";
x = is_alpha(prod_sorted[0]) ? get_mesa_iso_name(prod_sorted[1]) : get_mesa_iso_name(prod_sorted[0]);
}
else if (is_neutron(prod_sorted[0]) || is_neutron(prod_sorted[1])) {
em = "gn";
x = is_neutron(prod_sorted[0]) ? get_mesa_iso_name(prod_sorted[1]) : get_mesa_iso_name(prod_sorted[0]);
}
if (!em.empty()) return "r_" + get_mesa_iso_name(react_sorted[0]) + "_" + em + "_" + x;
}
if (react_sorted.size() == 2 && prod_sorted.size() == 2) {
int r_p = -1, r_a = -1, r_n = -1;
int p_p = -1, p_a = -1, p_n = -1;
for(int i=0; i<2; ++i) {
if(is_proton(react_sorted[i])) r_p = i;
if(is_alpha(react_sorted[i])) r_a = i;
if(is_neutron(react_sorted[i])) r_n = i;
if(is_proton(prod_sorted[i])) p_p = i;
if(is_alpha(prod_sorted[i])) p_a = i;
if(is_neutron(prod_sorted[i])) p_n = i;
}
std::string x, y, exc;
if (r_a != -1 && p_p != -1) { exc = "ap"; x = get_mesa_iso_name(react_sorted[1-r_a]); y = get_mesa_iso_name(prod_sorted[1-p_p]); }
else if (r_p != -1 && p_a != -1) { exc = "pa"; x = get_mesa_iso_name(react_sorted[1-r_p]); y = get_mesa_iso_name(prod_sorted[1-p_a]); }
else if (r_n != -1 && p_p != -1) { exc = "np"; x = get_mesa_iso_name(react_sorted[1-r_n]); y = get_mesa_iso_name(prod_sorted[1-p_p]); }
else if (r_p != -1 && p_n != -1) { exc = "pn"; x = get_mesa_iso_name(react_sorted[1-r_p]); y = get_mesa_iso_name(prod_sorted[1-p_n]); }
else if (r_n != -1 && p_a != -1) { exc = "na"; x = get_mesa_iso_name(react_sorted[1-r_n]); y = get_mesa_iso_name(prod_sorted[1-p_a]); }
else if (r_a != -1 && p_n != -1) { exc = "an"; x = get_mesa_iso_name(react_sorted[1-r_a]); y = get_mesa_iso_name(prod_sorted[1-p_n]); }
if (!exc.empty()) return "r_" + x + "_" + exc + "_" + y;
}
std::string fallback = "r";
for (const auto& s : react_sorted) fallback += "_" + get_mesa_iso_name(s);
fallback += "_to";
for (const auto& s : prod_sorted) fallback += "_" + get_mesa_iso_name(s);
return fallback;
}
std::string export_engine_to_mesa_net(const engine::DynamicEngine& engine, engine::scratch::StateBlob& ctx, bool skip_weak) {
std::stringstream ss;
ss << "! Auto-generated MESA .net file from GridFire\n";
ss << "! Generated by GridFire version: " << version().toString() << "\n";
ss << "! Generated on " << std::chrono::system_clock::to_time_t(std::chrono::system_clock::now()) << "\n\n";
ss << "add_isos(\n";
for (const auto& species : engine.getNetworkSpecies(ctx)) {
ss << " " << get_mesa_iso_name(species) << "\n";
}
ss << ")\n\n";
ss << "add_reactions(\n";
const auto& reactions = engine.getNetworkReactions(ctx);
for (const auto& reaction_ptr : reactions) {
if (skip_weak && (reaction_ptr->type() == reaction::ReactionType::WEAK ||
reaction_ptr->type() == reaction::ReactionType::REACLIB_WEAK ||
reaction_ptr->type() == reaction::ReactionType::LOGICAL_REACLIB_WEAK)) {
continue;
}
ss << " " << get_mesa_reaction_name(*reaction_ptr) << "\n";
}
ss << ")\n";
return ss.str();
}
}

View File

@@ -61,14 +61,7 @@ namespace gridfire::policy {
std::make_unique<engine::GraphEngine>(m_initializing_composition, *m_partition_function, engine::NetworkBuildDepth::ThirdOrder, engine::NetworkConstructionFlags::DEFAULT) std::make_unique<engine::GraphEngine>(m_initializing_composition, *m_partition_function, engine::NetworkBuildDepth::ThirdOrder, engine::NetworkConstructionFlags::DEFAULT)
); );
m_network_stack.emplace_back( std::unique_ptr<engine::scratch::StateBlob> scratch_blob = m_network_stack.back()->constructStateBlob(nullptr);
std::make_unique<engine::MultiscalePartitioningEngineView>(*m_network_stack.back().get())
);
m_network_stack.emplace_back(
std::make_unique<engine::AdaptiveEngineView>(*m_network_stack.back().get())
);
std::unique_ptr<engine::scratch::StateBlob> scratch_blob = get_stack_scratch_blob();
m_status = NetworkPolicyStatus::INITIALIZED_UNVERIFIED; m_status = NetworkPolicyStatus::INITIALIZED_UNVERIFIED;
m_status = check_status(*scratch_blob); m_status = check_status(*scratch_blob);
@@ -110,8 +103,6 @@ namespace gridfire::policy {
std::vector<engine::EngineTypes> MainSequencePolicy::get_engine_types_stack() const { std::vector<engine::EngineTypes> MainSequencePolicy::get_engine_types_stack() const {
return { return {
engine::EngineTypes::GRAPH_ENGINE, engine::EngineTypes::GRAPH_ENGINE,
engine::EngineTypes::MULTISCALE_PARTITIONING_ENGINE_VIEW,
engine::EngineTypes::ADAPTIVE_ENGINE_VIEW
}; };
} }
@@ -125,32 +116,14 @@ namespace gridfire::policy {
} }
auto blob = std::make_unique<engine::scratch::StateBlob>(); auto blob = std::make_unique<engine::scratch::StateBlob>();
blob->enroll<engine::scratch::GraphEngineScratchPad>(); blob->enroll<engine::scratch::GraphEngineScratchPad>();
blob->enroll<engine::scratch::AdaptiveEngineViewScratchPad>();
blob->enroll<engine::scratch::MultiscalePartitioningEngineViewScratchPad>();
const engine::GraphEngine* graph_engine = dynamic_cast<engine::GraphEngine*>(m_network_stack.front().get()); const engine::GraphEngine* graph_engine = dynamic_cast<engine::GraphEngine*>(m_network_stack.front().get());
if (!graph_engine) { if (!graph_engine) {
throw exceptions::PolicyError("Cannot get stack scratch blob from MainSequencePolicy: The base engine is not a GraphEngine. This indicates a serious internal inconsistency and should be reported to the GridFire developers, thank you."); throw exceptions::PolicyError("Cannot get stack scratch blob from MainSequencePolicy: The base engine is not a GraphEngine. This indicates a serious internal inconsistency and should be reported to the GridFire developers, thank you.");
} }
const engine::MultiscalePartitioningEngineView* multiscale_engine = dynamic_cast<engine::MultiscalePartitioningEngineView*>(m_network_stack[1].get());
if (!multiscale_engine) {
throw exceptions::PolicyError("Cannot get stack scratch blob from MainSequencePolicy: The middle engine is not a MultiscalePartitioningEngineView. This indicates a serious internal inconsistency and should be reported to the GridFire developers, thank you.");
}
const engine::AdaptiveEngineView* adaptive_engine = dynamic_cast<engine::AdaptiveEngineView*>(m_network_stack.back().get());
if (!adaptive_engine) {
throw exceptions::PolicyError("Cannot get stack scratch blob from MainSequencePolicy: The top engine is not an AdaptiveEngineView. This indicates a serious internal inconsistency and should be reported to the GridFire developers, thank you.");
}
auto* graph_engine_state = engine::scratch::get_state<engine::scratch::GraphEngineScratchPad, false>(*blob); auto* graph_engine_state = engine::scratch::get_state<engine::scratch::GraphEngineScratchPad, false>(*blob);
graph_engine_state->initialize(*graph_engine); graph_engine_state->initialize(*graph_engine);
auto* multiscale_engine_state = engine::scratch::get_state<engine::scratch::MultiscalePartitioningEngineViewScratchPad, false>(*blob);
multiscale_engine_state->initialize();
auto* adaptive_engine_state = engine::scratch::get_state<engine::scratch::AdaptiveEngineViewScratchPad, false>(*blob);
adaptive_engine_state->initialize(*adaptive_engine);
return blob; return blob;
} }

View File

@@ -17,6 +17,7 @@ gridfire_sources = files(
'lib/reaction/weak/weak_interpolator.cpp', 'lib/reaction/weak/weak_interpolator.cpp',
'lib/io/network_file.cpp', 'lib/io/network_file.cpp',
'lib/io/generative/python.cpp', 'lib/io/generative/python.cpp',
'lib/io/generative/mesa.cpp',
'lib/solver/strategies/PointSolver.cpp', 'lib/solver/strategies/PointSolver.cpp',
'lib/solver/strategies/GridSolver.cpp', 'lib/solver/strategies/GridSolver.cpp',
'lib/solver/strategies/triggers/engine_partitioning_trigger.cpp', 'lib/solver/strategies/triggers/engine_partitioning_trigger.cpp',

View File

@@ -0,0 +1,99 @@
// ReSharper disable CppUnusedIncludeDirective
#include <iostream>
#include <fstream>
#include <chrono>
#include <thread>
#include <format>
#include <cppad/utility/thread_alloc.hpp> // Required for parallel_setup
#include "fourdst/logging/logging.h"
#include "fourdst/atomic/species.h"
#include "fourdst/composition/utils.h"
#include "quill/Logger.h"
#include "quill/Backend.h"
#include "CLI/CLI.hpp"
#include <clocale>
#include "gridfire/gridfire.h"
#include "fourdst/composition/composition.h"
#include "gridfire/utils/gf_omp.h"
#include <atomic>
#include <new>
#include <cstdlib>
static std::terminate_handler g_previousHandler = nullptr;
void quill_terminate_handler();
gridfire::NetIn init(const double temp, const double rho, const double tMax) {
std::setlocale(LC_ALL, "");
g_previousHandler = std::set_terminate(quill_terminate_handler);
quill::Logger* logger = fourdst::logging::LogManager::getInstance().getLogger("log");
logger->set_log_level(quill::LogLevel::Info);
using namespace gridfire;
const std::vector<double> X = {0.7081145999999999, 2.94e-5, 0.276, 0.003, 0.0011, 9.62e-3, 1.62e-3, 5.16e-4};
const std::vector<std::string> symbols = {"H-1", "He-3", "He-4", "C-12", "N-14", "O-16", "Ne-20", "Mg-24"};
const fourdst::composition::Composition composition = fourdst::composition::buildCompositionFromMassFractions(symbols, X);
NetIn netIn;
netIn.composition = composition;
netIn.temperature = temp;
netIn.density = rho;
netIn.energy = 0;
netIn.tMax = tMax;
netIn.dt0 = 1e-12;
return netIn;
}
void quill_terminate_handler()
{
quill::Backend::stop();
if (g_previousHandler)
g_previousHandler();
else
std::abort();
}
int main(int argc, char* argv[]) {
using namespace gridfire;
double temp = 1.5e7;
double rho = 1.6e2;
double tMax = 3e17;
double coupling_ratio = 5.0;
std::string output_filename = "coupling.dat";
CLI::App app("GridFire Test Coupling");
app.add_option("--temperature", temp, "Temperature in degrees")->default_val(std::format("{:5.2E}", temp));
app.add_option("--density", rho, "Density in Kg")->default_val(std::format("{:5.2E}", rho));
app.add_option("--tmax", tMax, "Maximum time in seconds")->default_val(std::format("{:5.2E}", tMax));
app.add_option("--coupling_ratio", coupling_ratio, "Coupling ratio for multiscale partitioning")->default_val(std::format("{:.2f}", coupling_ratio));
app.add_option("--output", output_filename, "Output filename for intermediate results")->default_val("coupling.dat");
CLI11_PARSE(app, argc, argv);
const NetIn netIn = init(temp, rho, tMax);
auto base_engine = std::make_unique<engine::GraphEngine>(netIn.composition, 3);
auto base_blob = base_engine->constructStateBlob();
auto qse_engine = std::make_unique<engine::MultiscalePartitioningEngineView>(*base_engine);
auto blob = qse_engine->constructStateBlob(base_blob.get());
auto* state = engine::scratch::get_state<engine::scratch::MultiscalePartitioningEngineViewScratchPad, true>(*blob);
const solver::PointSolver localSolver(*base_engine);
solver::PointSolverContext solverCtx(*base_blob);
auto result = localSolver.evaluate(solverCtx, netIn, false, false);
}

View File

@@ -5,4 +5,5 @@
# Subdirectories for unit and integration tests # Subdirectories for unit and integration tests
subdir('graphnet_sandbox') subdir('graphnet_sandbox')
subdir('flux_coupling')
subdir('extern') subdir('extern')

View File