ESPResSo
Extensible Simulation Package for Research on Soft Matter Systems
Loading...
Searching...
No Matches
influence_function_dipolar.hpp
Go to the documentation of this file.
1/*
2 * Copyright (C) 2010-2022 The ESPResSo project
3 * Copyright (C) 2002-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#ifndef ESPRESSO_CORE_P3M_INFLUENCE_FUNCTION_DIPOLAR_HPP
22#define ESPRESSO_CORE_P3M_INFLUENCE_FUNCTION_DIPOLAR_HPP
23
24#include "config/config.hpp"
25
26#if defined(DP3M)
27
28#include "p3m/common.hpp"
29
30#include <utils/Vector.hpp>
31#include <utils/constants.hpp>
32#include <utils/index.hpp>
34#include <utils/math/sinc.hpp>
35#include <utils/math/sqr.hpp>
36
37#include <boost/range/numeric.hpp>
38
39#include <cmath>
40#include <cstddef>
41#include <functional>
42#include <vector>
43
44/** Calculate the aliasing sums for the optimal influence function.
45 *
46 * Calculates the aliasing sums in the numerator and denominator of
47 * the expression for the optimal influence function (see
48 * @cite hockney88a : 8-22, p. 275).
49 *
50 * \tparam S order (2 for energy, 3 for forces)
51 * \param params DP3M parameters
52 * \param shift shift for a given n-vector
53 * \param d_op differential operator for a given n-vector
54 * \return The result of the fraction.
55 */
56template <std::size_t S>
58 Utils::Vector3i const &d_op) {
59 using Utils::int_pow;
60 using Utils::sinc;
61 auto constexpr limit = P3M_BRILLOUIN;
62 auto constexpr exp_limit = 30.;
63 auto const exponent = 2. * params.cao;
64
65 auto numerator = 0.0;
66 auto denominator = 0.0;
67
68 auto const f1 = 1.0 / static_cast<double>(params.mesh[0]);
69 auto const f2 = Utils::sqr(Utils::pi() / params.alpha_L);
70
71 for (int mx = -limit; mx <= limit; mx++) {
72 auto const nmx = shift[0] + params.mesh[0] * mx;
73 auto const sx = std::pow(sinc(f1 * nmx), exponent);
74 for (int my = -limit; my <= limit; my++) {
75 auto const nmy = shift[1] + params.mesh[0] * my;
76 auto const sy = sx * std::pow(sinc(f1 * nmy), exponent);
77 for (int mz = -limit; mz <= limit; mz++) {
78 auto const nmz = shift[2] + params.mesh[0] * mz;
79 auto const sz = sy * std::pow(sinc(f1 * nmz), exponent);
80 auto const nm2 = Utils::sqr(nmx) + Utils::sqr(nmy) + Utils::sqr(nmz);
81 auto const exp_term = f2 * nm2;
82 if (exp_term < exp_limit) {
83 auto const f3 = sz * std::exp(-exp_term) / nm2;
84 auto const n_nm = d_op[0] * nmx + d_op[1] * nmy + d_op[2] * nmz;
85 numerator += f3 * int_pow<S>(n_nm);
86 }
87 denominator += sz;
88 }
89 }
90 }
91 return numerator / (int_pow<S>(static_cast<double>(d_op.norm2())) *
92 Utils::sqr(denominator));
93}
94
95/**
96 * @brief Map influence function over a grid.
97 *
98 * This evaluates the optimal influence function @ref G_opt_dipolar
99 * over a regular grid of k vectors, and returns the values as a vector.
100 *
101 * @tparam S Order of the differential operator, e.g. 2 for energy, 3 for force
102 *
103 * @param params DP3M parameters
104 * @param n_start Lower left corner of the grid
105 * @param n_end Upper right corner of the grid.
106 * @param box_l Box size
107 * @return Values of the influence function at regular grid points.
108 */
109template <std::size_t S>
111 Utils::Vector3i const &n_start,
112 Utils::Vector3i const &n_end,
113 Utils::Vector3d const &box_l) {
114
115 auto const size = n_end - n_start;
116
117 /* The influence function grid */
118 auto g =
119 std::vector<double>(boost::accumulate(size, 1, std::multiplies<>()), 0.);
120
121 /* Skip influence function calculation in tuning mode,
122 the results need not be correct for timing. */
123 if (params.tuning) {
124 return g;
125 }
126
127 double fak1 = Utils::int_pow<3>(static_cast<double>(params.mesh[0])) * 2.0 /
128 Utils::sqr(box_l[0]);
129
130 auto const shifts = detail::calc_meshift(params.mesh, false);
131 auto const d_ops = detail::calc_meshift(params.mesh, true);
132
133 Utils::Vector3i n{};
134 for (n[0] = n_start[0]; n[0] < n_end[0]; n[0]++) {
135 for (n[1] = n_start[1]; n[1] < n_end[1]; n[1]++) {
136 for (n[2] = n_start[2]; n[2] < n_end[2]; n[2]++) {
137 auto const ind = Utils::get_linear_index(n - n_start, size,
139
140 if (((n[0] % (params.mesh[0] / 2) == 0) &&
141 (n[1] % (params.mesh[0] / 2) == 0) &&
142 (n[2] % (params.mesh[0] / 2) == 0))) {
143 g[ind] = 0.0;
144 } else {
145 auto const shift = Utils::Vector3i{shifts[0][n[0]], shifts[0][n[1]],
146 shifts[0][n[2]]};
147 auto const d_op =
148 Utils::Vector3i{d_ops[0][n[0]], d_ops[0][n[1]], d_ops[0][n[2]]};
149 auto const fak2 = G_opt_dipolar<S>(params, shift, d_op);
150 g[ind] = fak1 * fak2;
151 }
152 }
153 }
154 }
155 return g;
156}
157
159 Utils::Vector3i const &shift) {
160 using Utils::sinc;
161 auto constexpr limit = P3M_BRILLOUIN + 1;
162 auto const exponent = 2. * params.cao;
163
164 auto u_sum = 0.0;
165
166 auto const f1 = 1.0 / static_cast<double>(params.mesh[0]);
167
168 for (int mx = -limit; mx <= limit; mx++) {
169 auto const nmx = shift[0] + params.mesh[0] * mx;
170 auto const sx = std::pow(sinc(f1 * nmx), exponent);
171 for (int my = -limit; my <= limit; my++) {
172 auto const nmy = shift[1] + params.mesh[0] * my;
173 auto const sy = sx * std::pow(sinc(f1 * nmy), exponent);
174 for (int mz = -limit; mz <= limit; mz++) {
175 auto const nmz = shift[2] + params.mesh[0] * mz;
176 auto const sz = sy * std::pow(sinc(f1 * nmz), exponent);
177 u_sum += sz;
178 }
179 }
180 }
181 return u_sum;
182}
183
184/**
185 * @brief Calculate self-energy of the influence function.
186 *
187 * @param params DP3M parameters
188 * @param n_start Lower left corner of the grid
189 * @param n_end Upper right corner of the grid.
190 * @param g Energies on the grid.
191 * @return Total self-energy.
192 */
194 P3MParameters const &params, Utils::Vector3i const &n_start,
195 Utils::Vector3i const &n_end, std::vector<double> const &g) {
196 auto const size = n_end - n_start;
197
198 auto const shifts = detail::calc_meshift(params.mesh, false);
199 auto const d_ops = detail::calc_meshift(params.mesh, true);
200
201 double energy = 0.0;
202 Utils::Vector3i n{};
203 for (n[0] = n_start[0]; n[0] < n_end[0]; n[0]++) {
204 for (n[1] = n_start[1]; n[1] < n_end[1]; n[1]++) {
205 for (n[2] = n_start[2]; n[2] < n_end[2]; n[2]++) {
206 if (((n[0] % (params.mesh[0] / 2) == 0) &&
207 (n[1] % (params.mesh[0] / 2) == 0) &&
208 (n[2] % (params.mesh[0] / 2) == 0))) {
209 energy += 0.0;
210 } else {
211 auto const ind = Utils::get_linear_index(
212 n - n_start, size, Utils::MemoryOrder::ROW_MAJOR);
213 auto const shift = Utils::Vector3i{shifts[0][n[0]], shifts[0][n[1]],
214 shifts[0][n[2]]};
215 auto const d_op =
216 Utils::Vector3i{d_ops[0][n[0]], d_ops[0][n[1]], d_ops[0][n[2]]};
217 auto const U2 = G_opt_dipolar_self_energy(params, shift);
218 energy += g[ind] * U2 * d_op.norm2();
219 }
220 }
221 }
222 }
223 return energy;
224}
225
226#endif
227#endif
Vector implementation and trait types for boost qvm interoperability.
T norm2() const
Definition Vector.hpp:130
Common functions for dipolar and charge P3M.
This file contains the defaults for ESPResSo.
#define P3M_BRILLOUIN
P3M: Number of Brillouin zones taken into account in the calculation of the optimal influence functio...
Definition config.hpp:53
double G_opt_dipolar(P3MParameters const &params, Utils::Vector3i const &shift, Utils::Vector3i const &d_op)
Calculate the aliasing sums for the optimal influence function.
double grid_influence_function_self_energy(P3MParameters const &params, Utils::Vector3i const &n_start, Utils::Vector3i const &n_end, std::vector< double > const &g)
Calculate self-energy of the influence function.
std::vector< double > grid_influence_function(P3MParameters const &params, Utils::Vector3i const &n_start, Utils::Vector3i const &n_end, Utils::Vector3d const &box_l)
Map influence function over a grid.
double G_opt_dipolar_self_energy(P3MParameters const &params, Utils::Vector3i const &shift)
DEVICE_QUALIFIER constexpr T pi()
Ratio of diameter and circumference of a circle.
Definition constants.hpp:36
int get_linear_index(int a, int b, int c, const Vector3i &adim, MemoryOrder memory_order=MemoryOrder::COLUMN_MAJOR)
get the linear index from the position (a,b,c) in a 3D grid of dimensions adim.
Definition index.hpp:43
DEVICE_QUALIFIER T sinc(T d)
Calculates the sinc-function as sin(PI*x)/(PI*x).
Definition sinc.hpp:45
DEVICE_QUALIFIER constexpr T sqr(T x)
Calculates the SQuaRe of x.
Definition sqr.hpp:26
DEVICE_QUALIFIER constexpr T int_pow(T x)
Calculate integer powers.
Definition int_pow.hpp:61
static SteepestDescentParameters params
Currently active steepest descent instance.
Structure to hold P3M parameters and some dependent variables.
Definition common.hpp:67