rizer.cantera_ext
C++ Cantera 1-D plasma extension (custom Domain1D models and solvers)
Loading...
Searching...
No Matches
PropertyTable.h
Go to the documentation of this file.
1// PropertyTable: a 1D temperature-indexed lookup with linear interpolation.
2//
3// This is the pluggable property backend used by ThermalPlasmaColumn1D for
4// sigma(T), kappa(T), P_rad(T), and the optional seed profile T_seed(r).
5// Today it is always fed rizer's tabulated LTE data (the same CSVs that
6// ElenbaasHeller uses), so the numerical and analytical solutions share
7// *identical* property models and any residual difference (~1–3 % in T_center
8// and current for H2) is purely the analytical linearisation error.
9//
10// Design contract:
11// eval(T) -> linearly interpolated value, clamped to the table endpoints
12// outside [T_min, T_max] (no extrapolation, no NaN).
13// empty() -> true for a default-constructed table; eval returns 0.0.
14// Used by the P_rad slot when radiation is disabled.
15//
16// Future: a Cantera-native backend (equilibrate("TP") + IonGasTransport for
17// sigma/kappa; SRI/JANAF for ionization equilibrium) can satisfy the same
18// eval(T) contract without touching ThermalPlasmaColumn1D. Note that built-in
19// Cantera plasma mechanisms do not cover H2 LTE thermal ionisation, so that
20// path needs a suitable mechanism file.
21
22#ifndef RIZER_PROPERTY_TABLE_H
23#define RIZER_PROPERTY_TABLE_H
24
25#include <vector>
26#include <stdexcept>
27#include <algorithm>
28
29namespace rizer {
30
32public:
33 PropertyTable() = default;
34
37 PropertyTable(std::vector<double> T, std::vector<double> values)
38 : m_T(std::move(T)), m_v(std::move(values))
39 {
40 if (m_T.size() != m_v.size() || m_T.size() < 2) {
41 throw std::invalid_argument(
42 "PropertyTable: T and values must have equal length >= 2");
43 }
44 }
45
48 static PropertyTable constant(double value) {
49 return PropertyTable({0.0, 1.0e9}, {value, value});
50 }
51
53 bool empty() const { return m_T.empty(); }
54
57 double eval(double T) const {
58 if (m_T.empty()) {
59 return 0.0;
60 }
61 if (T <= m_T.front()) {
62 return m_v.front();
63 }
64 if (T >= m_T.back()) {
65 return m_v.back();
66 }
67 // upper_bound gives the first node strictly greater than T; subtract 1
68 // to get the left bracket of the containing interval.
69 auto it = std::upper_bound(m_T.begin(), m_T.end(), T);
70 size_t hi = static_cast<size_t>(it - m_T.begin());
71 size_t lo = hi - 1;
72 double w = (T - m_T[lo]) / (m_T[hi] - m_T[lo]);
73 return m_v[lo] + w * (m_v[hi] - m_v[lo]);
74 }
75
76private:
77 std::vector<double> m_T;
78 std::vector<double> m_v;
79};
80
81} // namespace rizer
82
83#endif
static PropertyTable constant(double value)
A two-point constant table returning value for any T.
double eval(double T) const
Linearly interpolated value at T; clamped to the table endpoints.
bool empty() const
True for a default-constructed (empty) table; eval() returns 0.0.
PropertyTable(std::vector< double > T, std::vector< double > values)
Construct from parallel T (strictly increasing, [K]) and value arrays.