22 #include "DMRGSCFintegrals.h" 27 NCORE =
new int[ numberOfIrreps ];
28 NVIRTUAL =
new int[ numberOfIrreps ];
29 NTOTAL =
new int[ numberOfIrreps ];
31 for (
int irrep = 0; irrep < numberOfIrreps; irrep++){
32 NCORE[ irrep ] = iHandler->
getNOCC( irrep ) + iHandler->
getNDMRG( irrep );
33 NVIRTUAL[ irrep ] = iHandler->
getNVIRT( irrep );
34 NTOTAL[ irrep ] = iHandler->
getNORB( irrep );
37 coulomb_size = calcNumCoulombElements(
true );
38 exchange_size = calcNumExchangeElements(
true );
39 coulomb_array =
new double[ coulomb_size ];
40 exchange_array =
new double[ exchange_size ];
44 long long CheMPS2::DMRGSCFintegrals::calcNumCoulombElements(
const bool allocate){
47 long long theSize = 0;
49 if (allocate){ coulomb_ptr =
new long long***[ numberOfIrreps ]; }
50 for (
int I_cc = 0; I_cc < numberOfIrreps; I_cc++){
51 if (allocate){ coulomb_ptr[ I_cc ] =
new long long**[ numberOfIrreps ]; }
52 for (
int I_c1 = 0; I_c1 < numberOfIrreps; I_c1++){
54 if ( ( NCORE[ I_c1 ] > 0 ) && ( NCORE[ I_c2 ] > 0 ) && ( I_c1 <= I_c2 ) ){
55 if (allocate){ coulomb_ptr[ I_cc ][ I_c1 ] =
new long long*[ numberOfIrreps ]; }
56 for (
int I_a1 = 0; I_a1 < numberOfIrreps; I_a1++){
58 if ( ( NTOTAL[ I_a1 ] > 0 ) && ( NTOTAL[ I_a2 ] > 0 ) && ( I_a1 <= I_a2 ) ){
61 const long long coretriangle = ( NCORE[ I_c1 ] * ( NCORE[ I_c1 ] + 1 ) ) / 2;
62 const long long alltriangle = ( NTOTAL[ I_a1 ] * ( NTOTAL[ I_a1 ] + 1 ) ) / 2;
63 coulomb_ptr[ I_cc ][ I_c1 ][ I_a1 ] =
new long long[ coretriangle ];
64 for (
int combinedcore = 0; combinedcore < coretriangle; combinedcore++){
65 coulomb_ptr[ I_cc ][ I_c1 ][ I_a1 ][ combinedcore ] = theSize;
66 theSize += alltriangle;
68 }
else {
delete [] coulomb_ptr[ I_cc ][ I_c1 ][ I_a1 ]; }
71 const long long coresquare = NCORE[ I_c1 ] * NCORE[ I_c2 ];
72 const long long allsquare = NTOTAL[ I_a1 ] * NTOTAL[ I_a2 ];
73 coulomb_ptr[ I_cc ][ I_c1 ][ I_a1 ] =
new long long[ coresquare ];
74 for (
int combinedcore = 0; combinedcore < coresquare; combinedcore++){
75 coulomb_ptr[ I_cc ][ I_c1 ][ I_a1 ][ combinedcore ] = theSize;
78 }
else {
delete [] coulomb_ptr[ I_cc ][ I_c1 ][ I_a1 ]; }
82 if (!allocate){
delete [] coulomb_ptr[ I_cc ][ I_c1 ]; }
85 if (!allocate){
delete [] coulomb_ptr[ I_cc ]; }
87 if (!allocate){
delete [] coulomb_ptr; }
93 long long CheMPS2::DMRGSCFintegrals::calcNumExchangeElements(
const bool allocate){
96 long long theSize = 0;
98 if (allocate){ exchange_ptr =
new long long***[ numberOfIrreps ]; }
99 for (
int I_cc = 0; I_cc < numberOfIrreps; I_cc++){
100 if (allocate){ exchange_ptr[ I_cc ] =
new long long**[ numberOfIrreps ]; }
101 for (
int I_c1 = 0; I_c1 < numberOfIrreps; I_c1++){
103 if ( ( NCORE[ I_c1 ] > 0 ) && ( NCORE[ I_c2 ] > 0 ) && ( I_c1 <= I_c2 ) ){
104 if (allocate){ exchange_ptr[ I_cc ][ I_c1 ] =
new long long*[ numberOfIrreps ]; }
105 for (
int I_v1 = 0; I_v1 < numberOfIrreps; I_v1++){
107 if ( ( NTOTAL[ I_v1 ] > 0 ) && ( NTOTAL[ I_v2 ] > 0 ) ){
108 const long long virtualsquare = NVIRTUAL[ I_v1 ] * NVIRTUAL[ I_v2 ];
111 const long long coretriangle = ( NCORE[ I_c1 ] * ( NCORE[ I_c1 ] + 1 ) ) / 2;
112 exchange_ptr[ I_cc ][ I_c1 ][ I_v1 ] =
new long long[ coretriangle ];
113 for (
int combinedcore = 0; combinedcore < coretriangle; combinedcore++){
114 exchange_ptr[ I_cc ][ I_c1 ][ I_v1 ][ combinedcore ] = theSize;
115 theSize += virtualsquare;
117 }
else {
delete [] exchange_ptr[ I_cc ][ I_c1 ][ I_v1 ]; }
120 const long long coresquare = NCORE[ I_c1 ] * NCORE[ I_c2 ];
121 exchange_ptr[ I_cc ][ I_c1 ][ I_v1 ] =
new long long[ coresquare ];
122 for (
int combinedcore = 0; combinedcore < coresquare; combinedcore++){
123 exchange_ptr[ I_cc ][ I_c1 ][ I_v1 ][ combinedcore ] = theSize;
124 theSize += virtualsquare;
126 }
else {
delete [] exchange_ptr[ I_cc ][ I_c1 ][ I_v1 ]; }
130 if (!allocate){
delete [] exchange_ptr[ I_cc ][ I_c1 ]; }
133 if (!allocate){
delete [] exchange_ptr[ I_cc ]; }
135 if (!allocate){
delete [] exchange_ptr; }
143 delete [] coulomb_array;
144 delete [] exchange_array;
146 calcNumCoulombElements(
false );
147 calcNumExchangeElements(
false );
157 for (
long long counter = 0; counter < coulomb_size; counter++){ coulomb_array[ counter ] = 0.0; }
158 for (
long long counter = 0; counter < exchange_size; counter++){ exchange_array[ counter ] = 0.0; }
162 long long CheMPS2::DMRGSCFintegrals::get_coulomb_ptr(
const int Ic1,
const int Ic2,
const int Ia1,
const int Ia2,
const int c1,
const int c2,
const int a1,
const int a2 )
const{
168 const int index_c = ( c1 <= c2 ) ? c1 + (c2 * ( c2 + 1 ))/2 : c2 + (c1 * ( c1 + 1 ))/2 ;
169 const int index_a = ( a1 <= a2 ) ? a1 + (a2 * ( a2 + 1 ))/2 : a2 + (a1 * ( a1 + 1 ))/2 ;
170 return coulomb_ptr[ Icc ][ Ic1 ][ Ia1 ][ index_c ] + index_a ;
174 const int irrep_c = ( Ic1 < Ic2 ) ? Ic1 : Ic2 ;
175 const int irrep_a = ( Ia1 < Ia2 ) ? Ia1 : Ia2 ;
176 const int index_c = ( Ic1 < Ic2 ) ? c1 + NCORE[ Ic1 ] * c2 : c2 + NCORE[ Ic2 ] * c1 ;
177 const int index_a = ( Ia1 < Ia2 ) ? a1 + NTOTAL[ Ia1 ] * a2 : a2 + NTOTAL[ Ia2 ] * a1 ;
178 return coulomb_ptr[ Icc ][ irrep_c ][ irrep_a ][ index_c ] + index_a ;
184 coulomb_array[ get_coulomb_ptr( Ic1, Ic2, Ia1, Ia2, c1, c2, a1, a2 ) ] = val;
190 coulomb_array[ get_coulomb_ptr( Ic1, Ic2, Ia1, Ia2, c1, c2, a1, a2 ) ] += val;
196 return coulomb_array[ get_coulomb_ptr( Ic1, Ic2, Ia1, Ia2, c1, c2, a1, a2 ) ];
200 long long CheMPS2::DMRGSCFintegrals::get_exchange_ptr(
const int Ic1,
const int Ic2,
const int Iv1,
const int Iv2,
const int c1,
const int c2,
const int v1,
const int v2 )
const{
208 return exchange_ptr[ Icc ][ Ic1 ][ Iv1 ][ c1 + (c2 * ( c2 + 1 ))/2 ] + v1 - NCORE[ Iv1 ] + NVIRTUAL[ Iv1 ] * ( v2 - NCORE[ Iv2 ] ) ;
210 return exchange_ptr[ Icc ][ Ic2 ][ Iv2 ][ c2 + (c1 * ( c1 + 1 ))/2 ] + v2 - NCORE[ Iv2 ] + NVIRTUAL[ Iv2 ] * ( v1 - NCORE[ Iv1 ] ) ;
216 return exchange_ptr[ Icc ][ Ic1 ][ Iv1 ][ c1 + NCORE[ Ic1 ] * c2 ] + v1 - NCORE[ Iv1 ] + NVIRTUAL[ Iv1 ] * ( v2 - NCORE[ Iv2 ] ) ;
218 return exchange_ptr[ Icc ][ Ic2 ][ Iv2 ][ c2 + NCORE[ Ic2 ] * c1 ] + v2 - NCORE[ Iv2 ] + NVIRTUAL[ Iv2 ] * ( v1 - NCORE[ Iv1 ] ) ;
229 exchange_array[ get_exchange_ptr( Ic1, Ic2, Iv1, Iv2, c1, c2, v1, v2 ) ] = val;
235 exchange_array[ get_exchange_ptr( Ic1, Ic2, Iv1, Iv2, c1, c2, v1, v2 ) ] += val;
241 return exchange_array[ get_exchange_ptr( Ic1, Ic2, Iv1, Iv2, c1, c2, v1, v2 ) ];
249 const bool core1 = ( index1 < NCORE[I1] ) ?
true :
false;
250 const bool core2 = ( index2 < NCORE[I2] ) ?
true :
false;
251 const bool core3 = ( index3 < NCORE[I3] ) ?
true :
false;
252 const bool core4 = ( index4 < NCORE[I4] ) ?
true :
false;
254 const int numCore = ( ( core1 ) ? 1 : 0 ) + ( ( core2 ) ? 1 : 0 ) + ( ( core3 ) ? 1 : 0 ) + ( ( core4 ) ? 1 : 0 );
255 assert( numCore >= 2 );
258 return get_coulomb(I1, I3, I2, I4, index1, index3, index2, index4);
262 if (( !core1 ) || ( !core3 )){
return get_coulomb(I2, I4, I1, I3, index2, index4, index1, index3); }
263 if (( !core2 ) || ( !core4 )){
return get_coulomb(I1, I3, I2, I4, index1, index3, index2, index4); }
268 if ( !core2 ){
return get_exchange(I3, I4, I1, I2, index3, index4, index1, index2); }
269 if ( !core3 ){
return get_coulomb( I2, I4, I1, I3, index2, index4, index1, index3); }
270 if ( !core4 ){
return get_exchange(I3, I2, I1, I4, index3, index2, index1, index4); }
273 if ( !core3 ){
return get_exchange(I4, I1, I2, I3, index4, index1, index2, index3); }
274 if ( !core4 ){
return get_coulomb( I1, I3, I2, I4, index1, index3, index2, index4); }
276 return get_exchange(I1, I2, I3, I4, index1, index2, index3, index4);
double get_coulomb(const int Ic1, const int Ic2, const int Ia1, const int Ia2, const int c1, const int c2, const int a1, const int a2) const
Get an element of the Coulomb object ( c1 c2 | a1 a2 )
int getNORB(const int irrep) const
Get the number of orbitals for an irrep.
virtual ~DMRGSCFintegrals()
Destructor.
void add_coulomb(const int Ic1, const int Ic2, const int Ia1, const int Ia2, const int c1, const int c2, const int a1, const int a2, const double val)
Add a double to an element of the Coulomb object ( c1 c2 | a1 a2 )
double FourIndexAPI(const int I1, const int I2, const int I3, const int I4, const int index1, const int index2, const int index3, const int index4) const
Get a two-body matrix element with at most 2 virtual indices, using the FourIndex API...
void set_exchange(const int Ic1, const int Ic2, const int Iv1, const int Iv2, const int c1, const int c2, const int v1, const int v2, const double val)
Set an element of the Exchange object ( c1 v1 | c2 v2 )
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...
void add_exchange(const int Ic1, const int Ic2, const int Iv1, const int Iv2, const int c1, const int c2, const int v1, const int v2, const double val)
Add a double to an element of the Exchange object ( c1 v1 | c2 v2 )
int getNDMRG(const int irrep) const
Get the number of active orbitals for an irrep.
double get_exchange(const int Ic1, const int Ic2, const int Iv1, const int Iv2, const int c1, const int c2, const int v1, const int v2) const
Get an element of the Exchange object ( c1 v1 | c2 v2 )
DMRGSCFintegrals(DMRGSCFindices *iHandler)
Constructor.
int getNOCC(const int irrep) const
Get the number of occupied orbitals for an irrep.
void clear()
Set the storage objects to zero.
void set_coulomb(const int Ic1, const int Ic2, const int Ia1, const int Ia2, const int c1, const int c2, const int a1, const int a2, const double val)
Set an element of the Coulomb object ( c1 c2 | a1 a2 )
int getNVIRT(const int irrep) const
Get the number of virtual orbitals for an irrep.
int getNirreps() const
Get the number of irreps.