OPAL (Object Oriented Parallel Accelerator Library) 2022.1
OPAL
TransportFun.hpp
Go to the documentation of this file.
1#ifndef CLASSIC_TransportFun_CC
2#define CLASSIC_TransportFun_CC
3
4// ------------------------------------------------------------------------
5// $RCSfile: TransportFun.cpp,v $
6// ------------------------------------------------------------------------
7// $Revision: 1.2.2.1 $
8// ------------------------------------------------------------------------
9// Copyright: see Copyright.readme
10// ------------------------------------------------------------------------
11//
12// Template class: TransportFun<T,N>
13// Representation of a second-order function with values of type T,
14// and fixed number of variables N.
15//
16// ------------------------------------------------------------------------
17// Class category: FixedAlgebra
18// ------------------------------------------------------------------------
19//
20// $Date: 2004/11/18 22:18:06 $
21// $Author: jsberg $
22//
23// ------------------------------------------------------------------------
24
31#include <iomanip>
32#include <iostream>
33#include <cstring>
34
35
36// Implementation of template class TransportFun<T,N>.
37// ------------------------------------------------------------------------
38
39template <class T, int N>
41 for(int i = 0; i < SIZE; ++i) data[i] = 0.0;
42}
43
44
45template <class T, int N>
47 data[0] = rhs;
48 for(int i = 1; i < SIZE; ++i) data[i] = 0.0;
49}
50
51
52template <class T, int N>
54 data[0] = T(rhs);
55 for(int i = 1; i < SIZE; ++i) data[i] = 0.0;
56}
57
58
59template <class T, int N>
61 data[0] = rhs;
62 for(int i = 1; i < SIZE; ++i) data[i] = 0.0;
63 return *this;
64}
65
66
67template <class T, int N>
68const T TransportFun<T, N>::getCoefficient(int index) const {
69 return (index > N) ? T(0) : data[index];
70}
71
72
73template <class T, int N>
74const T TransportFun<T, N>::getCoefficient(int index1, int index2) const {
75 if(index1 <= index2 && index2 < N) {
76 int index = N * (2 * N + 1 - index1) * index1 + (N + 1) + index2;
77 return data[index];
78 } else {
79 return T(0);
80 }
81}
82
83
84template <class T, int N>
85void TransportFun<T, N>::setCoefficient(int index, const T &value) {
86 if(index <= N) data[index] = value;
87}
88
89
90template <class T, int N>
91void TransportFun<T, N>::setCoefficient(int index1, int index2, const T &value) {
92 if(index1 <= index2 && index2 < N) {
93 int index = N * (2 * N + 1 - index1) * index1 + (N + 1) + index2;
94 data[index] = value;
95 }
96}
97
98
99template <class T, int N> inline
100const T TransportFun<T, N>::operator[](int index) const {
101 return data[index];
102}
103
104
105template <class T, int N> inline
107 return data[index];
108}
109
110
111template <class T, int N> inline
112const T TransportFun<T, N>::operator()(int index1, int index2) const {
113 int index = N * (2 * N + 1 - index1) * index1 + (N + 1) + index2;
114 return data[index];
115}
116
117
118template <class T, int N> inline
119T &TransportFun<T, N>::operator()(int index1, int index2) {
120 int index = N * (2 * N + 1 - index1) * index1 + (N + 1) + index2;
121 return data[index];
122}
123
124
125template <class T, int N>
128 for(int i = 0; i < SIZE; ++i) z.data[i] = 0.0;
129 z.data[var+1] = T(1);
130 return z;
131}
132
133
134template <class T, int N> inline
136 return *this;
137}
138
139
140template <class T, int N>
143 for(int i = 0; i < SIZE; ++i) z.data[i] = - data[i];
144 return z;
145}
146
147
148template <class T, int N>
150 for(int i = 0; i < SIZE; ++i) data[i] += rhs.data[i];
151 return *this;
152}
153
154
155template <class T, int N>
157 for(int i = 0; i < SIZE; ++i) data[i] -= rhs.data[i];
158 return *this;
159}
160
161
162template <class T, int N>
164 return *this = multiply(rhs);
165}
166
167
168template <class T, int N>
170 if(rhs.data[0] == T(0)) throw DivideError("TransportFun::operator/=()");
171 return *this = multiply(rhs.inverse());
172}
173
174
175template <class T, int N> inline
177 data[0] += rhs;
178 return *this;
179}
180
181
182template <class T, int N> inline
184 data[0] -= rhs;
185 return *this;
186}
187
188
189template <class T, int N>
191 for(int i = 0; i < SIZE; ++i) data[i] *= rhs;
192 return *this;
193}
194
195
196template <class T, int N>
198 if(rhs == T(0)) throw DivideError("TransportFun::operator/=()");
199 for(int i = 0; i < SIZE; ++i) data[i] /= rhs;
200 return *this;
201}
202
203
204template <class T, int N>
206 for(int i = 0; i < SIZE; ++i) {
207 if(data[i] != rhs.data[i]) return false;
208 }
209
210 return true;
211}
212
213
214template <class T, int N>
215bool TransportFun<T, N>::operator==(const T &rhs) const {
216 if(data[0] != rhs) return false;
217
218 for(int i = 1; i < SIZE; ++i) {
219 if(data[i] != T(0)) return false;
220 }
221
222 return true;
223}
224
225
226template <class T, int N> inline
228 return !(*this == rhs);
229}
230
231
232template <class T, int N> inline
233bool TransportFun<T, N>::operator!=(const T &rhs) const {
234 return !(*this == rhs);
235}
236
237
238template <class T, int N>
240 T aZero = data[0];
241 if(aZero == T(0)) throw DivideError("TransportFun::inverse()");
242
243 T series[3];
244 series[0] = T(1) / aZero;
245 series[1] = - series[0] / aZero;
246 series[2] = - series[1] / aZero;
247 return taylor(series);
248}
249
250
251template <class T, int N> TransportFun<T, N>
254
255 // Product of constant terms.
256 z.data[0] = data[0] * rhs.data[0];
257
258 // Products of constant term with non-constant terms of other factor.
259 for(int i = 1; i < SIZE; ++i) {
260 z.data[i] = data[0] * rhs.data[i] + data[i] * rhs.data[0];
261 }
262
263 // Second-order terms generated as products of linear terms.
264 int k = N;
265 for(int i = 0; i < N; ++i) {
266 // Quadratic terms.
267 ++k;
268 z.data[k] += data[i+1] * rhs.data[i+1];
269
270 // Bilinear terms.
271 for(int j = i + 1; j < N; ++j) {
272 ++k;
273 z.data[k] += data[i+1] * rhs.data[j+1] + data[j+1] * rhs.data[i+1];
274 }
275 }
276
277 return z;
278}
279
280
281template <class T, int N>
283 // Constant term.
284 T z = data[0];
285
286 // Linear terms.
287 int k = 0;
288 for(int i = 0; i < N; ++i) {
289 z += data[++k] * rhs[i];
290 }
291
292 // Second-order terms.
293 for(int i = 0; i < N; ++i) {
294 for(int j = i; j < N; ++j) {
295 z += data[++k] * rhs[i] * rhs[j];
296 }
297 }
298
299 return z;
300}
301
302
303template <class T, int N>
305 return substitute(TransportMap<T, N>(M));
306}
307
308
309template <class T, int N>
312 z.data[0] = data[0];
313
314 // Linear terms.
315 int k = 0;
316 for(int i = 0; i < N; ++i) {
317 z += data[++k] * m[i];
318 }
319
320 // Second-order terms.
321 for(int i = 0; i < N; ++i) {
322 for(int j = i; j < N; ++i) {
323 z += data[++k] * m[i] * m[j];
324 }
325 }
326
327 return z;
328}
329
330
331template <class T, int N>
333 TransportFun<T, N> x(*this);
334 x[0] = 0.0;
335 return (series[2] * x + series[1]) * x + series[0];
336}
337
338
339template <class T, int N>
340std::istream &TransportFun<T, N>::get(std::istream &is) {
341 is.flags(std::ios::skipws);
342 char head[4];
343 is.get(head, 4);
344
345 if(strcmp(head, "Tps") != 0) {
346 throw FormatError("TransportFun::get()", "Flag word \"Tps\" missing.");
347 }
348
349 int maxOrder, truncOrder, nVar;
350 is >> maxOrder >> truncOrder >> nVar;
351
352 if(nVar != N) {
353 throw FormatError("TransportFun::get()", "Invalid number of variables.");
354 }
355
356 T coeff;
357 int mono[N];
358 bool done = false;
359 bool fail = false;
360
361 while(true) {
362 is >> coeff;
363 fail = is.fail();
364
365 int order = 0;
366 for(int var = 0; var < nVar; ++var) {
367 is >> mono[var];
368 fail |= is.fail();
369 if(mono[var] < 0) done = true;
370 order += mono[var];
371 }
372
373 if(done) break;
374 if(fail) throw FormatError("TransportFun::get()", "File read error");
375
376 // Store coefficient in proper place.
377 if(order <= 2 && coeff != T(0)) {
378 int order = 0;
379 int index = 0;
380 for(int var = N; var-- > 0;) {
381 order += mono[var];
382 if(order == 1) {
383 ++index;
384 } else if(order == 2) {
385 index += N + order - var;
386 }
387 }
388 data[index] = coeff;
389 }
390 }
391}
392
393
394template <class T, int N>
395std::ostream &TransportFun<T, N>::put(std::ostream &os) const {
396 os << "Tps " << this->itsRep->max << ' ' << this->itsRep->trc << ' ' << N
397 << std::endl;
398 std::streamsize old_prec = os.precision(14);
399 os.setf(std::ios::scientific, std::ios::floatfield);
400
401 // Constant term.
402 T *coeff = data;
403 if(*coeff != T(0)) {
404 os << std::setw(24) << *coeff[0];
405 for(int var = 0; var < N; ++var) {
406 os << std::setw(3) << 0;
407 }
408 }
409
410 // Linear terms.
411 for(int i = 0; i < N; i++) {
412 ++coeff;
413 if(*coeff != T(0)) {
414 os << std::setw(24) << *coeff;
415 for(int var = 0; var < N; ++var) {
416 os << std::setw(3) << ((var == i) ? 1 : 0);
417 }
418 os << std::endl;
419 }
420 }
421
422 // Second-order terms.
423 for(int i = 0; i < N; ++i) {
424 ++coeff;
425 if(*coeff != T(0)) {
426 os << std::setw(24) << *coeff;
427 for(int var = 0; var < N; ++var) {
428 os << std::setw(3) << ((var == i) ? 2 : 0);
429 }
430 }
431 for(int j = i + 1; j < N; ++j) {
432 ++coeff;
433 if(*coeff != T(0)) {
434 os << std::setw(24) << *coeff;
435 for(int var = 0; var < N; ++var) {
436 os << std::setw(3) << ((var == i || var == j) ? 1 : 0);
437 }
438 os << std::endl;
439 }
440 }
441 }
442
443 // End marker.
444 os << std::setw(24) << T(0);
445 for(int var = 0; var < N; ++var) {
446 os << std::setw(3) << (-1);
447 }
448 os << std::endl;
449
450 os.precision(old_prec);
451 os.setf(std::ios::fixed, std::ios::floatfield);
452 return os;
453}
454
455
456// Global functions acting on TransportFun<T> objects.
457// ------------------------------------------------------------------------
458
459template <class T, int N> inline
461 TransportFun<T, N> z(lhs);
462 return z += rhs;
463}
464
465
466template <class T, int N> inline
468 TransportFun<T, N> z(lhs);
469 return z -= rhs;
470}
471
472
473template <class T, int N> inline
475 TransportFun<T, N> z(lhs);
476 return z += rhs;
477}
478
479
480template <class T, int N> inline
482 TransportFun<T, N> z(lhs);
483 return z -= rhs;
484}
485
486
487template <class T, int N> inline
489 TransportFun<T, N> z(rhs);
490 return z += lhs;
491}
492
493
494template <class T, int N> inline
496 TransportFun<T, N> z(- rhs);
497 return z += lhs;
498}
499
500
501template <class T, int N> inline
503 return lhs.multiply(rhs);
504}
505
506
507template <class T, int N> inline
509 return lhs.multiply(rhs.inverse());
510}
511
512
513template <class T, int N> inline
515 TransportFun<T, N> z(lhs);
516 return z *= rhs;
517}
518
519
520template <class T, int N> inline
522 TransportFun<T, N> z(lhs);
523 return z /= rhs;
524}
525
526
527template <class T, int N> inline
529 TransportFun<T, N> z(rhs);
530 return z *= lhs;
531}
532
533
534template <class T, int N> inline
536 return rhs.inverse() * lhs;
537}
538
539
540template <class T, int N> inline
541bool operator==(const T &lhs, const TransportFun<T, N> &rhs) {
542 return rhs == lhs;
543}
544
545
546template <class T, int N> inline
547bool operator!=(const T &lhs, const TransportFun<T, N> &rhs) {
548 return rhs != lhs;
549}
550
551
552template <class T, int N>
553std::istream &operator>>(std::istream &is, TransportFun<T, N> &fun) {
554 return fun.get(is);
555}
556
557
558template <class T, int N>
559std::ostream &operator<<(std::ostream &os, const TransportFun<T, N> &fun) {
560 return fun.put(os);
561}
562
563#endif // CLASSIC_TransportFun_CC
TransportFun< T, N > operator/(const TransportFun< T, N > &lhs, const TransportFun< T, N > &rhs)
Divide.
TransportFun< T, N > operator-(const TransportFun< T, N > &lhs, const TransportFun< T, N > &rhs)
Subtract.
bool operator!=(const T &lhs, const TransportFun< T, N > &rhs)
Inequality.
std::istream & operator>>(std::istream &is, TransportFun< T, N > &fun)
Extract TransportFun from stream [b]is[/b].
TransportFun< T, N > operator+(const TransportFun< T, N > &lhs, const TransportFun< T, N > &rhs)
Add.
bool operator==(const T &lhs, const TransportFun< T, N > &rhs)
Equality.
std::ostream & operator<<(std::ostream &os, const TransportFun< T, N > &fun)
Insert TransportFun to stream [b]os[/b].
TransportFun< T, N > operator*(const TransportFun< T, N > &lhs, const TransportFun< T, N > &rhs)
Multiply.
@ SIZE
Definition: IndexMap.cpp:174
Inform & endl(Inform &inf)
Definition: Inform.cpp:42
A templated representation for vectors.
Definition: FVector.h:38
Transport map with values of type [b]T[/b] in [b]N[/b] variables.
Definition: TransportMap.h:39
Transport function in N variables of type T.
Definition: TransportFun.h:40
const T getCoefficient(int index) const
Get coefficient.
static TransportFun makeVariable(int var)
Make variable.
TransportFun multiply(const TransportFun &y) const
Multiplication truncated to order one.
T evaluate(const FVector< T, N > &) const
Evaluate TransportFun at point.
TransportFun & operator+=(const TransportFun &y)
Add and assign.
T data[SIZE]
Representation.
Definition: TransportFun.h:192
void setCoefficient(int index, const T &value)
Set coefficient.
TransportFun taylor(const T series[2]) const
Taylor series.
bool operator!=(const TransportFun &y) const
Inequality operator.
TransportFun< T, N > substitute(const TransportMap< T, N > &m) const
Substitute.
TransportFun operator-() const
Unary minus.
TransportFun operator+() const
Unary plus.
const T operator[](int) const
Get coefficient.
TransportFun & operator/=(const TransportFun &y)
Approximate division and assignation.
TransportFun()
Default constructor.
bool operator==(const TransportFun &y) const
Equality operator.
std::ostream & put(std::ostream &os) const
Write TransportFun on the stream [b]os[/b].
std::istream & get(std::istream &is)
Read TransportFun on the stream [b]is[/b].
const T operator()(int i1, int i2) const
Get coefficient.
TransportFun inverse() const
Approximate reciprocal value 1/(*this).
TransportFun & operator*=(const TransportFun &y)
Multiply and assign.
TransportFun & operator=(const T &y)
Convert and assign.
TransportFun & operator-=(const TransportFun &y)
Subtract and assign.
Zero divide error.
Definition: DivideError.h:32
Format error exception.
Definition: FormatError.h:32
int precision() const
Definition: Inform.h:112