IPPL (Independent Parallel Particle Layer)
IPPL
Loading...
Searching...
No Matches
TruncatedGreenParticleInteraction.hpp
Go to the documentation of this file.
1//
2// Class TruncatedGreenParticleInteraction
3// This class implements the short range interaction part of the green function splitting obtained
4// by taking the gradient of [forceConstant * (1 - erf(alpha * r)) / r]. The long range part is
5// handled by FFTTruncatedGreenPeriodicSolver.
6//
7// It assumes that ParticleContainer implements a function forAllPairs() to iterate over all
8// relevant particle pairs.
9//
10
11namespace ippl {
12 template <typename ParticleContainer, typename ScalarAttribute, typename VectorAttribute>
13 KOKKOS_INLINE_FUNCTION constexpr
14 typename TruncatedGreenParticleInteraction<ParticleContainer, ScalarAttribute,
15 VectorAttribute>::Vector_t
16 TruncatedGreenParticleInteraction<ParticleContainer, ScalarAttribute,
17 VectorAttribute>::fieldFromPair(const Vector_t& dist,
18 Scalar_t r2,
19 Scalar_t alpha,
20 Scalar_t forceConstant,
21 Scalar_t qm) {
22 const Scalar_t r = Kokkos::sqrt(r2);
23
24 // F = - q * forceConstant grad [(1 - erf(alpha * r)) / r].
25 return forceConstant * qm * (dist / r)
26 * (2.0 * alpha * Kokkos::exp(-alpha * alpha * r2)
27 / (Kokkos::sqrt(Kokkos::numbers::pi) * r)
28 + (1.0 - Kokkos::erf(alpha * r)) / r2);
29 }
30
31 template <typename ParticleContainer, typename ScalarAttribute, typename VectorAttribute>
33 VectorAttribute>::solve() {
34 static IpplTimings::TimerRef solveTimer =
35 IpplTimings::getTimer("TruncatedGreenParticleInteraction::solve()");
36 IpplTimings::startTimer(solveTimer);
37 // get particle data
38 auto& Field = Field_m;
39 const auto& R = R_m;
40 const auto& QM = QM_m;
41
42 // get simulation specific data
43 const auto rcut2 = std::pow<Scalar_t>(this->params_m.template get<Scalar_t>("rcut"), 2);
44 const auto alpha = this->params_m.template get<Scalar_t>("alpha");
45 const auto forceConstant = this->params_m.template get<Scalar_t>("force_constant");
46
47 const auto& particleLayout = this->pc_m.getLayout();
48
49 particleLayout.template forEachPair<execution_space>(
50 KOKKOS_LAMBDA(const size_t& i, const size_t& j) {
51 const Vector_t dist_ij = R(i) - R(j);
52 const Scalar_t rsq_ij = dist_ij.dot(dist_ij);
53
54 if (rsq_ij >= rcut2) {
55 return;
56 }
57
58 const auto F_ij = fieldFromPair(dist_ij, rsq_ij, alpha, forceConstant, QM(j));
59
60 // add force to particle i, don't do it for j as the ranges of i and j are
61 // asymmetric
62 Kokkos::atomic_sub(&Field(i), F_ij);
63 });
64 IpplTimings::stopTimer(solveTimer);
65 }
66} // namespace ippl
ippl::Vector< T, Dim > Vector_t
Definition datatypes.h:38
ippl::Field< T, Dim, Mesh_t< Dim >, Centering_t< Dim >, ViewArgs... > Field
Definition datatypes.h:29
Definition Archive.h:20
KOKKOS_INLINE_FUNCTION auto & get(Tuple< Ts... > &t)
Accessor function to get an element mutable reference at a specific index from a Tuple.
Definition Tuple.h:314
VectorAttribute & Field_m
! The electric or gravitational field
const ScalarAttribute & QM_m
! Charge or Mass of the particles
const VectorAttribute & R_m
! Positions of the particles
static KOKKOS_INLINE_FUNCTION constexpr Vector_t fieldFromPair(const Vector_t &dist, Scalar_t r2, Scalar_t alpha, Scalar_t forceConstant, Scalar_t qm)
Timing::TimerRef TimerRef
static TimerRef getTimer(const char *nm)
static void stopTimer(TimerRef t)
static void startTimer(TimerRef t)