IPPL API Reference
Independent Parallel Particle Layer C++ API
Loading...
Searching...
No Matches
ProjectCurrent.hpp
1#ifndef IPPL_PROJECT_CURRENT_H
2#define IPPL_PROJECT_CURRENT_H
3
4namespace ippl {
5
17template <typename Mesh,
18 typename ChargeAttrib,
19 typename PosAttrib,
20 typename FEMVector,
21 typename NedelecSpace,
22 typename policy_type = Kokkos::RangePolicy<>>
23inline void assemble_current_nedelec(const Mesh& mesh,
24 const ChargeAttrib& q_attrib,
25 const PosAttrib& X0,
26 const PosAttrib& X1,
27 FEMVector& fem_vector,
28 const NedelecSpace& space,
29 policy_type iteration_policy,
30 typename Mesh::value_type dt)
31{
32 using T = typename Mesh::value_type;
33 constexpr unsigned Dim = Mesh::Dimension;
34
35 const auto origin = mesh.getOrigin();
36 const auto h = mesh.getMeshSpacing();
37 auto ldom = space.getLocalNDIndex();
38
39 // Atomic view for safe concurrent scatter from multiple particles.
40 using AtomicViewType = Kokkos::View<T*, Kokkos::MemoryTraits<Kokkos::Atomic>>;
41 AtomicViewType atomic_view = fem_vector.getView();
42
43 constexpr unsigned numDOFs = NedelecSpace::numElementDOFs;
44
45 Kokkos::parallel_for("assemble_current_nedelec", iteration_policy,
46 KOKKOS_LAMBDA(const std::size_t p) {
47
48 // Split trajectory
50 ::split(X0(p), X1(p), origin, h);
51
52 const T q_over_dt = q_attrib(p) / dt;
53
54 for (unsigned i = 0; i < Dim + 1; ++i) {
55 const auto& seg = segs[i];
56
57 // Calcualte displacement of this sub-segment
58 Vector<T, Dim> dp{};
59 T len_sq = T(0);
60 for (unsigned d = 0; d < Dim; ++d) {
61 dp[d] = seg.p1[d] - seg.p0[d];
62 len_sq += dp[d] * dp[d];
63 }
64 //Skip unphisical zero-segments
65 if (len_sq == T(0)) continue;
66
67 // Calculate midpoint of the segment
68 Vector<T, Dim> mid{};
69 for (unsigned d = 0; d < Dim; ++d)
70 mid[d] = T(0.5) * (seg.p0[d] + seg.p1[d]);
71
72 // Index of the cell that contains the midpoint
73 typename NedelecSpace::indices_t cellIdx{};
74 for (unsigned d = 0; d < Dim; ++d)
75 cellIdx[d] = static_cast<size_t>((mid[d] - origin[d]) / h[d]);
76
77 // Calculate local reference coordinate
78 typename NedelecSpace::point_t xi{};
79 for (unsigned d = 0; d < Dim; ++d)
80 xi[d] = (mid[d] - origin[d]) / h[d] - T(cellIdx[d]);
81
82 // FEM-vector indices for the edge DOFs of this cell.
83 auto dofIdx = space.getFEMVectorDOFIndices(cellIdx, ldom);
84
85 // Scatter onto each edge DOF k.
86 for (unsigned k = 0; k < numDOFs; ++k) {
87 auto phi_k = space.evaluateRefElementShapeFunction(k, xi);
88 T contrib = T(0);
89 for (unsigned d = 0; d < Dim; ++d)
90 contrib += q_over_dt * dp[d] * phi_k[d];
91 atomic_view(dofIdx[k]) += contrib;
92 }
93 }
94 });
95}
96
97} // namespace ippl
98#endif
1D vector used in the context of FEM.
Definition FEMVector.h:34
const Kokkos::View< T * > & getView() const
Get underlying data view.
Definition FEMVector.hpp:223
Definition Mesh.h:15
A class representing a Nedelec space for finite element methods on a structured, rectilinear grid.
Definition NedelecSpace.h:37
KOKKOS_FUNCTION Vector< size_t, numElementDOFs > getFEMVectorDOFIndices(const size_t &elementIndex, NDIndex< Dim > ldom) const
Get the DOF indices (vector of indices) corresponding to the position inside the FEMVector of an elem...
Definition NedelecSpace.hpp:343
NDIndex< Dim > getLocalNDIndex() const
Return the local NDIndex of this rank's subdomain.
Definition NedelecSpace.h:124
KOKKOS_FUNCTION point_t evaluateRefElementShapeFunction(const size_t &localDOF, const point_t &localPoint) const
Basis functions and gradients /////////////////////////////////////.
Definition NedelecSpace.hpp:706
Definition Vector.h:23
Definition Archive.h:20
void assemble_current_nedelec(const Mesh &mesh, const ChargeAttrib &q_attrib, const PosAttrib &X0, const PosAttrib &X1, FEMVector &fem_vector, const NedelecSpace &space, policy_type iteration_policy, typename Mesh::value_type dt)
Assemble the current density RHS vector for a Nedelec FEM space.
Definition ProjectCurrent.hpp:23
Definition GridPathSegmenter.h:15