修订版 | 0c1e048209b1eaecdb0fd329442b2c8a8bff4461 (tree) |
---|---|
时间 | 2011-02-02 11:57:29 |
作者 | Mikiya Fujii <mikiya.fujii@gmai...> |
Commiter | Mikiya Fujii |
damp and diis are added.
git-svn-id: https://svn.sourceforge.jp/svnroot/molds/MolDS/trunk@74 1136aad2-a195-0410-b898-f5ea1d11b9d8
@@ -20,23 +20,27 @@ SCF: | ||
20 | 20 | THEORY_END |
21 | 21 | |
22 | 22 | -options |
23 | - "max_iter", "rms_density", "damping_thresh", and "damping_weight" are prepared as options. | |
24 | - option is "origin" only for setting the origin of the inertia tensor. | |
25 | - options are written in inertia-directive in angstrom unit. | |
26 | - Center of mass is used as origin when the "origin" is not set. | |
23 | + "max_iter", "rms_density", "damping_thresh", "damping_weight", | |
24 | + "diis_num_error_vect", "diis_start_error", and "diis_end_error" are prepared as options. | |
27 | 25 | |
28 | 26 | Default value of "max_iter" is 100. |
29 | 27 | Default value of "rms_density" is 10**(-8.0). |
30 | - Default value of "dampingThresh" is 1. | |
31 | - Default value of "dampingWeight" is 0.8. | |
28 | + Default value of "damping_thresh" is 1. | |
29 | + Default value of "damping_weight" is 0.8. | |
30 | + Default value of "diis_num_error_vect" is 5. | |
31 | + Default value of "diis_start_error" is 0.01. | |
32 | + Default value of "diis_end_error" is 10**(-8.0). | |
32 | 33 | |
33 | 34 | E.g. |
34 | - INERTIA | |
35 | + SCF | |
35 | 36 | max_iter 200 |
36 | 37 | rms_density 0.00000001 |
37 | 38 | damping_thresh 0.1 |
38 | 39 | damping_weight 0.7 |
39 | - INERTIA_END | |
40 | + diis_num_error_vect 6 | |
41 | + diis_start_error 0.01 | |
42 | + diis_end_error 0.00000001 | |
43 | + SCF_END | |
40 | 44 | |
41 | 45 | Principal Axes (Diagonalizing the inertia tensor): |
42 | 46 | Write "principal_axes" in theory-directive. |
@@ -7,6 +7,7 @@ | ||
7 | 7 | [RZ_1973] J. Ridley and M. C. Zerner, Theort. Chim. Acta (Berl.) 32, 111 (1973) |
8 | 8 | [RZ_1976] J. E. Ridley and M. C. Zerner, Theort. Chim. Acta (Berl.) 42, 223 (1976) |
9 | 9 | [BZ_1979] A. D. Bacon and M. C. Zerner, Theort. Chim. Acta (Berl.) 53, 21 (1979) |
10 | +[P_1980] P. Pulay, Chem. Phys. Lett. 73, 393 (1980) | |
10 | 11 | [HKLWNZ_1982] Z. S. Herman, R. F. Kirachner, G. H. Loew, U. T. M.-WesterHoff, A. Nazzal, and M. C. Zerner, Inorg. Chem., 21, 46 (1982) |
11 | 12 | [AEZ_1986] W. P. Anderson, W. D. Edwards, and M. C. Zerner, Inorg. Chem. 25, 2728 (1986) |
12 | 13 | [BFB_1997] M. A. Blanco, M. Fl{\'o}rez, and M. Bermejo, J. Mol. Struct. 419, 19 (1997) |
@@ -40,6 +40,9 @@ private: | ||
40 | 40 | string messageScfRmsDensity; |
41 | 41 | string messageScfDampingThresh; |
42 | 42 | string messageScfDampingWeight; |
43 | + string messageScfDiisNumErrorVect; | |
44 | + string messageScfDiisStartError; | |
45 | + string messageScfDiisEndError; | |
43 | 46 | string stringSpace; |
44 | 47 | string stringCommentOut; |
45 | 48 | string stringTheory; |
@@ -59,6 +62,9 @@ private: | ||
59 | 62 | string stringScfRmsDensity; |
60 | 63 | string stringScfDampingThresh; |
61 | 64 | string stringScfDampingWeight; |
65 | + string stringScfDiisNumErrorVect; | |
66 | + string stringScfDiisStartError; | |
67 | + string stringScfDiisEndError; | |
62 | 68 | string stringInertiaTensor; |
63 | 69 | string stringInertiaTensorEnd; |
64 | 70 | string stringInertiaTensorOrigin; |
@@ -100,6 +106,9 @@ InputParser::InputParser(){ | ||
100 | 106 | this->messageScfRmsDensity = "\t\tRMS density: "; |
101 | 107 | this->messageScfDampingThresh = "\t\tDamping threshold: "; |
102 | 108 | this->messageScfDampingWeight = "\t\tDamping weight: "; |
109 | + this->messageScfDiisNumErrorVect = "\t\tDIIS number of error vectors: "; | |
110 | + this->messageScfDiisStartError = "\t\tDIIS starting error: "; | |
111 | + this->messageScfDiisEndError = "\t\tDIIS ending error: "; | |
103 | 112 | this->stringSpace = " "; |
104 | 113 | this->stringCommentOut = "//"; |
105 | 114 | this->stringTheoryCNDO2 = "cndo/2"; |
@@ -119,6 +128,9 @@ InputParser::InputParser(){ | ||
119 | 128 | this->stringScfRmsDensity = "rms_density"; |
120 | 129 | this->stringScfDampingThresh = "damping_thresh"; |
121 | 130 | this->stringScfDampingWeight = "damping_weight"; |
131 | + this->stringScfDiisNumErrorVect = "diis_num_error_vect"; | |
132 | + this->stringScfDiisStartError = "diis_start_error"; | |
133 | + this->stringScfDiisEndError = "diis_end_error"; | |
122 | 134 | this->stringInertiaTensor = "inertia"; |
123 | 135 | this->stringInertiaTensorEnd = "inertia_end"; |
124 | 136 | this->stringInertiaTensorOrigin = "origin"; |
@@ -261,6 +273,21 @@ void InputParser::Parse(Molecule* molecule){ | ||
261 | 273 | Parameters::GetInstance()->SetDampingWeightSCF(atof(inputTerms[j+1].c_str())); |
262 | 274 | j++; |
263 | 275 | } |
276 | + // DIIS number of stored error vectors | |
277 | + if(inputTerms[j].compare(this->stringScfDiisNumErrorVect) == 0){ | |
278 | + Parameters::GetInstance()->SetDiisNumErrorVectSCF(atoi(inputTerms[j+1].c_str())); | |
279 | + j++; | |
280 | + } | |
281 | + // DIIS starting error | |
282 | + if(inputTerms[j].compare(this->stringScfDiisStartError) == 0){ | |
283 | + Parameters::GetInstance()->SetDiisStartErrorSCF(atof(inputTerms[j+1].c_str())); | |
284 | + j++; | |
285 | + } | |
286 | + // DIIS ending error | |
287 | + if(inputTerms[j].compare(this->stringScfDiisEndError) == 0){ | |
288 | + Parameters::GetInstance()->SetDiisEndErrorSCF(atof(inputTerms[j+1].c_str())); | |
289 | + j++; | |
290 | + } | |
264 | 291 | j++; |
265 | 292 | } |
266 | 293 | i = j; |
@@ -456,6 +483,9 @@ void InputParser::OutputScfConditions(){ | ||
456 | 483 | printf("%s%e\n",this->messageScfRmsDensity.c_str(),Parameters::GetInstance()->GetThresholdSCF()); |
457 | 484 | printf("%s%e\n",this->messageScfDampingThresh.c_str(),Parameters::GetInstance()->GetDampingThreshSCF()); |
458 | 485 | printf("%s%e\n",this->messageScfDampingWeight.c_str(),Parameters::GetInstance()->GetDampingWeightSCF()); |
486 | + printf("%s%d\n",this->messageScfDiisNumErrorVect.c_str(),Parameters::GetInstance()->GetDiisNumErrorVectSCF()); | |
487 | + printf("%s%e\n",this->messageScfDiisStartError.c_str(),Parameters::GetInstance()->GetDiisStartErrorSCF()); | |
488 | + printf("%s%e\n",this->messageScfDiisEndError.c_str(),Parameters::GetInstance()->GetDiisEndErrorSCF()); | |
459 | 489 | cout << "\n"; |
460 | 490 | |
461 | 491 | } |
@@ -23,6 +23,12 @@ public: | ||
23 | 23 | void SetDampingThreshSCF(double dampingThreshSCF); |
24 | 24 | double GetDampingWeightSCF(); |
25 | 25 | void SetDampingWeightSCF(double dampingWeightSCF); |
26 | + int GetDiisNumErrorVectSCF(); | |
27 | + void SetDiisNumErrorVectSCF(int diisNumErrorVectSCF); | |
28 | + double GetDiisStartErrorSCF(); | |
29 | + void SetDiisStartErrorSCF(double diisStartErrorSCF); | |
30 | + double GetDiisEndErrorSCF(); | |
31 | + void SetDiisEndErrorSCF(double diisEndErrorSCF); | |
26 | 32 | double GetEV2AU(); |
27 | 33 | double GetAngstrom2AU(); |
28 | 34 | double GetKayser2AU(); |
@@ -62,6 +68,9 @@ private: | ||
62 | 68 | int maxIterationsSCF; |
63 | 69 | double dampingThreshSCF; |
64 | 70 | double dampingWeightSCF; |
71 | + int diisNumErrorVectSCF; | |
72 | + double diisStartErrorSCF; | |
73 | + double diisEndErrorSCF; | |
65 | 74 | void SetDefaultValues(); |
66 | 75 | double eV2AU; |
67 | 76 | double angstrom2AU; |
@@ -123,6 +132,9 @@ void Parameters::SetDefaultValues(){ | ||
123 | 132 | this->maxIterationsSCF = 100; |
124 | 133 | this->dampingThreshSCF = 1.0; |
125 | 134 | this->dampingWeightSCF = 0.8; |
135 | + this->diisNumErrorVectSCF = 5; | |
136 | + this->diisStartErrorSCF = pow(10.0, -2.0); | |
137 | + this->diisEndErrorSCF = pow(10.0, -8.0); | |
126 | 138 | this->currentTheory = CNDO2; |
127 | 139 | this->gMolin2AU = pow(10.0,5.0)/(6.0221415*9.1095); |
128 | 140 | this->degree2Radian = M_PI / 180.0; |
@@ -175,6 +187,30 @@ void Parameters::SetDampingWeightSCF(double dampingWeightSCF){ | ||
175 | 187 | this->dampingWeightSCF = dampingWeightSCF; |
176 | 188 | } |
177 | 189 | |
190 | +int Parameters::GetDiisNumErrorVectSCF(){ | |
191 | + return this->diisNumErrorVectSCF; | |
192 | +} | |
193 | + | |
194 | +void Parameters::SetDiisNumErrorVectSCF(int diisNumErrorVectSCF){ | |
195 | + this->diisNumErrorVectSCF = diisNumErrorVectSCF; | |
196 | +} | |
197 | + | |
198 | +double Parameters::GetDiisStartErrorSCF(){ | |
199 | + return this->diisStartErrorSCF; | |
200 | +} | |
201 | + | |
202 | +void Parameters::SetDiisStartErrorSCF(double diisStartErrorSCF){ | |
203 | + this->diisStartErrorSCF = diisStartErrorSCF; | |
204 | +} | |
205 | + | |
206 | +double Parameters::GetDiisEndErrorSCF(){ | |
207 | + return this->diisEndErrorSCF; | |
208 | +} | |
209 | + | |
210 | +void Parameters::SetDiisEndErrorSCF(double diisEndErrorSCF){ | |
211 | + this->diisEndErrorSCF = diisEndErrorSCF; | |
212 | +} | |
213 | + | |
178 | 214 | double Parameters::GetEV2AU(){ |
179 | 215 | return this->eV2AU; |
180 | 216 | } |
@@ -102,6 +102,20 @@ private: | ||
102 | 102 | double GetAuxiliaryA(int k, double rho); |
103 | 103 | double GetAuxiliaryB(int k, double rho); |
104 | 104 | double GetAuxiliaryD(int la, int lb, int m); |
105 | + void DoesDamp(double rmsDensity, | |
106 | + double** orbitalElectronPopulation, | |
107 | + double** oldOrbitalElectronPopulation, | |
108 | + Molecule* molecule); | |
109 | + void DoesDIIS(double** orbitalElectronPopulation, | |
110 | + double** oldOrbitalElectronPopulation, | |
111 | + double* atomicElectronPopulation, | |
112 | + double*** diisStoredDensityMatrix, | |
113 | + double*** diisStoredErrorVect, | |
114 | + double** diisErrorProducts, | |
115 | + double* diisErrorCoefficients, | |
116 | + int diisNumErrorVect, | |
117 | + Molecule* molecule, | |
118 | + int step); | |
105 | 119 | void OutputResults(double** fockMatrix, double* energiesMO, double* atomicElectronPopulation, Molecule* molecule); |
106 | 120 | void CheckEnableAtomType(Molecule* molecule); |
107 | 121 | void CheckNumberValenceElectrons(Molecule* molecule); |
@@ -111,6 +125,11 @@ private: | ||
111 | 125 | double** hMatrix, |
112 | 126 | double** dammyOrbitalElectronPopulation, |
113 | 127 | double* dammyAtomicElectronPopulation ); |
128 | + void FreeSCFTemporaryMatrices(double** oldOrbitalElectronPopulation, | |
129 | + double*** diisStoredDensityMatrix, | |
130 | + double*** diisStoredErrorVect, | |
131 | + double** diisErrorProducts, | |
132 | + double* diisErrorCoefficients); | |
114 | 133 | |
115 | 134 | }; |
116 | 135 |
@@ -289,8 +308,28 @@ void Cndo2::DoesSCF(){ | ||
289 | 308 | throw MolDSException(ss.str()); |
290 | 309 | } |
291 | 310 | |
311 | + // diis parameters | |
312 | + int diisNumErrorVect = Parameters::GetInstance()->GetDiisNumErrorVectSCF(); | |
313 | + | |
314 | + | |
315 | + // malloc temporary matrices for scf | |
292 | 316 | double** oldOrbitalElectronPopulation = MallocerFreer::GetInstance()->MallocDoubleMatrix2d |
293 | 317 | (this->molecule->GetTotalNumberAOs(), this->molecule->GetTotalNumberAOs()); |
318 | + | |
319 | + // malloc temporary matrices for diis | |
320 | + double*** diisStoredDensityMatrix = NULL; | |
321 | + double*** diisStoredErrorVect = NULL; | |
322 | + double** diisErrorProducts = NULL; | |
323 | + double* diisErrorCoefficients = NULL; | |
324 | + if(0<diisNumErrorVect){ | |
325 | + diisStoredDensityMatrix = MallocerFreer::GetInstance()->MallocDoubleMatrix3d | |
326 | + (diisNumErrorVect, this->molecule->GetTotalNumberAOs(), this->molecule->GetTotalNumberAOs()); | |
327 | + diisStoredErrorVect = MallocerFreer::GetInstance()->MallocDoubleMatrix3d | |
328 | + (diisNumErrorVect, this->molecule->GetTotalNumberAOs(), this->molecule->GetTotalNumberAOs()); | |
329 | + diisErrorProducts = MallocerFreer::GetInstance()->MallocDoubleMatrix2d(diisNumErrorVect+1, diisNumErrorVect+1); | |
330 | + diisErrorCoefficients = MallocerFreer::GetInstance()->MallocDoubleMatrix1d(diisNumErrorVect+1); | |
331 | + } | |
332 | + | |
294 | 333 | try{ |
295 | 334 | // calculate electron integral |
296 | 335 | this->CalcGammaAB(this->gammaAB, this->molecule); |
@@ -298,8 +337,6 @@ void Cndo2::DoesSCF(){ | ||
298 | 337 | |
299 | 338 | // SCF |
300 | 339 | double rmsDensity; |
301 | - double dampingWeight = Parameters::GetInstance()->GetDampingWeightSCF(); | |
302 | - double dampingThresh = Parameters::GetInstance()->GetDampingThreshSCF(); | |
303 | 340 | int maxIterationsSCF = Parameters::GetInstance()->GetMaxIterationsSCF(); |
304 | 341 | bool isGuess=true; |
305 | 342 | for(int i=0; i<maxIterationsSCF; i++){ |
@@ -312,7 +349,7 @@ void Cndo2::DoesSCF(){ | ||
312 | 349 | this->orbitalElectronPopulation, |
313 | 350 | this->atomicElectronPopulation, |
314 | 351 | isGuess); |
315 | - | |
352 | + | |
316 | 353 | // diagonalization |
317 | 354 | bool calcEigenVectors = true; |
318 | 355 | MolDS_mkl_wrapper::LapackWrapper::GetInstance()->Dsyevd(this->fockMatrix, |
@@ -325,17 +362,6 @@ void Cndo2::DoesSCF(){ | ||
325 | 362 | this->molecule, |
326 | 363 | this->fockMatrix); |
327 | 364 | |
328 | - // damping | |
329 | - if(dampingThresh < rmsDensity){ | |
330 | - for(int j=0; j<this->molecule->GetTotalNumberAOs(); j++){ | |
331 | - for(int k=0; k<this->molecule->GetTotalNumberAOs(); k++){ | |
332 | - this->orbitalElectronPopulation[j][k] *= (1.0-dampingWeight); | |
333 | - this->orbitalElectronPopulation[j][k] += dampingWeight*oldOrbitalElectronPopulation[j][k]; | |
334 | - | |
335 | - } | |
336 | - } | |
337 | - } | |
338 | - | |
339 | 365 | // calc. electron population in each atom. |
340 | 366 | this->CalcAtomicElectronPopulation(this->atomicElectronPopulation, |
341 | 367 | this->orbitalElectronPopulation, |
@@ -347,13 +373,31 @@ void Cndo2::DoesSCF(){ | ||
347 | 373 | this->molecule->GetTotalNumberAOs(), &rmsDensity, i)){ |
348 | 374 | |
349 | 375 | cout << this->messageSCFMetConvergence; |
350 | - this->OutputResults(this->fockMatrix, | |
351 | - this->energiesMO, | |
352 | - this->atomicElectronPopulation, | |
353 | - this->molecule); | |
354 | - | |
376 | + this->OutputResults(this->fockMatrix, this->energiesMO, this->atomicElectronPopulation, this->molecule); | |
355 | 377 | break; |
356 | 378 | } |
379 | + else{ | |
380 | + | |
381 | + // damping | |
382 | + this->DoesDamp(rmsDensity, this->orbitalElectronPopulation, oldOrbitalElectronPopulation, this->molecule); | |
383 | + | |
384 | + // diis | |
385 | + this->DoesDIIS(this->orbitalElectronPopulation, | |
386 | + oldOrbitalElectronPopulation, | |
387 | + this->atomicElectronPopulation, | |
388 | + diisStoredDensityMatrix, | |
389 | + diisStoredErrorVect, | |
390 | + diisErrorProducts, | |
391 | + diisErrorCoefficients, | |
392 | + diisNumErrorVect, | |
393 | + this->molecule, | |
394 | + i); | |
395 | + | |
396 | + this->UpdateOldOrbitalElectronPopulation(oldOrbitalElectronPopulation, | |
397 | + this->orbitalElectronPopulation, | |
398 | + this->molecule->GetTotalNumberAOs()); | |
399 | + | |
400 | + } | |
357 | 401 | |
358 | 402 | // SCF fails |
359 | 403 | if(i==maxIterationsSCF-1){ |
@@ -361,27 +405,169 @@ void Cndo2::DoesSCF(){ | ||
361 | 405 | ss << this->errorMessageSCFNotConverged << maxIterationsSCF << "\n"; |
362 | 406 | throw MolDSException(ss.str()); |
363 | 407 | } |
364 | - | |
365 | 408 | } |
366 | 409 | } |
367 | 410 | catch(MolDSException ex){ |
368 | - if(oldOrbitalElectronPopulation != NULL){ | |
369 | - MallocerFreer::GetInstance()->FreeDoubleMatrix2d | |
370 | - (oldOrbitalElectronPopulation, this->molecule->GetTotalNumberAOs()); | |
371 | - oldOrbitalElectronPopulation = NULL; | |
372 | - //cout << "oldOrbitalElectronPopulation deleted\n"; | |
373 | - } | |
411 | + this->FreeSCFTemporaryMatrices(oldOrbitalElectronPopulation, | |
412 | + diisStoredDensityMatrix, | |
413 | + diisStoredErrorVect, | |
414 | + diisErrorProducts, | |
415 | + diisErrorCoefficients); | |
416 | + | |
374 | 417 | throw ex; |
375 | 418 | } |
376 | - | |
419 | + this->FreeSCFTemporaryMatrices(oldOrbitalElectronPopulation, | |
420 | + diisStoredDensityMatrix, | |
421 | + diisStoredErrorVect, | |
422 | + diisErrorProducts, | |
423 | + diisErrorCoefficients); | |
424 | + | |
425 | + | |
426 | + cout << this->messageDoneSCF; | |
427 | + | |
428 | +} | |
429 | + | |
430 | +void Cndo2::FreeSCFTemporaryMatrices(double** oldOrbitalElectronPopulation, | |
431 | + double*** diisStoredDensityMatrix, | |
432 | + double*** diisStoredErrorVect, | |
433 | + double** diisErrorProducts, | |
434 | + double* diisErrorCoefficients){ | |
435 | + | |
436 | + int diisNumErrorVect = Parameters::GetInstance()->GetDiisNumErrorVectSCF(); | |
377 | 437 | if(oldOrbitalElectronPopulation != NULL){ |
378 | 438 | MallocerFreer::GetInstance()->FreeDoubleMatrix2d |
379 | 439 | (oldOrbitalElectronPopulation, this->molecule->GetTotalNumberAOs()); |
380 | 440 | oldOrbitalElectronPopulation = NULL; |
381 | 441 | //cout << "oldOrbitalElectronPopulation deleted\n"; |
382 | 442 | } |
443 | + if(diisStoredDensityMatrix != NULL){ | |
444 | + MallocerFreer::GetInstance()->FreeDoubleMatrix3d | |
445 | + (diisStoredDensityMatrix, diisNumErrorVect, this->molecule->GetTotalNumberAOs()); | |
446 | + diisStoredDensityMatrix = NULL; | |
447 | + //cout << "diisStoredDensityMatrix deleted\n"; | |
448 | + } | |
449 | + if(diisStoredErrorVect != NULL){ | |
450 | + MallocerFreer::GetInstance()->FreeDoubleMatrix3d | |
451 | + (diisStoredErrorVect, diisNumErrorVect, this->molecule->GetTotalNumberAOs()); | |
452 | + diisStoredErrorVect = NULL; | |
453 | + //cout << "diisStoredErrorVect deleted\n"; | |
454 | + } | |
455 | + if(diisErrorProducts != NULL){ | |
456 | + MallocerFreer::GetInstance()->FreeDoubleMatrix2d | |
457 | + (diisErrorProducts, diisNumErrorVect+1); | |
458 | + diisErrorProducts = NULL; | |
459 | + //cout << "diisErrorProducts deleted\n"; | |
460 | + } | |
461 | + if(diisErrorCoefficients != NULL){ | |
462 | + MallocerFreer::GetInstance()->FreeDoubleMatrix1d | |
463 | + (diisErrorCoefficients); | |
464 | + diisErrorCoefficients = NULL; | |
465 | + //cout << "diisErrorCoefficients deleted\n"; | |
466 | + } | |
383 | 467 | |
384 | - cout << this->messageDoneSCF; | |
468 | +} | |
469 | + | |
470 | +/*** | |
471 | + * | |
472 | + * see ref. [P_1980] for diis methods. | |
473 | + * | |
474 | + */ | |
475 | +void Cndo2::DoesDIIS(double** orbitalElectronPopulation, | |
476 | + double** oldOrbitalElectronPopulation, | |
477 | + double* atomicElectronPopulation, | |
478 | + double*** diisStoredDensityMatrix, | |
479 | + double*** diisStoredErrorVect, | |
480 | + double** diisErrorProducts, | |
481 | + double* diisErrorCoefficients, | |
482 | + int diisNumErrorVect, | |
483 | + Molecule* molecule, | |
484 | + int step){ | |
485 | + | |
486 | + int totalNumberAOs = molecule->GetTotalNumberAOs(); | |
487 | + double diisStartError = Parameters::GetInstance()->GetDiisStartErrorSCF(); | |
488 | + double diisEndError = Parameters::GetInstance()->GetDiisEndErrorSCF(); | |
489 | + | |
490 | + if( 0 < diisNumErrorVect){ | |
491 | + for(int m=0; m<diisNumErrorVect-1; m++){ | |
492 | + for(int j=0; j<totalNumberAOs; j++){ | |
493 | + for(int k=0; k<totalNumberAOs; k++){ | |
494 | + diisStoredDensityMatrix[m][j][k] = diisStoredDensityMatrix[m+1][j][k]; | |
495 | + diisStoredErrorVect[m][j][k] = diisStoredErrorVect[m+1][j][k]; | |
496 | + } | |
497 | + } | |
498 | + } | |
499 | + | |
500 | + for(int j=0; j<totalNumberAOs; j++){ | |
501 | + for(int k=0; k<totalNumberAOs; k++){ | |
502 | + diisStoredDensityMatrix[diisNumErrorVect-1][j][k] = orbitalElectronPopulation[j][k]; | |
503 | + diisStoredErrorVect[diisNumErrorVect-1][j][k] = orbitalElectronPopulation[j][k] | |
504 | + -oldOrbitalElectronPopulation[j][k]; | |
505 | + | |
506 | + } | |
507 | + } | |
508 | + | |
509 | + for(int mi=0; mi<diisNumErrorVect-1; mi++){ | |
510 | + for(int mj=0; mj<diisNumErrorVect-1; mj++){ | |
511 | + diisErrorProducts[mi][mj] = diisErrorProducts[mi+1][mj+1]; | |
512 | + } | |
513 | + } | |
514 | + | |
515 | + double tempErrorProduct=0.0; | |
516 | + for(int mi=0; mi<diisNumErrorVect; mi++){ | |
517 | + tempErrorProduct = 0.0; | |
518 | + for(int j=0; j<totalNumberAOs; j++){ | |
519 | + for(int k=0; k<totalNumberAOs; k++){ | |
520 | + tempErrorProduct += diisStoredErrorVect[mi][j][k]*diisStoredErrorVect[diisNumErrorVect-1][j][k]; | |
521 | + } | |
522 | + } | |
523 | + diisErrorProducts[mi][diisNumErrorVect-1] = tempErrorProduct; | |
524 | + diisErrorProducts[diisNumErrorVect-1][mi] = tempErrorProduct; | |
525 | + diisErrorProducts[mi][diisNumErrorVect] = -1.0; | |
526 | + diisErrorProducts[diisNumErrorVect][mi] = -1.0; | |
527 | + diisErrorCoefficients[mi] = 0.0; | |
528 | + } | |
529 | + diisErrorProducts[diisNumErrorVect][diisNumErrorVect] = 0.0; | |
530 | + diisErrorCoefficients[diisNumErrorVect] = -1.0; | |
531 | + | |
532 | + double eMax = 0; | |
533 | + for(int j=0; j<totalNumberAOs; j++){ | |
534 | + for(int k=0; k<totalNumberAOs; k++){ | |
535 | + eMax = max(eMax, fabs(diisStoredErrorVect[diisNumErrorVect-1][j][k])); | |
536 | + } | |
537 | + } | |
538 | + | |
539 | + if(diisNumErrorVect <= step && diisEndError<eMax && eMax<diisStartError){ | |
540 | + MolDS_mkl_wrapper::LapackWrapper::GetInstance()->Dsysv(diisErrorProducts, | |
541 | + diisErrorCoefficients, | |
542 | + diisNumErrorVect+1); | |
543 | + for(int j=0; j<totalNumberAOs; j++){ | |
544 | + for(int k=0; k<totalNumberAOs; k++){ | |
545 | + orbitalElectronPopulation[j][k] = 0.0; | |
546 | + for(int m=0; m<diisNumErrorVect; m++){ | |
547 | + orbitalElectronPopulation[j][k] += diisErrorCoefficients[m]*diisStoredDensityMatrix[m][j][k]; | |
548 | + } | |
549 | + } | |
550 | + } | |
551 | + | |
552 | + // calc. electron population in each atom. | |
553 | + this->CalcAtomicElectronPopulation(atomicElectronPopulation, orbitalElectronPopulation, molecule); | |
554 | + } | |
555 | + } | |
556 | +} | |
557 | + | |
558 | +void Cndo2::DoesDamp(double rmsDensity, double** orbitalElectronPopulation, | |
559 | + double** oldOrbitalElectronPopulation, Molecule* molecule){ | |
560 | + | |
561 | + double dampingThresh = Parameters::GetInstance()->GetDampingThreshSCF(); | |
562 | + double dampingWeight = Parameters::GetInstance()->GetDampingWeightSCF(); | |
563 | + if(0.0 < dampingWeight && dampingThresh < rmsDensity){ | |
564 | + for(int j=0; j<molecule->GetTotalNumberAOs(); j++){ | |
565 | + for(int k=0; k<molecule->GetTotalNumberAOs(); k++){ | |
566 | + orbitalElectronPopulation[j][k] *= (1.0 - dampingWeight); | |
567 | + orbitalElectronPopulation[j][k] += dampingWeight*oldOrbitalElectronPopulation[j][k]; | |
568 | + } | |
569 | + } | |
570 | + } | |
385 | 571 | |
386 | 572 | } |
387 | 573 |
@@ -596,11 +782,6 @@ bool Cndo2::SatisfyConvergenceCriterion(double** oldOrbitalElectronPopulation, | ||
596 | 782 | if(*rmsDensity < Parameters::GetInstance()->GetThresholdSCF()){ |
597 | 783 | satisfy = true; |
598 | 784 | } |
599 | - else{ | |
600 | - this->UpdateOldOrbitalElectronPopulation(oldOrbitalElectronPopulation, | |
601 | - orbitalElectronPopulation, | |
602 | - numberAOs); | |
603 | - } | |
604 | 785 | |
605 | 786 | return satisfy; |
606 | 787 | } |
@@ -1,6 +1,6 @@ | ||
1 | 1 | THEORY |
2 | - //cndo/2 | |
3 | - indo | |
2 | + cndo/2 | |
3 | + //indo | |
4 | 4 | //zindo/s |
5 | 5 | //none |
6 | 6 | //principal_axes |
@@ -9,15 +9,18 @@ THEORY | ||
9 | 9 | THEORY_END |
10 | 10 | |
11 | 11 | SCF |
12 | - max_iter 200 | |
13 | - rms_density 0.00000001 | |
12 | + max_iter 50 | |
13 | + rms_density 0.000001 | |
14 | 14 | damping_thresh 1.0 |
15 | - damping_weight 0.7 | |
15 | + damping_weight 0.0 | |
16 | + diis_num_error_vect 5 | |
17 | + diis_start_error 0.002 | |
18 | + diis_end_error 0.00000002 | |
16 | 19 | SCF_END |
17 | 20 | |
18 | 21 | CIS |
19 | - activeOcc 100 | |
20 | - activeVir 100 | |
22 | + activeOcc 2 | |
23 | + activeVir 2 | |
21 | 24 | nstates 1000 |
22 | 25 | CIS_END |
23 | 26 |
@@ -18,24 +18,32 @@ public: | ||
18 | 18 | static LapackWrapper* GetInstance(); |
19 | 19 | static void DeleteInstance(); |
20 | 20 | int Dsyevd(double** matrix, double* eigenValues, int size, bool calcEigenVectors); |
21 | + int Dsysv(double** matrix, double* b, int size); | |
21 | 22 | private: |
22 | 23 | LapackWrapper(); |
23 | 24 | LapackWrapper(LapackWrapper&); |
24 | 25 | void operator = (LapackWrapper&); |
25 | 26 | ~LapackWrapper(); |
26 | 27 | static LapackWrapper* lapackWrapper; |
27 | - | |
28 | + bool calculatedDsysvWorkSize; | |
29 | + int dsysvWorkSize; | |
28 | 30 | string errorMessageDsyevdInfo; |
29 | 31 | string errorMessageDsyevdSize; |
32 | + string errorMessageDsysvInfo; | |
33 | + string errorMessageDsysvSize; | |
30 | 34 | }; |
31 | 35 | LapackWrapper* LapackWrapper::lapackWrapper = NULL; |
32 | 36 | |
33 | 37 | LapackWrapper::LapackWrapper(){ |
34 | 38 | this->errorMessageDsyevdInfo = "Error in mkl_wrapper::LapackWrapper::Dsyevd: info != 0\n"; |
35 | 39 | this->errorMessageDsyevdSize = "Error in mkl_wrapper::LapackWrapper::Dsyevd: size of matirx < 1\n"; |
40 | + this->errorMessageDsysvInfo = "Error in mkl_wrapper::LapackWrapper::Dsysv: info != 0\n"; | |
41 | + this->errorMessageDsysvSize = "Error in mkl_wrapper::LapackWrapper::Dsysv: size of matirx < 1\n"; | |
36 | 42 | } |
37 | 43 | |
38 | 44 | LapackWrapper::~LapackWrapper(){ |
45 | + this->calculatedDsysvWorkSize = false; | |
46 | + this->dsysvWorkSize = 64; | |
39 | 47 | } |
40 | 48 | |
41 | 49 | LapackWrapper* LapackWrapper::GetInstance(){ |
@@ -154,6 +162,72 @@ int LapackWrapper::Dsyevd(double** matrix, double* eigenValues, int size, bool c | ||
154 | 162 | return info; |
155 | 163 | } |
156 | 164 | |
165 | +/*** | |
166 | + * | |
167 | + * Slove matrix*X=b, then we get X by this method. | |
168 | + * The X is stored in b. | |
169 | + * | |
170 | + */ | |
171 | +int LapackWrapper::Dsysv(double** matrix, double* b, int size){ | |
172 | + int info = 0; | |
173 | + int lwork; | |
174 | + char uplo = 'U'; | |
175 | + int lda = size; | |
176 | + int ldb = size; | |
177 | + int nrhs = 1; | |
178 | + double* convertedMatrix; | |
179 | + double* work; | |
180 | + int* ipiv; | |
181 | + | |
182 | + if(size < 1 ){ | |
183 | + stringstream ss; | |
184 | + ss << errorMessageDsysvSize; | |
185 | + throw MolDSException(ss.str()); | |
186 | + } | |
187 | + | |
188 | + // malloc | |
189 | + ipiv = MallocerFreer::GetInstance()->MallocIntMatrix1d(2*size); | |
190 | + convertedMatrix = MallocerFreer::GetInstance()->MallocDoubleMatrix1d(size*size); | |
191 | + | |
192 | + for(int i = 0; i < size; i++){ | |
193 | + for(int j = i; j < size; j++){ | |
194 | + convertedMatrix[i+j*size] = matrix[i][j]; | |
195 | + } | |
196 | + } | |
197 | + | |
198 | + // calc. lwork | |
199 | + if(!this->calculatedDsysvWorkSize){ | |
200 | + lwork = -1; | |
201 | + double tempWork[3]={0.0, 0.0, 0.0}; | |
202 | + dsysv(&uplo, &size, &nrhs, convertedMatrix, &lda, ipiv, b, &ldb, tempWork, &lwork, &info); | |
203 | + this->calculatedDsysvWorkSize = true; | |
204 | + this->dsysvWorkSize = tempWork[0]; | |
205 | + } | |
206 | + | |
207 | + info = 0; | |
208 | + lwork = this->dsysvWorkSize; | |
209 | + work = MallocerFreer::GetInstance()->MallocDoubleMatrix1d(lwork); | |
210 | + | |
211 | + // call Lapack | |
212 | + dsysv(&uplo, &size, &nrhs, convertedMatrix, &lda, ipiv, b, &ldb, work, &lwork, &info); | |
213 | + | |
214 | + // free | |
215 | + MallocerFreer::GetInstance()->FreeDoubleMatrix1d(convertedMatrix); | |
216 | + convertedMatrix = NULL; | |
217 | + MallocerFreer::GetInstance()->FreeIntMatrix1d(ipiv); | |
218 | + ipiv = NULL; | |
219 | + MallocerFreer::GetInstance()->FreeDoubleMatrix1d(work); | |
220 | + work = NULL; | |
221 | + | |
222 | + if(info != 0){ | |
223 | + cout << "info=" << info << endl; | |
224 | + stringstream ss; | |
225 | + ss << errorMessageDsysvInfo; | |
226 | + throw MolDSException(ss.str()); | |
227 | + } | |
228 | + return info; | |
229 | +} | |
230 | + | |
157 | 231 | |
158 | 232 | |
159 | 233 | } |