rizer.cantera_ext
C++ Cantera 1-D plasma extension (custom Domain1D models and solvers)
Toggle main menu visibility
Loading...
Searching...
No Matches
PropertyTable.h
Go to the documentation of this file.
1
// PropertyTable: an immutable 1D piecewise-linear lookup with endpoint
2
// clamping.
3
//
4
// The abscissa is whatever the caller tabulated against, not necessarily a
5
// temperature. The same container holds, in this extension:
6
// - sigma(T), kappa(T), P_rad(T) and the optional seed profile T_seed(r)
7
// of ThermalPlasmaColumn1D (steady LTE column);
8
// - the sigma(Te) and nu_m(Te) fallbacks of PlasmaCell, and CollisionModel's
9
// Maxwellian kernel Qbar(Te) together with the momentum-transfer cross
10
// section sigma(energy) it is built from;
11
// - kappa(T), kappa_e(T) and the initial radial profiles Tg(r), Te(r),
12
// Y_s(r), rho(r), u_r(r) of PlasmaChannel1D;
13
// - the applied field E(t) of the transient solver.
14
// eval()'s argument and return carry the units of whatever was tabulated;
15
// the class itself is unit-agnostic.
16
//
17
// Three shapes, decided in one place. fromTableOrScalar() maps a caller's
18
// (grid, values) pair onto exactly one of
19
// - a real table, from >= 2 matching points;
20
// - a constant, from one value against an empty or one-point grid;
21
// - an empty table, when neither is, whose eval() returns 0.0 -- which is
22
// how "this property is not configured" is spelled.
23
// Any other pair throws, naming the pair. It has to: an empty table is
24
// indistinguishable from a property that is genuinely zero everywhere, so
25
// returning one for an off-by-one in the caller's arrays would turn a setup
26
// error into a silently different physical problem rather than a failure.
27
//
28
// Ordering is checked at construction, and is non-decreasing rather than
29
// strictly increasing. A repeated knot is legal and is how a step profile is
30
// written (two values at one abscissa), which NUMERICS.md section "Validation ladder"'s P3
31
// initial condition needs. A decreasing knot throws, because eval() would not
32
// fail on one: std::upper_bound returns an arbitrary bracket there, and the
33
// interpolation weight leaves [0, 1] for the rest of the run.
34
//
35
// Outside [front, back] eval() clamps to the endpoint value: no
36
// extrapolation, no NaN, and no error either. The transient closures evaluate
37
// their tables through numeric/TableLookup.h, which refuses a state outside
38
// them, and PlasmaChannel1D checks its initial profiles at construction. Three
39
// lookups still clamp: ThermalPlasmaColumn1D's Newton residual (its converged
40
// column is checked after the solve instead), CollisionModel::meanCrossSection's
41
// sigma(energy), whose integral runs past any finite table by design, and the
42
// LTE column's seed profile.
43
//
44
// Nothing here reads a file. Every table is built by the caller, either from
45
// numpy arrays through bindings.cpp's makeTable() or from a Config pair
46
// through fromTableOrScalar().
47
48
#ifndef RIZER_PROPERTY_TABLE_H
49
#define RIZER_PROPERTY_TABLE_H
50
51
#include <vector>
52
#include <stdexcept>
53
#include <algorithm>
54
#include <string>
55
56
namespace
rizer
57
{
58
59
class
PropertyTable
60
{
61
public
:
62
PropertyTable
() =
default
;
63
70
PropertyTable
(std::vector<double> T, std::vector<double> values)
71
: m_T(std::move(T)), m_v(std::move(values))
72
{
73
if
(m_T.size() != m_v.size() || m_T.size() < 2)
74
{
75
throw std::invalid_argument(
76
"PropertyTable: T and values must have equal length >= 2"
);
77
}
78
// eval() brackets with std::upper_bound and clamps on front()/back(),
79
// both of which need the knots ordered. An unsorted grid does not
80
// fail there -- it returns a value off an arbitrary bracket, with the
81
// interpolation weight outside [0, 1], for the rest of the run.
82
//
83
// Non-decreasing, not strictly increasing: a REPEATED knot is how a
84
// step profile is written (two values at the same radius), which the
85
// step-function initial condition of NUMERICS.md section "Validation ladder" needs.
86
// Repeats cannot divide by zero below, because upper_bound returns the
87
// first knot strictly greater than T, so m_T[hi] > T >= m_T[hi-1]
88
// forces m_T[hi] != m_T[hi-1].
89
for (std::size_t i = 1; i < m_T.size(); i++)
90
{
91
if
(m_T[i] < m_T[i - 1])
92
{
93
throw
std::invalid_argument(
94
"PropertyTable: T must be non-decreasing, but T["
+
95
std::to_string(i) +
"] = "
+ std::to_string(m_T[i]) +
96
" is below T["
+ std::to_string(i - 1) +
97
"] = "
+ std::to_string(m_T[i - 1]) +
"."
);
98
}
99
}
100
}
101
105
static
PropertyTable
constant
(
double
value)
106
{
107
return
PropertyTable
({0.0, 1.0e9}, {value, value});
108
}
109
126
static
PropertyTable
fromTableOrScalar
(
const
std::vector<double> &x,
127
const
std::vector<double> &v,
128
const
char
*name =
"property table"
)
129
{
130
if
(x.size() >= 2 && x.size() == v.size())
131
return
PropertyTable
(x, v);
132
// A grid of two or more points against one value is the mismatched
133
// pair below, not a constant: dropping the grid would hand back a
134
// different property than the one tabulated.
135
if
(v.size() == 1 && x.size() <= 1)
136
return
PropertyTable::constant
(v[0]);
137
if
(x.empty() && v.empty())
138
return
PropertyTable
();
139
throw
std::invalid_argument(
140
std::string(
"PropertyTable: "
) +
141
name +
142
" has a grid of "
+
143
std::to_string(x.size()) +
144
" point(s) against "
+
145
std::to_string(v.size()) +
146
" value(s). They must be the same length and at least 2 points, or a "
147
"single value for a constant, or both empty to leave the property unset."
);
148
}
149
151
bool
empty
()
const
{
return
m_T.empty(); }
152
156
bool
covers
(
double
x)
const
157
{
158
return
!m_T.empty() && x >= m_T.front() && x <= m_T.back();
159
}
160
162
double
first
()
const
{
return
m_T.front(); }
163
165
double
last
()
const
{
return
m_T.back(); }
166
170
double
eval
(
double
T)
const
171
{
172
if
(m_T.empty())
173
{
174
return
0.0;
175
}
176
if
(T <= m_T.front())
177
{
178
return
m_v.front();
179
}
180
if
(T >= m_T.back())
181
{
182
return
m_v.back();
183
}
184
// upper_bound gives the first node strictly greater than T; subtract 1
185
// to get the left bracket of the containing interval.
186
auto
it = std::upper_bound(m_T.begin(), m_T.end(), T);
187
size_t
hi =
static_cast<
size_t
>
(it - m_T.begin());
188
size_t
lo = hi - 1;
189
double
w = (T - m_T[lo]) / (m_T[hi] - m_T[lo]);
190
return
m_v[lo] + w * (m_v[hi] - m_v[lo]);
191
}
192
193
private
:
194
std::vector<double> m_T;
195
std::vector<double> m_v;
196
};
197
198
}
// namespace rizer
199
200
#endif
rizer::PropertyTable::constant
static PropertyTable constant(double value)
A two-point constant table returning value for any T.
Definition
PropertyTable.h:105
rizer::PropertyTable::first
double first() const
First abscissa of a non-empty table, in the table's own units.
Definition
PropertyTable.h:162
rizer::PropertyTable::PropertyTable
PropertyTable()=default
rizer::PropertyTable::last
double last() const
Last abscissa of a non-empty table, in the table's own units.
Definition
PropertyTable.h:165
rizer::PropertyTable::covers
bool covers(double x) const
Whether eval() interpolates at x rather than holding an end value.
Definition
PropertyTable.h:156
rizer::PropertyTable::eval
double eval(double T) const
Linearly interpolated value at T; clamped to the table endpoints.
Definition
PropertyTable.h:170
rizer::PropertyTable::empty
bool empty() const
True for a default-constructed (empty) table; eval() returns 0.0.
Definition
PropertyTable.h:151
rizer::PropertyTable::PropertyTable
PropertyTable(std::vector< double > T, std::vector< double > values)
Construct from parallel T (non-decreasing, [K]) and value arrays.
Definition
PropertyTable.h:70
rizer::PropertyTable::fromTableOrScalar
static PropertyTable fromTableOrScalar(const std::vector< double > &x, const std::vector< double > &v, const char *name="property table")
Build a table from a grid/value pair, a single scalar, or neither.
Definition
PropertyTable.h:126
rizer
Definition
ElectronReactions.cpp:11
rizer
cantera_ext
numeric
PropertyTable.h
Generated by
1.18.0