MPQC 3.0.0-alpha
Loading...
Searching...
No Matches
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
31namespace {
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:
std::string prepend_spincase(SpinCase1 S, const std::string &R, bool lowercase=false)
Prepend string representation of S to R and return.

Generated at Wed Sep 25 2024 02:45:29 for MPQC 3.0.0-alpha using the documentation package Doxygen 1.12.0.