ryujin 2.1.1 revision 336b16a72e829721302c626ec7071b92032b8248
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 by the ryujin authors
4//
5
6#pragma once
7
8#include <compile_time_options.h>
9
10#include "equation_of_state.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
22namespace ryujin
23{
24#ifdef WITH_EOSPAC
31 namespace eospac
32 {
38 enum class TableType : EOS_INTEGER {
43 p_rho_e = EOS_Pt_DUt,
48 e_rho_p = EOS_Ut_DPt,
49 };
50
51 class Interface
52 {
53 public:
60 Interface(const std::vector<std::tuple<EOS_INTEGER, TableType>> &tables)
61 {
62 n_tables_ = tables.size();
63
64 std::transform(std::begin(tables),
65 std::end(tables),
66 std::back_inserter(material_ids_),
67 [](const auto &it) { return std::get<0>(it); });
68
69 std::transform(std::begin(tables),
70 std::end(tables),
71 std::back_inserter(table_types_),
72 [](const auto &it) {
73 return static_cast<EOS_INTEGER>(std::get<1>(it));
74 });
75
76 table_handles_.resize(n_tables_);
77
78 /* create tables: */
79
80 EOS_INTEGER error_code;
81 eos_CreateTables(&n_tables_,
82 table_types_.data(),
83 material_ids_.data(),
84 table_handles_.data(),
85 &error_code);
86 check_tables("eos_CreateTables");
87
88 /* set table options: */
89
90 for (EOS_INTEGER i = 0; i < n_tables_; i++) {
91 // FIXME: refactor into options
92 eos_SetOption(
93 &table_handles_[i], &EOS_SMOOTH, EOS_NullPtr, &error_code);
94 check_error_code(error_code, "eos_SetOption", i);
95 }
96
97 /* load tables: */
98
99 eos_LoadTables(&n_tables_, table_handles_.data(), &error_code);
100 check_tables("eos_LoadTables");
101 }
102
106 ~Interface() noexcept
107 {
108 EOS_INTEGER error_code;
109 eos_DestroyTables(&n_tables_, table_handles_.data(), &error_code);
110 }
111
116 inline DEAL_II_ALWAYS_INLINE void
117 interpolate_values(const EOS_INTEGER &index,
118 const dealii::ArrayView<EOS_REAL> &F,
119 const dealii::ArrayView<EOS_REAL> &dFx,
120 const dealii::ArrayView<EOS_REAL> &dFy,
121 const dealii::ArrayView<const EOS_REAL> &X,
122 const dealii::ArrayView<const EOS_REAL> &Y)
123 {
124 Assert(index >= 0 && index < n_tables_,
125 dealii::ExcMessage("Table index out of range"));
126
127 EOS_INTEGER n_queries = F.size();
128
129 Assert(dFx.size() == n_queries && dFy.size() == n_queries &&
130 X.size() == n_queries && Y.size() == n_queries,
131 dealii::ExcMessage("vector sizes do not match"));
132
133 EOS_INTEGER error_code;
134 eos_Interpolate(&table_handles_[index],
135 &n_queries,
136 const_cast<EOS_REAL *>(X.data()), /* sigh */
137 const_cast<EOS_REAL *>(Y.data()), /* sigh */
138 F.data(),
139 dFx.data(),
140 dFy.data(),
141 &error_code);
142 }
143
144 private:
148 std::vector<EOS_INTEGER> material_ids_;
149 std::vector<EOS_INTEGER> table_types_;
150 EOS_INTEGER n_tables_;
151 /* Mutable so that we can call eospac functions from a const context. */
152 mutable std::vector<EOS_INTEGER> table_handles_;
153
158 void check_error_code(
159 EOS_INTEGER error_code,
160 const std::string &routine,
161 EOS_INTEGER i = std::numeric_limits<EOS_INTEGER>::max()) const
162 {
163 if (error_code != EOS_OK) {
164 std::array<EOS_CHAR, EOS_MaxErrMsgLen> error_message;
165 eos_GetErrorMessage(&error_code, error_message.data());
166
167 std::stringstream exception_body;
168 exception_body << "Error: " << routine;
169 if (i != std::numeric_limits<EOS_INTEGER>::max())
170 exception_body << " (table " << i << ")";
171 exception_body << ": " << error_code << " - " << error_message.data()
172 << std::flush;
173 AssertThrow(false, dealii::ExcMessage(exception_body.str()));
174 }
175 }
176
177 void check_tables(const std::string &routine) const
178 {
179 for (EOS_INTEGER i = 0; i < n_tables_; i++) {
180 EOS_INTEGER table_error_code = EOS_OK;
181 eos_GetErrorCode(&table_handles_[i], &table_error_code);
182 if (table_error_code != EOS_OK) {
183 std::array<EOS_CHAR, EOS_MaxErrMsgLen> error_message;
184 eos_GetErrorMessage(&table_error_code, error_message.data());
185
186 std::stringstream exception_body;
187 exception_body << "Error: " << routine << " (table " << i
188 << "): " << table_error_code << " - "
189 << error_message.data() << std::flush;
190
191 AssertThrow(false, dealii::ExcMessage(exception_body.str()));
192 }
193 }
194 }
195 };
196 } // namespace eospac
197#endif
198
199 namespace EquationOfStateLibrary
200 {
212 class Sesame : public EquationOfState
213 {
214 public:
215#ifdef WITH_EOSPAC
216 Sesame(const std::string &subsection)
217 : EquationOfState("sesame", subsection)
218 {
219 material_id_ = 5030;
220 this->add_parameter(
221 "material id", material_id_, "The Sesame Material ID");
222
223 this->prefer_vector_interface_ = true;
224
225 const auto set_up_database = [&]() {
226 const std::vector<std::tuple<EOS_INTEGER, eospac::TableType>> tables{
227 {material_id_, eospac::TableType::p_rho_e},
228 {material_id_, eospac::TableType::e_rho_p},
229 };
230
231 eospac_interface_ = std::make_unique<eospac::Interface>(tables);
232 };
233
234 this->parse_parameters_call_back.connect(set_up_database);
235 }
236
237
238 double pressure(double rho, double e) const final
239 {
240 EOS_INTEGER index = 0;
241
242 double p, p_drho, p_de;
243 const double rho_scaled = rho / 1.0e3; // convert from Kg/m^3 to Mg/m^3
244 const double e_scaled = e / 1.0e6; // convert from J/kg to MJ/kg
245
246 eospac_interface_->interpolate_values(
247 index,
248 dealii::ArrayView<double>(&p, 1),
249 dealii::ArrayView<double>(&p_drho, 1),
250 dealii::ArrayView<double>(&p_de, 1),
251 dealii::ArrayView<const double>(&rho_scaled, 1),
252 dealii::ArrayView<const double>(&e_scaled, 1));
253
254 return 1.0e9 * p; // convert from GPa to Pa
255 }
256
257
258 void pressure(const dealii::ArrayView<double> &p,
259 const dealii::ArrayView<double> &rho,
260 const dealii::ArrayView<double> &e) const final
261 {
262 Assert(p.size() == rho.size() && rho.size() == e.size(),
263 dealii::ExcMessage("vectors have different size"));
264
265 EOS_INTEGER index = 0;
266
267 /* FIXME: this is not reentrant... */
268 thread_local static std::vector<double> p_drho;
269 thread_local static std::vector<double> p_de;
270 p_drho.resize(p.size());
271 p_de.resize(p.size());
272
273 // convert from Kg/m^3 to Mg/m^3
274 std::transform(std::begin(rho),
275 std::end(rho),
276 std::begin(rho),
277 [](double rho) { return rho / 1.0e3; });
278
279 // convert from J/kg to MJ/kg
280 std::transform(std::begin(e), //
281 std::end(e),
282 std::begin(e),
283 [](auto e) { return e / 1.0e6; });
284
285 eospac_interface_->interpolate_values(index,
286 p,
287 dealii::ArrayView<double>(p_drho),
288 dealii::ArrayView<double>(p_de),
289 rho,
290 e);
291
292 // convert from GPa to Pa
293 std::transform(std::begin(p), //
294 std::end(p),
295 std::begin(p),
296 [](auto it) { return it * 1.0e9; });
297 }
298
299
300 double specific_internal_energy(double rho, double p) const final
301 {
302 EOS_INTEGER index = 1;
303
304 double e, e_drho, e_dp;
305 const double rho_scaled = rho / 1.0e3; // convert from Kg/M^3 to Mg/M^3
306 const double p_scaled = p / 1.0e9; // convert from Pa to GPa
307
308 eospac_interface_->interpolate_values(
309 index,
310 dealii::ArrayView<double>(&e, 1),
311 dealii::ArrayView<double>(&e_drho, 1),
312 dealii::ArrayView<double>(&e_dp, 1),
313 dealii::ArrayView<const double>(&rho_scaled, 1),
314 dealii::ArrayView<const double>(&p_scaled, 1));
315
316 return 1.0e6 * e; // convert from MJ/kg to J/kg
317 }
318
319
320 void
321 specific_internal_energy(const dealii::ArrayView<double> &e,
322 const dealii::ArrayView<double> &rho,
323 const dealii::ArrayView<double> &p) const final
324 {
325 Assert(e.size() == rho.size() && rho.size() == p.size(),
326 dealii::ExcMessage("vectors have different size"));
327
328 EOS_INTEGER index = 1;
329
330 /* FIXME: this is not reentrant... */
331 thread_local static std::vector<double> e_drho;
332 thread_local static std::vector<double> e_dp;
333 e_drho.resize(e.size());
334 e_dp.resize(e.size());
335
336 // convert from Kg/m^3 to Mg/m^3
337 std::transform(std::begin(rho),
338 std::end(rho),
339 std::begin(rho),
340 [](double rho) { return rho / 1.0e3; });
341
342 // convert from Pa to GPa
343 std::transform(std::begin(p), //
344 std::end(p),
345 std::begin(p),
346 [](auto it) { return it / 1.0e9; });
347
348 eospac_interface_->interpolate_values(index,
349 e,
350 dealii::ArrayView<double>(e_drho),
351 dealii::ArrayView<double>(e_dp),
352 rho,
353 p);
354
355 // convert from MJ/kg to J/kg
356 std::transform(std::begin(e), //
357 std::end(e),
358 std::begin(e),
359 [](auto e) { return e * 1.0e6; });
360 }
361
362 /* FIXME: Implement table look up for temperature. Need to think about
363 * whether it should be T(rho, e) or T(rho, p). */
364 double temperature(double /*rho*/, double /*e*/) const final
365 {
366 __builtin_trap();
367 }
368
369 void temperature(const dealii::ArrayView<double> & /*temp*/,
370 const dealii::ArrayView<double> & /*rho*/,
371 const dealii::ArrayView<double> & /*e*/) const final
372 {
373 __builtin_trap();
374 }
375
376 double speed_of_sound(double /*rho*/, double /*e*/) const final
377 {
378 __builtin_trap();
379 }
380
381
382 void speed_of_sound(const dealii::ArrayView<double> & /*c*/,
383 const dealii::ArrayView<double> & /*rho*/,
384 const dealii::ArrayView<double> & /*e*/) const final
385 {
386 __builtin_trap();
387 }
388
389 private:
390 EOS_INTEGER material_id_;
391 std::unique_ptr<eospac::Interface> eospac_interface_;
392
393#else /* WITHOUT_EOSPAC */
394
395 /* We do not have eospac support */
396 Sesame(const std::string &subsection)
397 : EquationOfState("Sesame", subsection)
398 {
399 }
400
401 static constexpr auto message =
402 "ryujin has to be configured with eospac support in order to use "
403 "the Sesame EOS database";
404
405 double pressure(double /*rho*/, double /*internal_energy*/) const final
406 {
407 AssertThrow(false, dealii::ExcMessage(message));
408 __builtin_trap();
409 }
410
411 double specific_internal_energy(double /*rho*/, double /*p*/) const final
412 {
413 AssertThrow(false, dealii::ExcMessage(message));
414 __builtin_trap();
415 }
416
417 double temperature(double /*rho*/, double /*e*/) const final
418 {
419 AssertThrow(false, dealii::ExcMessage(message));
420 __builtin_trap();
421 }
422
423 double speed_of_sound(double /*rho*/, double /*e*/) const final
424 {
425 AssertThrow(false, dealii::ExcMessage(message));
426 __builtin_trap();
427 }
428#endif
429 };
430 } // namespace EquationOfStateLibrary
431} // namespace ryujin
EquationOfState(const std::string &name, const std::string &subsection)
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