修订版 | 3a08df6186f3109360990c656bc4ae8dbb30aa32 (tree) |
---|---|
时间 | 2013-05-24 18:52:00 |
作者 | Mikiya Fujii <mikiya.fujii@gmai...> |
Commiter | Mikiya Fujii |
Cache of two electron integral, that is Nishimoto-Mataga, is implemented. #31428
git-svn-id: https://svn.sourceforge.jp/svnroot/molds/trunk@1356 1136aad2-a195-0410-b898-f5ea1d11b9d8
@@ -82,7 +82,7 @@ Mndo::~Mndo(){ | ||
82 | 82 | } |
83 | 83 | |
84 | 84 | void Mndo::SetMolecule(Molecule* molecule){ |
85 | - Cndo2::SetMolecule(molecule); | |
85 | + ZindoS::SetMolecule(molecule); | |
86 | 86 | MallocerFreer::GetInstance()->Malloc<double>(&this->twoElecTwoCore, |
87 | 87 | molecule->GetNumberAtoms(), |
88 | 88 | molecule->GetNumberAtoms(), |
@@ -73,6 +73,7 @@ ZindoS::ZindoS() : MolDS_cndo::Cndo2(){ | ||
73 | 73 | this->etaMatrixForce = NULL; |
74 | 74 | |
75 | 75 | //private variables |
76 | + this->nishimotoMatagaMatrix = NULL; | |
76 | 77 | this->matrixForceElecStatesNum = 0; |
77 | 78 | this->nishimotoMatagaParamA = 1.2; |
78 | 79 | this->nishimotoMatagaParamB = 2.4; |
@@ -82,6 +83,13 @@ ZindoS::ZindoS() : MolDS_cndo::Cndo2(){ | ||
82 | 83 | } |
83 | 84 | |
84 | 85 | ZindoS::~ZindoS(){ |
86 | + if(this->theory==ZINDOS){ | |
87 | + MallocerFreer::GetInstance()->Free<double>(&this->nishimotoMatagaMatrix, | |
88 | + this->molecule->GetNumberAtoms(), | |
89 | + OrbitalType_end, | |
90 | + this->molecule->GetNumberAtoms(), | |
91 | + OrbitalType_end); | |
92 | + } | |
85 | 93 | MallocerFreer::GetInstance()->Free<double>(&this->matrixCIS, |
86 | 94 | this->matrixCISdimension, |
87 | 95 | this->matrixCISdimension); |
@@ -119,6 +127,17 @@ ZindoS::~ZindoS(){ | ||
119 | 127 | //this->OutputLog("ZindoS deleted\n"); |
120 | 128 | } |
121 | 129 | |
130 | +void ZindoS::SetMolecule(Molecule* molecule){ | |
131 | + Cndo2::SetMolecule(molecule); | |
132 | + if(this->theory==ZINDOS){ | |
133 | + MallocerFreer::GetInstance()->Malloc<double>(&this->nishimotoMatagaMatrix, | |
134 | + this->molecule->GetNumberAtoms(), | |
135 | + OrbitalType_end, | |
136 | + this->molecule->GetNumberAtoms(), | |
137 | + OrbitalType_end); | |
138 | + } | |
139 | +} | |
140 | + | |
122 | 141 | void ZindoS::SetMessages(){ |
123 | 142 | this->errorMessageSCFNotConverged |
124 | 143 | = "Error in zindo::ZindoS::DoSCF: SCF did not met convergence criterion. maxIterationsSCF="; |
@@ -242,14 +261,10 @@ double ZindoS::GetFockDiagElement(const Atom& atomA, | ||
242 | 261 | sigma = i + atomB.GetFirstAOIndex(); |
243 | 262 | orbitalSigma = atomB.GetValence(i); |
244 | 263 | temp += orbitalElectronPopulationDiagPart[sigma] |
245 | - *this->GetNishimotoMatagaTwoEleInt(atomA, | |
246 | - orbitalMu, | |
247 | - atomB, | |
248 | - orbitalSigma, | |
249 | - rAB); | |
264 | + *this->nishimotoMatagaMatrix[indexAtomA][orbitalMu][B][orbitalSigma]; | |
250 | 265 | } |
251 | 266 | temp -= atomB.GetCoreCharge() |
252 | - *this->GetNishimotoMatagaTwoEleInt(atomA, s, atomB, s, rAB); | |
267 | + *this->nishimotoMatagaMatrix[indexAtomA][s][B][s]; | |
253 | 268 | } |
254 | 269 | } |
255 | 270 | value += temp; |
@@ -290,7 +305,7 @@ double ZindoS::GetFockOffDiagElement(const Atom& atomA, | ||
290 | 305 | else{ |
291 | 306 | value = bondParameter*overlapAOs[mu][nu]; |
292 | 307 | value -= 0.5*orbitalElectronPopulation[mu][nu] |
293 | - *this->GetNishimotoMatagaTwoEleInt(atomA, orbitalMu, atomB, orbitalNu); | |
308 | + *this->nishimotoMatagaMatrix[indexAtomA][orbitalMu][indexAtomB][orbitalNu]; | |
294 | 309 | } |
295 | 310 | } |
296 | 311 | return value; |
@@ -564,6 +579,11 @@ double ZindoS::GetExchangeInt(OrbitalType orbital1, OrbitalType orbital2, const | ||
564 | 579 | return value; |
565 | 580 | } |
566 | 581 | |
582 | +void ZindoS::CalcTwoElecTwoCore(double****** twoElecTwoCore, | |
583 | + const Molecule& molecule) const{ | |
584 | + this->CalcNishimotoMatagaMatrix(this->nishimotoMatagaMatrix, molecule); | |
585 | +} | |
586 | + | |
567 | 587 | // ref. [MN_1957] and (5a) in [AEZ_1986] |
568 | 588 | double ZindoS::GetNishimotoMatagaTwoEleInt(const Atom& atomA, OrbitalType orbitalA, |
569 | 589 | const Atom& atomB, OrbitalType orbitalB) const{ |
@@ -727,6 +747,9 @@ void ZindoS::CalcNishimotoMatagaMatrix(double**** nishimotoMatagaMatrix, const M | ||
727 | 747 | atomB, |
728 | 748 | orbitalNu, |
729 | 749 | rAB); |
750 | + if(A!=B){ | |
751 | + nishimotoMatagaMatrix[B][orbitalNu][A][orbitalMu] = nishimotoMatagaMatrix[A][orbitalMu][B][orbitalNu]; | |
752 | + } | |
730 | 753 | } |
731 | 754 | } |
732 | 755 | } |
@@ -944,10 +967,7 @@ double ZindoS::GetMolecularIntegralElement(int moI, int moJ, int moK, int moL, | ||
944 | 967 | OrbitalType orbitalNu = atomB.GetValence(nu-firstAOIndexB); |
945 | 968 | |
946 | 969 | if(A<B){ |
947 | - gamma = this->GetNishimotoMatagaTwoEleInt(atomA, | |
948 | - orbitalMu, | |
949 | - atomB, | |
950 | - orbitalNu); | |
970 | + gamma = this->nishimotoMatagaMatrix[A][orbitalMu][B][orbitalNu]; | |
951 | 971 | value += gamma |
952 | 972 | *fockMatrix[moI][mu] |
953 | 973 | *fockMatrix[moJ][mu] |
@@ -2258,68 +2278,56 @@ void ZindoS::CalcCISMatrix(double** matrixCIS) const{ | ||
2258 | 2278 | this->OutputLog(this->messageStartCalcCISMatrix); |
2259 | 2279 | double ompStartTime = omp_get_wtime(); |
2260 | 2280 | |
2261 | - int totalNumberAtoms = this->molecule->GetNumberAtoms(); | |
2262 | - double**** nishimotoMatagaMatrix=NULL; | |
2263 | - try{ | |
2264 | - MallocerFreer::GetInstance()->Malloc<double>(&nishimotoMatagaMatrix, totalNumberAtoms, OrbitalType_end, totalNumberAtoms, OrbitalType_end); | |
2265 | - this->CalcNishimotoMatagaMatrix(nishimotoMatagaMatrix, *this->molecule); | |
2266 | - | |
2267 | - stringstream ompErrors; | |
2281 | + stringstream ompErrors; | |
2268 | 2282 | #pragma omp parallel for schedule(auto) |
2269 | - for(int k=0; k<this->matrixCISdimension; k++){ | |
2270 | - try{ | |
2271 | - // single excitation from I-th (occupied)MO to A-th (virtual)MO | |
2272 | - int moI = this->GetActiveOccIndex(*this->molecule, k); | |
2273 | - int moA = this->GetActiveVirIndex(*this->molecule, k); | |
2274 | - | |
2275 | - for(int l=k; l<this->matrixCISdimension; l++){ | |
2276 | - // single excitation from J-th (occupied)MO to B-th (virtual)MO | |
2277 | - int moJ = this->GetActiveOccIndex(*this->molecule, l); | |
2278 | - int moB = this->GetActiveVirIndex(*this->molecule, l); | |
2279 | - | |
2280 | - // Fast algorithm, but this is not easy to read. Slow algorithm is also written below. | |
2281 | - if(k<l){ | |
2282 | - // Off diagonal term (right upper) | |
2283 | - matrixCIS[k][l] = this->GetCISOffDiagElement(nishimotoMatagaMatrix, *this->molecule, this->fockMatrix, moI, moA, moJ, moB); | |
2284 | - } | |
2285 | - else if(k==l){ | |
2286 | - // Diagonal term | |
2287 | - matrixCIS[k][l] = this->GetCISDiagElement(energiesMO, nishimotoMatagaMatrix, *this->molecule, this->fockMatrix, moI, moA); | |
2288 | - } | |
2289 | - // End of the fast algorith. | |
2290 | - | |
2291 | - /*// Slow algorith, but this is easy to read. Fast altorithm is also written above. | |
2292 | - double value=0.0; | |
2293 | - value = 2.0*this->GetMolecularIntegralElement(moA, moI, moJ, moB, | |
2294 | - *this->molecule, | |
2295 | - this->fockMatrix, | |
2296 | - NULL) | |
2297 | - -this->GetMolecularIntegralElement(moA, moB, moI, moJ, | |
2298 | - *this->molecule, | |
2299 | - this->fockMatrix, | |
2300 | - NULL); | |
2301 | - if(k==l){ | |
2302 | - value += this->energiesMO[moA] - this->energiesMO[moI]; | |
2303 | - } | |
2304 | - matrixCIS[k][l] = value; | |
2305 | - // End of the slow algorith. */ | |
2283 | + for(int k=0; k<this->matrixCISdimension; k++){ | |
2284 | + try{ | |
2285 | + // single excitation from I-th (occupied)MO to A-th (virtual)MO | |
2286 | + int moI = this->GetActiveOccIndex(*this->molecule, k); | |
2287 | + int moA = this->GetActiveVirIndex(*this->molecule, k); | |
2288 | + | |
2289 | + for(int l=k; l<this->matrixCISdimension; l++){ | |
2290 | + // single excitation from J-th (occupied)MO to B-th (virtual)MO | |
2291 | + int moJ = this->GetActiveOccIndex(*this->molecule, l); | |
2292 | + int moB = this->GetActiveVirIndex(*this->molecule, l); | |
2293 | + | |
2294 | + // Fast algorithm, but this is not easy to read. Slow algorithm is also written below. | |
2295 | + if(k<l){ | |
2296 | + // Off diagonal term (right upper) | |
2297 | + matrixCIS[k][l] = this->GetCISOffDiagElement(this->nishimotoMatagaMatrix, *this->molecule, this->fockMatrix, moI, moA, moJ, moB); | |
2306 | 2298 | } |
2299 | + else if(k==l){ | |
2300 | + // Diagonal term | |
2301 | + matrixCIS[k][l] = this->GetCISDiagElement(energiesMO, this->nishimotoMatagaMatrix, *this->molecule, this->fockMatrix, moI, moA); | |
2302 | + } | |
2303 | + // End of the fast algorith. | |
2304 | + | |
2305 | + /*// Slow algorith, but this is easy to read. Fast altorithm is also written above. | |
2306 | + double value=0.0; | |
2307 | + value = 2.0*this->GetMolecularIntegralElement(moA, moI, moJ, moB, | |
2308 | + *this->molecule, | |
2309 | + this->fockMatrix, | |
2310 | + NULL) | |
2311 | + -this->GetMolecularIntegralElement(moA, moB, moI, moJ, | |
2312 | + *this->molecule, | |
2313 | + this->fockMatrix, | |
2314 | + NULL); | |
2315 | + if(k==l){ | |
2316 | + value += this->energiesMO[moA] - this->energiesMO[moI]; | |
2317 | + } | |
2318 | + matrixCIS[k][l] = value; | |
2319 | + // End of the slow algorith. */ | |
2307 | 2320 | } |
2308 | - catch(MolDSException ex){ | |
2321 | + } | |
2322 | + catch(MolDSException ex){ | |
2309 | 2323 | #pragma omp critical |
2310 | - ompErrors << ex.what() << endl ; | |
2311 | - } | |
2312 | - } // end of k-loop | |
2313 | - // Exception throwing for omp-region | |
2314 | - if(!ompErrors.str().empty()){ | |
2315 | - throw MolDSException(ompErrors.str()); | |
2324 | + ompErrors << ex.what() << endl ; | |
2316 | 2325 | } |
2326 | + } // end of k-loop | |
2327 | + // Exception throwing for omp-region | |
2328 | + if(!ompErrors.str().empty()){ | |
2329 | + throw MolDSException(ompErrors.str()); | |
2317 | 2330 | } |
2318 | - catch(MolDSException ex){ | |
2319 | - MallocerFreer::GetInstance()->Free<double>(&nishimotoMatagaMatrix, totalNumberAtoms, OrbitalType_end, totalNumberAtoms, OrbitalType_end); | |
2320 | - throw ex; | |
2321 | - } | |
2322 | - MallocerFreer::GetInstance()->Free<double>(&nishimotoMatagaMatrix, totalNumberAtoms, OrbitalType_end, totalNumberAtoms, OrbitalType_end); | |
2323 | 2331 | double ompEndTime = omp_get_wtime(); |
2324 | 2332 | this->OutputLog(boost::format("%s%lf%s\n%s") % this->messageOmpElapsedTimeCalcCISMarix.c_str() |
2325 | 2333 | % (ompEndTime - ompStartTime) |
@@ -3028,11 +3036,7 @@ double ZindoS::GetSmallQElement(int moI, | ||
3028 | 3036 | for(int lambda=firstAOIndexB; lambda<=lastAOIndexB; lambda++){ |
3029 | 3037 | const OrbitalType orbitalLambda = atomB.GetValence(lambda-firstAOIndexB); |
3030 | 3038 | double twoElecInt = 0.0; |
3031 | - twoElecInt = this->GetNishimotoMatagaTwoEleInt(atomA, | |
3032 | - orbitalMu, | |
3033 | - atomB, | |
3034 | - orbitalLambda, | |
3035 | - rAB); | |
3039 | + twoElecInt = this->nishimotoMatagaMatrix[A][orbitalMu][B][orbitalLambda]; | |
3036 | 3040 | double temp = 0.0; |
3037 | 3041 | if(isMoPOcc){ |
3038 | 3042 | int p = numberOcc - (moP+1); |
@@ -3422,11 +3426,7 @@ double ZindoS::GetAuxiliaryKNRKRElement(int moI, int moJ, int moK, int moL) cons | ||
3422 | 3426 | *this->fockMatrix[moJ][lambda]; |
3423 | 3427 | double gamma = 0.0; |
3424 | 3428 | if(A!=B){ |
3425 | - gamma = this->GetNishimotoMatagaTwoEleInt(atomA, | |
3426 | - orbitalMu, | |
3427 | - atomB, | |
3428 | - orbitalLambda, | |
3429 | - this->molecule->GetDistanceAtoms(atomA, atomB)); | |
3429 | + gamma = this->nishimotoMatagaMatrix[A][orbitalMu][B][orbitalLambda]; | |
3430 | 3430 | } |
3431 | 3431 | else{ |
3432 | 3432 | gamma = 0.5*this->GetCoulombInt(orbitalMu, orbitalLambda, atomA); |
@@ -28,6 +28,7 @@ class ZindoS : public MolDS_cndo::Cndo2{ | ||
28 | 28 | public: |
29 | 29 | ZindoS(); |
30 | 30 | virtual ~ZindoS(); |
31 | + virtual void SetMolecule(MolDS_base::Molecule* molecule); | |
31 | 32 | void DoCIS(); |
32 | 33 | void OutputCISResults() const; |
33 | 34 | void CalcOverlapSingletSDsWithAnotherElectronicStructure(double** overlapSingletSDs, |
@@ -97,6 +98,8 @@ protected: | ||
97 | 98 | virtual double GetExchangeInt(MolDS_base::OrbitalType orbital1, |
98 | 99 | MolDS_base::OrbitalType orbital2, |
99 | 100 | const MolDS_base_atoms::Atom& atom) const; // Apendix in [BZ_1979] |
101 | + virtual void CalcTwoElecTwoCore(double****** twoElecTwoCore, | |
102 | + const MolDS_base::Molecule& molecule) const; | |
100 | 103 | virtual double GetMolecularIntegralElement(int moI, |
101 | 104 | int moJ, |
102 | 105 | int moK, |
@@ -171,6 +174,7 @@ private: | ||
171 | 174 | std::string messageElectronicDipoleMoment; |
172 | 175 | std::string messageTransitionDipoleMomentsTitle; |
173 | 176 | std::string messageTransitionDipoleMoment; |
177 | + double**** nishimotoMatagaMatrix; | |
174 | 178 | int matrixForceElecStatesNum; |
175 | 179 | double nishimotoMatagaParamA; |
176 | 180 | double nishimotoMatagaParamB; |