aboutsummaryrefslogtreecommitdiff
path: root/Source
diff options
context:
space:
mode:
authorGravatar Neïl Zaim <49716072+NeilZaim@users.noreply.github.com> 2021-05-24 20:42:39 +0200
committerGravatar GitHub <noreply@github.com> 2021-05-24 11:42:39 -0700
commit996505b96ec9ae025e22cd4214ff904479818d5c (patch)
treebee28a3638a5b594ea455cd8555a609592c7c552 /Source
parent9ab4c6d201a102aafa79cab1404bc9c157fd02aa (diff)
downloadWarpX-996505b96ec9ae025e22cd4214ff904479818d5c.tar.gz
WarpX-996505b96ec9ae025e22cd4214ff904479818d5c.tar.zst
WarpX-996505b96ec9ae025e22cd4214ff904479818d5c.zip
Add ComputeMaxStep() function in WarpXInitData (#1712)
* Add ComputeMaxStep() function in WarpXInitData * Avoid overflow in the static_cast * Change overflow handling and update stop_time constistently with max_step
Diffstat (limited to 'Source')
-rw-r--r--Source/Evolve/WarpXEvolve.cpp52
-rw-r--r--Source/Initialization/WarpXInitData.cpp69
-rw-r--r--Source/WarpX.H6
3 files changed, 75 insertions, 52 deletions
diff --git a/Source/Evolve/WarpXEvolve.cpp b/Source/Evolve/WarpXEvolve.cpp
index 2f04310a5..e48166cf1 100644
--- a/Source/Evolve/WarpXEvolve.cpp
+++ b/Source/Evolve/WarpXEvolve.cpp
@@ -30,10 +30,6 @@ WarpX::Evolve (int numsteps)
Real cur_time = t_new[0];
- if (do_compute_max_step_from_zmax) {
- computeMaxStepBoostAccelerator(geom[0]);
- }
-
int numsteps_max;
if (numsteps < 0) { // Note that the default argument is numsteps = -1
numsteps_max = max_step;
@@ -648,54 +644,6 @@ WarpX::PushParticlesandDepose (int lev, amrex::Real cur_time, DtType a_dt_type,
#endif
}
-/* \brief computes max_step for wakefield simulation in boosted frame.
- * \param geom: Geometry object that contains simulation domain.
- *
- * max_step is set so that the simulation stop when the lower corner of the
- * simulation box passes input parameter zmax_plasma_to_compute_max_step.
- */
-void
-WarpX::computeMaxStepBoostAccelerator(const amrex::Geometry& a_geom){
- // Sanity checks: can use zmax_plasma_to_compute_max_step only if
- // the moving window and the boost are all in z direction.
- AMREX_ALWAYS_ASSERT_WITH_MESSAGE(
- WarpX::moving_window_dir == AMREX_SPACEDIM-1,
- "Can use zmax_plasma_to_compute_max_step only if " +
- "moving window along z. TODO: all directions.");
- if (gamma_boost > 1){
- AMREX_ALWAYS_ASSERT_WITH_MESSAGE(
- (WarpX::boost_direction[0]-0)*(WarpX::boost_direction[0]-0) +
- (WarpX::boost_direction[1]-0)*(WarpX::boost_direction[1]-0) +
- (WarpX::boost_direction[2]-1)*(WarpX::boost_direction[2]-1) < 1.e-12,
- "Can use zmax_plasma_to_compute_max_step in boosted frame only if " +
- "warpx.boost_direction = z. TODO: all directions.");
- }
-
- // Lower end of the simulation domain. All quantities are given in boosted
- // frame except zmax_plasma_to_compute_max_step.
- const Real zmin_domain_boost = a_geom.ProbLo(AMREX_SPACEDIM-1);
- // End of the plasma: Transform input argument
- // zmax_plasma_to_compute_max_step to boosted frame.
- const Real len_plasma_boost = zmax_plasma_to_compute_max_step/gamma_boost;
- // Plasma velocity
- const Real v_plasma_boost = -beta_boost * PhysConst::c;
- // Get time at which the lower end of the simulation domain passes the
- // upper end of the plasma (in the z direction).
- const Real interaction_time_boost = (len_plasma_boost-zmin_domain_boost)/
- (moving_window_v-v_plasma_boost);
- // Divide by dt, and update value of max_step.
- int computed_max_step;
- if (do_subcycling){
- computed_max_step = static_cast<int>(interaction_time_boost/dt[0]);
- } else {
- computed_max_step =
- static_cast<int>(interaction_time_boost/dt[maxLevel()]);
- }
- max_step = computed_max_step;
- Print()<<"max_step computed in computeMaxStepBoostAccelerator: "
- <<computed_max_step<<std::endl;
-}
-
/* \brief Apply perfect mirror condition inside the box (not at a boundary).
* In practice, set all fields to 0 on a section of the simulation domain
* (as for a perfect conductor with a given thickness).
diff --git a/Source/Initialization/WarpXInitData.cpp b/Source/Initialization/WarpXInitData.cpp
index 892172745..98533ea33 100644
--- a/Source/Initialization/WarpXInitData.cpp
+++ b/Source/Initialization/WarpXInitData.cpp
@@ -92,6 +92,7 @@ WarpX::InitData ()
ScaleEdges();
ScaleAreas();
#endif
+ ComputeMaxStep();
ComputePMLFactors();
@@ -267,6 +268,74 @@ WarpX::ComputePMLFactors ()
}
void
+WarpX::ComputeMaxStep ()
+{
+ if (do_compute_max_step_from_zmax) {
+ computeMaxStepBoostAccelerator(geom[0]);
+ }
+
+ // Make max_step and stop_time self-consistent, assuming constant dt.
+
+ // If max_step is the limiting condition, decrease stop_time consistently
+ if (stop_time > t_new[0] + dt[0]*(max_step - istep[0]) ) {
+ stop_time = t_new[0] + dt[0]*(max_step - istep[0]);
+ }
+ // If stop_time is the limiting condition instead, decrease max_step consistently
+ else {
+ // The static_cast should not overflow since stop_time is the limiting condition here
+ max_step = static_cast<int>(istep[0] + std::ceil( (stop_time-t_new[0])/dt[0] ));
+ }
+}
+
+/* \brief computes max_step for wakefield simulation in boosted frame.
+ * \param geom: Geometry object that contains simulation domain.
+ *
+ * max_step is set so that the simulation stop when the lower corner of the
+ * simulation box passes input parameter zmax_plasma_to_compute_max_step.
+ */
+void
+WarpX::computeMaxStepBoostAccelerator(const amrex::Geometry& a_geom){
+ // Sanity checks: can use zmax_plasma_to_compute_max_step only if
+ // the moving window and the boost are all in z direction.
+ AMREX_ALWAYS_ASSERT_WITH_MESSAGE(
+ WarpX::moving_window_dir == AMREX_SPACEDIM-1,
+ "Can use zmax_plasma_to_compute_max_step only if " +
+ "moving window along z. TODO: all directions.");
+ if (gamma_boost > 1){
+ AMREX_ALWAYS_ASSERT_WITH_MESSAGE(
+ (WarpX::boost_direction[0]-0)*(WarpX::boost_direction[0]-0) +
+ (WarpX::boost_direction[1]-0)*(WarpX::boost_direction[1]-0) +
+ (WarpX::boost_direction[2]-1)*(WarpX::boost_direction[2]-1) < 1.e-12,
+ "Can use zmax_plasma_to_compute_max_step in boosted frame only if " +
+ "warpx.boost_direction = z. TODO: all directions.");
+ }
+
+ // Lower end of the simulation domain. All quantities are given in boosted
+ // frame except zmax_plasma_to_compute_max_step.
+ const Real zmin_domain_boost = a_geom.ProbLo(AMREX_SPACEDIM-1);
+ // End of the plasma: Transform input argument
+ // zmax_plasma_to_compute_max_step to boosted frame.
+ const Real len_plasma_boost = zmax_plasma_to_compute_max_step/gamma_boost;
+ // Plasma velocity
+ const Real v_plasma_boost = -beta_boost * PhysConst::c;
+ // Get time at which the lower end of the simulation domain passes the
+ // upper end of the plasma (in the z direction).
+ const Real interaction_time_boost = (len_plasma_boost-zmin_domain_boost)/
+ (moving_window_v-v_plasma_boost);
+ // Divide by dt, and update value of max_step.
+ int computed_max_step;
+ if (do_subcycling){
+ computed_max_step = static_cast<int>(interaction_time_boost/dt[0]);
+ } else {
+ computed_max_step =
+ static_cast<int>(interaction_time_boost/dt[maxLevel()]);
+ }
+ max_step = computed_max_step;
+ Print()<<"max_step computed in computeMaxStepBoostAccelerator: "
+ <<computed_max_step<<std::endl;
+}
+
+void
WarpX::InitNCICorrector ()
{
if (WarpX::use_fdtd_nci_corr)
diff --git a/Source/WarpX.H b/Source/WarpX.H
index 26f6045d0..82a3e1483 100644
--- a/Source/WarpX.H
+++ b/Source/WarpX.H
@@ -325,6 +325,12 @@ public:
/** Determine the timestep of the simulation. */
void ComputeDt ();
+ /**
+ * \brief
+ * Compute the last timestep of the simulation and make max_step and stop_time self-consistent.
+ * Calls computeMaxStepBoostAccelerator() if required.
+ */
+ void ComputeMaxStep ();
// Compute max_step automatically for simulations in a boosted frame.
void computeMaxStepBoostAccelerator(const amrex::Geometry& geom);
int MoveWindow (bool move_j);