diff --git a/Docs/source/usage/parameters.rst b/Docs/source/usage/parameters.rst index 17504a8065f..06b3edd0f2d 100644 --- a/Docs/source/usage/parameters.rst +++ b/Docs/source/usage/parameters.rst @@ -1824,7 +1824,9 @@ Particle push, charge and current deposition, field gathering Available options are: ``direct``, ``esirkepov``, and ``vay``. The default choice is ``esirkepov`` for FDTD maxwell solvers but ``direct`` for standard or Galilean PSATD solver (i.e. with ``algo.maxwell_solver = psatd``) and - for the hybrid-PIC solver (i.e. with ``algo.maxwell_solver = hybrid``). + for the hybrid-PIC solver (i.e. with ``algo.maxwell_solver = hybrid``) and for + diagnostics output with the electrostatic solvers (i.e., with + ``warpx.do_electrostatic = ...``). Note that ``vay`` is only available for ``algo.maxwell_solver = psatd``. 1. ``direct`` diff --git a/Docs/source/usage/python.rst b/Docs/source/usage/python.rst index 90015a85b9a..dd44c4098fd 100644 --- a/Docs/source/usage/python.rst +++ b/Docs/source/usage/python.rst @@ -14,7 +14,7 @@ defining the simulation time, field solver, registered species, etc. .. _usage-picmi-parameters: Classes ----------- +------- Simulation and grid setup ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -222,6 +222,8 @@ where ```` is the number of MPI ranks used, and ```` is the name of the script. +.. _usage-picmi-extend: + Extending a Simulation from Python ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -235,85 +237,101 @@ Places in the WarpX loop where callbacks are available include: ``afterinit``, ``beforecollisions``, ``aftercollisions``, ``beforeEsolve``, ``afterEsolve``, ``beforeInitEsolve``, ``afterInitEsolve``, ``beforedeposition``, ``afterdeposition``, ``beforestep``, ``afterstep``, ``afterdiagnostics``,``afterrestart`` and ``oncheckpointsignal``. -See the examples in *Examples/Tests/ParticleDataPython* for references on how to use +See the examples in ``Examples/Tests/ParticleDataPython`` for references on how to use ``callbacks``. There are several "hooks" available via the ``libwarpx`` shared library to access and manipulate simulation objects (particles, fields and memory buffers) as well as general properties (such as processor number). These "hooks" are accessible through the `Simulation.extension` object. -.. autofunction:: pywarpx.picmi.Simulation.extension.getNProcs +An important object is ``Simulation.extension.warpx``, which is available during simulation run. +This object is the Python equivalent to the central ``WarpX`` simulation class and provides access to +field ``MultiFab`` and ``ParticleContainer`` data. -.. autofunction:: pywarpx.picmi.Simulation.extension.getMyProc +.. function:: pywarpx.picmi.Simulation.extension.warpx.getistep -.. autofunction:: pywarpx.picmi.Simulation.extension.get_nattr +.. function:: pywarpx.picmi.Simulation.extension.warpx.gett_new -.. autofunction:: pywarpx.picmi.Simulation.extension.get_nattr_species +.. function:: pywarpx.picmi.Simulation.extension.warpx.evolve -.. autofunction:: pywarpx.picmi.Simulation.extension.getistep +.. autofunction:: pywarpx.picmi.Simulation.extension.finalize -.. autofunction:: pywarpx.picmi.Simulation.extension.gett_new +These and other classes are provided through `pyAMReX `__. +After the simulation is initialized, pyAMReX can be accessed via -.. autofunction:: pywarpx.picmi.Simulation.extension.evolve +.. code-block:: python -.. autofunction:: pywarpx.picmi.Simulation.extension.finalize + from pywarpx import picmi, libwarpx + + # ... simulation definition ... + + # equivalent to + # import amrex.space3d as amr + # for a 3D simulation + amr = libwarpx.amr # picks the right 1d, 2d or 3d variant + +.. function:: amr.ParallelDescriptor.NProcs() -.. autofunction:: pywarpx.picmi.Simulation.extension.getProbLo +.. function:: amr.ParallelDescriptor.MyProc() -.. autofunction:: pywarpx.picmi.Simulation.extension.getProbHi +.. function:: amr.ParallelDescriptor.IOProcessor() -.. autofunction:: pywarpx.picmi.Simulation.extension.getCellSize +.. function:: amr.ParallelDescriptor.IOProcessorNumber() Particles can be added to the simulation at specific positions and with specific attribute values: -.. autofunction:: pywarpx.picmi.Simulation.extension.add_particles +.. code-block:: python + + from pywarpx import particle_containers, picmi + + # ... + + electron_wrapper = particle_containers.ParticleContainerWrapper("electrons") + +.. autofunction:: pywarpx.particle_containers.ParticleContainerWrapper.add_particles Properties of the particles already in the simulation can be obtained with various functions. -.. autofunction:: pywarpx.picmi.Simulation.extension.get_particle_count +.. autofunction:: pywarpx.particle_containers.ParticleContainerWrapper.get_particle_count -.. autofunction:: pywarpx.picmi.Simulation.extension.get_particle_structs +.. autofunction:: pywarpx.particle_containers.ParticleContainerWrapper.get_particle_structs -.. autofunction:: pywarpx.picmi.Simulation.extension.get_particle_arrays +.. autofunction:: pywarpx.particle_containers.ParticleContainerWrapper.get_particle_arrays The ``get_particle_structs()`` and ``get_particle_arrays()`` functions are called by several utility functions of the form ``get_particle_{comp_name}`` where ``comp_name`` is one of ``x``, ``y``, ``z``, ``r``, ``theta``, ``id``, ``cpu``, ``weight``, ``ux``, ``uy`` or ``uz``. -The index of some specific component of the particle data can be obtained. - -.. autofunction:: pywarpx.picmi.Simulation.extension.get_particle_comp_index - New components can be added via Python. -.. autofunction:: pywarpx.picmi.Simulation.extension.add_real_comp +.. autofunction:: pywarpx.particle_containers.ParticleContainerWrapper.add_real_comp Various diagnostics are also accessible from Python. This includes getting the deposited or total charge density from a given species as well as accessing the scraped particle buffer. See the example in -*Examples/Tests/ParticleBoudaryScrape* for a reference on how to interact +``Examples/Tests/ParticleBoundaryScrape`` for a reference on how to interact with scraped particle data. -.. autofunction:: pywarpx.picmi.Simulation.extension.get_species_charge_sum +.. autofunction:: pywarpx.particle_containers.ParticleContainerWrapper.get_species_charge_sum -.. autofunction:: pywarpx.picmi.Simulation.extension.depositChargeDensity +.. autofunction:: pywarpx.particle_containers.ParticleContainerWrapper.deposit_charge_density -.. autofunction:: pywarpx.picmi.Simulation.extension.get_particle_boundary_buffer_size +.. autofunction:: pywarpx.particle_containers.ParticleBoundaryBufferWrapper.get_particle_boundary_buffer_size -.. autofunction:: pywarpx.picmi.Simulation.extension.get_particle_boundary_buffer_structs +.. autofunction:: pywarpx.particle_containers.ParticleBoundaryBufferWrapper.get_particle_boundary_buffer_structs -.. autofunction:: pywarpx.picmi.Simulation.extension.get_particle_boundary_buffer +.. autofunction:: pywarpx.particle_containers.ParticleBoundaryBufferWrapper.get_particle_boundary_buffer -.. autofunction:: pywarpx.picmi.Simulation.extension.clearParticleBoundaryBuffer +.. autofunction:: pywarpx.particle_containers.ParticleBoundaryBufferWrapper.clearParticleBoundaryBuffer The embedded boundary conditions can be modified when using the electrostatic solver. -.. autofunction:: pywarpx.picmi.Simulation.extension.set_potential_EB +.. function:: pywarpx.picmi.Simulation.extension.warpx.set_potential_on_eb -Using Python input as a preprocessor +Using Python Input as a Preprocessor ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ In this case, only the pure Python version needs to be installed, as described :ref:`here `. diff --git a/Examples/Physics_applications/capacitive_discharge/PICMI_inputs_1d.py b/Examples/Physics_applications/capacitive_discharge/PICMI_inputs_1d.py index dc9428229a4..0c6f9828543 100644 --- a/Examples/Physics_applications/capacitive_discharge/PICMI_inputs_1d.py +++ b/Examples/Physics_applications/capacitive_discharge/PICMI_inputs_1d.py @@ -11,7 +11,7 @@ from scipy.sparse import csc_matrix from scipy.sparse import linalg as sla -from pywarpx import callbacks, fields, particle_containers, picmi +from pywarpx import callbacks, fields, libwarpx, particle_containers, picmi constants = picmi.constants @@ -108,7 +108,7 @@ def solve(self): calculating phi from rho.""" left_voltage = 0.0 - t = self.sim_ext.gett_new() + t = self.sim.extension.warpx.gett_new(0) right_voltage = eval(self.right_voltage) # Construct b vector @@ -300,6 +300,7 @@ def setup_run(self): warpx_load_balance_intervals=self.max_steps//5000, verbose=self.test ) + self.solver.sim = self.sim self.sim.add_species( self.electrons, @@ -313,7 +314,6 @@ def setup_run(self): n_macroparticle_per_cell=[self.seed_nppc], grid=self.grid ) ) - self.solver.sim_ext = self.sim.extension ####################################################################### # Add diagnostics for the CI test to be happy # @@ -325,6 +325,7 @@ def setup_run(self): file_prefix = 'Python_background_mcc_1d_tridiag_plt' particle_diag = picmi.ParticleDiagnostic( + species=[self.electrons, self.ions], name='diag1', period=0, write_dir='.', @@ -343,7 +344,8 @@ def setup_run(self): def _get_rho_ions(self): # deposit the ion density in rho_fp - self.sim.extension.depositChargeDensity('he_ions', 0) + he_ions_wrapper = particle_containers.ParticleContainerWrapper('he_ions') + he_ions_wrapper.deposit_charge_density(level=0) rho_data = self.rho_wrapper[...] self.ion_density_array += rho_data / constants.q_e / self.diag_steps @@ -357,7 +359,7 @@ def run_sim(self): self.sim.step(self.diag_steps) - if self.sim.extension.getMyProc() == 0: + if libwarpx.amr.ParallelDescriptor.MyProc() == 0: np.save(f'ion_density_case_{self.n+1}.npy', self.ion_density_array) # query the particle z-coordinates if this is run during CI testing diff --git a/Examples/Physics_applications/capacitive_discharge/PICMI_inputs_2d.py b/Examples/Physics_applications/capacitive_discharge/PICMI_inputs_2d.py index fd66ba34a04..71e1070ef2f 100755 --- a/Examples/Physics_applications/capacitive_discharge/PICMI_inputs_2d.py +++ b/Examples/Physics_applications/capacitive_discharge/PICMI_inputs_2d.py @@ -177,7 +177,7 @@ def solve(self): calculating phi from rho.""" right_voltage = eval( self.right_voltage, - {'t':sim.extension.gett_new(0), 'sin':np.sin, 'pi':np.pi} + {'t': sim.extension.warpx.gett_new(0), 'sin': np.sin, 'pi': np.pi} ) left_voltage = 0.0 diff --git a/Examples/Tests/electrostatic_sphere_eb/PICMI_inputs_3d.py b/Examples/Tests/electrostatic_sphere_eb/PICMI_inputs_3d.py index 4da7feeff3a..55fbc87bd9e 100755 --- a/Examples/Tests/electrostatic_sphere_eb/PICMI_inputs_3d.py +++ b/Examples/Tests/electrostatic_sphere_eb/PICMI_inputs_3d.py @@ -119,6 +119,6 @@ sim.step(1) -sim.extension.set_potential_EB("2.") +sim.extension.warpx.set_potential_on_eb("2.") sim.step(1) diff --git a/Examples/Tests/langmuir/PICMI_inputs_rz.py b/Examples/Tests/langmuir/PICMI_inputs_rz.py index 018303a9611..8328aba5185 100755 --- a/Examples/Tests/langmuir/PICMI_inputs_rz.py +++ b/Examples/Tests/langmuir/PICMI_inputs_rz.py @@ -178,7 +178,7 @@ def calcEz( z, r, k0, w0, wp, t, epsilons) : return( Ez_array ) # Current time of the simulation -t0 = sim.extension.gett_new(0) +t0 = sim.extension.warpx.gett_new(0) # Get the raw field data. Note that these are the real and imaginary # parts of the fields for each azimuthal mode. diff --git a/Examples/Tests/ohm_solver_EM_modes/PICMI_inputs.py b/Examples/Tests/ohm_solver_EM_modes/PICMI_inputs.py index b51d291e478..51dbb53ab43 100644 --- a/Examples/Tests/ohm_solver_EM_modes/PICMI_inputs.py +++ b/Examples/Tests/ohm_solver_EM_modes/PICMI_inputs.py @@ -15,7 +15,7 @@ from mpi4py import MPI as mpi import numpy as np -from pywarpx import callbacks, fields, picmi +from pywarpx import callbacks, fields, libwarpx, picmi constants = picmi.constants @@ -25,8 +25,6 @@ warpx_serialize_initial_conditions=True, verbose=0 ) -# make a shorthand for simulation.extension since we use it a lot -sim_ext = simulation.extension class EMModes(object): @@ -318,7 +316,7 @@ def _record_average_fields(self): similar format as the reduced diagnostic so that the same analysis script can be used regardless of the simulation dimension. """ - step = sim_ext.getistep() - 1 + step = simulation.extension.warpx.getistep(lev=0) - 1 if step % self.diag_steps != 0: return @@ -327,7 +325,7 @@ def _record_average_fields(self): By_warpx = fields.BxWrapper()[...] Ez_warpx = fields.EzWrapper()[...] - if sim_ext.getMyProc() != 0: + if libwarpx.amr.ParallelDescriptor.MyProc() != 0: return t = step * self.dt diff --git a/Examples/Tests/ohm_solver_ion_Landau_damping/PICMI_inputs.py b/Examples/Tests/ohm_solver_ion_Landau_damping/PICMI_inputs.py index ecad73d381c..bd28f46b087 100644 --- a/Examples/Tests/ohm_solver_ion_Landau_damping/PICMI_inputs.py +++ b/Examples/Tests/ohm_solver_ion_Landau_damping/PICMI_inputs.py @@ -14,7 +14,7 @@ from mpi4py import MPI as mpi import numpy as np -from pywarpx import callbacks, fields, particle_containers, picmi +from pywarpx import callbacks, fields, libwarpx, particle_containers, picmi constants = picmi.constants @@ -22,9 +22,8 @@ simulation = picmi.Simulation( warpx_serialize_initial_conditions=True, - verbose=0) -# make a shorthand for simulation.extension since we use it a lot -sim_ext = simulation.extension + verbose=0 +) class IonLandauDamping(object): @@ -266,7 +265,8 @@ def setup_run(self): def text_diag(self): """Diagnostic function to print out timing data and particle numbers.""" - step = sim_ext.getistep(0) + step = simulation.extension.warpx.getistep(lev=0) - 1 + if step % (self.total_steps // 10) != 0: return @@ -290,7 +290,7 @@ def text_diag(self): "{step_rate:4.2f} steps/s" ) - if sim_ext.getMyProc() == 0: + if libwarpx.amr.ParallelDescriptor.MyProc() == 0: print(diag_string.format(**status_dict)) self.prev_time = time.time() @@ -301,14 +301,14 @@ def _record_average_fields(self): similar format as the reduced diagnostic so that the same analysis script can be used regardless of the simulation dimension. """ - step = sim_ext.getistep() - 1 + step = simulation.extension.warpx.getistep(lev=0) - 1 if step % self.diag_steps != 0: return Ez_warpx = fields.EzWrapper()[...] - if sim_ext.getMyProc() != 0: + if libwarpx.amr.ParallelDescriptor.MyProc() != 0: return t = step * self.dt diff --git a/Examples/Tests/ohm_solver_ion_beam_instability/PICMI_inputs.py b/Examples/Tests/ohm_solver_ion_beam_instability/PICMI_inputs.py index 21f55fb1166..79f268f6e3b 100644 --- a/Examples/Tests/ohm_solver_ion_beam_instability/PICMI_inputs.py +++ b/Examples/Tests/ohm_solver_ion_beam_instability/PICMI_inputs.py @@ -15,7 +15,7 @@ from mpi4py import MPI as mpi import numpy as np -from pywarpx import callbacks, fields, particle_containers, picmi +from pywarpx import callbacks, fields, libwarpx, particle_containers, picmi constants = picmi.constants @@ -23,9 +23,8 @@ simulation = picmi.Simulation( warpx_serialize_initial_conditions=True, - verbose=0) -# make a shorthand for simulation.extension since we use it a lot -sim_ext = simulation.extension + verbose=0 +) class HybridPICBeamInstability(object): @@ -336,13 +335,17 @@ def _create_data_arrays(self): self.start_time = self.prev_time self.prev_step = 0 - if sim_ext.getMyProc() == 0: + if libwarpx.amr.ParallelDescriptor.MyProc() == 0: # allocate arrays for storing energy values self.energy_vals = np.zeros((self.total_steps//self.diag_steps, 4)) def text_diag(self): """Diagnostic function to print out timing data and particle numbers.""" - step = sim_ext.getistep(0) + step = simulation.extension.warpx.getistep(lev=0) - 1 + + if not hasattr(self, "prev_time"): + self._create_data_arrays() + if step % (self.total_steps // 10) != 0: return @@ -368,7 +371,7 @@ def text_diag(self): "{step_rate:4.2f} steps/s" ) - if sim_ext.getMyProc() == 0: + if libwarpx.amr.ParallelDescriptor.MyProc() == 0: print(diag_string.format(**status_dict)) self.prev_time = time.time() @@ -377,8 +380,8 @@ def text_diag(self): def energy_diagnostic(self): """Diangostic to get the total, magnetic and kinetic energies in the simulation.""" + step = simulation.extension.warpx.getistep(lev=0) - 1 - step = sim_ext.getistep(0) if step % self.diag_steps != 1: return @@ -391,7 +394,7 @@ def energy_diagnostic(self): Ec_par, Ec_perp = self._get_kinetic_energy(self.ion_container_wrapper) Eb_par, Eb_perp = self._get_kinetic_energy(self.beam_ion_container_wrapper) - if sim_ext.getMyProc() != 0: + if libwarpx.amr.ParallelDescriptor.MyProc() != 0: return self.energy_vals[idx, 0] = Ec_par @@ -426,14 +429,14 @@ def _record_average_fields(self): similar format as the reduced diagnostic so that the same analysis script can be used regardless of the simulation dimension. """ - step = sim_ext.getistep() - 1 + step = simulation.extension.warpx.getistep(lev=0) - 1 if step % self.diag_steps != 0: return By_warpx = fields.BxWrapper()[...] - if sim_ext.getMyProc() != 0: + if libwarpx.amr.ParallelDescriptor.MyProc() != 0: return t = step * self.dt diff --git a/Examples/Tests/ohm_solver_magnetic_reconnection/PICMI_inputs.py b/Examples/Tests/ohm_solver_magnetic_reconnection/PICMI_inputs.py index bdeef96e0a6..143f1f3e82e 100644 --- a/Examples/Tests/ohm_solver_magnetic_reconnection/PICMI_inputs.py +++ b/Examples/Tests/ohm_solver_magnetic_reconnection/PICMI_inputs.py @@ -16,7 +16,7 @@ from mpi4py import MPI as mpi import numpy as np -from pywarpx import callbacks, fields, picmi +from pywarpx import callbacks, fields, libwarpx, picmi constants = picmi.constants @@ -24,9 +24,8 @@ simulation = picmi.Simulation( warpx_serialize_initial_conditions=True, - verbose=0) -# make a shorthand for simulation.extension since we use it a lot -sim_ext = simulation.extension + verbose=0 +) class ForceFreeSheetReconnection(object): @@ -306,7 +305,7 @@ def setup_run(self): def check_fields(self): - step = sim_ext.getistep() + step = simulation.extension.warpx.getistep(lev=0) - 1 if not (step == 1 or step%self.diag_steps == 0): return @@ -318,7 +317,7 @@ def check_fields(self): By = fields.ByFPWrapper(include_ghosts=False)[...] / self.B0 Bz = fields.BzFPWrapper(include_ghosts=False)[...] / self.B0 - if sim_ext.getMyProc() != 0: + if libwarpx.amr.ParallelDescriptor.MyProc() != 0: return # save the fields to file diff --git a/Examples/Tests/particle_boundary_scrape/PICMI_inputs_scrape.py b/Examples/Tests/particle_boundary_scrape/PICMI_inputs_scrape.py index 618b01b1c46..9871bdac655 100755 --- a/Examples/Tests/particle_boundary_scrape/PICMI_inputs_scrape.py +++ b/Examples/Tests/particle_boundary_scrape/PICMI_inputs_scrape.py @@ -5,7 +5,7 @@ import numpy as np -from pywarpx import particle_containers, picmi +from pywarpx import libwarpx, particle_containers, picmi ########################## # numerics parameters @@ -125,7 +125,7 @@ from mpi4py import MPI as mpi -my_id = sim.extension.getMyProc() +my_id = libwarpx.amr.ParallelDescriptor.MyProc() particle_buffer = particle_containers.ParticleBoundaryBufferWrapper() diff --git a/Examples/Tests/particle_data_python/PICMI_inputs_2d.py b/Examples/Tests/particle_data_python/PICMI_inputs_2d.py index 877824715cb..a4b7d9e134e 100755 --- a/Examples/Tests/particle_data_python/PICMI_inputs_2d.py +++ b/Examples/Tests/particle_data_python/PICMI_inputs_2d.py @@ -4,7 +4,7 @@ import numpy as np -from pywarpx import callbacks, particle_containers, picmi +from pywarpx import callbacks, libwarpx, particle_containers, picmi # Create the parser and add the argument parser = argparse.ArgumentParser() @@ -119,7 +119,7 @@ elec_wrapper = particle_containers.ParticleContainerWrapper('electrons') elec_wrapper.add_real_comp('newPid') -my_id = sim.extension.getMyProc() +my_id = libwarpx.amr.ParallelDescriptor.MyProc() def add_particles(): diff --git a/Examples/Tests/pass_mpi_communicator/PICMI_inputs_2d.py b/Examples/Tests/pass_mpi_communicator/PICMI_inputs_2d.py index b420b71c3aa..66f259da2ef 100755 --- a/Examples/Tests/pass_mpi_communicator/PICMI_inputs_2d.py +++ b/Examples/Tests/pass_mpi_communicator/PICMI_inputs_2d.py @@ -143,4 +143,4 @@ # verify that amrex proc ranks are offset by -1 from # world comm proc ranks -# assert sim.extension.getMyProc() == rank - 1 +# assert libwarpx.amr.ParallelDescriptor.MyProc() == rank - 1 diff --git a/Examples/Tests/restart/PICMI_inputs_id_cpu_read.py b/Examples/Tests/restart/PICMI_inputs_id_cpu_read.py index 8835e341fc7..d400924a378 100755 --- a/Examples/Tests/restart/PICMI_inputs_id_cpu_read.py +++ b/Examples/Tests/restart/PICMI_inputs_id_cpu_read.py @@ -150,7 +150,7 @@ def add_particles(): # simulation run ########################## -step_number = sim.extension.getistep(0) +step_number = sim.extension.warpx.getistep(lev=0) sim.step(max_steps) ############################################### diff --git a/Examples/Tests/restart/PICMI_inputs_runtime_component_analyze.py b/Examples/Tests/restart/PICMI_inputs_runtime_component_analyze.py index deb3c6060f6..706dedb6959 100755 --- a/Examples/Tests/restart/PICMI_inputs_runtime_component_analyze.py +++ b/Examples/Tests/restart/PICMI_inputs_runtime_component_analyze.py @@ -150,7 +150,7 @@ def add_particles(): # simulation run ########################## -step_number = sim.extension.getistep(0) +step_number = sim.extension.warpx.getistep(lev=0) sim.step(max_steps - 1 - step_number) ########################## diff --git a/Examples/Tests/restart_eb/PICMI_inputs_restart_eb.py b/Examples/Tests/restart_eb/PICMI_inputs_restart_eb.py index 7ef8e26d1d6..a4727053334 100755 --- a/Examples/Tests/restart_eb/PICMI_inputs_restart_eb.py +++ b/Examples/Tests/restart_eb/PICMI_inputs_restart_eb.py @@ -132,5 +132,5 @@ # simulation run ########################## -step_number = sim.extension.getistep(0) +step_number = sim.extension.warpx.getistep(lev=0) sim.step(max_steps - step_number) diff --git a/Python/pywarpx/WarpX.py b/Python/pywarpx/WarpX.py index cfa55641427..3fa59285f26 100644 --- a/Python/pywarpx/WarpX.py +++ b/Python/pywarpx/WarpX.py @@ -98,7 +98,7 @@ def init(self, mpi_comm=None, **kw): libwarpx.initialize(argv, mpi_comm=mpi_comm) def evolve(self, nsteps=-1): - libwarpx.evolve(nsteps) + libwarpx.warpx.evolve(nsteps) def finalize(self, finalize_mpi=1): libwarpx.finalize(finalize_mpi) diff --git a/Python/pywarpx/_libwarpx.py b/Python/pywarpx/_libwarpx.py index bf3ec0ded1a..fa2044d4240 100755 --- a/Python/pywarpx/_libwarpx.py +++ b/Python/pywarpx/_libwarpx.py @@ -14,7 +14,6 @@ import atexit import os -import sys import numpy as np @@ -114,46 +113,6 @@ def load_library(self): self.__version__ = self.libwarpx_so.__version__ - def getNProcs(self): - ''' - - Get the number of processors - - ''' - return self.libwarpx_so.getNProcs() - - def getMyProc(self): - ''' - - Get the number of the processor - - ''' - return self.libwarpx_so.getMyProc() - - def get_nattr(self): - ''' - - Get the number of extra particle attributes. - - ''' - # --- The -3 is because the comps include the velocites - return self.libwarpx_so.warpx_nComps() - 3 - - def get_nattr_species(self, species_name): - ''' - Get the number of real attributes for the given species. - - Parameters - ---------- - - species_name: str - Name of the species - ''' - warpx = self.libwarpx_so.get_instance() - mpc = warpx.multi_particle_container() - pc = mpc.get_particle_container_from_name(species_name) - return pc.num_real_comps() - def amrex_init(self, argv, mpi_comm=None): if mpi_comm is None: # or MPI is None: self.libwarpx_so.amrex_init(argv) @@ -162,9 +121,7 @@ def amrex_init(self, argv, mpi_comm=None): def initialize(self, argv=None, mpi_comm=None): ''' - Initialize WarpX and AMReX. Must be called before doing anything else. - ''' if argv is None: argv = sys.argv @@ -180,9 +137,7 @@ def initialize(self, argv=None, mpi_comm=None): def finalize(self, finalize_mpi=1): ''' - Call finalize for WarpX and AMReX. Registered to run at program exit. - ''' # TODO: simplify, part of pyAMReX already if self.initialized: @@ -194,193 +149,4 @@ def finalize(self, finalize_mpi=1): from pywarpx import callbacks callbacks.clear_all() - def getistep(self, level=0): - ''' - Get the current time step number for the specified level - - Parameter - --------- - - level : int - The refinement level to reference - ''' - - return self.warpx.getistep(level) - - def gett_new(self, level=0): - ''' - - Get the next time for the specified level. - - Parameters - ---------- - - level : int - The refinement level to reference - ''' - - return self.warpx.gett_new(level) - - def evolve(self, num_steps=-1): - ''' - Evolve the simulation for num_steps steps. If num_steps=-1, - the simulation will be run until the end as specified in the - inputs file. - - Parameters - ---------- - - num_steps: int - The number of steps to take - ''' - - self.warpx.evolve(num_steps) - - def getProbLo(self, direction, level=0): - ''' - Get the values of the lower domain boundary. - - Parameters - ---------- - - direction : int - Direction of interest - ''' - - assert 0 <= direction < self.dim, 'Inappropriate direction specified' - return self.warpx.Geom(level).ProbLo(direction) - - def getProbHi(self, direction, level=0): - ''' - Get the values of the upper domain boundary. - - Parameters - ---------- - - direction : int - Direction of interest - ''' - - assert 0 <= direction < self.dim, 'Inappropriate direction specified' - return self.warpx.Geom(level).ProbHi(direction) - - def getCellSize(self, direction, level=0): - ''' - Get the cell size in the given direction and on the given level. - - Parameters - ---------- - - direction : int - Direction of interest - - level : int - The refinement level to reference - ''' - - assert 0 <= direction < 3, 'Inappropriate direction specified' - assert 0 <= level and level <= self.libwarpx_so.warpx_finestLevel(), 'Inappropriate level specified' - return self.libwarpx_so.warpx_getCellSize(direction, level) - - #def get_sigma(self, direction): - # ''' - # - # Return the 'sigma' PML coefficients for the electric field - # in a given direction. - # - # ''' - # - # size = ctypes.c_int(0) - # data = self.libwarpx_so.warpx_getPMLSigma(direction, ctypes.byref(size)) - # arr = np.ctypeslib.as_array(data, (size.value,)) - # arr.setflags(write=1) - # return arr - # - # - #def get_sigma_star(self, direction): - # ''' - # - # Return the 'sigma*' PML coefficients for the magnetic field - # in the given direction. - # - # ''' - # - # size = ctypes.c_int(0) - # data = self.libwarpx_so.warpx_getPMLSigmaStar(direction, ctypes.byref(size)) - # arr = np.ctypeslib.as_array(data, (size.value,)) - # arr.setflags(write=1) - # return arr - # - # - #def compute_pml_factors(self, lev, dt): - # ''' - # - # This recomputes the PML coefficients for a given level, using the - # time step dt. This needs to be called after modifying the coefficients - # from Python. - # - # ''' - # - # self.libwarpx_so.warpx_ComputePMLFactors(lev, dt) - - - - def depositChargeDensity(self, species_name, level, clear_rho=True, sync_rho=True): - ''' - Deposit the specified species' charge density in rho_fp in order to - access that data via pywarpx.fields.RhoFPWrapper(). - - Parameters - ---------- - - species_name : str - The species name that will be deposited. - - level : int - Which AMR level to retrieve scraped particle data from. - - clear_rho : bool - If True, zero out rho_fp before deposition. - - sync_rho : bool - If True, perform MPI exchange and properly set boundary cells for rho_fp. - ''' - rho_fp = self.warpx.multifab(f'rho_fp[level={level}]') - - if rho_fp is None: - raise RuntimeError("Multifab `rho_fp` is not allocated.") - # ablastr::warn_manager::WMRecordWarning( - # "WarpXWrappers", "rho_fp is not allocated", - # ablastr::warn_manager::WarnPriority::low - # ); - # return - - if clear_rho: - rho_fp.set_val(0.0) - - # deposit the charge density from the desired species - mypc = self.warpx.multi_particle_container() - myspc = mypc.get_particle_container_from_name(species_name) - myspc.deposit_charge(rho_fp, level) - - if self.geometry_dim == 'rz': - self.warpx.apply_inverse_volume_scaling_to_charge_density(rho_fp, level) - - if sync_rho: - self.warpx.sync_rho() - - - def set_potential_EB(self, potential): - """ - Set the expression string for the embedded boundary potential - - Parameters - ---------- - - potential : str - The expression string - """ - self.warpx.set_potential_on_eb(potential) - - libwarpx = LibWarpX() diff --git a/Python/pywarpx/particle_containers.py b/Python/pywarpx/particle_containers.py index aedb36c38a6..c77781f6544 100644 --- a/Python/pywarpx/particle_containers.py +++ b/Python/pywarpx/particle_containers.py @@ -29,6 +29,7 @@ def __init__(self, species_name): mypc = libwarpx.warpx.multi_particle_container() self.particle_container = mypc.get_particle_container_from_name(self.name) + def add_particles(self, x=None, y=None, z=None, ux=None, uy=None, uz=None, w=None, unique_particles=True, **kwargs): ''' @@ -149,6 +150,7 @@ def add_particles(self, x=None, y=None, z=None, ux=None, uy=None, nattr, attr, nattr_int, attr_int, unique_particles ) + def get_particle_count(self, local=False): ''' Get the number of particles of this species in the simulation. @@ -169,6 +171,7 @@ def get_particle_count(self, local=False): return self.particle_container.total_number_of_particles(True, local) nps = property(get_particle_count) + def add_real_comp(self, pid_name, comm=True): ''' Add a real component to the particle data array. @@ -184,6 +187,7 @@ def add_real_comp(self, pid_name, comm=True): ''' self.particle_container.add_real_comp(pid_name, comm) + def get_particle_structs(self, level, copy_to_host=False): ''' This returns a list of numpy or cupy arrays containing the particle struct data @@ -233,6 +237,7 @@ def get_particle_structs(self, level, copy_to_host=False): particle_data.append(aos_arr) return particle_data + def get_particle_arrays(self, comp_name, level, copy_to_host=False): ''' This returns a list of numpy or cupy arrays containing the particle array data @@ -278,6 +283,7 @@ def get_particle_arrays(self, comp_name, level, copy_to_host=False): return data_array + def get_particle_id(self, level=0, copy_to_host=False): ''' Return a list of numpy or cupy arrays containing the particle 'id' @@ -302,6 +308,7 @@ def get_particle_id(self, level=0, copy_to_host=False): structs = self.get_particle_structs(level, copy_to_host) return [libwarpx.amr.unpack_ids(struct['cpuid']) for struct in structs] + def get_particle_cpu(self, level=0, copy_to_host=False): ''' Return a list of numpy or cupy arrays containing the particle 'cpu' @@ -326,6 +333,7 @@ def get_particle_cpu(self, level=0, copy_to_host=False): structs = self.get_particle_structs(level, copy_to_host) return [libwarpx.amr.unpack_cpus(struct['cpuid']) for struct in structs] + def get_particle_x(self, level=0, copy_to_host=False): ''' Return a list of numpy or cupy arrays containing the particle 'x' @@ -363,6 +371,7 @@ def get_particle_x(self, level=0, copy_to_host=False): raise Exception('get_particle_x: There is no x coordinate with 1D Cartesian') xp = property(get_particle_x) + def get_particle_y(self, level=0, copy_to_host=False): ''' Return a list of numpy or cupy arrays containing the particle 'y' @@ -400,6 +409,7 @@ def get_particle_y(self, level=0, copy_to_host=False): raise Exception('get_particle_y: There is no y coordinate with 1D or 2D Cartesian') yp = property(get_particle_y) + def get_particle_r(self, level=0, copy_to_host=False): ''' Return a list of numpy or cupy arrays containing the particle 'r' @@ -432,6 +442,7 @@ def get_particle_r(self, level=0, copy_to_host=False): raise Exception('get_particle_r: There is no r coordinate with 1D or 2D Cartesian') rp = property(get_particle_r) + def get_particle_theta(self, level=0, copy_to_host=False): ''' Return a list of numpy or cupy arrays containing the particle @@ -464,6 +475,7 @@ def get_particle_theta(self, level=0, copy_to_host=False): raise Exception('get_particle_theta: There is no theta coordinate with 1D or 2D Cartesian') thetap = property(get_particle_theta) + def get_particle_z(self, level=0, copy_to_host=False): ''' Return a list of numpy or cupy arrays containing the particle 'z' @@ -494,6 +506,7 @@ def get_particle_z(self, level=0, copy_to_host=False): return [struct['x'] for struct in structs] zp = property(get_particle_z) + def get_particle_weight(self, level=0, copy_to_host=False): ''' Return a list of numpy or cupy arrays containing the particle @@ -518,6 +531,7 @@ def get_particle_weight(self, level=0, copy_to_host=False): return self.get_particle_arrays('w', level, copy_to_host=copy_to_host) wp = property(get_particle_weight) + def get_particle_ux(self, level=0, copy_to_host=False): ''' Return a list of numpy or cupy arrays containing the particle @@ -542,6 +556,7 @@ def get_particle_ux(self, level=0, copy_to_host=False): return self.get_particle_arrays('ux', level, copy_to_host=copy_to_host) uxp = property(get_particle_ux) + def get_particle_uy(self, level=0, copy_to_host=False): ''' Return a list of numpy or cupy arrays containing the particle @@ -566,6 +581,7 @@ def get_particle_uy(self, level=0, copy_to_host=False): return self.get_particle_arrays('uy', level, copy_to_host=copy_to_host) uyp = property(get_particle_uy) + def get_particle_uz(self, level=0, copy_to_host=False): ''' Return a list of numpy or cupy arrays containing the particle @@ -591,6 +607,7 @@ def get_particle_uz(self, level=0, copy_to_host=False): return self.get_particle_arrays('uz', level, copy_to_host=copy_to_host) uzp = property(get_particle_uz) + def get_species_charge_sum(self, local=False): ''' Returns the total charge in the simulation due to the given species. @@ -606,31 +623,70 @@ def get_species_charge_sum(self, local=False): ctypes.c_char_p(species_name.encode('utf-8')), local ) + def getex(self): raise NotImplementedError('Particle E fields not supported') ex = property(getex) + def getey(self): raise NotImplementedError('Particle E fields not supported') ey = property(getey) + def getez(self): raise NotImplementedError('Particle E fields not supported') ez = property(getez) + def getbx(self): raise NotImplementedError('Particle B fields not supported') bx = property(getbx) + def getby(self): raise NotImplementedError('Particle B fields not supported') by = property(getby) + def getbz(self): raise NotImplementedError('Particle B fields not supported') bz = property(getbz) + def deposit_charge_density(self, level, clear_rho=True, sync_rho=True): + ''' + Deposit this species' charge density in rho_fp in order to + access that data via pywarpx.fields.RhoFPWrapper(). + Parameters + ---------- + species_name : str + The species name that will be deposited. + level : int + Which AMR level to retrieve scraped particle data from. + clear_rho : bool + If True, zero out rho_fp before deposition. + sync_rho : bool + If True, perform MPI exchange and properly set boundary cells for rho_fp. + ''' + rho_fp = libwarpx.warpx.multifab(f'rho_fp[level={level}]') + + if rho_fp is None: + raise RuntimeError("Multifab `rho_fp` is not allocated.") + + if clear_rho: + rho_fp.set_val(0.0) + + # deposit the charge density from the desired species + self.particle_container.deposit_charge(rho_fp, level) + + if libwarpx.geometry_dim == 'rz': + libwarpx.warpx.apply_inverse_volume_scaling_to_charge_density(rho_fp, level) + + if sync_rho: + libwarpx.warpx.sync_rho() + + class ParticleBoundaryBufferWrapper(object): """Wrapper around particle boundary buffer containers. This provides a convenient way to query data in the particle boundary @@ -640,6 +696,7 @@ class ParticleBoundaryBufferWrapper(object): def __init__(self): self.particle_buffer = libwarpx.warpx.get_particle_boundary_buffer() + def get_particle_boundary_buffer_size(self, species_name, boundary, local=False): ''' This returns the number of particles that have been scraped so far in the simulation @@ -664,6 +721,7 @@ def get_particle_boundary_buffer_size(self, species_name, boundary, local=False) local=local ) + def get_particle_boundary_buffer_structs( self, species_name, boundary, level, copy_to_host=False ): @@ -727,6 +785,7 @@ def get_particle_boundary_buffer_structs( particle_data.append(aos_arr) return particle_data + def get_particle_boundary_buffer(self, species_name, boundary, comp_name, level): ''' This returns a list of numpy or cupy arrays containing the particle array data @@ -773,6 +832,7 @@ def get_particle_boundary_buffer(self, species_name, boundary, comp_name, level) data_array.append(xp.array(soa.GetRealData(comp_idx), copy=False)) return data_array + def clear_buffer(self): ''' @@ -781,6 +841,7 @@ def clear_buffer(self): ''' self.particle_buffer.clear_particles() + def _get_boundary_number(self, boundary): ''' diff --git a/Regression/Checksum/benchmarks_json/Python_prev_positions.json b/Regression/Checksum/benchmarks_json/Python_prev_positions.json index e6e39d2272b..55c886775d5 100644 --- a/Regression/Checksum/benchmarks_json/Python_prev_positions.json +++ b/Regression/Checksum/benchmarks_json/Python_prev_positions.json @@ -6,9 +6,9 @@ "Ex": 3710588.849989976, "Ey": 0.0, "Ez": 646727.8074440088, - "jx": 4745.078379617619, - "jy": 368.4331779923921, - "jz": 632.1508106460103 + "jx": 15259.034603501308, + "jy": 650.139263398662, + "jz": 943.0244062246846 }, "electrons": { "particle_momentum_x": 8.78764082600202e-23, diff --git a/Regression/Checksum/benchmarks_json/hard_edged_quadrupoles.json b/Regression/Checksum/benchmarks_json/hard_edged_quadrupoles.json index 80a2dc87964..f8186748f2c 100644 --- a/Regression/Checksum/benchmarks_json/hard_edged_quadrupoles.json +++ b/Regression/Checksum/benchmarks_json/hard_edged_quadrupoles.json @@ -6,9 +6,9 @@ "Ex": 9.882421146615367e-06, "Ey": 1.0440261046714249e-05, "Ez": 1.003739697324731e-05, - "jx": 2.9148662809570633e-10, - "jy": 8.46582291468749e-19, - "jz": 3.823492756863969e-08 + "jx": 2.914866280957325e-10, + "jy": 8.46605718473121e-19, + "jz": 3.82349275686397e-08 }, "electron": { "particle_momentum_x": 2.0819392991319055e-25, diff --git a/Regression/Checksum/benchmarks_json/hard_edged_quadrupoles_moving.json b/Regression/Checksum/benchmarks_json/hard_edged_quadrupoles_moving.json index 813eead7374..05b398e4292 100644 --- a/Regression/Checksum/benchmarks_json/hard_edged_quadrupoles_moving.json +++ b/Regression/Checksum/benchmarks_json/hard_edged_quadrupoles_moving.json @@ -6,9 +6,9 @@ "Ex": 6.0282565190090465e-05, "Ey": 6.38479659567398e-05, "Ez": 7.880459213065183e-05, - "jx": 1.1659465170956616e-09, - "jy": 2.6115239381823616e-17, - "jz": 1.5293971084510288e-07 + "jx": 1.1659465170956563e-09, + "jy": 1.3057688751494639e-17, + "jz": 1.5293971084510282e-07 }, "electron": { "particle_momentum_x": 2.0819392998019267e-25, diff --git a/Source/Python/CMakeLists.txt b/Source/Python/CMakeLists.txt index 4b4be199c31..d976e3d2c05 100644 --- a/Source/Python/CMakeLists.txt +++ b/Source/Python/CMakeLists.txt @@ -8,9 +8,6 @@ foreach(D IN LISTS WarpX_DIMS) PRIVATE # callback hooks WarpX_py.cpp - - # legacy C wrapper APIs - WarpXWrappers.cpp ) if(WarpX_PYTHON) target_sources(pyWarpX_${SD} diff --git a/Source/Python/Make.package b/Source/Python/Make.package index 9f421456b40..f107fbbfaaa 100644 --- a/Source/Python/Make.package +++ b/Source/Python/Make.package @@ -1,4 +1,3 @@ -CEXE_sources += WarpXWrappers.cpp CEXE_sources += WarpX_py.cpp VPATH_LOCATIONS += $(WARPX_HOME)/Source/Python diff --git a/Source/Python/WarpXWrappers.H b/Source/Python/WarpXWrappers.H deleted file mode 100644 index d2d57445880..00000000000 --- a/Source/Python/WarpXWrappers.H +++ /dev/null @@ -1,80 +0,0 @@ -/* Copyright 2019 Andrew Myers, David Grote, Maxence Thevenet - * Remi Lehe, Weiqun Zhang - * - * This file is part of WarpX. - * - * This file is a legacy file and will be removed soon. - * Please do NOT add new bindings here! Please see the other files - * in this directory for the new pybind11-based bindings! - * - * License: BSD-3-Clause-LBNL - */ -#ifndef WARPX_WRAPPERS_H_ -#define WARPX_WRAPPERS_H_ - -#include "Particles/WarpXParticleContainer.H" -#include "Evolve/WarpXDtType.H" -#include -#include - -#ifdef AMREX_USE_MPI -# include -#endif - -#ifdef __cplusplus -extern "C" { -#endif - - int warpx_Real_size(); - int warpx_ParticleReal_size(); - - int warpx_nSpecies(); - - bool warpx_use_fdtd_nci_corr(); - - int warpx_galerkin_interpolation(); - - void amrex_init_with_inited_mpi (int argc, char* argv[], MPI_Comm mpicomm); - - typedef void(*WARPX_CALLBACK_PY_FUNC_0)(); - - void warpx_ConvertLabParamsToBoost(); - - void warpx_ReadBCParams(); - - void warpx_CheckGriddingForRZSpectral(); - - amrex::Real warpx_getCellSize(int dir, int lev); - - amrex::Real warpx_sumParticleCharge(const char* char_species_name, bool local); - - void warpx_ComputeDt (); - void warpx_MoveWindow (int step, bool move_j); - - void warpx_EvolveE (amrex::Real dt); - void warpx_EvolveB (amrex::Real dt, DtType a_dt_type); - void warpx_FillBoundaryE (); - void warpx_FillBoundaryB (); - void warpx_SyncCurrent ( - const amrex::Vector,3>>& J_fp, - const amrex::Vector,3>>& J_cp, - const amrex::Vector,3>>& J_buffer); - void warpx_UpdateAuxilaryData (); - void warpx_PushParticlesandDepose (amrex::Real cur_time); - - void warpx_setistep (int lev, int ii); - void warpx_sett_new (int lev, amrex::Real time); - amrex::Real warpx_getdt (int lev); - - int warpx_maxStep (); - amrex::Real warpx_stopTime (); - - int warpx_finestLevel (); - - void mypc_Redistribute (); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/Source/Python/WarpXWrappers.cpp b/Source/Python/WarpXWrappers.cpp deleted file mode 100644 index 44820dd1f53..00000000000 --- a/Source/Python/WarpXWrappers.cpp +++ /dev/null @@ -1,172 +0,0 @@ -/* Copyright 2019 Andrew Myers, Axel Huebl, David Grote - * Luca Fedeli, Maxence Thevenet, Remi Lehe - * Weiqun Zhang - * - * This file is part of WarpX. - * - * License: BSD-3-Clause-LBNL - */ -#include "BoundaryConditions/PML.H" -#include "FieldSolver/FiniteDifferenceSolver/HybridPICModel/HybridPICModel.H" -#include "Initialization/WarpXAMReXInit.H" -#include "Particles/MultiParticleContainer.H" -#include "Particles/ParticleBoundaryBuffer.H" -#include "Particles/WarpXParticleContainer.H" -#include "Utils/WarpXProfilerWrapper.H" -#include "Utils/WarpXUtil.H" -#include "WarpX.H" -#include "WarpXWrappers.H" -#include "WarpX_py.H" - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - - int warpx_Real_size() - { - return (int)sizeof(amrex::Real); - } - - int warpx_ParticleReal_size() - { - return (int)sizeof(amrex::ParticleReal); - } - - int warpx_nSpecies() - { - const auto & mypc = WarpX::GetInstance().GetPartContainer(); - return mypc.nSpecies(); - } - - bool warpx_use_fdtd_nci_corr() - { - return WarpX::use_fdtd_nci_corr; - } - - int warpx_galerkin_interpolation() - { - return WarpX::galerkin_interpolation; - } - - void amrex_init_with_inited_mpi (int argc, char* argv[], MPI_Comm /* mpicomm */) - { - warpx::initialization::amrex_init(argc, argv, true); - } - - void warpx_ConvertLabParamsToBoost() - { - ConvertLabParamsToBoost(); - } - - void warpx_ReadBCParams() - { - ReadBCParams(); - } - - void warpx_CheckGriddingForRZSpectral() - { - CheckGriddingForRZSpectral(); - } - - amrex::Real warpx_getCellSize(int dir, int lev) { - const std::array& dx = WarpX::CellSize(lev); - return dx[dir]; - } - - amrex::Real warpx_sumParticleCharge(const char* char_species_name, const bool local) - { - auto & mypc = WarpX::GetInstance().GetPartContainer(); - const std::string species_name(char_species_name); - auto & myspc = mypc.GetParticleContainerFromName(species_name); - return myspc.sumParticleCharge(local); - } - - void warpx_ComputeDt () { - WarpX& warpx = WarpX::GetInstance(); - warpx.ComputeDt(); - } - void warpx_MoveWindow (int step,bool move_j) { - WarpX& warpx = WarpX::GetInstance(); - warpx.MoveWindow(step, move_j); - } - - void warpx_EvolveE (amrex::Real dt) { - WarpX& warpx = WarpX::GetInstance(); - warpx.EvolveE(dt); - } - void warpx_EvolveB (amrex::Real dt, DtType a_dt_type) { - WarpX& warpx = WarpX::GetInstance(); - warpx.EvolveB(dt, a_dt_type); - } - void warpx_FillBoundaryE () { - WarpX& warpx = WarpX::GetInstance(); - warpx.FillBoundaryE(warpx.getngEB()); - } - void warpx_FillBoundaryB () { - WarpX& warpx = WarpX::GetInstance(); - warpx.FillBoundaryB(warpx.getngEB()); - } - void warpx_SyncCurrent ( - const amrex::Vector,3>>& J_fp, - const amrex::Vector,3>>& J_cp, - const amrex::Vector,3>>& J_buffer) { - WarpX& warpx = WarpX::GetInstance(); - warpx.SyncCurrent(J_fp, J_cp, J_buffer); - } - void warpx_UpdateAuxilaryData () { - WarpX& warpx = WarpX::GetInstance(); - warpx.UpdateAuxilaryData(); - } - void warpx_PushParticlesandDepose (amrex::Real cur_time) { - WarpX& warpx = WarpX::GetInstance(); - warpx.PushParticlesandDepose(cur_time); - } - - void warpx_setistep (int lev, int ii) { - WarpX& warpx = WarpX::GetInstance(); - warpx.setistep(lev, ii); - } - void warpx_sett_new (int lev, amrex::Real time) { - WarpX& warpx = WarpX::GetInstance(); - warpx.sett_new(lev, time); - } - amrex::Real warpx_getdt (int lev) { - const WarpX& warpx = WarpX::GetInstance(); - return warpx.getdt(lev); - } - - int warpx_maxStep () { - const WarpX& warpx = WarpX::GetInstance(); - return warpx.maxStep(); - } - amrex::Real warpx_stopTime () { - const WarpX& warpx = WarpX::GetInstance(); - return warpx.stopTime(); - } - - int warpx_finestLevel () { - const WarpX& warpx = WarpX::GetInstance(); - return warpx.finestLevel(); - } - - void mypc_Redistribute () { - auto & mypc = WarpX::GetInstance().GetPartContainer(); - mypc.Redistribute(); - } diff --git a/Source/Utils/WarpXAlgorithmSelection.cpp b/Source/Utils/WarpXAlgorithmSelection.cpp index d9cd5c138a8..ed8186a325c 100644 --- a/Source/Utils/WarpXAlgorithmSelection.cpp +++ b/Source/Utils/WarpXAlgorithmSelection.cpp @@ -158,7 +158,8 @@ GetAlgorithmInteger(const amrex::ParmParse& pp, const char* pp_search_key ){ } else if (0 == std::strcmp(pp_search_key, "current_deposition")) { algo_to_int = current_deposition_algo_to_int; if (WarpX::electromagnetic_solver_id == ElectromagneticSolverAlgo::PSATD || - WarpX::electromagnetic_solver_id == ElectromagneticSolverAlgo::HybridPIC) + WarpX::electromagnetic_solver_id == ElectromagneticSolverAlgo::HybridPIC || + WarpX::electrostatic_solver_id != ElectrostaticSolverAlgo::None) algo_to_int["default"] = CurrentDepositionAlgo::Direct; } else if (0 == std::strcmp(pp_search_key, "charge_deposition")) { algo_to_int = charge_deposition_algo_to_int; diff --git a/Source/WarpX.cpp b/Source/WarpX.cpp index 6be8d517775..2df53dc6d2c 100644 --- a/Source/WarpX.cpp +++ b/Source/WarpX.cpp @@ -1130,7 +1130,8 @@ WarpX::ReadParameters () } #endif - // note: current_deposition must be set after maxwell_solver is already determined, + // note: current_deposition must be set after maxwell_solver (electromagnetic_solver_id) or + // do_electrostatic (electrostatic_solver_id) are already determined, // because its default depends on the solver selection current_deposition_algo = GetAlgorithmInteger(pp_algo, "current_deposition"); charge_deposition_algo = GetAlgorithmInteger(pp_algo, "charge_deposition");