diff --git a/Docs/source/usage/parameters.rst b/Docs/source/usage/parameters.rst index 260c407eeea..4df474e54cb 100644 --- a/Docs/source/usage/parameters.rst +++ b/Docs/source/usage/parameters.rst @@ -2314,6 +2314,7 @@ Reduced Diagnostics otherwise it is set to ``1``. Integrated electric and magnetic field components can instead be obtained by specifying ``.integrate == true``. + In a *moving window* simulation, the FieldProbe can be set to follow the moving frame by specifying ``.do_moving_window_FP = 1`` (default 0). .. warning:: diff --git a/Examples/Physics_applications/laser_acceleration/inputs_1d b/Examples/Physics_applications/laser_acceleration/inputs_1d index 28c8f66a5da..e143b5b16b8 100644 --- a/Examples/Physics_applications/laser_acceleration/inputs_1d +++ b/Examples/Physics_applications/laser_acceleration/inputs_1d @@ -70,3 +70,15 @@ diagnostics.diags_names = diag1 diag1.intervals = 100 diag1.diag_type = Full diag1.fields_to_plot = Ex Ey Ez Bx By Bz jx jy jz rho + +# Reduced Diagnostics +warpx.reduced_diags_names = FP + +FP.type = FieldProbe +FP.intervals = 10 +FP.integrate = 0 +FP.probe_geometry = Line +FP.z_probe = -56e-6 +FP.z1_probe = 12e-6 +FP.resolution = 100 +FP.do_moving_window_FP = 1 diff --git a/Examples/Physics_applications/laser_acceleration/inputs_2d b/Examples/Physics_applications/laser_acceleration/inputs_2d index 8a79e57240d..e5c3790437f 100644 --- a/Examples/Physics_applications/laser_acceleration/inputs_2d +++ b/Examples/Physics_applications/laser_acceleration/inputs_2d @@ -87,3 +87,17 @@ diagnostics.diags_names = diag1 diag1.intervals = 200 diag1.diag_type = Full diag1.fields_to_plot = Ex Ey Ez Bx By Bz jx jy jz rho + +# Reduced Diagnostics +warpx.reduced_diags_names = FP + +FP.type = FieldProbe +FP.intervals = 10 +FP.integrate = 0 +FP.probe_geometry = Line +FP.x_probe = 0 +FP.z_probe = -56e-6 +FP.x1_probe = 0 +FP.z1_probe = 12e-6 +FP.resolution = 300 +FP.do_moving_window_FP = 1 diff --git a/Examples/Physics_applications/laser_acceleration/inputs_3d b/Examples/Physics_applications/laser_acceleration/inputs_3d index 11c34c3aff8..cc0aa6e0cb1 100644 --- a/Examples/Physics_applications/laser_acceleration/inputs_3d +++ b/Examples/Physics_applications/laser_acceleration/inputs_3d @@ -77,3 +77,19 @@ diagnostics.diags_names = diag1 diag1.intervals = 100 diag1.diag_type = Full diag1.fields_to_plot = Ex Ey Ez Bx By Bz jx jy jz rho + +# Reduced Diagnostics +warpx.reduced_diags_names = FP + +FP.type = FieldProbe +FP.intervals = 10 +FP.integrate = 0 +FP.probe_geometry = Line +FP.x_probe = 0 +FP.y_probe = 0 +FP.z_probe = -56e-6 +FP.x1_probe = 0 +FP.y1_probe = 0 +FP.z1_probe = 12e-6 +FP.resolution = 300 +FP.do_moving_window_FP = 1 diff --git a/Source/Diagnostics/ReducedDiags/FieldProbe.H b/Source/Diagnostics/ReducedDiags/FieldProbe.H index 15c5d18f202..27c52618731 100644 --- a/Source/Diagnostics/ReducedDiags/FieldProbe.H +++ b/Source/Diagnostics/ReducedDiags/FieldProbe.H @@ -76,6 +76,9 @@ private: //! counts number of particles for all MPI ranks long m_valid_particles {0}; + //! remember the last time @see ComputeDiags was called to count the number of steps in between (for non-integrated detectors) + int m_last_compute_step = 0; + //! determines geometry of detector point distribution DetectorGeometry m_probe_geometry = DetectorGeometry::Point; @@ -100,6 +103,9 @@ private: //! Judges whether to gather raw fields or interpolated data bool raw_fields = false; + //! Judges whether to follow a moving window + bool do_moving_window_FP = false; + /** * Built-in function in ReducedDiags to write out test data */ diff --git a/Source/Diagnostics/ReducedDiags/FieldProbe.cpp b/Source/Diagnostics/ReducedDiags/FieldProbe.cpp index a0414c0fc1f..fb305a293a0 100644 --- a/Source/Diagnostics/ReducedDiags/FieldProbe.cpp +++ b/Source/Diagnostics/ReducedDiags/FieldProbe.cpp @@ -8,6 +8,8 @@ #include "FieldProbe.H" #include "FieldProbeParticleContainer.H" #include "Particles/Gather/FieldGather.H" +#include "Particles/Pusher/GetAndSetPosition.H" +#include "Particles/Pusher/UpdatePosition.H" #include "Utils/IntervalsParser.H" #include "Utils/TextMsg.H" @@ -147,6 +149,7 @@ FieldProbe::FieldProbe (std::string rd_name) pp_rd_name.query("integrate", m_field_probe_integrate); pp_rd_name.query("raw_fields", raw_fields); pp_rd_name.query("interp_order", interp_order); + pp_rd_name.query("do_moving_window_FP", do_moving_window_FP); if (WarpX::gamma_boost > 1.0_rt) { @@ -385,6 +388,18 @@ void FieldProbe::ComputeDiags (int step) { const amrex::Geometry& gm = warpx.Geom(lev); const auto prob_lo = gm.ProbLo(); + amrex::Real const dt = WarpX::GetInstance().getdt(lev); + // Calculates particle movement in moving window sims + amrex::Real move_dist = 0.0; + bool const update_particles_moving_window = + do_moving_window_FP && + step > warpx.start_moving_window_step && + step <= warpx.end_moving_window_step; + if (update_particles_moving_window) + { + int step_diff = step - m_last_compute_step; + move_dist = dt*warpx.moving_window_v*step_diff; + } // get MultiFab data at lev const amrex::MultiFab &Ex = warpx.getEfield(lev, 0); @@ -426,8 +441,30 @@ void FieldProbe::ComputeDiags (int step) for (MyParIter pti(m_probe, lev); pti.isValid(); ++pti) { const auto getPosition = GetParticlePosition(pti); - auto const np = pti.numParticles(); + auto setPosition = SetParticlePosition(pti); + auto const np = pti.numParticles(); + if (update_particles_moving_window) + { + const auto temp_warpx_moving_window = warpx.moving_window_dir; + amrex::ParallelFor( np, [=] AMREX_GPU_DEVICE (long ip) + { + amrex::ParticleReal xp, yp, zp; + getPosition(ip, xp, yp, zp); + if (temp_warpx_moving_window == 0) + { + setPosition(ip, xp+move_dist, yp, zp); + } + if (temp_warpx_moving_window == 1) + { + setPosition(ip, xp, yp+move_dist, zp); + } + if (temp_warpx_moving_window == WARPX_ZINDEX) + { + setPosition(ip, xp, yp, zp+move_dist); + } + }); + } if( ProbeInDomain() ) { const auto cell_size = gm.CellSizeArray(); @@ -479,7 +516,6 @@ void FieldProbe::ComputeDiags (int step) const int temp_interp_order = interp_order; const bool temp_raw_fields = raw_fields; const bool temp_field_probe_integrate = m_field_probe_integrate; - amrex::Real const dt = WarpX::GetInstance().getdt(lev); // Interpolating to the probe positions for each particle amrex::ParallelFor( np, [=] AMREX_GPU_DEVICE (long ip) @@ -614,6 +650,7 @@ void FieldProbe::ComputeDiags (int step) }// end loop over refinement levels // make sure data is in m_data on the IOProcessor // TODO: In the future, we want to use a parallel I/O method instead (plotfiles or openPMD) + m_last_compute_step = step; } // end void FieldProbe::ComputeDiags void FieldProbe::WriteToFile (int step) const diff --git a/Source/Particles/Pusher/GetAndSetPosition.H b/Source/Particles/Pusher/GetAndSetPosition.H index 58dbe02c146..4067895790d 100644 --- a/Source/Particles/Pusher/GetAndSetPosition.H +++ b/Source/Particles/Pusher/GetAndSetPosition.H @@ -155,7 +155,9 @@ struct SetParticlePosition #if defined(WARPX_DIM_RZ) RType* AMREX_RESTRICT m_theta; #endif - SetParticlePosition (WarpXParIter& a_pti, int a_offset = 0) noexcept + + template + SetParticlePosition (const ptiType& a_pti, int a_offset = 0) noexcept { auto& aos = a_pti.GetArrayOfStructs(); m_structs = aos().dataPtr() + a_offset;