9#ifndef PERIODIC_OPTIMIZER_HPP
10#define PERIODIC_OPTIMIZER_HPP
18namespace PES_optimizer{
23 Eigen::Matrix3d initial_latttice;
24 Eigen::Matrix3d initial_latttice_inv;
25 Eigen::Matrix3d lattice_transformer;
26 Eigen::Matrix3d lattice_transformer_inv;
27 std::unique_ptr<sqnm_space::SQNM> opt;
31 double initial_step_size = 1;
34 double f_std_deviation = 0.0;
46 double get_initial_step_size(){
47 return initial_step_size;
59 this->opt_lattice =
false;
60 this->opt = std::make_unique<sqnm_space::SQNM>(ndim, n_hist_max, initial_step_size);
73 periodic_optimizer(
int &nat,
double initial_step_size,
int nhist_max,
double alpha0,
double eps_subsp)
77 this->initial_step_size = initial_step_size;
78 this->n_hist_max = nhist_max;
79 this->opt_lattice =
false;
80 this->opt = std::make_unique<sqnm_space::SQNM>(ndim, n_hist_max, initial_step_size, alpha0, eps_subsp);
91 periodic_optimizer(
int &nat, Eigen::Vector3d &lat_a, Eigen::Vector3d &lat_b, Eigen::Vector3d &lat_c)
93 setupInitialLattice(nat, lat_a, lat_b, lat_c);
94 this->opt = std::make_unique<sqnm_space::SQNM>(ndim, n_hist_max, initial_step_size);
111 periodic_optimizer(
int &nat, Eigen::Vector3d &lat_a, Eigen::Vector3d &lat_b, Eigen::Vector3d &lat_c,
double initial_step_size,
int nhist_max,
double lattice_weight,
double alpha0,
double eps_subsp)
113 this->w = lattice_weight;
114 this->n_hist_max = nhist_max;
115 this->initial_step_size = initial_step_size;
116 setupInitialLattice(nat, lat_a, lat_b, lat_c);
117 this->opt = std::make_unique<sqnm_space::SQNM>(ndim, n_hist_max, initial_step_size, alpha0, eps_subsp);
130 void step(Eigen::MatrixXd &r,
double &energy, Eigen::MatrixXd &f){
133 std::cout <<
"The fixed cell step function was called even though the object was created for vc-relaxation. returning" <<
"\n";
137 Eigen::VectorXd pos_all = Eigen::Map<Eigen::VectorXd>(r.data(), 3*nat);
138 Eigen::VectorXd force_all = - Eigen::Map<Eigen::VectorXd>(f.data(), 3*nat);
139 pos_all += opt->step(pos_all, energy, force_all);
140 r = Eigen::Map<Eigen::MatrixXd>(pos_all.data(), 3, nat);
157 void step(Eigen::MatrixXd &r,
double &energy, Eigen::MatrixXd &f, Eigen::Vector3d &lat_a, Eigen::Vector3d &lat_b, Eigen::Vector3d &lat_c, Eigen::Matrix3d &stress){
160 std::cout <<
"The vc step function was called even though the object was created for fixed cell relaxation. returning" <<
"\n";
164 Eigen::Matrix3d alat;
165 Eigen::MatrixXd alat_tilde;
171 Eigen::MatrixXd q(3, nat);
172 Eigen::MatrixXd dq(3, nat);
173 q = initial_latttice * alat.inverse() * r;
174 dq = - alat * this->initial_latttice_inv * f;
178 alat_tilde = alat * lattice_transformer;
179 Eigen::MatrixXd dalat = calc_lattice_derivatices(stress, alat) * lattice_transformer_inv;
180 Eigen::VectorXd qall = combine_matrices(q, alat_tilde);
181 Eigen::VectorXd dqall = combine_matrices(dq, dalat);
184 qall += this->opt->step(qall, energy, dqall);
186 split_matrices(q, alat_tilde, qall);
187 alat = alat_tilde * lattice_transformer_inv;
188 r = alat * this->initial_latttice_inv * q;
194 void check_forces(Eigen::MatrixXd forces)
196 double fnoise = forces.rowwise().sum().norm() / sqrt(3 * this->nat);
197 if (this->f_std_deviation == 0)
199 this->f_std_deviation = fnoise;
201 this->f_std_deviation = .8 * this->f_std_deviation + .2 * fnoise;
203 if (this->f_std_deviation > 0.2 * forces.cwiseAbs().maxCoeff()) {
204 std::cerr <<
"Noise in force is larger than 0.2 times the larges force component. Convergence cannot be guaranteed.";
215 return this->opt->lower_bound();
219 Eigen::VectorXd combine_matrices(Eigen::MatrixXd a, Eigen::MatrixXd b){
220 Eigen::VectorXd result(this->ndim);
221 for (
int i = 0; i < 3*nat; i++)
226 for (
int i = 3*nat; i < ndim; i++)
234 void split_matrices(Eigen::MatrixXd &a, Eigen::MatrixXd &b, Eigen::VectorXd &c){
235 for (
int i = 0; i < 3*nat; i++)
240 for (
int i = 3*nat; i < ndim; i++)
247 Eigen::Matrix3d calc_lattice_derivatices(Eigen::Matrix3d &stress, Eigen::Matrix3d &alat){
248 Eigen::Matrix3d da = - stress * alat.inverse().transpose() * alat.determinant();
252 void setupInitialLattice(
int &nat, Eigen::Vector3d &lat_a, Eigen::Vector3d &lat_b, Eigen::Vector3d &lat_c)
255 this->ndim = 3*nat + 9;
256 this->initial_latttice.col(0) = lat_a;
257 this->initial_latttice.col(1) = lat_b;
258 this->initial_latttice.col(2) = lat_c;
259 this->initial_latttice_inv = initial_latttice.inverse();
260 lattice_transformer.setZero();
261 for (
int i = 0; i < 3; i++)
263 lattice_transformer(i, i) = 1.0 / (initial_latttice.col(i).norm());
265 lattice_transformer = lattice_transformer * (w * sqrt(nat));
266 lattice_transformer_inv = lattice_transformer.inverse();
267 this->opt_lattice =
true;
periodic_optimizer(int &nat, Eigen::Vector3d &lat_a, Eigen::Vector3d &lat_b, Eigen::Vector3d &lat_c)
Construct a new periodic optimizer::periodic optimizer object for variable cell shape optimization wi...
double lower_bound()
Estimates a lower bound of the energy of the local minimum.
void step(Eigen::MatrixXd &r, double &energy, Eigen::MatrixXd &f, Eigen::Vector3d &lat_a, Eigen::Vector3d &lat_b, Eigen::Vector3d &lat_c, Eigen::Matrix3d &stress)
Calculates new atomic coordinates that are closer to the local minimum. Variable cell shape optimizat...
periodic_optimizer(int &nat, Eigen::Vector3d &lat_a, Eigen::Vector3d &lat_b, Eigen::Vector3d &lat_c, double initial_step_size, int nhist_max, double lattice_weight, double alpha0, double eps_subsp)
Construct a new periodic optimizer::periodic optimizer object for variable cell shape optimization wi...
periodic_optimizer(int &nat, double initial_step_size, int nhist_max, double alpha0, double eps_subsp)
Construct a new periodic optimizer::periodic optimizer object for free or fixed cell optimization wit...
void step(Eigen::MatrixXd &r, double &energy, Eigen::MatrixXd &f)
Calculates new atomic coordinates that are closer to the local minimum. Fixed cell optimization....
periodic_optimizer(int &nat)
Construct a new periodic optimizer::periodic optimizer object for free or fixed cell optimization wit...
Variable cell stable quasi-Newton lattice optimizer.
Implementation of the SQNM method. More informations about the algorithm can be found here: https://a...