MaMiCo 1.2
Loading...
Searching...
No Matches
ZhouBoundaryForce.h
1// Copyright (C) 2015 Technische Universitaet Muenchen
2// This file is part of the Mamico project. For conditions of distribution
3// and use, please see the copyright notice in Mamico's main folder, or at
4// www5.in.tum.de/mamico
5#ifndef _MOLECULARDYNAMICS_COUPLING_CELLMAPPINGS_ZHOUBOUNDARYFORCE_H_
6#define _MOLECULARDYNAMICS_COUPLING_CELLMAPPINGS_ZHOUBOUNDARYFORCE_H_
7
8#include "coupling/interface/MDSolverInterface.h"
9#include "coupling/interface/Molecule.h"
10#include "coupling/interface/MoleculeIterator.h"
11#include <cmath>
12#include <iostream>
13
14namespace coupling {
15namespace cellmappings {
16template <class LinkedCell, unsigned int dim> class ZhouBoundaryForce;
17}
18} // namespace coupling
19
40template <class LinkedCell, unsigned int dim> class coupling::cellmappings::ZhouBoundaryForce {
41public:
53 ZhouBoundaryForce(const double& density, const double& temperature, const double& epsilon, const double& sigma,
54 const tarch::la::Vector<2 * dim, bool>& boundary, const tarch::la::Vector<dim, double>& domainOffset,
56 : _boundary(boundary), _domainLowerLeft(domainOffset), _domainUpperRight(domainSize + domainOffset), _mdSolverInterface(mdSolverInterface),
57 _p1(getP1(density, temperature)), _p2(getP2(density, temperature)), _p3(getP3(density, temperature)), _q1(getQ1(density)), _q2(getQ2(density)),
58 _q3(getQ3(density)), _forceFactor(epsilon / sigma), _sigma(sigma),
60 _energyResolution(1000), _energyTable(new double[_energyResolution]) {
61 // simple trapezoidal integration scheme
62 double force(0);
63 double energy(0);
64 double dx(2.5 * sigma / (_energyResolution - 1));
65 for (unsigned int i = 0; i < _energyResolution; i++) {
66 force = getScalarBoundaryForce(2.5 - i * dx);
67 _energyTable[i] = energy + force / 2 * dx;
68 energy += force * dx;
69 }
70
71 // for(unsigned int i=0;i<_energyResolution;i++){
72 // std::cout << "_energyTable[" << i << "] = " << _energyTable[i] <<
73 // std::endl;
74 // }
75 // for(double pos = 0; pos <= 2.5; pos += .25/_energyResolution){
76 // std::cout << "getPotentialEnergy(" << pos << ") = " <<
77 // getPotentialEnergy(pos) << std::endl;
78 // }
79 }
80
82 ~ZhouBoundaryForce() { delete[] _energyTable; }
83
87
91
96 void handleCell(LinkedCell& cell) {
97 coupling::interface::MoleculeIterator<LinkedCell, dim>* it = _mdSolverInterface->getMoleculeIterator(cell);
98 it->begin();
99 while (it->continueIteration()) {
101 // std::cout << "apply force to Molecule " << wrapper.getPosition() <<
102 // std::endl;
103
104 // extract position and force of each molecule
105 const tarch::la::Vector<dim, double> position(wrapper.getPosition());
107 // add boundary force
108 force = force + getBoundaryForces(position);
109 wrapper.setForce(force);
110
111 it->next();
112 }
113 delete it;
114 }
115
121 double energy(0);
122 const double distance = 2.5 * _sigma;
123 for (unsigned int d = 0; d < dim; d++) {
124 if (_boundary[2 * d] && (position[d] - _domainLowerLeft[d] < distance)) {
125 energy += getPotentialEnergy((position[d] - _domainLowerLeft[d]) / _sigma);
126 }
127 if (_boundary[2 * d + 1] && (_domainUpperRight[d] - position[d] < distance)) {
128 energy += getPotentialEnergy((_domainUpperRight[d] - position[d]) / _sigma);
129 }
130 }
131 return energy;
132 }
133
143 const double distance = 2.5 * _sigma;
144
145 for (unsigned int d = 0; d < dim; d++) {
146 // for left/lower/back boundary: add force; for right/upper/front
147 // boundary: subtract force value
148 if (_boundary[2 * d] && (position[d] - _domainLowerLeft[d] < distance)) {
149 force[d] += _forceFactor * getScalarBoundaryForce((position[d] - _domainLowerLeft[d]) / _sigma);
150 }
151 if (_boundary[2 * d + 1] && (_domainUpperRight[d] - position[d] < distance)) {
152 force[d] -= _forceFactor * getScalarBoundaryForce((_domainUpperRight[d] - position[d]) / _sigma);
153 }
154 }
155 return force;
156 }
157
158private:
163 double getPotentialEnergy(double rw) const {
164 double dx(2.5 * _sigma / (_energyResolution - 1));
165 int upper = (int)((2.5 - rw) / 2.5 * (_energyResolution - 1) - .5);
166 int lower = (int)((2.5 - rw) / 2.5 * (_energyResolution - 1) + .5);
167 return _energyTable[lower] * ((2.5 - upper * dx - rw) / dx) + _energyTable[upper] * ((rw - 2.5 + lower * dx) / dx);
168 }
169
176 double getScalarBoundaryForce(double rw) const {
177 if (rw < 1.04) {
178 return _p1 + _p2 * exp(pow((rw + 0.25), 3.4)) * cos(_p3 * rw);
179 } else {
180 return -1.0 / (_q1 + _q2 * (2.5 - rw) * (2.5 - rw) + _q3 / ((2.5 - rw) * (2.5 - rw)));
181 }
182 }
183
189 double getP1(const double& density, const double& temperature) const {
190 const double logrho = log(density);
191 const double T2 = temperature * temperature;
192 const double T3 = T2 * temperature;
193
194 // an additional factor 10**-5 is in the expression 4.599/(...) -> private
195 // communication with Wenjing Zhou (typo in paper)
196 const double p1 = (-18.953 + 53.369 * temperature - 1.253 * T2 + 4.599 / 100000.0 * T3 + 59.871 * logrho + 19.737 * logrho * logrho) /
197 (1.0 + 2.592 * temperature - 0.557 * T2 + 0.049 * T3 - 13.912 * logrho + 18.657 * logrho * logrho);
198 return p1;
199 }
200
206 double getP2(const double& density, const double& temperature) const {
207 const double logrho = log(density);
208 const double T2 = temperature * temperature;
209 const double T3 = T2 * temperature;
210
211 const double p2 = (-0.094 + 2.808 * temperature - 0.019 * T2 - 0.001 * T3 + 2.823 * logrho + 2.071 * logrho * logrho) /
212 (1.0 + 0.168 * temperature - 0.013 * T2 - 4.323 * logrho + 2.557 * logrho * logrho - 2.155 * logrho * logrho * logrho);
213 return p2;
214 }
215
221 double getP3(const double& density, const double& temperature) const {
222 const double T394 = pow(temperature, 0.394);
223 const double rho17437 = pow(density, 17.437);
224 const double p3 = 3.934 + 0.099 * T394 - 0.097 * rho17437 + 0.075 * T394 * rho17437;
225 return p3;
226 }
227
232 double getQ1(const double& density) const {
233 const double rho2 = density * density;
234 const double rho3 = rho2 * density;
235 const double rho4 = rho2 * rho2;
236 return -30.471 + 113.879 * density - 207.205 * rho2 + 184.242 * rho3 - 62.879 * rho4;
237 }
238
243 double getQ2(const double& density) const {
244 const double rho2 = density * density;
245 const double rho3 = rho2 * density;
246 const double rho4 = rho2 * rho2;
247 return 6.938 - 25.788 * density + 46.773 * rho2 - 41.768 * rho3 + 14.394 * rho4;
248 }
249
254 double getQ3(const double& density) const {
255 const double rho2 = density * density;
256 const double rho3 = rho2 * density;
257 const double rho4 = rho2 * rho2;
258 return 39.634 - 147.821 * density + 269.519 * rho2 - 239.066 * rho3 + 81.439 * rho4;
259 }
260
268
270 // helper variables to speed up evaluation, see Zhou paper
271 const double _p1;
272 const double _p2;
273 const double _p3;
274 const double _q1;
275 const double _q2;
276 const double _q3;
277
279 const double _forceFactor;
281 const double _sigma;
282
283 const unsigned int _energyResolution;
284 double* _energyTable;
285};
286#endif // _MOLECULARDYNAMICS_COUPLING_CELLMAPPINGS_ZHOUBOUNDARYFORCE_H_
This class applies the Zhou boundary force to all molecules assuming a cut-off radius r_c=2....
Definition ZhouBoundaryForce.h:40
const tarch::la::Vector< dim, double > _domainLowerLeft
Definition ZhouBoundaryForce.h:265
~ZhouBoundaryForce()
Definition ZhouBoundaryForce.h:82
tarch::la::Vector< dim, double > getBoundaryForces(const tarch::la::Vector< dim, double > &position) const
Definition ZhouBoundaryForce.h:141
const tarch::la::Vector< dim, double > _domainUpperRight
Definition ZhouBoundaryForce.h:267
double getPotentialEnergy(const tarch::la::Vector< dim, double > &position) const
Definition ZhouBoundaryForce.h:120
const double _sigma
Definition ZhouBoundaryForce.h:281
void handleCell(LinkedCell &cell)
Definition ZhouBoundaryForce.h:96
const double _forceFactor
Definition ZhouBoundaryForce.h:279
double getScalarBoundaryForce(double rw) const
Definition ZhouBoundaryForce.h:176
void endCellIteration()
Definition ZhouBoundaryForce.h:90
double getP3(const double &density, const double &temperature) const
Definition ZhouBoundaryForce.h:221
double getPotentialEnergy(double rw) const
Definition ZhouBoundaryForce.h:163
double getP1(const double &density, const double &temperature) const
Definition ZhouBoundaryForce.h:189
double getQ2(const double &density) const
Definition ZhouBoundaryForce.h:243
double getP2(const double &density, const double &temperature) const
Definition ZhouBoundaryForce.h:206
double getQ1(const double &density) const
Definition ZhouBoundaryForce.h:232
double getQ3(const double &density) const
Definition ZhouBoundaryForce.h:254
const tarch::la::Vector< 2 *dim, bool > _boundary
Definition ZhouBoundaryForce.h:263
ZhouBoundaryForce(const double &density, const double &temperature, const double &epsilon, const double &sigma, const tarch::la::Vector< 2 *dim, bool > &boundary, const tarch::la::Vector< dim, double > &domainOffset, const tarch::la::Vector< dim, double > &domainSize, coupling::interface::MDSolverInterface< LinkedCell, dim > *const mdSolverInterface)
Definition ZhouBoundaryForce.h:53
void beginCellIteration()
Definition ZhouBoundaryForce.h:86
interface to the MD simulation
Definition MDSolverInterface.h:25
some iterator scheme for traversing the molecules within a linked cell.
Definition MoleculeIterator.h:24
virtual bool continueIteration() const =0
virtual coupling::interface::Molecule< dim > & get()=0
interface to access a single molecule in the MD simulation.
Definition Molecule.h:23
virtual void setForce(const tarch::la::Vector< dim, double > &force)=0
virtual tarch::la::Vector< dim, double > getForce() const =0
virtual tarch::la::Vector< dim, double > getPosition() const =0
Definition Vector.h:24
everything necessary for coupling operations, is defined in here
Definition AdditiveMomentumInsertion.h:15