MRMD 0.4.0
Multi Resolution Molecular Dynamics
Loading...
Searching...
No Matches
SPC.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 "Coulomb.hpp"
18#include "LennardJones.hpp"
19#include "Shake.hpp"
20#include "data/Atoms.hpp"
21#include "data/Histogram.hpp"
22#include "datatypes.hpp"
23#include "util/angle.hpp"
24
25namespace mrmd::action::impl
26{
27struct Energy
28{
29 real_t LJ = 0_r;
31
32 Energy() = default;
33 Energy(const Energy& rhs) = default;
34
35 KOKKOS_INLINE_FUNCTION
37 {
38 LJ += src.LJ;
39 coulomb += src.coulomb;
40 return *this;
41 }
42};
43} // namespace mrmd::action::impl
44
45namespace Kokkos
46{ // reduction identity must be defined in Kokkos namespace
47template <>
48struct reduction_identity<mrmd::action::impl::Energy>
49{
50 KOKKOS_FORCEINLINE_FUNCTION static mrmd::action::impl::Energy sum()
51 {
53 }
54};
55} // namespace Kokkos
56
57namespace mrmd
58{
59namespace action
60{
61class SPC
62{
63private:
65 impl::Coulomb coulomb_;
66 real_t rcSqr_ = 0_r;
67
68 data::Molecules::pos_t moleculesPos_;
69 data::Molecules::force_t::atomic_access_slice moleculesForce_;
70 data::Molecules::lambda_t moleculesLambda_;
71 data::Molecules::modulated_lambda_t moleculesModulatedLambda_;
72 data::Molecules::grad_lambda_t moleculesGradLambda_;
73 data::Molecules::atoms_offset_t moleculesAtomsOffset_;
74 data::Molecules::num_atoms_t moleculesNumAtoms_;
75
76 data::Atoms::pos_t atomsPos_;
77 data::Atoms::force_t::atomic_access_slice atomsForce_;
78 data::Atoms::charge_t atomsCharge_;
79
80 data::Histogram compensationEnergy_ = data::Histogram("compensationEnergy", 0_r, 1_r, 200);
81 ScalarScatterView compensationEnergyScatter_;
82
83 data::Histogram compensationEnergyCounter_ =
84 data::Histogram("compensationEnergyCounter", 0_r, 1_r, 200);
85
86 data::Histogram meanCompensationEnergy_ =
87 data::Histogram("meanCompensationEnergy", 0_r, 1_r, 200);
88
89 bool isDriftCompensationSamplingRun_ = false;
90
91 HalfVerletList verletList_;
92
93 idx_t runCounter_ = 0;
94
95 data::BondView::host_mirror_type bonds_;
96
97public:
100
101 auto getEnergyLJ() const { return sumEnergyLJ_; }
102 auto getEnergyCoulomb() const { return sumEnergyCoulomb_; }
103
104 static constexpr real_t massO = 15.999_r;
105 static constexpr real_t chargeO = -0.82_r;
106
107 static constexpr real_t massH = 1.008_r;
108 static constexpr real_t chargeH = +0.41_r;
109
110 // LJ parameters for O-O interaction
111 // DOI: 10.1021/j100308a038
112 static constexpr real_t sigma = 0.31655578901998815_r;
113 static constexpr real_t epsilon = 0.6501695808187486_r;
114 static constexpr real_t rc = 1.2_r;
115
116 // Coulomb DSF parameters
117 static constexpr real_t alpha = 2.0_r;
118
120 static constexpr real_t eqDistanceHO = 0.1_r;
121 static constexpr real_t angleHOH = util::degToRad(109.47_r);
122 const real_t eqDistanceHH = eqDistanceHO * std::sqrt(2_r - 2_r * std::cos(angleHOH));
123
126
127 const auto& getMeanCompensationEnergy() const { return meanCompensationEnergy_; }
128
130 {
131 };
133 {
134 };
135
142 KOKKOS_INLINE_FUNCTION void operator()(CalcInteractions,
143 const idx_t& alpha,
144 impl::Energy& sumEnergy) const
145 {
146 const auto numNeighbors = idx_c(HalfNeighborList::numNeighbor(verletList_, alpha));
147 for (idx_t n = 0; n < numNeighbors; ++n)
148 {
150 const idx_t beta = idx_c(HalfNeighborList::getNeighbor(verletList_, alpha, n));
151 assert(0 <= beta);
152
154 const auto startAtomsAlpha = moleculesAtomsOffset_(alpha);
156 const auto endAtomsAlpha = startAtomsAlpha + moleculesNumAtoms_(alpha);
157 assert(0 <= startAtomsAlpha);
158 assert(startAtomsAlpha < endAtomsAlpha);
159
161 const auto startAtomsBeta = moleculesAtomsOffset_(beta);
163 const auto endAtomsBeta = startAtomsBeta + moleculesNumAtoms_(beta);
164 assert(0 <= startAtomsBeta);
165 assert(startAtomsBeta < endAtomsBeta);
166
167 // LJ interaction between oxygen atoms
168 real_t posTmp[3];
169 posTmp[0] = atomsPos_(startAtomsAlpha, 0);
170 posTmp[1] = atomsPos_(startAtomsAlpha, 1);
171 posTmp[2] = atomsPos_(startAtomsAlpha, 2);
172
173 real_t dx[3];
174 dx[0] = posTmp[0] - atomsPos_(startAtomsBeta, 0);
175 dx[1] = posTmp[1] - atomsPos_(startAtomsBeta, 1);
176 dx[2] = posTmp[2] - atomsPos_(startAtomsBeta, 2);
177
178 const auto distSqr = util::dot3(dx, dx);
179
180 if (distSqr < rcSqr_)
181 {
182 auto forceAndVirial = LJ_.computeForceAndEnergy(distSqr, 0);
183 sumEnergy.LJ += forceAndVirial.energy;
184
185 atomsForce_(startAtomsBeta, 0) -= dx[0] * forceAndVirial.forceFactor;
186 atomsForce_(startAtomsBeta, 1) -= dx[1] * forceAndVirial.forceFactor;
187 atomsForce_(startAtomsBeta, 2) -= dx[2] * forceAndVirial.forceFactor;
188
189 atomsForce_(startAtomsAlpha, 0) += dx[0] * forceAndVirial.forceFactor;
190 atomsForce_(startAtomsAlpha, 1) += dx[1] * forceAndVirial.forceFactor;
191 atomsForce_(startAtomsAlpha, 2) += dx[2] * forceAndVirial.forceFactor;
192 }
193
195 for (idx_t idx = startAtomsAlpha; idx < endAtomsAlpha; ++idx)
196 {
197 real_t posTmp[3];
198 posTmp[0] = atomsPos_(idx, 0);
199 posTmp[1] = atomsPos_(idx, 1);
200 posTmp[2] = atomsPos_(idx, 2);
201
202 auto q1 = atomsCharge_(idx);
203
204 // avoid atomic force contributions to idx in innermost loop
205 real_t forceTmpIdx[3] = {0_r, 0_r, 0_r};
206
207 for (idx_t jdx = startAtomsBeta; jdx < endAtomsBeta; ++jdx)
208 {
209 auto q2 = atomsCharge_(jdx);
210
211 real_t dx[3];
212 dx[0] = posTmp[0] - atomsPos_(jdx, 0);
213 dx[1] = posTmp[1] - atomsPos_(jdx, 1);
214 dx[2] = posTmp[2] - atomsPos_(jdx, 2);
215
216 const auto distSqr = util::dot3(dx, dx);
217
218 if (distSqr > rcSqr_) continue;
219
220 auto ffactor = coulomb_.computeForce(distSqr, q1, q2);
221 sumEnergy.coulomb += coulomb_.computeEnergy(distSqr, q1, q2);
222
223 forceTmpIdx[0] += dx[0] * ffactor;
224 forceTmpIdx[1] += dx[1] * ffactor;
225 forceTmpIdx[2] += dx[2] * ffactor;
226
227 atomsForce_(jdx, 0) -= dx[0] * ffactor;
228 atomsForce_(jdx, 1) -= dx[1] * ffactor;
229 atomsForce_(jdx, 2) -= dx[2] * ffactor;
230 }
231
232 atomsForce_(idx, 0) += forceTmpIdx[0];
233 atomsForce_(idx, 1) += forceTmpIdx[1];
234 atomsForce_(idx, 2) += forceTmpIdx[2];
235 }
236 }
237 }
238
240 {
241 MoleculeConstraints moleculeConstraints(3, 20);
242 moleculeConstraints.setConstraints(bonds_);
243 moleculeConstraints.enforcePositionalConstraints(molecules, atoms, dt);
244 }
245
247 {
248 MoleculeConstraints moleculeConstraints(3, 20);
249 moleculeConstraints.setConstraints(bonds_);
250 moleculeConstraints.enforceVelocityConstraints(molecules, atoms, dt);
251 }
252
253 void applyForces(data::Molecules& molecules, HalfVerletList& verletList, data::Atoms& atoms)
254 {
255 moleculesPos_ = molecules.getPos();
256 moleculesForce_ = molecules.getForce();
257 moleculesLambda_ = molecules.getLambda();
258 moleculesModulatedLambda_ = molecules.getModulatedLambda();
259 moleculesGradLambda_ = molecules.getGradLambda();
260 moleculesAtomsOffset_ = molecules.getAtomsOffset();
261 moleculesNumAtoms_ = molecules.getNumAtoms();
262 atomsPos_ = atoms.getPos();
263 atomsForce_ = atoms.getForce();
264 atomsCharge_ = atoms.getCharge();
265 verletList_ = verletList;
266
267 isDriftCompensationSamplingRun_ = runCounter_ % COMPENSATION_ENERGY_SAMPLING_INTERVAL == 0;
268
269 // compensationEnergyScatter_ = ScalarScatterView(compensationEnergy_.data);
270
271 auto energy = impl::Energy();
272 auto policy = Kokkos::RangePolicy<CalcInteractions>(0, molecules.numLocalMolecules);
273 Kokkos::parallel_reduce(
274 "SPC::applyForces", policy, *this, Kokkos::Sum<impl::Energy>(energy));
275
276 // Kokkos::Experimental::contribute(compensationEnergy_.data,
277 // compensationEnergyScatter_);
278
279 Kokkos::fence();
280
281 // if (runCounter_ % compensationEnergyUpdateInveral == 0)
282 // updateMeanCompensationEnergy(
283 // compensationEnergy_, compensationEnergyCounter_, meanCompensationEnergy_,
284 // 10_r);
285 //
286 // ++runCounter_;
287
288 sumEnergyLJ_ = energy.LJ;
289 sumEnergyCoulomb_ = energy.coulomb;
290 }
291
292 KOKKOS_INLINE_FUNCTION void operator()(BondEnergy, const idx_t& alpha, real_t& sumEnergy) const
293 {
295 const auto startAtomsAlpha = moleculesAtomsOffset_(alpha);
296 assert(0 <= startAtomsAlpha);
297
298 auto idxO = startAtomsAlpha;
299 auto idxH0 = startAtomsAlpha + 1;
300 auto idxH1 = startAtomsAlpha + 2;
301
302 real_t dx[3];
303 real_t dist = 0_r;
304
305 dx[0] = atomsPos_(idxO, 0) - atomsPos_(idxH0, 0);
306 dx[1] = atomsPos_(idxO, 1) - atomsPos_(idxH0, 1);
307 dx[2] = atomsPos_(idxO, 2) - atomsPos_(idxH0, 2);
308 dist = std::sqrt(util::dot3(dx, dx));
309 sumEnergy += util::sqr(dist - eqDistanceHO);
310
311 dx[0] = atomsPos_(idxO, 0) - atomsPos_(idxH1, 0);
312 dx[1] = atomsPos_(idxO, 1) - atomsPos_(idxH1, 1);
313 dx[2] = atomsPos_(idxO, 2) - atomsPos_(idxH1, 2);
314 dist = std::sqrt(util::dot3(dx, dx));
315 sumEnergy += util::sqr(dist - eqDistanceHO);
316
317 dx[0] = atomsPos_(idxH0, 0) - atomsPos_(idxH1, 0);
318 dx[1] = atomsPos_(idxH0, 1) - atomsPos_(idxH1, 1);
319 dx[2] = atomsPos_(idxH0, 2) - atomsPos_(idxH1, 2);
320 dist = std::sqrt(util::dot3(dx, dx));
321 sumEnergy += util::sqr(dist - eqDistanceHH);
322 }
323
325 data::Atoms& atoms,
326 const real_t& harmonicPreFactor)
327 {
328 moleculesPos_ = molecules.getPos();
329 moleculesForce_ = molecules.getForce();
330 moleculesLambda_ = molecules.getLambda();
331 moleculesModulatedLambda_ = molecules.getModulatedLambda();
332 moleculesGradLambda_ = molecules.getGradLambda();
333 moleculesAtomsOffset_ = molecules.getAtomsOffset();
334 moleculesNumAtoms_ = molecules.getNumAtoms();
335 atomsPos_ = atoms.getPos();
336 atomsForce_ = atoms.getForce();
337 atomsCharge_ = atoms.getCharge();
338
339 real_t energy = 0_r;
340 auto policy = Kokkos::RangePolicy<BondEnergy>(
341 0, molecules.numLocalMolecules + molecules.numGhostMolecules);
342 Kokkos::parallel_reduce("SPC::calcHarmonicPotential", policy, *this, energy);
343
344 Kokkos::fence();
345
346 return harmonicPreFactor * energy / real_c(atoms.numLocalAtoms + atoms.numGhostAtoms);
347 }
348
350 : LJ_({0.7_r * sigma}, {rc}, {sigma}, {epsilon}, 1, true),
351 coulomb_(),
352 rcSqr_(rc * rc),
353 bonds_("bonds", 3)
354 {
355 bonds_(0).idx = 0;
356 bonds_(0).jdx = 1;
357 bonds_(0).eqDistance = eqDistanceHO;
358 bonds_(1).idx = 0;
359 bonds_(1).jdx = 2;
360 bonds_(1).eqDistance = eqDistanceHO;
361 bonds_(2).idx = 1;
362 bonds_(2).jdx = 2;
363 bonds_(2).eqDistance = eqDistanceHH;
364 }
365};
366} // namespace action
367} // 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
void setConstraints(const data::BondView &bonds)
Definition Shake.hpp:240
Definition SPC.hpp:62
static constexpr idx_t COMPENSATION_ENERGY_SAMPLING_INTERVAL
Definition SPC.hpp:124
SPC()
Definition SPC.hpp:349
static constexpr real_t massH
unit: g/mol
Definition SPC.hpp:107
static constexpr real_t rc
unit: nm
Definition SPC.hpp:114
void applyForces(data::Molecules &molecules, HalfVerletList &verletList, data::Atoms &atoms)
Definition SPC.hpp:253
void enforceVelocityConstraints(data::Molecules &molecules, data::Atoms &atoms, real_t dt)
Definition SPC.hpp:246
auto getEnergyLJ() const
Definition SPC.hpp:101
auto getEnergyCoulomb() const
Definition SPC.hpp:102
static constexpr real_t chargeH
Definition SPC.hpp:108
const real_t eqDistanceHH
Definition SPC.hpp:122
real_t sumEnergyLJ_
Definition SPC.hpp:98
static constexpr idx_t COMPENSATION_ENERGY_UPDATE_INTERVAL
Definition SPC.hpp:125
KOKKOS_INLINE_FUNCTION void operator()(CalcInteractions, const idx_t &alpha, impl::Energy &sumEnergy) const
Loop over molecules.
Definition SPC.hpp:142
void enforcePositionalConstraints(data::Molecules &molecules, data::Atoms &atoms, real_t dt)
Definition SPC.hpp:239
real_t calcBondEnergy(data::Molecules &molecules, data::Atoms &atoms, const real_t &harmonicPreFactor)
Definition SPC.hpp:324
static constexpr real_t sigma
unit: nm
Definition SPC.hpp:112
static constexpr real_t angleHOH
unit: radians
Definition SPC.hpp:121
static constexpr real_t chargeO
Definition SPC.hpp:105
static constexpr real_t epsilon
unit: kJ / mol
Definition SPC.hpp:113
static constexpr real_t massO
unit: g/mol
Definition SPC.hpp:104
const auto & getMeanCompensationEnergy() const
Definition SPC.hpp:127
static constexpr real_t alpha
unit: 1/nm
Definition SPC.hpp:117
static constexpr real_t eqDistanceHO
unit: nm, equilibirum distance between hydrogen and oxygen
Definition SPC.hpp:120
real_t sumEnergyCoulomb_
Definition SPC.hpp:99
KOKKOS_INLINE_FUNCTION void operator()(BondEnergy, const idx_t &alpha, real_t &sumEnergy) const
Definition SPC.hpp:292
KOKKOS_INLINE_FUNCTION ForceAndEnergy computeForceAndEnergy(const real_t &distSqr, const idx_t &typeIdx) const
Definition LennardJones.hpp:53
Definition Coulomb.hpp:28
KOKKOS_INLINE_FUNCTION real_t computeEnergy(const real_t &distSqr, const real_t q1, const real_t q2) const
Definition Coulomb.hpp:38
KOKKOS_INLINE_FUNCTION real_t computeForce(const real_t &distSqr, const real_t q1, const real_t q2) const
Definition Coulomb.hpp:31
Data structure for storing information about atoms on the host and the device.
Definition Atoms.hpp:35
idx_t numLocalAtoms
Definition Atoms.hpp:120
idx_t numGhostAtoms
Definition Atoms.hpp:121
KOKKOS_FORCEINLINE_FUNCTION charge_t getCharge() const
Definition Atoms.hpp:69
KOKKOS_FORCEINLINE_FUNCTION pos_t getPos() const
Definition Atoms.hpp:64
KOKKOS_FORCEINLINE_FUNCTION force_t getForce() const
Definition Atoms.hpp:66
typename AtomsT::template member_slice_type< CHARGE > charge_t
Definition Atoms.hpp:61
typename AtomsT::template member_slice_type< POS > pos_t
Definition Atoms.hpp:56
Definition Molecules.hpp:29
typename MoleculesT::template member_slice_type< GRAD_LAMBDA > grad_lambda_t
Definition Molecules.hpp:54
KOKKOS_FORCEINLINE_FUNCTION atoms_offset_t getAtomsOffset() const
Definition Molecules.hpp:67
KOKKOS_FORCEINLINE_FUNCTION num_atoms_t getNumAtoms() const
Definition Molecules.hpp:68
typename MoleculesT::template member_slice_type< MODULATED_LAMBDA > modulated_lambda_t
Definition Molecules.hpp:53
KOKKOS_FORCEINLINE_FUNCTION force_t getForce() const
Definition Molecules.hpp:59
KOKKOS_FORCEINLINE_FUNCTION pos_t getPos() const
Definition Molecules.hpp:58
typename MoleculesT::template member_slice_type< LAMBDA > lambda_t
Definition Molecules.hpp:52
KOKKOS_FORCEINLINE_FUNCTION modulated_lambda_t getModulatedLambda() const
Definition Molecules.hpp:62
typename MoleculesT::template member_slice_type< NUM_ATOMS > num_atoms_t
Definition Molecules.hpp:56
idx_t numGhostMolecules
Definition Molecules.hpp:121
KOKKOS_FORCEINLINE_FUNCTION lambda_t getLambda() const
Definition Molecules.hpp:61
typename MoleculesT::template member_slice_type< ATOMS_OFFSET > atoms_offset_t
Definition Molecules.hpp:55
idx_t numLocalMolecules
Definition Molecules.hpp:120
KOKKOS_FORCEINLINE_FUNCTION grad_lambda_t getGradLambda() const
Definition Molecules.hpp:66
typename MoleculesT::template member_slice_type< POS > pos_t
Definition Molecules.hpp:50
Definition SPC.hpp:46
Definition Coulomb.hpp:26
KOKKOS_INLINE_FUNCTION constexpr real_t degToRad(const real_t &grd)
converts degree to radians
Definition angle.hpp:28
KOKKOS_INLINE_FUNCTION real_t sqr(const real_t &sqr)
Definition math.hpp:29
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
Cabana::VerletList< Kokkos::DefaultExecutionSpace::memory_space, Cabana::HalfNeighborTag, Cabana::VerletLayout2D, Cabana::TeamOpTag > HalfVerletList
Definition datatypes.hpp:187
int64_t idx_t
Definition datatypes.hpp:91
Kokkos::Experimental::ScatterView< real_t * > ScalarScatterView
Definition datatypes.hpp:160
double real_t
Definition datatypes.hpp:99
KOKKOS_INLINE_FUNCTION constexpr real_t real_c(T t)
Definition datatypes.hpp:114
static KOKKOS_FORCEINLINE_FUNCTION mrmd::action::impl::Energy sum()
Definition SPC.hpp:50
Definition SPC.hpp:130
Definition SPC.hpp:28
real_t coulomb
Definition SPC.hpp:30
Energy(const Energy &rhs)=default
KOKKOS_INLINE_FUNCTION Energy & operator+=(const Energy &src)
Definition SPC.hpp:36
real_t LJ
Definition SPC.hpp:29
Definition Histogram.hpp:26