MPQC  3.0.0-alpha
pt2r12_utils.h
1 //
2 // pt2r12_utils.h
3 //
4 // Copyright (C) 2011 Edward Valeev
5 //
6 // Author: Edward Valeev <evaleev@vt.edu>
7 // Maintainer: EV
8 //
9 // This file is part of the SC Toolkit.
10 //
11 // The SC Toolkit is free software; you can redistribute it and/or modify
12 // it under the terms of the GNU Library General Public License as published by
13 // the Free Software Foundation; either version 2, or (at your option)
14 // any later version.
15 //
16 // The SC Toolkit is distributed in the hope that it will be useful,
17 // but WITHOUT ANY WARRANTY; without even the implied warranty of
18 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 // GNU Library General Public License for more details.
20 //
21 // You should have received a copy of the GNU Library General Public License
22 // along with the SC Toolkit; see the file COPYING.LIB. If not, write to
23 // the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
24 //
25 // The U.S. Government is granted a limited license as per AL 91-7.
26 //
27 
28 #ifndef _mpqc_src_lib_chemistry_qc_mbptr12_pt2r12_utils_h
29 #define _mpqc_src_lib_chemistry_qc_mbptr12_pt2r12_utils_h
30 
31 namespace {
32 
34  int triang_half_INDEX_ordered(int i, int j) {
35  return(i*(i+1)/2+j);
36  }
37 
39  int triang_half_INDEX(int i, int j) {
40  return((i>j) ? triang_half_INDEX_ordered(i,j) : triang_half_INDEX_ordered(j,i));
41  }
42 
44  int ordinary_INDEX(int i, int j, int coldim) {
45  return(i*coldim+j);
46  }
47 
49  int tpdm_index(int i, int j, int k, int l,int coldim){
50  //int ind_half1=triang_half_INDEX(i,j);
51  //int ind_half2=triang_half_INDEX(k,l);
52  int ind_half1=ordinary_INDEX(i,j,coldim);
53  int ind_half2=ordinary_INDEX(k,l,coldim);
54  return(triang_half_INDEX(ind_half1,ind_half2));
55  }
56 
58  void vector_to_symmmatrix(RefSymmSCMatrix &matrix, const RefSCVector &vector) {
59  int dim = matrix.dim().n();
60  for(int i=0; i<dim; i++){
61  for(int j=0; j<=i; j++) {
62  matrix.set_element(i,j,vector.get_element(triang_half_INDEX(i,j)));
63  }
64  }
65  }
66 
68  void symmmatrix_to_vector(RefSCVector &vector, const RefSymmSCMatrix &matrix) {
69  int dim = matrix.dim().n();
70  for(int i=0; i<dim; i++){
71  for(int j=0; j<=i; j++) {
72  vector.set_element(triang_half_INDEX(i,j),matrix.get_element(i,j));
73  }
74  }
75  }
76 
78  void vector_to_matrix(RefSCMatrix &matrix, const RefSCVector &vector) {
79  int dim1 = matrix.rowdim().n();
80  int dim2 = matrix.coldim().n();
81  for(int i=0; i<dim1; i++) {
82  for(int j=0; j<dim2; j++) {
83  matrix.set_element(i,j,vector.get_element(ordinary_INDEX(i,j,dim2)));
84  }
85  }
86  }
87 
88  int lowerupper_index(int p, int q);
89 
91  void vector_to_matrix(RefSCMatrix &matrix,const RefSCVector &vector,const SpinCase2 &pairspin) {
92  int dim1 = matrix.rowdim().n();
93  int dim2 = matrix.coldim().n();
94  if(pairspin==AlphaBeta) {
95  for(int i=0; i<dim1; i++) {
96  for(int j=0; j<dim2; j++) {
97  matrix.set_element(i,j,vector.get_element(ordinary_INDEX(i,j,dim2)));
98  }
99  }
100  }
101  else { // pairspin==AlphaAlpha || pairspin==BetaBeta
102  matrix->assign(0.0);
103  for(int i=0; i<dim1; i++) {
104  for(int j=0; j<i; j++) {
105  const double value = vector.get_element(lowerupper_index(i,j));
106  matrix.set_element(i,j,value);
107  matrix.set_element(j,i,-value);
108  }
109  }
110  }
111  }
112 
114  void matrix_to_vector(RefSCVector &vector, const RefSCMatrix &matrix) {
115  int dim1 = matrix.rowdim().n();
116  int dim2 = matrix.coldim().n();
117  for(int i=0; i<dim1; i++) {
118  for(int j=0; j<dim2; j++) {
119  vector.set_element(ordinary_INDEX(i,j,dim2),matrix.get_element(i,j));
120  }
121  }
122  }
123 
125  void matrix_to_vector(RefSCVector &vector, const RefSymmSCMatrix &matrix) {
126  int n = matrix.dim().n();
127  for(int i=0; i<n; i++) {
128  for(int j=0; j<=i; j++) {
129  const double value = matrix.get_element(i,j);
130  vector.set_element(ordinary_INDEX(i,j,n),value);
131  vector.set_element(ordinary_INDEX(j,i,n),value);
132  }
133  }
134  }
135 
137  void matrix_to_vector(RefSCVector &vector, const RefDiagSCMatrix &matrix) {
138  int n = matrix.dim().n();
139  for(int i=0; i<n; i++) {
140  const double value = matrix.get_element(i);
141  vector.set_element(ordinary_INDEX(i,i,n),value);
142  }
143  }
144 
146  void matrix_to_vector(RefSCVector &vector, const RefSCMatrix &matrix,const SpinCase2 &pairspin) {
147  int dim1 = matrix.rowdim().n();
148  int dim2 = matrix.coldim().n();
149  if(pairspin==AlphaBeta) {
150  for(int i=0; i<dim1; i++) {
151  for(int j=0; j<dim2; j++) {
152  vector.set_element(ordinary_INDEX(i,j,dim2),matrix.get_element(i,j));
153  }
154  }
155  }
156  else { // pairspin==AlphaAlpha || pairspin==BetaBeta
157  for(int i=0; i<dim1; i++) {
158  for(int j=0; j<i; j++) {
159  vector.set_element(lowerupper_index(i,j),matrix.get_element(i,j));
160  }
161  }
162  }
163  }
164 
165 
166  int lowertriang_index(int p,int q) {
167  if(q>=p){
168  throw ProgrammingError("lowertriang_index(p,q) -- q must be smaller than p.",__FILE__,__LINE__);
169  }
170  int index=p*(p+1)/2+q-p;
171  return(index);
172  }
173 
174  int lowerupper_index(int p, int q) {
175  if(p>q) {
176  return(lowertriang_index(p,q));
177  }
178  else if(q>p) {
179  return(lowertriang_index(q,p));
180  }
181  else {
182  throw ProgrammingError("lowerupper_index(p,q) -- p and q are not allowed to be equal.",__FILE__,__LINE__);
183  }
184  }
185  double indexsizeorder_sign(int p,int q) {
186  if(p>q) {
187  return(1.0);
188  }
189  else if(q>p) {
190  return(-1.0);
191  }
192  else {
193  return(0.0);
194  }
195  }
196 
197  int antisym_pairindex(int i, int j) {
198  int max_ij = std::max(i, j);
199  int min_ij = std::min(i, j);
200  return (max_ij -1)* max_ij/2 + min_ij;
201  }
202 
206  template <typename MatrixType>
207  double get_4ind_antisym_matelement(MatrixType & MM, const int & U1, const int & U2,
208  const int & L1, const int & L2)
209  {
210  if(U1 == U2 || L1 == L2) return 0.0;
211  else
212  {
213  int uppind = antisym_pairindex(U1, U2);
214  int lowind = antisym_pairindex(L1, L2);
215  const double totalsign = indexsizeorder_sign(U1,U2) * indexsizeorder_sign(L1, L2);
216  return totalsign * MM.get_element(uppind, lowind);
217  }
218  }
219 
222  template <typename MatrixType>
223  double get_4ind_matelement(MatrixType & MM, const int & U1, const int & U2,
224  const int & L1, const int & L2,
225  const int & UppDim, const int & LowDim)
226  {
227  int uppind = U1 * UppDim + U2;
228  int lowind = L1 * LowDim + L2;
229  return MM.get_element(uppind, lowind);
230  }
231 
232  RefSCMatrix convert_RefSC_to_local_kit(const RefSCMatrix& A)
233  {
234  RefSCMatrix result;
235  Ref<LocalSCMatrixKit> kit_cast_to_local; kit_cast_to_local << A.kit();
236  if (kit_cast_to_local.null()) {
237  Ref<LocalSCMatrixKit> local_kit = new LocalSCMatrixKit();
238  RefSCMatrix A_local = local_kit->matrix(A.rowdim(), A.coldim());
239  A_local->convert(A);
240  result = A_local;
241  }
242  else
243  result = A;
244  return result;
245  }
246 
247 
248  RefSCMatrix transform_one_ind(RefSCMatrix AA, RefSCMatrix BB, int whichindex, int onedim) // transform one index. A is a two-index tensor;
249  { // B is a 4-ind tensor; whichindex tells which to transform; onedim (1-4) tells the dimension of one ind; the second ind of A is the dummy
250 #if 0
251  ExEnv::out0() << "test transform_one_ind:\n";
252  ExEnv::out0() << (onedim*onedim)<< ", " << BB->nrow() << ", "<< BB->ncol() << "\n";
253  AA.print(prepend_spincase(AlphaBeta, "transform_one_ind: AA").c_str());
254  BB.print(prepend_spincase(AlphaBeta, "transform_one_ind: BB").c_str());
255 #endif
256  MPQC_ASSERT(((onedim*onedim) == BB->nrow()) and (BB->nrow() == BB->ncol()));
257  RefSCMatrix res = BB->clone();
258  res.assign(0.0);
259  int ext_ind, int_ind, row, col, Ap, Bp, Cp, Dp, A, B, C, D, a, b, c, d, f;
260  ext_ind = int_ind = row = col = Ap = Bp = Cp = Dp = A = B = C = D = a = b = c = d = f = 0;
261  double xx = 0;
262  for (a = 0; a < onedim; ++a) // the external index of A
263  {
264  for (b = 0; b < onedim; ++b)
265  {
266  for (c = 0; c < onedim; ++c)
267  {
268  for (d = 0; d < onedim; ++d)
269  {
270  xx = 0;
271  for (f = 0; f < onedim; ++f) // dummy index
272  {
273  switch (whichindex)
274  {
275  case 1: // Gamma^AB_CD * C_A^Ap
276  ext_ind = Ap = a; int_ind = A = f; B = b; C = c; D = d;// by renaming, we have BB always of the same form, convenient
277  xx += AA->get_element(ext_ind, int_ind) * BB->get_element(A*onedim + B, C*onedim + D);
278  break;
279  case 2: // Gamma^AB_CD * C_B^Bp
280  ext_ind = Bp = a; int_ind = B = f; A = b; C = c; D = d;
281  xx += AA->get_element(ext_ind, int_ind) *BB->get_element(A*onedim + B, C*onedim + D);
282  break;
283  case 3: // C_Cp^C * Gamma^AB_CD
284  ext_ind = Cp = a; int_ind = C = f; A = b; B = c; D = d;
285  xx += BB->get_element(A*onedim + B, C*onedim + D)*AA->get_element(ext_ind, int_ind);//AA->(ext,int) == Transpose(AA)(int, ext)
286  break;
287  case 4: // C_Dp^D * Gamma^AB_CD
288  ext_ind = Dp = a; int_ind = D = f; A = b; B = c; C = d;
289  xx += BB->get_element(A*onedim + B, C*onedim + D)*AA->get_element(ext_ind, int_ind);
290  break;
291  default: abort();
292  }
293  }
294  switch (whichindex)
295  {
296  case 1:// Gamma^AB_CD * C_A^Ap
297  col = C*onedim + D; row = Ap*onedim +B;
298  break;
299  case 2:// Gamma^AB_CD * C_B^Bp
300  col = C*onedim + D; row = A*onedim + Bp;
301  break;
302  case 3: // C_Cp^C * Gamma^AB_CD
303  col = Cp *onedim + D; row = A*onedim + B;
304  break;
305  case 4: // C_Dp^D * Gamma^AB_CD
306  col = C*onedim + Dp; row = A*onedim + B;
307  break;
308  default: abort();
309  }
310  res->set_element(row,col, xx);
311 // ExEnv::out0() << "row, col, xx: " << row << ", " << col << ", " << xx << "\n";
312  }
313  }
314  }
315  }
316  //res.print(prepend_spincase(AlphaBeta, "transform_one_ind: res").c_str());
317  return res;
318  }
319 
320  RefSymmSCMatrix convert_to_local_kit(const RefSymmSCMatrix& A) { //forward declaration
321  RefSymmSCMatrix result;
322  Ref<LocalSCMatrixKit> kit_cast_to_local; kit_cast_to_local << A.kit();
323  if (kit_cast_to_local.null()) {
324  Ref<LocalSCMatrixKit> local_kit = new LocalSCMatrixKit();
325  RefSymmSCMatrix A_local = local_kit->symmmatrix(A.dim());
326  A_local->convert(A);
327  result = A_local;
328  }
329  else
330  result = A;
331  return result;
332  }
333 
335  RefSCMatrix RefSCMAT_combine234(RefSCMatrix mat, const int b1, const int b2,
336  const int k1, const int k2)
337  {
338  const int ncol = b2 * k1 * k2;
339  RefSCDimension rowdim = new SCDimension(b1);
340  RefSCDimension coldim = new SCDimension(b2*k1*k2);
341  RefSCMatrix res = mat->kit()->matrix(rowdim, coldim);
342  res->assign(0.0);
343  const int num_e = k2*k1;
344 
345  for (int I1 = 0; I1 < b1; ++I1)
346  {
347  for (int I2 = 0; I2 < b2; ++I2)
348  {
349  const int mat_row = I1 * b2 + I2;
350  const int blockbegin = I2*num_e;
351  const int blockend = blockbegin + num_e - 1;
352 
353 // RefSCVector k1k2row = mat->get_row(mat_row);
354 // RefSCMatrix temp_mat = mat->kit()->matrix(new SCDimension(1), mat->coldim());
355 // temp_mat->assign_row(k1k2row, 0);
356 // res->assign_subblock(temp_mat, I1, I1, blockbegin, blockend);
357  res->assign_subblock(mat, I1, I1, blockbegin, blockend, mat_row, 0);
358  }
359  }
360  return res;
361  }
362 
363 
364 } // end of anonymous namespace
365 
366 #endif // end of header guard
367 
368 
369 // Local Variables:
370 // mode: c++
371 // c-file-style: "CLJ-CONDENSED"
372 // End:
sc::prepend_spincase
std::string prepend_spincase(SpinCase1 S, const std::string &R, bool lowercase=false)
Prepend string representation of S to R and return.

Generated at Sun Jan 26 2020 23:23:59 for MPQC 3.0.0-alpha using the documentation package Doxygen 1.8.16.