Loading...
Searching...
No Matches
NEBObjectiveFunction.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*/
13#include "eon/SolidStateNEB.h"
14
15namespace eonc {
16namespace {
17
18long nebSegment(const NudgedElasticBand &neb) {
19 return 3L * neb.atoms + (neb.solidState() ? 9L : 0L);
20}
21
22} // namespace
23
24VectorXd NEBObjectiveFunction::getGradient(bool fdstep) {
25 if (neb->movedAfterForceCall)
26 neb->updateForces();
27 const long seg = nebSegment(*neb);
28 const long atomDof = 3L * neb->atoms;
29 VectorXd gradV(seg * neb->numImages);
30 for (long i = 1; i <= neb->numImages; i++) {
31 // Negate in-place during copy to avoid a second pass over 40KB
32 gradV.segment(seg * (i - 1), atomDof) =
33 -VectorXd::Map(neb->projectedForce[i]->data(), atomDof);
34 if (neb->solidState()) {
36 *neb->path[i], *neb->projectedForce[i], neb->cellForce(i),
37 neb->solidJacobian());
38 gradV.segment(seg * (i - 1), atomDof) =
39 -VectorXd::Map(step.positions.data(), atomDof);
40 gradV.segment(seg * (i - 1) + atomDof, 9) =
41 -VectorXd::Map(step.cell.data(), 9);
42 }
43 }
44 return gradV;
45}
46
48 // The band update evaluates dirty images as one batch; summing image
49 // energies on a moved band would otherwise evaluate them one at a time.
50 if (neb->movedAfterForceCall)
51 neb->updateForces();
52 double Energy{0};
53 for (long i = 1; i <= neb->numImages; i++) {
54 Energy += neb->path[i]->getPotentialEnergy();
55 }
56 return Energy;
57}
58
59void NEBObjectiveFunction::setPositions(const VectorXd &x) {
60 neb->movedAfterForceCall = true;
61 const long seg = nebSegment(*neb);
62 const long atomDof = 3L * neb->atoms;
63 for (long i = 1; i <= neb->numImages; i++) {
64 const long offset = seg * (i - 1);
65 if (neb->solidState()) {
66 Matrix3d cell = Matrix3d::Map(x.segment(offset + atomDof, 9).data());
67 cell(0, 1) = 0.0;
68 cell(0, 2) = 0.0;
69 cell(1, 2) = 0.0;
70 neb->path[i]->setCell(cell);
71 }
72 neb->path[i]->setPositions(
73 AtomMatrix::Map(x.segment(offset, atomDof).data(), neb->atoms, 3));
74 }
75}
76
78 const long seg = nebSegment(*neb);
79 const long atomDof = 3L * neb->atoms;
80 VectorXd posV(seg * neb->numImages);
81 for (long i = 1; i <= neb->numImages; i++) {
82 const long offset = seg * (i - 1);
83 posV.segment(offset, atomDof) =
84 VectorXd::Map(neb->path[i]->getPositions().data(), atomDof);
85 if (neb->solidState()) {
86 posV.segment(offset + atomDof, 9) =
87 VectorXd::Map(neb->path[i]->getCell().data(), 9);
88 }
89 }
90 return posV;
91}
92
94 return static_cast<int>(nebSegment(*neb) * neb->numImages);
95}
96
98 double maxMaxUnc = std::numeric_limits<double>::lowest();
99 double currentMaxUnc{0};
100 for (long idx = 0; idx <= neb->numImages + 1; idx++) {
101 currentMaxUnc = neb->path[idx]->getEnergyVariance();
102 if (currentMaxUnc > maxMaxUnc) {
103 maxMaxUnc = currentMaxUnc;
104 }
105 }
106 bool unc_conv{maxMaxUnc > params.gp_surrogate_options().uncertainty};
107 if (unc_conv) {
109 }
110 return unc_conv;
111}
112
114 bool force_conv = getConvergence() < params.neb_options().force_tolerance;
115 return force_conv;
116}
117
119 return neb->convergenceForce();
120}
121
122VectorXd NEBObjectiveFunction::difference(const VectorXd &a,
123 const VectorXd &b) {
124 const long seg = nebSegment(*neb);
125 const long atomDof = 3L * neb->atoms;
126 VectorXd pbcDiff(seg * neb->numImages);
127 for (int i = 1; i <= neb->numImages; i++) {
128 const int n = (i - 1) * static_cast<int>(seg);
129 pbcDiff.segment(n, atomDof) =
130 neb->path[i]->pbcV(a.segment(n, atomDof) - b.segment(n, atomDof));
131 if (neb->solidState()) {
132 pbcDiff.segment(n + atomDof, 9) =
133 a.segment(n + atomDof, 9) - b.segment(n + atomDof, 9);
134 }
135 }
136 return pbcDiff;
137}
138
139} // namespace eonc
Eigen::Matrix< double, 3, 3, eOnStorageOrder > Matrix3d
Definition Eigen.h:35
VectorXd getGradient(bool fdstep=false)
NudgedElasticBand::NEBStatus status
VectorXd difference(const VectorXd &a, const VectorXd &b)
void setPositions(const VectorXd &x)
const Parameters & params
CartesianStep solidStateCartesianStep(const Matter &image, const AtomMatrix &atomicForce, const Matrix3d &cellForce, double jacobian)
RAII resource manager for the ARTn C library with global synchronization.
One steepest step in Cartesian coordinates and the cell matrix.