IPPL (Independent Parallel Particle Layer)
IPPL
Loading...
Searching...
No Matches
FEMInterpolate.hpp
Go to the documentation of this file.
1#ifndef IPPL_FEMINTERPOLATE_H
2#define IPPL_FEMINTERPOLATE_H
3
4
5namespace ippl {
6
14 template <typename T, unsigned Dim>
15 KOKKOS_INLINE_FUNCTION void
17 const Vector<T, Dim>& origin,
18 const Vector<T, Dim>& x,
20 Vector<T, Dim>& xi) {
21
22 for (unsigned d = 0; d < Dim; ++d) {
23 const T s = (x[d] - origin[d]) / hr[d]; // To cell units
24 const size_t e = static_cast<size_t>(Kokkos::floor(s));
25 e_nd[d] = e;
26 xi[d] = s - static_cast<T>(e);
27 }
28 }
29
30
31 template<class View, class IVec, std::size_t... Is>
32 KOKKOS_INLINE_FUNCTION
33 auto view_ptr_impl(View& v, const IVec& I, std::index_sequence<Is...>)
34 -> decltype(&v(I[Is]...)) {
35 return &v(I[Is]...);
36 }
37
38 template<int D, class View, class IVec>
39 KOKKOS_INLINE_FUNCTION
40 auto view_ptr(View& v, const IVec& I)
41 -> decltype(view_ptr_impl(v, I, std::make_index_sequence<D>{})) {
42 return view_ptr_impl(v, I, std::make_index_sequence<D>{});
43 }
44
58 template <typename AttribIn, typename Field, typename PosAttrib, typename Space,
59 typename policy_type = Kokkos::RangePolicy<typename Field::execution_space>>
60 inline void assemble_rhs_from_particles(const AttribIn& attrib, Field& f,
61 const PosAttrib& pp, const Space& space,
62 policy_type iteration_policy)
63 {
64 constexpr unsigned Dim = Field::dim;
65 using T = typename Field::value_type;
66 using view_type = typename Field::view_type;
67 using mesh_type = typename Field::Mesh_t;
68
69 static IpplTimings::TimerRef t = IpplTimings::getTimer("assemble_rhs_from_particles(P1)");
70
72
73 view_type view = f.getView();
74
75 // Mesh / layout (for locating + indexing into the field view)
76 const mesh_type& mesh = f.get_mesh();
77
78 const auto hr = mesh.getMeshSpacing();
79 const auto origin = mesh.getOrigin();
80
81 const FieldLayout<Dim>& layout = f.getLayout();
82 const NDIndex<Dim>& lDom = layout.getLocalNDIndex();
83 const int nghost = f.getNghost();
84
85 // Particle attribute/device views
86 auto d_attr = attrib.getView(); // scalar weight per particle (e.g. charge)
87 auto d_pos = pp.getView(); // positions (Vector<T,Dim>) per particle
88
89 // make device copy of space
90 auto device_space = space.getDeviceMirror();
91
92 Kokkos::parallel_for("assemble_rhs_from_particles_P1", iteration_policy,
93 KOKKOS_LAMBDA(const size_t p) {
94 const Vector<T, Dim> x = d_pos(p);
95 const T val = d_attr(p);
96
99
100 locate_element_nd_and_xi<T, Dim>(hr, origin, x, e_nd, xi);
101
102 // DOFs for this element
103 const auto dofs = device_space.getGlobalDOFIndices(e_nd);
104
105 // Deposit into each vertex/DOF
106 for (size_t a = 0; a < dofs.dim; ++a) {
107 const size_t local = device_space.getLocalDOFIndex(e_nd, dofs[a]);
108 const T w = device_space.evaluateRefElementShapeFunction(local, xi);
109
110 // ND coords (global, vertex-centered)
111 const auto v_nd = device_space.getMeshVertexNDIndex(dofs[a]);
112 Vector<size_t, Dim> I; // indices into view
113
114 for (unsigned d = 0; d < Dim; ++d) {
115 I[d] = static_cast<size_t>(v_nd[d] - lDom.first()[d] + nghost);
116 }
117 Kokkos::atomic_add(view_ptr<Dim>(view, I), val * w);
118 }
119 }
120 );
121
122 static IpplTimings::TimerRef accumulateHaloTimer = IpplTimings::getTimer("accumulateHalo");
123 IpplTimings::startTimer(accumulateHaloTimer);
124 f.accumulateHalo();
125 IpplTimings::stopTimer(accumulateHaloTimer);
126
127 }
128
129 template<class View, class IVec, std::size_t... Is>
130 KOKKOS_INLINE_FUNCTION
131 decltype(auto) view_ref_impl(View& v, const IVec& I, std::index_sequence<Is...>) {
132 return v(I[Is]...);
133 }
134
135 template<int D, class View, class IVec>
136 KOKKOS_INLINE_FUNCTION
137 decltype(auto) view_ref(View& v, const IVec& I) {
138 return view_ref_impl(v, I, std::make_index_sequence<D>{});
139 }
140
154 template <typename AttribOut, typename Field, typename PosAttrib, typename Space,
155 typename policy_type = Kokkos::RangePolicy<typename Field::execution_space>>
156 inline void interpolate_to_diracs(AttribOut& attrib_out,
157 const Field& coeffs,
158 const PosAttrib& pp,
159 const Space& space,
160 policy_type iteration_policy)
161 {
162 constexpr unsigned Dim = Field::dim;
163 using T = typename AttribOut::value_type;
164 using field_value_type = typename Field::value_type;
165 using view_type = typename Field::view_type;
166 using mesh_type = typename Field::Mesh_t;
167
168 static IpplTimings::TimerRef timer =
169 IpplTimings::getTimer("interpolate_field_to_particles(P1)");
171
172 view_type view = coeffs.getView();
173 const mesh_type& mesh = coeffs.get_mesh();
174
175 const auto hr = mesh.getMeshSpacing();
176 const auto origin = mesh.getOrigin();
177
178 const FieldLayout<Dim>& layout = coeffs.getLayout();
179 const NDIndex<Dim>& lDom = layout.getLocalNDIndex();
180 const int nghost = coeffs.getNghost();
181
182 // Particle device views
183 auto d_pos = pp.getView();
184 auto d_out = attrib_out.getView();
185
186 // make device copy of space
187 auto device_space = space.getDeviceMirror();
188 Kokkos::parallel_for("interpolate_to_diracs_P1", iteration_policy,
189 KOKKOS_LAMBDA(const size_t p) {
190
191 const Vector<T, Dim> x = d_pos(p);
192
195 locate_element_nd_and_xi<T, Dim>(hr, origin, x, e_nd, xi);
196
197 const auto dofs = device_space.getGlobalDOFIndices(e_nd);
198
199 field_value_type up = field_value_type(0);
200
201 for (size_t a = 0; a < dofs.dim; ++a) {
202 const size_t local = device_space.getLocalDOFIndex(e_nd, dofs[a]);
203 const field_value_type w = device_space.evaluateRefElementShapeFunction(local, xi);
204
205 const auto v_nd = device_space.getMeshVertexNDIndex(dofs[a]);
207 for (unsigned d = 0; d < Dim; ++d) {
208 I[d] = static_cast<size_t>(v_nd[d] - lDom.first()[d] + nghost);
209 }
210
211 up += view_ref<Dim>(view, I) * w;
212 }
213 d_out(p) = static_cast<T>(up);
214 });
215 }
216
217} // namespace ippl
218#endif
typename ippl::detail::ViewType< ippl::Vector< double, Dim >, 1 >::view_type view_type
constexpr unsigned Dim
ippl::Field< T, Dim, Mesh_t< Dim >, Centering_t< Dim >, ViewArgs... > Field
Definition datatypes.h:29
Definition Archive.h:20
KOKKOS_INLINE_FUNCTION decltype(auto) view_ref(View &v, const IVec &I)
KOKKOS_INLINE_FUNCTION auto view_ptr_impl(View &v, const IVec &I, std::index_sequence< Is... >) -> decltype(&v(I[Is]...))
KOKKOS_INLINE_FUNCTION auto view_ptr(View &v, const IVec &I) -> decltype(view_ptr_impl(v, I, std::make_index_sequence< D >{}))
void assemble_rhs_from_particles(const AttribIn &attrib, Field &f, const PosAttrib &pp, const Space &space, policy_type iteration_policy)
Assemble a P1 FEM load vector (RHS) from particle attributes.
void interpolate_to_diracs(AttribOut &attrib_out, const Field &coeffs, const PosAttrib &pp, const Space &space, policy_type iteration_policy)
Interpolate a P1 FEM field to particle positions.
KOKKOS_INLINE_FUNCTION void locate_element_nd_and_xi(const Vector< T, Dim > &hr, const Vector< T, Dim > &origin, const Vector< T, Dim > &x, Vector< size_t, Dim > &e_nd, Vector< T, Dim > &xi)
Mapping from global position to element ND index and reference coordinates (xi ∈ [0,...
KOKKOS_INLINE_FUNCTION decltype(auto) view_ref_impl(View &v, const IVec &I, std::index_sequence< Is... >)
Layout_t & getLayout() const
Definition BareField.h:134
void accumulateHalo()
int getNghost() const
Definition BareField.h:125
view_type & getView()
Definition BareField.h:169
KOKKOS_INLINE_FUNCTION Mesh_t & get_mesh() const
Definition Field.h:64
const NDIndex_t & getLocalNDIndex() const
KOKKOS_INLINE_FUNCTION Vector< int, Dim > first() const
Definition NDIndex.hpp:170
KOKKOS_INLINE_FUNCTION vector_type getOrigin() const
Definition Mesh.hpp:10
virtual KOKKOS_INLINE_FUNCTION const vector_type & getMeshSpacing() const =0
Timing::TimerRef TimerRef
static TimerRef getTimer(const char *nm)
static void stopTimer(TimerRef t)
static void startTimer(TimerRef t)