OPAL (Object Oriented Parallel Accelerator Library)  2.2.0
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"
24 #include "FixedAlgebra/FArray1D.h"
25 #include "FixedAlgebra/FMatrix.h"
26 #include "FixedAlgebra/FMonomial.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 
36 template <class T, int N>
38 FLieGenerator(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 
47 template <class T, int N>
49 FLieGenerator(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 
62 template <class T, int N>
65  itsOrder(-1),
66  bottomIndex(0),
67  topIndex(0),
68  itsCoeffs(1) {
69  itsCoeffs[0] = T(0);
70 }
71 
72 
73 template <class T, int N>
76  itsOrder(rhs.itsOrder),
77  bottomIndex(rhs.bottomIndex),
78  topIndex(rhs.topIndex),
79  itsCoeffs(rhs.itsCoeffs)
80 {}
81 
82 
83 template <class T, int N>
86 {}
87 
88 
89 template <class T, int N>
91 operator=(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 
100 template<class T, int N> inline
102 begin() {
103  return itsCoeffs.begin();
104 }
105 
106 
107 template<class T, int N> inline
109 begin() const {
110  return itsCoeffs.begin();
111 }
112 
113 
114 template<class T, int N> inline
116  return itsCoeffs.end();
117 }
118 
119 
120 template<class T, int N> inline
122 end() const {
123  return itsCoeffs.end();
124 }
125 
126 
127 template<class T, int N> inline
129  return itsCoeffs[i-bottomIndex];
130 }
131 
132 
133 template<class T, int N> inline
134 const T &FLieGenerator<T, N>::operator[](int i) const {
135  return itsCoeffs[i-bottomIndex];
136 }
137 
138 
139 template<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 
151 template<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 
163 template<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 
175 template<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 
191 template<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 
207 template <class T, int N>
209 clear() {
210  std::fill(itsCoeffs.begin(), itsCoeffs.end(), T(0));
211 }
212 
213 
214 template <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 
232 template <class T, int N>
234 isZero() 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 
245 template <class T, int N>
247 scale(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 
255 template <class T, int N> template <class U>
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 
305 template <class T, int N>
306 inline int FLieGenerator<T, N>::
307 getOrder() const {
308  return itsOrder;
309 }
310 
311 
312 template <class T, int N>
313 inline int FLieGenerator<T, N>::
314 getBottomIndex() const {
315  return bottomIndex;
316 }
317 
318 
319 template <class T, int N>
320 inline int FLieGenerator<T, N>::
321 getTopIndex() const {
322  return topIndex;
323 }
324 
325 
326 template <class T, int N>
327 inline int FLieGenerator<T, N>::
328 getSize(int order) {
329  return FTpsData<2 * N>::getSize(order) - FTpsData<2 * N>::getSize(order - 1);
330 }
331 
332 
333 template <class T, int N>
334 inline int FLieGenerator<T, N>::
335 getBottomIndex(int order) {
336  return FTpsData<2 * N>::getSize(order - 1);
337 }
338 
339 
340 template <class T, int N>
341 inline int FLieGenerator<T, N>::
342 getTopIndex(int order) {
343  return FTpsData<2 * N>::getSize(order);
344 }
345 
346 
347 // Global functions.
348 // ------------------------------------------------------------------------
349 
350 template <class T, int N>
353  FLieGenerator<T, N> z(x);
354  return z += y;
355 }
356 
357 
358 template <class T, int N>
361  FLieGenerator<T, N> z(x);
362  return z -= y;
363 }
364 
365 
366 template <class T, int N>
368 operator*(const FLieGenerator<T, N> &x, const T &y) {
369  FLieGenerator<T, N> z(x);
370  return z *= y;
371 }
372 
373 
374 template <class T, int N>
376 operator*(const T &x, const FLieGenerator<T, N> &y) {
377  FLieGenerator<T, N> z(y);
378  return z *= x;
379 }
380 
381 
382 template <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 
412 template <class T, int N>
414 operator/(const FLieGenerator<T, N> &x, const T &y) {
415  FLieGenerator<T, N> z(x);
416  return z /= y;
417 }
418 
419 
420 template <class T, int N>
422 real(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 
435 template <class T, int N>
437 imag(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 
450 template <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 
465 template <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);
487  const FMonomial<2 * N> &exp_f = FTpsData<2 * N>::getExponents(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);
491  const FMonomial<2 * N> &exp_g = FTpsData<2 * N>::getExponents(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 
514 template <class T, int N>
515 std::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
static const Array1D< int > & getProductArray(int index)
Definition: FTpsData.h:239
FLieGenerator< std::complex< T >, N > toComplex(const FLieGenerator< T, N > &)
Convert real generator to complex.
Matrix< T > operator+(const Matrix< T > &, const Matrix< T > &)
Matrix addition.
Definition: Matrix.h:275
Matrix< T > operator/(const Matrix< T > &, const T &)
Matrix divided by scalar.
Definition: Matrix.h:329
int getMaxOrder() const
Get maximum order.
Definition: FTps.h:174
static const Array1D< TpsSubstitution > & getSubTable()
Definition: FTpsData.h:270
Definition: rbendmap.h:8
A templated representation for matrices.
Definition: IdealMapper.h:26
Size error exception.
Definition: SizeError.h:33
FLieGenerator< U, N > transform(const FMatrix< U, 2 *N, 2 *N > &) const
Substitute matrix in Lie generator.
FLieGenerator & operator+=(const FLieGenerator &)
Add vector and assign.
Representation of the exponents for a monomial with fixed dimension.
Definition: FMonomial.h:32
FLieGenerator scale(const FLieGenerator &) const
Scale monomial-wise.
Matrix< T > operator*(const Matrix< T > &, const Matrix< T > &)
Matrix multiply.
Definition: Matrix.h:297
FmtFlags_t setf(FmtFlags_t setbits, FmtFlags_t field)
Definition: Inform.h:104
FLieGenerator< T, N > real(const FLieGenerator< std::complex< T >, N > &)
Take real part of a complex generator.
int size() const
Get array size.
Definition: Array1D.h:228
FLieGenerator derivative(int var) const
Partial derivative.
static int getSize(int order)
Definition: FTpsData.h:189
Tps< T > PoissonBracket(const Tps< T > &x, const Tps< T > &y)
Poisson bracket.
Definition: LieMap.h:154
void clear()
Clear all coefficients.
static int getSize(int order)
iterator begin()
Get beginning of data.
Definition: Array1D.h:204
FLieGenerator & operator-=(const FLieGenerator &)
Subtract vector and assign.
Internal utility class for FTps&lt;T,N&gt; class.
Definition: FTpsData.h:35
constexpr double c
The velocity of light in m/s.
Definition: Physics.h:52
FLieGenerator operator-() const
Change sign of generator.
int getOrder() const
Return order of this generator.
bool isZero() const
Test for zero.
const FLieGenerator & operator=(const FLieGenerator &)
int precision() const
Definition: Inform.h:115
A representation for a homogeneous polynomial, used as a Lie generator.
Definition: DragtFinnMap.h:29
static const FMonomial< N > & getExponents(int index)
Definition: FTpsData.h:160
Substitution for Tps&lt;T&gt;.
Array1D< T > itsCoeffs
T * begin()
Get pointer to beginning of generator.
FLieGenerator & operator*=(const T &)
Multiply by scalar and assign.
T::PETE_Expr_t::PETE_Return_t prod(const PETE_Expr< T > &expr)
Definition: PETE.h:1243
FLieGenerator & operator/=(const T &)
Divide by scalar and assign.
T * end()
Get pointer past end of generator.
Truncated power series in N variables of type T.
Matrix< T > operator-(const Matrix< T > &, const Matrix< T > &)
Matrix subtraction.
Definition: Matrix.h:282
int getBottomIndex() const
Return bottom index of this generator.
FLieGenerator< T, N > imag(const FLieGenerator< std::complex< T >, N > &)
Take imaginary part of a complex generator.
int getTopIndex() const
Return top index of this generator.
T & operator[](int n)
Get element.
Inform & endl(Inform &inf)
Definition: Inform.cpp:42
T * begin() const
Return beginning of monomial array.
Definition: FTps.h:118