@@ -318,7 +318,7 @@ namespace user {
318318
319319 const std::vector<real_t > xi_min;
320320 const std::vector<real_t > xi_max;
321- const real_t sigma0, sigma_max, inj_coeff, db_thr, temperature, m_eps;
321+ const real_t sigma0, sigma_max, inj_coeff, db_thr, temperature, m_eps, inv_n0 ;
322322
323323 InitFields<M, D> init_flds;
324324 const Metadomain<S, M>* metadomain;
@@ -333,6 +333,7 @@ namespace user {
333333 , db_thr { p.template get <real_t >(" setup.db_thr" ) }
334334 , temperature { p.template get <real_t >(" setup.temperature" ) }
335335 , m_eps { p.template get <real_t >(" setup.m_eps" ) }
336+ , inv_n0 { ONE / p.template get <real_t >(" scales.n0" ) }
336337 , init_flds { m.mesh ().metric , m_eps }
337338 , metadomain { &m } {}
338339
@@ -359,6 +360,110 @@ namespace user {
359360 1.0 ,
360361 true );
361362 }
363+
364+ void CustomFieldOutput (const std::string& name,
365+ ndfield_t <M::Dim, 6 > buffer,
366+ index_t index,
367+ timestep_t ,
368+ simtime_t ,
369+ const Domain<S, M>& domain) {
370+
371+
372+ if (name == " DB" ) {
373+ if constexpr (M::Dim == Dim::_2D) {
374+ const auto & EM = domain.fields .em ;
375+ const auto & metric = domain.mesh .metric ;
376+ Kokkos::parallel_for (
377+ " DB" ,
378+ domain.mesh .rangeActiveCells (),
379+ Lambda (index_t i1, index_t i2) {
380+ coord_t <M::Dim> xi { static_cast <real_t >(i1 - N_GHOSTS), static_cast <real_t >(i2 - N_GHOSTS) };
381+ const vec_t <Dim::_3D> B_cntrv { EM (i1, i2, em::bx1),
382+ EM (i1, i2, em::bx2),
383+ EM (i1, i2, em::bx3) };
384+ vec_t <Dim::_3D> B_cov { ZERO };
385+ const vec_t <Dim::_3D> D_cntrv { EM (i1, i2, em::dx1),
386+ EM (i1, i2, em::dx2),
387+ EM (i1, i2, em::dx3) };
388+ metric.template transform <Idx::U, Idx::D>(xi, B_cntrv, B_cov);
389+ buffer (i1, i2, index) = DOT (B_cov[0 ], B_cov[1 ], B_cov[2 ], D_cntrv[0 ], D_cntrv[1 ], D_cntrv[2 ])
390+ / DOT (B_cntrv[0 ], B_cntrv[1 ], B_cntrv[2 ], B_cntrv[0 ], B_cntrv[1 ], B_cntrv[2 ]);
391+ });
392+ }
393+ } else if (name == " fRho" ){
394+ auto T3 = domain.fields .buff ;
395+ auto & mesh = domain.mesh ;
396+ const auto use_weights = params.template get <bool >(
397+ " particles.use_weights" );
398+ const auto ni2 = mesh.n_active (in::x2);
399+ std::vector<unsigned short > specs {};
400+ for (auto & sp : domain.species ) {
401+ if (sp.mass () > 0 ) {
402+ specs.push_back (sp.index ());
403+ }
404+ }
405+ const auto & metric = domain.mesh .metric ;
406+
407+ // compute T_00, T_01, T_11
408+ auto scatter_buff = Kokkos::Experimental::create_scatter_view (T3);
409+ for (const auto & sp : specs) {
410+ auto & prtl_spec = domain.species [sp - 1 ];
411+ // clang-format off
412+ Kokkos::parallel_for (
413+ " ComputeMoments" ,
414+ prtl_spec.rangeActiveParticles (),
415+ kernel::ParticleMoments_kernel<S, M, FldsID::T, 3 >({0 , 0 }, scatter_buff, 0u ,
416+ prtl_spec.i1 , prtl_spec.i2 , prtl_spec.i3 ,
417+ prtl_spec.dx1 , prtl_spec.dx2 , prtl_spec.dx3 ,
418+ prtl_spec.ux1 , prtl_spec.ux2 , prtl_spec.ux3 ,
419+ prtl_spec.phi , prtl_spec.weight , prtl_spec.tag ,
420+ prtl_spec.mass (), prtl_spec.charge (),
421+ use_weights,
422+ metric, mesh.flds_bc (),
423+ ni2, inv_n0, ZERO));
424+ Kokkos::parallel_for (
425+ " ComputeMoments" ,
426+ prtl_spec.rangeActiveParticles (),
427+ kernel::ParticleMoments_kernel<S, M, FldsID::T, 3 >({0 , 1 }, scatter_buff, 1u ,
428+ prtl_spec.i1 , prtl_spec.i2 , prtl_spec.i3 ,
429+ prtl_spec.dx1 , prtl_spec.dx2 , prtl_spec.dx3 ,
430+ prtl_spec.ux1 , prtl_spec.ux2 , prtl_spec.ux3 ,
431+ prtl_spec.phi , prtl_spec.weight , prtl_spec.tag ,
432+ prtl_spec.mass (), prtl_spec.charge (),
433+ use_weights,
434+ metric, mesh.flds_bc (),
435+ ni2, inv_n0, ZERO));
436+ Kokkos::parallel_for (
437+ " ComputeMoments" ,
438+ prtl_spec.rangeActiveParticles (),
439+ kernel::ParticleMoments_kernel<S, M, FldsID::T, 3 >({1 , 1 }, scatter_buff, 2u ,
440+ prtl_spec.i1 , prtl_spec.i2 , prtl_spec.i3 ,
441+ prtl_spec.dx1 , prtl_spec.dx2 , prtl_spec.dx3 ,
442+ prtl_spec.ux1 , prtl_spec.ux2 , prtl_spec.ux3 ,
443+ prtl_spec.phi , prtl_spec.weight , prtl_spec.tag ,
444+ prtl_spec.mass (), prtl_spec.charge (),
445+ use_weights,
446+ metric, mesh.flds_bc (),
447+ ni2, inv_n0, ZERO));
448+ // clang-format on
449+ }
450+ Kokkos::Experimental::contribute (T3, scatter_buff);
451+
452+ if constexpr (M::Dim == Dim::_2D) {
453+ Kokkos::parallel_for (
454+ " fRho" ,
455+ domain.mesh .rangeActiveCells (),
456+ Lambda (index_t i1, index_t i2) {
457+ coord_t <M::Dim> xi { static_cast <real_t >(i1 - N_GHOSTS), static_cast <real_t >(i2 - N_GHOSTS) };
458+ real_t alpha_ij = metric.alpha (xi);
459+ real_t beta_ij = metric.beta1 (xi);
460+ buffer (i1, i2, index) = (T3 (i1, i2, 0 ) - TWO * beta_ij * T3 (i1, i2, 1 ) + SQR (beta_ij) * T3 (i1, i2, 2 )) / SQR (alpha_ij);
461+ });
462+ }
463+ } else {
464+ raise::Error (" Custom output not provided" , HERE);
465+ }
466+ }
362467 };
363468
364469} // namespace user
0 commit comments