78template <std::
size_t S, std::
size_t m>
82 auto constexpr exp_limit = 30.;
85 auto const cao =
params.cao;
86 auto const mesh =
params.mesh[0];
94 auto denominator = 0.;
97 m_start, m_stop, indices,
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);
108 [&](
unsigned dim,
int n) {
109 nm[dim] = shift[dim] + n * mesh;
110 fnm[dim] =
math::sinc(offset[dim] + n * mesh);
113 return numerator / (Utils::int_pow<S>(
static_cast<double>(d_op.
norm2())) *
114 Utils::int_pow<2>(denominator));
132template <
typename FloatType, std::
size_t S, std::
size_t m>
137 auto const size = n_stop - n_start;
140 auto g = std::vector<FloatType>(
Utils::product(size), FloatType(0));
148 auto prefactor = Utils::int_pow<3>(
static_cast<double>(
params.mesh[0])) * 2. *
149 Utils::int_pow<2>(inv_box_l[0]);
153 auto const half_mesh =
params.mesh[0] / 2;
157 auto index = std::size_t(0u);
160 n_start, n_stop, indices,
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));
169 [&](
unsigned dim,
int n) {
170 d_op_off[dim] = d_op[n];
171 shift_off[dim] = offset[n];
177template <std::
size_t m>
183 auto const cao =
params.cao;
184 auto const mesh =
params.mesh[0];
192 m_start, m_stop, indices,
194 [&](
unsigned dim,
int n) {
195 fnm[dim] =
math::sinc(offset[dim] + n * mesh);
212template <
typename FloatType, std::
size_t m>
219 auto const half_mesh =
params.mesh[0] / 2;
223 auto index = std::size_t(0u);
227 n_start, n_stop, indices,
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();
236 [&](
unsigned dim,
int n) {
237 d_op_off[dim] = d_op[n];
238 shift_off[dim] = offset[n];
Vector implementation and trait types for boost qvm interoperability.
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.
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 ¶ms, 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 ¶ms, 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 ¶ms, 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 ¶ms, Utils::Vector3i const &shift)
T product(Vector< T, N > const &v)
DEVICE_QUALIFIER constexpr T sqr(T x)
Calculates the SQuaRe of x.
DEVICE_QUALIFIER auto sinc(T x)
Calculate the function .
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.