1#ifndef MADNESS_MOLOPT_H
2#define MADNESS_MOLOPT_H
33 const double gradient_precision;
34 const int print_level;
37 Tensor<double> hessian;
40 Tensor<double> new_search_direction(
const Tensor<double>&
g,
41 const Tensor<double>&
h)
const {
43 double tol = gradient_precision;
48 if (print_level > 1)
print(
"hessian eigenvalues",
e);
52 if (print_level > 1)
print(
"spectral gradient",
gv);
56 for (
int i = 0; i <
e.dim(0); i++) {
59 if (print_level > 1)
print(
"skipping redundant mode", i);
63 printf(
" forcing negative eigenvalue to be positive %d %.1e\n", i,
67 }
else if (
e[i] < tol) {
69 printf(
" forcing small eigenvalue to be positive %d %.1e\n", i,
75 gv[i] = -
gv[i] /
e[i];
80 printf(
" restricting step in spectral direction %d %.1e --> %.1e\n",
92 if (print_level > 1)
print(
"cartesian dx before restriction",
gv);
96 for (
int i = 0; i <
gv.dim(0); i++) {
99 if (print_level > 0) {
100 if (!
printing)
printf(
" restricting step in Cartesian direction");
117 const Tensor<double> coords =
molecule.get_all_coords();
121 Tensor<double>
V(6, natom, 3);
123 for (
int k = 0;
k < 3;
k++)
124 V(
k,
_,
k) = 1.0 / std::sqrt(
static_cast<double>(natom));
127 for (
int k = 0;
k < 3;
k++)
centroid(
k) = coords(
_,
k).sum() / natom;
130 for (
int i = 0; i < natom; i++) {
131 double x = coords(i, 0) -
centroid[0];
132 double y = coords(i, 1) -
centroid[1];
133 double z = coords(i, 2) -
centroid[2];
148 V =
V.reshape(6, 3 * natom);
150 if (print_level > 1)
print(
"V before orthonormal");
151 if (print_level > 1)
print(
V);
155 for (
int i = 3; i < 6; i++) {
156 V(i,
_).scale(1.0 /
V(i,
_).normf());
157 for (
int j = 0; j < i; j++) {
158 double s =
V(i,
_).trace(
V(j,
_));
159 V(i,
_) -=
V(j,
_) *
s;
161 double vnorm =
V(i,
_).normf();
171 for (
int i = 0; i < 3 * natom; i++)
V(i, i) += 1.0;
180 template <
typename targetT>
188 Tensor<double> x =
molecule.get_all_coords().flat();
192 if (print_level > 0)
print(
" line search gradient +ve ",
a1,
dxgrad);
207 }
else if (
hess > 0.0) {
237 if (print_level > 0) {
238 printf(
"\n line search grad=%.2e hess=%.2e mode=%s newstep=%.3f\n",
249 double gradient_precision = 1
e-4,
int print_level = 1,
250 std::string
update =
"BFGS")
254 gtol(
std::
max(gtol, gradient_precision)),
257 gradient_precision(gradient_precision),
258 print_level(print_level),
262 if (print_level > 0) {
269 print(
" gradient convergence", gtol);
272 print(
" gradient precision", gradient_precision);
277 void set_hessian(
const Tensor<double>&
h) { hessian =
h; }
279 const Tensor<double>&
get_hessian()
const {
return hessian; }
283 hessian = Tensor<double>(
N,
N);
284 for (
int i = 0; i <
N; i++) hessian(i, i) = 0.5;
287 template <
typename targetT>
288 Molecule optimize(Molecule
molecule,
298 Tensor<double>
gp(3 * natom);
299 Tensor<double>
dx(3 * natom);
303 for (
int iter = 0; iter <
maxiter; iter++) {
305 print(
"\n\n Geometry optimization iteration", iter,
"\n");
306 if (print_level > 0)
molecule.print();
315 double gmax =
g.absmax();
322 if (!converged &&
gmax < gradient_precision) {
325 "\nInsufficient precision in gradient to proceed further -- "
326 "forcing convergence\n");
330 if (print_level > 0) {
331 const char*
tf[] = {
"F",
"T"};
334 " energy delta-e max-dx max-g e dx g\n");
336 " ---------------- --------- --------- --------- --- --- "
346 if (print_level > 0)
print(
"\n Geometry optimization converged!\n");
347 if (print_level > 0)
molecule.print();
356 if (print_level > 1)
print(
"gradient after projection",
g);
359 if ((
g -
gp).absmax() < 2.0 * gradient_precision) {
362 " skipping hessian update due to insufficient precision in "
364 }
else if (
update ==
"bfgs") {
366 }
else if (
update ==
"sr1") {
369 throw "unknown update";
377 const double shift = 1000.0;
379 if (print_level > 1) {
383 for (
int i = 0; i < 3 * natom; i++)
PHPS(i, i) +=
shift;
384 if (print_level > 1) {
391 dx = new_search_direction(
g,
PHPS);
392 if (print_level > 1)
print(
"dx",
dx);
398 if (print_level > 1)
print(
"scaled dx",
dx);
401 Tensor<double> x =
molecule.get_all_coords().flat();
403 molecule.set_all_coords(x.reshape(natom, 3));
405 if (print_level > 1)
print(
"new molecular coords");
static void hessian_update_bfgs(const Tensor< double > &dx, const Tensor< double > &dg, Tensor< double > &hessian)
make this static for other QN classed to have access to it
Definition solvers.cc:179
static void hessian_update_sr1(const Tensor< double > &s, const Tensor< double > &y, Tensor< double > &hessian)
make this static for other QN classed to have access to it
Definition solvers.cc:166
static double shift
Definition dirac-hatom.cc:19
const int maxiter
Definition gygi_soltion.cc:68
static const double v
Definition hatom_sf_dirac.cc:20
#define max(a, b)
Definition lda.h:51
Namespace for all elements and tools of MADNESS.
Definition DFParameters.h:10
response_space transpose(response_space &f)
Definition basic_operators.cc:10
static const Slice _(0,-1, 1)
void print(const T &t, const Ts &... ts)
Print items to std::cout (items separated by spaces) and terminate with a new line.
Definition print.h:226
void print_justified(const char *s, int column, bool underline)
Print a string justified on the left to start at the given column with optional underlining.
Definition print.cc:75
NDIM const Function< R, NDIM > & g
Definition mra.h:2528
double inner(response_space &a, response_space &b)
Definition response_functions.h:639
static XNonlinearSolver< std::vector< Function< T, NDIM > >, T, vector_function_allocator< T, NDIM > > nonlinear_vector_solver(World &world, const long nvec)
Definition nonlinsol.h:371
void syev(const Tensor< T > &A, Tensor< T > &V, Tensor< typename Tensor< T >::scalar_type > &e)
Real-symmetric or complex-Hermitian eigenproblem.
Definition lapack.cc:969
static long abs(long a)
Definition tensor.h:218
static const long k
Definition rk.cc:44
Defines interfaces for optimization and non-linear equation solvers.
static double V(const coordT &r)
Definition tdse.cc:288
Defines and implements most of Tensor.
Prototypes for a partial interface from Tensor to LAPACK.
int P
Definition test_binsorter.cc:9
void e()
Definition test_sig.cc:75
#define N
Definition testconv.cc:37
vector_complex_function_3d update(World &world, const vector_complex_function_3d &psi, vector_complex_function_3d &vpsi, const tensor_real &e, int iter)
Definition testcosine.cc:210
static const double alpha
Definition testcosine.cc:10
double h(const coord_1d &r)
Definition testgconv.cc:175
static Molecule molecule
Definition testperiodicdft.cc:39
const double a2
Definition vnucso.cc:86
const double a1
Definition vnucso.cc:85
FLOAT target(const FLOAT &x)
Definition y.cc:295