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
22#pragma once
23
24#include "config/config.hpp"
25
26#if defined(DP3M)
27
28#include "p3m/common.hpp"
29#include "p3m/for_each_3d.hpp"
30#include "p3m/math.hpp"
31
32#include <utils/Vector.hpp>
34#include <utils/math/sqr.hpp>
35
36#include <cmath>
37#include <cstddef>
38#include <functional>
39#include <numbers>
40#include <vector>
41
42/**
43 * @brief Calculate the aliasing sums for the optimal influence function.
44 *
45 * Evaluate the aliasing sums in the numerator and denominator of
46 * the expression for the optimal influence function, see
47 * @cite hockney88a eq (8-22), p. 275.
48 *
49 * The full equation is:
50 * @f{align*}{
51 * G_{\text{opt}}(\vec{n}, S, \text{cao}) &=
52 * \displaystyle\frac{1}{\sum_\vec{m} U^2}
53 * \sum_\vec{m}U^2
54 * \displaystyle\frac{\left(\vec{d}_{\text{op}}[\vec{n}](\vec{s}[\vec{n}] +
55 * \vec{m}\odot\vec{N})\right)^S}
56 * {\left(\vec{s}[\vec{n}] + \vec{m}\odot\vec{N}\right)^2}
57 * e^{-\pi^2\left(\alpha\vec{N}\odot\vec{a}\right)^{-2}\left(\vec{s}[\vec{n}]
58 * +\vec{m}\odot\vec{N}\right)^2} \\
59 *
60 * U &= \operatorname{det}\left[I_3\cdot\operatorname{sinc}\left(
61 * \vec{s}[\vec{n}]\oslash{\vec{N}}+\vec{m}\odot\vec{N}\right)
62 * \right]^{\text{cao}}
63 * @f}
64 *
65 * with @f$ I_3 @f$ the 3x3 identity matrix, @f$ \vec{N} @f$ the global mesh
66 * size in k-space coordinates, @f$ \vec{a} @f$ the mesh size, @f$ \vec{m} @f$
67 * the Brillouin zone coordinates, @f$ \odot @f$ the Hadamard product,
68 * @f$ \oslash @f$ the Hadamard division.
69 *
70 * @tparam S Order of the differential operator (2 for energy, 3 for forces)
71 * @tparam m Number of Brillouin zones that contribute to the aliasing sums
72 *
73 * @param params DP3M parameters
74 * @param shift shifting integer vector for a specific k-vector
75 * @param d_op differential operator for a specific k-vector
76 * @return The optimal influence function for a specific k-vector.
77 */
78template <std::size_t S, std::size_t m>
80 Utils::Vector3i const &d_op) {
81
82 auto constexpr exp_limit = 30.;
83 auto constexpr m_start = Utils::Vector3i::broadcast(-m);
84 auto constexpr m_stop = Utils::Vector3i::broadcast(m + 1);
85 auto const cao = params.cao;
86 auto const mesh = params.mesh[0];
87 auto const offset =
88 static_cast<Utils::Vector3d>(shift) / static_cast<double>(mesh);
89 auto const exp_prefactor = Utils::sqr(std::numbers::pi / params.alpha_L);
90 auto indices = Utils::Vector3i{};
91 auto nm = Utils::Vector3i{};
92 auto fnm = Utils::Vector3d{};
93 auto numerator = 0.;
94 auto denominator = 0.;
95
97 m_start, m_stop, indices,
98 [&]() {
99 auto const U2 = std::pow(Utils::product(fnm), 2 * cao);
100 auto const nm2 = nm.norm2();
101 auto const exp_term = exp_prefactor * nm2;
102 if (exp_term < exp_limit) {
103 auto const f3 = U2 * std::exp(-exp_term) / nm2;
104 numerator += f3 * Utils::int_pow<S>(d_op * nm);
105 }
106 denominator += U2;
107 },
108 [&](unsigned dim, int n) {
109 nm[dim] = shift[dim] + n * mesh;
110 fnm[dim] = math::sinc(offset[dim] + n * mesh);
111 });
112
113 return numerator / (Utils::int_pow<S>(static_cast<double>(d_op.norm2())) *
114 Utils::int_pow<2>(denominator));
115}
116
117/**
118 * @brief Map influence function over a grid.
119 *
120 * This evaluates the optimal influence function @ref G_opt_dipolar
121 * over a regular grid of k vectors, and returns the values as a vector.
122 *
123 * @tparam S Order of the differential operator, e.g. 2 for energy, 3 for force
124 * @tparam m Number of Brillouin zones that contribute to the aliasing sums
125 *
126 * @param params DP3M parameters
127 * @param n_start Lower left corner of the grid in k-space.
128 * @param n_stop Upper right corner of the grid in k-space.
129 * @param inv_box_l Inverse box length
130 * @return Values of the influence function at regular grid points.
131 */
132template <typename FloatType, std::size_t S, std::size_t m>
133std::vector<FloatType> grid_influence_function(
134 P3MParameters const &params, Utils::Vector3i const &n_start,
135 Utils::Vector3i const &n_stop, Utils::Vector3d const &inv_box_l) {
136
137 auto const size = n_stop - n_start;
138
139 /* The influence function grid */
140 auto g = std::vector<FloatType>(Utils::product(size), FloatType(0));
141
142 /* Skip influence function calculation in tuning mode,
143 the results need not be correct for timing. */
144 if (params.tuning) {
145 return g;
146 }
147
148 auto prefactor = Utils::int_pow<3>(static_cast<double>(params.mesh[0])) * 2. *
149 Utils::int_pow<2>(inv_box_l[0]);
150
151 auto const offset = calc_p3m_mesh_shift(params.mesh, false)[0];
152 auto const d_op = calc_p3m_mesh_shift(params.mesh, true)[0];
153 auto const half_mesh = params.mesh[0] / 2;
154 auto indices = Utils::Vector3i{};
155 auto shift_off = Utils::Vector3i{};
156 auto d_op_off = Utils::Vector3i{};
157 auto index = std::size_t(0u);
158
160 n_start, n_stop, indices,
161 [&]() {
162 if (((indices[0] % half_mesh != 0) or (indices[1] % half_mesh != 0) or
163 (indices[2] % half_mesh != 0))) {
164 g[index] = FloatType(
165 prefactor * G_opt_dipolar<S, m>(params, shift_off, d_op_off));
166 }
167 ++index;
168 },
169 [&](unsigned dim, int n) {
170 d_op_off[dim] = d_op[n];
171 shift_off[dim] = offset[n];
172 });
173
174 return g;
175}
176
177template <std::size_t m>
179 Utils::Vector3i const &shift) {
180
181 auto constexpr m_start = Utils::Vector3i::broadcast(-m);
182 auto constexpr m_stop = Utils::Vector3i::broadcast(m + 1);
183 auto const cao = params.cao;
184 auto const mesh = params.mesh[0];
185 auto const offset =
186 static_cast<Utils::Vector3d>(shift) / static_cast<double>(mesh);
187 auto indices = Utils::Vector3i{};
188 auto fnm = Utils::Vector3d{};
189 auto energy = 0.;
190
192 m_start, m_stop, indices,
193 [&]() { energy += std::pow(Utils::product(fnm), 2 * cao); },
194 [&](unsigned dim, int n) {
195 fnm[dim] = math::sinc(offset[dim] + n * mesh);
196 });
197
198 return energy;
199}
200
201/**
202 * @brief Calculate self-energy of the influence function.
203 *
204 * @tparam m Number of Brillouin zones that contribute to the aliasing sums
205 *
206 * @param params DP3M parameters
207 * @param n_start Lower left corner of the grid in k-space.
208 * @param n_stop Upper right corner of the grid in k-space.
209 * @param g Energies on the grid.
210 * @return Total self-energy.
211 */
212template <typename FloatType, std::size_t m>
214 P3MParameters const &params, Utils::Vector3i const &n_start,
215 Utils::Vector3i const &n_stop, std::vector<FloatType> const &g) {
216
217 auto const offset = calc_p3m_mesh_shift(params.mesh, false)[0];
218 auto const d_op = calc_p3m_mesh_shift(params.mesh, true)[0];
219 auto const half_mesh = params.mesh[0] / 2;
220 auto indices = Utils::Vector3i{};
221 auto shift_off = Utils::Vector3i{};
222 auto d_op_off = Utils::Vector3i{};
223 auto index = std::size_t(0u);
224 auto energy = 0.;
225
227 n_start, n_stop, indices,
228 [&]() {
229 if (((indices[0] % half_mesh != 0) or (indices[1] % half_mesh != 0) or
230 (indices[2] % half_mesh != 0))) {
231 auto const U2 = G_opt_dipolar_self_energy<m>(params, shift_off);
232 energy += static_cast<double>(g[index]) * U2 * d_op_off.norm2();
233 }
234 ++index;
235 },
236 [&](unsigned dim, int n) {
237 d_op_off[dim] = d_op[n];
238 shift_off[dim] = offset[n];
239 });
240
241 return energy;
242}
243
244#endif // defined(DP3M)
Vector implementation and trait types for boost qvm interoperability.
T norm2() const
Definition Vector.hpp:137
static DEVICE_QUALIFIER constexpr Vector< T, N > broadcast(typename Base::value_type const &value)
Create a vector that has all entries set to the same value.
Definition Vector.hpp:110
This file contains the defaults for ESPResSo.
and std::invocable< Projector, unsigned, int > void for_each_3d(detail::IndexVectorConcept auto &&start, detail::IndexVectorConcept auto &&stop, detail::IndexVectorConcept auto &&counters, Kernel &&kernel, Projector &&projector=detail::noop_projector)
Repeat an operation on every element of a 3D grid.
double grid_influence_function_self_energy(P3MParameters const &params, Utils::Vector3i const &n_start, Utils::Vector3i const &n_stop, std::vector< FloatType > const &g)
Calculate self-energy of the influence function.
std::vector< FloatType > grid_influence_function(P3MParameters const &params, Utils::Vector3i const &n_start, Utils::Vector3i const &n_stop, Utils::Vector3d const &inv_box_l)
Map influence function over a grid.
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 G_opt_dipolar_self_energy(P3MParameters const &params, Utils::Vector3i const &shift)
T product(Vector< T, N > const &v)
Definition Vector.hpp:374
DEVICE_QUALIFIER constexpr T sqr(T x)
Calculates the SQuaRe of x.
Definition sqr.hpp:28
DEVICE_QUALIFIER auto sinc(T x)
Calculate the function .
Definition math.hpp:53
Common functions for dipolar and charge P3M.
std::array< std::vector< int >, 3 > calc_p3m_mesh_shift(Utils::Vector3i const &mesh_size, bool zero_out_midpoint=false)
Calculate indices that shift P3MParameters::mesh by mesh/2.
static SteepestDescentParameters params
Currently active steepest descent instance.
Structure to hold P3M parameters and some dependent variables.