TrioCFD 1.9.9_beta
TrioCFD documentation
Loading...
Searching...
No Matches
Table.cpp
1/****************************************************************************
2* Copyright (c) 2025, CEA
3* All rights reserved.
4*
5* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
6* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
7* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
8* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
9*
10* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
11* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
12* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
13*
14*****************************************************************************/
15
16#include <Table.h>
17#include <utility>
18
19Implemente_instanciable_sans_constructeur_ni_destructeur(Table,"Table",Objet_U);
20
21
22/*! @brief Default constructor. Creates an empty table.
23 *
24 */
25Table::Table() : les_valeurs() , les_parametres() { }
26
28{
29 (*this)=t;
30}
31
32// Reads an analytic expression depending on the values (val) of a parameter field.
33// isf is set to 1.
34Entree& Table::lire_f(Entree& is, const int nb_comp)
35{
36 isf=1;
37 Nom tmp;
38
39 VECT(Parser_U)& fval=fonction();
40 fval.dimensionner(nb_comp);
41 for (int i = 0; i < nb_comp; i++)
42 {
43 is >> tmp;
44 Cerr << "Reading and interpretation of the function " << tmp << finl;
45 fval[i].setNbVar(1);
46 fval[i].setString(tmp);
47 fval[i].addVar("val");
48 fval[i].parseString();
49 }
50 Cerr << "Interpretation of the function " << tmp << " OK" << finl;
51
52 return is;
53}
54
55// Reads an analytic expression depending on the values (val) of a parameter field,
56// on space (x, y, z) and on time (t).
57// isf is set to 2.
58Entree& Table::lire_fxyzt(Entree& is,const int dim)
59{
60 isf=2;
61 Nom tmp;
62
63 VECT(Parser_U)& fval=fonction();
64 fval.dimensionner(dim);
65 for (int i=0; i<dim; i++)
66 {
67 is >> tmp;
68 fval[i].setNbVar(5);
69 fval[i].setString(tmp);
70 fval[i].addVar("t");
71 fval[i].addVar("x");
72 fval[i].addVar("y");
73 fval[i].addVar("z");
74 fval[i].addVar("val");
75 fval[i].parseString();
76 }
77 Cerr << "Interpretation of the function " << tmp << " OK" << finl;
78
79
80 return is;
81}
82
83/*! @brief Writes only the type and name of the object to an output stream.
84 *
85 * @param (Sortie& s) the output stream to use
86 * @return (Sortie&) the modified output stream
87 */
89{
90 return s << que_suis_je() << " " << le_nom();
91}
92
93
94
95/*! @brief Reads the parameters and values of the table from an input stream.
96 *
97 * @param (Entree& s) the input stream to use
98 * @return (Entree&) the modified input stream
99 */
101{
102 s >> les_parametres;
103 s >> les_valeurs;
104 return s ;
105}
106
107// Computes the n-linear interpolant of data at point x inside a hyper-rectangle defined by gridpoints.
108// The shapes should be (n) for x, (n, 2) for gridpoints and (2, 2, 2, ..., 2) n times for data (stored as a single vector here)
109double nlinear_interpolation(const std::vector<double>& x, const std::vector<std::pair<double, double>>& gridpoints, const std::vector<double>& data)
110{
111 const int n = (int)x.size();
112
113 // Build the weights for each vertex of the hyper-rectangle
114 std::vector<double> weight(n);
115 for (int i = 0; i < n; i++)
116 weight[i] = std::min(1.0, std::max(0.0, (x[i] - gridpoints[i].first) / (gridpoints[i].second - gridpoints[i].first)));
117
118 // Computation uses a bit-representation of j (int) -> index (n values of 0 or 1)
119 // j=0 -> index=00...000 ; j=1 -> index=00...001 ; j=2 -> index=00...010
120 double interpolant = 0.0, prod;
121 for (int j = 0, i; j < (1<<n); interpolant += prod, j++)
122 for (prod = data[j], i = 0; i < n; i++) prod *= (j >> (n - 1 - i)) & 1 ? weight[i] : 1.0 - weight[i];
123
124 return interpolant;
125}
126
127// Does not use nlinear_interpolation: optimized path for nb_comp = 1 and nb_param = 1
128double Table::val_simple(double vp) const
129{
130 assert(les_parametres.size() == 1);
131 const DoubleVect& p = les_parametres[0];
132 const int size = p.size();
133 if (p[0] >= vp) return les_valeurs(0);
134 else
135 {
136 for (int i = 1; i < size; i++)
137 if (p[i] == vp) return les_valeurs(i);
138 else if (p[i] > vp) return (les_valeurs(i - 1) + ((les_valeurs(i) - les_valeurs(i - 1)) / (p[i] - p[i - 1])) * (vp - p[i - 1]));
139 }
140 return les_valeurs(size - 1);
141}
142
143double Table::val(const double val_param, int ncomp) const
144{
145 std::vector<double> vals_param {val_param};
146 return val(vals_param, ncomp);
147}
148
149double Table::val(const std::vector<double>& vals_param, int ncomp) const
150{
151 const int nb_param = les_parametres.size();
152 int nb_comp = les_valeurs.size();
153 if (nb_param == (int)vals_param.size())
154 {
155 std::vector<double> data;
156 std::vector<int> icube;
157 std::vector<std::pair<double, double>> gridpoints;
158
159 for (int ip = 0; ip < nb_param; ip++)
160 {
161 const DoubleVect& p = les_parametres[ip];
162 if (p.size()==1)
163 {
164 Cerr << "Error, a table should have more than one single value." << finl;
166 }
167 nb_comp /= p.size();
168 int i_interval = p.size() - 1;
169 for (int i = 1; i < p.size(); i++)
170 if (vals_param[ip] < p[i])
171 {
172 i_interval = i;
173 break;
174 }
175 icube.push_back(i_interval - 1);
176 gridpoints.push_back({p[i_interval - 1], p[i_interval]});
177 }
178 for (int j = 0; j < (1 << nb_param); j++)
179 {
180 std::vector<int> index(nb_param, 0);
181 for (int k = 0; k < nb_param; k++) index[nb_param - 1 - k] = icube[nb_param - 1 - k] + ((j >> k) & 1);
182
183 // Index in the global array of tabulated values
184 int k = index[0];
185 for (int i = 1; i < nb_param; i++)
186 k = k * les_parametres[i].size() + index[i];
187 k = k * nb_comp + ncomp;
188
189 data.push_back(les_valeurs[k]);
190 }
191
192 return nlinear_interpolation(vals_param, gridpoints, data);
193 }
194 else if (isf == 1 && vals_param.size() == 1)
195 {
196 // Plus rapide que parser(0).setVar("val",val_param);
197 parser(ncomp).setVar(0,vals_param[0]);
198 return parser(ncomp).eval();
199 }
200 else Process::exit("Error in a Table::val : wrong number of parameters.");
201
202 return 0;
203}
204
205/*! @brief Not yet implemented. Exits with an error.
206 *
207 */
208double Table::val(const DoubleVect& val_param) const
209{
210 Cerr << "Table::val(const DoubleVect& ) is not coded yet." << finl;
211 exit();
212 return 0;
213}
214
215
216/*! @brief Returns the computed values at point val_param (for a 2D value array).
217 *
218 * Values are exact if the point matches a tabulated parameter value,
219 * otherwise they are linearly interpolated (order 1).
220 *
221 * @param (DoubleVect& x) output vector of values
222 * @param (const double val_param) the evaluation point
223 * @return (DoubleVect&) the modified vector x
224 * @throws Exits with an error if parameters are missing
225 */
226DoubleVect& Table::valeurs(DoubleVect& x, const double val_param) const
227{
228
229 if (les_parametres.size() == 1)
230 {
231 int size;
232 const DoubleVect& p = les_parametres[0];
233 int size_p=p.size();
234 if (p[0] >= val_param)
235 {
236 size=x.size();
237 for(int j=0; j<size; j++)
238 x[j] = les_valeurs(0,j);
239 }
240 else if (p[size_p-1] <= val_param)
241 {
242 size=x.size();
243 for(int j=0; j<size; j++)
244 x[j] = les_valeurs(size_p-1,j);
245 }
246 else
247 {
248 for (int i=1; i<size_p; i++)
249 if (p[i] == val_param)
250 {
251 size=x.size();
252 for(int j=0; j<size; j++)
253 x[j] = les_valeurs(i,j);
254 break;
255 }
256 else if (p[i] > val_param)
257 {
258 size=x.size();
259 for(int j=0; j<size; j++)
260 x[j] = les_valeurs(i-1,j)+
261 ((les_valeurs(i,j)-les_valeurs(i-1,j))/(p[i]-p[i-1]))
262 *(val_param-p[i-1]) ;
263 break;
264 }
265 }
266 }
267 else
268 {
269 Cerr << "Error in a Table : it misses some parameters." << finl;
270 exit();
271 }
272 return x;
273}
274
275/*! @brief Not yet implemented. Exits with an error.
276 *
277 */
278DoubleVect& Table::valeurs(DoubleVect& x, const DoubleVect& val_param) const
279{
280 Cerr << "Table::val(const DoubleVect& ) is not coded yet." << finl;
281 exit();
282 return x;
283}
284
285// Evaluates an array of values (val) from an analytic expression depending on the values (val_param)
286// of a parameter field, on space (pos) and on time (t).
287DoubleTab& Table::valeurs(const DoubleTab& val_param,const DoubleTab& pos,const double tps,DoubleTab& aval) const
288{
289 eval_fct(pos,tps,val_param,aval);
290 return aval;
291
292}
293
294/*! @brief Sets the parameters and values of the table.
295 *
296 * @param (const DoubleVect& param) the parameter values
297 * @param (const DoubleTab& aval) the table values
298 */
299void Table::remplir(const DoubleVect& param,const DoubleTab& aval)
300{
301 // Check that param is strictly monotone
302 double val_ = param[0];
303 for (int i = 1; i < param.size(); i++)
304 if (val_ < param[i]) val_ = param[i];
305 else Process::exit("A table is not strictly monotonic!");
306
307 les_valeurs.ref(aval);
308 les_parametres.dimensionner(1);
309 les_parametres[0].ref(param);
310}
311
312void Table::remplir(const DoubleVects& params, const DoubleVect& aval)
313{
314 // Check that each parameter array is strictly monotone
315 for (int n = 0; n < params.size(); n++)
316 {
317 double val_ = params[n][0];
318 for (int i = 1; i < params[n].size(); i++)
319 if (val_ < params[n][i]) val_ = params[n][i];
320 else Process::exit("A table is not strictly monotonic!");
321 }
322
323 les_valeurs = aval;
324 les_parametres.dimensionner(params.size());
325 for (int i = 0; i < params.size(); i++) les_parametres[i].ref(params[i]);
326}
327
328static bool checked=false;
330{
331 if (!checked)
332 {
333 for (int comp = 0; comp < les_valeurs.dimension(1); comp++)
334 {
335 double val_ = les_valeurs(0, comp);
336 for (int i = 1; i < les_valeurs.dimension(0); i++)
337 if (val_ != les_valeurs(i, comp))
338 instationnaire_ = true;
339 }
340 checked = true;
341 }
342 return instationnaire_;
343}
Class defining operators and methods for all reading operation in an input flow (file,...
Definition Entree.h:42
class Nom: a character string for naming TRUST objects.
Definition Nom.h:31
Base class for TRUST objects (Objet_U).
Definition Objet_U.h:68
friend class Entree
Definition Objet_U.h:71
const Nom & que_suis_je() const
Returns the string identifying the class.
Definition Objet_U.cpp:104
virtual Entree & readOn(Entree &)
Reads an Objet_U from an input stream. Virtual method to override.
Definition Objet_U.cpp:289
Objet_U()
Default constructor: assigns a unique identifier to the object (object_id_) and registers the object ...
Definition Objet_U.cpp:54
virtual const Nom & le_nom() const
Returns the name of the Objet_U. Virtual method to override: returns "neant" in this implementation.
Definition Objet_U.cpp:317
virtual Sortie & printOn(Sortie &) const
Writes the object to an output stream. Virtual method to override.
Definition Objet_U.cpp:278
Parser_Eval class - Evaluates the values taken by an analytic function.
Definition Parser_Eval.h:29
VECT(Parser_U) &fonction()
Definition Parser_Eval.h:31
Parser_U & parser(int i)
Definition Parser_Eval.h:32
void eval_fct(const DoubleTab &positions, DoubleTab &val) const
Definition Parser_Eval.h:36
class Parser_U Version of the Parser class, deriving from Objet_U.
Definition Parser_U.h:32
void setVar(const char *sv, double val)
Definition Parser_U.h:149
double eval()
Definition Parser_U.h:125
static void exit(int exit_code=-1)
Exit routine for TRUST within a Kokkos region.
Definition Process.cpp:466
Base class for output streams.
Definition Sortie.h:52
_SIZE_ size() const
Definition TRUSTVect.tpp:45
int size() const
Definition Table.h:29
Table()
Default constructor. Creates an empty table.
Definition Table.cpp:25
void remplir(const DoubleVect &param, const DoubleTab &val)
Sets the parameters and values of the table.
Definition Table.cpp:299
double val_simple(double vals_param) const
Definition Table.cpp:128
double val(const double val_param, int ncomp=0) const
Definition Table.cpp:143
DoubleTab & valeurs(const DoubleTab &val_param, const DoubleTab &pos, const double tps, DoubleTab &val) const
Definition Table.cpp:287
Entree & lire_f(Entree &is, const int nb_comp)
Definition Table.cpp:34
Entree & lire_fxyzt(Entree &is, const int dim)
Definition Table.cpp:58
bool instationnaire() const
Definition Table.cpp:329