24 #include "Tensor3RDM.h" 55 assert( two_j1 == Sigma->
get_2j() );
58 const int two_j2 =
two_j;
60 for (
int ikappa = 0; ikappa <
nKappa; ikappa++ ){
73 for (
int two_jl_down = two_jr_down-1; two_jl_down <= two_jr_down+1; two_jl_down+=2 ){
78 if (( dimLup > 0 ) && ( dimLdown > 0 ) && ( abs( two_jr_up - two_jl_down ) <= two_j1 )){
80 double * Sblock = Sigma->
gStorage( nr_up, two_jr_up, ir_up, nr_up+2, two_jl_down, il_down );
81 double * Tup = denT->
gStorage( nr_up, two_jr_up, ir_up, nr_up, two_jr_up, ir_up );
82 double * Tdown = denT->
gStorage( nr_up+2, two_jl_down, il_down, nr_up+3, two_jr_down, ir_down );
84 double alpha = sqrt( 1.0 * ( two_j2 + 1 ) * ( two_jl_down + 1 ) )
90 dgemm_( ¬rans, ¬rans, &dimLup, &dimRdown, &dimLdown, &alpha, Sblock, &dimLup, Tdown, &dimLdown, &beta, workmem, &dimLup );
93 dgemm_( &trans, ¬rans, &dimRup, &dimRdown, &dimLup, &alpha, Tup, &dimLup, workmem, &dimLup, &beta,
storage +
kappa2index[ikappa], &dimRup );
100 for (
int two_jl_up = two_jr_up-1; two_jl_up <= two_jr_up+1; two_jl_up+=2 ){
105 if (( dimLup > 0 ) && ( dimLdown > 0 ) && ( abs( two_jr_down - two_jl_up ) <= two_j1 )){
107 double * Sblock = Sigma->
gStorage( nr_up-1, two_jl_up, il_up, nr_up+1, two_jr_down, ir_down );
108 double * Tup = denT->
gStorage( nr_up-1, two_jl_up, il_up, nr_up, two_jr_up, ir_up );
109 double * Tdown = denT->
gStorage( nr_up+1, two_jr_down, ir_down, nr_up+3, two_jr_down, ir_down );
111 double alpha = sqrt( 1.0 * ( two_j2 + 1 ) * ( two_jr_up + 1 ) )
117 dgemm_( ¬rans, ¬rans, &dimLup, &dimRdown, &dimLdown, &alpha, Sblock, &dimLup, Tdown, &dimLdown, &beta, workmem, &dimLup );
120 dgemm_( &trans, ¬rans, &dimRup, &dimRdown, &dimLup, &alpha, Tup, &dimLup, workmem, &dimLup, &beta,
storage +
kappa2index[ikappa], &dimRup );
131 assert( two_j1 == Sigma->
get_2j() );
134 const int two_j2 =
two_j;
136 for (
int ikappa = 0; ikappa <
nKappa; ikappa++ ){
149 for (
int two_jl_up = two_jr_up-1; two_jl_up <= two_jr_up+1; two_jl_up+=2 ){
154 if (( dimLup > 0 ) && ( dimLdown > 0 ) && ( abs( two_jr_down - two_jl_up ) <= two_j1 )){
156 double * Sblock = Sigma->
gStorage( nr_up-1, two_jl_up, il_up, nr_up+1, two_jr_down, ir_down );
157 double * Tup = denT->
gStorage( nr_up-1, two_jl_up, il_up, nr_up, two_jr_up, ir_up );
158 double * Tdown = denT->
gStorage( nr_up+1, two_jr_down, ir_down, nr_up+1, two_jr_down, ir_down );
160 double alpha = sqrt( 1.0 * ( two_j2 + 1 ) * ( two_jr_up + 1 ) )
166 dgemm_( ¬rans, ¬rans, &dimLup, &dimRdown, &dimLdown, &alpha, Sblock, &dimLup, Tdown, &dimLdown, &beta, workmem, &dimLup );
169 dgemm_( &trans, ¬rans, &dimRup, &dimRdown, &dimLup, &alpha, Tup, &dimLup, workmem, &dimLup, &beta,
storage +
kappa2index[ikappa], &dimRup );
176 for (
int two_jl_down = two_jr_down-1; two_jl_down <= two_jr_down+1; two_jl_down+=2 ){
181 if (( dimLup > 0 ) && ( dimLdown > 0 ) && ( abs( two_jr_up - two_jl_down ) <= two_j1 )){
183 double * Sblock = Sigma->
gStorage( nr_up-2, two_jr_up, ir_up, nr_up, two_jl_down, il_down );
184 double * Tup = denT->
gStorage( nr_up-2, two_jr_up, ir_up, nr_up, two_jr_up, ir_up );
185 double * Tdown = denT->
gStorage( nr_up, two_jl_down, il_down, nr_up+1, two_jr_down, ir_down );
187 double alpha = sqrt( 1.0 * ( two_j2 + 1 ) * ( two_jl_down + 1 ) )
188 *
Wigner::wigner6j( 1, two_j1, two_j2, two_jr_up, two_jr_down, two_jl_down )
193 dgemm_( ¬rans, ¬rans, &dimLup, &dimRdown, &dimLdown, &alpha, Sblock, &dimLup, Tdown, &dimLdown, &beta, workmem, &dimLup );
196 dgemm_( &trans, ¬rans, &dimRup, &dimRdown, &dimLup, &alpha, Tup, &dimLup, workmem, &dimLup, &beta,
storage +
kappa2index[ikappa], &dimRup );
207 assert( two_j1 == denF->
get_2j() );
210 const int two_j2 =
two_j;
212 for (
int ikappa = 0; ikappa <
nKappa; ikappa++ ){
225 for (
int two_jl_down = two_jr_down-1; two_jl_down <= two_jr_down+1; two_jl_down+=2 ){
230 if (( dimLup > 0 ) && ( dimLdown > 0 ) && ( abs( two_jr_up - two_jl_down ) <= two_j1 )){
232 double * Fblock = denF->
gStorage( nr_up, two_jr_up, ir_up, nr_up, two_jl_down, il_down );
233 double * Tup = denT->
gStorage( nr_up, two_jr_up, ir_up, nr_up, two_jr_up, ir_up );
234 double * Tdown = denT->
gStorage( nr_up, two_jl_down, il_down, nr_up+1, two_jr_down, ir_down );
236 double alpha = sqrt( 1.0 * ( two_j2 + 1 ) * ( two_jl_down + 1 ) )
237 *
Wigner::wigner6j( 1, two_j1, two_j2, two_jr_up, two_jr_down, two_jl_down )
242 dgemm_( ¬rans, ¬rans, &dimLup, &dimRdown, &dimLdown, &alpha, Fblock, &dimLup, Tdown, &dimLdown, &beta, workmem, &dimLup );
245 dgemm_( &trans, ¬rans, &dimRup, &dimRdown, &dimLup, &alpha, Tup, &dimLup, workmem, &dimLup, &beta,
storage +
kappa2index[ikappa], &dimRup );
252 for (
int two_jl_up = two_jr_up-1; two_jl_up <= two_jr_up+1; two_jl_up+=2 ){
257 if (( dimLup > 0 ) && ( dimLdown > 0 ) && ( abs( two_jr_down - two_jl_up ) <= two_j1 )){
259 double * Fblock = denF->
gStorage( nr_up-1, two_jl_up, il_up, nr_up-1, two_jr_down, ir_down );
260 double * Tup = denT->
gStorage( nr_up-1, two_jl_up, il_up, nr_up, two_jr_up, ir_up );
261 double * Tdown = denT->
gStorage( nr_up-1, two_jr_down, ir_down, nr_up+1, two_jr_down, ir_down );
263 double alpha = sqrt( 1.0 * ( two_j2 + 1 ) * ( two_jr_up + 1 ) )
269 dgemm_( ¬rans, ¬rans, &dimLup, &dimRdown, &dimLdown, &alpha, Fblock, &dimLup, Tdown, &dimLdown, &beta, workmem, &dimLup );
272 dgemm_( &trans, ¬rans, &dimRup, &dimRdown, &dimLup, &alpha, Tup, &dimLup, workmem, &dimLup, &beta,
storage +
kappa2index[ikappa], &dimRup );
283 assert( two_j1 == denF->
get_2j() );
286 const int two_j2 =
two_j;
288 for (
int ikappa = 0; ikappa <
nKappa; ikappa++ ){
301 for (
int two_jl_down = two_jr_down-1; two_jl_down <= two_jr_down+1; two_jl_down+=2 ){
306 if (( dimLup > 0 ) && ( dimLdown > 0 ) && ( abs( two_jr_up - two_jl_down ) <= two_j1 )){
308 double * Fblock = denF->
gStorage( nr_up, two_jl_down, il_down, nr_up, two_jr_up, ir_up );
309 double * Tup = denT->
gStorage( nr_up, two_jr_up, ir_up, nr_up, two_jr_up, ir_up );
310 double * Tdown = denT->
gStorage( nr_up, two_jl_down, il_down, nr_up+1, two_jr_down, ir_down );
312 double alpha = sqrt( 1.0 * ( two_j2 + 1 ) * ( two_jr_down + 1 ) )
313 *
Wigner::wigner6j( 1, two_j1, two_j2, two_jr_up, two_jr_down, two_jl_down )
318 dgemm_( &trans, ¬rans, &dimLup, &dimRdown, &dimLdown, &alpha, Fblock, &dimLdown, Tdown, &dimLdown, &beta, workmem, &dimLup );
321 dgemm_( &trans, ¬rans, &dimRup, &dimRdown, &dimLup, &alpha, Tup, &dimLup, workmem, &dimLup, &beta,
storage +
kappa2index[ikappa], &dimRup );
328 for (
int two_jl_up = two_jr_up-1; two_jl_up <= two_jr_up+1; two_jl_up+=2 ){
333 if (( dimLup > 0 ) && ( dimLdown > 0 ) && ( abs( two_jr_down - two_jl_up ) <= two_j1 )){
335 double * Fblock = denF->
gStorage( nr_up-1, two_jr_down, ir_down, nr_up-1, two_jl_up, il_up );
336 double * Tup = denT->
gStorage( nr_up-1, two_jl_up, il_up, nr_up, two_jr_up, ir_up );
337 double * Tdown = denT->
gStorage( nr_up-1, two_jr_down, ir_down, nr_up+1, two_jr_down, ir_down );
339 double alpha = sqrt( 1.0 * ( two_j2 + 1 ) * ( two_jl_up + 1 ) )
345 dgemm_( &trans, ¬rans, &dimLup, &dimRdown, &dimLdown, &alpha, Fblock, &dimLdown, Tdown, &dimLdown, &beta, workmem, &dimLup );
348 dgemm_( &trans, ¬rans, &dimRup, &dimRdown, &dimLup, &alpha, Tup, &dimLup, workmem, &dimLup, &beta,
storage +
kappa2index[ikappa], &dimRup );
361 const int two_j2 =
two_j;
362 assert( two_j2 == 1 );
364 for (
int ikappa = 0; ikappa <
nKappa; ikappa++ ){
378 double * Tup = denT->
gStorage( nr_up-1, two_jr_down, ir_down, nr_up, two_jr_up, ir_up );
379 double * Tdown = denT->
gStorage( nr_up-1, two_jr_down, ir_down, nr_up+1, two_jr_down, ir_down );
381 double alpha = sqrt( 0.5 * ( two_j1 + 1 ) ) *
Special::phase( two_j1 );
385 dgemm_( &trans, ¬rans, &dimRup, &dimRdown, &dimL, &alpha, Tup, &dimL, Tdown, &dimL, &beta,
storage +
kappa2index[ikappa], &dimRup );
396 const int two_j2 =
two_j;
397 assert( two_j2 == 1 );
399 for (
int ikappa = 0; ikappa <
nKappa; ikappa++ ){
412 if (( dimLup > 0 ) && ( dimLdown > 0 )){
414 double * Tup = denT->
gStorage( nr_up, two_jr_up, ir_up, nr_up, two_jr_up, ir_up );
415 double * Tdown = denT->
gStorage( nr_up+1, two_jr_down, ir_down, nr_up+3, two_jr_down, ir_down );
416 double * Lblock = denL->
gStorage( nr_up, two_jr_up, ir_up, nr_up+1, two_jr_down, ir_down );
418 double alpha = sqrt( 0.5 * ( two_j1 + 1 ) ) *
Special::phase( two_j1 + 2 );
422 dgemm_( ¬rans, ¬rans, &dimLup, &dimRdown, &dimLdown, &alpha, Lblock, &dimLup, Tdown, &dimLdown, &beta, workmem, &dimLup );
424 dgemm_( &trans, ¬rans, &dimRup, &dimRdown, &dimLup, &alpha, Tup, &dimLup, workmem, &dimLup, &beta,
storage +
kappa2index[ikappa], &dimRup );
435 const int two_j2 =
two_j;
436 assert( two_j2 == 1 );
438 for (
int ikappa = 0; ikappa <
nKappa; ikappa++ ){
451 if (( dimLup > 0 ) && ( dimLdown > 0 )){
453 double * Tup = denT->
gStorage( nr_up, two_jr_up, ir_up, nr_up, two_jr_up, ir_up );
454 double * Tdown = denT->
gStorage( nr_up-1, two_jr_down, ir_down, nr_up+1, two_jr_down, ir_down );
455 double * Lblock = denL->
gStorage( nr_up-1, two_jr_down, ir_down, nr_up, two_jr_up, ir_up );
457 double alpha = sqrt( 0.5 * ( two_j1 + 1 ) ) *
Special::phase( two_j1 );
461 dgemm_( &trans, ¬rans, &dimLup, &dimRdown, &dimLdown, &alpha, Lblock, &dimLdown, Tdown, &dimLdown, &beta, workmem, &dimLup );
463 dgemm_( &trans, ¬rans, &dimRup, &dimRdown, &dimLup, &alpha, Tup, &dimLup, workmem, &dimLup, &beta,
storage +
kappa2index[ikappa], &dimRup );
474 const int two_j2 =
two_j;
476 for (
int ikappa = 0; ikappa <
nKappa; ikappa++ ){
492 if (( dimLup > 0 ) && ( dimLdown > 0 )){
494 double * Tup = denT->
gStorage( nr_up-2, two_jr_up, ir_up, nr_up, two_jr_up, ir_up );
495 double * Tdown = denT->
gStorage( nr_up-1, two_jr_down, ir_down, nr_up+1, two_jr_down, ir_down );
496 double * Lblock = denL->
gStorage( nr_up-2, two_jr_up, ir_up, nr_up-1, two_jr_down, ir_down );
498 double alpha = sqrt( 0.5 * ( two_j1 + 1 ) ) *
Special::phase( two_j1 + 2 );
502 dgemm_( ¬rans, ¬rans, &dimLup, &dimRdown, &dimLdown, &alpha, Lblock, &dimLup, Tdown, &dimLdown, &beta, workmem, &dimLup );
505 dgemm_( &trans, ¬rans, &dimRup, &dimRdown, &dimLup, &alpha, Tup, &dimLup, workmem, &dimLup, &beta,
storage +
kappa2index[ikappa], &dimRup );
512 for (
int two_jl_up = two_jr_up-1; two_jl_up <= two_jr_up+1; two_jl_up+=2 ){
513 for (
int two_jl_down = two_jr_down-1; two_jl_down <= two_jr_down+1; two_jl_down+=2 ){
518 if (( dimLup > 0 ) && ( dimLdown > 0 ) && ( abs( two_jl_up - two_jl_down ) <= 1 )){
520 double * Tup = denT->
gStorage( nr_up-1, two_jl_up, il_up, nr_up, two_jr_up, ir_up );
521 double * Tdown = denT->
gStorage( nr_up, two_jl_down, il_down, nr_up+1, two_jr_down, ir_down );
522 double * Lblock = denL->
gStorage( nr_up-1, two_jl_up, il_up, nr_up, two_jl_down, il_down );
524 double alpha = sqrt( 1.0 * ( two_j1 + 1 ) * ( two_j2 + 1 ) * ( two_jr_up + 1 ) * ( two_jl_down + 1 ) )
525 *
Special::phase( two_jr_up + two_jr_down - two_jl_up - two_jl_down )
527 *
Wigner::wigner6j( 1, two_j1, two_j2, two_jr_up, two_jr_down, two_jl_down );
531 dgemm_( ¬rans, ¬rans, &dimLup, &dimRdown, &dimLdown, &alpha, Lblock, &dimLup, Tdown, &dimLdown, &beta, workmem, &dimLup );
534 dgemm_( &trans, ¬rans, &dimRup, &dimRdown, &dimLup, &alpha, Tup, &dimLup, workmem, &dimLup, &beta,
storage +
kappa2index[ikappa], &dimRup );
545 if ( buddy == NULL ){
return 0.0; }
562 for (
int ikappa = 0; ikappa <
nKappa; ikappa++ ){
569 value += prefactor * ddot_( &length,
storage + offset, &inc, buddy->
gStorage() + offset, &inc );
static double wigner6j(const int two_ja, const int two_jb, const int two_jc, const int two_jd, const int two_je, const int two_jf)
Wigner-6j symbol (gsl api)
int index
Index of the Tensor object. For TensorT: a site index; for other tensors: a boundary index...
int * sector_nelec_up
The up particle number sector.
int get_2j() const
Get twice the spin of the tensor operator.
void extra1(TensorT *denT)
Make diagram extra1.
int * sector_spin_down
The down spin symmetry sector (pointer points to sectorTwoS1 if two_j == 0)
int gCurrentDim(const int boundary, const int N, const int TwoS, const int irrep) const
Get the current virtual dimensions.
int get_nelec() const
Get how many electrons there are more in the symmetry sector of the lower leg compared to the upper l...
void c1(TensorOperator *denF, TensorT *denT, double *workmem)
Make diagram c1.
bool prime_last
Convention in which the tensor operator is stored (see class information)
static int phase(const int power_times_two)
Phase function.
Tensor3RDM(const int boundary, const int two_j1_in, const int two_j2, const int nelec, const int irrep, const bool prime_last, const SyBookkeeper *book)
Constructor.
bool get_prime_last() const
Get whether the tensor convention is prime last.
double contract(Tensor3RDM *buddy) const
Make the in-product of two Tensor3RDMs.
void extra3(TensorL *denL, TensorT *denT, double *workmem)
Make diagram extra3.
void a1(TensorOperator *Sigma, TensorT *denT, double *workmem)
Make diagram a1.
void extra2(TensorL *denL, TensorT *denT, double *workmem)
Make diagram extra2.
double * gStorage()
Get the pointer to the storage.
int get_two_j1() const
Get the intermediary spin coupling value of the Tensor3RDM.
void d1(TensorOperator *denF, TensorT *denT, double *workmem)
Make diagram d1.
virtual ~Tensor3RDM()
Destructor.
int * sector_spin_up
The up spin symmetry sector.
double * gStorage()
Get the pointer to the storage.
int n_irrep
The (real-valued abelian) point group irrep difference between the symmetry sectors of the lower and ...
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 * sector_irrep_up
The up spin symmetry sector.
void extra4(TensorL *denL, TensorT *denT, double *workmem)
Make diagram extra4.
const SyBookkeeper * bk_up
The bookkeeper of the upper MPS.
int * kappa2index
kappa2index[kappa] indicates the start of tensor block kappa in storage. kappa2index[nKappa] gives th...
void b1(TensorOperator *Sigma, TensorT *denT, double *workmem)
Make diagram b1.
int get_two_j2() const
Get the spin value of the Tensor3RDM.
int get_irrep() const
Get the (real-valued abelian) point group irrep difference between the symmetry sectors of the lower ...
void clear()
Set all storage variables to 0.0.
int nKappa
Number of Tensor blocks.
int gIrrep(const int orbital) const
Get an orbital irrep.
int n_elec
How many electrons there are more in the symmetry sector of the lower leg compared to the upper leg...
int two_j
Twice the spin of the tensor operator.
double * storage
The actual variables. Tensor block kappa begins at storage+kappa2index[kappa] and ends at storage+kap...