26#if defined(ESPRESSO_DP3M)
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;
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[dim];
110 fnm[dim] =
math::sinc(offset[dim] + n * mesh[dim]);
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,
138 auto const size = n_stop - n_start;
141 auto g = std::vector<FloatType>(
Utils::product(size), FloatType(0));
154 auto const half_mesh = params.
mesh / 2;
160 n_start, n_stop, indices,
162 if (((indices[0u] % half_mesh[0u] != 0) or
163 (indices[1u] % half_mesh[1u] != 0) or
164 (indices[2u] % half_mesh[2u] != 0))) {
166 Utils::get_linear_index<memory_order>(indices - n_start, size);
167 g[index] = FloatType(
168 prefactor * G_opt_dipolar<S, m>(params, shift_off, d_op_off));
171 [&](
unsigned dim,
int n) {
172 d_op_off[dim] = d_op[n];
173 shift_off[dim] = offset[n];
179template <std::
size_t m>
185 auto const cao = params.
cao;
186 auto const &mesh = params.
mesh;
194 m_start, m_stop, indices,
196 [&](
unsigned dim,
int n) {
197 fnm[dim] =
math::sinc(offset[dim] + n * mesh[dim]);
214template <
typename FloatType, std::
size_t m>
221 auto const half_mesh = params.
mesh / 2;
225 auto index = std::size_t(0u);
229 n_start, n_stop, indices,
231 if (((indices[0u] % half_mesh[0u] != 0) or
232 (indices[1u] % half_mesh[1u] != 0) or
233 (indices[2u] % half_mesh[2u] != 0))) {
234 auto const U2 = G_opt_dipolar_self_energy<m>(params, shift_off);
235 energy +=
static_cast<double>(g[index]) * U2 * d_op_off.norm2();
239 [&](
unsigned dim,
int n) {
240 d_op_off[dim] = d_op[n];
241 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) noexcept
Create a vector that has all entries set to the same value.
constexpr T norm2() const
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.
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)
std::vector< FloatType > grid_influence_function_dipolar(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.
T product(Vector< T, N > const &v)
DEVICE_QUALIFIER constexpr T sqr(T x)
Calculates the SQuaRe of x.
auto hadamard_division(Vector< T, N > const &a, Vector< U, N > const &b)
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.
Structure to hold P3M parameters and some dependent variables.
int cao
charge assignment order ([0,7]).
double alpha_L
Ewald splitting parameter (0.
bool tuning
tuning or production?
Utils::Vector3i mesh
number of mesh points per coordinate direction (>0), in real space.