Révision | ce896c8ce3c7ae8cbfadc32e4101add78c19e25f (tree) |
---|---|
l'heure | 2011-07-08 19:20:41 |
Auteur | Mikiya Fujii <mikiya.fujii@gmai...> |
Commiter | Mikiya Fujii |
CIS-Davidson is implemented. This is implemented with also open MP.
git-svn-id: https://svn.sourceforge.jp/svnroot/molds/MolDS/trunk@111 1136aad2-a195-0410-b898-f5ea1d11b9d8
@@ -48,6 +48,9 @@ private: | ||
48 | 48 | string messageCisNumberActiveVir; |
49 | 49 | string messageCisNumberExcitedStates; |
50 | 50 | string messageCisDavidson; |
51 | + string messageCisNormTolerance; | |
52 | + string messageCisMaxIterations; | |
53 | + string messageCisMaxDimensions; | |
51 | 54 | string stringYES; |
52 | 55 | string stringNO; |
53 | 56 | string stringSpace; |
@@ -93,6 +96,9 @@ private: | ||
93 | 96 | string stringCISActiveVir; |
94 | 97 | string stringCISNStates; |
95 | 98 | string stringCISDavidson; |
99 | + string stringCISMaxIter; | |
100 | + string stringCISMaxDimensions; | |
101 | + string stringCISNormTolerance; | |
96 | 102 | void CalcMolecularBasics(Molecule* molecule); |
97 | 103 | void CalcCisCondition(Molecule* molecule); |
98 | 104 | void OutputMolecularBasics(Molecule* molecule); |
@@ -124,6 +130,9 @@ InputParser::InputParser(){ | ||
124 | 130 | this->messageCisNumberActiveVir = "\t\tNumber of active Vir.: "; |
125 | 131 | this->messageCisNumberExcitedStates = "\t\tNumber of excited states: "; |
126 | 132 | this->messageCisDavidson = "\t\tCIS-Davidson: "; |
133 | + this->messageCisNormTolerance = "\t\tNorm tolerance for the residual of the Davidson: "; | |
134 | + this->messageCisMaxIterations = "\t\tMax iterations for the Davidson: "; | |
135 | + this->messageCisMaxDimensions = "\t\tMax dimensions for the Davidson: "; | |
127 | 136 | this->stringYES = "yes"; |
128 | 137 | this->stringNO = "no"; |
129 | 138 | this->stringSpace = " "; |
@@ -169,6 +178,9 @@ InputParser::InputParser(){ | ||
169 | 178 | this->stringCISActiveVir = "active_vir"; |
170 | 179 | this->stringCISNStates = "nstates"; |
171 | 180 | this->stringCISDavidson = "davidson"; |
181 | + this->stringCISMaxIter = "max_iter"; | |
182 | + this->stringCISMaxDimensions = "max_dim"; | |
183 | + this->stringCISNormTolerance = "norm_tol"; | |
172 | 184 | } |
173 | 185 | |
174 | 186 | InputParser::~InputParser(){ |
@@ -426,12 +438,29 @@ void InputParser::Parse(Molecule* molecule){ | ||
426 | 438 | } |
427 | 439 | j++; |
428 | 440 | } |
441 | + // max iterations for the Davidson roop | |
442 | + if(inputTerms[j].compare(this->stringCISMaxIter) == 0){ | |
443 | + int maxIter = atoi(inputTerms[j+1].c_str()); | |
444 | + Parameters::GetInstance()->SetMaxIterationsCIS(maxIter); | |
445 | + j++; | |
446 | + } | |
447 | + // max dimensions for the Davidson expansion | |
448 | + if(inputTerms[j].compare(this->stringCISMaxDimensions) == 0){ | |
449 | + int maxDim = atoi(inputTerms[j+1].c_str()); | |
450 | + Parameters::GetInstance()->SetMaxDimensionsCIS(maxDim); | |
451 | + j++; | |
452 | + } | |
453 | + // nolm tolerance for the norm of the resiudal vectors of the Davidson. | |
454 | + if(inputTerms[j].compare(this->stringCISNormTolerance) == 0){ | |
455 | + double normTol = atof(inputTerms[j+1].c_str()); | |
456 | + Parameters::GetInstance()->SetNormToleranceCIS(normTol); | |
457 | + j++; | |
458 | + } | |
429 | 459 | j++; |
430 | 460 | } |
431 | 461 | i = j; |
432 | 462 | } |
433 | 463 | |
434 | - | |
435 | 464 | // theory |
436 | 465 | if(inputTerms[i].compare(this->stringTheory) == 0){ |
437 | 466 | int j=i+1; |
@@ -524,14 +553,17 @@ void InputParser::CalcCisCondition(Molecule* molecule){ | ||
524 | 553 | } |
525 | 554 | |
526 | 555 | // check the number of calculated excited states. |
527 | - int numberExcitedStates = Parameters::GetInstance()->GetActiveOccCIS() | |
528 | - *Parameters::GetInstance()->GetActiveVirCIS(); | |
556 | + int numberSlaterDeterminants = Parameters::GetInstance()->GetActiveOccCIS() | |
557 | + *Parameters::GetInstance()->GetActiveVirCIS(); | |
529 | 558 | if(!Parameters::GetInstance()->GetIsDavidsonCIS()){ |
530 | - Parameters::GetInstance()->SetNumberExcitedStatesCIS(numberExcitedStates); | |
559 | + Parameters::GetInstance()->SetNumberExcitedStatesCIS(numberSlaterDeterminants); | |
531 | 560 | } |
532 | 561 | else{ |
533 | - if(numberExcitedStates < Parameters::GetInstance()->GetNumberExcitedStatesCIS()){ | |
534 | - Parameters::GetInstance()->SetNumberExcitedStatesCIS(numberExcitedStates); | |
562 | + if(numberSlaterDeterminants < Parameters::GetInstance()->GetNumberExcitedStatesCIS()){ | |
563 | + Parameters::GetInstance()->SetNumberExcitedStatesCIS(numberSlaterDeterminants); | |
564 | + } | |
565 | + if(numberSlaterDeterminants < Parameters::GetInstance()->GetMaxDimensionsCIS()){ | |
566 | + Parameters::GetInstance()->SetMaxDimensionsCIS(numberSlaterDeterminants); | |
535 | 567 | } |
536 | 568 | } |
537 | 569 |
@@ -568,6 +600,9 @@ void InputParser::OutputCisConditions(){ | ||
568 | 600 | printf("%s",this->messageCisDavidson.c_str()); |
569 | 601 | if(Parameters::GetInstance()->GetIsDavidsonCIS()){ |
570 | 602 | printf("%s\n",this->stringYES.c_str()); |
603 | + printf("%s%d\n",this->messageCisMaxIterations.c_str(),Parameters::GetInstance()->GetMaxIterationsCIS()); | |
604 | + printf("%s%d\n",this->messageCisMaxDimensions.c_str(),Parameters::GetInstance()->GetMaxDimensionsCIS()); | |
605 | + printf("%s%e\n",this->messageCisNormTolerance.c_str(),Parameters::GetInstance()->GetNormToleranceCIS()); | |
571 | 606 | } |
572 | 607 | else{ |
573 | 608 | printf("%s\n",this->stringNO.c_str()); |
@@ -59,6 +59,12 @@ public: | ||
59 | 59 | void SetNumberExcitedStatesCIS(int nStates); |
60 | 60 | bool GetIsDavidsonCIS(); |
61 | 61 | void SetIsDavidsonCIS(bool isDavidsonCIS); |
62 | + int GetMaxIterationsCIS(); | |
63 | + void SetMaxIterationsCIS(int maxIterationsCIS); | |
64 | + int GetMaxDimensionsCIS(); | |
65 | + void SetMaxDimensionsCIS(int maxDimensionsCIS); | |
66 | + double GetNormToleranceCIS(); | |
67 | + void SetNormToleranceCIS(double normToleranceCIS); | |
62 | 68 | private: |
63 | 69 | static Parameters* parameters; |
64 | 70 | Parameters(); |
@@ -91,6 +97,9 @@ private: | ||
91 | 97 | int activeOccCIS; |
92 | 98 | int activeVirCIS; |
93 | 99 | int numberExcitedStatesCIS; |
100 | + int maxIterationsCIS; | |
101 | + int maxDimensionsCIS; | |
102 | + double normToleranceCIS; | |
94 | 103 | bool isDavidsonCIS; |
95 | 104 | }; |
96 | 105 | Parameters* Parameters::parameters = NULL; |
@@ -155,6 +164,9 @@ void Parameters::SetDefaultValues(){ | ||
155 | 164 | this->activeVirCIS = 10; |
156 | 165 | this->numberExcitedStatesCIS = 5; |
157 | 166 | this->isDavidsonCIS = true; |
167 | + this->maxIterationsCIS = 100; | |
168 | + this->maxDimensionsCIS = 100; | |
169 | + this->normToleranceCIS = pow(10.0, -6.0); | |
158 | 170 | } |
159 | 171 | |
160 | 172 | double Parameters::GetThresholdSCF(){ |
@@ -354,6 +366,30 @@ void Parameters::SetIsDavidsonCIS(bool isDavidsonCIS){ | ||
354 | 366 | this->isDavidsonCIS = isDavidsonCIS; |
355 | 367 | } |
356 | 368 | |
369 | +int Parameters::GetMaxIterationsCIS(){ | |
370 | + return this->maxIterationsCIS; | |
371 | +} | |
372 | + | |
373 | +void Parameters::SetMaxIterationsCIS(int maxIterationsCIS){ | |
374 | + this->maxIterationsCIS = maxIterationsCIS; | |
375 | +} | |
376 | + | |
377 | +int Parameters::GetMaxDimensionsCIS(){ | |
378 | + return this->maxDimensionsCIS; | |
379 | +} | |
380 | + | |
381 | +void Parameters::SetMaxDimensionsCIS(int maxDimensionsCIS){ | |
382 | + this->maxDimensionsCIS = maxDimensionsCIS; | |
383 | +} | |
384 | + | |
385 | +double Parameters::GetNormToleranceCIS(){ | |
386 | + return this->normToleranceCIS; | |
387 | +} | |
388 | + | |
389 | +void Parameters::SetNormToleranceCIS(double normToleranceCIS){ | |
390 | + this->normToleranceCIS = normToleranceCIS; | |
391 | +} | |
392 | + | |
357 | 393 | } |
358 | 394 | #endif |
359 | 395 |
@@ -22,7 +22,10 @@ CIS | ||
22 | 22 | davidson yes |
23 | 23 | active_occ 100 |
24 | 24 | active_vir 100 |
25 | - nstates 10 | |
25 | + nstates 11 | |
26 | + max_iter 200 | |
27 | + max_dim 100 | |
28 | + norm_tol 0.000001 | |
26 | 29 | CIS_END |
27 | 30 | |
28 | 31 |
@@ -80,13 +83,13 @@ CIS_END | ||
80 | 83 | //GEOMETRY_END |
81 | 84 | |
82 | 85 | //metane |
83 | -GEOMETRY | |
84 | - C 0.647389 0.820131 0.000000 | |
85 | - H 1.004043 -0.188679 0.000000 | |
86 | - H 1.004062 1.324529 0.873652 | |
87 | - H 1.004062 1.324529 -0.873652 | |
88 | - H -0.422611 0.820144 0.000000 | |
89 | -GEOMETRY_END | |
86 | +//GEOMETRY | |
87 | +// C 0.647389 0.820131 0.000000 | |
88 | +// H 1.004043 -0.188679 0.000000 | |
89 | +// H 1.004062 1.324529 0.873652 | |
90 | +// H 1.004062 1.324529 -0.873652 | |
91 | +// H -0.422611 0.820144 0.000000 | |
92 | +//GEOMETRY_END | |
90 | 93 | |
91 | 94 | |
92 | 95 | // c2 |
@@ -131,12 +134,12 @@ GEOMETRY_END | ||
131 | 134 | //GEOMETRY_END |
132 | 135 | |
133 | 136 | // acetylene |
134 | -//GEOMETRY | |
135 | -// C 0.24933 0.0 0.0 | |
136 | -// C 1.45053 0.0 0.0 | |
137 | -// H -0.82067 0.0 0.0 | |
138 | -// H 2.52053 0.0 0.0 | |
139 | -//GEOMETRY_END | |
137 | +GEOMETRY | |
138 | + C 0.24933 0.0 0.0 | |
139 | + C 1.45053 0.0 0.0 | |
140 | + H -0.82067 0.0 0.0 | |
141 | + H 2.52053 0.0 0.0 | |
142 | +GEOMETRY_END | |
140 | 143 | |
141 | 144 | // acetylene2 |
142 | 145 | //GEOMETRY |
@@ -37,7 +37,7 @@ LapackWrapper* LapackWrapper::lapackWrapper = NULL; | ||
37 | 37 | LapackWrapper::LapackWrapper(){ |
38 | 38 | this->calculatedDsysvBlockSize = false; |
39 | 39 | this->dsysvBlockSize = 64; |
40 | - this->errorMessageDsyevdInfo = "Error in mkl_wrapper::LapackWrapper::Dsyevd: info != 0\n"; | |
40 | + this->errorMessageDsyevdInfo = "Error in mkl_wrapper::LapackWrapper::Dsyevd: info != 0: info = "; | |
41 | 41 | this->errorMessageDsyevdSize = "Error in mkl_wrapper::LapackWrapper::Dsyevd: size of matirx < 1\n"; |
42 | 42 | this->errorMessageDsysvInfo = "Error in mkl_wrapper::LapackWrapper::Dsysv: info != 0\n"; |
43 | 43 | this->errorMessageDsysvSize = "Error in mkl_wrapper::LapackWrapper::Dsysv: size of matirx < 1\n"; |
@@ -160,6 +160,7 @@ int LapackWrapper::Dsyevd(double** matrix, double* eigenValues, int size, bool c | ||
160 | 160 | if(info != 0){ |
161 | 161 | stringstream ss; |
162 | 162 | ss << errorMessageDsyevdInfo; |
163 | + ss << info << endl; | |
163 | 164 | throw MolDSException(ss.str()); |
164 | 165 | } |
165 | 166 | return info; |
@@ -48,12 +48,46 @@ private: | ||
48 | 48 | Atom* atom); // Apendix in [BZ_1979] |
49 | 49 | double GetNishimotoMatagaTwoEleInt(Atom* atomA, OrbitalType orbitalA, |
50 | 50 | Atom* atomB, OrbitalType orbitalB); // ref. [MN_1957] and (5a) in [AEZ_1986] |
51 | + struct MoEnergy{ | |
52 | + double energy; | |
53 | + int occIndex; | |
54 | + int virIndex; | |
55 | + int slaterIndex; | |
56 | + }; | |
57 | + struct LessMoEnergy { bool operator()(const MoEnergy& rLeft, const MoEnergy& rRight) | |
58 | + const { return rLeft.energy < rRight.energy; } }; | |
51 | 59 | void DoesCISDirect(); |
52 | 60 | void DoesCISDavidson(); |
61 | + void CalcRitzVector(double* ritzVector, double** expansionVectors, double** interactionMatrix, | |
62 | + int interactionMatrixDimension, int ritzVectorIndex); | |
63 | + void CalcResidualVectorAndNorm(double* residualVector, double* norm, double* ritzVector, | |
64 | + double* interactionEigenEnergies, int residualVectorIndex); | |
65 | + void SortSingleExcitationSlaterDeterminants(vector<MoEnergy>* moEnergies); | |
66 | + void UpdateExpansionVectors(double** expansionVectors, double* interactionEigenEnergies, double* residualVector, | |
67 | + int interactionMatrixDimension, int* notConvergedStates, int residualVectorIndex); | |
68 | + void CalcInteractionMatrix(double** interactionMatrix, double** expansionVectors, int interactionMatrixDimension); | |
69 | + void FreeDavidsonCISTemporaryMtrices(double*** expansionVectors, double** residualVector, double** ritzVector); | |
70 | + void FreeDavidsonRoopCISTemporaryMtrices(double*** interactionMatrix, | |
71 | + double interactionMatrixDimension, | |
72 | + double** interactionEigenEnergies); | |
53 | 73 | void CalcCISMatrix(double** matrixCIS, int numberOcc, int numberVir); |
54 | 74 | string errorMessageNishimotoMataga; |
75 | + string errorMessageDavidsonNotConverged; | |
76 | + string errorMessageDavidsonMaxIter; | |
77 | + string errorMessageDavidsonMaxDim; | |
55 | 78 | string messageStartCIS; |
56 | 79 | string messageDoneCIS; |
80 | + string messageStartDirectCIS; | |
81 | + string messageDoneDirectCIS; | |
82 | + string messageStartDavidsonCIS; | |
83 | + string messageDoneDavidsonCIS; | |
84 | + string messageNumIterCIS; | |
85 | + string messageResidualNorm; | |
86 | + string messageDavidsonConverge; | |
87 | + string messageDavidsonReachCISMatrix; | |
88 | + string messageDavidsonGoToDirect; | |
89 | + string messageExcitedStatesEnergies; | |
90 | + string messageExcitedStatesEnergiesTitle; | |
57 | 91 | }; |
58 | 92 | |
59 | 93 | ZindoS::ZindoS() : MolDS_cndo::Cndo2(){ |
@@ -92,11 +126,25 @@ void ZindoS::SetMessages(){ | ||
92 | 126 | this->errorMessageNishimotoMataga = "Error in base_zindo::ZindoS::GetNishimotoMatagaTwoEleInt: Invalid orbitalType.\n"; |
93 | 127 | this->errorMessageMolecularIntegralElement |
94 | 128 | = "Error in zindo::ZindoS::GetMolecularIntegralElement: Non available orbital is contained.\n"; |
129 | + this->errorMessageDavidsonNotConverged = "Error in zindo::ZindoS::DoesCISDavidson: Davidson did not met convergence criterion. \n"; | |
130 | + this->errorMessageDavidsonMaxIter = "Davidson roop reaches max_iter="; | |
131 | + this->errorMessageDavidsonMaxDim = "Dimension of the expansion vectors reaches max_dim="; | |
95 | 132 | this->messageSCFMetConvergence = "\n\n\n\t\tZINDO/S-SCF met convergence criterion(^^b\n\n\n"; |
96 | 133 | this->messageStartSCF = "********** START: ZINDO/S-SCF **********\n"; |
97 | 134 | this->messageDoneSCF = "********** DONE: ZINDO/S-SCF **********\n\n\n"; |
98 | 135 | this->messageStartCIS = "********** START: ZINDO/S-CIS **********\n"; |
99 | 136 | this->messageDoneCIS = "********** DONE: ZINDO/S-CIS **********\n\n\n"; |
137 | + this->messageStartDirectCIS = "\t====== START: Direct-CIS =====\n\n"; | |
138 | + this->messageDoneDirectCIS = "\t====== DONE: Direct-CIS =====\n\n\n"; | |
139 | + this->messageStartDavidsonCIS = "\t====== START: Davidson-CIS =====\n"; | |
140 | + this->messageDoneDavidsonCIS = "\t====== DONE: Davidson-CIS =====\n\n\n"; | |
141 | + this->messageNumIterCIS = "\tDavidson iter="; | |
142 | + this->messageResidualNorm = "-th excited: norm of the residual = "; | |
143 | + this->messageDavidsonConverge = "\n\n\t\tDavidson for ZINDO/S-CIS met convergence criterion(^^b\n\n\n"; | |
144 | + this->messageDavidsonReachCISMatrix = "\n\t\tDimension of the expansion vectors reaches to the dimension of the CIS-matrix.\n"; | |
145 | + this->messageDavidsonGoToDirect = "\t\tHence, we go to the Direct-CIS.\n\n"; | |
146 | + this->messageExcitedStatesEnergies = "\tExcitation energies:\n"; | |
147 | + this->messageExcitedStatesEnergiesTitle = "\t\t| i-th | e[a.u.] | e[eV] | \n"; | |
100 | 148 | } |
101 | 149 | |
102 | 150 | void ZindoS::SetEnableAtomTypes(){ |
@@ -621,6 +669,33 @@ double ZindoS::GetMolecularIntegralElement(int moI, int moJ, int moK, int moL, | ||
621 | 669 | void ZindoS::DoesCIS(){ |
622 | 670 | cout << this->messageStartCIS; |
623 | 671 | |
672 | + int numberOcc = Parameters::GetInstance()->GetActiveOccCIS(); | |
673 | + int numberVir = Parameters::GetInstance()->GetActiveVirCIS(); | |
674 | + | |
675 | + // malloc or initialize CIS matrix | |
676 | + if(this->matrixCIS == NULL){ | |
677 | + this->matrixCISdimension = numberOcc*numberVir; | |
678 | + this->matrixCIS = MallocerFreer::GetInstance()->MallocDoubleMatrix2d(this->matrixCISdimension, | |
679 | + this->matrixCISdimension); | |
680 | + } | |
681 | + else{ | |
682 | + MallocerFreer::GetInstance()->InitializeDoubleMatrix2d(this->matrixCIS, | |
683 | + this->matrixCISdimension, | |
684 | + this->matrixCISdimension); | |
685 | + } | |
686 | + | |
687 | + // malloc or initialize CIS eigen vector | |
688 | + if(this->excitedEnergies == NULL){ | |
689 | + this->excitedEnergies = MallocerFreer::GetInstance()->MallocDoubleMatrix1d(this->matrixCISdimension); | |
690 | + } | |
691 | + else{ | |
692 | + MallocerFreer::GetInstance()->InitializeDoubleMatrix1d(this->excitedEnergies, this->matrixCISdimension); | |
693 | + } | |
694 | + | |
695 | + // calculate CIS matrix | |
696 | + this->CalcCISMatrix(matrixCIS, numberOcc, numberVir); | |
697 | + | |
698 | + // calculate excited energies | |
624 | 699 | if(Parameters::GetInstance()->GetIsDavidsonCIS()){ |
625 | 700 | this->DoesCISDavidson(); |
626 | 701 | } |
@@ -629,55 +704,325 @@ void ZindoS::DoesCIS(){ | ||
629 | 704 | } |
630 | 705 | |
631 | 706 | // output eigen energies |
707 | + cout << this->messageExcitedStatesEnergies; | |
708 | + cout << this->messageExcitedStatesEnergiesTitle; | |
709 | + double eV2AU = Parameters::GetInstance()->GetEV2AU(); | |
632 | 710 | for(int k=0; k<Parameters::GetInstance()->GetNumberExcitedStatesCIS(); k++){ |
633 | - printf("%d-th excited energy: %e\n",k+1, this->excitedEnergies[k]); | |
711 | + printf("\t\t %d\t%e\t%e\n",k+1, this->excitedEnergies[k], this->excitedEnergies[k]/eV2AU); | |
634 | 712 | } |
635 | 713 | cout << endl; |
636 | 714 | cout << this->messageDoneCIS; |
637 | 715 | } |
638 | 716 | |
639 | -void ZindoS::DoesCISDavidson(){ | |
640 | - // ToDo: CIS-Davidson | |
641 | - stringstream ss; | |
642 | - ss << "CIS-Davidson (ZindoS::DoesCISDavidson()) is not implemented yet.\n\n"; | |
643 | - throw MolDSException(ss.str()); | |
717 | +void ZindoS::SortSingleExcitationSlaterDeterminants(vector<MoEnergy>* moEnergies){ | |
718 | + | |
719 | + int numberOcc = Parameters::GetInstance()->GetActiveOccCIS(); | |
720 | + int numberVir = Parameters::GetInstance()->GetActiveVirCIS(); | |
721 | + for(int k=0; k<numberOcc*numberVir; k++){ | |
722 | + // single excitation from I-th (occupied)MO to A-th (virtual)MO | |
723 | + int moI = this->molecule->GetTotalNumberValenceElectrons()/2 - (k/numberVir) -1; | |
724 | + int moA = this->molecule->GetTotalNumberValenceElectrons()/2 + (k%numberVir); | |
725 | + | |
726 | + MoEnergy moEnergy = {this->energiesMO[moA] - this->energiesMO[moI], moI, moA, k}; | |
727 | + moEnergies->push_back(moEnergy); | |
728 | + } | |
729 | + sort(moEnergies->begin(), moEnergies->end(), LessMoEnergy()); | |
644 | 730 | } |
645 | 731 | |
646 | -void ZindoS::DoesCISDirect(){ | |
732 | +// This method is used for Davidson | |
733 | +void ZindoS::CalcRitzVector(double* ritzVector, double** expansionVectors, double** interactionMatrix, | |
734 | + int interactionMatrixDimension, int ritzVectorIndex){ | |
735 | + | |
736 | + for(int j=0; j<this->matrixCISdimension; j++){ | |
737 | + ritzVector[j] = 0.0; | |
738 | + for(int k=0; k<interactionMatrixDimension; k++){ | |
739 | + ritzVector[j] += expansionVectors[j][k]*interactionMatrix[ritzVectorIndex][k]; | |
740 | + } | |
741 | + } | |
742 | +} | |
743 | + | |
744 | +// This method is used for Davidson | |
745 | +void ZindoS::CalcResidualVectorAndNorm(double* residualVector, double* norm, double* ritzVector, | |
746 | + double* interactionEigenEnergies, int residualVectorIndex){ | |
747 | + | |
748 | + double sqNorm = 0.0; | |
749 | + for(int j=0; j<this->matrixCISdimension; j++){ | |
750 | + residualVector[j] = interactionEigenEnergies[residualVectorIndex] * ritzVector[j]; | |
751 | + for(int k=0; k<this->matrixCISdimension; k++){ | |
752 | + double value = j<=k ? this->matrixCIS[j][k] : this->matrixCIS[k][j]; | |
753 | + residualVector[j] -= value*ritzVector[k]; | |
754 | + } | |
755 | + sqNorm += pow(residualVector[j],2.0); | |
756 | + } | |
757 | + *norm = sqrt(sqNorm); | |
758 | +} | |
759 | + | |
760 | +// This method is used for Davidson | |
761 | +void ZindoS::UpdateExpansionVectors(double** expansionVectors, double* interactionEigenEnergies, double* residualVector, | |
762 | + int interactionMatrixDimension, int* notConvergedStates, int residualVectorIndex){ | |
763 | + | |
764 | + double newExpansionVector[this->matrixCISdimension]; | |
765 | + | |
766 | + // calculate new expansion vector from residual vector | |
767 | + for(int j=0; j<this->matrixCISdimension; j++){ | |
768 | + double temp = interactionEigenEnergies[residualVectorIndex]-this->matrixCIS[j][j]; | |
769 | + if(temp == 0.0){ | |
770 | + // prevent dividing by 0. | |
771 | + temp = pow(10,-100); | |
772 | + } | |
773 | + newExpansionVector[j]=pow(temp, -1.0)*residualVector[j]; | |
774 | + } | |
775 | + | |
776 | + // orthonormalize old expansion vectors and new expansion vector | |
777 | + for(int k=0; k<interactionMatrixDimension+*notConvergedStates; k++){ | |
778 | + double overlap=0.0; | |
779 | + for(int j=0; j<this->matrixCISdimension; j++){ | |
780 | + overlap += expansionVectors[j][k] * newExpansionVector[j]; | |
781 | + } | |
782 | + for(int j=0; j<this->matrixCISdimension; j++){ | |
783 | + newExpansionVector[j] -= overlap*expansionVectors[j][k]; | |
784 | + } | |
785 | + } | |
786 | + | |
787 | + // add new expansion vector to old expansion vectors | |
788 | + double sqNormNewExpVect = 0.0; | |
789 | + for(int j=0; j<this->matrixCISdimension; j++){ | |
790 | + sqNormNewExpVect += pow(newExpansionVector[j],2.0); | |
791 | + } | |
792 | + double normNewExpVect = sqrt(sqNormNewExpVect); | |
793 | + for(int j=0; j<this->matrixCISdimension; j++){ | |
794 | + expansionVectors[j][interactionMatrixDimension+*notConvergedStates] | |
795 | + = pow(normNewExpVect,-1.0)*newExpansionVector[j]; | |
796 | + } | |
797 | + *notConvergedStates += 1; | |
798 | +} | |
799 | + | |
800 | +// This method is used for Davidson | |
801 | +void ZindoS::CalcInteractionMatrix(double** interactionMatrix, double** expansionVectors, int interactionMatrixDimension){ | |
802 | + | |
803 | + for(int i=0; i<interactionMatrixDimension; i++){ | |
804 | + for(int j=i; j<interactionMatrixDimension; j++){ | |
805 | + for(int a=0; a<this->matrixCISdimension; a++){ | |
806 | + for(int b=0; b<this->matrixCISdimension; b++){ | |
807 | + double value = a<=b ? this->matrixCIS[a][b] : this->matrixCIS[b][a]; | |
808 | + interactionMatrix[i][j] += expansionVectors[a][i] | |
809 | + *value | |
810 | + *expansionVectors[b][j]; | |
811 | + } | |
812 | + } | |
813 | + } | |
814 | + } | |
815 | +} | |
816 | + | |
817 | +void ZindoS::DoesCISDavidson(){ | |
818 | + cout << this->messageStartDavidsonCIS; | |
647 | 819 | |
648 | 820 | int numberOcc = Parameters::GetInstance()->GetActiveOccCIS(); |
649 | 821 | int numberVir = Parameters::GetInstance()->GetActiveVirCIS(); |
650 | 822 | int numberExcitedStates = Parameters::GetInstance()->GetNumberExcitedStatesCIS(); |
823 | + int maxIter = Parameters::GetInstance()->GetMaxIterationsCIS(); | |
824 | + int maxDim = Parameters::GetInstance()->GetMaxDimensionsCIS(); | |
825 | + double normTol = Parameters::GetInstance()->GetNormToleranceCIS(); | |
826 | + bool convergeExcitedStates[numberExcitedStates]; | |
827 | + int interactionMatrixDimension; | |
828 | + bool reachMaxDim; | |
829 | + bool allConverged; | |
830 | + int notConvergedStates; | |
831 | + bool goToDirectCIS; | |
832 | + double** expansionVectors = NULL; | |
833 | + double* ritzVector = NULL; | |
834 | + double* residualVector = NULL; | |
835 | + | |
836 | + // malloc | |
837 | + expansionVectors = MallocerFreer::GetInstance()->MallocDoubleMatrix2d(this->matrixCISdimension, maxDim); | |
838 | + ritzVector = MallocerFreer::GetInstance()->MallocDoubleMatrix1d(this->matrixCISdimension); | |
839 | + residualVector = MallocerFreer::GetInstance()->MallocDoubleMatrix1d(this->matrixCISdimension); | |
840 | + | |
841 | + try{ | |
842 | + // sort single excitation slater determinants | |
843 | + vector<MoEnergy> moEnergies; | |
844 | + this->SortSingleExcitationSlaterDeterminants(&moEnergies); | |
845 | + | |
846 | + // set initial expansion vectors and initial conveged vectors | |
847 | + for(int k=0; k<numberExcitedStates; k++){ | |
848 | + expansionVectors[moEnergies[k].slaterIndex][k] = 1.0; | |
849 | + convergeExcitedStates[k] = false; | |
850 | + } | |
651 | 851 | |
652 | - // malloc CIS matrix | |
653 | - if(this->matrixCIS == NULL){ | |
654 | - this->matrixCISdimension = numberExcitedStates; | |
655 | - this->matrixCIS = MallocerFreer::GetInstance()->MallocDoubleMatrix2d(this->matrixCISdimension, | |
656 | - this->matrixCISdimension); | |
852 | + interactionMatrixDimension = 0; | |
853 | + reachMaxDim = false; | |
854 | + goToDirectCIS = false; | |
855 | + // Davidson roop | |
856 | + for(int k=0; k<maxIter; k++){ | |
857 | + cout << messageNumIterCIS << k << endl; | |
858 | + | |
859 | + // calculate dimension of the interaction matrix (= number of the expansion vectors). | |
860 | + for(int i=0; i<numberExcitedStates; i++){ | |
861 | + if(!convergeExcitedStates[i]){ | |
862 | + interactionMatrixDimension += 1; | |
863 | + } | |
864 | + } | |
865 | + | |
866 | + // malloc interaction matrix and etc. | |
867 | + double** interactionMatrix = NULL; | |
868 | + double* interactionEigenEnergies = NULL; | |
869 | + interactionMatrix = MallocerFreer::GetInstance()->MallocDoubleMatrix2d | |
870 | + (interactionMatrixDimension, interactionMatrixDimension); | |
871 | + interactionEigenEnergies = MallocerFreer::GetInstance()->MallocDoubleMatrix1d(interactionMatrixDimension); | |
872 | + | |
873 | + try{ | |
874 | + | |
875 | + // calculate interaction matrix | |
876 | + this->CalcInteractionMatrix(interactionMatrix, expansionVectors, interactionMatrixDimension); | |
877 | + | |
878 | + // diagonalize interaction matrix | |
879 | + bool calcEigenVectors = true; | |
880 | + MolDS_mkl_wrapper::LapackWrapper::GetInstance()->Dsyevd(interactionMatrix, | |
881 | + interactionEigenEnergies, | |
882 | + interactionMatrixDimension, | |
883 | + calcEigenVectors); | |
884 | + | |
885 | + // check convergence of all excited states | |
886 | + notConvergedStates=0; | |
887 | + allConverged = true; | |
888 | + for(int i=0; i<numberExcitedStates; i++){ | |
889 | + | |
890 | + // calculate i-th ritz vector | |
891 | + this->CalcRitzVector(ritzVector, expansionVectors, interactionMatrix, interactionMatrixDimension, i); | |
892 | + | |
893 | + // calculate i-th residual vector and the norm of the residual vector | |
894 | + double norm = 0.0; | |
895 | + this->CalcResidualVectorAndNorm(residualVector, &norm, ritzVector, interactionEigenEnergies, i); | |
896 | + | |
897 | + // output norm of residual vector | |
898 | + cout << "\t " << i+1 << this->messageResidualNorm << norm << endl; | |
899 | + if(i == numberExcitedStates-1){ | |
900 | + cout << endl; | |
901 | + } | |
902 | + | |
903 | + // check tolerance for the norm of the residual vector. | |
904 | + if(norm < normTol){ | |
905 | + convergeExcitedStates[i] = true; | |
906 | + } | |
907 | + else{ | |
908 | + convergeExcitedStates[i] = false; | |
909 | + allConverged = false; | |
910 | + if(interactionMatrixDimension+notConvergedStates == maxDim && maxDim !=this->matrixCISdimension){ | |
911 | + reachMaxDim = true; | |
912 | + break; | |
913 | + } | |
914 | + else if(interactionMatrixDimension+notConvergedStates == this->matrixCISdimension){ | |
915 | + goToDirectCIS = true; | |
916 | + break; | |
917 | + } | |
918 | + | |
919 | + // update expansion vectors | |
920 | + this->UpdateExpansionVectors(expansionVectors, interactionEigenEnergies, residualVector, | |
921 | + interactionMatrixDimension, ¬ConvergedStates, i); | |
922 | + | |
923 | + } | |
924 | + } | |
925 | + | |
926 | + if(allConverged){ | |
927 | + // copy to cis eigen vector and value | |
928 | + for(int i=0; i<numberExcitedStates; i++){ | |
929 | + this->excitedEnergies[i] = interactionEigenEnergies[i]; | |
930 | + this->CalcRitzVector(ritzVector, expansionVectors, interactionMatrix, interactionMatrixDimension, i); | |
931 | + for(int j=0; j<this->matrixCISdimension; j++){ | |
932 | + this->matrixCIS[i][j] = ritzVector[j]; | |
933 | + } | |
934 | + } | |
935 | + } | |
936 | + } | |
937 | + catch(MolDSException ex){ | |
938 | + this->FreeDavidsonRoopCISTemporaryMtrices(&interactionMatrix, | |
939 | + interactionMatrixDimension, | |
940 | + &interactionEigenEnergies); | |
941 | + throw ex; | |
942 | + } | |
943 | + this->FreeDavidsonRoopCISTemporaryMtrices(&interactionMatrix, | |
944 | + interactionMatrixDimension, | |
945 | + &interactionEigenEnergies); | |
946 | + | |
947 | + // stop the Davidson roop | |
948 | + if(allConverged){ | |
949 | + cout << this->messageDavidsonConverge; | |
950 | + break; | |
951 | + } | |
952 | + else if(!allConverged && goToDirectCIS){ | |
953 | + cout << this->messageDavidsonReachCISMatrix; | |
954 | + cout << this->messageDavidsonGoToDirect; | |
955 | + break; | |
956 | + } | |
957 | + else if(!allConverged && reachMaxDim){ | |
958 | + stringstream ss; | |
959 | + ss << endl; | |
960 | + ss << this->errorMessageDavidsonNotConverged; | |
961 | + ss << this->errorMessageDavidsonMaxDim << maxDim << endl; | |
962 | + throw MolDSException(ss.str()); | |
963 | + } | |
964 | + else if(!allConverged && k==maxIter-1){ | |
965 | + stringstream ss; | |
966 | + ss << this->errorMessageDavidsonNotConverged; | |
967 | + ss << this->errorMessageDavidsonMaxIter << maxIter << endl; | |
968 | + throw MolDSException(ss.str()); | |
969 | + } | |
970 | + | |
971 | + }// end Davidson roop | |
657 | 972 | } |
658 | - else{ | |
659 | - MallocerFreer::GetInstance()->InitializeDoubleMatrix2d(this->matrixCIS, | |
660 | - this->matrixCISdimension, | |
661 | - this->matrixCISdimension); | |
973 | + catch(MolDSException ex){ | |
974 | + this->FreeDavidsonCISTemporaryMtrices(&expansionVectors, &residualVector, &ritzVector); | |
975 | + throw ex; | |
662 | 976 | } |
977 | + this->FreeDavidsonCISTemporaryMtrices(&expansionVectors, &residualVector, &ritzVector); | |
663 | 978 | |
664 | - // malloc CIS eigen vector | |
665 | - if(this->excitedEnergies == NULL){ | |
666 | - this->excitedEnergies = MallocerFreer::GetInstance()->MallocDoubleMatrix1d(this->matrixCISdimension); | |
979 | + cout << this->messageDoneDavidsonCIS; | |
980 | + // change algorithm from Davidso to direct | |
981 | + if(goToDirectCIS){ | |
982 | + this->DoesCISDirect(); | |
667 | 983 | } |
668 | - else{ | |
669 | - MallocerFreer::GetInstance()->InitializeDoubleMatrix1d(this->excitedEnergies, this->matrixCISdimension); | |
984 | + | |
985 | +} | |
986 | + | |
987 | +void ZindoS::FreeDavidsonCISTemporaryMtrices(double*** expansionVectors, double** residualVector, double** ritzVector){ | |
988 | + | |
989 | + if(*expansionVectors != NULL){ | |
990 | + MallocerFreer::GetInstance()->FreeDoubleMatrix2d(expansionVectors, this->matrixCISdimension); | |
991 | + //cout << "expansion vectors deleted\n"; | |
992 | + } | |
993 | + if(*residualVector != NULL){ | |
994 | + MallocerFreer::GetInstance()->FreeDoubleMatrix1d(residualVector); | |
995 | + //cout << "residual vector deleted\n"; | |
996 | + } | |
997 | + if(*ritzVector != NULL){ | |
998 | + MallocerFreer::GetInstance()->FreeDoubleMatrix1d(ritzVector); | |
999 | + //cout << "ritz vector deleted\n"; | |
670 | 1000 | } |
671 | 1001 | |
672 | - // calc CIS matrix | |
673 | - this->CalcCISMatrix(matrixCIS, numberOcc, numberVir); | |
1002 | +} | |
674 | 1003 | |
1004 | +void ZindoS::FreeDavidsonRoopCISTemporaryMtrices(double*** interactionMatrix, | |
1005 | + double interactionMatrixDimension, | |
1006 | + double** interactionEigenEnergies){ | |
1007 | + if(*interactionMatrix != NULL){ | |
1008 | + MallocerFreer::GetInstance()->FreeDoubleMatrix2d(interactionMatrix, interactionMatrixDimension); | |
1009 | + //cout << "interactionMatrix deleted\n"; | |
1010 | + } | |
1011 | + if(*interactionEigenEnergies != NULL){ | |
1012 | + MallocerFreer::GetInstance()->FreeDoubleMatrix1d(interactionEigenEnergies); | |
1013 | + //cout << "interactionEigenEnergies deleted\n"; | |
1014 | + } | |
1015 | + | |
1016 | +} | |
1017 | +void ZindoS::DoesCISDirect(){ | |
1018 | + | |
1019 | + cout << this->messageStartDirectCIS; | |
675 | 1020 | bool calcEigenVectors = true; |
676 | 1021 | MolDS_mkl_wrapper::LapackWrapper::GetInstance()->Dsyevd(this->matrixCIS, |
677 | 1022 | this->excitedEnergies, |
678 | 1023 | this->matrixCISdimension, |
679 | 1024 | calcEigenVectors); |
680 | - | |
1025 | + cout << this->messageDoneDirectCIS; | |
681 | 1026 | } |
682 | 1027 | |
683 | 1028 | void ZindoS::CalcCISMatrix(double** matrixCIS, int numberOcc, int numberVir){ |