chombo-discharge
Loading...
Searching...
No Matches
CD_LookupTable1DImplem.H
1/* chombo-discharge
2 * Copyright © 2021 SINTEF Energy Research.
3 * Please refer to Copyright.txt and LICENSE in the chombo-discharge root directory.
4 */
5
12#ifndef CD_LookupTableImplem_H
13#define CD_LookupTableImplem_H
14
15// Std includes
16#include <algorithm>
17#include <math.h>
18#include <iomanip>
19#include <fstream>
20#include <limits>
21
22// Our includes
23#include <CD_LookupTable1D.H>
24
25template <typename T, size_t N, typename I>
30
31template <typename T, size_t N, typename I>
32inline void
34{
35 m_isGood = false;
36 m_grid = std::make_tuple(LookupTable::Spacing::Uniform, 0, -1.0, -1.0, -1.0);
37 m_rangeStrategyLo = LookupTable::OutOfRangeStrategy::Constant;
38 m_rangeStrategyHi = LookupTable::OutOfRangeStrategy::Constant;
39
40 m_rawData.clear();
41 m_structuredData.clear();
42}
43
44template <typename T, size_t N, typename I>
45template <typename... Ts>
46inline void
49 std::array<T, sizeof...(Ts)> arr = {(T)x...};
50
51 m_rawData.emplace_back(arr);
52}
53
54template <typename T, size_t N, typename I>
55inline void
58 m_rawData.emplace_back(x);
59}
60
61template <typename T, size_t N, typename I>
62inline void
63LookupTable1D<T, N, I>::swap(const size_t a_columnOne, const size_t a_columnTwo) noexcept
64{
65 for (auto& r : m_rawData) {
66 const auto tmp = r[a_columnOne];
67
69 r[a_columnTwo] = tmp;
70 }
71
72 for (auto& r : m_structuredData) {
73 const auto tmp = r[a_columnOne];
74
76 r[a_columnTwo] = tmp;
77 }
78
79 if (m_isGood) {
80 if (a_columnOne == std::get<4>(m_grid)) {
81 std::get<4>(m_grid) = a_columnOne;
82 }
83 else if (a_columnTwo == std::get<4>(m_grid)) {
84 std::get<4>(m_grid) = a_columnTwo;
85 }
86 }
87}
88
89template <typename T, size_t N, typename I>
90template <size_t K>
91inline void
93{
94 for (auto& r : m_rawData) {
95 r[K] *= a_scale;
96 }
97
98 for (auto& r : m_structuredData) {
99 r[K] *= a_scale;
101
102 if (m_isGood && K == std::get<2>(m_grid)) {
103 std::get<4>(m_grid) *= a_scale;
104 }
105}
106
107template <typename T, size_t N, typename I>
108inline void
109LookupTable1D<T, N, I>::truncate(const T& a_min, const T& a_max, const size_t a_column) noexcept
110{
112
113 for (const auto& xy : m_rawData) {
114 if (xy[a_column] >= a_min && xy[a_column] <= a_max) {
115 truncatedData.emplace_back(xy);
116 }
117 }
118
119 m_rawData = truncatedData;
120}
121
122template <typename T, size_t N, typename I>
123inline void
128
129template <typename T, size_t N, typename I>
130inline void
132{
133 m_rangeStrategyHi = a_strategy;
134}
135
136template <typename T, size_t N, typename I>
137inline void
139 const size_t& a_numPoints,
141{
142
143 const std::string baseError = "LookupTable1D<T,N,I>::prepareTable";
144
145 if (a_numPoints <= 1) {
146 throw std::runtime_error(baseError + " - must have 'a_numPoints > 1'");
147 }
148
149 // Sort the raw data along the specified column.
153 std::sort(sortedData.begin(),
154 sortedData.end(),
155 [i = a_independentVariable](const Values& X1, const Values& X2) -> bool {
156 return X1[i] < X2[i];
157 });
158
159 // Set up the 1D grid
160 T xmin;
161 T xmax;
162 T delta;
163
168
169 switch (a_spacing) {
170 case LookupTable::Spacing::Uniform: {
171 delta = (xmax - xmin) / (a_numPoints - 1);
172
173 for (size_t i = 0; i < a_numPoints; i++) {
174 coords[i] = xmin + i * delta;
175 }
176
177 break;
178 }
179 case LookupTable::Spacing::Exponential: {
180 if (xmin <= std::numeric_limits<T>::min()) {
181 throw std::runtime_error(baseError + " - but must have all 'x > 0.0' for logarithmic grid");
182 }
183
184 else {
185 delta = log10(xmax / xmin) / (a_numPoints - 1);
186
187 for (int i = 0; i < a_numPoints; i++) {
188 coords[i] = xmin * std::pow(10.0, i * delta);
189 }
190
191 break;
192 }
193 }
194 default: {
195 throw std::runtime_error(baseError + " - logic bust (unsupported table spacing system)");
196
197 break;
198 }
199 }
200
201 m_structuredData.clear();
202
203 size_t curRow = 0;
204
205 for (const auto& x : coords) {
206 while (curRow < m_rawData.size() - 1) {
207 const auto& row1 = m_rawData[curRow];
208 const auto& row2 = m_rawData[curRow + 1];
209
210 const auto x1 = row1[a_independentVariable];
211 const auto x2 = row2[a_independentVariable];
212
213 if (x >= x1 && x <= x2) {
214 const auto t = (x - x1) / (x2 - x1);
215
217
218 for (size_t i = 0; i <= N; i++) {
219 interpRow[i] = row1[i] + t * (row2[i] - row1[i]);
220 }
221
222 m_structuredData.emplace_back(interpRow);
223
224 break;
225 }
226
227 curRow++;
228 }
229 }
230
232
233 m_isGood = true;
234}
235
236template <typename T, size_t N, typename I>
239{
240 return (m_rawData);
242
243template <typename T, size_t N, typename I>
246{
247 return (m_structuredData);
249
250template <typename T, size_t N, typename I>
253{
254 return (m_rawData);
255}
256
257template <typename T, size_t N, typename I>
260{
261 return (m_structuredData);
262}
263
264template <typename T, size_t N, typename I>
265inline void
267{
268 this->writeToFile(a_file, m_rawData);
269}
270
271template <typename T, size_t N, typename I>
272inline void
274{
275 this->writeToFile(a_file, m_structuredData);
276}
277
278template <typename T, size_t N, typename I>
279inline void
281{
282 this->outputData(a_ostream, m_rawData);
283}
284
285template <typename T, size_t N, typename I>
286inline void
288{
289 this->outputData(a_ostream, m_structuredData);
290}
291
292template <typename T, size_t N, typename I>
293inline void
295 const std::vector<std::array<T, N + 1>>& a_data) const noexcept
296{
297 for (const auto& r : a_data) {
298 for (const auto& c : r) {
299 a_ostream << std::left << std::setw(14) << c;
300 }
301 a_ostream << "\n";
302 }
303}
304
305template <typename T, size_t N, typename I>
306inline void
308 const std::vector<std::array<T, N + 1>>& a_data) const noexcept
309{
310
311#ifdef CH_MPI
312 if (procID() == 0) {
313#endif
315
316 file.open(a_file);
317 this->outputData(file, a_data);
318 file.close();
319#ifdef CH_MPI
320 }
321#endif
322}
323
324template <typename T, size_t N, typename I>
325inline size_t
327{
329 const T& x0 = std::get<2>(m_grid);
330 const T& delta = std::get<4>(m_grid);
331
332 size_t idxLo;
333
334 switch (spacing) {
335 case LookupTable::Spacing::Uniform: {
336 idxLo = std::floor((a_x - x0) / delta);
337
338 break;
339 }
340 case LookupTable::Spacing::Exponential: {
341 idxLo = std::floor(log10(a_x / x0) / delta);
342
343 break;
344 }
345 default: {
346 throw std::runtime_error("LookupTable1D<T,N,I>::getIndexLo - logic bust (unsupported table spacing system)");
347 }
348 }
349
350 return idxLo;
351}
352
353template <typename T, size_t N, typename I>
356{
357 if (!m_isGood) {
358 throw std::runtime_error("LookupTable1D<T, N, I>::interpolate(array) but need to call 'prepareTable first'");
359 }
360
361 const size_t& indVar = std::get<1>(m_grid);
362 const T& xmin = std::get<2>(m_grid);
363 const T& xmax = std::get<3>(m_grid);
364
366
367 if (a_x < xmin) {
368 switch (m_rangeStrategyLo) {
369 case LookupTable::OutOfRangeStrategy::Constant: {
370 ret = m_structuredData.front();
371
372 break;
373 }
374 case LookupTable::OutOfRangeStrategy::Interpolate: {
375 const T diffDx = m_structuredData[1][indVar] - m_structuredData[0][indVar];
376 const T extrapDx = m_structuredData[0][indVar] - a_x;
377
378 ret = m_structuredData.front();
379
380 for (size_t i = 0; i < N + 1; i++) {
381 const T slope = (m_structuredData[1][i] - m_structuredData[0][i]) / diffDx;
382
383 ret[i] -= slope * extrapDx;
384 }
385
386 break;
387 }
388 default: {
389 throw std::runtime_error("LookupTable1D<T, N, I>::interpolate(array) unsupported range strategy at low end");
390
391 break;
392 }
393 }
394 }
395 else if (a_x > xmax) {
396 switch (m_rangeStrategyHi) {
397 case LookupTable::OutOfRangeStrategy::Constant: {
398 ret = m_structuredData.back();
399
400 break;
401 }
402 case LookupTable::OutOfRangeStrategy::Interpolate: {
403 const size_t& size = m_structuredData.size();
404
405 const T diffDx = m_structuredData[size - 1][indVar] - m_structuredData[size - 2][indVar];
406 const T extrapDx = a_x - m_structuredData[size - 1][indVar];
407
408 ret = m_structuredData.back();
409
410 for (size_t i = 0; i < N + 1; i++) {
411 const T slope = (m_structuredData[size - 1][i] - m_structuredData[size - 2][i]) / diffDx;
412
413 ret[i] += slope * extrapDx;
414 }
415
416 break;
417 }
418 default: {
419 throw std::runtime_error("LookupTable1D<T, N, I>::interpolate(array) unsupported range strategy at low end");
420
421 break;
422 }
423 }
424 }
425 else {
426 const size_t idx = this->getIndexLo(a_x);
427
428 const T diffDx = m_structuredData[idx + 1][indVar] - m_structuredData[idx][indVar];
429 const T interpDx = a_x - m_structuredData[idx][indVar];
430
431 ret = m_structuredData[idx];
432
433 for (size_t i = 0; i < N + 1; i++) {
434 const T slope = (m_structuredData[idx + 1][i] - m_structuredData[idx][i]) / diffDx;
435
436 ret[i] += slope * interpDx;
437 }
438 }
439
440 return ret;
441}
442
443template <typename T, size_t N, typename I>
444template <size_t K>
445inline T
447{
448 return std::get<K>(this->interpolate(a_x));
449}
450
451template <typename T, size_t N, typename I>
452template <size_t M, typename... Ts>
455{
456 static_assert(M <= N, "LookupTable1D<T, N,I>::slice must have have 'M <= N'");
457
458 std::array<size_t, sizeof...(Ts)> arr = {(size_t)a_columns...};
459
461
462 for (const auto& r : m_rawData) {
464
465 for (size_t i = 0; i < M + 1; i++) {
466 slicedData[i] = r[arr[i]];
467 }
468
469 ret.addData(slicedData);
470 }
471
472 return ret;
473}
474
475#endif
Declaration of a lookup table in one independent variable.
OutOfRangeStrategy
Strategy for obtaining data when requesting data that is out of range. We can use either constant (i....
Definition CD_LookupTable.H:29
Spacing
Enum for classifying the coordinate system.
Definition CD_LookupTable.H:38
std::vector< std::array< T, N+1 > > & getStructuredData() noexcept
Access function for structured data.
Definition CD_LookupTable1DImplem.H:245
T interpolate(const T &a_x) const
Interpolation function for specific dependent variable K.
Definition CD_LookupTable1DImplem.H:446
void addData(const Ts &... x) noexcept
Add entry.
Definition CD_LookupTable1DImplem.H:47
void setRangeStrategyLo(const LookupTable::OutOfRangeStrategy &a_strategy) noexcept
Set the out-of-range strategy on the low end.
Definition CD_LookupTable1DImplem.H:124
size_t getIndexLo(const T &a_x) const
Get the lower index that brackets the input variable between two data points in the structured grid.
Definition CD_LookupTable1DImplem.H:326
void swap(const size_t a_columnOne, const size_t a_columnTwo) noexcept
Utility function for swapping columns.
Definition CD_LookupTable1DImplem.H:63
void truncate(const T &a_min, const T &a_max, const size_t a_column) noexcept
Utility function for truncating raw data along one of the variables (either dependent or independent)...
Definition CD_LookupTable1DImplem.H:109
void setRangeStrategyHi(const LookupTable::OutOfRangeStrategy &a_strategy) noexcept
Set the out-of-range strategy on the high end.
Definition CD_LookupTable1DImplem.H:131
LookupTable1D() noexcept
Default constructor. Creates a table without any entries.
Definition CD_LookupTable1DImplem.H:26
void writeRawData(const std::string &a_file) const noexcept
Dump raw table data to file.
Definition CD_LookupTable1DImplem.H:266
void outputStructuredData(std::ostream &a_ostream=std::cout) const noexcept
Dump structured table data to file.
Definition CD_LookupTable1DImplem.H:287
void reset() noexcept
Reset everything.
Definition CD_LookupTable1DImplem.H:33
void outputRawData(std::ostream &a_ostream=std::cout) const noexcept
Dump raw table data to output stream.
Definition CD_LookupTable1DImplem.H:280
void prepareTable(const size_t &a_independentVariable, const size_t &a_numPoints, const LookupTable::Spacing &a_spacing)
Turn the raw data into uniform data for fast lookup.
Definition CD_LookupTable1DImplem.H:138
void scale(const T &a_scale) noexcept
Utility function which scales one of the columns (either dependent or independent variable)
Definition CD_LookupTable1DImplem.H:92
void writeToFile(const std::string &a_file, const std::vector< std::array< T, N+1 > > &a_data) const noexcept
Utility function for outputting data to a file.
Definition CD_LookupTable1DImplem.H:307
void writeStructuredData(const std::string &a_file) const noexcept
Dump structured table data to file.
Definition CD_LookupTable1DImplem.H:273
LookupTable1D< T, M, I > slice(const Ts &... a_columns) const noexcept
Slice this table, keeping only the user-specified columns.
Definition CD_LookupTable1DImplem.H:454
void outputData(std::ostream &a_ostream, const std::vector< std::array< T, N+1 > > &a_data) const noexcept
Utility function for outputting data.
Definition CD_LookupTable1DImplem.H:294
std::vector< std::array< T, N+1 > > & getRawData() noexcept
Access function for raw data.
Definition CD_LookupTable1DImplem.H:238
Base class for a tracer particle solver. This solver can advance particles in a pre-defined velocity ...
Definition CD_TracerParticleSolver.H:37
TracerParticleSolver()
Default constructor.
Definition CD_TracerParticleSolverImplem.H:25