← Documentation
ADS-IDAC Engine 5.0.0
RelapSolver.cpp
Go to the documentation of this file.
1
4
5#include "RelapSolver.h"
6#include "../Global/fmodule.h"
7#include "../Global/CheckedIO.h"
8#include "../Global/SimulationContext.h"
9#include "../Global/RestartTrim.h"
10#include <cstring>
11#include <cstdlib>
12#include <iostream>
13using namespace std;
14
15// ---- Fortran entry points ----
16extern "C" { void relap5_(); }
17extern "C" { void ads_set_cache_mode_(int* mode); }
18extern "C" { void ads_set_membuf_mode_(int mode); }
19extern "C" { void ads_membuf_get_trimmed_(char** ptr, int* size); }
20extern "C" { void ads_membuf_stats_(int* sz, int* dumps,
21 long long* b_rstrec, long long* b_rnewp,
22 long long* b_wrplid); }
23extern "C" { void ads_membuf_get_(char** ptr, int* sz); }
24extern "C" { void ads_membuf_set_(char* ptr, int sz); }
25
26// ---- Static callback routing ----
27// Set before relap5_() is called, cleared after it returns.
28// Safe: RELAP5 is single-threaded; in MPI, each rank is a separate process.
31
34
35// ---- Sequence execution ----
36
39 s_active_solver = this;
40 relap5_();
41 s_active_callback = nullptr;
42 s_active_solver = nullptr;
43}
44
45// ---- State accessors (thin wrappers around r5pars_) ----
46
47double RelapSolver::currentTime() const { return r5pars_.timesno; }
48int RelapSolver::stopFlag() const { return r5pars_.csnostop; }
49bool RelapSolver::isTerminateAll() const { return r5pars_.terminateall; }
50void RelapSolver::setTerminateAll(bool v) { r5pars_.terminateall = v; }
51
52// ---- Branch control ----
53
54void RelapSolver::setBranchCount(int n) { r5pars_.cnbranch = n; }
55void RelapSolver::setGenNode(bool v) { r5pars_.cgennode = v; }
56
57// ---- Restart lifecycle ----
58
59void RelapSolver::setNewRestart(bool v) { r5pars_.cnewrst = v; }
60
61void RelapSolver::setInputDeck(const std::string& path) {
62 strncpy(r5pars_.carg2, path.c_str(), sizeof(r5pars_.carg2) - 1);
63 r5pars_.carg2[sizeof(r5pars_.carg2) - 1] = '\0';
64 r5pars_.carg2len = static_cast<int>(path.size());
65}
66
67// ---- Checkpoint/restore ----
68
69std::vector<char> RelapSolver::checkpoint() {
70 char* buf_ptr = nullptr;
71 int buf_sz = 0;
72 // Environment variable ADS_MEMBUF_TRIM (read once per process): "1" makes
73 // the capture return [file header + plot-id block][last restart dump]
74 // instead of the whole accumulated buffer. A child inherits its parent's
75 // entire buffer and appends to it, so an untrimmed capture carries every
76 // dump in the lineage. The trimmed form is valid only if the buffer is
77 // restored at the point it was captured. Experimental, off by default.
78 static const bool trim = [] {
79 const char* t = std::getenv("ADS_MEMBUF_TRIM");
80 return t && *t == '1';
81 }();
82 if (trim) ads_membuf_get_trimmed_(&buf_ptr, &buf_sz);
83 else ads_membuf_get_(&buf_ptr, &buf_sz);
84 // ADS_MEMBUF_TRACE=1: report what a transfer is actually made of. Reported
85 // from C++ because RELAP rebinds Fortran unit 6, so writes from inside the
86 // membuf module go somewhere unobservable.
87 if (const char* t = std::getenv("ADS_MEMBUF_TRACE"); t && *t == '1') {
88 int sz = 0, dumps = 0; long long r = 0, n = 0, w = 0;
89 ads_membuf_stats_(&sz, &dumps, &r, &n, &w);
90 std::cout << "[MEMBUF] capture " << buf_sz / 1048576.0 << " MB"
91 << " dumps=" << dumps
92 << " rstrec=" << r / 1048576.0 << " MB"
93 << " rnewp=" << n / 1048576.0 << " MB"
94 << " wrplid=" << w / 1048576.0 << " MB"
95 << " (per dump " << (dumps ? r / 1048576.0 / dumps : 0.0) << " MB)"
96 << std::endl;
97 }
98 if (buf_sz > 0 && buf_ptr)
99 return std::vector<char>(buf_ptr, buf_ptr + buf_sz);
100 return {};
101}
102
103void RelapSolver::restore(const std::vector<char>& data) {
104 if (data.empty()) return;
105
106 // Splice the run-wide restart base back on if this buffer omits it.
107 //
108 // With ADS_RESTART_TRIM=1, MPI transfers ship [header][target] only: the
109 // [header][base] prefix is byte-identical across lineages, so it is cached
110 // per process instead of being sent with every branch. RELAP aborts in
111 // fabend if the first restart record it sees is not a COMPLETE one
112 // (rrestf.f), so the prefix has to come back before the restore.
113 //
114 // This lives HERE as well as in Client, because serial restores go
115 // straight to solver.restore() from ADSIDAC.cpp, and an MPI checkpoint
116 // resumed in serial mode carries base-less buffers.
118 if (base_cache_.empty()) {
119 std::vector<char> f;
120 const std::string p = g_sim.SScheduler.getProjectDirectory() + "/restart_base.bin";
121 if (read_file_verified(p, f) && !f.empty()) base_cache_ = std::move(f);
122 }
123 if (base_cache_.empty()) {
124 std::cerr << "FATAL: restart buffer has no complete restart record and no "
125 << "cached base is available — restoring it would abend in RELAP."
126 << std::endl;
127 std::abort();
128 }
129 auto spliced = adsidac::splice_base(base_cache_, data);
130 if (spliced.empty()) {
131 std::cerr << "FATAL: could not splice the restart base onto a buffer."
132 << std::endl;
133 std::abort();
134 }
135 ads_membuf_set_(spliced.data(), static_cast<int>(spliced.size()));
136 return;
137 }
138
139 // Self-contained: remember the base so later base-less buffers can be fixed
140 // without touching the disk.
142 ads_membuf_set_(const_cast<char*>(data.data()), static_cast<int>(data.size()));
143}
144
145// ---- Configuration ----
146
bool read_file_verified(const std::string &path, std::vector< char > &out)
Read an entire binary file into out, verifying the byte count.
Definition: CheckedIO.h:64
static SolverCallback * s_active_callback
Definition: RelapSolver.cpp:29
void ads_membuf_get_trimmed_(char **ptr, int *size)
void ads_set_cache_mode_(int *mode)
void relap5_()
void ads_membuf_get_(char **ptr, int *sz)
SolverCallback * getActiveSolverCallback()
Get the currently active SolverCallback (set during runSequence). Used by extern "C" trampoline funct...
Definition: RelapSolver.cpp:32
void ads_membuf_set_(char *ptr, int sz)
void ads_membuf_stats_(int *sz, int *dumps, long long *b_rstrec, long long *b_rnewp, long long *b_wrplid)
ThermalHydraulicSolver * getActiveSolver()
Get the currently active ThermalHydraulicSolver (set during runSequence). Returns nullptr when no seq...
Definition: RelapSolver.cpp:33
static ThermalHydraulicSolver * s_active_solver
Definition: RelapSolver.cpp:30
void ads_set_membuf_mode_(int mode)
RELAP5 implementation of ThermalHydraulicSolver.
SimulationContext g_sim
Global simulation context: the single instance, defined in SimulationContext.cpp.
std::vector< char > base_cache_
Definition: RelapSolver.h:66
void setNewRestart(bool v) override
Sets r5pars_.cnewrst.
Definition: RelapSolver.cpp:59
std::vector< char > checkpoint() override
Copy the Fortran in-memory restart buffer.
Definition: RelapSolver.cpp:69
void restore(const std::vector< char > &data) override
Load data into the Fortran in-memory restart buffer.
void setMembufMode(int mode) override
Forwards to ads_set_membuf_mode_()
void setThermoCacheMode(int mode) override
Forwards to ads_set_cache_mode_()
void runSequence(SolverCallback &cb) override
Run one RELAP5 sequence: registers cb and this solver as the active pair, calls relap5_() (blocking),...
Definition: RelapSolver.cpp:37
void setTerminateAll(bool v) override
Sets r5pars_.terminateall.
Definition: RelapSolver.cpp:50
bool isTerminateAll() const override
r5pars_.terminateall
Definition: RelapSolver.cpp:49
double currentTime() const override
r5pars_.timesno [s]
Definition: RelapSolver.cpp:47
void setInputDeck(const std::string &path) override
Copy path into r5pars_.carg2 (truncated to the array size minus one) and set r5pars_....
Definition: RelapSolver.cpp:61
int stopFlag() const override
r5pars_.csnostop
Definition: RelapSolver.cpp:48
void setBranchCount(int n) override
Sets r5pars_.cnbranch.
Definition: RelapSolver.cpp:54
void setGenNode(bool v) override
Sets r5pars_.cgennode.
Definition: RelapSolver.cpp:55
std::string getProjectDirectory()
Definition: Scheduler.cpp:595
Callback interface that the engine implements to receive notifications from the solver.
Abstract interface for thermal-hydraulic solvers.
struct @0 r5pars_
int size
Total number of MPI processes.
std::vector< char > splice_base(const std::vector< char > &hdr_base, const std::vector< char > &body)
Put the cached base back in front of a base-less transfer.
Definition: RestartTrim.h:150
std::vector< char > extract_header_and_base(const std::vector< char > &buf)
[header][complete base], the run-wide constant that is cached per rank and published as <project>/res...
Definition: RestartTrim.h:113
bool has_complete_restart(const std::vector< char > &buf)
Does this buffer contain a complete restart dump (the base)?
Definition: RestartTrim.h:105
Scheduler SScheduler
Simulation scheduling, parses CLI options.