OPAL (Object Oriented Parallel Accelerator Library)  2.2.0
OPAL
rdm.h
Go to the documentation of this file.
1 
10 #ifndef RDM_H
11 #define RDM_H
12 
13 #include <cmath>
14 #include <iostream>
15 #include <stdexcept>
16 
17 #include <boost/numeric/ublas/matrix_sparse.hpp>
18 #include <boost/numeric/ublas/matrix.hpp>
19 #include <boost/numeric/ublas/vector.hpp>
20 
22 
23 // Remark: Comments starting with "///" are doxygen comments, comments with "//" are normal comments.
24 
26 template<typename Value_type, typename Size_type>
27 class RDM
28 {
29  public:
31  typedef Value_type value_type;
33  typedef Size_type size_type;
35  typedef boost::numeric::ublas::compressed_matrix<value_type,boost::numeric::ublas::row_major> sparse_matrix_type;
37  typedef boost::numeric::ublas::matrix<value_type> matrix_type;
39  typedef boost::numeric::ublas::vector<value_type> vector_type;
40 
42  RDM();
43 
45 
49 
51 
55 
57 
61 
63 
69 
71 
75 
77 
81 
83  short NumOfRDMs;
85  short DimOfRDMs;
86 
87  private:
89 
97 };
98 
99 // -----------------------------------------------------------------------------------------------------------------------
100 // PUBLIC MEMBER FUNCTIONS
101 // -----------------------------------------------------------------------------------------------------------------------
102 
103 template<typename Value_type, typename Size_type>
104 RDM<Value_type, Size_type>::RDM() : NumOfRDMs(16), DimOfRDMs(4) {};
105 
106 template<typename Value_type, typename Size_type>
108  sparse_matrix_type rdm(4,4,4); // #nrows, #ncols, #non-zeros
109  switch(i) {
110  case 0: rdm(0,1) = rdm(2,3) = 1; rdm(1,0) = rdm(3,2) = -1; break;
111  case 1: rdm(0,1) = rdm(1,0) = -1; rdm(2,3) = rdm(3,2) = 1; break;
112  case 2: rdm(0,3) = rdm(1,2) = rdm(2,1) = rdm(3,0) = 1; break;
113  case 3: rdm(0,0) = rdm(2,2) = -1; rdm(1,1) = rdm(3,3) = 1; break;
114  case 4: rdm(0,0) = rdm(3,3) = -1; rdm(1,1) = rdm(2,2) = 1; break;
115  case 5: rdm(0,2) = rdm(2,0) = 1; rdm(1,3) = rdm(3,1) = -1; break;
116  case 6: rdm(0,1) = rdm(1,0) = rdm(2,3) = rdm(3,2) = 1; break;
117  case 7: rdm(0,3) = rdm(2,1) = 1; rdm(1,2) = rdm(3,0) = -1; break;
118  case 8: rdm(0,1) = rdm(3,2) = 1; rdm(1,0) = rdm(2,3) = -1; break;
119  case 9: rdm(0,2) = rdm(1,3) = -1; rdm(2,0) = rdm(3,1) = 1; break;
120  case 10: rdm(0,2) = rdm(3,1) = 1; rdm(1,3) = rdm(2,0) = -1; break;
121  case 11: rdm(0,2) = rdm(1,3) = rdm(2,0) = rdm(3,1) = -1; break;
122  case 12: rdm(0,0) = rdm(1,1) = -1; rdm(2,2) = rdm(3,3) = 1; break;
123  case 13: rdm(0,3) = rdm(3,0) = -1; rdm(1,2) = rdm(2,1) = 1; break;
124  case 14: rdm(0,3) = rdm(1,2) = -1; rdm(2,1) = rdm(3,0) = 1; break;
125  case 15: rdm(0,0) = rdm(1,1) = rdm(2,2) = rdm(3,3) = 1; break;
126  default: throw std::out_of_range("Error in RDM::generate: 0 <= i <= 15"); break;
127  }
128  return rdm;
129 }
130 
131 template<typename Value_type, typename Size_type>
133  /*
134  * Formula (11) from paper:
135  * Geometrical method of decoupling
136  */
137  if (M.size1() != 4 && M.size1() != M.size2())
138  throw std::length_error("Error in RDM::decompose: Wrong matrix dimensions.");
139 
140  vector_type coeffs(16);
141 
142  matrix_type left(4,4), right(4,4), rdm2(4,4);
143 
144  value_type inv32 = 1.0 / 32.0;
145 
146  // do it with iterators
147  for (short i = 0; i < 16; ++i) {
148  sparse_matrix_type rdm = getRDM(i);
149  left = boost::numeric::ublas::prod(M,rdm);
150  right = boost::numeric::ublas::prod(rdm,M);
151  rdm2 = boost::numeric::ublas::prod(rdm,rdm);
152  left *= inv32;
153  right *= inv32;
154  left += right;
155  coeffs(i) = matt_boost::trace(rdm2) * matt_boost::trace(left);
156  }
157  return coeffs;
158 }
159 
160 template<typename Value_type, typename Size_type>
162  if (coeffs.size() > 16)
163  throw std::length_error("Error in RDM::combine: Wrong size of coefficient vector.");
164 
165  // initialize a 4x4 zero matrix
166  matrix_type M = boost::numeric::ublas::zero_matrix<value_type>(4,4);
167 
168  // evaluate linear combination
169  for (short i = 0; i < 16; ++i)
170  M += coeffs(i)*getRDM(i);
171 
172  return M;
173 }
174 
175 template<typename Value_type, typename Size_type>
177 
178  // R and invR store the total transformation
179  R = boost::numeric::ublas::identity_matrix<value_type>(4);
180  invR = R;
181 
182  vector_type P(3), E(3), B(3), b;
183  value_type mr, mg, mb, eps;
184 
185  // Lambda function to compute vectors E, P, B and scalar eps (it takes the current Ms as reference argument (--> [&])
186  auto mult = [&](short i) {
187  /*
188  * For computing E, P, B, eps according to formula (C4) from paper:
189  * Geometrical method of decoupling
190  */
191  matrix_type tmp = boost::numeric::ublas::prod(Ms,getRDM(i))+boost::numeric::ublas::prod(getRDM(i),Ms);
192  return 0.125*matt_boost::trace(tmp);
193  };
194 
195  // 1. Transformation with \gamma_{0}
196  P(0) = mult(1); P(1) = mult(2); P(2) = mult(3);
197  E(0) = mult(4); E(1) = mult(5); E(2) = mult(6);
198  B(0) = -mult(7); B(1) = -mult(8); B(2) = -mult(9);
199  mr = boost::numeric::ublas::inner_prod(E,B); // formula (31), paper: Geometrical method of decoupling
200  mg = boost::numeric::ublas::inner_prod(B,P); // formula (31), paper: Geometrical method of decoupling
201 
202  transform(Ms,short(0),0.5 * std::atan2(mg,mr),R,invR);
203 
204  // 2. Transformation with \gamma_{7}
205  eps = -mult(0);
206  P(0) = mult(1); P(1) = mult(2); P(2) = mult(3);
207  E(0) = mult(4); E(1) = mult(5); E(2) = mult(6);
208  B(0) = -mult(7); B(1) = -mult(8); B(2) = -mult(9);
209  b = eps*B+matt_boost::cross_prod(E,P); // formula (32), paper: Geometrical method of decoupling
210 
211  transform(Ms,short(7),0.5 * std::atan2(b(2),b(1)),R,invR);
212 
213  // 3. Transformation with \gamma_{9}
214  eps = -mult(0);
215  P(0) = mult(1); P(1) = mult(2); P(2) = mult(3);
216  E(0) = mult(4); E(1) = mult(5); E(2) = mult(6);
217  B(0) = -mult(7); B(1) = -mult(8); B(2) = -mult(9);
218  b = eps*B+matt_boost::cross_prod(E,P);
219 
220  transform(Ms,short(9),-0.5 * std::atan2(b(0),b(1)),R,invR);
221 
222  // 4. Transformation with \gamma_{2}
223  eps = -mult(0);
224  P(0) = mult(1); P(1) = mult(2); P(2) = mult(3);
225  E(0) = mult(4); E(1) = mult(5); E(2) = mult(6);
226  B(0) = -mult(7); B(1) = -mult(8); B(2) = -mult(9);
227  mr = boost::numeric::ublas::inner_prod(E,B);
228  b = eps*B+matt_boost::cross_prod(E,P);
229 
230  // Transformation distinction made according to function "rdm_Decouple_F" in rdm.c of Dr. Christian Baumgarten
231 
232  if (std::fabs(mr) < std::fabs(b(1))) {
233  transform(Ms,short(2),0.5 * std::atanh(mr / b(1)),R,invR);
234  } else {
235  transform(Ms,short(2),0.5 * std::atanh(b(1) / mr),R,invR);
236  }
237 
238  eps = -mult(0);
239  P(0) = mult(1); P(1) = mult(2); P(2) = mult(3);
240  E(0) = mult(4); E(1) = mult(5); E(2) = mult(6);
241  B(0) = -mult(7); B(1) = -mult(8); B(2) = -mult(9);
242 
243  // formula (31), paper: Geometrical method of decoupling
244  mr = boost::numeric::ublas::inner_prod(E,B);
245  mg = boost::numeric::ublas::inner_prod(B,P);
246  mb = boost::numeric::ublas::inner_prod(E,P);
247 
248  value_type P2 = boost::numeric::ublas::inner_prod(P,P);
249  value_type E2 = boost::numeric::ublas::inner_prod(E,E);
250 
251  // 5. Transform with \gamma_{0}
252  transform(Ms,short(0),0.25 * std::atan2(mb,0.5 * (E2 - P2)),R,invR);
253 
254  // 6. Transformation with \gamma_{8}
255  P(0) = mult(1); P(2) = mult(3);
256 
257  transform(Ms,short(8),-0.5 * std::atan2(P(2),P(0)),R,invR);
258 }
259 
260 template<typename Value_type, typename Size_type>
262  /*
263  * formula(16), p. 3
264  */
265  sparse_matrix_type rdm0 = getRDM(0);
266  return 0.5 * (M + matt_boost::gemmm<matrix_type>(rdm0,boost::numeric::ublas::trans(M),rdm0));
267 }
268 
269 
270 template<typename Value_type, typename Size_type>
272  /*
273  * formula (16), p, 3
274  */
275  sparse_matrix_type rdm0 = getRDM(0);
276  return 0.5 * (M - matt_boost::gemmm<matrix_type>(rdm0,boost::numeric::ublas::trans(M),rdm0));
277 }
278 
279 // -----------------------------------------------------------------------------------------------------------------------
280 // PRIVATE MEMBER FUNCTIONS
281 // -----------------------------------------------------------------------------------------------------------------------
282 
283 template<typename Value_type, typename Size_type>
285 
286  if (phi) { // if phi == 0 --> nothing happens, since R and invR would be identity_matrix matrix
287  sparse_matrix_type R(4,4), invR(4,4);
288  sparse_matrix_type I = boost::numeric::ublas::identity_matrix<value_type>(4);
289 
290  if (i < 7 && i != 0 && i < 11 && i != 14) {
291  R = I * std::cosh(phi) + getRDM(i) * std::sinh(phi);
292  invR = I * std::cosh(phi) - getRDM(i) * std::sinh(phi);
293  } else {
294  R = I * std::cos(phi) + getRDM(i) * std::sin(phi);
295  invR = I * std::cos(phi) - getRDM(i) * std::sin(phi);
296  }
297  // update matrices
298  M = matt_boost::gemmm<matrix_type>(R,M,invR);
299  Rtot = boost::numeric::ublas::prod(R,Rtot);
300  invRtot = boost::numeric::ublas::prod(invRtot,invR);
301  }
302 }
303 
304 #endif
Size_type size_type
Type for specifying sizes.
Definition: rdm.h:33
void transform(matrix_type &, short, value_type, sparse_matrix_type &, sparse_matrix_type &)
Applies a rotation to the matrix M by a given angle.
Definition: rdm.h:284
PETE_TUTree< FnFabs, typename T::PETE_Expr_t > fabs(const PETE_Expr< T > &l)
Definition: PETE.h:815
Tps< T > sin(const Tps< T > &x)
Sine.
Definition: TpsMath.h:111
short DimOfRDMs
The matrix dimension (4x4)
Definition: rdm.h:85
matrix_type symplex(const matrix_type &)
Returns the symplex part of a 4x4 real-valued matrix.
Definition: rdm.h:261
Tps< T > cosh(const Tps< T > &x)
Hyperbolic cosine.
Definition: TpsMath.h:222
matrix_type combine(const vector_type &)
Takes a vector of coefficients, evaluates the linear combination of RDMs with these coefficients and ...
Definition: rdm.h:161
boost::numeric::ublas::vector< value_type > vector_type
Dense vector type definition.
Definition: rdm.h:39
void diagonalize(matrix_type &, sparse_matrix_type &, sparse_matrix_type &)
Brings a 4x4 symplex matrix into Hamilton form and computes the transformation matrix and its inverse...
Definition: rdm.h:176
PETE_TBTree< FnArcTan2, PETE_Scalar< Vektor< T1, Dim > >, typename T2::PETE_Expr_t > atan2(const Vektor< T1, Dim > &l, const PETE_Expr< T2 > &r)
boost::numeric::ublas::matrix< value_type > matrix_type
Dense matrix type definition.
Definition: rdm.h:37
boost::numeric::ublas::compressed_matrix< value_type, boost::numeric::ublas::row_major > sparse_matrix_type
Sparse matrix type definition.
Definition: rdm.h:35
BOOST_UBLAS_INLINE V trace(ublas::matrix< V > &e)
Computes the trace of a square matrix.
Tps< T > cos(const Tps< T > &x)
Cosine.
Definition: TpsMath.h:129
T::PETE_Expr_t::PETE_Return_t prod(const PETE_Expr< T > &expr)
Definition: PETE.h:1243
vector_type decompose(const matrix_type &)
Decomposes a real-valued 4x4 matrix into a linear combination and returns a vector containing the coe...
Definition: rdm.h:132
Real Dirac Matrix class.
Definition: rdm.h:27
Value_type value_type
Type of variables.
Definition: rdm.h:31
short NumOfRDMs
The number of real Dirac matrices.
Definition: rdm.h:83
sparse_matrix_type getRDM(short)
Returns the i-th Real Dirac matrix.
Definition: rdm.h:107
BOOST_UBLAS_INLINE ublas::vector< V > cross_prod(ublas::vector< V > &v1, ublas::vector< V > &v2)
Computes the cross product of two vectors in .
Tps< T > sinh(const Tps< T > &x)
Hyperbolic sine.
Definition: TpsMath.h:204
matrix_type cosymplex(const matrix_type &)
Returns the cosymplex part of a 4x4 real-valued matrix.
Definition: rdm.h:271
RDM()
Default constructor (sets only NumOfRDMs and DimOfRDMs)
Definition: rdm.h:104