1#ifndef MADNESS_MOLOPT_H
2#define MADNESS_MOLOPT_H
34 const double gradient_precision;
35 const int print_level;
38 Tensor<double> hessian;
41 Tensor<double> new_search_direction(
const Tensor<double> &
g,
42 const Tensor<double> &
h)
const {
44 double tol = gradient_precision;
50 print(
"hessian eigenvalues",
e);
59 for (
int i = 0; i <
e.dim(0); i++) {
63 print(
"skipping redundant mode", i);
67 printf(
" forcing negative eigenvalue to be positive %d %.1e\n", i,
71 }
else if (
e[i] < tol) {
73 printf(
" forcing small eigenvalue to be positive %d %.1e\n", i,
79 gv[i] = -
gv[i] /
e[i];
84 printf(
" restricting step in spectral direction %d %.1e --> %.1e\n",
97 print(
"cartesian dx before restriction",
gv);
101 for (
int i = 0; i <
gv.dim(0); i++) {
104 if (print_level > 0) {
106 printf(
" restricting step in Cartesian direction");
124 const Tensor<double> coords =
molecule.get_all_coords();
128 Tensor<double>
V(6, natom, 3);
130 for (
int k = 0;
k < 3;
k++)
131 V(
k,
_,
k) = 1.0 / std::sqrt(
static_cast<double>(natom));
134 for (
int k = 0;
k < 3;
k++)
139 for (
int i = 0; i < natom; i++) {
140 double x = coords(i, 0) -
centroid[0];
141 double y = coords(i, 1) -
centroid[1];
142 double z = coords(i, 2) -
centroid[2];
157 V =
V.reshape(6, 3 * natom);
160 print(
"V before orthonormal");
166 for (
int i = 3; i < 6; i++) {
167 V(i,
_).scale(1.0 /
V(i,
_).normf());
168 for (
int j = 0; j < i; j++) {
169 double s =
V(i,
_).trace(
V(j,
_));
170 V(i,
_) -=
V(j,
_) *
s;
172 double vnorm =
V(i,
_).normf();
182 for (
int i = 0; i < 3 * natom; i++)
202 const Tensor<double> &
g)
const {
203 const size_t natom =
molecule.natom();
207 double net[3] = {0.0, 0.0, 0.0};
208 for (
size_t i = 0; i < natom; ++i)
209 for (
int c = 0;
c < 3; ++
c)
212 print(
"\n Gradient (a.u.), translations and rotations projected out\n"
213 " ---------------------------------------------------------\n");
214 print(
" atom x y z dE/dx "
216 print(
" ------ ------------ ------------ ------------ ------------ "
217 "------------ ------------");
218 for (
size_t i = 0; i < natom; ++i) {
220 printf(
" %5d %12.6f %12.6f %12.6f %12.6f %12.6f %12.6f\n",
int(i), atom.
x,
221 atom.
y, atom.
z,
g[i * 3 + 0],
g[i * 3 + 1],
g[i * 3 + 2]);
223 printf(
" max element of the projected gradient %12.3e\n",
g.absmax());
224 printf(
" net force removed by the projection %12.3e %12.3e %12.3e\n",
232 template <
typename targetT>
240 Tensor<double> x =
molecule.get_all_coords().flat();
260 }
else if (
hess > 0.0) {
290 if (print_level > 0) {
291 printf(
"\n line search grad=%.2e hess=%.2e mode=%s newstep=%.3f\n",
302 double gradient_precision = 1
e-4,
int print_level = 1,
303 std::string
update =
"BFGS")
308 gradient_precision(gradient_precision), print_level(print_level),
312 if (print_level > 0) {
322 print(
" gradient precision", gradient_precision);
327 void set_hessian(
const Tensor<double> &
h) { hessian =
h; }
329 const Tensor<double> &
get_hessian()
const {
return hessian; }
333 hessian = Tensor<double>(
N,
N);
334 for (
int i = 0; i <
N; i++)
338 template <
typename targetT>
339 Molecule optimize(Molecule
molecule,
346 if (hessian.size() == 0)
350 Tensor<double>
gp(3 * natom);
351 Tensor<double>
dx(3 * natom);
355 for (
int iter = 0; iter <
maxiter; iter++) {
357 print(
"\n\n Geometry optimization iteration", iter,
"\n");
379 double gmax =
g.absmax();
386 if (!converged &&
gmax < gradient_precision) {
388 print(
"\nInsufficient precision in gradient to proceed further -- "
389 "forcing convergence\n");
393 if (print_level > 0) {
394 const char *
tf[] = {
"F",
"T"};
397 " energy delta-e max-dx max-g e dx g\n");
398 printf(
" ---------------- --------- --------- --------- --- --- "
409 print(
"\n Geometry optimization converged!\n");
416 if ((
g -
gp).absmax() < 2.0 * gradient_precision) {
418 print(
" skipping hessian update due to insufficient precision in "
420 }
else if (
update ==
"bfgs") {
422 }
else if (
update ==
"sr1") {
425 throw "unknown update";
433 const double shift = 1000.0;
435 if (print_level > 1) {
439 for (
int i = 0; i < 3 * natom; i++)
441 if (print_level > 1) {
448 dx = new_search_direction(
g,
PHPS);
461 Tensor<double> x =
molecule.get_all_coords().flat();
463 molecule.set_all_coords(x.reshape(natom, 3));
466 print(
"new molecular coords");
472 template <
typename targetT>
475 -> OptimizationResults {
480 OptimizationResults results;
482 if (hessian.size() == 0)
486 Tensor<double>
gp(3 * natom);
487 Tensor<double>
dx(3 * natom);
492 for (iter = 0; iter <
maxiter; iter++) {
494 print(
"\n\n Geometry optimization iteration", iter,
"\n");
516 results.max_gradient =
g.absmax();
519 bool gconv = results.max_gradient <
gtol;
523 if (!converged && results.max_gradient < gradient_precision) {
525 print(
"\nInsufficient precision in gradient to proceed further -- "
526 "forcing convergence\n");
530 if (print_level > 0) {
531 const char *
tf[] = {
"F",
"T"};
534 " energy delta-e max-dx max-g e dx g\n");
535 printf(
" ---------------- --------- --------- --------- --- --- "
546 print(
"\n Geometry optimization converged!\n");
553 if ((
g -
gp).absmax() < 2.0 * gradient_precision) {
555 print(
" skipping hessian update due to insufficient precision in "
557 }
else if (
update ==
"bfgs") {
559 }
else if (
update ==
"sr1") {
562 throw "unknown update";
570 const double shift = 1000.0;
572 if (print_level > 1) {
576 for (
int i = 0; i < 3 * natom; i++)
578 if (print_level > 1) {
585 dx = new_search_direction(
g,
PHPS);
598 Tensor<double> x =
molecule.get_all_coords().flat();
600 molecule.set_all_coords(x.reshape(natom, 3));
603 print(
"new molecular coords");
606 results.final_energy =
ep;
607 results.nsteps = iter;
double x
Definition mentity.h:73
double y
Definition mentity.h:73
double z
Definition mentity.h:73
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
Tensor< T > transpose(const Tensor< T > &t)
Returns a new deep copy of the transpose of the input tensor.
Definition tensor.h:2035
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
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:227
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:2622
Function< T, CCPairFunction< T, NDIM >::LDIM > inner(const CCPairFunction< T, NDIM > &c, const Function< T, CCPairFunction< T, NDIM >::LDIM > &f, const std::tuple< int, int, int > v1, const std::tuple< int, int, int > v2)
Definition ccpairfunction.h:993
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
Function< T, NDIM > copy(const Function< T, NDIM > &f, const std::shared_ptr< WorldDCPmapInterface< Key< NDIM > > > &pmap, bool fence=true)
Create a new copy of the function with different distribution and optional fence.
Definition mra.h:2187
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:219
static const double c
Definition relops.cc:10
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