diff options
Diffstat (limited to 'Source/Laser/LaserParticleContainer.cpp')
-rw-r--r-- | Source/Laser/LaserParticleContainer.cpp | 94 |
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]); |