OPAL (Object Oriented Parallel Accelerator Library) 2022.1
OPAL
FLieGenerator.hpp
Go to the documentation of this file.
1#ifndef CLASSIC_FLieGenerator_CC
2#define CLASSIC_FLieGenerator_CC
3// ------------------------------------------------------------------------
4// $RCSfile: FLieGenerator.cpp,v $
5// ------------------------------------------------------------------------
6// $Revision: 1.2 $
7// ------------------------------------------------------------------------
8// Copyright: see Copyright.readme
9// ------------------------------------------------------------------------
10//
11// Template class: FLieGenerator<T,N>
12//
13// ------------------------------------------------------------------------
14// Class category: FixedAlgebra
15// ------------------------------------------------------------------------
16//
17// $Date: 2001/11/15 08:52:26 $
18// $Author: jsberg $
19//
20// ------------------------------------------------------------------------
21
23#include "Algebra/Array1D.h"
27#include "FixedAlgebra/FTps.h"
28#include <complex>
29#include <iosfwd>
30#include <functional>
31
32// Template class FLieGenerator<T,N>.
33// This code contains various tweaks for speed.
34// ------------------------------------------------------------------------
35
36template <class T, int N>
38FLieGenerator(int order):
39 itsOrder(order),
40 bottomIndex(getBottomIndex(order)),
41 topIndex(getTopIndex(order)),
42 itsCoeffs(getSize(order)) {
43 std::fill(itsCoeffs.begin(), itsCoeffs.end(), T(0));
44}
45
46
47template <class T, int N>
49FLieGenerator(const FTps<T, 2 * N> &tps, int order):
50 itsOrder(order),
51 bottomIndex(getBottomIndex(order)),
52 topIndex(getTopIndex(order)),
53 itsCoeffs(getSize(order)) {
54 if(order <= tps.getMaxOrder()) {
55 std::copy(tps.begin() + bottomIndex, tps.begin() + topIndex,
56 itsCoeffs.begin());
57 } else {
58 std::fill(itsCoeffs.begin(), itsCoeffs.end(), T(0));
59 }
60}
61
62template <class T, int N>
65 itsOrder(-1),
66 bottomIndex(0),
67 topIndex(0),
68 itsCoeffs(1) {
69 itsCoeffs[0] = T(0);
70}
71
72
73template <class T, int N>
76 itsOrder(rhs.itsOrder),
77 bottomIndex(rhs.bottomIndex),
78 topIndex(rhs.topIndex),
79 itsCoeffs(rhs.itsCoeffs)
80{}
81
82
83template <class T, int N>
86{}
87
88
89template <class T, int N>
91operator=(const FLieGenerator &rhs) {
92 itsCoeffs = rhs.itsCoeffs;
93 itsOrder = rhs.itsOrder;
94 bottomIndex = rhs.bottomIndex;
95 topIndex = rhs.topIndex;
96 return *this;
97}
98
99
100template<class T, int N> inline
102begin() {
103 return itsCoeffs.begin();
104}
105
106
107template<class T, int N> inline
109begin() const {
110 return itsCoeffs.begin();
111}
112
113
114template<class T, int N> inline
116 return itsCoeffs.end();
117}
118
119
120template<class T, int N> inline
122end() const {
123 return itsCoeffs.end();
124}
125
126
127template<class T, int N> inline
129 return itsCoeffs[i-bottomIndex];
130}
131
132
133template<class T, int N> inline
135 return itsCoeffs[i-bottomIndex];
136}
137
138
139template<class T, int N>
141 if(itsOrder < 0) {
142 return *this;
143 } else {
144 FLieGenerator<T, N> result(itsOrder);
145 std::transform(itsCoeffs.begin(), itsCoeffs.end(),
146 result.itsCoeffs.begin(), std::negate<T>());
147 return result;
148 }
149}
150
151template<class T, int N>
153 if(itsOrder < 0) {
154 return *this;
155 } else {
156 std::transform(itsCoeffs.begin(), itsCoeffs.end(), itsCoeffs.begin(),
157 std::bind(std::multiplies<T>(), std::placeholders::_1, val));
158 return *this;
159 }
160}
161
162
163template<class T, int N>
165 if(itsOrder < 0) {
166 return *this;
167 } else {
168 std::transform(itsCoeffs.begin(), itsCoeffs.end(), itsCoeffs.begin(),
169 std::bind(std::divides<T>(), std::placeholders::_1, val));
170 return *this;
171 }
172}
173
174
175template<class T, int N>
178 if(itsOrder == rhs.itsOrder) {
179 std::transform(itsCoeffs.begin(), itsCoeffs.end(), rhs.itsCoeffs.begin(),
180 itsCoeffs.begin(), std::plus<T>());
181 } else if(isZero()) {
182 *this = rhs;
183 } else if(! rhs.isZero()) {
184 throw SizeError("operator+=(FLieGenerator)", "Inconsistent orders.");
185 }
186
187 return *this;
188}
189
190
191template<class T, int N>
194 if(itsOrder == rhs.itsOrder) {
195 std::transform(itsCoeffs.begin(), itsCoeffs.end(), rhs.itsCoeffs.begin(),
196 itsCoeffs.begin(), std::minus<T>());
197 } else if(isZero()) {
198 *this = rhs;
199 } else if(! rhs.isZero()) {
200 throw SizeError("operator+=(FLieGenerator)", "Inconsistent orders.");
201 }
202
203 return *this;
204}
205
206
207template <class T, int N>
209clear() {
210 std::fill(itsCoeffs.begin(), itsCoeffs.end(), T(0));
211}
212
213
214template <class T, int N>
216 if(getOrder() > 0) {
217 FLieGenerator<T, N> result(getOrder() - 1);
218 const Array1D<int> &product = FTpsData<2 * N>::getProductArray(var + 1);
219
220 for(int i = result.getBottomIndex(); i < result.getTopIndex(); ++i) {
221 int k = product[i];
222 result[i] = (*this)[k] * double(FTpsData<2 * N>::getExponents(k)[var]);
223 }
224
225 return result;
226 } else {
227 return FLieGenerator<T, N>();
228 }
229}
230
231
232template <class T, int N>
234isZero() const {
235 if(itsOrder < 0) return true;
236
237 for(const T *i = itsCoeffs.begin(); i != itsCoeffs.end(); ++i) {
238 if(*i != T(0)) return false;
239 }
240
241 return true;
242}
243
244
245template <class T, int N>
247scale(const FLieGenerator &rhs) const {
248 FLieGenerator result(itsOrder);
249 std::transform(itsCoeffs.begin(), itsCoeffs.end(), rhs.itsCoeffs.begin(),
250 result.itsCoeffs.begin(), std::multiplies<T>());
251 return result;
252}
253
254
255template <class T, int N> template <class U>
257transform(const FMatrix<U, 2 * N, 2 * N> &mat) const {
258 int order = getOrder();
259 FLieGenerator<U, N> trans(order);
260
261 // Working array to accumulate partial products.
262 Array1D<U> temp(getTopIndex());
263 temp[0] = U(1);
264 U *tt = temp.begin();
265
267 for(int next = 1; next < table.size();) {
268 const TpsSubstitution &s = table[next];
269 int bot1 = getBottomIndex(s.order);
270 int top1 = getTopIndex(s.order);
271 for(int i = bot1; i < top1; ++i) tt[i] = U(0);
272 const U *row = mat[s.variable];
273
274 for(int v = 0; v < 2 * N; ++v) {
275 U c = row[v];
276 if(c != 0.0) {
278 int bot2 = getBottomIndex(s.order - 1);
279 int top2 = getTopIndex(s.order - 1);
280 for(int k = bot2; k < top2; ++k) {
281 tt[prod[k]] += c * tt[k];
282 }
283 }
284 }
285
286 if(s.order < order) {
287 ++next;
288 } else if(s.order == order) {
289 T coeff = (*this)[s.index];
290 if(coeff != T(0)) {
291 for(int k = bot1; k < top1; ++k) {
292 trans[k] += coeff * tt[k];
293 }
294 }
295 next = s.skip;
296 } else {
297 next = s.skip;
298 }
299 }
300
301 return trans;
302}
303
304
305template <class T, int N>
307getOrder() const {
308 return itsOrder;
309}
310
311
312template <class T, int N>
314getBottomIndex() const {
315 return bottomIndex;
316}
317
318
319template <class T, int N>
321getTopIndex() const {
322 return topIndex;
323}
324
325
326template <class T, int N>
328getSize(int order) {
329 return FTpsData<2 * N>::getSize(order) - FTpsData<2 * N>::getSize(order - 1);
330}
331
332
333template <class T, int N>
335getBottomIndex(int order) {
336 return FTpsData<2 * N>::getSize(order - 1);
337}
338
339
340template <class T, int N>
342getTopIndex(int order) {
343 return FTpsData<2 * N>::getSize(order);
344}
345
346
347// Global functions.
348// ------------------------------------------------------------------------
349
350template <class T, int N>
354 return z += y;
355}
356
357
358template <class T, int N>
362 return z -= y;
363}
364
365
366template <class T, int N>
368operator*(const FLieGenerator<T, N> &x, const T &y) {
370 return z *= y;
371}
372
373
374template <class T, int N>
376operator*(const T &x, const FLieGenerator<T, N> &y) {
378 return z *= x;
379}
380
381
382template <class T, int N>
385 if(x.isZero()) {
386 return FLieGenerator<T, N>();
387 } else if(y.isZero()) {
388 return FLieGenerator<T, N>();
389 } else {
391
392 int bot1 = x.getBottomIndex();
393 int top1 = x.getTopIndex();
394 int bot2 = y.getBottomIndex();
395 int top2 = y.getTopIndex();
396
397 for(int i1 = bot1; i1 < top1; ++i1) {
399 T f = x[i1];
400 if(f != 0.0) {
401 for(int i2 = bot2; i2 < top2; ++i2) {
402 z[p[i2]] += f * y[i2];
403 }
404 }
405 }
406
407 return z;
408 }
409}
410
411
412template <class T, int N>
414operator/(const FLieGenerator<T, N> &x, const T &y) {
416 return z /= y;
417}
418
419
420template <class T, int N>
422real(const FLieGenerator<std::complex<T>, N> &x) {
423 FLieGenerator<T, N> z(x.getOrder());
424 T *i1 = z.begin();
425 const std::complex<T> *i2 = x.begin();
426
427 while(i1 != z.end()) {
428 *i1++ = std::real(*i2++);
429 }
430
431 return z;
432}
433
434
435template <class T, int N>
437imag(const FLieGenerator<std::complex<T>, N> &x) {
438 FLieGenerator<T, N> z(x.getOrder());
439 T *i1 = z.begin();
440 const std::complex<T> *i2 = x.begin();
441
442 while(i1 != z.end()) {
443 *i1++ = std::imag(*i2++);
444 }
445
446 return z;
447}
448
449
450template <class T, int N>
454 std::complex<T> *i1 = z.begin();
455 const T *i2 = x.begin();
456
457 while(i1 != z.end()) {
458 *i1++ = std::complex<T>(*i2++, T(0));
459 }
460
461 return z;
462}
463
464
465template <class T, int N> FLieGenerator<T, N>
467 if(f.isZero()) {
468 return FLieGenerator<T, N>();
469 } else if(g.isZero()) {
470 return FLieGenerator<T, N>();
471 } else {
472 // Index limits for the derivatives.
473 int ord_f = f.getOrder() - 1;
474 int ord_g = g.getOrder() - 1;
475 int top_f = f.getBottomIndex();
476 int top_g = g.getBottomIndex();
477 int bot_f = (top_f * ord_f) / (2 * N + ord_f);
478 int bot_g = (top_g * ord_g) / (2 * N + ord_g);
479 const T *ff = f.begin() - f.getBottomIndex();
480 const T *gg = g.begin() - g.getBottomIndex();
481
482 FLieGenerator<T, N> h(ord_f + ord_g);
483 T *hh = h.begin() - h.getBottomIndex();
484
485 for(int ind_1 = bot_f; ind_1 < top_f; ++ind_1) {
486 const Array1D<int> &prod_f = FTpsData<2 * N>::getProductArray(ind_1);
488
489 for(int ind_g = bot_g; ind_g < top_g; ++ind_g) {
490 const Array1D<int> &prod_g = FTpsData<2 * N>::getProductArray(ind_g);
492
493 for(int var = 0; var < 2 * N; var += 2) {
494 // Index of product monomial.
495 int ind_h = prod_f[ind_g];
496
497 // The relevant coefficients of the four derivatives.
498 double f_q = ff[prod_f[var+1]] * T(exp_f[var] + 1);
499 double g_p = gg[prod_g[var+2]] * T(exp_g[var+1] + 1);
500 double f_p = ff[prod_f[var+2]] * T(exp_f[var+1] + 1);
501 double g_q = gg[prod_g[var+1]] * T(exp_g[var] + 1);
502
503 // Accumulate.
504 hh[ind_h] += (f_q * g_p - f_p * g_q);
505 }
506 }
507 }
508
509 return h;
510 }
511}
512
513
514template <class T, int N>
515std::ostream &operator<<(std::ostream &os, const FLieGenerator<T, N> &gen) {
516 os << "Tps" << std::setw(4) << gen.getOrder() << std::setw(4)
517 << gen.getOrder() << std::setw(4) << (2 * N) << std::endl;
518 std::streamsize old_prec = os.precision(14);
519 os.setf(std::ios::scientific, std::ios::floatfield);
520
521 for(int i = gen.getBottomIndex(); i < gen.getTopIndex(); ++i) {
522 if(gen[i] != T(0)) {
523 os << std::setw(24) << gen[i];
525
526 for(int var = 0; var < 2 * N; var++) {
527 os << std::setw(3) << index[var];
528 }
529
530 os << std::endl;
531 }
532 }
533
534 os << std::setw(24) << T(0);
535
536 for(int var = 0; var < 2 * N; var++) {
537 os << std::setw(3) << (-1);
538 }
539
540 os << std::endl;
541 os.setf(std::ios::fixed, std::ios::floatfield);
542 os.precision(old_prec);
543 return os;
544}
545
546#endif
FLieGenerator< T, N > operator*(const FLieGenerator< T, N > &x, const T &y)
Multiply by scalar.
FLieGenerator< T, N > PoissonBracket(const FLieGenerator< T, N > &f, const FLieGenerator< T, N > &g)
Poisson bracket of two Lie generators.
FLieGenerator< T, N > operator/(const FLieGenerator< T, N > &x, const T &y)
Divide by scalar.
FLieGenerator< T, N > real(const FLieGenerator< std::complex< T >, N > &x)
Take real part of a complex generator.
FLieGenerator< T, N > operator-(const FLieGenerator< T, N > &x, const FLieGenerator< T, N > &y)
Subtract.
std::ostream & operator<<(std::ostream &os, const FLieGenerator< T, N > &gen)
Output.
FLieGenerator< T, N > operator+(const FLieGenerator< T, N > &x, const FLieGenerator< T, N > &y)
Add.
FLieGenerator< std::complex< T >, N > toComplex(const FLieGenerator< T, N > &x)
Convert real generator to complex.
FLieGenerator< T, N > imag(const FLieGenerator< std::complex< T >, N > &x)
Take imaginary part of a complex generator.
T::PETE_Expr_t::PETE_Return_t prod(const PETE_Expr< T > &expr)
Definition: PETE.h:1121
Inform & endl(Inform &inf)
Definition: Inform.cpp:42
constexpr double c
The velocity of light in m/s.
Definition: Physics.h:45
iterator begin()
Get beginning of data.
Definition: Array1D.h:204
int size() const
Get array size.
Definition: Array1D.h:228
Substitution for Tps<T>.
A templated representation for matrices.
Definition: FMatrix.h:39
Truncated power series in N variables of type T.
Definition: FTps.h:45
T * begin() const
Return beginning of monomial array.
Definition: FTps.h:118
int getMaxOrder() const
Get maximum order.
Definition: FTps.h:174
A representation for a homogeneous polynomial, used as a Lie generator.
Definition: FLieGenerator.h:40
void clear()
Clear all coefficients.
int getBottomIndex() const
Return bottom index of this generator.
FLieGenerator & operator*=(const T &)
Multiply by scalar and assign.
const FLieGenerator & operator=(const FLieGenerator &)
FLieGenerator & operator-=(const FLieGenerator &)
Subtract vector and assign.
T * begin()
Get pointer to beginning of generator.
FLieGenerator & operator+=(const FLieGenerator &)
Add vector and assign.
static int getSize(int order)
T & operator[](int n)
Get element.
FLieGenerator & operator/=(const T &)
Divide by scalar and assign.
FLieGenerator derivative(int var) const
Partial derivative.
int getOrder() const
Return order of this generator.
bool isZero() const
Test for zero.
FLieGenerator scale(const FLieGenerator &) const
Scale monomial-wise.
FLieGenerator operator-() const
Change sign of generator.
T * end()
Get pointer past end of generator.
Array1D< T > itsCoeffs
FLieGenerator< U, N > transform(const FMatrix< U, 2 *N, 2 *N > &) const
Substitute matrix in Lie generator.
int getTopIndex() const
Return top index of this generator.
Representation of the exponents for a monomial with fixed dimension.
Definition: FMonomial.h:32
Internal utility class for FTps<T,N> class.
Definition: FTpsData.h:33
static const FMonomial< N > & getExponents(int index)
Definition: FTpsData.h:158
static const Array1D< TpsSubstitution > & getSubTable()
Definition: FTpsData.h:268
static int getSize(int order)
Definition: FTpsData.h:187
static const Array1D< int > & getProductArray(int index)
Definition: FTpsData.h:237
Size error exception.
Definition: SizeError.h:33
FmtFlags_t setf(FmtFlags_t setbits, FmtFlags_t field)
Definition: Inform.h:101
int precision() const
Definition: Inform.h:112