OpenMD 3.2
Molecular Dynamics in the Open
Loading...
Searching...
No Matches
BoxObjectiveFunction.cpp
1/*
2 * Copyright (c) 2004-present, The University of Notre Dame. All rights
3 * reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation
13 * and/or other materials provided with the distribution.
14 *
15 * 3. Neither the name of the copyright holder nor the names of its
16 * contributors may be used to endorse or promote products derived from
17 * this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 *
31 * SUPPORT OPEN SCIENCE! If you use OpenMD or its source code in your
32 * research, please cite the following paper when you publish your work:
33 *
34 * [1] Drisko et al., J. Open Source Softw. 9, 7004 (2024).
35 *
36 * Good starting points for code and simulation methodology are:
37 *
38 * [2] Meineke, et al., J. Comp. Chem. 26, 252-271 (2005).
39 * [3] Fennell & Gezelter, J. Chem. Phys. 124, 234104 (2006).
40 * [4] Sun, Lin & Gezelter, J. Chem. Phys. 128, 234107 (2008).
41 * [5] Vardeman, Stocker & Gezelter, J. Chem. Theory Comput. 7, 834 (2011).
42 * [6] Kuang & Gezelter, Mol. Phys., 110, 691-701 (2012).
43 * [7] Lamichhane, Gezelter & Newman, J. Chem. Phys. 141, 134109 (2014).
44 * [8] Bhattarai, Newman & Gezelter, Phys. Rev. B 99, 094106 (2019).
45 * [9] Drisko & Gezelter, J. Chem. Theory Comput. 20, 4986-4997 (2024).
46 */
47
48#include "optimization/BoxObjectiveFunction.hpp"
49
50#include "math/CholeskyDecomposition.hpp"
51
52namespace OpenMD {
53
54 BoxObjectiveFunction::BoxObjectiveFunction(SimInfo* info,
55 ForceManager* forceMan) :
56 info_(info),
57 forceMan_(forceMan), thermo(info) {
58 shake_ = new Shake(info_);
59
60 if (info_->usesFluctuatingCharges()) {
61 if (info_->getNFluctuatingCharges() > 0) {
62 hasFlucQ_ = true;
63 fqConstraints_ = new FluctuatingChargeConstraints(info_);
64 bool cr = info_->getSimParams()
65 ->getFluctuatingChargeParameters()
66 ->getConstrainRegions();
67 fqConstraints_->setConstrainRegions(cr);
68 }
69 }
70 }
71
72 BoxObjectiveFunction::~BoxObjectiveFunction() {
73 delete shake_;
74 }
75
77 info_->getSnapshotManager()->advance();
78
79 if (setCoor(x) == 0) {
80 shake_->constraintR();
81 forceMan_->calcForces();
82 if (hasFlucQ_) fqConstraints_->applyConstraints();
83 shake_->constraintF();
84 return thermo.getPotential();
85 } else {
86 // The deformation was too large, so return an infinite potential
87 return std::numeric_limits<RealType>::infinity();
88 }
89 }
90
92 const DynamicVector<RealType>& x) {
93 info_->getSnapshotManager()->advance();
94 if (setCoor(x) == 0) {
95 shake_->constraintR();
96 forceMan_->calcForces();
97 if (hasFlucQ_) fqConstraints_->applyConstraints();
98 shake_->constraintF();
99 getGrad(grad);
100 } else {
101 // The deformation was too large, so return an infinite gradient:
102 for (int j = 0; j < 6; j++)
103 grad[j] = std::numeric_limits<RealType>::infinity();
104 }
105 }
106
109 info_->getSnapshotManager()->advance();
110 if (setCoor(x) == 0) {
111 shake_->constraintR();
112 forceMan_->calcForces();
113 if (hasFlucQ_) fqConstraints_->applyConstraints();
114 shake_->constraintF();
115 getGrad(grad);
116 return thermo.getPotential();
117 } else {
118 // The deformation was too large, so return infinite
119 // potential and gradient
120 for (int j = 0; j < 6; j++)
121 grad[j] = std::numeric_limits<RealType>::infinity();
122 return std::numeric_limits<RealType>::infinity();
123 }
124 }
125
126 int BoxObjectiveFunction::setCoor(const DynamicVector<RealType>& x) {
127 Vector3d posO;
128 Vector3d posN;
129 Vector3d delta;
130 SimInfo::MoleculeIterator miter;
131 Molecule* mol;
132 Mat3x3d eta(0.0);
133 Mat3x3d eps(0.0);
134 Mat3x3d y(0.0);
135 Mat3x3d test(0.0);
136 RealType norm;
137
138 // η is the Lagrangian strain tensor:
139 eta.setupVoigtTensor(x[0], x[1], x[2], x[3] / 2., x[4] / 2., x[5] / 2.);
140
141 // Make sure the deformation isn't too large:
142 if (eta.frobeniusNorm() > 0.7) {
143 // Deformation is too large, return an error condition:
144 return -1;
145 }
146
147 // Find the physical strain tensor, ε, from the Lagrangian strain, η:
148 // η = ε + 0.5 * ε^2
149 norm = 1.0;
150 eps = eta;
151 while (norm > 1.0e-10) {
152 y = eta - eps * eps / 2.0;
153 test = y - eps;
154 norm = test.frobeniusNorm();
155 eps = y;
156 }
157 deformation_ = SquareMatrix3<RealType>::identity() + eps;
158
159 int index = 0;
160
161 for (mol = info_->beginMolecule(miter); mol != NULL;
162 mol = info_->nextMolecule(miter)) {
163 posO = refPos_[index++];
164 posN = mol->getCom();
165 delta = deformation_ * posO - posN;
166 mol->moveCom(delta);
167 }
168
169 Mat3x3d Hmat = deformation_ * refHmat_;
170 info_->getSnapshotManager()->getCurrentSnapshot()->setHmat(Hmat);
171 return 0;
172 }
173
174 void BoxObjectiveFunction::getGrad(DynamicVector<RealType>& grad) {
175 Mat3x3d pressureTensor;
176 Vector<RealType, 6> lstress(0.0);
177
178 // Find the Lagragian stress tensor, τ, from the physical
179 // stress tensor, σ, that was computed from the pressureTensor
180 // in this code.
181 // τ = det(1+ε) (1+ε)^−1 · σ · (1+ε)^−1
182 // (Note that 1+ε is the deformation tensor computed above.)
183
184 Mat3x3d idm = deformation_.inverse();
185 RealType ddm = deformation_.determinant();
186
187 pressureTensor = thermo.getPressureTensor();
188 pressureTensor.negate();
189 pressureTensor *= Constants::elasticConvert;
190
191 Mat3x3d tao = idm * (pressureTensor * idm);
192 tao *= ddm;
193
194 lstress = tao.toVoigtTensor();
195 RealType V = thermo.getVolume();
196
197 for (int j = 0; j < 6; j++) {
198 grad[j] = V * lstress[j];
199 }
200 }
201
202 DynamicVector<RealType> BoxObjectiveFunction::setInitialCoords() {
203 DynamicVector<RealType> xinit(6, 0.0);
204 SimInfo::MoleculeIterator miter;
205 Molecule* mol;
206
207 Snapshot* snap = info_->getSnapshotManager()->getCurrentSnapshot();
208 refHmat_ = snap->getHmat();
209 V0_ = snap->getVolume();
210
211 refPos_.clear();
212 for (mol = info_->beginMolecule(miter); mol != NULL;
213 mol = info_->nextMolecule(miter)) {
214 refPos_.push_back(mol->getCom());
215 }
216
217 return xinit;
218 }
219} // namespace OpenMD
RealType valueAndGradient(DynamicVector< RealType > &grad, const DynamicVector< RealType > &x)
method to overload to compute grad_f, the first derivative
RealType value(const DynamicVector< RealType > &x)
method to overload to compute the objective function value in x
void gradient(DynamicVector< RealType > &grad, const DynamicVector< RealType > &x)
method to overload to compute grad_f, the first derivative of
Dynamically-sized vector class.
ForceManager is responsible for calculating both the short range (bonded) interactions and long range...
void moveCom(const Vector3d &delta)
Moves the center of this molecule.
Definition Molecule.cpp:358
Vector3d getCom()
Returns the current center of mass position of this molecule.
Definition Molecule.cpp:315
void negate()
Negates the value of this matrix in place.
One of the heavy-weight classes of OpenMD, SimInfo maintains objects and variables relating to the cu...
Definition SimInfo.hpp:96
Mat3x3d getHmat()
Returns the H-Matrix.
Definition Snapshot.cpp:217
SquareMatrix3< Real > inverse() const
Sets the value of this matrix to the inverse of itself.
Real determinant() const
Returns the determinant of this matrix.
static SquareMatrix< Real, Dim > identity()
This basic Periodic Table class was originally taken from the data.cpp file in OpenBabel.