Revision | d5b846f87409da25db9520322b2640389622bb03 (tree) |
---|---|
Time | 2014-01-11 03:44:51 |
Author | ktns <ktns@1136...> |
Commiter | ktns |
Refactor BFGS::SearchMinimum using BFGSState. #32881
git-svn-id: https://svn.sourceforge.jp/svnroot/molds/branches/refactor_opt@1638 1136aad2-a195-0410-b898-f5ea1d11b9d8
@@ -52,11 +52,35 @@ using namespace MolDS_base; | ||
52 | 52 | using namespace MolDS_base_atoms; |
53 | 53 | |
54 | 54 | namespace MolDS_optimization{ |
55 | + | |
56 | +BFGS::BFGSState::BFGSState(Molecule& molecule): | |
57 | + matrixHessian(NULL), | |
58 | + matrixOldForce(NULL), | |
59 | + matrixStep(NULL), | |
60 | + matrixOldCoordinates(NULL), | |
61 | + matrixDisplacement(NULL), | |
62 | + numAtoms(molecule.GetAtomVect().size()) | |
63 | +{ | |
64 | + const int dimension = numAtoms * CartesianType_end; | |
65 | + MallocerFreer::GetInstance()->Malloc(&this->matrixHessian, dimension, dimension); | |
66 | + MallocerFreer::GetInstance()->Malloc(&this->matrixOldForce, this->numAtoms, CartesianType_end); | |
67 | + MallocerFreer::GetInstance()->Malloc(&this->matrixStep, this->numAtoms, CartesianType_end); | |
68 | + MallocerFreer::GetInstance()->Malloc(&this->matrixOldCoordinates, this->numAtoms, CartesianType_end); | |
69 | + MallocerFreer::GetInstance()->Malloc(&this->matrixDisplacement, this->numAtoms, CartesianType_end); | |
70 | +} | |
71 | +BFGS::BFGSState::~BFGSState(){ | |
72 | + const int dimension = numAtoms * CartesianType_end; | |
73 | + MallocerFreer::GetInstance()->Free(&this->matrixHessian, dimension, dimension); | |
74 | + MallocerFreer::GetInstance()->Free(&this->matrixOldForce, this->numAtoms, CartesianType_end); | |
75 | + MallocerFreer::GetInstance()->Free(&this->matrixStep, this->numAtoms, CartesianType_end); | |
76 | + MallocerFreer::GetInstance()->Free(&this->matrixOldCoordinates, this->numAtoms, CartesianType_end); | |
77 | + MallocerFreer::GetInstance()->Free(&this->matrixDisplacement, this->numAtoms, CartesianType_end); | |
78 | +} | |
79 | + | |
55 | 80 | BFGS::BFGS(){ |
56 | 81 | this->SetMessages(); |
57 | 82 | //this->OutputLog("BFGS created\n"); |
58 | 83 | } |
59 | - | |
60 | 84 | BFGS::~BFGS(){ |
61 | 85 | //this->OutputLog("BFGS deleted\n"); |
62 | 86 | } |
@@ -110,129 +134,98 @@ void BFGS::SearchMinimum(boost::shared_ptr<ElectronicStructure> electronicStruct | ||
110 | 134 | int totalSteps = Parameters::GetInstance()->GetTotalStepsOptimization(); |
111 | 135 | double maxGradientThreshold = Parameters::GetInstance()->GetMaxGradientOptimization(); |
112 | 136 | double rmsGradientThreshold = Parameters::GetInstance()->GetRmsGradientOptimization(); |
113 | - double lineSearchCurrentEnergy = 0.0; | |
114 | - double lineSearchInitialEnergy = 0.0; | |
115 | - double const* const* matrixForce = NULL; | |
116 | - double const* vectorForce = NULL; | |
117 | 137 | const int dimension = molecule.GetAtomVect().size()*CartesianType_end; |
118 | - double** matrixHessian = NULL; | |
119 | - double* vectorOldForce = NULL; | |
120 | - double* vectorStep = NULL; | |
121 | - double** matrixStep = NULL; | |
122 | - double** matrixOldCoordinates = NULL; | |
123 | - double* vectorOldCoordinates = NULL; | |
124 | - double** matrixDisplacement = NULL; | |
125 | 138 | double trustRadius = Parameters::GetInstance()->GetInitialTrustRadiusOptimization(); |
126 | 139 | const double maxNormStep = Parameters::GetInstance()->GetMaxNormStepOptimization(); |
140 | + BFGSState state(molecule); | |
127 | 141 | |
128 | - try{ | |
129 | - // initialize Hessian with unit matrix | |
130 | - MallocerFreer::GetInstance()->Malloc(&matrixHessian, dimension, dimension); | |
131 | - const double one = 1; | |
132 | - MolDS_wrappers::Blas::GetInstance()->Dcopy(dimension, &one, 0, &matrixHessian[0][0], dimension+1); | |
133 | - | |
134 | - // initial calculation | |
135 | - bool requireGuess = true; | |
136 | - this->UpdateElectronicStructure(electronicStructure, molecule, requireGuess, this->CanOutputLogs()); | |
137 | - lineSearchCurrentEnergy = electronicStructure->GetElectronicEnergy(elecState); | |
138 | - | |
139 | - requireGuess = false; | |
140 | - matrixForce = electronicStructure->GetForce(elecState); | |
141 | - vectorForce = &matrixForce[0][0]; | |
142 | - | |
143 | - for(int s=0; s<totalSteps; s++){ | |
144 | - this->OutputLog(boost::format("%s%d\n\n") % this->messageStartBFGSStep % (s+1)); | |
145 | - | |
146 | - // Store old Force data | |
147 | - MallocerFreer::GetInstance()->Malloc(&vectorOldForce, dimension); | |
148 | - MolDS_wrappers::Blas::GetInstance()->Dcopy(dimension, | |
149 | - static_cast<double const*>(vectorForce), | |
150 | - vectorOldForce); | |
151 | - | |
152 | - this->StoreMolecularGeometry(matrixOldCoordinates, molecule); | |
153 | - | |
154 | - // Level shift Hessian redundant modes | |
155 | - this->ShiftHessianRedundantMode(matrixHessian, molecule); | |
156 | - | |
157 | - // Limit the trustRadius to maxNormStep | |
158 | - trustRadius=min(trustRadius,maxNormStep); | |
159 | - | |
160 | - //Calculate RFO step | |
161 | - MallocerFreer::GetInstance()->Malloc(&matrixStep, molecule.GetAtomVect().size(), CartesianType_end); | |
162 | - vectorStep = &matrixStep[0][0]; | |
163 | - this->CalcRFOStep(vectorStep, matrixHessian, vectorForce, trustRadius, dimension); | |
164 | - | |
165 | - double approximateChange = this->ApproximateEnergyChange(dimension, matrixHessian, vectorForce, vectorStep); | |
166 | - | |
167 | - // Take a RFO step | |
168 | - bool doLineSearch = false; | |
169 | - bool tempCanOutputLogs = false; | |
170 | - lineSearchInitialEnergy = lineSearchCurrentEnergy; | |
171 | - if(doLineSearch){ | |
172 | - this->LineSearch(electronicStructure, molecule, lineSearchCurrentEnergy, matrixStep, elecState, dt); | |
173 | - } | |
174 | - else{ | |
175 | - this->UpdateMolecularCoordinates(molecule, matrixStep); | |
142 | + // initialize Hessian with unit matrix | |
143 | + const double one = 1; | |
144 | + MolDS_wrappers::Blas::GetInstance()->Dcopy(dimension, &one, 0, &state.GetMatrixHessian()[0][0], dimension+1); | |
176 | 145 | |
177 | - // Broadcast to all processes | |
178 | - int root = MolDS_mpi::MpiProcess::GetInstance()->GetHeadRank(); | |
179 | - molecule.BroadcastConfigurationToAllProcesses(root); | |
146 | + // initial calculation | |
147 | + bool requireGuess = true; | |
148 | + this->UpdateElectronicStructure(electronicStructure, molecule, requireGuess, this->CanOutputLogs()); | |
149 | + state.SetCurrentEnergy(electronicStructure->GetElectronicEnergy(elecState)); | |
180 | 150 | |
181 | - this->UpdateElectronicStructure(electronicStructure, molecule, requireGuess, tempCanOutputLogs); | |
182 | - lineSearchCurrentEnergy = electronicStructure->GetElectronicEnergy(elecState); | |
183 | - } | |
184 | - this->OutputMoleculeElectronicStructure(electronicStructure, molecule, this->CanOutputLogs()); | |
185 | - | |
186 | - this->UpdateTrustRadius(trustRadius, approximateChange, lineSearchInitialEnergy, lineSearchCurrentEnergy); | |
187 | - | |
188 | - // check convergence | |
189 | - if(this->SatisfiesConvergenceCriterion(matrixForce, | |
190 | - molecule, | |
191 | - lineSearchInitialEnergy, | |
192 | - lineSearchCurrentEnergy, | |
193 | - maxGradientThreshold, | |
194 | - rmsGradientThreshold)){ | |
195 | - *obtainesOptimizedStructure = true; | |
196 | - break; | |
197 | - } | |
151 | + requireGuess = false; | |
152 | + state.SetMatrixForce(electronicStructure->GetForce(elecState)); | |
198 | 153 | |
199 | - //Calculate displacement (K_k at Eq. (15) in [SJTO_1983]) | |
200 | - this->CalcDisplacement(matrixDisplacement, matrixOldCoordinates, molecule); | |
154 | + for(int s=0; s<totalSteps; s++){ | |
155 | + this->OutputLog(boost::format("%s%d\n\n") % this->messageStartBFGSStep % (s+1)); | |
201 | 156 | |
202 | - //Rollback geometry and energy if energy increases | |
203 | - bool isHillClimbing = lineSearchCurrentEnergy > lineSearchInitialEnergy; | |
204 | - if(isHillClimbing){ | |
205 | - this->OutputLog(this->messageHillClimbing); | |
206 | - this->RollbackMolecularGeometry(molecule, matrixOldCoordinates); | |
207 | - lineSearchCurrentEnergy = lineSearchInitialEnergy; | |
208 | - } | |
157 | + // Store old Force data | |
158 | + MolDS_wrappers::Blas::GetInstance()->Dcopy(dimension, | |
159 | + static_cast<double const*>(state.GetVectorForce()), | |
160 | + state.GetVectorOldForce()); | |
209 | 161 | |
210 | - matrixForce = electronicStructure->GetForce(elecState); | |
211 | - vectorForce = &matrixForce[0][0]; | |
162 | + this->StoreMolecularGeometry(state.GetMatrixOldCoordinatesRef(), molecule); | |
212 | 163 | |
213 | - // Update Hessian | |
214 | - this->UpdateHessian(matrixHessian, dimension, vectorForce, vectorOldForce, &matrixDisplacement[0][0]); | |
164 | + // Level shift Hessian redundant modes | |
165 | + this->ShiftHessianRedundantMode(state.GetMatrixHessian(), molecule); | |
215 | 166 | |
216 | - //Rollback gradient if energy increases | |
217 | - if(isHillClimbing){ | |
218 | - vectorForce = vectorOldForce; | |
219 | - } | |
167 | + // Limit the trustRadius to maxNormStep | |
168 | + trustRadius=min(trustRadius,maxNormStep); | |
169 | + | |
170 | + //Calculate RFO step | |
171 | + this->CalcRFOStep(state.GetVectorStep(), state.GetMatrixHessian(), state.GetVectorForce(), trustRadius, dimension); | |
172 | + | |
173 | + double approximateChange = this->ApproximateEnergyChange(dimension, state.GetMatrixHessian(), state.GetVectorForce(), state.GetVectorStep()); | |
174 | + | |
175 | + // Take a RFO step | |
176 | + bool doLineSearch = false; | |
177 | + bool tempCanOutputLogs = false; | |
178 | + state.SetInitialEnergy(state.GetCurrentEnergy()); | |
179 | + if(doLineSearch){ | |
180 | + this->LineSearch(electronicStructure, molecule, state.GetCurrentEnergyRef(), state.GetMatrixStep(), elecState, dt); | |
181 | + } | |
182 | + else{ | |
183 | + this->UpdateMolecularCoordinates(molecule, state.GetMatrixStep()); | |
184 | + | |
185 | + // Broadcast to all processes | |
186 | + int root = MolDS_mpi::MpiProcess::GetInstance()->GetHeadRank(); | |
187 | + molecule.BroadcastConfigurationToAllProcesses(root); | |
188 | + | |
189 | + this->UpdateElectronicStructure(electronicStructure, molecule, requireGuess, tempCanOutputLogs); | |
190 | + state.SetCurrentEnergy(electronicStructure->GetElectronicEnergy(elecState)); | |
191 | + } | |
192 | + this->OutputMoleculeElectronicStructure(electronicStructure, molecule, this->CanOutputLogs()); | |
193 | + | |
194 | + this->UpdateTrustRadius(trustRadius, approximateChange, state.GetInitialEnergy(), state.GetCurrentEnergy()); | |
195 | + | |
196 | + // check convergence | |
197 | + if(this->SatisfiesConvergenceCriterion(state.GetMatrixForce(), | |
198 | + molecule, | |
199 | + state.GetInitialEnergy(), | |
200 | + state.GetCurrentEnergy(), | |
201 | + maxGradientThreshold, | |
202 | + rmsGradientThreshold)){ | |
203 | + *obtainesOptimizedStructure = true; | |
204 | + break; | |
205 | + } | |
206 | + | |
207 | + //Calculate displacement (K_k at Eq. (15) in [SJTO_1983]) | |
208 | + this->CalcDisplacement(state.GetMatrixDisplacement(), state.GetMatrixOldCoordinates(), molecule); | |
209 | + | |
210 | + //Rollback geometry and energy if energy increases | |
211 | + bool isHillClimbing = state.GetCurrentEnergy() > state.GetInitialEnergy(); | |
212 | + if(isHillClimbing){ | |
213 | + this->OutputLog(this->messageHillClimbing); | |
214 | + this->RollbackMolecularGeometry(molecule, state.GetMatrixOldCoordinates()); | |
215 | + state.SetCurrentEnergy(state.GetInitialEnergy()); | |
216 | + } | |
217 | + | |
218 | + state.SetMatrixForce(electronicStructure->GetForce(elecState)); | |
219 | + | |
220 | + // Update Hessian | |
221 | + this->UpdateHessian(state.GetMatrixHessian(), dimension, state.GetVectorForce(), state.GetVectorOldForce(), &state.GetMatrixDisplacement()[0][0]); | |
222 | + | |
223 | + //Rollback gradient if energy increases | |
224 | + if(isHillClimbing){ | |
225 | + state.SetMatrixForce(state.GetMatrixOldForce()); | |
220 | 226 | } |
221 | - *lineSearchedEnergy = lineSearchCurrentEnergy; | |
222 | - } | |
223 | - catch(MolDSException ex){ | |
224 | - MallocerFreer::GetInstance()->Free(&matrixHessian, dimension, dimension); | |
225 | - MallocerFreer::GetInstance()->Free(&vectorOldForce, dimension); | |
226 | - MallocerFreer::GetInstance()->Free(&matrixStep, molecule.GetAtomVect().size(), CartesianType_end); | |
227 | - MallocerFreer::GetInstance()->Free(&matrixDisplacement, molecule.GetAtomVect().size(), CartesianType_end); | |
228 | - MallocerFreer::GetInstance()->Free(&matrixOldCoordinates, molecule.GetAtomVect().size(), CartesianType_end); | |
229 | - throw ex; | |
230 | 227 | } |
231 | - MallocerFreer::GetInstance()->Free(&matrixHessian, dimension, dimension); | |
232 | - MallocerFreer::GetInstance()->Free(&vectorOldForce, dimension); | |
233 | - MallocerFreer::GetInstance()->Free(&matrixStep, molecule.GetAtomVect().size(), CartesianType_end); | |
234 | - MallocerFreer::GetInstance()->Free(&matrixDisplacement, molecule.GetAtomVect().size(), CartesianType_end); | |
235 | - MallocerFreer::GetInstance()->Free(&matrixOldCoordinates, molecule.GetAtomVect().size(), CartesianType_end); | |
228 | + *lineSearchedEnergy = state.GetCurrentEnergy(); | |
236 | 229 | } |
237 | 230 | |
238 | 231 | void BFGS::CalcRFOStep(double* vectorStep, |
@@ -566,11 +559,10 @@ void BFGS::RollbackMolecularGeometry(MolDS_base::Molecule& molecule, | ||
566 | 559 | molecule.SetCanOutputLogs(tempCanOutputLogs); |
567 | 560 | } |
568 | 561 | |
569 | -void BFGS::CalcDisplacement(double * *& matrixDisplacement, | |
570 | - double const* const* matrixOldCoordinates, | |
562 | +void BFGS::CalcDisplacement(double * * matrixDisplacement, | |
563 | + double const* const* matrixOldCoordinates, | |
571 | 564 | const MolDS_base::Molecule& molecule)const{ |
572 | 565 | //Calculate displacement (K_k at Eq. (15) in [SJTO_1983]) |
573 | - MallocerFreer::GetInstance()->Malloc(&matrixDisplacement, molecule.GetAtomVect().size(), CartesianType_end); | |
574 | 566 | for(int i=0;i<molecule.GetAtomVect().size();i++){ |
575 | 567 | const Atom* atom = molecule.GetAtomVect()[i]; |
576 | 568 | const double* xyz = atom->GetXyz(); |
@@ -22,6 +22,33 @@ | ||
22 | 22 | namespace MolDS_optimization{ |
23 | 23 | |
24 | 24 | class BFGS : public MolDS_optimization::Optimizer{ |
25 | +private: | |
26 | + class BFGSState: public OptimizerState{ | |
27 | + protected: | |
28 | + double** matrixHessian; | |
29 | + double** matrixOldForce; | |
30 | + double** matrixStep; | |
31 | + double** matrixOldCoordinates; | |
32 | + double* vectorOldCoordinates; | |
33 | + double** matrixDisplacement; | |
34 | + size_t numAtoms; | |
35 | + private: | |
36 | + template<class vector> | |
37 | + vector Matrix2Vector(vector const* matrix){return matrix == NULL ? NULL : &matrix[0][0];} | |
38 | + public: | |
39 | + BFGSState(MolDS_base::Molecule& molecule); | |
40 | + virtual ~BFGSState(); | |
41 | + double const* GetVectorForce (){return this->Matrix2Vector(this->matrixForce);} | |
42 | + double* GetVectorOldForce (){return this->Matrix2Vector(this->matrixOldForce);} | |
43 | + double* GetVectorStep (){return this->Matrix2Vector(this->matrixStep);} | |
44 | + double const* GetVectorOldCoordinates(){return this->Matrix2Vector(this->matrixOldCoordinates);} | |
45 | + double** GetMatrixHessian() {return this->matrixHessian;} | |
46 | + double** GetMatrixOldForce() {return this->matrixOldForce;} | |
47 | + double** GetMatrixStep() {return this->matrixStep;} | |
48 | + double** GetMatrixOldCoordinates() {return this->matrixOldCoordinates;} | |
49 | + double**& GetMatrixOldCoordinatesRef(){return this->matrixOldCoordinates;} | |
50 | + double** GetMatrixDisplacement() {return this->matrixDisplacement;} | |
51 | + }; | |
25 | 52 | public: |
26 | 53 | BFGS(); |
27 | 54 | ~BFGS(); |
@@ -56,8 +83,8 @@ protected: | ||
56 | 83 | double const* vectorForce, |
57 | 84 | const double maxNormStep, |
58 | 85 | const int dimension) const; |
59 | - void CalcDisplacement(double * *& matrixDisplacement, | |
60 | - double const* const* matrixOldCoordinates, | |
86 | + void CalcDisplacement(double * * matrixDisplacement, | |
87 | + double const* const* matrixOldCoordinates, | |
61 | 88 | const MolDS_base::Molecule& molecule)const; |
62 | 89 | void UpdateHessian(double** matrixHessian, |
63 | 90 | const int dimension, |
@@ -24,7 +24,7 @@ namespace MolDS_optimization{ | ||
24 | 24 | class Optimizer : public MolDS_base::PrintController{ |
25 | 25 | protected: |
26 | 26 | class OptimizerState{ |
27 | - private: | |
27 | + protected: | |
28 | 28 | double currentEnergy; |
29 | 29 | double initialEnergy; |
30 | 30 | double const* const* matrixForce; |