diff options
author | 2021-05-24 20:42:39 +0200 | |
---|---|---|
committer | 2021-05-24 11:42:39 -0700 | |
commit | 996505b96ec9ae025e22cd4214ff904479818d5c (patch) | |
tree | bee28a3638a5b594ea455cd8555a609592c7c552 /Source | |
parent | 9ab4c6d201a102aafa79cab1404bc9c157fd02aa (diff) | |
download | WarpX-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.cpp | 52 | ||||
-rw-r--r-- | Source/Initialization/WarpXInitData.cpp | 69 | ||||
-rw-r--r-- | Source/WarpX.H | 6 |
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); |