aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Exec/plasma_acceleration/inputs7
-rw-r--r--Source/WarpX.H9
-rw-r--r--Source/WarpX.cpp16
-rw-r--r--Source/WarpXEvolve.cpp93
4 files changed, 120 insertions, 5 deletions
diff --git a/Exec/plasma_acceleration/inputs b/Exec/plasma_acceleration/inputs
index 951ea4e85..ef8729aaa 100644
--- a/Exec/plasma_acceleration/inputs
+++ b/Exec/plasma_acceleration/inputs
@@ -56,3 +56,10 @@ pwfa.plasma_density = 1e22 # number of electrons per m^3
warpx.do_moving_window = 1
warpx.moving_window_dir = 2 # 0, 1, 2, for x, y, z
warpx.moving_window_v = 1.0 # in units of the speed of light
+
+# Particle Injection
+warpx.do_plasma_injection = 1
+warpx.num_injected_species = 1
+warpx.injected_plasma_species = 1 0
+warpx.injected_plasma_density = 1e22 1e22
+warpx.injected_plasma_ppc = 4 4
diff --git a/Source/WarpX.H b/Source/WarpX.H
index b03b4e9fc..be290c6f2 100644
--- a/Source/WarpX.H
+++ b/Source/WarpX.H
@@ -77,6 +77,7 @@ private:
void ComputeDt ();
void MoveWindow ();
+ void InjectPlasma(int num_shift, int dir);
void WriteWarpXHeader(const std::string& name) const;
void WriteCheckPointFile() const;
@@ -106,8 +107,14 @@ private:
Real moving_window_x;
Real moving_window_v;
- // runtime parameters
+ // Plasma injection parameters
+ int do_plasma_injection = 0;
+ int num_injected_species;
+ Array<int> injected_plasma_ppc;
+ Array<int> injected_plasma_species;
+ Array<Real> injected_plasma_density;
+ // Other runtime parameters
int verbose = 1;
int max_step = std::numeric_limits<int>::max();
diff --git a/Source/WarpX.cpp b/Source/WarpX.cpp
index bb6509786..00453fa5c 100644
--- a/Source/WarpX.cpp
+++ b/Source/WarpX.cpp
@@ -133,6 +133,20 @@ WarpX::ReadParameters ()
pp.get("moving_window_v", moving_window_v);
}
+ pp.query("do_plasma_injection", do_plasma_injection);
+ if (do_plasma_injection) {
+ pp.get("num_injected_species", num_injected_species);
+ injected_plasma_ppc.resize(num_injected_species);
+ pp.getarr("injected_plasma_ppc", injected_plasma_ppc,
+ 0, num_injected_species);
+ injected_plasma_species.resize(num_injected_species);
+ pp.getarr("injected_plasma_species", injected_plasma_species,
+ 0, num_injected_species);
+ injected_plasma_density.resize(num_injected_species);
+ pp.getarr("injected_plasma_density", injected_plasma_density,
+ 0, num_injected_species);
+ }
+
moving_window_x = geom[0].ProbLo(moving_window_dir);
moving_window_v = 0.0;
pp.query("moving_window_v", moving_window_v);
@@ -238,8 +252,6 @@ WarpX::shiftMF(MultiFab& mf, const Geometry& geom, int num_shift,
mf[mfi].copy(tmpmf[mfi], srcBox, 0, dstBox, 0, mf.nComp());
mf[mfi].SetBoxType(dst_typ);
}
-
- mf.FillBoundary(geom.periodicity());
}
void
diff --git a/Source/WarpXEvolve.cpp b/Source/WarpXEvolve.cpp
index 76c928621..975d54d6a 100644
--- a/Source/WarpXEvolve.cpp
+++ b/Source/WarpXEvolve.cpp
@@ -272,6 +272,93 @@ WarpX::ComputeDt ()
}
void
+WarpX::InjectPlasma(int num_shift, int dir) {
+
+ if(do_plasma_injection) {
+
+ // particleBox encloses the cells where we generate particles
+ Box particleBox = geom[0].Domain();
+ int domainLength = particleBox.length(dir);
+ int sign = (num_shift < 0) ? -1 : 1;
+ particleBox.shift(dir, sign*(domainLength - std::abs(num_shift)));
+ particleBox &= geom[0].Domain();
+
+ // get a dummy mf to loop over
+ const Real* dx = geom[0].CellSize();
+ WarpXParticleContainer* myspc = &(mypc->GetParticleContainer(0));
+ const BoxArray& ba = myspc->ParticleBoxArray(0);
+ const DistributionMapping& dm = myspc->ParticleDistributionMap(0);
+ MultiFab dummy_mf(ba, 1, 0, dm, Fab_noallocate);
+
+ // For each grid, loop only over the cells in the new region
+ for (MFIter mfi(dummy_mf,false); mfi.isValid(); ++mfi) {
+ int gid = mfi.index();
+ Box grid = ba[gid];
+ Box intersectBox = grid & particleBox;
+ if (intersectBox.isEmpty()) continue;
+ RealBox intersectRealBox { intersectBox, dx, geom[0].ProbLo() };
+
+#if (BL_SPACEDIM == 3)
+ int nx = intersectBox.length(0);
+ int ny = intersectBox.length(1);
+ int nz = intersectBox.length(2);
+#elif (BL_SPACEDIM == 2)
+ int nx = intersectBox.length(0);
+ int ny = 1;
+ int nz = intersectBox.length(1);
+#endif
+
+ for (int k = 0; k < nz; k++) {
+ for (int j = 0; j < ny; j++) {
+ for (int i = 0; i < nx; i++) {
+ for (int ispec=0; ispec < num_injected_species; ispec++) {
+ int ispecies = injected_plasma_species[ispec];
+ myspc = &(mypc->GetParticleContainer(ispecies));
+ for (int i_part=0; i_part < injected_plasma_ppc[ispec]; i_part++) {
+ Real particle_shift = (0.5+i_part)/injected_plasma_ppc[ispec];
+#if (BL_SPACEDIM == 3)
+ Real x = intersectRealBox.lo(0) + (i + particle_shift)*dx[0];
+ Real y = intersectRealBox.lo(1) + (j + particle_shift)*dx[1];
+ Real z = intersectRealBox.lo(2) + (k + particle_shift)*dx[2];
+#elif (BL_SPACEDIM == 2)
+ Real x = intersectRealBox.lo(0) + (i + particle_shift)*dx[0];
+ Real y = 0.0;
+ Real z = intersectRealBox.lo(1) + (k + particle_shift)*dx[1];
+#endif
+
+ int id = ParticleBase::NextID();
+ int cpu = ParallelDescriptor::MyProc();
+
+ std::vector<Real> pos(3, 0.0);
+#if (BL_SPACEDIM == 3)
+ pos[0] = x;
+ pos[1] = y;
+ pos[2] = z;
+#elif (BL_SPACEDIM == 2)
+ pos[0] = x;
+ pos[1] = z;
+#endif
+
+ std::vector<Real> attributes(PIdx::nattribs, 0.0);
+
+ Real weight = injected_plasma_density[ispec];
+#if BL_SPACEDIM==3
+ weight *= dx[0]*dx[1]*dx[2]/injected_plasma_ppc[ispec];
+#elif BL_SPACEDIM==2
+ weight *= dx[0]*dx[1]/injected_plasma_ppc[ispec];
+#endif
+ attributes[PIdx::w] = weight;
+ myspc->addOneParticle(id, cpu, pos, attributes);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+void
WarpX::MoveWindow ()
{
@@ -307,6 +394,8 @@ WarpX::MoveWindow ()
shiftMF(*Efield[0][1], geom[0], num_shift, dir, Ey_nodal_flag);
shiftMF(*Efield[0][2], geom[0], num_shift, dir, Ez_nodal_flag);
- // remove particles that are outside of the box
- mypc->Redistribute(false); // Redistribute particles
+ InjectPlasma(num_shift, dir);
+
+ // Redistribute (note - this removes particles that are outside of the box)
+ mypc->Redistribute(false);
}