ESPResSo
Extensible Simulation Package for Research on Soft Matter Systems
Loading...
Searching...
No Matches
p3m.hpp
Go to the documentation of this file.
1/*
2 * Copyright (C) 2010-2024 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 * P3M algorithm for long-range Coulomb interaction.
24 *
25 * We use a P3M (Particle-Particle Particle-Mesh) method based on the
26 * Ewald summation. Details of the used method can be found in
27 * @cite hockney88a and @cite deserno98a @cite deserno98b.
28 *
29 * Further reading: @cite ewald21a, @cite hockney88a, @cite deserno98a,
30 * @cite deserno98b, @cite deserno00e, @cite deserno00b, @cite cerda08d.
31 *
32 * Implementation in p3m.cpp.
33 */
34
35#pragma once
36
37#include <config/config.hpp>
38
39#ifdef ESPRESSO_P3M
40
42
43#include "p3m/common.hpp"
44#include "p3m/data_struct.hpp"
45#include "p3m/math.hpp"
46
47#include <utils/Vector.hpp>
49
50#include <cmath>
51#include <cstddef>
52#include <numbers>
53
54/** @brief P3M solver. */
55struct CoulombP3M : public Coulomb::Actor<CoulombP3M> {
57
58public:
60
61 virtual ~CoulombP3M() = default;
62
63 [[nodiscard]] virtual bool is_tuned() const noexcept = 0;
64 [[nodiscard]] virtual bool is_gpu() const noexcept = 0;
65 [[nodiscard]] virtual bool is_double_precision() const noexcept = 0;
66
67 /** @brief Recalculate all derived parameters. */
68 virtual void init() = 0;
69 virtual void on_activation() = 0;
70
71 /** @brief Recalculate all box-length-dependent parameters. */
73 void on_node_grid_change() const {}
85
86 /**
87 * Count the number of charged particles and calculate
88 * the sum of the squared charges.
89 */
90 virtual void count_charged_particles() = 0;
91 virtual void count_charged_particles_elc(std::size_t, double, double) = 0;
92 virtual void adapt_epsilon_elc() = 0;
93
94 /**
95 * @brief Tune P3M parameters to desired accuracy.
96 *
97 * The parameters
98 * @ref P3MParameters::mesh "mesh",
99 * @ref P3MParameters::cao "cao",
100 * @ref P3MParameters::r_cut_iL "r_cut_iL" and
101 * @ref P3MParameters::alpha_L "alpha_L" are tuned to obtain the target
102 * @ref P3MParameters::accuracy "accuracy" in optimal time.
103 * These parameters are stored in the @ref p3m_params object.
104 *
105 * The function utilizes the analytic expression of the error estimate
106 * for the P3M method in @cite hockney88a (eq. (8.23)) in
107 * order to obtain the rms error in the force for a system of N randomly
108 * distributed particles in a cubic box.
109 * For the real space error the estimate of Kolafa/Perram is used.
110 *
111 * Parameter ranges if not given explicitly in the constructor:
112 * - @p mesh explores the range 0-512 (biased toward values less than 128)
113 * - @p cao explores all possible values
114 * - @p alpha_L is tuned for each tuple (@p r_cut_iL, @p mesh, @p cao) and
115 * calculated assuming that the error contributions of real and reciprocal
116 * space should be equal
117 *
118 * After checking if the total error lies below the target accuracy,
119 * the time needed for one force calculation is measured. Parameters
120 * that minimize the runtime are kept.
121 *
122 * The function is based on routines of the program HE_Q.cpp written by M.
123 * Deserno.
124 */
125 virtual void tune() = 0;
126
127 /** Assign the physical charges using the tabulated charge assignment
128 * function.
129 */
130 virtual void charge_assign() = 0;
131
132 /**
133 * @brief Assign a single charge into the current charge grid.
134 *
135 * @param[in] q Particle charge
136 * @param[in] real_pos Particle position in real space
137 * @param[in] skip_cache Skip interpolation weights caching.
138 */
139 virtual void assign_charge(double q, Utils::Vector3d const &real_pos,
140 bool skip_cache) = 0;
141
142 virtual void prepare_fft_mesh(bool reset_weights) = 0;
143
144 /** Calculate real-space contribution of p3m Coulomb pair forces. */
146 double dist) const {
147 if (q1q2 == 0. or dist >= p3m_params.r_cut or dist <= 0.) {
148 return {};
149 }
150 auto const alpha = p3m_params.alpha;
151 auto const adist = alpha * dist;
152 auto const exp_adist_sq = exp(-adist * adist);
153 auto const dist_sq = dist * dist;
154 auto const two_a_sqrt_pi_i = 2. * alpha * std::numbers::inv_sqrtpi;
155#if USE_ERFC_APPROXIMATION
156 auto const erfc_part_ri = Utils::AS_erfc_part(adist) / dist;
157 auto const fac = exp_adist_sq * (erfc_part_ri + two_a_sqrt_pi_i) / dist_sq;
158#else
159 auto const erfc_part_ri = erfc(adist) / dist;
160 auto const fac = (erfc_part_ri + two_a_sqrt_pi_i * exp_adist_sq) / dist_sq;
161#endif
162 return (fac * prefactor * q1q2) * d;
163 }
164
165 /** Calculate real-space contribution of Coulomb pair energy. */
166 // Eq. (3.6) @cite deserno00b
167 double pair_energy(double q1q2, double dist) const {
168 if (q1q2 == 0. or dist >= p3m_params.r_cut or dist <= 0.) {
169 return {};
170 }
171 auto const adist = p3m_params.alpha * dist;
172#if USE_ERFC_APPROXIMATION
173 auto const erfc_part_ri = Utils::AS_erfc_part(adist) / dist;
174 return prefactor * q1q2 * erfc_part_ri * exp(-adist * adist);
175#else
176 auto const erfc_part_ri = erfc(adist) / dist;
177 return prefactor * q1q2 * erfc_part_ri;
178#endif
179 }
180
181 /** Compute the k-space part of the pressure tensor */
183
184 /** Compute the k-space part of energies. */
185 virtual double long_range_energy() = 0;
186
187 /** Compute the k-space part of forces. */
188 virtual void add_long_range_forces() = 0;
189
190protected:
193
194 /** Checks for correctness of the k-space cutoff. */
195 void sanity_checks_boxl() const;
196 void sanity_checks_periodicity() const;
197 void sanity_checks_cell_structure() const;
198
199 virtual void scaleby_box_l() = 0;
200};
201
202std::shared_ptr<CoulombP3M>
204 TuningParameters const &tuning_params, double prefactor,
205 bool single_precision, Arch arch);
206
207#endif // ESPRESSO_P3M
Vector implementation and trait types for boost qvm interoperability.
double prefactor
Electrostatics prefactor.
constexpr T AS_erfc_part(T d)
Approximate by applying a formula from chapter 7.
Common functions for dipolar and charge P3M.
Arch
P3M kernel architecture.
std::shared_ptr< CoulombP3M > new_coulomb_p3m_heffte(P3MParameters &&p3m_params, TuningParameters const &tuning_params, double prefactor, bool single_precision, Arch arch)
P3M solver.
Definition p3m.hpp:55
virtual ~CoulombP3M()=default
virtual bool is_gpu() const noexcept=0
void sanity_checks_periodicity() const
void on_cell_structure_change()
Definition p3m.hpp:75
virtual void tune()=0
Tune P3M parameters to desired accuracy.
CoulombP3M(P3MParameters const &p3m_params)
Definition p3m.hpp:59
Utils::Vector3d pair_force(double q1q2, Utils::Vector3d const &d, double dist) const
Calculate real-space contribution of p3m Coulomb pair forces.
Definition p3m.hpp:145
void on_boxl_change()
Recalculate all box-length-dependent parameters.
Definition p3m.hpp:72
virtual void add_long_range_forces()=0
Compute the k-space part of forces.
double pair_energy(double q1q2, double dist) const
Calculate real-space contribution of Coulomb pair energy.
Definition p3m.hpp:167
void sanity_checks_boxl() const
Checks for correctness of the k-space cutoff.
virtual void prepare_fft_mesh(bool reset_weights)=0
void sanity_checks_cell_structure() const
P3MParameters const & p3m_params
Definition p3m.hpp:56
virtual Utils::Vector9d long_range_pressure()=0
Compute the k-space part of the pressure tensor.
virtual void on_activation()=0
virtual void count_charged_particles_elc(std::size_t, double, double)=0
void sanity_checks() const
Definition p3m.hpp:79
virtual void charge_assign()=0
Assign the physical charges using the tabulated charge assignment function.
void on_periodicity_change() const
Definition p3m.hpp:74
virtual void adapt_epsilon_elc()=0
virtual void calc_influence_function_force()=0
void on_node_grid_change() const
Definition p3m.hpp:73
virtual bool is_double_precision() const noexcept=0
virtual bool is_tuned() const noexcept=0
virtual double long_range_energy()=0
Compute the k-space part of energies.
virtual void count_charged_particles()=0
Count the number of charged particles and calculate the sum of the squared charges.
virtual void assign_charge(double q, Utils::Vector3d const &real_pos, bool skip_cache)=0
Assign a single charge into the current charge grid.
virtual void init()=0
Recalculate all derived parameters.
virtual void scaleby_box_l()=0
virtual void calc_influence_function_energy()=0
Structure to hold P3M parameters and some dependent variables.
double alpha
unscaled alpha_L for use with fast inline functions only
double r_cut
unscaled r_cut_iL for use with fast inline functions only