1414#include " global.h"
1515
1616#include " arch/kokkos_aliases.h"
17+ #include " utils/comparators.h"
1718#include " utils/error.h"
1819#include " utils/numeric.h"
1920
@@ -40,8 +41,10 @@ namespace kernel {
4041 static_assert (M::is_metric, " M must be a metric class" );
4142 static constexpr auto D = M::Dim;
4243
43- static_assert ((F == FldsID::Rho) || (F == FldsID::Charge) ||
44- (F == FldsID::N) || (F == FldsID::Nppc) || (F == FldsID::T),
44+ static_assert (!((S == SimEngine::GRPIC) && (F == FldsID::V)),
45+ " Bulk velocity not supported for GRPIC" );
46+ static_assert ((F == FldsID::Rho) || (F == FldsID::Charge) || (F == FldsID::N) ||
47+ (F == FldsID::Nppc) || (F == FldsID::T) || (F == FldsID::V),
4548 " Invalid field ID" );
4649
4750 const unsigned short c1, c2;
@@ -89,8 +92,8 @@ namespace kernel {
8992 std::size_t ni2,
9093 real_t inv_n0,
9194 unsigned short window)
92- : c1 { (components.size () == 2 ) ? components[0 ]
93- : static_cast <unsigned short >(0 ) }
95+ : c1 { (components.size () > 0 ) ? components[0 ]
96+ : static_cast <unsigned short >(0 ) }
9497 , c2 { (components.size () == 2 ) ? components[1 ]
9598 : static_cast <unsigned short >(0 ) }
9699 , Buff { scatter_buff }
@@ -200,11 +203,97 @@ namespace kernel {
200203 coeff *= u_Phys[c - 1 ];
201204 }
202205 }
206+ } else if constexpr (F == FldsID::V) {
207+ real_t gamma { ZERO };
208+ // for bulk 3vel (tetrad basis)
209+ vec_t <Dim::_3D> u_Phys { ZERO };
210+ if constexpr (M::CoordType == Coord::Cart) {
211+ u_Phys[0 ] = ux1 (p);
212+ u_Phys[1 ] = ux2 (p);
213+ u_Phys[2 ] = ux3 (p);
214+ } else {
215+ coord_t <M::PrtlDim> x_Code { ZERO };
216+ x_Code[0 ] = static_cast <real_t >(i1 (p)) + static_cast <real_t >(dx1 (p));
217+ x_Code[1 ] = static_cast <real_t >(i2 (p)) + static_cast <real_t >(dx2 (p));
218+ if constexpr (D == Dim::_3D) {
219+ x_Code[2 ] = static_cast <real_t >(i3 (p)) + static_cast <real_t >(dx3 (p));
220+ } else {
221+ x_Code[2 ] = phi (p);
222+ }
223+ metric.template transform_xyz <Idx::XYZ, Idx::T>(x_Code,
224+ { ux1 (p), ux2 (p), ux3 (p) },
225+ u_Phys);
226+ }
227+ if (mass == ZERO) {
228+ gamma = NORM (u_Phys[0 ], u_Phys[1 ], u_Phys[2 ]);
229+ } else {
230+ gamma = math::sqrt (ONE + NORM_SQR (u_Phys[0 ], u_Phys[1 ], u_Phys[2 ]));
231+ }
232+ // compute the corresponding moment
233+ coeff = (mass == ZERO ? ONE : mass) * u_Phys[c1 - 1 ] / gamma;
203234 } else {
204235 // for other cases, use the `contrib` defined above
205236 coeff = contrib;
206237 }
207238
239+ if constexpr (F == FldsID::V) {
240+ real_t gamma { ZERO };
241+ // for stress-energy tensor
242+ vec_t <Dim::_3D> u_Phys { ZERO };
243+ if constexpr (S == SimEngine::SRPIC) {
244+ // SR
245+ // stress-energy tensor for SR is computed in the tetrad (hatted) basis
246+ if constexpr (M::CoordType == Coord::Cart) {
247+ u_Phys[0 ] = ux1 (p);
248+ u_Phys[1 ] = ux2 (p);
249+ u_Phys[2 ] = ux3 (p);
250+ } else {
251+ static_assert (D != Dim::_1D, " non-Cartesian SRPIC 1D" );
252+ coord_t <M::PrtlDim> x_Code { ZERO };
253+ x_Code[0 ] = static_cast <real_t >(i1 (p)) + static_cast <real_t >(dx1 (p));
254+ x_Code[1 ] = static_cast <real_t >(i2 (p)) + static_cast <real_t >(dx2 (p));
255+ if constexpr (D == Dim::_3D) {
256+ x_Code[2 ] = static_cast <real_t >(i3 (p)) + static_cast <real_t >(dx3 (p));
257+ } else {
258+ x_Code[2 ] = phi (p);
259+ }
260+ metric.template transform_xyz <Idx::XYZ, Idx::T>(
261+ x_Code,
262+ { ux1 (p), ux2 (p), ux3 (p) },
263+ u_Phys);
264+ }
265+ if (mass == ZERO) {
266+ gamma = NORM (u_Phys[0 ], u_Phys[1 ], u_Phys[2 ]);
267+ } else {
268+ gamma = math::sqrt (ONE + NORM_SQR (u_Phys[0 ], u_Phys[1 ], u_Phys[2 ]));
269+ }
270+ } else {
271+ // GR
272+ // stress-energy tensor for GR is computed in contravariant basis
273+ static_assert (D != Dim::_1D, " GRPIC 1D" );
274+ coord_t <D> x_Code { ZERO };
275+ x_Code[0 ] = static_cast <real_t >(i1 (p)) + static_cast <real_t >(dx1 (p));
276+ x_Code[1 ] = static_cast <real_t >(i2 (p)) + static_cast <real_t >(dx2 (p));
277+ if constexpr (D == Dim::_3D) {
278+ x_Code[2 ] = static_cast <real_t >(i3 (p)) + static_cast <real_t >(dx3 (p));
279+ }
280+ vec_t <Dim::_3D> u_Cntrv { ZERO };
281+ // compute u_i u^i for energy
282+ metric.template transform <Idx::D, Idx::U>(x_Code,
283+ { ux1 (p), ux2 (p), ux3 (p) },
284+ u_Cntrv);
285+ gamma = u_Cntrv[0 ] * ux1 (p) + u_Cntrv[1 ] * ux2 (p) + u_Cntrv[2 ] * ux3 (p);
286+ if (mass == ZERO) {
287+ gamma = math::sqrt (gamma);
288+ } else {
289+ gamma = math::sqrt (ONE + gamma);
290+ }
291+ metric.template transform <Idx::U, Idx::PU>(x_Code, u_Cntrv, u_Phys);
292+ }
293+ // compute the corresponding moment
294+ coeff = u_Phys[c1 - 1 ] / gamma;
295+ }
296+
208297 if constexpr (F != FldsID::Nppc) {
209298 // for nppc calculation ...
210299 // ... do not take volume, weights or smoothing into account
@@ -288,6 +377,79 @@ namespace kernel {
288377 }
289378 };
290379
380+ template <Dimension D, unsigned short N>
381+ class NormalizeVectorByRho_kernel {
382+ const ndfield_t <D, N> Rho;
383+ ndfield_t <D, N> Vector;
384+ const unsigned short c_rho, c_v1, c_v2, c_v3;
385+
386+ public:
387+ NormalizeVectorByRho_kernel (const ndfield_t <D, N>& rho,
388+ const ndfield_t <D, N>& vector,
389+ unsigned short crho,
390+ unsigned short cv1,
391+ unsigned short cv2,
392+ unsigned short cv3)
393+ : Rho { rho }
394+ , Vector { vector }
395+ , c_rho { crho }
396+ , c_v1 { cv1 }
397+ , c_v2 { cv2 }
398+ , c_v3 { cv3 } {
399+ raise::ErrorIf (c_rho >= N or c_v1 >= N or c_v2 >= N or c_v3 >= N,
400+ " Invalid component index" ,
401+ HERE);
402+ raise::ErrorIf (c_rho == c_v1 or c_rho == c_v2 or c_rho == c_v3,
403+ " Invalid component index" ,
404+ HERE);
405+ raise::ErrorIf (c_v1 == c_v2 or c_v1 == c_v3 or c_v2 == c_v3,
406+ " Invalid component index" ,
407+ HERE);
408+ }
409+
410+ Inline void operator ()(index_t i1) const {
411+ if constexpr (D == Dim::_1D) {
412+ if (not cmp::AlmostZero (Rho (i1, c_rho))) {
413+ Vector (i1, c_v1) /= Rho (i1, c_rho);
414+ Vector (i1, c_v2) /= Rho (i1, c_rho);
415+ Vector (i1, c_v3) /= Rho (i1, c_rho);
416+ }
417+ } else {
418+ raise::KernelError (
419+ HERE,
420+ " 1D implementation of NormalizeVectorByRho_kernel called for non-1D" );
421+ }
422+ }
423+
424+ Inline void operator ()(index_t i1, index_t i2) const {
425+ if constexpr (D == Dim::_2D) {
426+ if (not cmp::AlmostZero (Rho (i1, i2, c_rho))) {
427+ Vector (i1, i2, c_v1) /= Rho (i1, i2, c_rho);
428+ Vector (i1, i2, c_v2) /= Rho (i1, i2, c_rho);
429+ Vector (i1, i2, c_v3) /= Rho (i1, i2, c_rho);
430+ }
431+ } else {
432+ raise::KernelError (
433+ HERE,
434+ " 2D implementation of NormalizeVectorByRho_kernel called for non-2D" );
435+ }
436+ }
437+
438+ Inline void operator ()(index_t i1, index_t i2, index_t i3) const {
439+ if constexpr (D == Dim::_3D) {
440+ if (not cmp::AlmostZero (Rho (i1, i2, i3, c_rho))) {
441+ Vector (i1, i2, i3, c_v1) /= Rho (i1, i2, i3, c_rho);
442+ Vector (i1, i2, i3, c_v2) /= Rho (i1, i2, i3, c_rho);
443+ Vector (i1, i2, i3, c_v3) /= Rho (i1, i2, i3, c_rho);
444+ }
445+ } else {
446+ raise::KernelError (
447+ HERE,
448+ " 3D implementation of NormalizeVectorByRho_kernel called for non-3D" );
449+ }
450+ }
451+ };
452+
291453} // namespace kernel
292454
293455#endif // KERNELS_PARTICLE_MOMENTS_HPP
0 commit comments