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