ryujin 2.1.1 revision ee5cbcbf2346c1299c942d0e1f13b46449973c18
Loading...
Searching...
No Matches
equation_of_state_sesame.h
Go to the documentation of this file.
1//
2// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
3// Copyright (C) 2023 - 2026 by the ryujin authors
4//
5
6#pragma once
7
8#include <compile_time_options.h>
9
10#include "equation_of_state.h"
11#include "lazy.h"
12
13#include <deal.II/base/array_view.h>
14#include <deal.II/base/config.h>
15#include <deal.II/base/exceptions.h>
16#include <deal.II/base/parameter_acceptor.h>
17
18#ifdef WITH_EOSPAC
19#include "eos_Interface.h"
20#endif
21
22#include <filesystem>
23
24
25namespace ryujin
26{
27#ifdef WITH_EOSPAC
35 namespace eospac
36 {
42 enum class TableType : EOS_INTEGER {
47 p_rho_e = EOS_Pt_DUt,
52 e_rho_p = EOS_Ut_DPt,
53 };
54
60 class Interface
61 {
62 public:
69 Interface(const std::vector<std::tuple<EOS_INTEGER, TableType>> &tables)
70 {
71 n_tables_ = tables.size();
72
73 std::transform(std::begin(tables),
74 std::end(tables),
75 std::back_inserter(material_ids_),
76 [](const auto &it) { return std::get<0>(it); });
77
78 std::transform(std::begin(tables),
79 std::end(tables),
80 std::back_inserter(table_types_),
81 [](const auto &it) {
82 return static_cast<EOS_INTEGER>(std::get<1>(it));
83 });
84
85 table_handles_.resize(n_tables_);
86
87 /* create tables: */
88
89 EOS_INTEGER error_code;
90 eos_CreateTables(&n_tables_,
91 table_types_.data(),
92 material_ids_.data(),
93 table_handles_.data(),
94 &error_code);
95 check_tables("eos_CreateTables");
96
97 /* set table options: */
98
99 for (EOS_INTEGER i = 0; i < n_tables_; i++) {
100 // FIXME: refactor into options
101 eos_SetOption(
102 &table_handles_[i], &EOS_SMOOTH, EOS_NullPtr, &error_code);
103 check_error_code(error_code, "eos_SetOption", i);
104 }
105
106 /* load tables: */
107
108 eos_LoadTables(&n_tables_, table_handles_.data(), &error_code);
109 check_tables("eos_LoadTables");
110 }
111
115 ~Interface() noexcept
116 {
117 EOS_INTEGER error_code;
118 eos_DestroyTables(&n_tables_, table_handles_.data(), &error_code);
119 }
120
125 inline DEAL_II_ALWAYS_INLINE void
126 interpolate_values(const EOS_INTEGER &index,
127 const dealii::ArrayView<EOS_REAL> &F,
128 const dealii::ArrayView<EOS_REAL> &dFx,
129 const dealii::ArrayView<EOS_REAL> &dFy,
130 const dealii::ArrayView<const EOS_REAL> &X,
131 const dealii::ArrayView<const EOS_REAL> &Y)
132 {
133 Assert(index >= 0 && index < n_tables_,
134 dealii::ExcMessage("Table index out of range"));
135
136 EOS_INTEGER n_queries = F.size();
137
138#ifdef DEBUG
139 const decltype(dFx.size()) size = n_queries;
140 Assert(dFx.size() == size && dFy.size() == size && X.size() == size &&
141 Y.size() == size,
142 dealii::ExcMessage("vector sizes do not match"));
143#endif
144
145 EOS_INTEGER error_code;
146 eos_Interpolate(&table_handles_[index],
147 &n_queries,
148 const_cast<EOS_REAL *>(X.data()), /* sigh */
149 const_cast<EOS_REAL *>(Y.data()), /* sigh */
150 F.data(),
151 dFx.data(),
152 dFy.data(),
153 &error_code);
154 }
155
156 private:
160 std::vector<EOS_INTEGER> material_ids_;
161 std::vector<EOS_INTEGER> table_types_;
162 EOS_INTEGER n_tables_;
163 /* Mutable so that we can call eospac functions from a const context. */
164 mutable std::vector<EOS_INTEGER> table_handles_;
165
170 void check_error_code(
171 EOS_INTEGER error_code,
172 const std::string &routine,
173 EOS_INTEGER i = std::numeric_limits<EOS_INTEGER>::max()) const
174 {
175 if (error_code != EOS_OK) {
176 std::array<EOS_CHAR, EOS_MaxErrMsgLen> error_message;
177 eos_GetErrorMessage(&error_code, error_message.data());
178
179 std::stringstream exception_body;
180 exception_body << "Error: " << routine;
181 if (i != std::numeric_limits<EOS_INTEGER>::max())
182 exception_body << " (table " << i << ")";
183 exception_body << ": " << error_code << " - " << error_message.data()
184 << std::flush;
185 AssertThrow(false, dealii::ExcMessage(exception_body.str()));
186 }
187 }
188
189 void check_tables(const std::string &routine) const
190 {
191 for (EOS_INTEGER i = 0; i < n_tables_; i++) {
192 EOS_INTEGER table_error_code = EOS_OK;
193 eos_GetErrorCode(&table_handles_[i], &table_error_code);
194 if (table_error_code != EOS_OK) {
195 std::array<EOS_CHAR, EOS_MaxErrMsgLen> error_message;
196 eos_GetErrorMessage(&table_error_code, error_message.data());
197
198 std::stringstream exception_body;
199 exception_body << "Error: " << routine << " (table " << i
200 << "): " << table_error_code << " - "
201 << error_message.data() << std::flush;
202
203 AssertThrow(false, dealii::ExcMessage(exception_body.str()));
204 }
205 }
206 }
207 };
208 } // namespace eospac
209#endif
210
211 namespace EquationOfStateLibrary
212 {
224 class Sesame : public EquationOfState
225 {
226 public:
231
232#ifdef WITH_EOSPAC
233 Sesame(const std::string &subsection)
234 : EquationOfState("sesame", subsection)
235 {
236 material_id_ = 5030;
237 this->add_parameter(
238 "material id", material_id_, "The Sesame Material ID");
239 }
240
241
242 double pressure(double rho, double e) const final
243 {
244 eospac_guard_.ensure_initialized([&]() {
245 this->set_up_database();
246 return true;
247 });
248
249 EOS_INTEGER index = 0;
250
251 double p, p_drho, p_de;
252 const double rho_scaled = rho / 1.0e3; // convert from Kg/m^3 to Mg/m^3
253 const double e_scaled = e / 1.0e6; // convert from J/kg to MJ/kg
254
255 eospac_interface_->interpolate_values(
256 index,
257 dealii::ArrayView<double>(&p, 1),
258 dealii::ArrayView<double>(&p_drho, 1),
259 dealii::ArrayView<double>(&p_de, 1),
260 dealii::ArrayView<const double>(&rho_scaled, 1),
261 dealii::ArrayView<const double>(&e_scaled, 1));
262
263 return 1.0e9 * p; // convert from GPa to Pa
264 }
265
266
267 void pressure(const dealii::ArrayView<double> &p,
268 const dealii::ArrayView<double> &rho,
269 const dealii::ArrayView<double> &e) const final
270 {
271 Assert(p.size() == rho.size() && rho.size() == e.size(),
272 dealii::ExcMessage("vectors have different size"));
273
274 eospac_guard_.ensure_initialized([&]() {
275 this->set_up_database();
276 return true;
277 });
278
279 EOS_INTEGER index = 0;
280
281 /* FIXME: this is not reentrant... */
282 thread_local static std::vector<double> p_drho;
283 thread_local static std::vector<double> p_de;
284 p_drho.resize(p.size());
285 p_de.resize(p.size());
286
287 // convert from Kg/m^3 to Mg/m^3
288 std::transform(std::begin(rho),
289 std::end(rho),
290 std::begin(rho),
291 [](double rho) { return rho / 1.0e3; });
292
293 // convert from J/kg to MJ/kg
294 std::transform(std::begin(e), //
295 std::end(e),
296 std::begin(e),
297 [](auto e) { return e / 1.0e6; });
298
299 eospac_interface_->interpolate_values(index,
300 p,
301 dealii::ArrayView<double>(p_drho),
302 dealii::ArrayView<double>(p_de),
303 rho,
304 e);
305
306 // convert from GPa to Pa
307 std::transform(std::begin(p), //
308 std::end(p),
309 std::begin(p),
310 [](auto it) { return it * 1.0e9; });
311 }
312
313
314 double specific_internal_energy(double rho, double p) const final
315 {
316 eospac_guard_.ensure_initialized([&]() {
317 this->set_up_database();
318 return true;
319 });
320
321 EOS_INTEGER index = 1;
322
323 double e, e_drho, e_dp;
324 const double rho_scaled = rho / 1.0e3; // convert from Kg/M^3 to Mg/M^3
325 const double p_scaled = p / 1.0e9; // convert from Pa to GPa
326
327 eospac_interface_->interpolate_values(
328 index,
329 dealii::ArrayView<double>(&e, 1),
330 dealii::ArrayView<double>(&e_drho, 1),
331 dealii::ArrayView<double>(&e_dp, 1),
332 dealii::ArrayView<const double>(&rho_scaled, 1),
333 dealii::ArrayView<const double>(&p_scaled, 1));
334
335 return 1.0e6 * e; // convert from MJ/kg to J/kg
336 }
337
338
339 void
340 specific_internal_energy(const dealii::ArrayView<double> &e,
341 const dealii::ArrayView<double> &rho,
342 const dealii::ArrayView<double> &p) const final
343 {
344 Assert(e.size() == rho.size() && rho.size() == p.size(),
345 dealii::ExcMessage("vectors have different size"));
346
347 eospac_guard_.ensure_initialized([&]() {
348 this->set_up_database();
349 return true;
350 });
351
352 EOS_INTEGER index = 1;
353
354 /* FIXME: this is not reentrant... */
355 thread_local static std::vector<double> e_drho;
356 thread_local static std::vector<double> e_dp;
357 e_drho.resize(e.size());
358 e_dp.resize(e.size());
359
360 // convert from Kg/m^3 to Mg/m^3
361 std::transform(std::begin(rho),
362 std::end(rho),
363 std::begin(rho),
364 [](double rho) { return rho / 1.0e3; });
365
366 // convert from Pa to GPa
367 std::transform(std::begin(p), //
368 std::end(p),
369 std::begin(p),
370 [](auto it) { return it / 1.0e9; });
371
372 eospac_interface_->interpolate_values(index,
373 e,
374 dealii::ArrayView<double>(e_drho),
375 dealii::ArrayView<double>(e_dp),
376 rho,
377 p);
378
379 // convert from MJ/kg to J/kg
380 std::transform(std::begin(e), //
381 std::end(e),
382 std::begin(e),
383 [](auto e) { return e * 1.0e6; });
384 }
385
386 /* FIXME: Implement table look up for temperature. Need to think about
387 * whether it should be T(rho, e) or T(rho, p). */
388
389 double temperature(double /*rho*/, double /*e*/) const final
390 {
391 eospac_guard_.ensure_initialized([&]() {
392 this->set_up_database();
393 return true;
394 });
395
396 AssertThrow(false, dealii::ExcInternalError());
397 __builtin_trap();
398 }
399
400
401 void temperature(const dealii::ArrayView<double> & /*temp*/,
402 const dealii::ArrayView<double> & /*rho*/,
403 const dealii::ArrayView<double> & /*e*/) const final
404 {
405 eospac_guard_.ensure_initialized([&]() {
406 this->set_up_database();
407 return true;
408 });
409
410 AssertThrow(false, dealii::ExcInternalError());
411 __builtin_trap();
412 }
413
414
415 double speed_of_sound(double /*rho*/, double /*e*/) const final
416 {
417 eospac_guard_.ensure_initialized([&]() {
418 this->set_up_database();
419 return true;
420 });
421
422 AssertThrow(false, dealii::ExcInternalError());
423 __builtin_trap();
424 }
425
426
427 void speed_of_sound(const dealii::ArrayView<double> & /*c*/,
428 const dealii::ArrayView<double> & /*rho*/,
429 const dealii::ArrayView<double> & /*e*/) const final
430 {
431 eospac_guard_.ensure_initialized([&]() {
432 this->set_up_database();
433 return true;
434 });
435
436 AssertThrow(false, dealii::ExcInternalError());
437 __builtin_trap();
438 }
439
440 private:
445
446 void set_up_database() const
447 {
448 AssertThrow(
449 std::filesystem::exists("sesameFilesDir.txt"),
450 dealii::ExcMessage(
451 "For EOSPAC to find the sesame database, we assume that there "
452 "exists a file named 'sesameFilesDir.txt' in the current "
453 "simulation directory. This file should list the path to the "
454 "sesame database. See the EOSPAC manual for more "
455 "information."));
456 const std::vector<std::tuple<EOS_INTEGER, eospac::TableType>> tables{
457 {material_id_, eospac::TableType::p_rho_e},
458 {material_id_, eospac::TableType::e_rho_p},
459 };
460
461 eospac_interface_ = std::make_unique<eospac::Interface>(tables);
462 }
463
464 Lazy<bool> eospac_guard_;
465 mutable std::unique_ptr<eospac::Interface> eospac_interface_;
466
468
472
473 EOS_INTEGER material_id_;
474
476
477#else /* WITHOUT_EOSPAC */
478
479 /* We do not have eospac support */
480 Sesame(const std::string &subsection)
481 : EquationOfState("Sesame", subsection)
482 {
483 }
484
485 static constexpr auto message =
486 "ryujin has to be configured with eospac support in order to use "
487 "the Sesame EOS database";
488
489 double pressure(double /*rho*/, double /*internal_energy*/) const final
490 {
491 AssertThrow(false, dealii::ExcMessage(message));
492 __builtin_trap();
493 }
494
495 double specific_internal_energy(double /*rho*/, double /*p*/) const final
496 {
497 AssertThrow(false, dealii::ExcMessage(message));
498 __builtin_trap();
499 }
500
501 double temperature(double /*rho*/, double /*e*/) const final
502 {
503 AssertThrow(false, dealii::ExcMessage(message));
504 __builtin_trap();
505 }
506
507 double speed_of_sound(double /*rho*/, double /*e*/) const final
508 {
509 AssertThrow(false, dealii::ExcMessage(message));
510 __builtin_trap();
511 }
512#endif
513 };
514 } // namespace EquationOfStateLibrary
515} // namespace ryujin
virtual double specific_internal_energy(double rho, double p) const =0
virtual double pressure(double rho, double e) const =0
virtual double speed_of_sound(double, double) const
virtual double temperature(double, double) const
double pressure(double, double) const final
double speed_of_sound(double, double) const final
double temperature(double, double) const final
double specific_internal_energy(double, double) const final