IPPL API Reference
Independent Parallel Particle Layer C++ API
Loading...
Searching...
No Matches
CurrentDeposition.hpp
1#ifndef IPPL_PROJECT_CURRENT_FDTD_H
2#define IPPL_PROJECT_CURRENT_FDTD_H
3
4#include "FEM/GridPathSegmenter.h"
5
6namespace ippl {
7
18template <typename Mesh,
19 typename ChargeAttrib,
20 typename PosAttrib,
21 typename JField,
22 typename policy_type = Kokkos::RangePolicy<>>
23inline void assemble_current_yee(const Mesh& mesh,
24 const ChargeAttrib& q_attrib,
25 const PosAttrib& X0,
26 const PosAttrib& X1,
27 JField& J_field,
28 policy_type iteration_policy,
29 typename Mesh::value_type dt)
30{
31 using T = typename Mesh::value_type;
32 constexpr unsigned Dim = Mesh::Dimension;
33 static_assert(Dim == 2 || Dim == 3,
34 "assemble_current_yee only supports 2D and 3D");
35
36 const auto origin = mesh.getOrigin();
37 const auto h = mesh.getMeshSpacing();
38 auto ldom = J_field.getLayout().getLocalNDIndex();
39 const int nghost = J_field.getNghost();
40 auto view = J_field.getView();
41
42 Kokkos::parallel_for("assemble_current_yee", iteration_policy,
43 KOKKOS_LAMBDA(const std::size_t p) {
44
46 ::split(X0(p), X1(p), origin, h);
47
48 const T q_over_dt = q_attrib(p) / dt;
49
50 for (unsigned i = 0; i < Dim + 1; ++i) {
51 const auto& seg = segs[i];
52
53 Vector<T, Dim> dp{};
54 T len_sq = T(0);
55 for (unsigned d = 0; d < Dim; ++d) {
56 dp[d] = seg.p1[d] - seg.p0[d];
57 len_sq += dp[d] * dp[d];
58 }
59 if (len_sq == T(0)) continue;
60
61 Vector<T, Dim> mid{};
62 for (unsigned d = 0; d < Dim; ++d)
63 mid[d] = T(0.5) * (seg.p0[d] + seg.p1[d]);
64
65 Kokkos::Array<size_t, Dim> cellIdx;
66 for (unsigned d = 0; d < Dim; ++d)
67 cellIdx[d] = static_cast<size_t>((mid[d] - origin[d]) / h[d]);
68
69 Kokkos::Array<T, Dim> xi;
70 for (unsigned d = 0; d < Dim; ++d)
71 xi[d] = (mid[d] - origin[d]) / h[d] - T(cellIdx[d]);
72
73 // For component c, scatter to 2^(Dim-1) transverse neighbours.
74 // In direction c (staggered): fixed cell face, no weight.
75 // In each transverse direction d: linear CIC weight between
76 // nodes cellIdx[d] and cellIdx[d]+1.
77 for (unsigned c = 0; c < Dim; ++c) {
78 const T val_c = q_over_dt * dp[c];
79
80 for (unsigned corner = 0; corner < (1u << (Dim - 1)); ++corner) {
81 size_t idx[Dim];
82 T weight = T(1);
83 unsigned bit = 0;
84 for (unsigned d = 0; d < Dim; ++d) {
85 if (d == c) {
86 idx[d] = cellIdx[d] - ldom.first()[d] + nghost;
87 } else {
88 const unsigned offset = (corner >> bit) & 1u;
89 weight *= offset ? xi[d] : (T(1) - xi[d]);
90 idx[d] = cellIdx[d] - ldom.first()[d] + nghost + offset;
91 ++bit;
92 }
93 }
94
95 Kokkos::atomic_add(&(apply(view, idx)[c]), val_c * weight);
96 }
97 }
98 }
99 });
100}
101
102} // namespace ippl
103#endif
Definition Mesh.h:15
Definition Vector.h:23
Definition Archive.h:20
KOKKOS_INLINE_FUNCTION constexpr decltype(auto) apply(const View &view, const Coords &coords)
Definition IpplOperations.h:64
void assemble_current_yee(const Mesh &mesh, const ChargeAttrib &q_attrib, const PosAttrib &X0, const PosAttrib &X1, JField &J_field, policy_type iteration_policy, typename Mesh::value_type dt)
Deposit current density onto a Yee-staggered grid.
Definition CurrentDeposition.hpp:23
Definition GridPathSegmenter.h:15