diff options
Diffstat (limited to 'Source/Utils')
-rw-r--r-- | Source/Utils/WarpXMovingWindow.cpp | 179 |
1 files changed, 123 insertions, 56 deletions
diff --git a/Source/Utils/WarpXMovingWindow.cpp b/Source/Utils/WarpXMovingWindow.cpp index 7e7985b98..cef4764b1 100644 --- a/Source/Utils/WarpXMovingWindow.cpp +++ b/Source/Utils/WarpXMovingWindow.cpp @@ -56,25 +56,81 @@ void WarpX::UpdatePlasmaInjectionPosition (amrex::Real a_dt) { const int dir = moving_window_dir; - // Continuously inject plasma in new cells (by default only on level 0) - if (WarpX::warpx_do_continuous_injection and (WarpX::gamma_boost > 1)){ - // In boosted-frame simulations, the plasma has moved since the last - // call to this function, and injection position needs to be updated - current_injection_position -= WarpX::beta_boost * + + // Loop over species + const int n_species = mypc->nSpecies(); + for (int i=0; i<n_species; i++) + { + WarpXParticleContainer& pc = mypc->GetParticleContainer(i); + + // Continuously inject plasma in new cells (by default only on level 0) + if (pc.doContinuousInjection()) + { + PlasmaInjector* plasma_injector = pc.GetPlasmaInjector(); + if (plasma_injector == nullptr) continue; + + // Get bulk momentum and velocity of plasma + amrex::XDim3 u_bulk = amrex::XDim3{0._rt, 0._rt, 0._rt}; + amrex::Real v_bulk = 0._rt; + if (dir == 0) + { + // dir=0 is z in 1D, x in 2D, x in 3D +#if defined(WARPX_DIM_1D_Z) + u_bulk = plasma_injector->getInjectorMomentumHost()->getBulkMomentum(0._rt, 0._rt, pc.m_current_injection_position); + v_bulk = PhysConst::c * u_bulk.z / std::sqrt(1._rt + u_bulk.z*u_bulk.z); +#else // 2D, 3D + u_bulk = plasma_injector->getInjectorMomentumHost()->getBulkMomentum(pc.m_current_injection_position, 0._rt, 0._rt); + v_bulk = PhysConst::c * u_bulk.x / std::sqrt(1._rt + u_bulk.x*u_bulk.x); +#endif + } + else if (dir == 1) + { + // dir=1 is nothing in 1D, z in 2D, y in 3D + // (we do not expect to enter this code block in 1D) +#if defined(WARPX_DIM_XZ) || defined(WARPX_DIM_RZ) + u_bulk = plasma_injector->getInjectorMomentumHost()->getBulkMomentum(0._rt, 0._rt, pc.m_current_injection_position); + v_bulk = PhysConst::c * u_bulk.z / std::sqrt(1._rt + u_bulk.z*u_bulk.z); +#else // 3D + u_bulk = plasma_injector->getInjectorMomentumHost()->getBulkMomentum(0._rt, pc.m_current_injection_position, 0._rt); + v_bulk = PhysConst::c * u_bulk.y / std::sqrt(1._rt + u_bulk.y*u_bulk.y); +#endif + } + else if (dir == 2) + { + // dir=2 is nothing in 1D, nothing in 2D, z in 3D + // (we do not expect to enter this code block in 1D and 2D) + u_bulk = plasma_injector->getInjectorMomentumHost()->getBulkMomentum(0._rt, 0._rt, pc.m_current_injection_position); + v_bulk = PhysConst::c * u_bulk.z / std::sqrt(1._rt + u_bulk.z*u_bulk.z); + } + + // In boosted-frame simulations, the plasma has moved since the last + // call to this function, and injection position needs to be updated. + // Note that the bulk velocity v, obtained from getBulkMomentum, is + // transformed to the boosted frame velocity v' via the formula + // v' = (v-c*beta)/(1-v*beta/c) + if (WarpX::gamma_boost > 1._rt) + { + v_bulk = (v_bulk - PhysConst::c*WarpX::beta_boost) + / (1._rt - v_bulk*WarpX::beta_boost/PhysConst::c); #if defined(WARPX_DIM_3D) - WarpX::boost_direction[dir] * PhysConst::c * a_dt; + v_bulk *= WarpX::boost_direction[dir]; #elif defined(WARPX_DIM_XZ) || defined(WARPX_DIM_RZ) - // In 2D, dir=0 corresponds to x and dir=1 corresponds to z - // This needs to be converted in order to index `boost_direction` - // which has 3 components, for both 2D and 3D simulations. - WarpX::boost_direction[2*dir] * PhysConst::c * a_dt; + // In 2D, dir=0 corresponds to x and dir=1 corresponds to z. + // This needs to be converted to access boost_direction, + // which has always 3 components. + v_bulk *= WarpX::boost_direction[2*dir]; #elif defined(WARPX_DIM_1D_Z) - // In 1D, dir=0 corresponds to z - // This needs to be converted in order to index `boost_direction` - // which has 3 components, for 1D, 2D, and 3D simulations. - WarpX::boost_direction[2] * PhysConst::c * a_dt; - amrex::ignore_unused(dir); + // In 1D, dir=0 corresponds to z. + // This needs to be converted to access boost_direction, + // which has always 3 components. + v_bulk *= WarpX::boost_direction[2]; + amrex::ignore_unused(dir); #endif + } + + // Update current injection position + pc.m_current_injection_position += v_bulk * a_dt; + } } } @@ -96,15 +152,13 @@ WarpX::MoveWindow (const int step, bool move_j) moving_window_x += (moving_window_v - WarpX::beta_boost * PhysConst::c)/(1 - moving_window_v * WarpX::beta_boost / PhysConst::c) * dt[0]; const int dir = moving_window_dir; - // Update warpx.current_injection_position + // Update warpx.current_injection_position, // PhysicalParticleContainer uses this injection position UpdatePlasmaInjectionPosition( dt[0] ); - if (WarpX::warpx_do_continuous_injection){ - // Update injection position for WarpXParticleContainer in mypc. - // Nothing to do for PhysicalParticleContainers - // For LaserParticleContainer, need to update the antenna position. - mypc->UpdateContinuousInjectionPosition( dt[0] ); - } + // Update injection position for WarpXParticleContainer in mypc, + // nothing to do for PhysicalParticleContainer, + // need to update the antenna position for LaserParticleContainer. + mypc->UpdateContinuousInjectionPosition( dt[0] ); // compute the number of cells to shift on the base level amrex::Real new_lo[AMREX_SPACEDIM]; @@ -312,41 +366,54 @@ WarpX::MoveWindow (const int step, bool move_j) } } - // Continuously inject plasma in new cells (by default only on level 0) - if (WarpX::warpx_do_continuous_injection) { - - const int lev = 0; - - // particleBox encloses the cells where we generate particles - // (only injects particles in an integer number of cells, - // for correct particle spacing) - amrex::RealBox particleBox = geom[lev].ProbDomain(); - amrex::Real new_injection_position; - if (moving_window_v >= 0){ - // Forward-moving window - const amrex::Real dx = geom[lev].CellSize(dir); - new_injection_position = current_injection_position + - std::floor( (geom[lev].ProbHi(dir) - current_injection_position)/dx ) * dx; - } else { - // Backward-moving window - const amrex::Real dx = geom[lev].CellSize(dir); - new_injection_position = current_injection_position - - std::floor( (current_injection_position - geom[lev].ProbLo(dir))/dx) * dx; - } - // Modify the corresponding bounds of the particleBox - if (moving_window_v >= 0) { - particleBox.setLo( dir, current_injection_position ); - particleBox.setHi( dir, new_injection_position ); - } else { - particleBox.setLo( dir, new_injection_position ); - particleBox.setHi( dir, current_injection_position ); - } + // Loop over species + const int n_species = mypc->nSpecies(); + for (int i=0; i<n_species; i++) + { + WarpXParticleContainer& pc = mypc->GetParticleContainer(i); + + // Continuously inject plasma in new cells (by default only on level 0) + if (pc.doContinuousInjection()) + { + const int lev = 0; + + // particleBox encloses the cells where we generate particles + // (only injects particles in an integer number of cells, + // for correct particle spacing) + amrex::RealBox particleBox = geom[lev].ProbDomain(); + amrex::Real new_injection_position = pc.m_current_injection_position; + if (moving_window_v > 0._rt) + { + // Forward-moving window + const amrex::Real dx = geom[lev].CellSize(dir); + new_injection_position = pc.m_current_injection_position + + std::floor( (geom[lev].ProbHi(dir) - pc.m_current_injection_position)/dx ) * dx; + } + else if (moving_window_v < 0._rt) + { + // Backward-moving window + const amrex::Real dx = geom[lev].CellSize(dir); + new_injection_position = pc.m_current_injection_position - + std::floor( (pc.m_current_injection_position - geom[lev].ProbLo(dir))/dx) * dx; + } + // Modify the corresponding bounds of the particleBox + if (moving_window_v > 0._rt) + { + particleBox.setLo( dir, pc.m_current_injection_position ); + particleBox.setHi( dir, new_injection_position ); + } + else if (moving_window_v < 0._rt) + { + particleBox.setLo( dir, new_injection_position ); + particleBox.setHi( dir, pc.m_current_injection_position ); + } - if (particleBox.ok() and (current_injection_position != new_injection_position)){ - // Performs continuous injection of all WarpXParticleContainer - // in mypc. - mypc->ContinuousInjection(particleBox); - current_injection_position = new_injection_position; + if (particleBox.ok() and (pc.m_current_injection_position != new_injection_position)){ + // Performs continuous injection of all WarpXParticleContainer + // in mypc. + pc.ContinuousInjection(particleBox); + pc.m_current_injection_position = new_injection_position; + } } } |