ESPResSo
Extensible Simulation Package for Research on Soft Matter Systems
Loading...
Searching...
No Matches
elc.hpp
Go to the documentation of this file.
1/*
2 * Copyright (C) 2010-2022 The ESPResSo project
3 * Copyright (C) 2002,2003,2004,2005,2006,2007,2008,2009,2010
4 * Max-Planck-Institute for Polymer Research, Theory Group
5 *
6 * This file is part of ESPResSo.
7 *
8 * ESPResSo is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * ESPResSo is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 */
21
22/** @file
23 * @brief ELC algorithm for long-range Coulomb interactions.
24 *
25 * Implementation of the ELC method for the calculation of the electrostatic
26 * interaction in two dimensional periodic systems. For details on the method
27 * see MMM in general. The ELC method works together with any three-dimensional
28 * method, for example @ref p3m.hpp "P3M", with metallic boundary conditions.
29 */
30
31#pragma once
32
33#include "config/config.hpp"
34
35#ifdef P3M
36
37#include "actor/traits.hpp"
38
41
42#include "BoxGeometry.hpp"
43#include "Particle.hpp"
44#include "ParticleRange.hpp"
45
46#include <utils/Vector.hpp>
47
48#include <memory>
49#include <optional>
50#include <stdexcept>
51#include <string>
52#include <utility>
53#include <variant>
54
56
57namespace traits {
58template <>
60} // namespace traits
61
62/** @brief Parameters for the ELC method */
63struct elc_data {
64 elc_data(double maxPWerror, double gap_size, double far_cut, bool neutralize,
65 double delta_top, double delta_bot, bool const_pot, double pot_diff);
66
67 /**
68 * @brief Maximal allowed pairwise error for the potential and force.
69 * Note that this counts for the plain 1/r contribution
70 * alone, without the prefactor and the charge prefactor.
71 */
72 double maxPWerror;
73 /** Size of the empty gap. Note that ELC relies on the user to make sure
74 * that this condition is fulfilled.
75 */
76 double gap_size;
77 /** Up to where particles can be found. */
78 double box_h;
79 /**
80 * @brief Cutoff of the exponential sum.
81 * Since in all other MMM methods this is the far formula,
82 * it is given the same name here.
83 */
84 double far_cut;
85 /** Squared value of #far_cut. */
86 double far_cut2;
87 /** Flag whether #far_cut was set by the user, or calculated by ESPResSo.
88 * In the latter case, the cutoff will be adapted if important parameters,
89 * such as the box dimensions, change.
90 */
92
93 /// @brief Flag whether there is any dielectric contrast in the system.
95 /// @brief Flag whether a constant potential difference is applied.
97 /**
98 * @brief Flag whether the box is neutralized by a homogeneous background.
99 * If true, use a homogeneous neutralizing background for non-neutral
100 * systems. Unlike the 3D case, this background adds an additional
101 * force pointing towards the system center, and the gap size
102 * enters into the value of the forces, so be careful with this.
103 */
105
106 /// dielectric contrast in the upper part of the simulation cell.
108 /// dielectric contrast in the lower part of the simulation cell.
110 /// @brief Constant potential difference.
111 double pot_diff;
112
113 /** Layer around the dielectric contrast in which we trick around. */
115 /** The space that is finally left. */
116 double space_box;
117
118 /// pairwise contributions from the lowest and top layers
119 template <typename Kernel>
121 BoxGeometry const &box_geo,
122 Utils::Vector3d const &pos1,
123 Utils::Vector3d const &pos2, double q1q2,
124 Kernel &&kernel) const {
125 if (pos1[2] < space_layer) {
126 auto const q_eff = delta_mid_bot * q1q2;
127 auto const d = box_geo.get_mi_vector(pos2, {pos1[0], pos1[1], -pos1[2]});
128 kernel(q_eff, d);
129 }
130 if (pos1[2] > (box_h - space_layer)) {
131 auto const q_eff = delta_mid_top * q1q2;
132 auto const z = 2. * box_h - pos1[2];
133 auto const d = box_geo.get_mi_vector(pos2, {pos1[0], pos1[1], z});
134 kernel(q_eff, d);
135 }
136 }
137
138 /// self energies of top and bottom layers with their virtual images
140 BoxGeometry const &box_geo,
141 ParticleRange const &particles) const {
142 auto energy = 0.;
143 for (auto const &p : particles) {
145 p3m, box_geo, p.pos(), p.pos(), Utils::sqr(p.q()),
146 [&](double q1q2, Utils::Vector3d const &d) {
147 energy += p3m.pair_energy(q1q2, d.norm());
148 });
149 }
150 return energy;
151 }
152
153 /// forces of particles in border layers with themselves
155 BoxGeometry const &box_geo,
156 ParticleRange const &particles) const {
157 for (auto &p : particles) {
159 p3m, box_geo, p.pos(), p.pos(), Utils::sqr(p.q()),
160 [&](double q1q2, Utils::Vector3d const &d) {
161 p.force() += p3m.pair_force(q1q2, d, d.norm());
162 });
163 }
164 }
165};
166
168 : public Coulomb::Actor<ElectrostaticLayerCorrection> {
169 using BaseSolver = std::variant<
170#ifdef CUDA
171 std::shared_ptr<CoulombP3MGPU>,
172#endif // CUDA
173 std::shared_ptr<CoulombP3M>>;
174
177
178 /** Electrostatics solver that is adapted. */
180
181 ElectrostaticLayerCorrection(elc_data &&parameters, BaseSolver &&solver);
182
184 visit_base_solver(
185 [this](auto &solver) { solver->bind_system(m_system.lock()); });
186 sanity_checks_periodicity();
187 sanity_checks_cell_structure();
189 sanity_checks_dielectric_contrasts();
190 /* Most ELC parameters do not depend on the P3M parameters,
191 * but the P3M parameters depend on the ELC parameters during tuning,
192 * therefore ELC needs to be tuned before P3M. */
193 recalc_box_h();
194 recalc_far_cut();
195 visit_base_solver([](auto &solver) { solver->on_activation(); });
196 /* With dielectric contrasts, the ELC space layer depends
197 * on the P3M real-space cutoff, and the P3M FFT parameters
198 * depend on the ELC space layer */
200 recalc_space_layer();
201 visit_base_solver([](auto &actor) { actor->init(); });
202 }
203 }
204 /** @brief Recalculate all box-length-dependent parameters. */
206 visit_base_solver([](auto &actor) { actor->on_boxl_change(); });
207 recalc_box_h();
208 recalc_far_cut();
209 recalc_space_layer();
210 }
211 void on_node_grid_change() const {
212 visit_base_solver([](auto &solver) { solver->on_node_grid_change(); });
213 }
215 sanity_checks_periodicity();
216 visit_base_solver([](auto &solver) { solver->on_periodicity_change(); });
217 }
219 sanity_checks_cell_structure();
220 visit_base_solver([](auto &solver) { solver->on_cell_structure_change(); });
221 recalc_box_h();
222 recalc_far_cut();
224 recalc_space_layer();
225 visit_base_solver([](auto &actor) { actor->init(); });
226 }
227 }
228 /** @brief Recalculate all derived parameters. */
229 void init() {
230 visit_base_solver([](auto &actor) { actor->init(); });
231 recalc_box_h();
232 recalc_far_cut();
233 recalc_space_layer();
234 }
235
236 void sanity_checks() const {
237 sanity_checks_periodicity();
238 sanity_checks_cell_structure();
240 sanity_checks_dielectric_contrasts();
241 visit_base_solver([](auto &actor) { actor->sanity_checks(); });
242 }
243
244 /**
245 * @brief Veto real-space cutoff values that are incompatible with ELC.
246 * When ELC is used with dielectric contrasts, the short-range cutoff needs
247 * to be smaller than the gap size to allow placement of the image charges.
248 */
249 std::optional<std::string> veto_r_cut(double r_cut) const {
250 if (elc.dielectric_contrast_on and r_cut >= elc.gap_size) {
251 return {std::string("conflict with ELC w/ dielectric contrasts")};
252 }
253 return {};
254 }
255
256 /** @brief Calculate short-range pair energy correction. */
257 double pair_energy_correction(Particle const &p1, Particle const &p2,
258 double q1q2) const {
259 double energy = 0.;
261 energy = std::visit(
262 [this, &p1, &p2, q1q2](auto &p3m_ptr) {
263 auto const &pos1 = p1.pos();
264 auto const &pos2 = p2.pos();
265 auto const &p3m = *p3m_ptr;
266 auto energy = 0.;
268 p3m, *m_box_geo, pos1, pos2, q1q2,
269 [&](double q_eff, Utils::Vector3d const &d) {
270 energy += p3m.pair_energy(q_eff, d.norm());
271 });
273 p3m, *m_box_geo, pos2, pos1, q1q2,
274 [&](double q_eff, Utils::Vector3d const &d) {
275 energy += p3m.pair_energy(q_eff, d.norm());
276 });
277 return energy / 2.;
278 },
280 }
281 return energy;
282 }
283
284 /** @brief Add short-range pair force corrections. */
286 double q1q2) const {
288 std::visit(
289 [this, &p1, &p2, q1q2](auto &p3m_ptr) {
290 auto const &pos1 = p1.pos();
291 auto const &pos2 = p2.pos();
292 auto const &p3m = *p3m_ptr;
294 p3m, *m_box_geo, pos1, pos2, q1q2,
295 [&](double q_eff, Utils::Vector3d const &d) {
296 p1.force() += p3m.pair_force(q_eff, d, d.norm());
297 });
299 p3m, *m_box_geo, pos2, pos1, q1q2,
300 [&](double q_eff, Utils::Vector3d const &d) {
301 p2.force() += p3m.pair_force(q_eff, d, d.norm());
302 });
303 },
305 }
306 }
307
308 double long_range_energy(ParticleRange const &particles) const;
309 void add_long_range_forces(ParticleRange const &particles) const;
310
311private:
312 /** Check if a charged particle is in the gap region. */
313 void check_gap(Particle const &p) const;
314 double tune_far_cut() const;
315 void adapt_solver();
316 /** pairwise contributions from the lowest and top layers to the energy */
317 double dipole_energy(ParticleRange const &particles) const;
318 void add_dipole_force(ParticleRange const &particles) const;
319 double z_energy(ParticleRange const &particles) const;
320 void add_z_force(ParticleRange const &particles) const;
321
322 void recalc_box_h();
323 void recalc_far_cut() {
324 if (elc.far_calculated) {
325 elc.far_cut = tune_far_cut();
326 }
328 }
329 void recalc_space_layer();
330
331 void sanity_checks_cell_structure() const {}
332 void sanity_checks_periodicity() const;
333 void sanity_checks_dielectric_contrasts() const;
334
335 /// the force calculation
336 void add_force(ParticleRange const &particles) const;
337 /// the energy calculation
338 double calc_energy(ParticleRange const &particles) const;
339
340 template <class Visitor> void visit_base_solver(Visitor &&visitor) const {
341 std::visit(visitor, base_solver);
342 }
343};
344
345#endif // P3M
Vector implementation and trait types for boost qvm interoperability.
Utils::Vector< T, 3 > get_mi_vector(const Utils::Vector< T, 3 > &a, const Utils::Vector< T, 3 > &b) const
Get the minimum-image vector between two coordinates.
A range of particles.
std::weak_ptr< System > m_system
T norm() const
Definition Vector.hpp:131
This file contains the defaults for ESPResSo.
DEVICE_QUALIFIER constexpr T sqr(T x)
Calculates the SQuaRe of x.
Definition sqr.hpp:26
P3M algorithm for long-range Coulomb interaction.
P3M electrostatics on GPU.
P3M solver.
Definition p3m.hpp:85
double pair_energy_correction(Particle const &p1, Particle const &p2, double q1q2) const
Calculate short-range pair energy correction.
Definition elc.hpp:257
void on_boxl_change()
Recalculate all box-length-dependent parameters.
Definition elc.hpp:205
void on_periodicity_change() const
Definition elc.hpp:214
void sanity_checks() const
Definition elc.hpp:236
std::optional< std::string > veto_r_cut(double r_cut) const
Veto real-space cutoff values that are incompatible with ELC.
Definition elc.hpp:249
BaseSolver base_solver
Electrostatics solver that is adapted.
Definition elc.hpp:179
void init()
Recalculate all derived parameters.
Definition elc.hpp:229
std::variant< std::shared_ptr< CoulombP3MGPU >, std::shared_ptr< CoulombP3M > > BaseSolver
Definition elc.hpp:173
void add_pair_force_corrections(Particle &p1, Particle &p2, double q1q2) const
Add short-range pair force corrections.
Definition elc.hpp:285
void on_node_grid_change() const
Definition elc.hpp:211
BoxGeometry * m_box_geo
Definition elc.hpp:176
void add_long_range_forces(ParticleRange const &particles) const
Definition elc.cpp:1233
double long_range_energy(ParticleRange const &particles) const
Definition elc.cpp:1191
Struct holding all information for one particle.
Definition Particle.hpp:393
auto const & pos() const
Definition Particle.hpp:429
auto const & force() const
Definition Particle.hpp:433
Parameters for the ELC method.
Definition elc.hpp:63
double dielectric_layers_self_energy(CoulombP3M const &p3m, BoxGeometry const &box_geo, ParticleRange const &particles) const
self energies of top and bottom layers with their virtual images
Definition elc.hpp:139
double maxPWerror
Maximal allowed pairwise error for the potential and force.
Definition elc.hpp:72
double pot_diff
Constant potential difference.
Definition elc.hpp:111
void dielectric_layers_contribution(CoulombP3M const &, BoxGeometry const &box_geo, Utils::Vector3d const &pos1, Utils::Vector3d const &pos2, double q1q2, Kernel &&kernel) const
pairwise contributions from the lowest and top layers
Definition elc.hpp:120
double box_h
Up to where particles can be found.
Definition elc.hpp:78
bool dielectric_contrast_on
Flag whether there is any dielectric contrast in the system.
Definition elc.hpp:94
double space_box
The space that is finally left.
Definition elc.hpp:116
bool neutralize
Flag whether the box is neutralized by a homogeneous background.
Definition elc.hpp:104
double far_cut
Cutoff of the exponential sum.
Definition elc.hpp:84
double space_layer
Layer around the dielectric contrast in which we trick around.
Definition elc.hpp:114
bool far_calculated
Flag whether far_cut was set by the user, or calculated by ESPResSo.
Definition elc.hpp:91
double gap_size
Size of the empty gap.
Definition elc.hpp:76
double delta_mid_bot
dielectric contrast in the lower part of the simulation cell.
Definition elc.hpp:109
void dielectric_layers_self_forces(CoulombP3M const &p3m, BoxGeometry const &box_geo, ParticleRange const &particles) const
forces of particles in border layers with themselves
Definition elc.hpp:154
bool const_pot
Flag whether a constant potential difference is applied.
Definition elc.hpp:96
double far_cut2
Squared value of far_cut.
Definition elc.hpp:86
double delta_mid_top
dielectric contrast in the upper part of the simulation cell.
Definition elc.hpp:107
Whether an actor is a layer correction method.
Definition traits.hpp:26