6#include "../Global/fmodule.h"
19 : base_url_(base_url) {}
29 auto pos = host.find(
"://");
30 if (pos != std::string::npos) host = host.substr(pos + 3);
33 if (pos != std::string::npos) {
34 port = std::stoi(host.substr(pos + 1));
35 host = host.substr(0, pos);
38 httplib::Client cli(host, port);
39 cli.set_connection_timeout(5);
40 cli.set_read_timeout(30);
42 auto res = cli.Post(path, body,
"application/json");
44 throw std::runtime_error(
"HTTP POST failed: " + path +
" error=" + httplib::to_string(res.error()));
46 if (res->status >= 400) {
47 throw std::runtime_error(
"HTTP POST " + path +
" returned " + std::to_string(res->status) +
": " + res->body);
55 auto pos = host.find(
"://");
56 if (pos != std::string::npos) host = host.substr(pos + 3);
58 if (pos != std::string::npos) {
59 port = std::stoi(host.substr(pos + 1));
60 host = host.substr(0, pos);
63 httplib::Client cli(host, port);
64 cli.set_connection_timeout(5);
65 cli.set_read_timeout(30);
67 auto res = cli.Get(path);
69 throw std::runtime_error(
"HTTP GET failed: " + path);
77 auto pos = host.find(
"://");
78 if (pos != std::string::npos) host = host.substr(pos + 3);
80 if (pos != std::string::npos) {
81 port = std::stoi(host.substr(pos + 1));
82 host = host.substr(0, pos);
85 httplib::Client cli(host, port);
86 auto res = cli.Delete(path);
87 if (!res)
return "{}";
94 json body = {{
"mode", fresh ?
"fresh" :
"restart"}};
95 auto resp_str =
httpPost(
"/api/v1/sessions", body.dump());
97 session_id_ = resp[
"session_id"].get<std::string>();
98 std::cout <<
"[RestApiSolver] Created session: " <<
session_id_ << std::endl;
113 r5pars_.timesno = resp[
"time"].get<
double>();
116 if (resp.contains(
"volumes")) {
117 for (
auto& v : resp[
"volumes"]) {
118 int i = v[
"index"].get<
int>();
119 if (i >= 0 && i < 500) {
120 r5pars_.liq_t[i] = v[
"liq_t"].get<
double>();
121 r5pars_.vap_t[i] = v[
"vap_t"].get<
double>();
122 r5pars_.sat_t[i] = v[
"sat_t"].get<
double>();
123 r5pars_.sys_pressure[i] = v[
"pressure"].get<
double>();
124 r5pars_.boron_d[i] = v[
"boron_d"].get<
double>();
125 r5pars_.quality[i] = v[
"quality"].get<
double>();
126 r5pars_.flow_reg[i] = v[
"flow_reg"].get<
double>();
132 if (resp.contains(
"junctions")) {
133 for (
auto& j : resp[
"junctions"]) {
134 int i = j[
"index"].get<
int>();
135 if (i >= 0 && i < 500) {
136 r5pars_.mass_fr[i] = j[
"mass_fr"].get<
double>();
137 r5pars_.liq_vel[i] = j[
"liq_vel"].get<
double>();
138 r5pars_.vap_vel[i] = j[
"vap_vel"].get<
double>();
144 if (resp.contains(
"variable_trips")) {
145 for (
auto& t : resp[
"variable_trips"]) {
146 int i = t[
"index"].get<
int>();
147 if (i >= 0 && i < 500) {
148 r5pars_.vartrip_t[i] = t[
"trip_time"].get<
double>();
154 if (resp.contains(
"logical_trips")) {
155 for (
auto& t : resp[
"logical_trips"]) {
156 int i = t[
"index"].get<
int>();
157 if (i >= 0 && i < 500) {
158 r5pars_.logtrip_t[i] = t[
"trip_time"].get<
double>();
164 if (resp.contains(
"control_variables")) {
165 for (
auto& c : resp[
"control_variables"]) {
166 int i = c[
"index"].get<
int>();
167 if (i >= 0 && i < 500) {
168 r5pars_.ctrl_var_val[i] = c[
"value"].get<
double>();
174 if (resp.contains(
"stop_flag")) {
175 r5pars_.csnostop = resp[
"stop_flag"].get<
int>();
183 json actions = json::array();
185 for (
int i = 0; i < n; i++) {
186 double current =
r5pars_.inter_val[i];
188 if (it ==
last_inter_val_.end() || std::abs(it->second - current) > 1
e-10) {
189 actions.push_back({{
"index", i}, {
"value", current}});
194 if (!actions.empty()) {
195 json body = {{
"actions", actions}};
214 ckpt_id = it->second;
218 std::cerr <<
"[RestApiSolver] WARNING: ncount=" << ncount
219 <<
" not found in checkpoint map, using fallback" << std::endl;
221 if (!ckpt_id.empty()) {
222 json restore_body = {{
"checkpoint_id", ckpt_id}};
224 restore_body.dump());
226 double restored_time = rj[
"time"].get<
double>();
231 r5pars_.timesno = restored_time;
234 std::cout <<
"[RestApiSolver] Restored checkpoint " << ckpt_id
235 <<
" (ncount=" << ncount <<
") t=" << restored_time << std::endl;
254 json advance_body = {{
"dt", 0.5}};
256 advance_body.dump());
273 std::string ckpt_id = ckpt[
"checkpoint_id"].get<std::string>();
280 std::cout <<
"[RestApiSolver] Checkpoint " << ckpt_id
281 <<
" ncount=" <<
r5pars_.cncount
282 <<
" t=" <<
r5pars_.timesno << std::endl;
312 r5pars_.carg2len =
static_cast<int>(path.size());
324 j[std::to_string(ncount)] = ckpt_id;
326 std::string s = j.dump();
327 return std::vector<char>(s.begin(), s.end());
331 if (data.empty())
return;
335 std::string s(data.begin(), data.end());
338 for (
auto& [key, val] : j.items()) {
356 std::ifstream ifs(path);
358 while (std::getline(ifs, line)) {
359 if (line.size() >= 4 && line.substr(0, 3) ==
"103") {
360 auto pos = line.find_first_of(
"0123456789", 3);
361 if (pos != std::string::npos) {
362 return std::stoi(line.substr(pos));
REST API implementation of ThermalHydraulicSolver.
void setInputDeck(const std::string &path) override
Store path in r5pars_.carg2 / carg2len. The remote solver does not read input decks; runSequence() al...
void setTerminateAll(bool v) override
Sets r5pars_.terminateall.
std::map< int, std::string > restore_checkpoints_
void setThermoCacheMode(int mode) override
No-op.
RestApiSolver(const std::string &base_url)
bool isTerminateAll() const override
r5pars_.terminateall
static int parseNcountFromIndeck(const std::string &path)
std::string httpDelete(const std::string &path)
std::string httpPost(const std::string &path, const std::string &body="{}")
std::map< int, std::string > seq_checkpoints_
std::map< int, double > last_inter_val_
void runSequence(SolverCallback &cb) override
Run one sequence against the remote solver. Blocks until it ends.
std::string httpGet(const std::string &path)
void setBranchCount(int n) override
Sets r5pars_.cnbranch.
void createSession(bool fresh)
std::vector< char > checkpoint() override
JSON object mapping restart count (as a string key) to the server-side checkpoint id,...
double currentTime() const override
r5pars_.timesno [s]
int stopFlag() const override
r5pars_.csnostop
void populateR5Pars(const std::string &json_str)
void restore(const std::vector< char > &data) override
Parse a buffer produced by checkpoint() and keep its map for the next runSequence(),...
void setMembufMode(int mode) override
No-op.
std::string last_checkpoint_id_
void setGenNode(bool v) override
Sets r5pars_.cgennode.
void setNewRestart(bool v) override
Sets r5pars_.cnewrst.
Callback interface that the engine implements to receive notifications from the solver.
virtual void onBranchingPoint(ThermalHydraulicSolver &solver)=0
Called when a branching point is reached during simulation. RelapSolver routes the Fortran initiate_b...
virtual void onFirstInit(ThermalHydraulicSolver &solver)=0
Called once for the entire simulation during first initialization. RelapSolver routes the Fortran act...
virtual void onScenarioStart(ThermalHydraulicSolver &solver)=0
Called once at the start of each scenario/sequence. RelapSolver routes the Fortran secini_() callback...
virtual void onEvaluationPoint(ThermalHydraulicSolver &solver)=0
Called at each evaluation point (~0.5s simulation time intervals). RelapSolver routes the Fortran int...
Element parse(const std::string &text)