Loading...
Searching...
No Matches
tip4p_ccl.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*/
19#include <cassert>
20#include <cmath>
21#include <iostream>
22// If unit_system.hpp is removed the system of unit will be (Energy: eV,
23// distance: Angstrom, time: fs, charge: e).
25
26using namespace forcefields;
27/* defined(FORCEFIELDS_UNIT_SYSTEM_HPP) && \
28( FORCEFIELDS_UNIT_SYSTEM_HPP !=
29FORCEFIELDS_UNIT_SYSTEM_ELECTRONVOLT_ANGSTROM_FEMTOSECOND_ECHARGE) //*/
30using namespace forcefields::unit_system;
31namespace {
32double const re_ = 0.9572 * ANGSTROM;
33double const thetae_ = 104.52 * DEGREE;
34double const charge_ = 0.520 * ECHARGE;
35double const charge2_ = charge_ * charge_;
36double const sigma_ =
37 3.154 * ANGSTROM;
38double const epsilon_ =
39 78.0 * KELVIN;
40double const ron_ =
41 0.150 * ANGSTROM;
42double const rok_ =
43 ::re_ *
44 std::cos(::thetae_ / 2.0);
46double const wh_ = ron_ / rok_ * 0.5;
47double const wo_ = (1.0 - wh_ * 2.0);
48} // namespace
49
66
68 : Ccl() {}
69
70Tip4p::Tip4p(double cutoff, double switchingWidth)
71 : Ccl(cutoff, switchingWidth) {}
72
85void Tip4p::computeHH_O_(const int nAtoms, const double R[], double F[],
86 double &U, const double b[]) {
87 computeHH_O_(nAtoms, R, F, U, b, 0);
88}
89
103void Tip4p::computeHH_O_(const int nAtoms, const double R[], double F[],
104 double &U, const double b[], const bool fixed[]) {
105 int const nMolecules = nAtoms / 3;
106 const double (*const rh1)[6] = reinterpret_cast<const double (*)[6]>(R);
107 const double (*const rh2)[6] = reinterpret_cast<const double (*)[6]>(&R[3]);
108 const double (*const ro)[3] =
109 reinterpret_cast<const double (*)[3]>(&R[nMolecules * 6]);
110 double (*const fh1)[6] = reinterpret_cast<double (*)[6]>(F);
111 double (*const fh2)[6] = reinterpret_cast<double (*)[6]>(&F[3]);
112 double (*const fo)[3] = reinterpret_cast<double (*)[3]>(&F[nMolecules * 6]);
113 bool const(*const xh1)[2] = reinterpret_cast<bool const(*)[2]>(fixed);
114 bool const(*const xh2)[2] = reinterpret_cast<bool const(*)[2]>(&fixed[1]);
115 bool const(*const xo)[1] =
116 reinterpret_cast<bool const(*)[1]>(&fixed[nMolecules * 2]);
117 computeTemplate(nMolecules, rh1, rh2, ro, fh1, fh2, fo, U, b, xh1, xh2, xo);
118}
119
121char const *Tip4p::getName() { return "Tip4p"; }
122
123// -----------------------------------------------------private----------------------------------------
124
127 const double *const rh1_;
128 const double *const rh2_;
129 const double *const ro_;
130 const double *const rn_;
131 const double *const rc_;
132 double *const fh1_;
133 double *const fh2_;
134 double *const fo_;
135 double *const fn_;
136};
137
156template <int H, int O>
158 const int nMolecules, const double (*const rh1)[H * 3],
159 const double (*const rh2)[H * 3], const double (*const ro)[O * 3],
160 double (*const fh1)[H * 3], double (*const fh2)[H * 3],
161 double (*const fo)[O * 3], double &energy, double const b[],
162 bool const (*const xh1)[H], bool const (*const xh2)[H],
163 bool const (*const xo)[O]) {
164 for (int i = 0; i < nMolecules; ++i) {
165 for (int a = 0; a < 3; a++) {
166 fh1[i][a] = 0.0;
167 fh2[i][a] = 0.0;
168 fo[i][a] = 0.0;
169 };
170 };
171 energy = 0.0;
173 for (int i = nMolecules - 1; i >= 0; --i) {
174 double rc1[3], rn1[3], fn1[3] = {0}; // rn position charge N, rc centre of
175 // charge for groupbased cutoff.
176 calculateWeightedCentre(wo_, wh_, wh_, ro[i], rh1[i], rh2[i], rn1);
177 calculateCentre(rn1, rh1[i], rh2[i], rc1);
178 Water w1 = {rh1[i], rh2[i], ro[i], rn1, rc1, fh1[i], fh2[i], fo[i], fn1};
179 intramolecular(rh1[i], rh2[i], ro[i], fh1[i], fh2[i], fo[i], energy);
180 for (int j = i - 1; j >= 0; --j) {
181 bool areFixed = false;
182 if (xh1 and xh2 and xo) {
183 areFixed = xh1[i][0] and xh2[i][0] and xo[i][0];
184 // check if all the atoms of molecule j are fixed.
185 areFixed &= xh1[j][0] and xh2[j][0] and xo[j][0];
186 };
187 // if both molecules are fixed skip force calculation
188 if (not areFixed) {
189 double rc2[3], rn2[3], fn2[3] = {0};
190 calculateWeightedCentre(wo_, wh_, wh_, ro[j], rh1[j], rh2[j], rn2);
191 calculateCentre(rn2, rh1[j], rh2[j], rc2);
192 Water w2 = {rh1[j], rh2[j], ro[j], rn2, rc2,
193 fh1[j], fh2[j], fo[j], fn2};
194 coulombWithCutoff(w1, w2, energy);
195 spreadWeightedForce(wo_, wh_, wh_, w2.fo_, w2.fh1_, w2.fh2_, w2.fn_);
196 lennardJonesWithCutoff(w1, w2, energy);
197 };
198 };
199 spreadWeightedForce(wo_, wh_, wh_, w1.fo_, w1.fh1_, w1.fh2_, w1.fn_);
200 };
201 assert(not std::isnan(energy) and not std::isinf(energy));
202}
203
210void Tip4p::coulombWithCutoff(Water &w1, Water &w2, double &U) {
211 double z[3], z1, z2;
212 distance(w1.rc_, w2.rc_, z, z1, z2);
213 if (z1 <= cutoff_ - switchingWidth_) {
214 coulombFull(w1, w2, U);
215 } else if (z1 < cutoff_) {
216 double f1[3][3] = {{0}}, f2[3][3] = {{0}};
217 // f1[0], f1[1], 0, f1[2] are respectively, H1, H2, O, N. There is no charge
218 // on O.
219 Water v1 = {w1.rh1_, w1.rh2_, w1.ro_, w1.rn_, w1.rc_,
220 f1[0], f1[1], 0, f1[2]};
221 Water v2 = {w2.rh1_, w2.rh2_, w2.ro_, w2.rn_, w2.rc_,
222 f2[0], f2[1], 0, f2[2]};
223 double energy = 0.0;
224 coulombFull(v1, v2, energy);
225 ChargeGroup<3> g1 = {v1.rc_, 0, f1};
226 ChargeGroup<3> g2 = {v2.rc_, 0, f2};
227 // Calculate the weakened forces and energy.
228 switching(g1, g2, energy, cutoff_, switchingWidth_);
229 // add weakened force and energy to those of other interactions.
230 U += energy;
231 for (int i = 0; i < 3; ++i) {
232 w1.fh1_[i] += v1.fh1_[i];
233 w1.fh2_[i] += v1.fh2_[i];
234 w1.fn_[i] += v1.fn_[i];
235 w2.fh1_[i] += v2.fh1_[i];
236 w2.fh2_[i] += v2.fh2_[i];
237 w2.fn_[i] += v2.fn_[i];
238 };
239 }
240}
241
252void Tip4p::coulombFull(Water &w1, Water &w2, double &U) {
253 // Coulomb interactions between hydrogens
254 coulomb(w1.rh1_, w2.rh1_, w1.fh1_, w2.fh1_, U, charge2_);
255 coulomb(w1.rh1_, w2.rh2_, w1.fh1_, w2.fh2_, U, charge2_);
256 coulomb(w1.rh2_, w2.rh1_, w1.fh2_, w2.fh1_, U, charge2_);
257 coulomb(w1.rh2_, w2.rh2_, w1.fh2_, w2.fh2_, U, charge2_);
258 // interactions between H and N.
259 coulomb(w1.rn_, w2.rh1_, w1.fn_, w2.fh1_, U, -2.0 * charge2_);
260 coulomb(w1.rn_, w2.rh2_, w1.fn_, w2.fh2_, U, -2.0 * charge2_);
261 coulomb(w1.rh1_, w2.rn_, w1.fh1_, w2.fn_, U, -2.0 * charge2_);
262 coulomb(w1.rh2_, w2.rn_, w1.fh2_, w2.fn_, U, -2.0 * charge2_);
263 // interactions between N1, N2
264 coulomb(w1.rn_, w2.rn_, w1.fn_, w2.fn_, U, 4.0 * charge2_);
265}
266
274void Tip4p::lennardJonesWithCutoff(Water &w1, Water &w2, double &U) {
275 double z[3], z1;
276 distance(w1.ro_, w2.ro_, z, z1);
277 if (z1 <= cutoff_ - switchingWidth_) {
278 lennardJones(w1.ro_, w2.ro_, w1.fo_, w2.fo_, U, epsilon_, sigma_);
279 } else if (z1 < cutoff_) {
280 double f1[3] = {0}, f2[3] = {0};
281 double energy = 0.0;
282 lennardJones(w1.ro_, w2.ro_, f1, f2, energy, epsilon_, sigma_);
283 switching(w1.ro_, w2.ro_, f1, f2, energy);
284 U += energy;
285 for (int i = 0; i < 3; i++) {
286 w1.fo_[i] += f1[i];
287 w2.fo_[i] += f2[i];
288 };
289 };
290}
void intramolecular(double const rh1[], double const rh2[], double const ro[], double fh1[], double fh2[], double fo[], double &energy)
Interactions inside one molecules.
Definition ccl.cpp:238
void spreadWeightedForce(double const w1, double const w2, double const w3, double f1[], double f2[], double f3[], double const fc[])
Spread force on barycentre to atoms.
void switching(ChargeGroup< N, R, F > &g1, ChargeGroup< N, R, F > &g2, double &energy, double cutoff, double switchingWidth)
void coulomb(const double r1[], const double r2[], double f1[], double f2[], double &u, double const qq)
Compute Coulomb interaction between two charges.
void lennardJones(double const distance, double &force, double &energy, double const epsilon, double const sigma)
Lennard-Jones 12-6 between two atoms.
void calculateCentre(double const r1[], double const r2[], double rc[])
Calculate centre of two points.
void setPeriodicity(const double periods[])
Set periodicity.
void distance(const double x[], const double y[], double z[], double &z1, double &z2)
Distance vector, norm and norm square.
void calculateWeightedCentre(double const w1, double const w2, double const w3, double const r1[], double const r2[], double const r3[], double rc[])
Calculate barycentre.
static char const * getName()
Name of the potential.
void coulombWithCutoff(Water &w1, Water &w2, double &U)
Interactions between two molecules.
void computeHH_O_(const int nAtoms, const double R[], double F[], double &U, const double b[])
Compute the forces and the energy.
Definition tip4p_ccl.cpp:85
void lennardJonesWithCutoff(Water &w1, Water &w2, double &U)
Interactions between two molecules.
void coulombFull(Water &w1, Water &w2, double &U)
Interactions between two molecules.
void computeTemplate(const int nMolecules, const double(*const rh1)[H *3], const double(*const rh2)[H *3], const double(*const ro)[O *3], double(*const fh1)[H *3], double(*const fh2)[H *3], double(*const fo)[O *3], double &energy, double const b[], bool const (*const xh1)[H]=0, bool const (*const xh2)[H]=0, bool const (*const xo)[O]=0)
Compute forces and energy.
Physical constants and unit conversion.
Pointers for one molecule of water.
const double *const ro_
const double *const rh1_
double *const fo_
const double *const rc_
double *const fn_
const double *const rh2_
double *const fh1_
const double *const rn_
double *const fh2_
TIP4P potential for water.
Physical constants, unit conversion.