aboutsummaryrefslogtreecommitdiff
path: root/Source/Laser/LaserParticleContainer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/Laser/LaserParticleContainer.cpp')
-rw-r--r--Source/Laser/LaserParticleContainer.cpp94
1 files changed, 88 insertions, 6 deletions
diff --git a/Source/Laser/LaserParticleContainer.cpp b/Source/Laser/LaserParticleContainer.cpp
index 2b56c3cfd..d28bd75e5 100644
--- a/Source/Laser/LaserParticleContainer.cpp
+++ b/Source/Laser/LaserParticleContainer.cpp
@@ -49,6 +49,7 @@ LaserParticleContainer::LaserParticleContainer (AmrCore* amr_core, int ispecies,
pp.query("pusher_algo", pusher_algo);
pp.get("wavelength", wavelength);
pp.get("e_max", e_max);
+ pp.query("do_continuous_injection", do_continuous_injection);
if ( profile == laser_t::Gaussian ) {
// Parse the properties of the Gaussian profile
@@ -148,14 +149,88 @@ LaserParticleContainer::LaserParticleContainer (AmrCore* amr_core, int ispecies,
u_Y = {0., 1., 0.};
#endif
- prob_domain = Geometry::ProbDomain();
+ laser_prob_domain = Geometry::ProbDomain();
{
Vector<Real> lo, hi;
if (pp.queryarr("prob_lo", lo)) {
- prob_domain.setLo(lo);
+ laser_prob_domain.setLo(lo);
}
if (pp.queryarr("prob_hi", hi)) {
- prob_domain.setHi(hi);
+ laser_prob_domain.setHi(hi);
+ }
+ }
+
+ if (do_continuous_injection){
+ // If laser antenna initially outside of the box, store its theoretical
+ // position in z_antenna_th, and set done_injecting to 0.
+ z_antenna_th = position[2];
+ const Real prob_lo_z = laser_prob_domain.lo()[AMREX_SPACEDIM-1];
+ const Real prob_hi_z = laser_prob_domain.hi()[AMREX_SPACEDIM-1];
+ if ( z_antenna_th<prob_lo_z || z_antenna_th>prob_hi_z ){
+ done_injecting = 0;
+ }
+ // Sanity checks: do_continuous_injection can be used only if the
+ // laser, the moving window and the boost are all in z direction.
+ AMREX_ALWAYS_ASSERT_WITH_MESSAGE(
+ (nvec[0]-0)*(nvec[0]-0) +
+ (nvec[1]-0)*(nvec[1]-0) +
+ (nvec[2]-1)*(nvec[2]-1) < 1.e-12,
+ "do_continous_injection for laser particle only works if " +
+ "laser.direction = 0 0 1 (laser along z). TODO: all directions.");
+ AMREX_ALWAYS_ASSERT_WITH_MESSAGE(
+ WarpX::moving_window_dir == AMREX_SPACEDIM-1,
+ "do_continous_injection for laser particle only works if " +
+ "moving window along z. TODO: all directions.");
+ AMREX_ALWAYS_ASSERT_WITH_MESSAGE(
+ maxLevel() == 0,
+ "do_continous_injection for laser particle only works if " +
+ "max level = 0.");
+ if ( WarpX::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,
+ "do_continous_injection for laser particle only works if " +
+ "warpx.boost_direction = z. TODO: all directions.");
+ }
+ }
+}
+
+/* \brief Check if laser particles enter the box, and inject if necessary.
+ * \param dt: time step (assume no MR for now)
+ * \param prob_domain: a RealBox that contains current simulation boundaries.
+ * This function checks if the laser antenna should be injected at this
+ * iteration. If so, it injects it and set done_injecting to 1.
+ */
+void
+LaserParticleContainer::ContinuousInjection (Real dt, const RealBox& prob_domain)
+{
+ // update position of the antenna (outside of the box)
+ if (WarpX::gamma_boost>1){
+ z_antenna_th -= PhysConst::c * WarpX::beta_boost * dt;
+ }
+ // If laser antenna particles have not been injected yet,
+ // check if they should be injected at this iteration. If
+ // so, inject them and set done_injecting to 0 (false).
+ if (done_injecting==0)
+ {
+ // Input parameter prob_domain contains up-to-date properties of the
+ // simulation domain (i.e. including moving window shift).
+ // So far, LaserParticleContainer::laser_prob_domain contains the
+ // outdated prob_domain at t=0.
+
+ // Get domain boundaries in the z direction
+ const Real prob_lo_z = prob_domain.lo()[AMREX_SPACEDIM-1];
+ const Real prob_hi_z = prob_domain.hi()[AMREX_SPACEDIM-1];
+ if ( z_antenna_th>prob_lo_z && z_antenna_th<prob_hi_z ){
+ // Update laser_prob_domain with current value
+ laser_prob_domain = prob_domain;
+ // Inject laser particles. LaserParticleContainer::InitData
+ // is called only once, when the antenna enters the simulation
+ // domain.
+ InitData(maxLevel());
+ // Set done_injecting to 1, to avoid re-injecting particles.
+ done_injecting = 1;
}
}
}
@@ -175,6 +250,13 @@ LaserParticleContainer::InitData (int lev)
ComputeSpacing(lev, S_X, S_Y);
ComputeWeightMobility(S_X, S_Y);
+ // LaserParticleContainer::position contains the initial position of the
+ // laser antenna. In the boosted frame, the antenna is moving.
+ // Update its position.
+ if (do_continuous_injection){
+ position[2] = z_antenna_th;
+ }
+
auto Transform = [&](int i, int j) -> Vector<Real>{
#if (AMREX_SPACEDIM == 3)
return { position[0] + (S_X*(i+0.5))*u_X[0] + (S_Y*(j+0.5))*u_Y[0],
@@ -210,8 +292,8 @@ LaserParticleContainer::InitData (int lev)
plane_hi[1] = std::max(plane_hi[1], j);
};
- const Real* prob_lo = prob_domain.lo();
- const Real* prob_hi = prob_domain.hi();
+ const Real* prob_lo = laser_prob_domain.lo();
+ const Real* prob_hi = laser_prob_domain.hi();
#if (AMREX_SPACEDIM == 3)
compute_min_max(prob_lo[0], prob_lo[1], prob_lo[2]);
compute_min_max(prob_hi[0], prob_lo[1], prob_lo[2]);
@@ -272,7 +354,7 @@ LaserParticleContainer::InitData (int lev)
#else
const Real x[2] = {pos[0], pos[2]};
#endif
- if (prob_domain.contains(x))
+ if (laser_prob_domain.contains(x))
{
for (int k = 0; k<2; ++k) {
particle_x.push_back(pos[0]);