OpenMD 3.0
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 appropriate papers when you publish your
33 * work. Good starting points are:
34 *
35 * [1] Meineke, et al., J. Comp. Chem. 26, 252-271 (2005).
36 * [2] Fennell & Gezelter, J. Chem. Phys. 124, 234104 (2006).
37 * [3] Sun, Lin & Gezelter, J. Chem. Phys. 128, 234107 (2008).
38 * [4] Vardeman, Stocker & Gezelter, J. Chem. Theory Comput. 7, 834 (2011).
39 * [5] Kuang & Gezelter, Mol. Phys., 110, 691-701 (2012).
40 * [6] Lamichhane, Gezelter & Newman, J. Chem. Phys. 141, 134109 (2014).
41 * [7] Lamichhane, Newman & Gezelter, J. Chem. Phys. 141, 134110 (2014).
42 * [8] Bhattarai, Newman & Gezelter, Phys. Rev. B 99, 094106 (2019).
43 */
44
45#include "optimization/BoxObjectiveFunction.hpp"
46
47#include "math/CholeskyDecomposition.hpp"
48
49namespace OpenMD {
50
51 BoxObjectiveFunction::BoxObjectiveFunction(SimInfo* info,
52 ForceManager* forceMan) :
53 info_(info),
54 forceMan_(forceMan), thermo(info) {
55 shake_ = new Shake(info_);
56
57 if (info_->usesFluctuatingCharges()) {
58 if (info_->getNFluctuatingCharges() > 0) {
59 hasFlucQ_ = true;
60 fqConstraints_ = new FluctuatingChargeConstraints(info_);
61 bool cr = info_->getSimParams()
62 ->getFluctuatingChargeParameters()
63 ->getConstrainRegions();
64 fqConstraints_->setConstrainRegions(cr);
65 }
66 }
67 }
68
69 RealType BoxObjectiveFunction::value(const DynamicVector<RealType>& x) {
70 info_->getSnapshotManager()->advance();
71
72 if (setCoor(x) == 0) {
73 shake_->constraintR();
74 forceMan_->calcForces();
75 if (hasFlucQ_) fqConstraints_->applyConstraints();
76 shake_->constraintF();
77 return thermo.getPotential();
78 } else {
79 // The deformation was too large, so return an infinite potential
80 return std::numeric_limits<RealType>::infinity();
81 }
82 }
83
84 void BoxObjectiveFunction::gradient(DynamicVector<RealType>& grad,
85 const DynamicVector<RealType>& x) {
86 info_->getSnapshotManager()->advance();
87 if (setCoor(x) == 0) {
88 shake_->constraintR();
89 forceMan_->calcForces();
90 if (hasFlucQ_) fqConstraints_->applyConstraints();
91 shake_->constraintF();
92 getGrad(grad);
93 } else {
94 // The deformation was too large, so return an infinite gradient:
95 for (int j = 0; j < 6; j++)
96 grad[j] = std::numeric_limits<RealType>::infinity();
97 }
98 }
99
101 DynamicVector<RealType>& grad, const DynamicVector<RealType>& x) {
102 info_->getSnapshotManager()->advance();
103 if (setCoor(x) == 0) {
104 shake_->constraintR();
105 forceMan_->calcForces();
106 if (hasFlucQ_) fqConstraints_->applyConstraints();
107 shake_->constraintF();
108 getGrad(grad);
109 return thermo.getPotential();
110 ;
111 } else {
112 // The deformation was too large, so return infinite
113 // potential and gradient
114 for (int j = 0; j < 6; j++)
115 grad[j] = std::numeric_limits<RealType>::infinity();
116 return std::numeric_limits<RealType>::infinity();
117 }
118 }
119
120 int BoxObjectiveFunction::setCoor(const DynamicVector<RealType>& x) {
121 Vector3d posO;
122 Vector3d posN;
123 Vector3d delta;
124 SimInfo::MoleculeIterator miter;
125 Molecule* mol;
126 Mat3x3d eta(0.0);
127 Mat3x3d eps(0.0);
128 Mat3x3d y(0.0);
129 Mat3x3d test(0.0);
130 RealType norm;
131
132 // η is the Lagrangian strain tensor:
133 eta.setupVoigtTensor(x[0], x[1], x[2], x[3] / 2., x[4] / 2., x[5] / 2.);
134
135 // Make sure the deformation isn't too large:
136 if (eta.frobeniusNorm() > 0.7) {
137 // Deformation is too large, return an error condition:
138 return -1;
139 }
140
141 // Find the physical strain tensor, ε, from the Lagrangian strain, η:
142 // η = ε + 0.5 * ε^2
143 norm = 1.0;
144 eps = eta;
145 while (norm > 1.0e-10) {
146 y = eta - eps * eps / 2.0;
147 test = y - eps;
148 norm = test.frobeniusNorm();
149 eps = y;
150 }
151 deformation_ = SquareMatrix3<RealType>::identity() + eps;
152
153 int index = 0;
154
155 for (mol = info_->beginMolecule(miter); mol != NULL;
156 mol = info_->nextMolecule(miter)) {
157 posO = refPos_[index++];
158 posN = mol->getCom();
159 delta = deformation_ * posO - posN;
160 mol->moveCom(delta);
161 }
162
163 Mat3x3d Hmat = deformation_ * refHmat_;
165 return 0;
166 }
167
168 void BoxObjectiveFunction::getGrad(DynamicVector<RealType>& grad) {
169 Mat3x3d pressureTensor;
170 Vector<RealType, 6> lstress(0.0);
171
172 // Find the Lagragian stress tensor, τ, from the physical
173 // stress tensor, σ, that was computed from the pressureTensor
174 // in this code.
175 // τ = det(1+ε) (1+ε)^−1 · σ · (1+ε)^−1
176 // (Note that 1+ε is the deformation tensor computed above.)
177
178 Mat3x3d idm = deformation_.inverse();
179 RealType ddm = deformation_.determinant();
180
181 pressureTensor = thermo.getPressureTensor();
182 pressureTensor.negate();
183 pressureTensor *= Constants::elasticConvert;
184
185 Mat3x3d tao = idm * (pressureTensor * idm);
186 tao *= ddm;
187
188 lstress = tao.toVoigtTensor();
189 RealType V = thermo.getVolume();
190
191 for (int j = 0; j < 6; j++) {
192 grad[j] = V * lstress[j];
193 }
194 }
195
196 DynamicVector<RealType> BoxObjectiveFunction::setInitialCoords() {
197 DynamicVector<RealType> xinit(6, 0.0);
198 SimInfo::MoleculeIterator miter;
199 Molecule* mol;
200
202 refHmat_ = snap->getHmat();
203 V0_ = snap->getVolume();
204
205 refPos_.clear();
206 for (mol = info_->beginMolecule(miter); mol != NULL;
207 mol = info_->nextMolecule(miter)) {
208 refPos_.push_back(mol->getCom());
209 }
210
211 return xinit;
212 }
213} // 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
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:341
Vector3d getCom()
Returns the current center of mass position of this molecule.
Definition Molecule.cpp:298
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:93
Molecule * beginMolecule(MoleculeIterator &i)
Returns the first molecule in this SimInfo and intialize the iterator.
Definition SimInfo.cpp:240
Molecule * nextMolecule(MoleculeIterator &i)
Returns the next avaliable Molecule based on the iterator.
Definition SimInfo.cpp:245
SnapshotManager * getSnapshotManager()
Returns the snapshot manager.
Definition SimInfo.hpp:248
The Snapshot class is a repository storing dynamic data during a Simulation.
Definition Snapshot.hpp:147
Mat3x3d getHmat()
Returns the H-Matrix.
Definition Snapshot.cpp:214
void setHmat(const Mat3x3d &m)
Sets the H-Matrix.
Definition Snapshot.cpp:217
Snapshot * getCurrentSnapshot()
Returns the pointer of current snapshot.
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()
Returns an identity matrix.
Mat3x3d getPressureTensor()
gives the pressure tensor in amu*fs^-2*Ang^-1
Definition Thermo.cpp:443
This basic Periodic Table class was originally taken from the data.cpp file in OpenBabel.