Loading...
Searching...
No Matches
BiasedGradientSquaredDescent.cpp
Go to the documentation of this file.
1/*
2** This file is part of eOn.
3**
4** SPDX-License-Identifier: BSD-3-Clause
5**
6** Copyright (c) 2010--present, eOn Development Team
7** All rights reserved.
8**
9** Repo:
10** https://github.com/TheochemUI/eOn
11*/
14#include "eon/HelperFunctions.h"
15#include "eon/Matter.h"
17#include "eon/Optimizer.h"
19
20#include <cassert>
21#include <cmath>
22#include <cstdlib>
23#include <cstring>
24#include <map>
25
28
29public:
30 BGSDObjectiveFunction(Matter &matterRef, double reactantEnergyPassed,
31 double bgsdAlphaPassed,
32 const Parameters &parametersPassed)
33 : ObjectiveFunction(parametersPassed),
34 matter{matterRef} {
35 bgsdAlpha = bgsdAlphaPassed;
36 reactantEnergy = reactantEnergyPassed;
37 }
38
40
41 double getEnergy() {
42 VectorXd Vforce = matter.getForcesFreeV();
43 double Henergy = 0.5 * Vforce.dot(Vforce) +
44 0.5 * bgsdAlpha *
45 (matter.getPotentialEnergy() -
46 (reactantEnergy + params.bgsd_options.beta)) *
47 (matter.getPotentialEnergy() -
48 (reactantEnergy + params.bgsd_options.beta));
49 return Henergy;
50 }
51
52 VectorXd getGradient(bool fdstep = false) {
53 VectorXd Vforce = matter.getForcesFreeV();
54 double magVforce = Vforce.norm();
55 VectorXd normVforce = Vforce / magVforce;
56 VectorXd Vpositions = matter.getPositionsFreeV();
57 matter.setPositionsFreeV(
58 matter.getPositionsFreeV() -
59 normVforce * params.bgsd_options.gradient_finite_difference);
60 VectorXd Vforcenew = matter.getForcesFreeV();
61 matter.setPositionsFreeV(Vpositions);
62 VectorXd Hforce = magVforce * (Vforcenew - Vforce) /
63 params.bgsd_options.gradient_finite_difference +
64 bgsdAlpha *
65 (matter.getPotentialEnergy() -
66 (reactantEnergy + params.bgsd_options.beta)) *
67 Vforce;
68 return -Hforce;
69 }
70
71 double getGradientnorm() {
72 VectorXd Hforce = getGradient();
73 double Hnorm = Hforce.norm();
74 return Hnorm;
75 }
76
77 void setPositions(const VectorXd &x) { matter.setPositionsFreeV(x); }
78 VectorXd getPositions() { return matter.getPositionsFreeV(); }
79 int degreesOfFreedom() { return 3 * matter.numberOfFreeAtoms(); }
80 bool isConverged() { return isConvergedH() && isConvergedV(); }
81 bool isConvergedH() {
82 return getConvergenceH() < params.bgsd_options.h_force_convergence;
83 }
84 bool isConvergedV() {
85 return getConvergenceV() < params.bgsd_options.grad2energy_convergence;
86 }
88 return getConvergenceH() < params.bgsd_options.grad2force_convergence;
89 }
90
91 double getConvergence() { return getEnergy() && getGradient().norm(); }
92 double getConvergenceH() { return getGradient().norm(); }
93 double getConvergenceV() { return getEnergy(); }
94 VectorXd difference(const VectorXd &a, const VectorXd &b) {
95 return matter.pbcV(a - b);
96 }
97
98private:
100 double bgsdAlpha;
101};
102
104 auto objf = std::make_shared<BGSDObjectiveFunction>(
105 *saddle, reactantEnergy, params.bgsd_options.alpha, params);
107 objf, params.optimizer_options.method, params);
108 int iteration = 0;
109 QUILL_LOG_DEBUG(
110 log,
111 "starting optimization of H with params alpha and beta: {:.2f} {:.2f}",
112 params.bgsd_options.alpha, params.bgsd_options.beta);
113 while (!objf->isConvergedH() || iteration == 0) {
114 optim->step(params.optimizer_options.max_move);
115 QUILL_LOG_DEBUG(log,
116 "iteration {} Henergy, gradientHnorm, and Venergy: "
117 "{:.8f} {:.8f} {:.8f}",
118 iteration, objf->getEnergy(), objf->getGradientnorm(),
119 saddle->getPotentialEnergy());
120 iteration++;
121 }
122 auto objf2 = std::make_shared<BGSDObjectiveFunction>(*saddle, reactantEnergy,
123 0.0, params);
124 auto optim2 = eonc::helpers::create::mkOptim(
125 objf2, params.optimizer_options.method, params);
126 while (!objf2->isConvergedV() || iteration == 0) {
127 if (objf2->isConvergedIP()) {
128 break;
129 };
130 optim2->step(params.optimizer_options.max_move);
131 QUILL_LOG_DEBUG(log,
132 "gradient squared iteration {} Henergy, gradientHnorm, "
133 "and Venergy: {:.8f} {:.8f} {:.8f}",
134 iteration, objf2->getEnergy(), objf2->getGradientnorm(),
135 saddle->getPotentialEnergy());
136 iteration++;
137 }
138
139 auto minModeMethod = eonc::buildEigenmodeStrategy(saddle, params, pot);
140
141 eigenvector.setRandom();
142 for (int i = 0; i < saddle->numberOfAtoms(); i++) {
143 for (int j = 0; j < 3; j++) {
144 if (saddle->getFixed(i)) {
145 eigenvector(i, j) = 0.0;
146 };
147 }
148 }
149 eigenvector.normalize();
150 eonc::eigenmodeCompute(*minModeMethod, saddle, eigenvector);
153 QUILL_LOG_DEBUG(log, "lowest eigenvalue {:.8f}", eigenvalue);
154 if (objf2->isConvergedV()) {
155 return 0;
156 } else if (objf2->isConvergedIP()) {
157 return 1;
158 } else {
159 return 1;
160 };
161}
162
164
Eigen::Matrix< double, Eigen::Dynamic, 3, eOnStorageOrder > AtomMatrix
Definition Eigen.h:37
The optimizer class is used to serve as an abstract class for all optimizers, as well as to call an o...
BGSDObjectiveFunction(Matter &matterRef, double reactantEnergyPassed, double bgsdAlphaPassed, const Parameters &parametersPassed)
VectorXd difference(const VectorXd &a, const VectorXd &b)
~BGSDObjectiveFunction()=default
void setPositions(const VectorXd &x)
VectorXd getGradient(bool fdstep=false)
ObjectiveFunction(const Parameters &paramsPassed)
const Parameters & params
std::shared_ptr< Potential > pot
std::unique_ptr< Optimizer > mkOptim(std::shared_ptr< ObjectiveFunction > a_objf, OptType a_otype, const Parameters &a_params)
Definition Optimizer.cpp:21
AtomMatrix eigenmodeGetEigenvector(EigenmodeStrategy &s)
Dispatch getEigenvector() to the active variant.
std::shared_ptr< EigenmodeStrategy > buildEigenmodeStrategy(std::shared_ptr< Matter > matter, const Parameters &params, std::shared_ptr< Potential > pot)
Build the eigenmode solver from parameters.
void eigenmodeCompute(EigenmodeStrategy &s, std::shared_ptr< Matter > matter, AtomMatrix direction)
Dispatch compute() to the active variant.
double eigenmodeGetEigenvalue(EigenmodeStrategy &s)
Dispatch getEigenvalue() to the active variant.