MRMD 0.4.0
Multi Resolution Molecular Dynamics
Loading...
Searching...
No Matches
Shake.hpp
Go to the documentation of this file.
1// Copyright 2024 Sebastian Eibl
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#pragma once
16
17#include "assert/assert.hpp"
18#include "data/Atoms.hpp"
19#include "data/Bond.hpp"
20#include "data/Molecules.hpp"
21#include "datatypes.hpp"
22#include "util/Kokkos_grow.hpp"
23#include "util/math.hpp"
24
25namespace mrmd
26{
27namespace action
28{
29namespace impl
30{
35class Shake
36{
37private:
40 data::Atoms::force_t::atomic_access_slice force_;
42 VectorView updatedPos_;
43
44 real_t dtv_;
45 real_t dtf_;
46
47public:
49 {
50 };
52 {
53 };
55 {
56 };
57
58 KOKKOS_INLINE_FUNCTION
59 void enforceVelocityConstraint(const idx_t idx, const idx_t jdx, const real_t eqDistance) const
60 {
62 real_t dist[3];
63 dist[0] = pos_(idx, 0) - pos_(jdx, 0);
64 dist[1] = pos_(idx, 1) - pos_(jdx, 1);
65 dist[2] = pos_(idx, 2) - pos_(jdx, 2);
67 auto distSq = util::dot3(dist, dist);
68
69 auto invMassI = 1_r / mass_(idx);
70 auto invMassJ = 1_r / mass_(jdx);
71 auto reducedMass = 1_r / (invMassI + invMassJ);
72
73 real_t relVel[3];
74 relVel[0] = vel_(idx, 0) - vel_(jdx, 0);
75 relVel[1] = vel_(idx, 1) - vel_(jdx, 1);
76 relVel[2] = vel_(idx, 2) - vel_(jdx, 2);
77
78 auto factor = util::dot3(relVel, dist) / distSq * reducedMass;
79
80 vel_(idx, 0) -= factor * dist[0] * invMassI;
81 vel_(idx, 1) -= factor * dist[1] * invMassI;
82 vel_(idx, 2) -= factor * dist[2] * invMassI;
83
84 vel_(jdx, 0) += factor * dist[0] * invMassJ;
85 vel_(jdx, 1) += factor * dist[1] * invMassJ;
86 vel_(jdx, 2) += factor * dist[2] * invMassJ;
87 }
88
89 KOKKOS_INLINE_FUNCTION
91 const idx_t jdx,
92 const real_t eqDistance) const
93 {
95 real_t dist[3];
96 dist[0] = pos_(idx, 0) - pos_(jdx, 0);
97 dist[1] = pos_(idx, 1) - pos_(jdx, 1);
98 dist[2] = pos_(idx, 2) - pos_(jdx, 2);
100 real_t distSq = util::dot3(dist, dist);
101
103 real_t updatedDist[3];
104 updatedDist[0] = updatedPos_(idx, 0) - updatedPos_(jdx, 0);
105 updatedDist[1] = updatedPos_(idx, 1) - updatedPos_(jdx, 1);
106 updatedDist[2] = updatedPos_(idx, 2) - updatedPos_(jdx, 2);
108 real_t updatedDistSq = util::dot3(updatedDist, updatedDist);
109
110 auto invMassI = 1_r / mass_(idx);
111 auto invMassJ = 1_r / mass_(jdx);
112
114 real_t a = util::sqr(invMassI + invMassJ) * distSq;
115 real_t b = 2_r * (invMassI + invMassJ) * util::dot3(updatedDist, dist);
116 real_t c = updatedDistSq - util::sqr(eqDistance);
117
118 real_t determinant = b * b - 4_r * a * c;
119 MRMD_DEVICE_ASSERT_GREATER(determinant, 1e-8);
120 determinant = Kokkos::max(0_r, determinant); // ensure positive determinant
121
122 // solve for lambda
123 auto lambda1 = (-b + std::sqrt(determinant)) / (2_r * a);
124 auto lambda2 = (-b - std::sqrt(determinant)) / (2_r * a);
125 auto lambda = std::abs(lambda1) < std::abs(lambda2) ? lambda1 : lambda2;
126
127 lambda /= dtf_;
128
129 force_(idx, 0) += lambda * dist[0];
130 force_(idx, 1) += lambda * dist[1];
131 force_(idx, 2) += lambda * dist[2];
132
133 force_(jdx, 0) -= lambda * dist[0];
134 force_(jdx, 1) -= lambda * dist[1];
135 force_(jdx, 2) -= lambda * dist[2];
136 }
137
138 KOKKOS_INLINE_FUNCTION
139 void operator()(UnconstraintUpdate, const idx_t idx) const
140 {
141 auto dtfm = dtf_ / mass_(idx);
142 updatedPos_(idx, 0) = pos_(idx, 0) + dtv_ * vel_(idx, 0) + dtfm * force_(idx, 0);
143 updatedPos_(idx, 1) = pos_(idx, 1) + dtv_ * vel_(idx, 1) + dtfm * force_(idx, 1);
144 updatedPos_(idx, 2) = pos_(idx, 2) + dtv_ * vel_(idx, 2) + dtfm * force_(idx, 2);
145 }
146
147 Shake(data::Atoms& atoms, const real_t& dt)
148 {
149 pos_ = atoms.getPos();
150 vel_ = atoms.getVel();
151 force_ = atoms.getForce();
152 mass_ = atoms.getMass();
153
154 util::grow(updatedPos_, idx_c(atoms.numLocalAtoms + atoms.numGhostAtoms));
155
156 dtv_ = dt;
157 dtf_ = 0.5_r * dt * dt;
158 }
159};
160} // namespace impl
161
163{
164private:
165 idx_t atomsPerMolecule_;
166 data::BondView bonds_;
167
168 idx_t numConstraintIterations_;
169
170public:
172 data::Atoms& atoms,
173 const real_t dt)
174 {
175 impl::Shake shake(atoms, dt);
176
177 for (int iteration = 0; iteration < numConstraintIterations_; ++iteration)
178 {
179 auto policy = Kokkos::RangePolicy<impl::Shake::UnconstraintUpdate>(
180 0, atoms.numLocalAtoms + atoms.numGhostAtoms);
181 Kokkos::parallel_for("Shake::UnconstraintUpdate", policy, shake);
182 Kokkos::fence();
183
184 auto moleculesAtomsOffset = molecules.getAtomsOffset();
185 auto moleculesNumAtoms = molecules.getNumAtoms();
186 auto bonds = bonds_;
187 auto applyBondsPolicy = Kokkos::RangePolicy<>(0, molecules.numLocalMolecules);
188 auto kernel = KOKKOS_LAMBDA(idx_t moleculeIdx)
189 {
190 auto atomsStart = moleculesAtomsOffset(moleculeIdx);
191 auto numAtoms = moleculesNumAtoms(moleculeIdx);
192 for (idx_t bondIdx = 0; bondIdx < bonds.extent(0); ++bondIdx)
193 {
194 MRMD_DEVICE_ASSERT_LESS(bonds(bondIdx).idx,
195 numAtoms,
196 "not enough atoms in molecule to satisfy bond");
197 MRMD_DEVICE_ASSERT_LESS(bonds(bondIdx).jdx,
198 numAtoms,
199 "not enough atoms in molecule to satisfy bond");
200 shake.enforcePositionalConstraint(atomsStart + bonds(bondIdx).idx,
201 atomsStart + bonds(bondIdx).jdx,
202 bonds(bondIdx).eqDistance);
203 }
204 };
205
206 Kokkos::parallel_for(
207 "MoleculeConstraints::enforcePositionalConstraints", applyBondsPolicy, kernel);
208 Kokkos::fence();
209 }
210 }
211
213 {
214 impl::Shake shake(atoms, dt);
215
216 auto moleculesAtomsOffset = molecules.getAtomsOffset();
217 auto moleculesNumAtoms = molecules.getNumAtoms();
218 auto bonds = bonds_;
219 auto applyBondsPolicy = Kokkos::RangePolicy<>(0, molecules.numLocalMolecules);
220 auto kernel = KOKKOS_LAMBDA(idx_t moleculeIdx)
221 {
222 auto atomsStart = moleculesAtomsOffset(moleculeIdx);
223 auto numAtoms = moleculesNumAtoms(moleculeIdx);
224 for (idx_t bondIdx = 0; bondIdx < bonds.extent(0); ++bondIdx)
225 {
227 bonds(bondIdx).idx, numAtoms, "not enough atoms in molecule to satisfy bond");
229 bonds(bondIdx).jdx, numAtoms, "not enough atoms in molecule to satisfy bond");
230 shake.enforceVelocityConstraint(atomsStart + bonds(bondIdx).idx,
231 atomsStart + bonds(bondIdx).jdx,
232 bonds(bondIdx).eqDistance);
233 }
234 };
235 Kokkos::parallel_for(
236 "MoleculeConstraints::enforceVelocityConstraints", applyBondsPolicy, kernel);
237 Kokkos::fence();
238 }
239
240 void setConstraints(const data::BondView& bonds) { bonds_ = bonds; }
241 void setConstraints(const data::BondView::host_mirror_type& bonds)
242 {
243 Kokkos::resize(bonds_, bonds.extent(0));
244 Kokkos::deep_copy(bonds_, bonds);
245 }
246
247 MoleculeConstraints(idx_t atomsPerMolecule, idx_t numConstraintIterations)
248 : atomsPerMolecule_(atomsPerMolecule), numConstraintIterations_(numConstraintIterations)
249 {
250 }
251};
252
253} // namespace action
254} // namespace mrmd
Definition Shake.hpp:163
void enforceVelocityConstraints(data::Molecules &molecules, data::Atoms &atoms, const real_t dt)
Definition Shake.hpp:212
void enforcePositionalConstraints(data::Molecules &molecules, data::Atoms &atoms, const real_t dt)
Definition Shake.hpp:171
MoleculeConstraints(idx_t atomsPerMolecule, idx_t numConstraintIterations)
Definition Shake.hpp:247
void setConstraints(const data::BondView::host_mirror_type &bonds)
Definition Shake.hpp:241
void setConstraints(const data::BondView &bonds)
Definition Shake.hpp:240
SHAKE algorithm (DOI: 10.1016/0021-9991(77)90098-5) RATTLE algorithm (DOI: 10.1016/0021-9991(83)90014...
Definition Shake.hpp:36
KOKKOS_INLINE_FUNCTION void enforceVelocityConstraint(const idx_t idx, const idx_t jdx, const real_t eqDistance) const
Definition Shake.hpp:59
KOKKOS_INLINE_FUNCTION void operator()(UnconstraintUpdate, const idx_t idx) const
Definition Shake.hpp:139
Shake(data::Atoms &atoms, const real_t &dt)
Definition Shake.hpp:147
KOKKOS_INLINE_FUNCTION void enforcePositionalConstraint(const idx_t idx, const idx_t jdx, const real_t eqDistance) const
Definition Shake.hpp:90
Data structure for storing information about atoms on the host and the device.
Definition Atoms.hpp:35
KOKKOS_FORCEINLINE_FUNCTION vel_t getVel() const
Definition Atoms.hpp:65
idx_t numLocalAtoms
Definition Atoms.hpp:120
idx_t numGhostAtoms
Definition Atoms.hpp:121
KOKKOS_FORCEINLINE_FUNCTION pos_t getPos() const
Definition Atoms.hpp:64
typename AtomsT::template member_slice_type< MASS > mass_t
Definition Atoms.hpp:60
KOKKOS_FORCEINLINE_FUNCTION force_t getForce() const
Definition Atoms.hpp:66
typename AtomsT::template member_slice_type< POS > pos_t
Definition Atoms.hpp:56
KOKKOS_FORCEINLINE_FUNCTION charge_t getMass() const
Definition Atoms.hpp:68
typename AtomsT::template member_slice_type< VEL > vel_t
Definition Atoms.hpp:57
Definition Molecules.hpp:29
KOKKOS_FORCEINLINE_FUNCTION atoms_offset_t getAtomsOffset() const
Definition Molecules.hpp:67
KOKKOS_FORCEINLINE_FUNCTION num_atoms_t getNumAtoms() const
Definition Molecules.hpp:68
idx_t numLocalMolecules
Definition Molecules.hpp:120
#define MRMD_DEVICE_ASSERT_GREATER(...)
Definition device.hpp:471
#define MRMD_DEVICE_ASSERT_LESS(...)
Definition device.hpp:472
Kokkos::View< Bond * > BondView
Definition Bond.hpp:30
KOKKOS_INLINE_FUNCTION real_t sqr(const real_t &sqr)
Definition math.hpp:29
void grow(Kokkos::View< T, P... > &view, idx_t size, real_t safetyMargin=1.1_r)
Definition Kokkos_grow.hpp:25
KOKKOS_INLINE_FUNCTION real_t dot3(real_t const *const a, real_t const *const b)
Definition math.hpp:24
Definition BerendsenBarostat.cpp:18
KOKKOS_INLINE_FUNCTION constexpr idx_t idx_c(const T &val)
Definition datatypes.hpp:93
Kokkos::View< real_t *[3]> VectorView
Definition datatypes.hpp:163
int64_t idx_t
Definition datatypes.hpp:91
double real_t
Definition datatypes.hpp:99