aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Docs/source/building/rzgeometry.rst4
-rw-r--r--Docs/source/building/spectral.rst2
-rw-r--r--Docs/source/running_cpp/parameters.rst16
-rw-r--r--Docs/source/visualization/advanced.rst53
-rw-r--r--Docs/source/visualization/inputs.2d4
-rw-r--r--Docs/source/visualization/openpmdviewer.rst53
-rw-r--r--Docs/source/visualization/picviewer.rst4
-rw-r--r--Docs/source/visualization/visit.rst10
-rw-r--r--Docs/source/visualization/visualization.rst25
-rw-r--r--Docs/source/visualization/yt.rst28
-rw-r--r--Examples/Modules/RigidInjection/inputs5
-rw-r--r--Examples/Modules/boosted_diags/inputs.2d7
-rw-r--r--Examples/Modules/boosted_diags/inputs.3d7
-rw-r--r--Examples/Modules/gaussian_beam/inputs5
-rw-r--r--Examples/Physics_applications/laser_acceleration/inputs.2d5
-rw-r--r--Examples/Physics_applications/laser_acceleration/inputs.2d.boost7
-rw-r--r--Examples/Physics_applications/laser_acceleration/inputs.3d6
-rw-r--r--Examples/Physics_applications/plasma_acceleration/inputs.2d4
-rw-r--r--Examples/Physics_applications/plasma_acceleration/inputs.2d.boost5
-rw-r--r--Examples/Physics_applications/plasma_acceleration/inputs.3d.boost5
-rw-r--r--Examples/Tests/Larmor/inputs3
-rw-r--r--Examples/Tests/Larmor/inputs.ml3
-rw-r--r--Examples/Tests/PML/inputs2d5
-rw-r--r--Examples/Tests/laser_on_fine/inputs5
-rw-r--r--Examples/Tests/laser_on_fine/inputs.2d5
-rw-r--r--Examples/Tests/self_force_test/inputs3
-rw-r--r--Examples/Tests/subcycling/inputs.2d8
-rw-r--r--Python/pywarpx/picmi.py18
-rw-r--r--Source/Laser/LaserParticleContainer.H12
-rw-r--r--Source/Laser/LaserParticleContainer.cpp98
-rw-r--r--Source/Particles/MultiParticleContainer.H10
-rw-r--r--Source/Particles/MultiParticleContainer.cpp45
-rw-r--r--Source/Particles/PhysicalParticleContainer.H5
-rw-r--r--Source/Particles/PhysicalParticleContainer.cpp18
-rw-r--r--Source/Particles/WarpXParticleContainer.H20
-rw-r--r--Source/Utils/WarpXMovingWindow.cpp25
-rw-r--r--Source/WarpX.H4
-rw-r--r--Source/WarpX.cpp30
-rw-r--r--Tools/Visualization.ipynb10
-rw-r--r--Tools/performance_tests/automated_test_4_labdiags_2ppc7
40 files changed, 401 insertions, 188 deletions
diff --git a/Docs/source/building/rzgeometry.rst b/Docs/source/building/rzgeometry.rst
index 79bb1edc0..1c4df9ea3 100644
--- a/Docs/source/building/rzgeometry.rst
+++ b/Docs/source/building/rzgeometry.rst
@@ -8,4 +8,6 @@ To select RZ geometry, set the flag USE_RZ = TRUE when compiling:
make -j 4 USE_RZ=TRUE
-Note that this sets DIM=2, which is required with USE_RZ=TRUE. The executable produced will have "RZ" as a suffix.
+Note that this sets DIM=2, which is required with USE_RZ=TRUE.
+The executable produced will have "RZ" as a suffix. Currently
+does not work with USE_PSATD.
diff --git a/Docs/source/building/spectral.rst b/Docs/source/building/spectral.rst
index 50c67d4a9..55a402c87 100644
--- a/Docs/source/building/spectral.rst
+++ b/Docs/source/building/spectral.rst
@@ -20,3 +20,5 @@ In order to run the code with a spectral solver, you need to:
::
make -j 4 USE_PSATD=TRUE
+
+Note that this is not compatible with USE_RZ yet. \ No newline at end of file
diff --git a/Docs/source/running_cpp/parameters.rst b/Docs/source/running_cpp/parameters.rst
index 624aeaf84..076e39ce6 100644
--- a/Docs/source/running_cpp/parameters.rst
+++ b/Docs/source/running_cpp/parameters.rst
@@ -178,6 +178,11 @@ Particle initialization
* ``NRandomPerCell``: injection with a fixed number of randomly-distributed particles per cell.
This requires the additional parameter ``<species_name>.num_particles_per_cell``.
+* ``<species_name>.do_continuous_injection`` (`0` or `1`)
+ Whether to inject particles during the simulation, and not only at
+ initialization. This can be required whith a moving window and/or when
+ running in a boosted frame.
+
* ``<species_name>.profile`` (`string`)
Density profile for this species. The options are:
@@ -432,6 +437,17 @@ Laser initialization
Temporal chirp at focus.
See definition in Akturk et al., Opt Express, vol 12, no 19 (2014).
+* ``<laser_name>.do_continuous_injection`` (`0` or `1`) optional (default `0`).
+ Whether or not to use continuous injection (`0` or not `0`).
+ If the antenna starts outside of the simulation domain but enters it
+ at some point (due to moving window or moving antenna in the boosted
+ frame), use this so that the laser antenna is injected when it reaches
+ the box boundary. If running in a boosted frame, this requires the
+ boost direction, moving window direction and laser propagation direction
+ to be along `z`. If not running in a boosted frame, this requires the
+ moving window and laser propagation directions to be the same (`x`, `y`
+ or `z`)
+
* ``warpx.num_mirrors`` (`int`) optional (default `0`)
Users can input perfect mirror condition inside the simulation domain.
The number of mirrors is given by ``warpx.num_mirrors``. The mirrors are
diff --git a/Docs/source/visualization/advanced.rst b/Docs/source/visualization/advanced.rst
index 9747eec91..157f8a8e0 100644
--- a/Docs/source/visualization/advanced.rst
+++ b/Docs/source/visualization/advanced.rst
@@ -1,22 +1,22 @@
-Advanced visualization (for developers)
-=======================================
+Advanced yt visualization, for developers (for plotfiles)
+=========================================================
This sections contains yt commands for advanced users. The Particle-In-Cell methods uses a
-staggered grid (see :doc:`../theory/picsar_theory`), so that the x, y, and z components of the
+staggered grid (see :doc:`../theory/picsar_theory`), so that the x, y, and z components of the
electric and magnetic fields are all defined at different locations in space. Regular output
-(see the :doc:`yt` page, or the notebook at ``WarpX/Tools/Visualization.ipynb`` for an example)
-returns cell-centered data for convenience, which involves an additional operation. It is sometimes
-useful to access the raw data directly. Furthermore,
-the WarpX implementation for mesh refinement contains a number of grids for each level (coarse,
-fine and auxilary, see
-:doc:`../theory/warpx_theory` for more details), and it is sometimes useful to access each of
-them (regular output return the auxiliary grid only). This page provides information to read
+(see the :doc:`yt` page, or the notebook at ``WarpX/Tools/Visualization.ipynb`` for an example)
+returns cell-centered data for convenience, which involves an additional operation. It is sometimes
+useful to access the raw data directly. Furthermore,
+the WarpX implementation for mesh refinement contains a number of grids for each level (coarse,
+fine and auxilary, see
+:doc:`../theory/warpx_theory` for more details), and it is sometimes useful to access each of
+them (regular output return the auxiliary grid only). This page provides information to read
raw data of all grids.
Dump additional data
--------------------
-In order to dump additional data in WarpX (mostly for debugging purpose), run the simulation
+In order to dump additional data in WarpX (mostly for debugging purpose), run the simulation
with parameters
::
@@ -27,13 +27,13 @@ with parameters
warpx.plot_dive = 1
warpx.plot_rho = 1
-see :doc:`../running_cpp/parameters` for more information on these parameters.
+see :doc:`../running_cpp/parameters` for more information on these parameters.
Read raw data
-------------
-Meta-data
-relevant to this topic (number and locations of grids in the simulation) are accessed to
+Meta-data
+relevant to this topic (number and locations of grids in the simulation) are accessed to
with
::
@@ -51,13 +51,13 @@ with
# List available fields
ds.field_list
-When ``warpx.plot_raw_fields=1`` and ``warpx.plot_finepatch=1``, here are some useful
+When ``warpx.plot_raw_fields=1`` and ``warpx.plot_finepatch=1``, here are some useful
commands to access properties of a grid and the Ex field on the fine patch:
::
# store grid number 2 into my_grid
- my_grid = ds.index.grids[2]
+ my_grid = ds.index.grids[2]
# Get left and right edges of my_grid
my_grid.LeftEdge
my_grid.RightEdge
@@ -71,15 +71,14 @@ Return the ``Ex`` field on the fine patch of grid ``my_grid``:
::
my_field = my_grid['raw', 'Ex_fp'].squeeze().v
-
-For a 2D plotfile, ``my_field`` has shape ``(nx,nz,2)``. The last component stands for the
-two values on the edges of each cell for the electric field, due to field staggering. Numpy
-function ``squeeze`` removes empty components. While ``yt`` arrays are unit-aware, it is
-sometimes useful to extract the data into unitless numpy arrays. This is achieved with ``.v``.
-In the case of ``Ex_fp``, the staggering is on direction ``x``, so that
-``my_field[:,:-1,1] == my_field[:,1:,0]``.
-
-All combinations of the fields (``E`` or ``B``), the component (``x``, ``y`` or ``z``) and the
-grid (``_fp`` for fine, ``_cp`` for coarse and ``_aux`` for auxiliary) can be accessed in this
-way, i.e., ``my_grid['raw', 'Ey_aux']`` or ``my_grid['raw', 'Bz_cp']`` are valid queries.
+For a 2D plotfile, ``my_field`` has shape ``(nx,nz,2)``. The last component stands for the
+two values on the edges of each cell for the electric field, due to field staggering. Numpy
+function ``squeeze`` removes empty components. While ``yt`` arrays are unit-aware, it is
+sometimes useful to extract the data into unitless numpy arrays. This is achieved with ``.v``.
+In the case of ``Ex_fp``, the staggering is on direction ``x``, so that
+``my_field[:,:-1,1] == my_field[:,1:,0]``.
+
+All combinations of the fields (``E`` or ``B``), the component (``x``, ``y`` or ``z``) and the
+grid (``_fp`` for fine, ``_cp`` for coarse and ``_aux`` for auxiliary) can be accessed in this
+way, i.e., ``my_grid['raw', 'Ey_aux']`` or ``my_grid['raw', 'Bz_cp']`` are valid queries.
diff --git a/Docs/source/visualization/inputs.2d b/Docs/source/visualization/inputs.2d
index 83daa2da5..f392ac3c9 100644
--- a/Docs/source/visualization/inputs.2d
+++ b/Docs/source/visualization/inputs.2d
@@ -45,9 +45,6 @@ interpolation.noz = 3
particles.nspecies = 3
particles.species_names = plasma_e beam driver
particles.use_fdtd_nci_corr = 1
-warpx.do_plasma_injection = 1
-warpx.num_injected_species = 1
-warpx.injected_plasma_species = 0
driver.charge = -q_e
driver.mass = m_e
@@ -82,6 +79,7 @@ plasma_e.momentum_distribution_type = "constant"
plasma_e.ux = 0.0
plasma_e.uy = 0.0
plasma_e.uz = 0.0
+plasma_e.do_continuous_injection = 1
beam.charge = -q_e
beam.mass = m_e
diff --git a/Docs/source/visualization/openpmdviewer.rst b/Docs/source/visualization/openpmdviewer.rst
new file mode 100644
index 000000000..4d41ba00f
--- /dev/null
+++ b/Docs/source/visualization/openpmdviewer.rst
@@ -0,0 +1,53 @@
+Visualization with openPMD-viewer (for openPMD data)
+====================================================
+
+openPMD-viewer is an open-source Python package to access openPMD data.
+
+It allows to:
+- Quickly browse through the data, with a GUI-type interface in the Jupyter notebook
+- Have access to the data numpy array, for more detailed analysis
+
+Installation
+------------
+
+openPMD-viewer can be installed via ``conda`` or ``pip``:
+
+::
+
+ conda install -c rlehe openpmd_viewer
+
+::
+
+ pip install openPMD-viewer
+
+Usage
+-----
+
+openPMD-viewer can be used either in simple Python scripts, or in a Jupyter
+notebook. In both cases, you can import openPMD-viewer, and load the data
+with the following commands:
+
+::
+
+ from opmd_viewer import OpenPMDTimeSeries
+ ts = OpenPMDTimeSeries('./diags/hdf5')
+
+.. note::
+
+ If you are using the Jupyter notebook, then you can start a pre-filled
+ notebook, which already contains the above lines, by typing in a terminal:
+
+ ::
+
+ openPMD_notebook
+
+When using the Jupyter notebook, you can quickly browse through the data
+by using the command:
+
+::
+
+ ts.slider()
+
+You can also access the particle and field data as numpy arrays with the
+methods ``ts.get_field`` and ``ts.get_particle``. See the openPMD-viewer
+tutorials `here <https://github.com/openPMD/openPMD-viewer/tree/master/tutorials>`_ for more info.
diff --git a/Docs/source/visualization/picviewer.rst b/Docs/source/visualization/picviewer.rst
index b29faddaa..3b5832238 100644
--- a/Docs/source/visualization/picviewer.rst
+++ b/Docs/source/visualization/picviewer.rst
@@ -1,5 +1,5 @@
-PyQt-based visualization GUI: PICViewer
-=========================================
+PyQt-based visualization GUI: PICViewer (for both plotfiles and openPMD)
+========================================================================
.. figure:: sample_image.png
:alt: picture
diff --git a/Docs/source/visualization/visit.rst b/Docs/source/visualization/visit.rst
index 50f0be978..153d44734 100644
--- a/Docs/source/visualization/visit.rst
+++ b/Docs/source/visualization/visit.rst
@@ -1,5 +1,11 @@
-Visualization with Visit
-========================
+Visualization with Visit (for plotfiles)
+========================================
+
+.. note::
+
+ The openPMD format can also be visualized with Visit, but requires the
+ installation of a specific plugin: see
+ `this link <https://github.com/openPMD/openPMD-visit-plugin>`_.
WarpX results can also be visualized by VisIt, an open source visualization and analysis software. VisIT can be downloaded and installed from https://wci.llnl.gov/simulation/computer-codes/visit.
diff --git a/Docs/source/visualization/visualization.rst b/Docs/source/visualization/visualization.rst
index 29c299798..0c9c56837 100644
--- a/Docs/source/visualization/visualization.rst
+++ b/Docs/source/visualization/visualization.rst
@@ -1,12 +1,33 @@
Visualizing the simulation results
==================================
+WarpX can write data either in `plotfile` format (AMReX's native format), or
+in `openPMD format <https://www.openpmd.org/>`_ (a common data format for
+Particle-In-Cell codes).
+
+.. note::
+
+ This is controlled by the parameters ``warpx.dump_plotfiles`` and
+ ``warpx.dump_openpmd`` in the section :doc:`../running_cpp/parameters`.
+
+This section describes some of the tools available to visualize the data:
+
.. toctree::
:maxdepth: 1
yt
visit
picviewer
- sensei
- ascent
+ openpmdviewer
advanced
+
+
+In addition, WarpX also has In-Situ Visualization capabilities (i.e.
+visualizing the data directly from the simulation, without dumping data
+files to disk).
+
+.. toctree::
+ :maxdepth: 1
+
+ sensei
+ ascent
diff --git a/Docs/source/visualization/yt.rst b/Docs/source/visualization/yt.rst
index 9317a3579..d52080458 100644
--- a/Docs/source/visualization/yt.rst
+++ b/Docs/source/visualization/yt.rst
@@ -1,5 +1,5 @@
-Visualization with yt
-=====================
+Visualization with yt (for plotfiles)
+=====================================
`yt <http://yt-project.org/>`__ is a Python package that can help in analyzing
and visualizing WarpX data (among other data formats). It is convenient
@@ -18,12 +18,12 @@ or with the `Anaconda distribution <https://anaconda.org/>`__ of python (recomme
::
- conda install -c atmyers yt
+ conda install yt
Visualizing the data
--------------------
-Once data ("plot files") has been created by the simulation, open a Jupyter notebook from
+Once data ("plotfiles") has been created by the simulation, open a Jupyter notebook from
the terminal:
::
@@ -36,7 +36,13 @@ and load the first plot file:
::
import yt
- ds = yt.load('./plt00000/')
+ ds = yt.load('./diags/plotfiles/plt00000/')
+
+The list of field data and particle data stored can be seen with:
+
+::
+
+ ds.field_list
Field data
~~~~~~~~~~
@@ -50,6 +56,18 @@ For instance, in order to plot the field ``Ex`` in a slice orthogonal to ``y`` (
yt.SlicePlot( ds, 1, 'Ex', origin='native' )
+.. note::
+
+ `yt.SlicePlot` creates a 2D plot with the same aspect ratio as the physical
+ size of the simulation box. Sometimes this can lead to very elongated plots
+ that are difficult to read. You can modify the aspect ratio with the
+ `aspect` argument ; for instance:
+
+ ::
+
+ yt.SlicePlot( ds, 1, 'Ex', aspect=1./10 )
+
+
Alternatively, the data can be obtained as a `numpy <http://www.numpy.org/>`__ array.
For instance, in order to obtain the field `jz` (on level 0) as a numpy array:
diff --git a/Examples/Modules/RigidInjection/inputs b/Examples/Modules/RigidInjection/inputs
index b6a62d0bd..d7e3b77e8 100644
--- a/Examples/Modules/RigidInjection/inputs
+++ b/Examples/Modules/RigidInjection/inputs
@@ -90,8 +90,3 @@ warpx.moving_window_v = 1.0 # in units of the speed of light
# Boosted frame
warpx.gamma_boost = 1.5
warpx.boost_direction = z
-
-# Particle Injection
-warpx.do_plasma_injection = 0
-warpx.num_injected_species = 0
-warpx.injected_plasma_species = 0
diff --git a/Examples/Modules/boosted_diags/inputs.2d b/Examples/Modules/boosted_diags/inputs.2d
index 6315d34cb..33eee5392 100644
--- a/Examples/Modules/boosted_diags/inputs.2d
+++ b/Examples/Modules/boosted_diags/inputs.2d
@@ -51,11 +51,6 @@ warpx.do_boosted_frame_diagnostic = 1
warpx.num_snapshots_lab = 20;
warpx.dt_snapshots_lab = 7.0e-14;
-# Particle Injection
-warpx.do_plasma_injection = 1
-warpx.num_injected_species = 2
-warpx.injected_plasma_species = 0 1
-
# Species
particles.nspecies = 2
particles.species_names = electrons ions
@@ -72,6 +67,7 @@ electrons.num_particles_per_cell_each_dim = 1 1 2
electrons.profile = constant
electrons.density = 1.
electrons.momentum_distribution_type = "constant"
+electrons.do_continuous_injection = 1
ions.charge = q_e
ions.mass = m_p
@@ -85,6 +81,7 @@ ions.num_particles_per_cell_each_dim = 1 1 2
ions.profile = constant
ions.density = 1.
ions.momentum_distribution_type = "constant"
+ions.do_continuous_injection = 1
# Laser
lasers.nlasers = 1
diff --git a/Examples/Modules/boosted_diags/inputs.3d b/Examples/Modules/boosted_diags/inputs.3d
index 6315d34cb..33eee5392 100644
--- a/Examples/Modules/boosted_diags/inputs.3d
+++ b/Examples/Modules/boosted_diags/inputs.3d
@@ -51,11 +51,6 @@ warpx.do_boosted_frame_diagnostic = 1
warpx.num_snapshots_lab = 20;
warpx.dt_snapshots_lab = 7.0e-14;
-# Particle Injection
-warpx.do_plasma_injection = 1
-warpx.num_injected_species = 2
-warpx.injected_plasma_species = 0 1
-
# Species
particles.nspecies = 2
particles.species_names = electrons ions
@@ -72,6 +67,7 @@ electrons.num_particles_per_cell_each_dim = 1 1 2
electrons.profile = constant
electrons.density = 1.
electrons.momentum_distribution_type = "constant"
+electrons.do_continuous_injection = 1
ions.charge = q_e
ions.mass = m_p
@@ -85,6 +81,7 @@ ions.num_particles_per_cell_each_dim = 1 1 2
ions.profile = constant
ions.density = 1.
ions.momentum_distribution_type = "constant"
+ions.do_continuous_injection = 1
# Laser
lasers.nlasers = 1
diff --git a/Examples/Modules/gaussian_beam/inputs b/Examples/Modules/gaussian_beam/inputs
index 23eca9bdc..0cab8d140 100644
--- a/Examples/Modules/gaussian_beam/inputs
+++ b/Examples/Modules/gaussian_beam/inputs
@@ -102,8 +102,3 @@ warpx.do_pml = 0
warpx.do_moving_window = 0
warpx.moving_window_dir = z
warpx.moving_window_v = 1.0 # in units of the speed of light
-
-# Particle Injection
-warpx.do_plasma_injection = 0
-warpx.num_injected_species = 1
-warpx.injected_plasma_species = 1 0
diff --git a/Examples/Physics_applications/laser_acceleration/inputs.2d b/Examples/Physics_applications/laser_acceleration/inputs.2d
index 733ea6b86..11ddc6b0b 100644
--- a/Examples/Physics_applications/laser_acceleration/inputs.2d
+++ b/Examples/Physics_applications/laser_acceleration/inputs.2d
@@ -53,6 +53,7 @@ electrons.zmin = 10.e-6
electrons.profile = constant
electrons.density = 2.e23 # number of electrons per m^3
electrons.momentum_distribution_type = "constant"
+electrons.do_continuous_injection = 1
beam.charge = -q_e
beam.mass = m_e
@@ -74,10 +75,6 @@ beam.uz_m = 500.
beam.ux_th = 2.
beam.uy_th = 2.
beam.uz_th = 50.
-# Particle Injection
-warpx.do_plasma_injection = 1
-warpx.num_injected_species = 1
-warpx.injected_plasma_species = 0
#################################
############ PLASMA #############
diff --git a/Examples/Physics_applications/laser_acceleration/inputs.2d.boost b/Examples/Physics_applications/laser_acceleration/inputs.2d.boost
index 3b452851e..b1fb28126 100644
--- a/Examples/Physics_applications/laser_acceleration/inputs.2d.boost
+++ b/Examples/Physics_applications/laser_acceleration/inputs.2d.boost
@@ -66,6 +66,7 @@ electrons.profile = "predefined"
electrons.predefined_profile_name = "parabolic_channel"
# predefined_profile_params = z_start ramp_up plateau ramp_down rc n0
electrons.predefined_profile_params = .5e-3 .5e-3 2.e-3 .5e-3 50.e-6 3.5e24
+electrons.do_continuous_injection = 1
ions.charge = q_e
ions.mass = m_p
@@ -80,6 +81,7 @@ ions.profile = "predefined"
ions.predefined_profile_name = "parabolic_channel"
# predefined_profile_params = z_start ramp_up plateau ramp_down rc n0
ions.predefined_profile_params = .5e-3 .5e-3 2.e-3 .5e-3 50.e-6 3.5e24
+ions.do_continuous_injection = 1
beam.charge = -q_e
beam.mass = m_e
@@ -106,11 +108,6 @@ beam.rigid_advance = true
beam.projected = true
beam.focused = false
-# Particle Injection
-warpx.do_plasma_injection = 1
-warpx.num_injected_species = 2
-warpx.injected_plasma_species = 0 1
-
#################################
############# LASER #############
#################################
diff --git a/Examples/Physics_applications/laser_acceleration/inputs.3d b/Examples/Physics_applications/laser_acceleration/inputs.3d
index 91837b23c..8e854cbf4 100644
--- a/Examples/Physics_applications/laser_acceleration/inputs.3d
+++ b/Examples/Physics_applications/laser_acceleration/inputs.3d
@@ -55,11 +55,7 @@ electrons.zmin = 10.e-6
electrons.profile = constant
electrons.density = 2.e23 # number of electrons per m^3
electrons.momentum_distribution_type = "constant"
-
-# Particle Injection
-warpx.do_plasma_injection = 1
-warpx.num_injected_species = 1
-warpx.injected_plasma_species = 0
+electrons.do_continuous_injection = 1
#################################
############ PLASMA #############
diff --git a/Examples/Physics_applications/plasma_acceleration/inputs.2d b/Examples/Physics_applications/plasma_acceleration/inputs.2d
index c6115182b..e092cf932 100644
--- a/Examples/Physics_applications/plasma_acceleration/inputs.2d
+++ b/Examples/Physics_applications/plasma_acceleration/inputs.2d
@@ -40,9 +40,6 @@ interpolation.noz = 3
particles.nspecies = 3
particles.species_names = plasma_e beam driver
particles.use_fdtd_nci_corr = 1
-warpx.do_plasma_injection = 1
-warpx.num_injected_species = 1
-warpx.injected_plasma_species = 0
driver.charge = -q_e
driver.mass = m_e
@@ -77,6 +74,7 @@ plasma_e.momentum_distribution_type = "constant"
plasma_e.ux = 0.0
plasma_e.uy = 0.0
plasma_e.uz = 0.0
+plasma_e.do_continuous_injection = 1
beam.charge = -q_e
beam.mass = m_e
diff --git a/Examples/Physics_applications/plasma_acceleration/inputs.2d.boost b/Examples/Physics_applications/plasma_acceleration/inputs.2d.boost
index adeedaba9..59e7c432b 100644
--- a/Examples/Physics_applications/plasma_acceleration/inputs.2d.boost
+++ b/Examples/Physics_applications/plasma_acceleration/inputs.2d.boost
@@ -54,9 +54,6 @@ particles.nspecies = 4
particles.species_names = driver plasma_e plasma_p beam
particles.use_fdtd_nci_corr = 1
particles.rigid_injected_species = driver beam
-warpx.do_plasma_injection = 1
-warpx.num_injected_species = 2
-warpx.injected_plasma_species = 1 2
driver.charge = -q_e
driver.mass = m_e
@@ -95,6 +92,7 @@ plasma_e.momentum_distribution_type = "constant"
plasma_e.ux = 0.0
plasma_e.uy = 0.0
plasma_e.uz = 0.0
+plasma_e.do_continuous_injection = 1
plasma_p.charge = q_e
plasma_p.mass = m_p
@@ -110,6 +108,7 @@ plasma_p.momentum_distribution_type = "constant"
plasma_p.ux = 0.0
plasma_p.uy = 0.0
plasma_p.uz = 0.0
+plasma_p.do_continuous_injection = 1
beam.charge = -q_e
beam.mass = m_e
diff --git a/Examples/Physics_applications/plasma_acceleration/inputs.3d.boost b/Examples/Physics_applications/plasma_acceleration/inputs.3d.boost
index 5f1ef1a2e..275cf6335 100644
--- a/Examples/Physics_applications/plasma_acceleration/inputs.3d.boost
+++ b/Examples/Physics_applications/plasma_acceleration/inputs.3d.boost
@@ -53,9 +53,6 @@ particles.nspecies = 5
particles.species_names = driver plasma_e plasma_p beam driverback
particles.use_fdtd_nci_corr = 1
particles.rigid_injected_species = driver beam
-warpx.do_plasma_injection = 1
-warpx.num_injected_species = 2
-warpx.injected_plasma_species = 1 2
driver.charge = -q_e
driver.mass = 1.e10
@@ -122,6 +119,7 @@ plasma_e.momentum_distribution_type = "constant"
plasma_e.ux = 0.0
plasma_e.uy = 0.0
plasma_e.uz = 0.0
+plasma_e.do_continuous_injection = 1
plasma_p.charge = q_e
plasma_p.mass = m_p
@@ -141,6 +139,7 @@ plasma_p.momentum_distribution_type = "constant"
plasma_p.ux = 0.0
plasma_p.uy = 0.0
plasma_p.uz = 0.0
+plasma_p.do_continuous_injection = 1
beam.charge = -q_e
beam.mass = m_e
diff --git a/Examples/Tests/Larmor/inputs b/Examples/Tests/Larmor/inputs
index 265a43383..729d315e9 100644
--- a/Examples/Tests/Larmor/inputs
+++ b/Examples/Tests/Larmor/inputs
@@ -79,7 +79,4 @@ interpolation.noz = 3
# Moving window
warpx.do_moving_window = 0
-# Particle Injection
-warpx.do_plasma_injection = 0
-
warpx.do_dive_cleaning = 1
diff --git a/Examples/Tests/Larmor/inputs.ml b/Examples/Tests/Larmor/inputs.ml
index 9adb655fb..9a0c9eb3d 100644
--- a/Examples/Tests/Larmor/inputs.ml
+++ b/Examples/Tests/Larmor/inputs.ml
@@ -79,7 +79,4 @@ interpolation.noz = 3
# Moving window
warpx.do_moving_window = 0
-# Particle Injection
-warpx.do_plasma_injection = 0
-
warpx.do_dive_cleaning = 1
diff --git a/Examples/Tests/PML/inputs2d b/Examples/Tests/PML/inputs2d
index ff64f68a8..c84cf0555 100644
--- a/Examples/Tests/PML/inputs2d
+++ b/Examples/Tests/PML/inputs2d
@@ -38,11 +38,6 @@ warpx.do_moving_window = 0
warpx.maxwell_fdtd_solver = yee
-# Particle Injection
-warpx.do_plasma_injection = 0
-warpx.num_injected_species = 0
-warpx.injected_plasma_species = 0
-
# Laser
lasers.nlasers = 1
lasers.names = laser1
diff --git a/Examples/Tests/laser_on_fine/inputs b/Examples/Tests/laser_on_fine/inputs
index a9bf8bf8c..8fc8876cb 100644
--- a/Examples/Tests/laser_on_fine/inputs
+++ b/Examples/Tests/laser_on_fine/inputs
@@ -57,11 +57,6 @@ warpx.do_moving_window = 0
warpx.moving_window_dir = z
warpx.moving_window_v = 1.0 # in units of the speed of light
-# Particle Injection
-warpx.do_plasma_injection = 0
-warpx.num_injected_species = 1
-warpx.injected_plasma_species = 0
-
# Laser
lasers.nlasers = 1
lasers.names = laser1
diff --git a/Examples/Tests/laser_on_fine/inputs.2d b/Examples/Tests/laser_on_fine/inputs.2d
index 34f174cf9..c4af2df56 100644
--- a/Examples/Tests/laser_on_fine/inputs.2d
+++ b/Examples/Tests/laser_on_fine/inputs.2d
@@ -57,11 +57,6 @@ warpx.do_moving_window = 0
warpx.moving_window_dir = z
warpx.moving_window_v = 1.0 # in units of the speed of light
-# Particle Injection
-warpx.do_plasma_injection = 0
-warpx.num_injected_species = 1
-warpx.injected_plasma_species = 0
-
# Laser
lasers.nlasers = 1
lasers.names = laser1
diff --git a/Examples/Tests/self_force_test/inputs b/Examples/Tests/self_force_test/inputs
index 9da7d5675..1e55c1174 100644
--- a/Examples/Tests/self_force_test/inputs
+++ b/Examples/Tests/self_force_test/inputs
@@ -69,6 +69,3 @@ interpolation.noz = 1
# Moving window
warpx.do_moving_window = 0
-
-# Particle Injection
-warpx.do_plasma_injection = 0
diff --git a/Examples/Tests/subcycling/inputs.2d b/Examples/Tests/subcycling/inputs.2d
index f1e2951c9..9790ee973 100644
--- a/Examples/Tests/subcycling/inputs.2d
+++ b/Examples/Tests/subcycling/inputs.2d
@@ -125,7 +125,7 @@ plasma_e.momentum_distribution_type = "constant"
plasma_e.ux = 0.0
plasma_e.uy = 0.0
plasma_e.uz = 0.0
-
+plasma_e.do_continuous_injection = 1
plasma_p.charge = q_e
plasma_p.mass = m_p
@@ -142,13 +142,9 @@ plasma_p.momentum_distribution_type = "constant"
plasma_p.ux = 0.0
plasma_p.uy = 0.0
plasma_p.uz = 0.0
+plasma_p.do_continuous_injection = 1
# Moving window
warpx.do_moving_window = 1
warpx.moving_window_dir = z
warpx.moving_window_v = 1. # in units of the speed of light
-
-# Particle Injection
-warpx.do_plasma_injection = 1
-warpx.num_injected_species = 2
-warpx.injected_plasma_species = 2 3
diff --git a/Python/pywarpx/picmi.py b/Python/pywarpx/picmi.py
index a5d9fba87..a439205a7 100644
--- a/Python/pywarpx/picmi.py
+++ b/Python/pywarpx/picmi.py
@@ -113,6 +113,9 @@ class GaussianBunchDistribution(picmistandard.PICMI_GaussianBunchDistribution):
species.uy = self.centroid_velocity[1]
species.uz = self.centroid_velocity[2]
+ if self.fill_in:
+ species.do_continuous_injection = 1
+
class UniformDistribution(picmistandard.PICMI_UniformDistribution):
def initialize_inputs(self, species_number, layout, species):
@@ -153,14 +156,6 @@ class UniformDistribution(picmistandard.PICMI_UniformDistribution):
species.uy = self.directed_velocity[1]
species.uz = self.directed_velocity[2]
- if self.fill_in:
- pywarpx.warpx.do_plasma_injection = 1
- if not hasattr(pywarpx.warpx, 'injected_plasma_species'):
- pywarpx.warpx.injected_plasma_species = []
-
- pywarpx.warpx.injected_plasma_species.append(species_number)
- pywarpx.warpx.num_injected_species = len(pywarpx.warpx.injected_plasma_species)
-
class AnalyticDistribution(picmistandard.PICMI_AnalyticDistribution):
def initialize_inputs(self, species_number, layout, species):
@@ -205,12 +200,7 @@ class AnalyticDistribution(picmistandard.PICMI_AnalyticDistribution):
species.uz = self.directed_velocity[2]
if self.fill_in:
- pywarpx.warpx.do_plasma_injection = 1
- if not hasattr(pywarpx.warpx, 'injected_plasma_species'):
- pywarpx.warpx.injected_plasma_species = []
-
- pywarpx.warpx.injected_plasma_species.append(species_number)
- pywarpx.warpx.num_injected_species = len(pywarpx.warpx.injected_plasma_species)
+ species.do_continuous_injection = 1
class ParticleListDistribution(picmistandard.PICMI_ParticleListDistribution):
diff --git a/Source/Laser/LaserParticleContainer.H b/Source/Laser/LaserParticleContainer.H
index 5dd94d0c7..516e368ab 100644
--- a/Source/Laser/LaserParticleContainer.H
+++ b/Source/Laser/LaserParticleContainer.H
@@ -84,11 +84,19 @@ private:
std::string field_function;
// laser particle domain
- amrex::RealBox prob_domain;
-
+ amrex::RealBox laser_injection_box;
+ // Theoretical position of the antenna. Used if do_continuous_injection=1.
+ // Track the position of the antenna until it enters the simulation domain.
+ amrex::Vector<amrex::Real> updated_position;
+
void ComputeSpacing (int lev, amrex::Real& Sx, amrex::Real& Sy) const;
void ComputeWeightMobility (amrex::Real Sx, amrex::Real Sy);
void InitData (int lev);
+ // Inject the laser antenna during the simulation, if it started
+ // outside of the simulation domain and enters it.
+ void ContinuousInjection(const amrex::RealBox& injection_box) override;
+ // Update position of the antenna
+ void UpdateContinuousInjectionPosition(amrex::Real dt) override;
};
#endif
diff --git a/Source/Laser/LaserParticleContainer.cpp b/Source/Laser/LaserParticleContainer.cpp
index 2b56c3cfd..8a2590e5e 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,16 +149,94 @@ LaserParticleContainer::LaserParticleContainer (AmrCore* amr_core, int ispecies,
u_Y = {0., 1., 0.};
#endif
- prob_domain = Geometry::ProbDomain();
+ laser_injection_box= Geometry::ProbDomain();
{
Vector<Real> lo, hi;
if (pp.queryarr("prob_lo", lo)) {
- prob_domain.setLo(lo);
+ laser_injection_box.setLo(lo);
}
if (pp.queryarr("prob_hi", hi)) {
- prob_domain.setHi(hi);
+ laser_injection_box.setHi(hi);
}
}
+
+ if (do_continuous_injection){
+ // If laser antenna initially outside of the box, store its theoretical
+ // position in z_antenna_th
+ updated_position = position;
+
+ // Sanity checks
+ int dir = WarpX::moving_window_dir;
+ std::vector<Real> windir(3, 0.0);
+#if (AMREX_SPACEDIM==2)
+ windir[2*dir] = 1.0;
+#else
+ windir[dir] = 1.0;
+#endif
+ AMREX_ALWAYS_ASSERT_WITH_MESSAGE(
+ (nvec[0]-windir[0]) + (nvec[1]-windir[1]) + (nvec[2]-windir[2])
+ < 1.e-12, "do_continous_injection for laser particle only works" +
+ " if moving window direction and laser propagation direction are the same");
+ 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 injection_box: a RealBox where particles should be injected.
+ */
+void
+LaserParticleContainer::ContinuousInjection (const RealBox& injection_box)
+{
+ // Input parameter injection_box contains small box where injection
+ // should occur.
+ // So far, LaserParticleContainer::laser_injection_box contains the
+ // outdated full problem domain at t=0.
+
+ // Convert updated_position to Real* to use RealBox::contains().
+#if (AMREX_SPACEDIM == 3)
+ const Real* p_pos = updated_position.dataPtr();
+#else
+ const Real p_pos[2] = {updated_position[0], updated_position[2]};
+#endif
+ if ( injection_box.contains(p_pos) ){
+ // Update laser_injection_box with current value
+ laser_injection_box = injection_box;
+ // Inject laser particles. LaserParticleContainer::InitData
+ // is called only once, when the antenna enters the simulation
+ // domain.
+ InitData();
+ }
+}
+
+/* \brief update position of the antenna if running in boosted frame.
+ * \param dt time step (level 0).
+ * The up-to-date antenna position is stored in updated_position.
+ */
+void
+LaserParticleContainer::UpdateContinuousInjectionPosition(Real dt)
+{
+ int dir = WarpX::moving_window_dir;
+ if (do_continuous_injection and (WarpX::gamma_boost > 1)){
+ // In boosted-frame simulations, the antenna has moved since the last
+ // call to this function, and injection position needs to be updated
+#if ( AMREX_SPACEDIM == 3 )
+ updated_position[dir] -= WarpX::beta_boost *
+ WarpX::boost_direction[dir] * PhysConst::c * dt;
+#elif ( AMREX_SPACEDIM == 2 )
+ // 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.
+ updated_position[2*dir] -= WarpX::beta_boost *
+ WarpX::boost_direction[2*dir] * PhysConst::c * dt;
+#endif
+ }
}
void
@@ -175,6 +254,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 with updated_position.
+ if (do_continuous_injection){
+ position = updated_position;
+ }
+
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 +296,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_injection_box.lo();
+ const Real* prob_hi = laser_injection_box.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 +358,7 @@ LaserParticleContainer::InitData (int lev)
#else
const Real x[2] = {pos[0], pos[2]};
#endif
- if (prob_domain.contains(x))
+ if (laser_injection_box.contains(x))
{
for (int k = 0; k<2; ++k) {
particle_x.push_back(pos[0]);
diff --git a/Source/Particles/MultiParticleContainer.H b/Source/Particles/MultiParticleContainer.H
index f3fd522a9..0c5e49c04 100644
--- a/Source/Particles/MultiParticleContainer.H
+++ b/Source/Particles/MultiParticleContainer.H
@@ -169,7 +169,15 @@ public:
const amrex::Real z_old, const amrex::Real z_new,
const amrex::Real t_boost, const amrex::Real t_lab, const amrex::Real dt,
amrex::Vector<WarpXParticleContainer::DiagnosticParticleData>& parts) const;
-
+
+ // Inject particles during the simulation (for particles entering the
+ // simulation domain after some iterations, due to flowing plasma and/or
+ // moving window).
+ void ContinuousInjection(const amrex::RealBox& injection_box) const;
+ // Update injection position for continuously-injected species.
+ void UpdateContinuousInjectionPosition(amrex::Real dt) const;
+ int doContinuousInjection() const;
+
//
// Parameters for the Cherenkov corrector in the FDTD solver.
// Both stencils are calculated ar runtime.
diff --git a/Source/Particles/MultiParticleContainer.cpp b/Source/Particles/MultiParticleContainer.cpp
index a4df1f83a..440906348 100644
--- a/Source/Particles/MultiParticleContainer.cpp
+++ b/Source/Particles/MultiParticleContainer.cpp
@@ -414,3 +414,48 @@ MultiParticleContainer
}
}
}
+
+/* \brief Continuous injection for particles initially outside of the domain.
+ * \param injection_box: Domain where new particles should be injected.
+ * Loop over all WarpXParticleContainer in MultiParticleContainer and
+ * calls virtual function ContinuousInjection.
+ */
+void
+MultiParticleContainer::ContinuousInjection(const RealBox& injection_box) const
+{
+ for (int i=0; i<nspecies+nlasers; i++){
+ auto& pc = allcontainers[i];
+ if (pc->do_continuous_injection){
+ pc->ContinuousInjection(injection_box);
+ }
+ }
+}
+
+/* \brief Update position of continuous injection parameters.
+ * \param dt: simulation time step (level 0)
+ * All classes inherited from WarpXParticleContainer do not have
+ * a position to update (PhysicalParticleContainer does not do anything).
+ */
+void
+MultiParticleContainer::UpdateContinuousInjectionPosition(Real dt) const
+{
+ for (int i=0; i<nspecies+nlasers; i++){
+ auto& pc = allcontainers[i];
+ if (pc->do_continuous_injection){
+ pc->UpdateContinuousInjectionPosition(dt);
+ }
+ }
+}
+
+int
+MultiParticleContainer::doContinuousInjection() const
+{
+ int warpx_do_continuous_injection = 0;
+ for (int i=0; i<nspecies+nlasers; i++){
+ auto& pc = allcontainers[i];
+ if (pc->do_continuous_injection){
+ warpx_do_continuous_injection = 1;
+ }
+ }
+ return warpx_do_continuous_injection;
+}
diff --git a/Source/Particles/PhysicalParticleContainer.H b/Source/Particles/PhysicalParticleContainer.H
index 362683879..4f365768b 100644
--- a/Source/Particles/PhysicalParticleContainer.H
+++ b/Source/Particles/PhysicalParticleContainer.H
@@ -101,8 +101,6 @@ public:
const amrex::Real t_lab, const amrex::Real dt,
DiagnosticParticles& diagnostic_particles) final;
- bool injected = false;
-
protected:
std::string species_name;
@@ -122,6 +120,9 @@ protected:
int GetRefineFac(const amrex::Real x, const amrex::Real y, const amrex::Real z);
std::unique_ptr<amrex::IArrayBox> m_refined_injection_mask = nullptr;
+ // Inject particles during the whole simulation
+ void ContinuousInjection(const amrex::RealBox& injection_box) override;
+
};
#endif
diff --git a/Source/Particles/PhysicalParticleContainer.cpp b/Source/Particles/PhysicalParticleContainer.cpp
index 17e6d98d9..2fa39d87d 100644
--- a/Source/Particles/PhysicalParticleContainer.cpp
+++ b/Source/Particles/PhysicalParticleContainer.cpp
@@ -24,7 +24,7 @@ NumParticlesToAdd(const Box& overlap_box, const RealBox& overlap_realbox,
for (IntVect iv = overlap_box.smallEnd(); iv <= overlap_box.bigEnd(); overlap_box.next(iv))
{
int fac;
- if (injected) {
+ if (do_continuous_injection) {
#if ( AMREX_SPACEDIM == 3 )
Real x = overlap_corner[0] + (iv[0] + 0.5)*dx[0];
Real y = overlap_corner[1] + (iv[1] + 0.5)*dx[1];
@@ -81,6 +81,7 @@ PhysicalParticleContainer::PhysicalParticleContainer (AmrCore* amr_core, int isp
pp.query("do_backward_propagation", do_backward_propagation);
pp.query("do_splitting", do_splitting);
pp.query("split_type", split_type);
+ pp.query("do_continuous_injection", do_continuous_injection);
}
PhysicalParticleContainer::PhysicalParticleContainer (AmrCore* amr_core)
@@ -361,7 +362,7 @@ PhysicalParticleContainer::AddPlasmaCPU (int lev, RealBox part_realbox)
for (IntVect iv = overlap_box.smallEnd(); iv <= overlap_box.bigEnd(); overlap_box.next(iv))
{
int fac;
- if (injected) {
+ if (do_continuous_injection) {
#if ( AMREX_SPACEDIM == 3 )
Real x = overlap_corner[0] + (iv[0] + 0.5)*dx[0];
Real y = overlap_corner[1] + (iv[1] + 0.5)*dx[1];
@@ -602,7 +603,7 @@ PhysicalParticleContainer::AddPlasmaGPU (int lev, RealBox part_realbox)
for (IntVect iv = overlap_box.smallEnd(); iv <= overlap_box.bigEnd(); overlap_box.next(iv))
{
int fac;
- if (injected) {
+ if (do_continuous_injection) {
#if ( AMREX_SPACEDIM == 3 )
Real x = overlap_corner[0] + (iv[0] + 0.5)*dx[0];
Real y = overlap_corner[1] + (iv[1] + 0.5)*dx[1];
@@ -2004,3 +2005,14 @@ int PhysicalParticleContainer::GetRefineFac(const Real x, const Real y, const Re
return ref_fac;
}
+
+/* \brief Inject particles during the simulation
+ * \param injection_box: domain where particles should be injected.
+ */
+void
+PhysicalParticleContainer::ContinuousInjection(const RealBox& injection_box)
+{
+ // Inject plasma on level 0. Paticles will be redistributed.
+ const int lev=0;
+ AddPlasma(lev, injection_box);
+}
diff --git a/Source/Particles/WarpXParticleContainer.H b/Source/Particles/WarpXParticleContainer.H
index 275554cd8..6fa02b824 100644
--- a/Source/Particles/WarpXParticleContainer.H
+++ b/Source/Particles/WarpXParticleContainer.H
@@ -183,7 +183,18 @@ public:
int thread_num,
int lev,
amrex::Real dt );
-
+
+ // If particles start outside of the domain, ContinuousInjection
+ // makes sure that they are initialized when they enter the domain, and
+ // NOT before. Virtual function, overriden by derived classes.
+ // Current status:
+ // PhysicalParticleContainer: implemented.
+ // LaserParticleContainer: implemented.
+ // RigidInjectedParticleContainer: not implemented.
+ virtual void ContinuousInjection(const amrex::RealBox& injection_box) {}
+ // Update optional sub-class-specific injection location.
+ virtual void UpdateContinuousInjectionPosition(amrex::Real dt) {}
+
///
/// This returns the total charge for all the particles in this ParticleContainer.
/// This is needed when solving Poisson's equation with periodic boundary conditions.
@@ -248,6 +259,12 @@ protected:
static int do_not_push;
+ // Whether to allow particles outside of the simulation domain to be
+ // initialized when they enter the domain.
+ // This is currently required because continuous injection does not
+ // support all features allowed by direct injection.
+ int do_continuous_injection = 0;
+
amrex::Vector<amrex::FArrayBox> local_rho;
amrex::Vector<amrex::FArrayBox> local_jx;
amrex::Vector<amrex::FArrayBox> local_jy;
@@ -258,6 +275,7 @@ protected:
private:
virtual void particlePostLocate(ParticleType& p, const amrex::ParticleLocData& pld,
const int lev) override;
+
};
#endif
diff --git a/Source/Utils/WarpXMovingWindow.cpp b/Source/Utils/WarpXMovingWindow.cpp
index 05e171f22..18d89951d 100644
--- a/Source/Utils/WarpXMovingWindow.cpp
+++ b/Source/Utils/WarpXMovingWindow.cpp
@@ -9,7 +9,7 @@ WarpX::UpdatePlasmaInjectionPosition (Real dt)
{
int dir = moving_window_dir;
// Continuously inject plasma in new cells (by default only on level 0)
- if (WarpX::do_plasma_injection and (WarpX::gamma_boost > 1)){
+ 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 *
@@ -33,7 +33,16 @@ WarpX::MoveWindow (bool move_j)
// and of the plasma injection
moving_window_x += moving_window_v * dt[0];
int dir = moving_window_dir;
+
+ // 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] );
+ }
// compute the number of cells to shift on the base level
Real new_lo[AMREX_SPACEDIM];
@@ -134,7 +143,7 @@ WarpX::MoveWindow (bool move_j)
}
// Continuously inject plasma in new cells (by default only on level 0)
- if (WarpX::do_plasma_injection) {
+ if (WarpX::warpx_do_continuous_injection) {
const int lev = 0;
@@ -162,15 +171,11 @@ WarpX::MoveWindow (bool move_j)
particleBox.setLo( dir, new_injection_position );
particleBox.setHi( dir, current_injection_position );
}
- // Perform the injection of new particles in particleBox
+
if (particleBox.ok() and (current_injection_position != new_injection_position)){
- for (int i = 0; i < num_injected_species; ++i) {
- int ispecies = injected_plasma_species[i];
- WarpXParticleContainer& pc = mypc->GetParticleContainer(ispecies);
- auto& ppc = dynamic_cast<PhysicalParticleContainer&>(pc);
- ppc.AddPlasma(lev, particleBox);
- }
- // Update the injection position
+ // Performs continuous injection of all WarpXParticleContainer
+ // in mypc.
+ mypc->ContinuousInjection(particleBox);
current_injection_position = new_injection_position;
}
}
diff --git a/Source/WarpX.H b/Source/WarpX.H
index 6cec8e5be..44e84033f 100644
--- a/Source/WarpX.H
+++ b/Source/WarpX.H
@@ -476,10 +476,10 @@ private:
amrex::Real current_injection_position = 0;
// Plasma injection parameters
- int do_plasma_injection = 0;
+ int warpx_do_continuous_injection = 0;
int num_injected_species = -1;
amrex::Vector<int> injected_plasma_species;
-
+
int do_electrostatic = 0;
int n_buffer = 4;
amrex::Real const_dt = 0.5e-11;
diff --git a/Source/WarpX.cpp b/Source/WarpX.cpp
index 47ead98df..a3a24897a 100644
--- a/Source/WarpX.cpp
+++ b/Source/WarpX.cpp
@@ -145,13 +145,14 @@ WarpX::WarpX ()
// Particle Container
mypc = std::unique_ptr<MultiParticleContainer> (new MultiParticleContainer(this));
-
- if (do_plasma_injection) {
- for (int i = 0; i < num_injected_species; ++i) {
- int ispecies = injected_plasma_species[i];
- WarpXParticleContainer& pc = mypc->GetParticleContainer(ispecies);
- auto& ppc = dynamic_cast<PhysicalParticleContainer&>(pc);
- ppc.injected = true;
+ warpx_do_continuous_injection = mypc->doContinuousInjection();
+ if (warpx_do_continuous_injection){
+ if (moving_window_v >= 0){
+ // Inject particles continuously from the right end of the box
+ current_injection_position = geom[0].ProbHi(moving_window_dir);
+ } else {
+ // Inject particles continuously from the left end of the box
+ current_injection_position = geom[0].ProbLo(moving_window_dir);
}
}
@@ -300,21 +301,6 @@ WarpX::ReadParameters ()
moving_window_v *= PhysConst::c;
}
- pp.query("do_plasma_injection", do_plasma_injection);
- if (do_plasma_injection) {
- pp.get("num_injected_species", num_injected_species);
- injected_plasma_species.resize(num_injected_species);
- pp.getarr("injected_plasma_species", injected_plasma_species,
- 0, num_injected_species);
- if (moving_window_v >= 0){
- // Inject particles continuously from the right end of the box
- current_injection_position = geom[0].ProbHi(moving_window_dir);
- } else {
- // Inject particles continuously from the left end of the box
- current_injection_position = geom[0].ProbLo(moving_window_dir);
- }
- }
-
pp.query("do_boosted_frame_diagnostic", do_boosted_frame_diagnostic);
if (do_boosted_frame_diagnostic) {
diff --git a/Tools/Visualization.ipynb b/Tools/Visualization.ipynb
index f5946a3de..5ac03f931 100644
--- a/Tools/Visualization.ipynb
+++ b/Tools/Visualization.ipynb
@@ -991,21 +991,21 @@
"metadata": {
"anaconda-cloud": {},
"kernelspec": {
- "display_name": "Python 2",
+ "display_name": "Python 3",
"language": "python",
- "name": "python2"
+ "name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
- "version": 2
+ "version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
- "pygments_lexer": "ipython2",
- "version": "2.7.14"
+ "pygments_lexer": "ipython3",
+ "version": "3.7.1"
},
"widgets": {
"state": {
diff --git a/Tools/performance_tests/automated_test_4_labdiags_2ppc b/Tools/performance_tests/automated_test_4_labdiags_2ppc
index 866bb68d1..f762c9b8c 100644
--- a/Tools/performance_tests/automated_test_4_labdiags_2ppc
+++ b/Tools/performance_tests/automated_test_4_labdiags_2ppc
@@ -45,11 +45,6 @@ warpx.do_boosted_frame_diagnostic = 1
warpx.num_snapshots_lab = 20
warpx.dt_snapshots_lab = 7.0e-14
-# Particle Injection
-warpx.do_plasma_injection = 1
-warpx.num_injected_species = 2
-warpx.injected_plasma_species = 0 1
-
# Species
particles.nspecies = 2
particles.species_names = electrons ions
@@ -66,6 +61,7 @@ electrons.num_particles_per_cell_each_dim = 1 1 1
electrons.profile = constant
electrons.density = 1.
electrons.momentum_distribution_type = "constant"
+electrons.do_continuous_injection = 1
ions.charge = q_e
ions.mass = m_p
@@ -79,6 +75,7 @@ ions.num_particles_per_cell_each_dim = 1 1 1
ions.profile = constant
ions.density = 1.
ions.momentum_distribution_type = "constant"
+ions.do_continuous_injection = 1
# Laser
warpx.use_laser = 1