ESPResSo
Extensible Simulation Package for Research on Soft Matter Systems
Loading...
Searching...
No Matches
influence_function.hpp
Go to the documentation of this file.
1/*
2 * Copyright (C) 2019-2024 The ESPResSo project
3 *
4 * This file is part of ESPResSo.
5 *
6 * ESPResSo is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * ESPResSo is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#pragma once
21
22#include "config/config.hpp"
23
24#if defined(P3M)
25
26#include "p3m/common.hpp"
27#include "p3m/for_each_3d.hpp"
28#include "p3m/math.hpp"
29
30#include <utils/Vector.hpp>
31#include <utils/index.hpp>
33#include <utils/math/sqr.hpp>
34
35#include <cmath>
36#include <cstddef>
37#include <functional>
38#include <numbers>
39#include <utility>
40#include <vector>
41
42/**
43 * @brief Calculate the aliasing sums for the optimal influence function.
44 *
45 * This implements Eq. 30 of @cite cerda08d, which can be used
46 * for monopole and dipole P3M by choosing the appropriate S factor.
47 *
48 * The full equation is:
49 * @f{align*}{
50 * G_{\text{opt}}(\vec{n}, S, \text{cao}) &=
51 * \displaystyle\frac{4\pi}{\sum_\vec{m} U^2}
52 * \sum_\vec{m}U^2
53 * \displaystyle\frac{\left(\vec{k}\odot\vec{k}_m\right)^S}
54 * {|\vec{k}_m|^2}
55 * e^{-1/(2\alpha)^2|\vec{k}_m|^2} \\
56 *
57 * U &= \operatorname{det}\left[I_3\cdot\operatorname{sinc}\left(
58 * \frac{\vec{k}_m\odot\vec{a}}{2\pi}\right)\right]^{\text{cao}} \\
59 *
60 * \vec{k} &= \frac{2\pi}{\vec{N}\odot\vec{a}}\vec{s}[\vec{n}] \\
61 *
62 * \vec{k}_m &= \frac{2\pi}{\vec{N}\odot\vec{a}}
63 * \left(\vec{s}[\vec{n}]+\vec{m}\odot\vec{N}\right)
64 * @f}
65 *
66 * with @f$ I_3 @f$ the 3x3 identity matrix, @f$ \vec{N} @f$ the global mesh
67 * size in k-space coordinates, @f$ \vec{a} @f$ the mesh size, @f$ \vec{m} @f$
68 * the Brillouin zone coordinates, @f$ \odot @f$ the Hadamard product.
69 *
70 * @tparam S Order of the differential operator (0 for potential, 1 for E-field)
71 * @tparam m Number of Brillouin zones that contribute to the aliasing sums
72 *
73 * @param params P3M parameters
74 * @param k k-vector to evaluate the function for.
75 * @return The optimal influence function for a specific k-vector.
76 */
77template <std::size_t S, std::size_t m>
78double G_opt(P3MParameters const &params, Utils::Vector3d const &k) {
79
80 auto const k2 = k.norm2();
81 if (k2 == 0.) {
82 return 0.;
83 }
84
85 auto constexpr exp_limit = 30.;
86 auto constexpr m_start = Utils::Vector3i::broadcast(-m);
87 auto constexpr m_stop = Utils::Vector3i::broadcast(m + 1);
88 auto const cao = params.cao;
89 auto const exponent_prefactor = Utils::sqr(1. / (2. * params.alpha));
90 auto const wavevector = (2. * std::numbers::pi) / params.a;
91 auto const wavevector_i = 1. / wavevector;
92 auto indices = Utils::Vector3i{};
93 auto km = Utils::Vector3d{};
94 auto fnm = Utils::Vector3d{};
95 auto numerator = 0.;
96 auto denominator = 0.;
97
99 m_start, m_stop, indices,
100 [&]() {
101 auto const U2 = std::pow(Utils::product(fnm), 2 * cao);
102 auto const km2 = km.norm2();
103 auto const exp_term = exponent_prefactor * km2;
104 if (exp_term < exp_limit) {
105 auto const f3 = std::exp(-exp_term) * (4. * std::numbers::pi / km2);
106 numerator += U2 * f3 * Utils::int_pow<S>(k * km);
107 }
108 denominator += U2;
109 },
110 [&](unsigned dim, int n) {
111 km[dim] = k[dim] + n * wavevector[dim];
112 fnm[dim] = math::sinc(km[dim] * wavevector_i[dim]);
113 });
114
115 return numerator / (Utils::int_pow<S>(k2) * Utils::sqr(denominator));
116}
117
118/**
119 * @brief Map influence function over a grid.
120 *
121 * This evaluates the optimal influence function @ref G_opt
122 * over a regular grid of k vectors, and returns the values as a vector.
123 *
124 * @tparam S Order of the differential operator (0 for potential, 1 for E-field)
125 * @tparam m Number of Brillouin zones that contribute to the aliasing sums
126 *
127 * @param params P3M parameters.
128 * @param n_start Lower left corner of the grid in k-space.
129 * @param n_stop Upper right corner of the grid in k-space.
130 * @param KX k-space x-axis index.
131 * @param KY k-space y-axis index.
132 * @param KZ k-space z-axis index.
133 * @param inv_box_l Inverse box length.
134 * @return Values of G_opt at regular grid points.
135 */
136template <typename FloatType, std::size_t S, std::size_t m>
137std::vector<FloatType> grid_influence_function(
138 P3MParameters const &params, Utils::Vector3i const &n_start,
139 Utils::Vector3i const &n_stop, int const KX, int const KY, int const KZ,
140 Utils::Vector3d const &inv_box_l) {
141
142 auto const shifts = calc_p3m_mesh_shift(params.mesh);
143 auto const size = n_stop - n_start;
144
145 /* The influence function grid */
146 auto g = std::vector<FloatType>(Utils::product(size), FloatType(0));
147
148 /* Skip influence function calculation in tuning mode,
149 the results need not be correct for timing. */
150 if (params.tuning) {
151 return g;
152 }
153
154 auto const wavevector = (2. * std::numbers::pi) * inv_box_l;
155 auto const half_mesh = params.mesh / 2;
156 auto indices = Utils::Vector3i{};
157 auto index = std::size_t(0u);
158
159 for_each_3d(n_start, n_stop, indices, [&]() {
160 if ((indices[KX] % half_mesh[0u] != 0) or
161 (indices[KY] % half_mesh[1u] != 0) or
162 (indices[KZ] % half_mesh[2u] != 0)) {
163 auto const k =
164 Utils::Vector3d{{shifts[0u][indices[KX]] * wavevector[0u],
165 shifts[1u][indices[KY]] * wavevector[1u],
166 shifts[2u][indices[KZ]] * wavevector[2u]}};
167 g[index] = FloatType(G_opt<S, m>(params, k));
168 }
169 ++index;
170 });
171
172 return g;
173}
174
175#endif // defined(P3M)
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.
std::vector< FloatType > grid_influence_function(P3MParameters const &params, Utils::Vector3i const &n_start, Utils::Vector3i const &n_stop, int const KX, int const KY, int const KZ, Utils::Vector3d const &inv_box_l)
Map influence function over a grid.
double G_opt(P3MParameters const &params, Utils::Vector3d const &k)
Calculate the aliasing sums for the optimal influence function.
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.