24 #include "OrbitalTransform.h"
25 #include "Hamiltonian.h"
27 #include "UnitaryMatrix.h"
46 unsigned long long maxlinsize = 0;
47 for (
int irrep=0; irrep< index.
getNirreps(); irrep++)
49 unsigned int linsize_irrep = index.
getNORB(irrep);
50 if (linsize_irrep > maxlinsize)
51 maxlinsize = linsize_irrep;
55 auto& maxBlockSize = maxlinsize;
57 auto maxBSpower4 = maxBlockSize * maxBlockSize * maxBlockSize * maxBlockSize;
58 auto sizeWorkmem1 = max( max( maxBSpower4 , 3*maxlinsize*maxlinsize ) , 1uLL * L * L );
59 auto sizeWorkmem2 = max( max( maxBSpower4 , 2*maxlinsize*maxlinsize ) , L*(L + 1uLL) );
60 mem1.reset(
new double[sizeWorkmem1]);
61 mem2.reset(
new double[sizeWorkmem2]);
66 assert(&HamCI != _hamorig.get());
71 for (
int irrep1 = 0; irrep1<numberOfIrreps; irrep1++)
72 for (
int irrep2 = irrep1; irrep2<numberOfIrreps; irrep2++)
74 const int productSymm = SymmInfo.
directProd(irrep1,irrep2);
75 for (
int irrep3 = irrep1; irrep3<numberOfIrreps; irrep3++)
77 const int irrep4 = SymmInfo.
directProd(productSymm,irrep3);
81 int linsize1 = index.
getNORB(irrep1);
82 int linsize2 =index.
getNORB(irrep2);
83 int linsize3 =index.
getNORB(irrep3);
84 int linsize4 =index.
getNORB(irrep4);
86 if ((linsize1>0) && (linsize2>0) && (linsize3>0) && (linsize4>0))
88 for (
int cnt1=0; cnt1<linsize1; cnt1++)
89 for (
int cnt2=0; cnt2<linsize2; cnt2++)
90 for (
int cnt3=0; cnt3<linsize3; cnt3++)
91 for (
int cnt4=0; cnt4<linsize4; cnt4++)
92 mem1[cnt1 + linsize1 * ( cnt2 + linsize2 * (cnt3 + linsize3 * cnt4) ) ]
100 int rightdim = linsize2 * linsize3 * linsize4;
101 double * Umx = _unitary->getBlock(irrep1);
102 dgemm_(¬ra, ¬ra, &linsize1, &rightdim, &linsize1, &alpha, Umx, &linsize1, mem1.get(), &linsize1, &beta, mem2.get(), &linsize1);
104 int leftdim = linsize1 * linsize2 * linsize3;
105 Umx = _unitary->getBlock(irrep4);
106 dgemm_(¬ra, &trans, &leftdim, &linsize4, &linsize4, &alpha, mem2.get(), &leftdim, Umx, &linsize4, &beta, mem1.get(), &leftdim);
108 int jump1 = linsize1 * linsize2 * linsize3;
109 int jump2 = linsize1 * linsize2 * linsize3;
110 leftdim = linsize1 * linsize2;
111 Umx = _unitary->getBlock(irrep3);
112 for (
int bla=0; bla<linsize4; bla++)
113 dgemm_(¬ra, &trans, &leftdim, &linsize3, &linsize3, &alpha, mem1.get()+jump1*bla, &leftdim, Umx, &linsize3, &beta, mem2.get()+jump2*bla, &leftdim);
115 jump2 = linsize1 * linsize2;
116 jump1 = linsize1 * linsize2;
117 rightdim = linsize3 * linsize4;
118 Umx = _unitary->getBlock(irrep2);
119 for (
int bla=0; bla<rightdim; bla++)
120 dgemm_(¬ra, &trans, &linsize1, &linsize2, &linsize2, &alpha, mem2.get()+jump2*bla, &linsize1, Umx, &linsize2, &beta, mem1.get()+jump1*bla, &linsize1);
122 for (
int cnt1=0; cnt1<linsize1; cnt1++)
123 for (
int cnt2=0; cnt2<linsize2; cnt2++)
124 for (
int cnt3=0; cnt3<linsize3; cnt3++)
125 for (
int cnt4=0; cnt4<linsize4; cnt4++)
126 HamCI.
setVmat(index.
getNstart(irrep1) + cnt1,index.
getNstart(irrep2) + cnt2, index.
getNstart(irrep3) + cnt3,index.
getNstart(irrep4) + cnt4, mem1[cnt1 + linsize1 * ( cnt2 + linsize2 * (cnt3 + linsize3 * cnt4) ) ] );
140 if(!QmatrixWork.size() || !OneBodyMatrixElements.size())
142 QmatrixWork.resize(numberOfIrreps);
143 OneBodyMatrixElements.resize(numberOfIrreps);
145 for (
int irrep=0; irrep<numberOfIrreps; irrep++)
148 QmatrixWork[irrep].reset(
new double[size]);
149 OneBodyMatrixElements[irrep].reset(
new double[size]);
154 for (
int irrep=0; irrep<numberOfIrreps; irrep++)
156 const int linsize = index.
getNORB(irrep);
157 for (
int row=0; row<linsize; row++)
159 const int HamIndex1 = index.
getNstart(irrep) + row;
161 OneBodyMatrixElements[irrep][row*(1+linsize)] = _hamorig->getTmat(HamIndex1,HamIndex1);
162 for (
int col=row+1; col<linsize; col++)
164 const int HamIndex2 = index.
getNstart(irrep) + col;
166 OneBodyMatrixElements[irrep][row + linsize * col] = _hamorig->getTmat(HamIndex1,HamIndex2);
167 OneBodyMatrixElements[irrep][col + linsize * row] = OneBodyMatrixElements[irrep][row + linsize * col];
171 rotate_old_to_new(OneBodyMatrixElements.data());
180 void OrbitalTransform::rotate_old_to_new(std::unique_ptr<
double []> * matrix)
183 for (
int irrep=0; irrep<numberOfIrreps; irrep++)
188 double * Umx = _unitary->getBlock(irrep);
194 dgemm_(¬rans,¬rans,&linsize,&linsize,&linsize,&alpha,Umx,&linsize,matrix[irrep].
get(),&linsize,&beta,QmatrixWork[irrep].
get(),&linsize);
196 dgemm_(¬rans,&trans, &linsize,&linsize,&linsize,&alpha,QmatrixWork[irrep].
get(),&linsize,Umx,&linsize,&beta,matrix[irrep].
get(),&linsize);
203 if(!OneBodyMatrixElements.size())
205 std::cerr <<
"First build the OneBodyMatrixElements!" << std::endl;
209 const int irrep1 = _hamorig->getOrbitalIrrep(index1);
210 const int irrep2 = _hamorig->getOrbitalIrrep(index2);
212 if (irrep1 != irrep2)
218 return OneBodyMatrixElements[irrep1][index1-shift + index.
getNORB(irrep1) * (index2-shift)];
224 double value = _hamorig->getEconst();
228 for (
int irrep=0; irrep<numberOfIrreps; irrep++)
230 const int linsize = index.
getNORB(irrep);
231 for (
int cnt1=0; cnt1<linsize; cnt1++)
232 for (
int cnt2=cnt1; cnt2<linsize; cnt2++)
235 Ham.
setTmat( cnt1 + shift , cnt2 + shift ,
TmatRotated(cnt1 + shift , cnt2 + shift) );
249 _unitary->CheckDeviationFromUnitary(mem2.get());
264 _unitary->updateUnitary(mem1.get(),mem2.get(),change,1);
275 _unitary->updateUnitary(mem1.get(),mem2.get(),X,replace);
292 const int linsize = index.
getNORB(irrep);
293 const int shift = index.
getNstart(irrep);
295 const int k2 = k - shift;
296 const int l2 = l - shift;
298 const double cos = std::cos(theta);
299 const double sin = std::sin(theta);
304 const double tmpkk = ham_rot.
getTmat(k,k);
305 const double tmpll = ham_rot.
getTmat(l,l);
306 const double tmpkl = ham_rot.
getTmat(k,l);
309 tmp = cos*cos*tmpkk+sin*sin*tmpll-2*cos*sin*tmpkl;
312 tmp = cos*cos*tmpll+sin*sin*tmpkk+2*cos*sin*tmpkl;
315 tmp = tmpkl*(cos*cos-sin*sin)+cos*sin*(tmpkk-tmpll);
318 for(
int a=shift;a<linsize+shift;a++)
323 const double tmpk = ham_rot.
getTmat(k,a);
324 const double tmpl = ham_rot.
getTmat(l,a);
326 tmp = cos * tmpk - sin * tmpl;
329 tmp = cos * tmpl + sin * tmpk;
338 for (
int irrep1 = 0; irrep1<numberOfIrreps; irrep1++)
339 for (
int irrep2 = irrep1; irrep2<numberOfIrreps; irrep2++)
341 const int productSymm = SymmInfo.
directProd(irrep1, irrep2);
342 for (
int irrep3 = irrep1; irrep3<numberOfIrreps; irrep3++)
344 const int irrep4 = SymmInfo.
directProd(productSymm, irrep3);
346 if(irrep4>=irrep2 && (irrep4==irrep || irrep3==irrep || irrep2==irrep || irrep1==irrep))
348 const int linsize1 = index.
getNORB(irrep1);
349 const int linsize2 = index.
getNORB(irrep2);
350 const int linsize3 = index.
getNORB(irrep3);
351 const int linsize4 = index.
getNORB(irrep4);
353 if ((linsize1>0) && (linsize2>0) && (linsize3>0) && (linsize4>0))
355 for (
int cnt1=0; cnt1<linsize1; cnt1++)
356 for (
int cnt2=0; cnt2<linsize2; cnt2++)
357 for (
int cnt3=0; cnt3<linsize3; cnt3++)
358 for (
int cnt4=0; cnt4<linsize4; cnt4++)
359 mem1[cnt1 + linsize1 * ( cnt2 + linsize2 * (cnt3 + linsize3 * cnt4) ) ]
362 int rightdim = linsize2 * linsize3 * linsize4;
365 for(
int d=0;d<rightdim;d++)
367 const double tmpk = mem1[d*linsize1+k2];
368 const double tmpl = mem1[d*linsize1+l2];
370 mem1[d*linsize1+k2] = cos*tmpk-sin*tmpl;
371 mem1[d*linsize1+l2] = cos*tmpl+sin*tmpk;
374 int leftdim = linsize1 * linsize2 * linsize3;
377 for(
int d=0;d<leftdim;d++)
379 const double tmpk = mem1[k2*leftdim+d];
380 const double tmpl = mem1[l2*leftdim+d];
382 mem1[k2*leftdim+d] = cos*tmpk-sin*tmpl;
383 mem1[l2*leftdim+d] = cos*tmpl+sin*tmpk;
386 int jump = linsize1 * linsize2 * linsize3;
387 leftdim = linsize1 * linsize2;
390 for (
int strideidx=0;strideidx<linsize4;strideidx++)
391 for(
int d=0;d<leftdim;d++)
393 const double tmpk = mem1[k2*leftdim+d+jump*strideidx];
394 const double tmpl = mem1[l2*leftdim+d+jump*strideidx];
396 mem1[k2*leftdim+d+jump*strideidx] = cos*tmpk-sin*tmpl;
397 mem1[l2*leftdim+d+jump*strideidx] = cos*tmpl+sin*tmpk;
401 jump = linsize1 * linsize2;
402 rightdim = linsize3 * linsize4;
405 for (
int strideidx=0;strideidx<rightdim;strideidx++)
406 for(
int d=0;d<linsize1;d++)
408 const double tmpk = mem1[k2*linsize1+d+jump*strideidx];
409 const double tmpl = mem1[l2*linsize1+d+jump*strideidx];
411 mem1[k2*linsize1+d+jump*strideidx] = cos*tmpk-sin*tmpl;
412 mem1[l2*linsize1+d+jump*strideidx] = cos*tmpl+sin*tmpk;
415 for (
int cnt1=0; cnt1<linsize1; cnt1++)
416 for (
int cnt2=0; cnt2<linsize2; cnt2++)
417 for (
int cnt3=0; cnt3<linsize3; cnt3++)
418 for (
int cnt4=0; cnt4<linsize4; cnt4++)
419 ham_rot.
setVmat(index.
getNstart(irrep1) + cnt1,index.
getNstart(irrep2) + cnt2, index.
getNstart(irrep3) + cnt3,index.
getNstart(irrep4) + cnt4, mem1[cnt1 + linsize1 * ( cnt2 + linsize2 * (cnt3 + linsize3 * cnt4) ) ] );
bool setGroup(const int nGroup)
Set the group.
void setTmat(const int index1, const int index2, const double val)
Set a Tmat element.
int getOrbitalIrrep(const int nOrb) const
Get an orbital irrep number.
double getVmat(const int index1, const int index2, const int index3, const int index4) const
Get a Vmat element.
void setVmat(const int index1, const int index2, const int index3, const int index4, const double val)
Set a Vmat element.
void setEconst(const double val)
Set the constant energy.
double getTmat(const int index1, const int index2) const
Get a Tmat element.
int getNORB(const int irrep) const
int getNstart(const int irrep) const
static int directProd(const int Irrep1, const int Irrep2)
Get the direct product of the irreps with numbers Irrep1 and Irrep2: a bitwise XOR for Psi4's convent...
int getNGroup() const
Get the group number.
int getL() const
Get the number of orbitals.
void dgemm_(char *transA, char *transB, int *m, int *n, int *k, double *alpha, double *A, int *lda, double *B, int *ldb, double *beta, double *C, int *ldc)