diff options
Diffstat (limited to 'Python/pywarpx')
-rw-r--r-- | Python/pywarpx/WarpX.py | 17 | ||||
-rw-r--r-- | Python/pywarpx/WarpXPIC.py | 38 | ||||
-rw-r--r-- | Python/pywarpx/__init__.py | 2 | ||||
-rwxr-xr-x | Python/pywarpx/_libwarpx.py | 877 | ||||
-rw-r--r-- | Python/pywarpx/callbacks.py | 39 | ||||
-rw-r--r-- | Python/pywarpx/fields.py | 10 | ||||
-rw-r--r-- | Python/pywarpx/timestepper.py | 38 | ||||
-rw-r--r-- | Python/pywarpx/wx.py | 20 |
8 files changed, 534 insertions, 507 deletions
diff --git a/Python/pywarpx/WarpX.py b/Python/pywarpx/WarpX.py index 7b1a07e24..232550764 100644 --- a/Python/pywarpx/WarpX.py +++ b/Python/pywarpx/WarpX.py @@ -20,6 +20,8 @@ from .Collisions import collisions, collisions_list from .PSATD import psatd from .Diagnostics import diagnostics +from . import _libwarpx + class WarpX(Bucket): """ @@ -74,25 +76,20 @@ class WarpX(Bucket): return argv def init(self, mpi_comm=None): - from . import wx argv = ['warpx'] + self.create_argv_list() - wx.initialize(argv, mpi_comm=mpi_comm) + _libwarpx.initialize(argv, mpi_comm=mpi_comm) def evolve(self, nsteps=-1): - from . import wx - wx.evolve(nsteps) + _libwarpx.evolve(nsteps) def finalize(self, finalize_mpi=1): - from . import wx - wx.finalize(finalize_mpi) + _libwarpx.finalize(finalize_mpi) def getProbLo(self, direction): - from . import wx - return wx.libwarpx.warpx_getProbLo(direction) + return _libwarpx.libwarpx.libwarpx_so.warpx_getProbLo(direction) def getProbHi(self, direction): - from . import wx - return wx.libwarpx.warpx_getProbHi(direction) + return _libwarpx.libwarpx.libwarpx_so.warpx_getProbHi(direction) def write_inputs(self, filename='inputs', **kw): argv = self.create_argv_list() diff --git a/Python/pywarpx/WarpXPIC.py b/Python/pywarpx/WarpXPIC.py index 241951d13..e98ff823d 100644 --- a/Python/pywarpx/WarpXPIC.py +++ b/Python/pywarpx/WarpXPIC.py @@ -17,46 +17,46 @@ from ._libwarpx import libwarpx class WarpXPIC(PICAPI): def get_time(self): - return libwarpx.warpx_gett_new(0) + return libwarpx.libwarpx_so.warpx_gett_new(0) def set_time(self, time): - for i in range(libwarpx.warpx_finestLevel()+1): - libwarpx.warpx_sett_new(i, time) + for i in range(libwarpx.libwarpx_so.warpx_finestLevel()+1): + libwarpx.libwarpx_so.warpx_sett_new(i, time) def get_step_size(self): - libwarpx.warpx_ComputeDt() - return libwarpx.warpx_getdt(0) + libwarpx.libwarpx_so.warpx_ComputeDt() + return libwarpx.libwarpx_so.warpx_getdt(0) def get_step_number(self): - return libwarpx.warpx_getistep(0) + return libwarpx.libwarpx_so.warpx_getistep(0) def set_step_number(self, it): - for i in range(libwarpx.warpx_finestLevel()+1): - libwarpx.warpx_setistep(i, it) + for i in range(libwarpx.libwarpx_so.warpx_finestLevel()+1): + libwarpx.libwarpx_so.warpx_setistep(i, it) def push_positions(self, dt): - libwarpx.warpx_PushX(0, dt) + libwarpx.libwarpx_so.warpx_PushX(0, dt) def push_velocities_withE(self, dt): - libwarpx.warpx_EPushV(0, dt) + libwarpx.libwarpx_so.warpx_EPushV(0, dt) def push_velocities_withB(self, dt): - libwarpx.warpx_BPushV(0, dt) + libwarpx.libwarpx_so.warpx_BPushV(0, dt) def get_self_fields(self): - libwarpx.warpx_FieldGather(0) + libwarpx.libwarpx_so.warpx_FieldGather(0) def calculate_source(self): - libwarpx.warpx_CurrentDeposition(0) + libwarpx.libwarpx_so.warpx_CurrentDeposition(0) def push_Efields(self, dt): - libwarpx.warpx_EvolveE(0, dt) - libwarpx.warpx_FillBoundaryE(0, True) + libwarpx.libwarpx_so.warpx_EvolveE(0, dt) + libwarpx.libwarpx_so.warpx_FillBoundaryE(0, True) def push_Bfields(self, dt): - libwarpx.warpx_EvolveB(0, dt) - libwarpx.warpx_FillBoundaryB(0, True) + libwarpx.libwarpx_so.warpx_EvolveB(0, dt) + libwarpx.libwarpx_so.warpx_FillBoundaryB(0, True) def apply_particle_boundary_conditions(self): - libwarpx.mypc_Redistribute() # Redistribute particles - libwarpx.warpx_MoveWindow(self.istep,True) # !!! not the correct place yet + libwarpx.libwarpx_so.mypc_Redistribute() # Redistribute particles + libwarpx.libwarpx_so.warpx_MoveWindow(self.istep,True) # !!! not the correct place yet diff --git a/Python/pywarpx/__init__.py b/Python/pywarpx/__init__.py index 7c10d4947..fb671915e 100644 --- a/Python/pywarpx/__init__.py +++ b/Python/pywarpx/__init__.py @@ -17,3 +17,5 @@ from .Collisions import collisions from .PSATD import psatd from .Lasers import lasers from .Diagnostics import diagnostics + +from ._libwarpx import * # noqa diff --git a/Python/pywarpx/_libwarpx.py b/Python/pywarpx/_libwarpx.py index 6850e1b28..9f588f806 100755 --- a/Python/pywarpx/_libwarpx.py +++ b/Python/pywarpx/_libwarpx.py @@ -30,112 +30,315 @@ except ImportError: MPI = None _MPI_Comm_type = ctypes.c_void_p -# --- Is there a better way of handling constants? -clight = 2.99792458e+8 # m/s - -def _get_package_root(): - ''' - Get the path to the installation location (where libwarpx.so would be installed). - ''' - cur = os.path.abspath(__file__) - while True: - name = os.path.basename(cur) - if name == 'pywarpx': - return cur - elif not name: - return '' - cur = os.path.dirname(cur) - -# --- Use geometry to determine whether to import the 1D, 2D, 3D or RZ version. -# --- This assumes that the input is setup before this module is imported, -# --- which should normally be the case. -# --- Default to 3D if geometry is not setup yet. -try: - _prob_lo = geometry.prob_lo - _coord_sys = geometry.coord_sys -except AttributeError: - geometry_dim = '3d' -else: - if _coord_sys == 0: - geometry_dim = '%dd'%len(_prob_lo) - elif _coord_sys == 1: - geometry_dim = 'rz' - else: - raise Exception('Undefined coordinate system %d'%_coord_sys) - del _prob_lo, _coord_sys - if platform.system() == 'Windows': - path_libc = _find_library('msvcrt') + _path_libc = _find_library('msvcrt') else: - path_libc = _find_library('c') -_libc = ctypes.CDLL(path_libc) - -# this is a plain C/C++ shared library, not a Python module -if os.name == 'nt': - mod_ext = "dll" -else: - mod_ext = "so" -libname = "libwarpx.{0}.{1}".format(geometry_dim, mod_ext) - -try: - libwarpx = ctypes.CDLL(os.path.join(_get_package_root(), libname)) -except OSError as e: - value = e.args[0] - if f'{libname}: cannot open shared object file: No such file or directory' in value: - raise Exception(f'"{libname}" was not installed. Installation instructions can be found here https://warpx.readthedocs.io/en/latest/install/users.html') from e - else: - print("Failed to load the libwarpx shared object library") - raise - -# track whether libwarpx has been initialized -libwarpx.initialized = False + _path_libc = _find_library('c') +_libc = ctypes.CDLL(_path_libc) +_LP_c_int = ctypes.POINTER(ctypes.c_int) +_LP_c_char = ctypes.POINTER(ctypes.c_char) -# WarpX can be compiled using either double or float -libwarpx.warpx_Real_size.restype = ctypes.c_int -libwarpx.warpx_ParticleReal_size.restype = ctypes.c_int +class LibWarpX(): + """This class manages the warpx shared object, the library from the compiled C++ code. + It will only load the library when it is referenced, and this can only be done after + the geometry is defined so that the version of the library that is needed can be determined. + Once loaded, all of the setting of function call interfaces is setup. + """ + def __init__(self): -_Real_size = libwarpx.warpx_Real_size() -_ParticleReal_size = libwarpx.warpx_ParticleReal_size() + # Track whether amrex and warpx have been initialized + self.initialized = False -if _Real_size == 8: - c_real = ctypes.c_double - _numpy_real_dtype = 'f8' -else: - c_real = ctypes.c_float - _numpy_real_dtype = 'f4' + def __getattr__(self, attribute): + if attribute == 'libwarpx_so': + # If the 'libwarpx_so' is referenced, load it. + # Once loaded, it gets added to the dictionary so this code won't be called again. + self.load_library() + return self.__dict__[attribute] + else: + # For any other attribute, call the built-in routine - this should always + # return an AttributeException. + return self.__getattribute__(attribute) + + def _get_package_root(self): + ''' + Get the path to the installation location (where libwarpx.so would be installed). + ''' + cur = os.path.abspath(__file__) + while True: + name = os.path.basename(cur) + if name == 'pywarpx': + return cur + elif not name: + return '' + cur = os.path.dirname(cur) + + def load_library(self): + + if 'libwarpx_so' in self.__dict__: + raise RuntimeError( + "Invalid attempt to load libwarpx_so library multiple times." + ) + + # --- Use geometry to determine whether to import the 1D, 2D, 3D or RZ version. + # --- The geometry must be setup before the lib warpx shared object can be loaded. + try: + _prob_lo = geometry.prob_lo + _coord_sys = geometry.coord_sys + except AttributeError: + raise Exception('The shared object could not be loaded. The geometry must be setup before the WarpX shared object can be accessesd. The geometry determines which version of the shared object to load.') + + if _coord_sys == 0: + self.geometry_dim = '%dd'%len(_prob_lo) + elif _coord_sys == 1: + self.geometry_dim = 'rz' + else: + raise Exception('Undefined coordinate system %d'%_coord_sys) -if _ParticleReal_size == 8: - c_particlereal = ctypes.c_double - _numpy_particlereal_dtype = 'f8' -else: - c_particlereal = ctypes.c_float - _numpy_particlereal_dtype = 'f4' + # this is a plain C/C++ shared library, not a Python module + if os.name == 'nt': + mod_ext = 'dll' + else: + mod_ext = 'so' + libname = f'libwarpx.{self.geometry_dim}.{mod_ext}' -dim = libwarpx.warpx_SpaceDim() + try: + self.libwarpx_so = ctypes.CDLL(os.path.join(self._get_package_root(), libname)) + except OSError as e: + value = e.args[0] + if f'{libname}: cannot open shared object file: No such file or directory' in value: + raise Exception(f'"{libname}" was not installed. Installation instructions can be found here https://warpx.readthedocs.io/en/latest/install/users.html') from e + else: + print("Failed to load the libwarpx shared object library") + raise + + # WarpX can be compiled using either double or float + self.libwarpx_so.warpx_Real_size.restype = ctypes.c_int + self.libwarpx_so.warpx_ParticleReal_size.restype = ctypes.c_int + + _Real_size = self.libwarpx_so.warpx_Real_size() + _ParticleReal_size = self.libwarpx_so.warpx_ParticleReal_size() + + if _Real_size == 8: + c_real = ctypes.c_double + self._numpy_real_dtype = 'f8' + else: + c_real = ctypes.c_float + self._numpy_real_dtype = 'f4' -# our particle data type, depends on _ParticleReal_size -_p_struct = [(d, _numpy_particlereal_dtype) for d in 'xyz'[:dim]] + [('id', 'i4'), ('cpu', 'i4')] -_p_dtype = np.dtype(_p_struct, align=True) + if _ParticleReal_size == 8: + c_particlereal = ctypes.c_double + _numpy_particlereal_dtype = 'f8' + else: + c_particlereal = ctypes.c_float + _numpy_particlereal_dtype = 'f4' + + self.dim = self.libwarpx_so.warpx_SpaceDim() + + # our particle data type, depends on _ParticleReal_size + _p_struct = [(d, _numpy_particlereal_dtype) for d in 'xyz'[:self.dim]] + [('id', 'i4'), ('cpu', 'i4')] + self._p_dtype = np.dtype(_p_struct, align=True) + + _numpy_to_ctypes = {} + _numpy_to_ctypes[_numpy_particlereal_dtype] = c_particlereal + _numpy_to_ctypes['i4'] = ctypes.c_int + + class Particle(ctypes.Structure): + _fields_ = [(v[0], _numpy_to_ctypes[v[1]]) for v in _p_struct] + + # some useful typenames + _LP_particle_p = ctypes.POINTER(ctypes.POINTER(Particle)) + _LP_LP_c_int = ctypes.POINTER(_LP_c_int) + #_LP_c_void_p = ctypes.POINTER(ctypes.c_void_p) + _LP_c_real = ctypes.POINTER(c_real) + _LP_LP_c_real = ctypes.POINTER(_LP_c_real) + _LP_c_particlereal = ctypes.POINTER(c_particlereal) + _LP_LP_c_particlereal = ctypes.POINTER(_LP_c_particlereal) + _LP_LP_c_char = ctypes.POINTER(_LP_c_char) + + # set the arg and return types of the wrapped functions + self.libwarpx_so.amrex_init.argtypes = (ctypes.c_int, _LP_LP_c_char) + self.libwarpx_so.amrex_init_with_inited_mpi.argtypes = (ctypes.c_int, _LP_LP_c_char, _MPI_Comm_type) + self.libwarpx_so.warpx_getParticleStructs.restype = _LP_particle_p + self.libwarpx_so.warpx_getParticleArrays.restype = _LP_LP_c_particlereal + self.libwarpx_so.warpx_getParticleCompIndex.restype = ctypes.c_int + self.libwarpx_so.warpx_getEfield.restype = _LP_LP_c_real + self.libwarpx_so.warpx_getEfieldLoVects.restype = _LP_c_int + self.libwarpx_so.warpx_getEfieldCP.restype = _LP_LP_c_real + self.libwarpx_so.warpx_getEfieldCPLoVects.restype = _LP_c_int + self.libwarpx_so.warpx_getEfieldFP.restype = _LP_LP_c_real + self.libwarpx_so.warpx_getEfieldFPLoVects.restype = _LP_c_int + self.libwarpx_so.warpx_getEfieldCP_PML.restype = _LP_LP_c_real + self.libwarpx_so.warpx_getEfieldCPLoVects_PML.restype = _LP_c_int + self.libwarpx_so.warpx_getEfieldFP_PML.restype = _LP_LP_c_real + self.libwarpx_so.warpx_getEfieldFPLoVects_PML.restype = _LP_c_int + self.libwarpx_so.warpx_getBfield.restype = _LP_LP_c_real + self.libwarpx_so.warpx_getBfieldLoVects.restype = _LP_c_int + self.libwarpx_so.warpx_getBfieldCP.restype = _LP_LP_c_real + self.libwarpx_so.warpx_getBfieldCPLoVects.restype = _LP_c_int + self.libwarpx_so.warpx_getBfieldFP.restype = _LP_LP_c_real + self.libwarpx_so.warpx_getBfieldFPLoVects.restype = _LP_c_int + self.libwarpx_so.warpx_getBfieldCP_PML.restype = _LP_LP_c_real + self.libwarpx_so.warpx_getBfieldCPLoVects_PML.restype = _LP_c_int + self.libwarpx_so.warpx_getBfieldFP_PML.restype = _LP_LP_c_real + self.libwarpx_so.warpx_getBfieldFPLoVects_PML.restype = _LP_c_int + self.libwarpx_so.warpx_getCurrentDensity.restype = _LP_LP_c_real + self.libwarpx_so.warpx_getCurrentDensityLoVects.restype = _LP_c_int + self.libwarpx_so.warpx_getCurrentDensityCP.restype = _LP_LP_c_real + self.libwarpx_so.warpx_getCurrentDensityCPLoVects.restype = _LP_c_int + self.libwarpx_so.warpx_getCurrentDensityFP.restype = _LP_LP_c_real + self.libwarpx_so.warpx_getCurrentDensityFPLoVects.restype = _LP_c_int + self.libwarpx_so.warpx_getCurrentDensityCP_PML.restype = _LP_LP_c_real + self.libwarpx_so.warpx_getCurrentDensityCPLoVects_PML.restype = _LP_c_int + self.libwarpx_so.warpx_getCurrentDensityFP_PML.restype = _LP_LP_c_real + self.libwarpx_so.warpx_getCurrentDensityFPLoVects_PML.restype = _LP_c_int + self.libwarpx_so.warpx_getChargeDensityCP.restype = _LP_LP_c_real + self.libwarpx_so.warpx_getChargeDensityCPLoVects.restype = _LP_c_int + self.libwarpx_so.warpx_getChargeDensityFP.restype = _LP_LP_c_real + self.libwarpx_so.warpx_getChargeDensityFPLoVects.restype = _LP_c_int + self.libwarpx_so.warpx_getPhiFP.restype = _LP_LP_c_real + self.libwarpx_so.warpx_getPhiFPLoVects.restype = _LP_c_int + self.libwarpx_so.warpx_getFfieldCP.restype = _LP_LP_c_real + self.libwarpx_so.warpx_getFfieldCPLoVects.restype = _LP_c_int + self.libwarpx_so.warpx_getFfieldFP.restype = _LP_LP_c_real + self.libwarpx_so.warpx_getFfieldFPLoVects.restype = _LP_c_int + self.libwarpx_so.warpx_getFfieldCP_PML.restype = _LP_LP_c_real + self.libwarpx_so.warpx_getFfieldCPLoVects_PML.restype = _LP_c_int + self.libwarpx_so.warpx_getFfieldFP_PML.restype = _LP_LP_c_real + self.libwarpx_so.warpx_getFfieldFPLoVects_PML.restype = _LP_c_int + self.libwarpx_so.warpx_getGfieldCP.restype = _LP_LP_c_real + self.libwarpx_so.warpx_getGfieldCPLoVects.restype = _LP_c_int + self.libwarpx_so.warpx_getGfieldFP.restype = _LP_LP_c_real + self.libwarpx_so.warpx_getGfieldFPLoVects.restype = _LP_c_int + self.libwarpx_so.warpx_getGfieldCP_PML.restype = _LP_LP_c_real + self.libwarpx_so.warpx_getGfieldCPLoVects_PML.restype = _LP_c_int + self.libwarpx_so.warpx_getGfieldFP_PML.restype = _LP_LP_c_real + self.libwarpx_so.warpx_getGfieldFPLoVects_PML.restype = _LP_c_int + self.libwarpx_so.warpx_getEdgeLengths.restype = _LP_LP_c_real + self.libwarpx_so.warpx_getEdgeLengthsLoVects.restype = _LP_c_int + self.libwarpx_so.warpx_getFaceAreas.restype = _LP_LP_c_real + self.libwarpx_so.warpx_getFaceAreasLoVects.restype = _LP_c_int + + self.libwarpx_so.warpx_getParticleBoundaryBufferSize.restype = ctypes.c_int + self.libwarpx_so.warpx_getParticleBoundaryBufferStructs.restype = _LP_LP_c_particlereal + self.libwarpx_so.warpx_getParticleBoundaryBuffer.restype = _LP_LP_c_particlereal + self.libwarpx_so.warpx_getParticleBoundaryBufferScrapedSteps.restype = _LP_LP_c_int + + self.libwarpx_so.warpx_getEx_nodal_flag.restype = _LP_c_int + self.libwarpx_so.warpx_getEy_nodal_flag.restype = _LP_c_int + self.libwarpx_so.warpx_getEz_nodal_flag.restype = _LP_c_int + self.libwarpx_so.warpx_getBx_nodal_flag.restype = _LP_c_int + self.libwarpx_so.warpx_getBy_nodal_flag.restype = _LP_c_int + self.libwarpx_so.warpx_getBz_nodal_flag.restype = _LP_c_int + self.libwarpx_so.warpx_getJx_nodal_flag.restype = _LP_c_int + self.libwarpx_so.warpx_getJy_nodal_flag.restype = _LP_c_int + self.libwarpx_so.warpx_getJz_nodal_flag.restype = _LP_c_int + self.libwarpx_so.warpx_getRho_nodal_flag.restype = _LP_c_int + self.libwarpx_so.warpx_getPhi_nodal_flag.restype = _LP_c_int + self.libwarpx_so.warpx_getF_nodal_flag.restype = _LP_c_int + self.libwarpx_so.warpx_getG_nodal_flag.restype = _LP_c_int + self.libwarpx_so.warpx_getF_pml_nodal_flag.restype = _LP_c_int + self.libwarpx_so.warpx_getG_pml_nodal_flag.restype = _LP_c_int + + self.libwarpx_so.warpx_get_edge_lengths_x_nodal_flag.restype = _LP_c_int + self.libwarpx_so.warpx_get_edge_lengths_y_nodal_flag.restype = _LP_c_int + self.libwarpx_so.warpx_get_edge_lengths_z_nodal_flag.restype = _LP_c_int + self.libwarpx_so.warpx_get_face_areas_x_nodal_flag.restype = _LP_c_int + self.libwarpx_so.warpx_get_face_areas_y_nodal_flag.restype = _LP_c_int + self.libwarpx_so.warpx_get_face_areas_z_nodal_flag.restype = _LP_c_int + + #self.libwarpx_so.warpx_getPMLSigma.restype = _LP_c_real + #self.libwarpx_so.warpx_getPMLSigmaStar.restype = _LP_c_real + #self.libwarpx_so.warpx_ComputePMLFactors.argtypes = (ctypes.c_int, c_real) + self.libwarpx_so.warpx_addNParticles.argtypes = (ctypes.c_char_p, ctypes.c_int, + _ndpointer(c_particlereal, flags="C_CONTIGUOUS"), + _ndpointer(c_particlereal, flags="C_CONTIGUOUS"), + _ndpointer(c_particlereal, flags="C_CONTIGUOUS"), + _ndpointer(c_particlereal, flags="C_CONTIGUOUS"), + _ndpointer(c_particlereal, flags="C_CONTIGUOUS"), + _ndpointer(c_particlereal, flags="C_CONTIGUOUS"), + ctypes.c_int, + _ndpointer(c_particlereal, flags="C_CONTIGUOUS"), + ctypes.c_int) + + self.libwarpx_so.warpx_getProbLo.restype = c_real + self.libwarpx_so.warpx_getProbHi.restype = c_real + self.libwarpx_so.warpx_getCellSize.restype = c_real + self.libwarpx_so.warpx_getistep.restype = ctypes.c_int + self.libwarpx_so.warpx_gett_new.restype = c_real + self.libwarpx_so.warpx_getdt.restype = c_real + self.libwarpx_so.warpx_maxStep.restype = ctypes.c_int + self.libwarpx_so.warpx_stopTime.restype = c_real + self.libwarpx_so.warpx_finestLevel.restype = ctypes.c_int + self.libwarpx_so.warpx_getMyProc.restype = ctypes.c_int + self.libwarpx_so.warpx_getNProcs.restype = ctypes.c_int + + self.libwarpx_so.warpx_EvolveE.argtypes = [c_real] + self.libwarpx_so.warpx_EvolveB.argtypes = [c_real] + self.libwarpx_so.warpx_FillBoundaryE.argtypes = [] + self.libwarpx_so.warpx_FillBoundaryB.argtypes = [] + self.libwarpx_so.warpx_UpdateAuxilaryData.argtypes = [] + self.libwarpx_so.warpx_SyncCurrent.argtypes = [] + self.libwarpx_so.warpx_PushParticlesandDepose.argtypes = [c_real] + self.libwarpx_so.warpx_getProbLo.argtypes = [ctypes.c_int] + self.libwarpx_so.warpx_getProbHi.argtypes = [ctypes.c_int] + self.libwarpx_so.warpx_getCellSize.argtypes = [ctypes.c_int, ctypes.c_int] + self.libwarpx_so.warpx_getistep.argtypes = [ctypes.c_int] + self.libwarpx_so.warpx_setistep.argtypes = [ctypes.c_int, ctypes.c_int] + self.libwarpx_so.warpx_gett_new.argtypes = [ctypes.c_int] + self.libwarpx_so.warpx_sett_new.argtypes = [ctypes.c_int, c_real] + self.libwarpx_so.warpx_getdt.argtypes = [ctypes.c_int] + + def get_boundary_number(self, boundary): + ''' + + Utility function to find the boundary number given a boundary name. + + Parameters + ---------- + + boundary : the boundary from which to get the scraped particle data. + In the form x/y/z_hi/lo or eb. + + Returns + ------- + + Integer index in the boundary scraper buffer for the given boundary. + ''' + if self.geometry_dim == '3d': + dimensions = {'x' : 0, 'y' : 1, 'z' : 2} + elif self.geometry_dim == '2d': + dimensions = {'x' : 0, 'z' : 1} + elif self.geometry_dim == '1d': + dimensions = {'z' : 0} + else: + raise NotImplementedError("RZ is not supported for particle scraping.") + + if boundary != 'eb': + boundary_parts = boundary.split("_") + dim_num = dimensions[boundary_parts[0]] + if boundary_parts[1] == 'lo': + side = 0 + elif boundary_parts[1] == 'hi': + side = 1 + else: + raise RuntimeError(f'Unknown boundary specified: {boundary}') + boundary_num = 2 * dim_num + side + else: + if self.geometry_dim == '3d': + boundary_num = 6 + elif self.geometry_dim == '2d': + boundary_num = 4 + elif self.geometry_dim == '1d': + boundary_num = 2 -_numpy_to_ctypes = {} -_numpy_to_ctypes[_numpy_particlereal_dtype] = c_particlereal -_numpy_to_ctypes['i4'] = ctypes.c_int + return boundary_num -class Particle(ctypes.Structure): - _fields_ = [(v[0], _numpy_to_ctypes[v[1]]) for v in _p_struct] +libwarpx = LibWarpX() -# some useful typenames -_LP_particle_p = ctypes.POINTER(ctypes.POINTER(Particle)) -_LP_c_int = ctypes.POINTER(ctypes.c_int) -_LP_LP_c_int = ctypes.POINTER(_LP_c_int) -_LP_c_void_p = ctypes.POINTER(ctypes.c_void_p) -_LP_c_real = ctypes.POINTER(c_real) -_LP_LP_c_real = ctypes.POINTER(_LP_c_real) -_LP_c_particlereal = ctypes.POINTER(c_particlereal) -_LP_LP_c_particlereal = ctypes.POINTER(_LP_c_particlereal) -_LP_c_char = ctypes.POINTER(ctypes.c_char) -_LP_LP_c_char = ctypes.POINTER(_LP_c_char) +# --- Is there a better way of handling constants? +clight = 2.99792458e+8 # m/s # this is a function for converting a ctypes pointer to a numpy array def _array1d_from_pointer(pointer, dtype, size): @@ -155,137 +358,21 @@ def _array1d_from_pointer(pointer, dtype, size): buf = buffer_from_memory(pointer, dtype.itemsize*size) return np.frombuffer(buf, dtype=dtype, count=size) +def getNProcs(): + ''' -# set the arg and return types of the wrapped functions -libwarpx.amrex_init.argtypes = (ctypes.c_int, _LP_LP_c_char) -libwarpx.amrex_init_with_inited_mpi.argtypes = (ctypes.c_int, _LP_LP_c_char, _MPI_Comm_type) -libwarpx.warpx_getParticleStructs.restype = _LP_particle_p -libwarpx.warpx_getParticleArrays.restype = _LP_LP_c_particlereal -libwarpx.warpx_getParticleCompIndex.restype = ctypes.c_int -libwarpx.warpx_getEfield.restype = _LP_LP_c_real -libwarpx.warpx_getEfieldLoVects.restype = _LP_c_int -libwarpx.warpx_getEfieldCP.restype = _LP_LP_c_real -libwarpx.warpx_getEfieldCPLoVects.restype = _LP_c_int -libwarpx.warpx_getEfieldFP.restype = _LP_LP_c_real -libwarpx.warpx_getEfieldFPLoVects.restype = _LP_c_int -libwarpx.warpx_getEfieldCP_PML.restype = _LP_LP_c_real -libwarpx.warpx_getEfieldCPLoVects_PML.restype = _LP_c_int -libwarpx.warpx_getEfieldFP_PML.restype = _LP_LP_c_real -libwarpx.warpx_getEfieldFPLoVects_PML.restype = _LP_c_int -libwarpx.warpx_getBfield.restype = _LP_LP_c_real -libwarpx.warpx_getBfieldLoVects.restype = _LP_c_int -libwarpx.warpx_getBfieldCP.restype = _LP_LP_c_real -libwarpx.warpx_getBfieldCPLoVects.restype = _LP_c_int -libwarpx.warpx_getBfieldFP.restype = _LP_LP_c_real -libwarpx.warpx_getBfieldFPLoVects.restype = _LP_c_int -libwarpx.warpx_getBfieldCP_PML.restype = _LP_LP_c_real -libwarpx.warpx_getBfieldCPLoVects_PML.restype = _LP_c_int -libwarpx.warpx_getBfieldFP_PML.restype = _LP_LP_c_real -libwarpx.warpx_getBfieldFPLoVects_PML.restype = _LP_c_int -libwarpx.warpx_getCurrentDensity.restype = _LP_LP_c_real -libwarpx.warpx_getCurrentDensityLoVects.restype = _LP_c_int -libwarpx.warpx_getCurrentDensityCP.restype = _LP_LP_c_real -libwarpx.warpx_getCurrentDensityCPLoVects.restype = _LP_c_int -libwarpx.warpx_getCurrentDensityFP.restype = _LP_LP_c_real -libwarpx.warpx_getCurrentDensityFPLoVects.restype = _LP_c_int -libwarpx.warpx_getCurrentDensityCP_PML.restype = _LP_LP_c_real -libwarpx.warpx_getCurrentDensityCPLoVects_PML.restype = _LP_c_int -libwarpx.warpx_getCurrentDensityFP_PML.restype = _LP_LP_c_real -libwarpx.warpx_getCurrentDensityFPLoVects_PML.restype = _LP_c_int -libwarpx.warpx_getChargeDensityCP.restype = _LP_LP_c_real -libwarpx.warpx_getChargeDensityCPLoVects.restype = _LP_c_int -libwarpx.warpx_getChargeDensityFP.restype = _LP_LP_c_real -libwarpx.warpx_getChargeDensityFPLoVects.restype = _LP_c_int -libwarpx.warpx_getPhiFP.restype = _LP_LP_c_real -libwarpx.warpx_getPhiFPLoVects.restype = _LP_c_int -libwarpx.warpx_getFfieldCP.restype = _LP_LP_c_real -libwarpx.warpx_getFfieldCPLoVects.restype = _LP_c_int -libwarpx.warpx_getFfieldFP.restype = _LP_LP_c_real -libwarpx.warpx_getFfieldFPLoVects.restype = _LP_c_int -libwarpx.warpx_getFfieldCP_PML.restype = _LP_LP_c_real -libwarpx.warpx_getFfieldCPLoVects_PML.restype = _LP_c_int -libwarpx.warpx_getFfieldFP_PML.restype = _LP_LP_c_real -libwarpx.warpx_getFfieldFPLoVects_PML.restype = _LP_c_int -libwarpx.warpx_getGfieldCP.restype = _LP_LP_c_real -libwarpx.warpx_getGfieldCPLoVects.restype = _LP_c_int -libwarpx.warpx_getGfieldFP.restype = _LP_LP_c_real -libwarpx.warpx_getGfieldFPLoVects.restype = _LP_c_int -libwarpx.warpx_getGfieldCP_PML.restype = _LP_LP_c_real -libwarpx.warpx_getGfieldCPLoVects_PML.restype = _LP_c_int -libwarpx.warpx_getGfieldFP_PML.restype = _LP_LP_c_real -libwarpx.warpx_getGfieldFPLoVects_PML.restype = _LP_c_int -libwarpx.warpx_getEdgeLengths.restype = _LP_LP_c_real -libwarpx.warpx_getEdgeLengthsLoVects.restype = _LP_c_int -libwarpx.warpx_getFaceAreas.restype = _LP_LP_c_real -libwarpx.warpx_getFaceAreasLoVects.restype = _LP_c_int -libwarpx.warpx_getParticleBoundaryBufferSize.restype = ctypes.c_int -libwarpx.warpx_getParticleBoundaryBufferStructs.restype = _LP_LP_c_particlereal -libwarpx.warpx_getParticleBoundaryBuffer.restype = _LP_LP_c_particlereal -libwarpx.warpx_getParticleBoundaryBufferScrapedSteps.restype = _LP_LP_c_int - -libwarpx.warpx_getEx_nodal_flag.restype = _LP_c_int -libwarpx.warpx_getEy_nodal_flag.restype = _LP_c_int -libwarpx.warpx_getEz_nodal_flag.restype = _LP_c_int -libwarpx.warpx_getBx_nodal_flag.restype = _LP_c_int -libwarpx.warpx_getBy_nodal_flag.restype = _LP_c_int -libwarpx.warpx_getBz_nodal_flag.restype = _LP_c_int -libwarpx.warpx_getJx_nodal_flag.restype = _LP_c_int -libwarpx.warpx_getJy_nodal_flag.restype = _LP_c_int -libwarpx.warpx_getJz_nodal_flag.restype = _LP_c_int -libwarpx.warpx_getRho_nodal_flag.restype = _LP_c_int -libwarpx.warpx_getPhi_nodal_flag.restype = _LP_c_int -libwarpx.warpx_getF_nodal_flag.restype = _LP_c_int -libwarpx.warpx_getG_nodal_flag.restype = _LP_c_int -libwarpx.warpx_getF_pml_nodal_flag.restype = _LP_c_int -libwarpx.warpx_getG_pml_nodal_flag.restype = _LP_c_int -libwarpx.warpx_get_edge_lengths_x_nodal_flag.restype = _LP_c_int -libwarpx.warpx_get_edge_lengths_y_nodal_flag.restype = _LP_c_int -libwarpx.warpx_get_edge_lengths_z_nodal_flag.restype = _LP_c_int -libwarpx.warpx_get_face_areas_x_nodal_flag.restype = _LP_c_int -libwarpx.warpx_get_face_areas_y_nodal_flag.restype = _LP_c_int -libwarpx.warpx_get_face_areas_z_nodal_flag.restype = _LP_c_int - -#libwarpx.warpx_getPMLSigma.restype = _LP_c_real -#libwarpx.warpx_getPMLSigmaStar.restype = _LP_c_real -#libwarpx.warpx_ComputePMLFactors.argtypes = (ctypes.c_int, c_real) -libwarpx.warpx_addNParticles.argtypes = (ctypes.c_char_p, ctypes.c_int, - _ndpointer(c_particlereal, flags="C_CONTIGUOUS"), - _ndpointer(c_particlereal, flags="C_CONTIGUOUS"), - _ndpointer(c_particlereal, flags="C_CONTIGUOUS"), - _ndpointer(c_particlereal, flags="C_CONTIGUOUS"), - _ndpointer(c_particlereal, flags="C_CONTIGUOUS"), - _ndpointer(c_particlereal, flags="C_CONTIGUOUS"), - ctypes.c_int, - _ndpointer(c_particlereal, flags="C_CONTIGUOUS"), - ctypes.c_int) - -libwarpx.warpx_getProbLo.restype = c_real -libwarpx.warpx_getProbHi.restype = c_real -libwarpx.warpx_getCellSize.restype = c_real -libwarpx.warpx_getistep.restype = ctypes.c_int -libwarpx.warpx_gett_new.restype = c_real -libwarpx.warpx_getdt.restype = c_real -libwarpx.warpx_maxStep.restype = ctypes.c_int -libwarpx.warpx_stopTime.restype = c_real -libwarpx.warpx_finestLevel.restype = ctypes.c_int -libwarpx.warpx_getMyProc.restype = ctypes.c_int -libwarpx.warpx_getNProcs.restype = ctypes.c_int - -libwarpx.warpx_EvolveE.argtypes = [c_real] -libwarpx.warpx_EvolveB.argtypes = [c_real] -libwarpx.warpx_FillBoundaryE.argtypes = [] -libwarpx.warpx_FillBoundaryB.argtypes = [] -libwarpx.warpx_UpdateAuxilaryData.argtypes = [] -libwarpx.warpx_SyncCurrent.argtypes = [] -libwarpx.warpx_PushParticlesandDepose.argtypes = [c_real] -libwarpx.warpx_getProbLo.argtypes = [ctypes.c_int] -libwarpx.warpx_getProbHi.argtypes = [ctypes.c_int] -libwarpx.warpx_getCellSize.argtypes = [ctypes.c_int, ctypes.c_int] -libwarpx.warpx_getistep.argtypes = [ctypes.c_int] -libwarpx.warpx_setistep.argtypes = [ctypes.c_int, ctypes.c_int] -libwarpx.warpx_gett_new.argtypes = [ctypes.c_int] -libwarpx.warpx_sett_new.argtypes = [ctypes.c_int, c_real] -libwarpx.warpx_getdt.argtypes = [ctypes.c_int] + Get the number of processors + + ''' + return libwarpx.libwarpx_so.warpx_getNProcs() + +def getMyProc(): + ''' + + Get the number of the processor + + ''' + return libwarpx.libwarpx_so.warpx_getMyProc() def get_nattr(): ''' @@ -294,7 +381,7 @@ def get_nattr(): ''' # --- The -3 is because the comps include the velocites - return libwarpx.warpx_nComps() - 3 + return libwarpx.libwarpx_so.warpx_nComps() - 3 def get_nattr_species(species_name): ''' @@ -302,7 +389,7 @@ def get_nattr_species(species_name): Get the number of real attributes for the given species. ''' - return libwarpx.warpx_nCompsSpecies( + return libwarpx.libwarpx_so.warpx_nCompsSpecies( ctypes.c_char_p(species_name.encode('utf-8'))) def amrex_init(argv, mpi_comm=None): @@ -314,11 +401,11 @@ def amrex_init(argv, mpi_comm=None): argvC[i] = ctypes.create_string_buffer(enc_arg) if mpi_comm is None or MPI is None: - libwarpx.amrex_init(argc, argvC) + libwarpx.libwarpx_so.amrex_init(argc, argvC) else: comm_ptr = MPI._addressof(mpi_comm) comm_val = _MPI_Comm_type.from_address(comm_ptr) - libwarpx.amrex_init_with_inited_mpi(argc, argvC, comm_val) + libwarpx.libwarpx_so.amrex_init_with_inited_mpi(argc, argvC, comm_val) def initialize(argv=None, mpi_comm=None): ''' @@ -330,11 +417,11 @@ def initialize(argv=None, mpi_comm=None): if argv is None: argv = sys.argv amrex_init(argv, mpi_comm) - libwarpx.warpx_ConvertLabParamsToBoost() - libwarpx.warpx_ReadBCParams() - if geometry_dim == 'rz': - libwarpx.warpx_CheckGriddingForRZSpectral() - libwarpx.warpx_init() + libwarpx.libwarpx_so.warpx_ConvertLabParamsToBoost() + libwarpx.libwarpx_so.warpx_ReadBCParams() + if libwarpx.geometry_dim == 'rz': + libwarpx.libwarpx_so.warpx_CheckGriddingForRZSpectral() + libwarpx.libwarpx_so.warpx_init() libwarpx.initialized = True @@ -348,9 +435,28 @@ def finalize(finalize_mpi=1): ''' if libwarpx.initialized: - libwarpx.warpx_finalize() - libwarpx.amrex_finalize(finalize_mpi) + libwarpx.libwarpx_so.warpx_finalize() + libwarpx.libwarpx_so.amrex_finalize(finalize_mpi) + +def getistep(level=0): + ''' + Get the current time step number for the specified level + + Parameter + --------- + + level : the refinement level to reference + ''' + return libwarpx.libwarpx_so.warpx_getistep(level) + +def gett_new(level=0): + ''' + + Get the next time for the specified level + + ''' + return libwarpx.libwarpx_so.warpx_gett_new(level) def evolve(num_steps=-1): ''' @@ -366,23 +472,23 @@ def evolve(num_steps=-1): ''' - libwarpx.warpx_evolve(num_steps); + libwarpx.libwarpx_so.warpx_evolve(num_steps); def getProbLo(direction): - assert 0 <= direction < dim, 'Inappropriate direction specified' - return libwarpx.warpx_getProbLo(direction) + assert 0 <= direction < libwarpx.dim, 'Inappropriate direction specified' + return libwarpx.libwarpx_so.warpx_getProbLo(direction) def getProbHi(direction): - assert 0 <= direction < dim, 'Inappropriate direction specified' - return libwarpx.warpx_getProbHi(direction) + assert 0 <= direction < libwarpx.dim, 'Inappropriate direction specified' + return libwarpx.libwarpx_so.warpx_getProbHi(direction) def getCellSize(direction, level=0): assert 0 <= direction < 3, 'Inappropriate direction specified' - assert 0 <= level and level <= libwarpx.warpx_finestLevel(), 'Inappropriate level specified' - return libwarpx.warpx_getCellSize(direction, level) + assert 0 <= level and level <= libwarpx.libwarpx_so.warpx_finestLevel(), 'Inappropriate level specified' + return libwarpx.libwarpx_so.warpx_getCellSize(direction, level) #def get_sigma(direction): @@ -394,7 +500,7 @@ def getCellSize(direction, level=0): # ''' # # size = ctypes.c_int(0) -# data = libwarpx.warpx_getPMLSigma(direction, ctypes.byref(size)) +# data = libwarpx.libwarpx_so.warpx_getPMLSigma(direction, ctypes.byref(size)) # arr = np.ctypeslib.as_array(data, (size.value,)) # arr.setflags(write=1) # return arr @@ -409,7 +515,7 @@ def getCellSize(direction, level=0): # ''' # # size = ctypes.c_int(0) -# data = libwarpx.warpx_getPMLSigmaStar(direction, ctypes.byref(size)) +# data = libwarpx.libwarpx_so.warpx_getPMLSigmaStar(direction, ctypes.byref(size)) # arr = np.ctypeslib.as_array(data, (size.value,)) # arr.setflags(write=1) # return arr @@ -424,7 +530,7 @@ def getCellSize(direction, level=0): # # ''' # -# libwarpx.warpx_ComputePMLFactors(lev, dt) +# libwarpx.libwarpx_so.warpx_ComputePMLFactors(lev, dt) def add_particles(species_name, x=None, y=None, z=None, ux=None, uy=None, uz=None, w=None, unique_particles=True, **kwargs): @@ -518,7 +624,7 @@ def add_particles(species_name, x=None, y=None, z=None, ux=None, uy=None, uz=Non # --- The -3 is because components 1 to 3 are velocities attr[:,get_particle_comp_index(species_name, key)-3] = vals - libwarpx.warpx_addNParticles( + libwarpx.libwarpx_so.warpx_addNParticles( ctypes.c_char_p(species_name.encode('utf-8')), x.size, x, y, z, ux, uy, uz, nattr, attr, unique_particles ) @@ -541,7 +647,7 @@ def get_particle_count(species_name): An integer count of the number of particles ''' - return libwarpx.warpx_getNumParticles( + return libwarpx.libwarpx_so.warpx_getNumParticles( ctypes.c_char_p(species_name.encode('utf-8')) ) @@ -570,7 +676,7 @@ def get_particle_structs(species_name, level): particles_per_tile = _LP_c_int() num_tiles = ctypes.c_int(0) - data = libwarpx.warpx_getParticleStructs( + data = libwarpx.libwarpx_so.warpx_getParticleStructs( ctypes.c_char_p(species_name.encode('utf-8')), level, ctypes.byref(num_tiles), ctypes.byref(particles_per_tile) ) @@ -579,7 +685,7 @@ def get_particle_structs(species_name, level): for i in range(num_tiles.value): if particles_per_tile[i] == 0: continue - arr = _array1d_from_pointer(data[i], _p_dtype, particles_per_tile[i]) + arr = _array1d_from_pointer(data[i], libwarpx._p_dtype, particles_per_tile[i]) particle_data.append(arr) _libc.free(particles_per_tile) @@ -611,7 +717,7 @@ def get_particle_arrays(species_name, comp_name, level): particles_per_tile = _LP_c_int() num_tiles = ctypes.c_int(0) - data = libwarpx.warpx_getParticleArrays( + data = libwarpx.libwarpx_so.warpx_getParticleArrays( ctypes.c_char_p(species_name.encode('utf-8')), ctypes.c_char_p(comp_name.encode('utf-8')), level, ctypes.byref(num_tiles), ctypes.byref(particles_per_tile) @@ -644,9 +750,9 @@ def get_particle_x(species_name, level=0): ''' structs = get_particle_structs(species_name, level) - if geometry_dim == '3d' or geometry_dim == '2d': + if libwarpx.geometry_dim == '3d' or libwarpx.geometry_dim == '2d': return [struct['x'] for struct in structs] - elif geometry_dim == 'rz': + elif libwarpx.geometry_dim == 'rz': return [struct['x']*np.cos(theta) for struct, theta in zip(structs, get_particle_theta(species_name))] @@ -658,9 +764,9 @@ def get_particle_y(species_name, level=0): ''' structs = get_particle_structs(species_name, level) - if geometry_dim == '3d' or geometry_dim == '2d': + if libwarpx.geometry_dim == '3d' or libwarpx.geometry_dim == '2d': return [struct['y'] for struct in structs] - elif geometry_dim == 'rz': + elif libwarpx.geometry_dim == 'rz': return [struct['x']*np.sin(theta) for struct, theta in zip(structs, get_particle_theta(species_name))] @@ -672,11 +778,11 @@ def get_particle_r(species_name, level=0): ''' structs = get_particle_structs(species_name, level) - if geometry_dim == 'rz': + if libwarpx.geometry_dim == 'rz': return [struct['x'] for struct in structs] - elif geometry_dim == '3d': + elif libwarpx.geometry_dim == '3d': return [np.sqrt(struct['x']**2 + struct['y']**2) for struct in structs] - elif geometry_dim == '2d': + elif libwarpx.geometry_dim == '2d': raise Exception('get_particle_r: There is no r coordinate with 2D Cartesian') @@ -688,9 +794,9 @@ def get_particle_z(species_name, level=0): ''' structs = get_particle_structs(species_name, level) - if geometry_dim == '3d': + if libwarpx.geometry_dim == '3d': return [struct['z'] for struct in structs] - elif geometry_dim == 'rz' or geometry_dim == '2d': + elif libwarpx.geometry_dim == 'rz' or libwarpx.geometry_dim == '2d': return [struct['y'] for struct in structs] @@ -768,11 +874,11 @@ def get_particle_theta(species_name, level=0): ''' - if geometry_dim == 'rz': + if libwarpx.geometry_dim == 'rz': return get_particle_arrays(species_name, 'theta', level) - elif geometry_dim == '3d': + elif libwarpx.geometry_dim == '3d': return [np.arctan2(struct['y'], struct['x']) for struct in structs] - elif geometry_dim == '2d': + elif libwarpx.geometry_dim == '2d': raise Exception('get_particle_r: There is no theta coordinate with 2D Cartesian') @@ -795,7 +901,7 @@ def get_particle_comp_index(species_name, pid_name): Integer corresponding to the index of the requested attribute ''' - return libwarpx.warpx_getParticleCompIndex( + return libwarpx.libwarpx_so.warpx_getParticleCompIndex( ctypes.c_char_p(species_name.encode('utf-8')), ctypes.c_char_p(pid_name.encode('utf-8')) ) @@ -814,58 +920,12 @@ def add_real_comp(species_name, pid_name, comm=True): comm : should the component be communicated ''' - libwarpx.warpx_addRealComp( + libwarpx.libwarpx_so.warpx_addRealComp( ctypes.c_char_p(species_name.encode('utf-8')), ctypes.c_char_p(pid_name.encode('utf-8')), comm ) -def _get_boundary_number(boundary): - ''' - - Utility function to find the boundary number given a boundary name. - - Parameters - ---------- - - boundary : the boundary from which to get the scraped particle data. - In the form x/y/z_hi/lo or eb. - - Returns - ------- - - Integer index in the boundary scraper buffer for the given boundary. - ''' - if geometry_dim == '3d': - dimensions = {'x' : 0, 'y' : 1, 'z' : 2} - elif geometry_dim == '2d': - dimensions = {'x' : 0, 'z' : 1} - elif geometry_dim == '1d': - dimensions = {'z' : 0} - else: - raise NotImplementedError("RZ is not supported for particle scraping.") - - if boundary != 'eb': - boundary_parts = boundary.split("_") - dim_num = dimensions[boundary_parts[0]] - if boundary_parts[1] == 'lo': - side = 0 - elif boundary_parts[1] == 'hi': - side = 1 - else: - raise RuntimeError(f'Unknown boundary specified: {boundary}') - boundary_num = 2 * dim_num + side - else: - if geometry_dim == '3d': - boundary_num = 6 - elif geometry_dim == '2d': - boundary_num = 4 - elif geometry_dim == '1d': - boundary_num = 2 - - return boundary_num - - def get_particle_boundary_buffer_size(species_name, boundary): ''' @@ -885,9 +945,9 @@ def get_particle_boundary_buffer_size(species_name, boundary): The number of particles scraped so far from a boundary and of a species. ''' - return libwarpx.warpx_getParticleBoundaryBufferSize( + return libwarpx.libwarpx_so.warpx_getParticleBoundaryBufferSize( ctypes.c_char_p(species_name.encode('utf-8')), - _get_boundary_number(boundary) + libwarpx.get_boundary_number(boundary) ) @@ -919,9 +979,9 @@ def get_particle_boundary_buffer_structs(species_name, boundary, level): particles_per_tile = _LP_c_int() num_tiles = ctypes.c_int(0) - data = libwarpx.warpx_getParticleBoundaryBufferStructs( + data = libwarpx.libwarpx_so.warpx_getParticleBoundaryBufferStructs( ctypes.c_char_p(species_name.encode('utf-8')), - _get_boundary_number(boundary), level, + libwarpx.get_boundary_number(boundary), level, ctypes.byref(num_tiles), ctypes.byref(particles_per_tile) ) @@ -929,7 +989,7 @@ def get_particle_boundary_buffer_structs(species_name, boundary, level): for i in range(num_tiles.value): if particles_per_tile[i] == 0: continue - arr = _array1d_from_pointer(data[i], _p_dtype, particles_per_tile[i]) + arr = _array1d_from_pointer(data[i], libwarpx._p_dtype, particles_per_tile[i]) particle_data.append(arr) _libc.free(particles_per_tile) @@ -967,15 +1027,15 @@ def get_particle_boundary_buffer(species_name, boundary, comp_name, level): particles_per_tile = _LP_c_int() num_tiles = ctypes.c_int(0) if comp_name == 'step_scraped': - data = libwarpx.warpx_getParticleBoundaryBufferScrapedSteps( + data = libwarpx.libwarpx_so.warpx_getParticleBoundaryBufferScrapedSteps( ctypes.c_char_p(species_name.encode('utf-8')), - _get_boundary_number(boundary), level, + libwarpx.get_boundary_number(boundary), level, ctypes.byref(num_tiles), ctypes.byref(particles_per_tile) ) else: - data = libwarpx.warpx_getParticleBoundaryBuffer( + data = libwarpx.libwarpx_so.warpx_getParticleBoundaryBuffer( ctypes.c_char_p(species_name.encode('utf-8')), - _get_boundary_number(boundary), level, + libwarpx.get_boundary_number(boundary), level, ctypes.byref(num_tiles), ctypes.byref(particles_per_tile), ctypes.c_char_p(comp_name.encode('utf-8')) ) @@ -999,6 +1059,15 @@ def get_particle_boundary_buffer(species_name, boundary, comp_name, level): return particle_data +def clearParticleBoundaryBuffer(): + ''' + + Clear the buffer that holds the particles lost at the boundaries. + + ''' + libwarpx.libwarpx_so.warpx_clearParticleBoundaryBuffer() + + def _get_mesh_field_list(warpx_func, level, direction, include_ghosts): """ Generic routine to fetch the list of field data arrays. @@ -1018,9 +1087,9 @@ def _get_mesh_field_list(warpx_func, level, direction, include_ghosts): if not data: raise Exception('object was not initialized') - ngvect = [ngrowvect[i] for i in range(dim)] + ngvect = [ngrowvect[i] for i in range(libwarpx.dim)] grid_data = [] - shapesize = dim + shapesize = libwarpx.dim if ncomps.value > 1: shapesize += 1 for i in range(size.value): @@ -1039,7 +1108,7 @@ def _get_mesh_field_list(warpx_func, level, direction, include_ghosts): if include_ghosts: grid_data.append(arr) else: - grid_data.append(arr[tuple([slice(ngvect[d], -ngvect[d]) for d in range(dim)])]) + grid_data.append(arr[tuple([slice(ngvect[d], -ngvect[d]) for d in range(libwarpx.dim)])]) _libc.free(shapes) _libc.free(data) @@ -1071,7 +1140,7 @@ def get_mesh_electric_field(level, direction, include_ghosts=True): ''' - return _get_mesh_field_list(libwarpx.warpx_getEfield, level, direction, include_ghosts) + return _get_mesh_field_list(libwarpx.libwarpx_so.warpx_getEfield, level, direction, include_ghosts) def get_mesh_electric_field_cp(level, direction, include_ghosts=True): @@ -1098,7 +1167,7 @@ def get_mesh_electric_field_cp(level, direction, include_ghosts=True): ''' - return _get_mesh_field_list(libwarpx.warpx_getEfieldCP, level, direction, include_ghosts) + return _get_mesh_field_list(libwarpx.libwarpx_so.warpx_getEfieldCP, level, direction, include_ghosts) def get_mesh_electric_field_fp(level, direction, include_ghosts=True): @@ -1125,7 +1194,7 @@ def get_mesh_electric_field_fp(level, direction, include_ghosts=True): ''' - return _get_mesh_field_list(libwarpx.warpx_getEfieldFP, level, direction, include_ghosts) + return _get_mesh_field_list(libwarpx.libwarpx_so.warpx_getEfieldFP, level, direction, include_ghosts) def get_mesh_electric_field_cp_pml(level, direction, include_ghosts=True): @@ -1153,7 +1222,7 @@ def get_mesh_electric_field_cp_pml(level, direction, include_ghosts=True): ''' try: - return _get_mesh_field_list(libwarpx.warpx_getEfieldCP_PML, level, direction, include_ghosts) + return _get_mesh_field_list(libwarpx.libwarpx_so.warpx_getEfieldCP_PML, level, direction, include_ghosts) except ValueError: raise Exception('PML not initialized') @@ -1183,7 +1252,7 @@ def get_mesh_electric_field_fp_pml(level, direction, include_ghosts=True): ''' try: - return _get_mesh_field_list(libwarpx.warpx_getEfieldFP_PML, level, direction, include_ghosts) + return _get_mesh_field_list(libwarpx.libwarpx_so.warpx_getEfieldFP_PML, level, direction, include_ghosts) except ValueError: raise Exception('PML not initialized') @@ -1213,7 +1282,7 @@ def get_mesh_magnetic_field(level, direction, include_ghosts=True): ''' - return _get_mesh_field_list(libwarpx.warpx_getBfield, level, direction, include_ghosts) + return _get_mesh_field_list(libwarpx.libwarpx_so.warpx_getBfield, level, direction, include_ghosts) def get_mesh_magnetic_field_cp(level, direction, include_ghosts=True): @@ -1240,7 +1309,7 @@ def get_mesh_magnetic_field_cp(level, direction, include_ghosts=True): ''' - return _get_mesh_field_list(libwarpx.warpx_getBfieldCP, level, direction, include_ghosts) + return _get_mesh_field_list(libwarpx.libwarpx_so.warpx_getBfieldCP, level, direction, include_ghosts) def get_mesh_magnetic_field_fp(level, direction, include_ghosts=True): @@ -1267,7 +1336,7 @@ def get_mesh_magnetic_field_fp(level, direction, include_ghosts=True): ''' - return _get_mesh_field_list(libwarpx.warpx_getBfieldFP, level, direction, include_ghosts) + return _get_mesh_field_list(libwarpx.libwarpx_so.warpx_getBfieldFP, level, direction, include_ghosts) def get_mesh_magnetic_field_cp_pml(level, direction, include_ghosts=True): @@ -1295,7 +1364,7 @@ def get_mesh_magnetic_field_cp_pml(level, direction, include_ghosts=True): ''' try: - return _get_mesh_field_list(libwarpx.warpx_getBfieldCP_PML, level, direction, include_ghosts) + return _get_mesh_field_list(libwarpx.libwarpx_so.warpx_getBfieldCP_PML, level, direction, include_ghosts) except ValueError: raise Exception('PML not initialized') @@ -1325,7 +1394,7 @@ def get_mesh_magnetic_field_fp_pml(level, direction, include_ghosts=True): ''' try: - return _get_mesh_field_list(libwarpx.warpx_getBfieldFP_PML, level, direction, include_ghosts) + return _get_mesh_field_list(libwarpx.libwarpx_so.warpx_getBfieldFP_PML, level, direction, include_ghosts) except ValueError: raise Exception('PML not initialized') @@ -1353,7 +1422,7 @@ def get_mesh_current_density(level, direction, include_ghosts=True): ''' - return _get_mesh_field_list(libwarpx.warpx_getCurrentDensity, level, direction, include_ghosts) + return _get_mesh_field_list(libwarpx.libwarpx_so.warpx_getCurrentDensity, level, direction, include_ghosts) def get_mesh_current_density_cp(level, direction, include_ghosts=True): @@ -1380,7 +1449,7 @@ def get_mesh_current_density_cp(level, direction, include_ghosts=True): ''' - return _get_mesh_field_list(libwarpx.warpx_getCurrentDensityCP, level, direction, include_ghosts) + return _get_mesh_field_list(libwarpx.libwarpx_so.warpx_getCurrentDensityCP, level, direction, include_ghosts) def get_mesh_current_density_fp(level, direction, include_ghosts=True): @@ -1407,7 +1476,7 @@ def get_mesh_current_density_fp(level, direction, include_ghosts=True): ''' - return _get_mesh_field_list(libwarpx.warpx_getCurrentDensityFP, level, direction, include_ghosts) + return _get_mesh_field_list(libwarpx.libwarpx_so.warpx_getCurrentDensityFP, level, direction, include_ghosts) def get_mesh_current_density_cp_pml(level, direction, include_ghosts=True): @@ -1435,7 +1504,7 @@ def get_mesh_current_density_cp_pml(level, direction, include_ghosts=True): ''' try: - return _get_mesh_field_list(libwarpx.warpx_getCurrentDensityCP_PML, level, direction, include_ghosts) + return _get_mesh_field_list(libwarpx.libwarpx_so.warpx_getCurrentDensityCP_PML, level, direction, include_ghosts) except ValueError: raise Exception('PML not initialized') @@ -1465,7 +1534,7 @@ def get_mesh_current_density_fp_pml(level, direction, include_ghosts=True): ''' try: - return _get_mesh_field_list(libwarpx.warpx_getCurrentDensityFP_PML, level, direction, include_ghosts) + return _get_mesh_field_list(libwarpx.libwarpx_so.warpx_getCurrentDensityFP_PML, level, direction, include_ghosts) except ValueError: raise Exception('PML not initialized') @@ -1493,7 +1562,7 @@ def get_mesh_charge_density_cp(level, include_ghosts=True): ''' - return _get_mesh_field_list(libwarpx.warpx_getChargeDensityCP, level, None, include_ghosts) + return _get_mesh_field_list(libwarpx.libwarpx_so.warpx_getChargeDensityCP, level, None, include_ghosts) def get_mesh_charge_density_fp(level, include_ghosts=True): @@ -1519,7 +1588,7 @@ def get_mesh_charge_density_fp(level, include_ghosts=True): ''' - return _get_mesh_field_list(libwarpx.warpx_getChargeDensityFP, level, None, include_ghosts) + return _get_mesh_field_list(libwarpx.libwarpx_so.warpx_getChargeDensityFP, level, None, include_ghosts) def get_mesh_phi_fp(level, include_ghosts=True): @@ -1544,7 +1613,7 @@ def get_mesh_phi_fp(level, include_ghosts=True): A List of numpy arrays. ''' - return _get_mesh_field_list(libwarpx.warpx_getPhiFP, level, None, include_ghosts) + return _get_mesh_field_list(libwarpx.libwarpx_so.warpx_getPhiFP, level, None, include_ghosts) def get_mesh_F_cp(level, include_ghosts=True): @@ -1570,7 +1639,7 @@ def get_mesh_F_cp(level, include_ghosts=True): ''' - return _get_mesh_field_list(libwarpx.warpx_getFfieldCP, level, None, include_ghosts) + return _get_mesh_field_list(libwarpx.libwarpx_so.warpx_getFfieldCP, level, None, include_ghosts) def get_mesh_F_fp(level, include_ghosts=True): @@ -1596,7 +1665,7 @@ def get_mesh_F_fp(level, include_ghosts=True): ''' - return _get_mesh_field_list(libwarpx.warpx_getFfieldFP, level, None, include_ghosts) + return _get_mesh_field_list(libwarpx.libwarpx_so.warpx_getFfieldFP, level, None, include_ghosts) def get_mesh_F_fp_pml(level, include_ghosts=True): @@ -1622,7 +1691,7 @@ def get_mesh_F_fp_pml(level, include_ghosts=True): ''' try: - return _get_mesh_field_list(libwarpx.warpx_getFfieldFP_PML, level, None, include_ghosts) + return _get_mesh_field_list(libwarpx.libwarpx_so.warpx_getFfieldFP_PML, level, None, include_ghosts) except ValueError: raise Exception('PML not initialized') @@ -1650,7 +1719,7 @@ def get_mesh_F_cp_pml(level, include_ghosts=True): ''' try: - return _get_mesh_field_list(libwarpx.warpx_getFfieldCP_PML, level, None, include_ghosts) + return _get_mesh_field_list(libwarpx.libwarpx_so.warpx_getFfieldCP_PML, level, None, include_ghosts) except ValueError: raise Exception('PML not initialized') @@ -1678,7 +1747,7 @@ def get_mesh_G_cp(level, include_ghosts=True): ''' - return _get_mesh_field_list(libwarpx.warpx_getGfieldCP, level, None, include_ghosts) + return _get_mesh_field_list(libwarpx.libwarpx_so.warpx_getGfieldCP, level, None, include_ghosts) def get_mesh_G_fp(level, include_ghosts=True): @@ -1704,7 +1773,7 @@ def get_mesh_G_fp(level, include_ghosts=True): ''' - return _get_mesh_field_list(libwarpx.warpx_getGfieldFP, level, None, include_ghosts) + return _get_mesh_field_list(libwarpx.libwarpx_so.warpx_getGfieldFP, level, None, include_ghosts) def get_mesh_G_cp_pml(level, include_ghosts=True): @@ -1730,7 +1799,7 @@ def get_mesh_G_cp_pml(level, include_ghosts=True): ''' try: - return _get_mesh_field_list(libwarpx.warpx_getGfieldCP_PML, level, None, include_ghosts) + return _get_mesh_field_list(libwarpx.libwarpx_so.warpx_getGfieldCP_PML, level, None, include_ghosts) except ValueError: raise Exception('PML not initialized') @@ -1758,7 +1827,7 @@ def get_mesh_G_fp_pml(level, include_ghosts=True): ''' try: - return _get_mesh_field_list(libwarpx.warpx_getGfieldFP_PML, level, None, include_ghosts) + return _get_mesh_field_list(libwarpx.libwarpx_so.warpx_getGfieldFP_PML, level, None, include_ghosts) except ValueError: raise Exception('PML not initialized') @@ -1787,7 +1856,7 @@ def get_mesh_edge_lengths(level, direction, include_ghosts=True): ''' - return _get_mesh_field_list(libwarpx.warpx_getEdgeLengths, level, direction, include_ghosts) + return _get_mesh_field_list(libwarpx.libwarpx_so.warpx_getEdgeLengths, level, direction, include_ghosts) def get_mesh_face_areas(level, direction, include_ghosts=True): @@ -1814,11 +1883,11 @@ def get_mesh_face_areas(level, direction, include_ghosts=True): ''' - return _get_mesh_field_list(libwarpx.warpx_getFaceAreas, level, direction, include_ghosts) + return _get_mesh_field_list(libwarpx.libwarpx_so.warpx_getFaceAreas, level, direction, include_ghosts) def _get_mesh_array_lovects(level, direction, include_ghosts=True, getlovectsfunc=None): - assert(0 <= level and level <= libwarpx.warpx_finestLevel()) + assert(0 <= level and level <= libwarpx.libwarpx_so.warpx_finestLevel()) size = ctypes.c_int(0) ngrowvect = _LP_c_int() @@ -1830,7 +1899,7 @@ def _get_mesh_array_lovects(level, direction, include_ghosts=True, getlovectsfun if not data: raise Exception('object was not initialized') - lovects_ref = np.ctypeslib.as_array(data, (size.value, dim)) + lovects_ref = np.ctypeslib.as_array(data, (size.value, libwarpx.dim)) # --- Make a copy of the data to avoid memory problems # --- Also, take the transpose to give shape (dims, number of grids) @@ -1838,10 +1907,10 @@ def _get_mesh_array_lovects(level, direction, include_ghosts=True, getlovectsfun ng = [] if include_ghosts: - for d in range(dim): + for d in range(libwarpx.dim): ng.append(ngrowvect[d]) else: - for d in range(dim): + for d in range(libwarpx.dim): ng.append(0) lovects[d,:] += ngrowvect[d] @@ -1871,7 +1940,7 @@ def get_mesh_electric_field_lovects(level, direction, include_ghosts=True): A 2d numpy array of the lo vector for each grid with the shape (dims, number of grids) ''' - return _get_mesh_array_lovects(level, direction, include_ghosts, libwarpx.warpx_getEfieldLoVects) + return _get_mesh_array_lovects(level, direction, include_ghosts, libwarpx.libwarpx_so.warpx_getEfieldLoVects) def get_mesh_electric_field_cp_lovects(level, direction, include_ghosts=True): @@ -1893,7 +1962,7 @@ def get_mesh_electric_field_cp_lovects(level, direction, include_ghosts=True): A 2d numpy array of the lo vector for each grid with the shape (dims, number of grids) ''' - return _get_mesh_array_lovects(level, direction, include_ghosts, libwarpx.warpx_getEfieldCPLoVects) + return _get_mesh_array_lovects(level, direction, include_ghosts, libwarpx.libwarpx_so.warpx_getEfieldCPLoVects) def get_mesh_electric_field_fp_lovects(level, direction, include_ghosts=True): @@ -1915,7 +1984,7 @@ def get_mesh_electric_field_fp_lovects(level, direction, include_ghosts=True): A 2d numpy array of the lo vector for each grid with the shape (dims, number of grids) ''' - return _get_mesh_array_lovects(level, direction, include_ghosts, libwarpx.warpx_getEfieldFPLoVects) + return _get_mesh_array_lovects(level, direction, include_ghosts, libwarpx.libwarpx_so.warpx_getEfieldFPLoVects) def get_mesh_electric_field_cp_lovects_pml(level, direction, include_ghosts=True): @@ -1938,7 +2007,7 @@ def get_mesh_electric_field_cp_lovects_pml(level, direction, include_ghosts=True ''' try: - return _get_mesh_array_lovects(level, direction, include_ghosts, libwarpx.warpx_getEfieldCPLoVects_PML) + return _get_mesh_array_lovects(level, direction, include_ghosts, libwarpx.libwarpx_so.warpx_getEfieldCPLoVects_PML) except ValueError: raise Exception('PML not initialized') @@ -1963,7 +2032,7 @@ def get_mesh_electric_field_fp_lovects_pml(level, direction, include_ghosts=True ''' try: - return _get_mesh_array_lovects(level, direction, include_ghosts, libwarpx.warpx_getEfieldFPLoVects_PML) + return _get_mesh_array_lovects(level, direction, include_ghosts, libwarpx.libwarpx_so.warpx_getEfieldFPLoVects_PML) except ValueError: raise Exception('PML not initialized') @@ -1989,7 +2058,7 @@ def get_mesh_magnetic_field_lovects(level, direction, include_ghosts=True): A 2d numpy array of the lo vector for each grid with the shape (dims, number of grids) ''' - return _get_mesh_array_lovects(level, direction, include_ghosts, libwarpx.warpx_getBfieldLoVects) + return _get_mesh_array_lovects(level, direction, include_ghosts, libwarpx.libwarpx_so.warpx_getBfieldLoVects) def get_mesh_magnetic_field_cp_lovects(level, direction, include_ghosts=True): @@ -2011,7 +2080,7 @@ def get_mesh_magnetic_field_cp_lovects(level, direction, include_ghosts=True): A 2d numpy array of the lo vector for each grid with the shape (dims, number of grids) ''' - return _get_mesh_array_lovects(level, direction, include_ghosts, libwarpx.warpx_getBfieldCPLoVects) + return _get_mesh_array_lovects(level, direction, include_ghosts, libwarpx.libwarpx_so.warpx_getBfieldCPLoVects) def get_mesh_magnetic_field_fp_lovects(level, direction, include_ghosts=True): @@ -2033,7 +2102,7 @@ def get_mesh_magnetic_field_fp_lovects(level, direction, include_ghosts=True): A 2d numpy array of the lo vector for each grid with the shape (dims, number of grids) ''' - return _get_mesh_array_lovects(level, direction, include_ghosts, libwarpx.warpx_getBfieldFPLoVects) + return _get_mesh_array_lovects(level, direction, include_ghosts, libwarpx.libwarpx_so.warpx_getBfieldFPLoVects) def get_mesh_magnetic_field_cp_lovects_pml(level, direction, include_ghosts=True): @@ -2056,7 +2125,7 @@ def get_mesh_magnetic_field_cp_lovects_pml(level, direction, include_ghosts=True ''' try: - return _get_mesh_array_lovects(level, direction, include_ghosts, libwarpx.warpx_getBfieldCPLoVects_PML) + return _get_mesh_array_lovects(level, direction, include_ghosts, libwarpx.libwarpx_so.warpx_getBfieldCPLoVects_PML) except ValueError: raise Exception('PML not initialized') @@ -2081,7 +2150,7 @@ def get_mesh_magnetic_field_fp_lovects_pml(level, direction, include_ghosts=True ''' try: - return _get_mesh_array_lovects(level, direction, include_ghosts, libwarpx.warpx_getBfieldFPLoVects_PML) + return _get_mesh_array_lovects(level, direction, include_ghosts, libwarpx.libwarpx_so.warpx_getBfieldFPLoVects_PML) except ValueError: raise Exception('PML not initialized') @@ -2105,7 +2174,7 @@ def get_mesh_current_density_lovects(level, direction, include_ghosts=True): A 2d numpy array of the lo vector for each grid with the shape (dims, number of grids) ''' - return _get_mesh_array_lovects(level, direction, include_ghosts, libwarpx.warpx_getCurrentDensityLoVects) + return _get_mesh_array_lovects(level, direction, include_ghosts, libwarpx.libwarpx_so.warpx_getCurrentDensityLoVects) def get_mesh_current_density_cp_lovects(level, direction, include_ghosts=True): @@ -2127,7 +2196,7 @@ def get_mesh_current_density_cp_lovects(level, direction, include_ghosts=True): A 2d numpy array of the lo vector for each grid with the shape (dims, number of grids) ''' - return _get_mesh_array_lovects(level, direction, include_ghosts, libwarpx.warpx_getCurrentDensityCPLoVects) + return _get_mesh_array_lovects(level, direction, include_ghosts, libwarpx.libwarpx_so.warpx_getCurrentDensityCPLoVects) def get_mesh_current_density_fp_lovects(level, direction, include_ghosts=True): ''' @@ -2148,7 +2217,7 @@ def get_mesh_current_density_fp_lovects(level, direction, include_ghosts=True): A 2d numpy array of the lo vector for each grid with the shape (dims, number of grids) ''' - return _get_mesh_array_lovects(level, direction, include_ghosts, libwarpx.warpx_getCurrentDensityFPLoVects) + return _get_mesh_array_lovects(level, direction, include_ghosts, libwarpx.libwarpx_so.warpx_getCurrentDensityFPLoVects) def get_mesh_current_density_cp_lovects_pml(level, direction, include_ghosts=True): @@ -2171,7 +2240,7 @@ def get_mesh_current_density_cp_lovects_pml(level, direction, include_ghosts=Tru ''' try: - return _get_mesh_array_lovects(level, direction, include_ghosts, libwarpx.warpx_getCurrentDensityCPLoVects_PML) + return _get_mesh_array_lovects(level, direction, include_ghosts, libwarpx.libwarpx_so.warpx_getCurrentDensityCPLoVects_PML) except ValueError: raise Exception('PML not initialized') @@ -2195,7 +2264,7 @@ def get_mesh_current_density_fp_lovects_pml(level, direction, include_ghosts=Tru ''' try: - return _get_mesh_array_lovects(level, direction, include_ghosts, libwarpx.warpx_getCurrentDensityFPLoVects_PML) + return _get_mesh_array_lovects(level, direction, include_ghosts, libwarpx.libwarpx_so.warpx_getCurrentDensityFPLoVects_PML) except ValueError: raise Exception('PML not initialized') @@ -2218,7 +2287,7 @@ def get_mesh_charge_density_cp_lovects(level, include_ghosts=True): A 2d numpy array of the lo vector for each grid with the shape (dims, number of grids) ''' - return _get_mesh_array_lovects(level, None, include_ghosts, libwarpx.warpx_getChargeDensityCPLoVects) + return _get_mesh_array_lovects(level, None, include_ghosts, libwarpx.libwarpx_so.warpx_getChargeDensityCPLoVects) def get_mesh_charge_density_fp_lovects(level, include_ghosts=True): @@ -2239,7 +2308,7 @@ def get_mesh_charge_density_fp_lovects(level, include_ghosts=True): A 2d numpy array of the lo vector for each grid with the shape (dims, number of grids) ''' - return _get_mesh_array_lovects(level, None, include_ghosts, libwarpx.warpx_getChargeDensityFPLoVects) + return _get_mesh_array_lovects(level, None, include_ghosts, libwarpx.libwarpx_so.warpx_getChargeDensityFPLoVects) def get_mesh_phi_fp_lovects(level, include_ghosts=True): @@ -2260,7 +2329,7 @@ def get_mesh_phi_fp_lovects(level, include_ghosts=True): A 2d numpy array of the lo vector for each grid with the shape (dims, number of grids) ''' - return _get_mesh_array_lovects(level, None, include_ghosts, libwarpx.warpx_getPhiFPLoVects) + return _get_mesh_array_lovects(level, None, include_ghosts, libwarpx.libwarpx_so.warpx_getPhiFPLoVects) def get_mesh_F_cp_lovects(level, include_ghosts=True): @@ -2281,7 +2350,7 @@ def get_mesh_F_cp_lovects(level, include_ghosts=True): A 2d numpy array of the lo vector for each grid with the shape (dims, number of grids) ''' - return _get_mesh_array_lovects(level, None, include_ghosts, libwarpx.warpx_getFfieldCPLoVects) + return _get_mesh_array_lovects(level, None, include_ghosts, libwarpx.libwarpx_so.warpx_getFfieldCPLoVects) def get_mesh_F_fp_lovects(level, include_ghosts=True): @@ -2302,7 +2371,7 @@ def get_mesh_F_fp_lovects(level, include_ghosts=True): A 2d numpy array of the lo vector for each grid with the shape (dims, number of grids) ''' - return _get_mesh_array_lovects(level, None, include_ghosts, libwarpx.warpx_getFfieldFPLoVects) + return _get_mesh_array_lovects(level, None, include_ghosts, libwarpx.libwarpx_so.warpx_getFfieldFPLoVects) def get_mesh_F_cp_lovects_pml(level, include_ghosts=True): @@ -2324,7 +2393,7 @@ def get_mesh_F_cp_lovects_pml(level, include_ghosts=True): ''' try: - return _get_mesh_array_lovects(level, None, include_ghosts, libwarpx.warpx_getFfieldCPLoVects_PML) + return _get_mesh_array_lovects(level, None, include_ghosts, libwarpx.libwarpx_so.warpx_getFfieldCPLoVects_PML) except ValueError: raise Exception('PML not initialized') @@ -2348,7 +2417,7 @@ def get_mesh_F_fp_lovects_pml(level, include_ghosts=True): ''' try: - return _get_mesh_array_lovects(level, None, include_ghosts, libwarpx.warpx_getFfieldFPLoVects_PML) + return _get_mesh_array_lovects(level, None, include_ghosts, libwarpx.libwarpx_so.warpx_getFfieldFPLoVects_PML) except ValueError: raise Exception('PML not initialized') @@ -2371,7 +2440,7 @@ def get_mesh_G_cp_lovects(level, include_ghosts=True): A 2d numpy array of the lo vector for each grid with the shape (dims, number of grids) ''' - return _get_mesh_array_lovects(level, None, include_ghosts, libwarpx.warpx_getGfieldCPLoVects) + return _get_mesh_array_lovects(level, None, include_ghosts, libwarpx.libwarpx_so.warpx_getGfieldCPLoVects) def get_mesh_G_fp_lovects(level, include_ghosts=True): @@ -2392,7 +2461,7 @@ def get_mesh_G_fp_lovects(level, include_ghosts=True): A 2d numpy array of the lo vector for each grid with the shape (dims, number of grids) ''' - return _get_mesh_array_lovects(level, None, include_ghosts, libwarpx.warpx_getGfieldFPLoVects) + return _get_mesh_array_lovects(level, None, include_ghosts, libwarpx.libwarpx_so.warpx_getGfieldFPLoVects) def get_mesh_G_cp_lovects_pml(level, include_ghosts=True): @@ -2414,7 +2483,7 @@ def get_mesh_G_cp_lovects_pml(level, include_ghosts=True): ''' try: - return _get_mesh_array_lovects(level, None, include_ghosts, libwarpx.warpx_getGfieldCPLoVects_PML) + return _get_mesh_array_lovects(level, None, include_ghosts, libwarpx.libwarpx_so.warpx_getGfieldCPLoVects_PML) except ValueError: raise Exception('PML not initialized') @@ -2438,7 +2507,7 @@ def get_mesh_G_fp_lovects_pml(level, include_ghosts=True): ''' try: - return _get_mesh_array_lovects(level, None, include_ghosts, libwarpx.warpx_getGfieldFPLoVects_PML) + return _get_mesh_array_lovects(level, None, include_ghosts, libwarpx.libwarpx_so.warpx_getGfieldFPLoVects_PML) except ValueError: raise Exception('PML not initialized') @@ -2462,7 +2531,7 @@ def get_mesh_edge_lengths_lovects(level, direction, include_ghosts=True): A 2d numpy array of the lo vector for each grid with the shape (dims, number of grids) ''' - return _get_mesh_array_lovects(level, direction, include_ghosts, libwarpx.warpx_getEdgeLengthsLoVects) + return _get_mesh_array_lovects(level, direction, include_ghosts, libwarpx.libwarpx_so.warpx_getEdgeLengthsLoVects) def get_mesh_face_areas_lovects(level, direction, include_ghosts=True): @@ -2484,7 +2553,7 @@ def get_mesh_face_areas_lovects(level, direction, include_ghosts=True): A 2d numpy array of the lo vector for each grid with the shape (dims, number of grids) ''' - return _get_mesh_array_lovects(level, direction, include_ghosts, libwarpx.warpx_getFaceAreasLoVects) + return _get_mesh_array_lovects(level, direction, include_ghosts, libwarpx.libwarpx_so.warpx_getFaceAreasLoVects) def _get_nodal_flag(getdatafunc): @@ -2492,7 +2561,7 @@ def _get_nodal_flag(getdatafunc): if not data: raise Exception('object was not initialized') - nodal_flag_ref = np.ctypeslib.as_array(data, (dim,)) + nodal_flag_ref = np.ctypeslib.as_array(data, (libwarpx.dim,)) # --- Make a copy of the data to avoid memory problems nodal_flag = nodal_flag_ref.copy() @@ -2506,133 +2575,133 @@ def get_Ex_nodal_flag(): ''' This returns a 1d array of the nodal flags for Ex along each direction. A 1 means node centered, and 0 cell centered. ''' - return _get_nodal_flag(libwarpx.warpx_getEx_nodal_flag) + return _get_nodal_flag(libwarpx.libwarpx_so.warpx_getEx_nodal_flag) def get_Ey_nodal_flag(): ''' This returns a 1d array of the nodal flags for Ey along each direction. A 1 means node centered, and 0 cell centered. ''' - return _get_nodal_flag(libwarpx.warpx_getEy_nodal_flag) + return _get_nodal_flag(libwarpx.libwarpx_so.warpx_getEy_nodal_flag) def get_Ez_nodal_flag(): ''' This returns a 1d array of the nodal flags for Ez along each direction. A 1 means node centered, and 0 cell centered. ''' - return _get_nodal_flag(libwarpx.warpx_getEz_nodal_flag) + return _get_nodal_flag(libwarpx.libwarpx_so.warpx_getEz_nodal_flag) def get_Bx_nodal_flag(): ''' This returns a 1d array of the nodal flags for Bx along each direction. A 1 means node centered, and 0 cell centered. ''' - return _get_nodal_flag(libwarpx.warpx_getBx_nodal_flag) + return _get_nodal_flag(libwarpx.libwarpx_so.warpx_getBx_nodal_flag) def get_By_nodal_flag(): ''' This returns a 1d array of the nodal flags for By along each direction. A 1 means node centered, and 0 cell centered. ''' - return _get_nodal_flag(libwarpx.warpx_getBy_nodal_flag) + return _get_nodal_flag(libwarpx.libwarpx_so.warpx_getBy_nodal_flag) def get_Bz_nodal_flag(): ''' This returns a 1d array of the nodal flags for Bz along each direction. A 1 means node centered, and 0 cell centered. ''' - return _get_nodal_flag(libwarpx.warpx_getBz_nodal_flag) + return _get_nodal_flag(libwarpx.libwarpx_so.warpx_getBz_nodal_flag) def get_Jx_nodal_flag(): ''' This returns a 1d array of the nodal flags for Jx along each direction. A 1 means node centered, and 0 cell centered. ''' - return _get_nodal_flag(libwarpx.warpx_getJx_nodal_flag) + return _get_nodal_flag(libwarpx.libwarpx_so.warpx_getJx_nodal_flag) def get_Jy_nodal_flag(): ''' This returns a 1d array of the nodal flags for Jy along each direction. A 1 means node centered, and 0 cell centered. ''' - return _get_nodal_flag(libwarpx.warpx_getJy_nodal_flag) + return _get_nodal_flag(libwarpx.libwarpx_so.warpx_getJy_nodal_flag) def get_Jz_nodal_flag(): ''' This returns a 1d array of the nodal flags for Jz along each direction. A 1 means node centered, and 0 cell centered. ''' - return _get_nodal_flag(libwarpx.warpx_getJz_nodal_flag) + return _get_nodal_flag(libwarpx.libwarpx_so.warpx_getJz_nodal_flag) def get_Rho_nodal_flag(): ''' This returns a 1d array of the nodal flags for Rho along each direction. A 1 means node centered, and 0 cell centered. ''' - return _get_nodal_flag(libwarpx.warpx_getRho_nodal_flag) + return _get_nodal_flag(libwarpx.libwarpx_so.warpx_getRho_nodal_flag) def get_Phi_nodal_flag(): ''' This returns a 1d array of the nodal flags for Phi along each direction. A 1 means node centered, and 0 cell centered. ''' - return _get_nodal_flag(libwarpx.warpx_getPhi_nodal_flag) + return _get_nodal_flag(libwarpx.libwarpx_so.warpx_getPhi_nodal_flag) def get_F_nodal_flag(): ''' This returns a 1d array of the nodal flags for F along each direction. A 1 means node centered, and 0 cell centered. ''' - return _get_nodal_flag(libwarpx.warpx_getF_nodal_flag) + return _get_nodal_flag(libwarpx.libwarpx_so.warpx_getF_nodal_flag) def get_G_nodal_flag(): ''' This returns a 1d array of the nodal flags for G along each direction. A 1 means node centered, and 0 cell centered. ''' - return _get_nodal_flag(libwarpx.warpx_getG_nodal_flag) + return _get_nodal_flag(libwarpx.libwarpx_so.warpx_getG_nodal_flag) def get_edge_lengths_x_nodal_flag(): ''' This returns a 1d array of the nodal flags for the x edge lengths along each direction. A 1 means node centered, and 0 cell centered. ''' - return _get_nodal_flag(libwarpx.warpx_get_edge_lengths_x_nodal_flag) + return _get_nodal_flag(libwarpx.libwarpx_so.warpx_get_edge_lengths_x_nodal_flag) def get_edge_lengths_y_nodal_flag(): ''' This returns a 1d array of the nodal flags for the y edge lengths along each direction. A 1 means node centered, and 0 cell centered. ''' - return _get_nodal_flag(libwarpx.warpx_get_edge_lengths_y_nodal_flag) + return _get_nodal_flag(libwarpx.libwarpx_so.warpx_get_edge_lengths_y_nodal_flag) def get_edge_lengths_z_nodal_flag(): ''' This returns a 1d array of the nodal flags for the z edge lengths along each direction. A 1 means node centered, and 0 cell centered. ''' - return _get_nodal_flag(libwarpx.warpx_get_edge_lengths_z_nodal_flag) + return _get_nodal_flag(libwarpx.libwarpx_so.warpx_get_edge_lengths_z_nodal_flag) def get_face_areas_x_nodal_flag(): ''' This returns a 1d array of the nodal flags for the x face areas along each direction. A 1 means node centered, and 0 cell centered. ''' - return _get_nodal_flag(libwarpx.warpx_get_face_areas_x_nodal_flag) + return _get_nodal_flag(libwarpx.libwarpx_so.warpx_get_face_areas_x_nodal_flag) def get_face_areas_y_nodal_flag(): ''' This returns a 1d array of the nodal flags for the y face areas along each direction. A 1 means node centered, and 0 cell centered. ''' - return _get_nodal_flag(libwarpx.warpx_get_face_areas_y_nodal_flag) + return _get_nodal_flag(libwarpx.libwarpx_so.warpx_get_face_areas_y_nodal_flag) def get_face_areas_z_nodal_flag(): ''' This returns a 1d array of the nodal flags for the z face areas along each direction. A 1 means node centered, and 0 cell centered. ''' - return _get_nodal_flag(libwarpx.warpx_get_face_areas_z_nodal_flag) + return _get_nodal_flag(libwarpx.libwarpx_so.warpx_get_face_areas_z_nodal_flag) def get_F_pml_nodal_flag(): ''' This returns a 1d array of the nodal flags for F in the PML along each direction. A 1 means node centered, and 0 cell centered. ''' - return _get_nodal_flag(libwarpx.warpx_getF_pml_nodal_flag) + return _get_nodal_flag(libwarpx.libwarpx_so.warpx_getF_pml_nodal_flag) def get_G_pml_nodal_flag(): ''' This returns a 1d array of the nodal flags for G in the PML along each direction. A 1 means node centered, and 0 cell centered. ''' - return _get_nodal_flag(libwarpx.warpx_getG_pml_nodal_flag) + return _get_nodal_flag(libwarpx.libwarpx_so.warpx_getG_pml_nodal_flag) diff --git a/Python/pywarpx/callbacks.py b/Python/pywarpx/callbacks.py index 2d3576c5b..49d0c3db2 100644 --- a/Python/pywarpx/callbacks.py +++ b/Python/pywarpx/callbacks.py @@ -146,6 +146,14 @@ class CallbackFunctions(object): def installfuncinlist(self,f): "Check if the specified function is installed" + if len(self.funcs) == 0: + # If this is the first function installed, set the callback in the C++ + # to call this class instance. + # Note that the _c_func must be saved. + _CALLBACK_FUNC_0 = ctypes.CFUNCTYPE(None) + self._c_func = _CALLBACK_FUNC_0(self) + callback_setter = getattr(libwarpx.libwarpx_so, f'warpx_set_callback_py_{self.name}') + callback_setter(self._c_func) if isinstance(f,types.MethodType): # --- If the function is a method of a class instance, then save a full # --- reference to that instance and the method name. @@ -241,34 +249,6 @@ _afterrestart = CallbackFunctions('afterrestart',lcallonce=1) _particleinjection = CallbackFunctions('particleinjection') _appliedfields = CallbackFunctions('appliedfields') -# --- Create the objects that can be called from C. -# --- Note that each of the CFUNCTYPE instances need to be saved -_CALLBACK_FUNC_0 = ctypes.CFUNCTYPE(None) -_c_afterinit = _CALLBACK_FUNC_0(_afterinit) -libwarpx.warpx_set_callback_py_afterinit(_c_afterinit) -_c_beforeEsolve = _CALLBACK_FUNC_0(_beforeEsolve) -libwarpx.warpx_set_callback_py_beforeEsolve(_c_beforeEsolve) -_c_poissonsolver = _CALLBACK_FUNC_0(_poissonsolver) -_c_afterEsolve = _CALLBACK_FUNC_0(_afterEsolve) -libwarpx.warpx_set_callback_py_afterEsolve(_c_afterEsolve) -_c_beforedeposition = _CALLBACK_FUNC_0(_beforedeposition) -libwarpx.warpx_set_callback_py_beforedeposition(_c_beforedeposition) -_c_afterdeposition = _CALLBACK_FUNC_0(_afterdeposition) -libwarpx.warpx_set_callback_py_afterdeposition(_c_afterdeposition) -_c_particlescraper = _CALLBACK_FUNC_0(_particlescraper) -libwarpx.warpx_set_callback_py_particlescraper(_c_particlescraper) -_c_particleloader = _CALLBACK_FUNC_0(_particleloader) -libwarpx.warpx_set_callback_py_particleloader(_c_particleloader) -_c_beforestep = _CALLBACK_FUNC_0(_beforestep) -libwarpx.warpx_set_callback_py_beforestep(_c_beforestep) -_c_afterstep = _CALLBACK_FUNC_0(_afterstep) -libwarpx.warpx_set_callback_py_afterstep(_c_afterstep) -_c_afterrestart = _CALLBACK_FUNC_0(_afterrestart) -libwarpx.warpx_set_callback_py_afterrestart(_c_afterrestart) -_c_particleinjection = _CALLBACK_FUNC_0(_particleinjection) -libwarpx.warpx_set_callback_py_particleinjection(_c_particleinjection) -_c_appliedfields = _CALLBACK_FUNC_0(_appliedfields) -libwarpx.warpx_set_callback_py_appliedfields(_c_appliedfields) #============================================================================= def printcallbacktimers(tmin=1.,lminmax=False,ff=None): @@ -299,7 +279,7 @@ def printcallbacktimers(tmin=1.,lminmax=False,ff=None): vmin = numpy.min(vlist) vmax = numpy.max(vlist) ff.write(' %10.4f %10.4f'%(vmin,vmax)) - it = libwarpx.warpx_getistep(0) + it = libwarpx.libwarpx_so.warpx_getistep(0) if it > 0: ff.write(' %10.4f'%(vsum/npes/(it))) ff.write('\n') @@ -345,7 +325,6 @@ def installpoissonsolver(f): cannot be uninstalled with the uninstallfuncinlist functionality at present.""" if _poissonsolver.hasfuncsinstalled(): raise RuntimeError('Only one field solver can be installed.') - libwarpx.warpx_set_callback_py_poissonsolver(_c_poissonsolver) _poissonsolver.installfuncinlist(f) def isinstalledpoissonsolver(f): """Checks if the function is called for a field solve""" diff --git a/Python/pywarpx/fields.py b/Python/pywarpx/fields.py index cb63a8af4..6f4ec1c43 100644 --- a/Python/pywarpx/fields.py +++ b/Python/pywarpx/fields.py @@ -42,7 +42,7 @@ class _MultiFABWrapper(object): self.level = level self.include_ghosts = include_ghosts - self.dim = _libwarpx.dim + self.dim = _libwarpx.libwarpx.dim # overlaps is one along the axes where the grid boundaries overlap the neighboring grid, # which is the case with node centering. @@ -85,13 +85,13 @@ class _MultiFABWrapper(object): """ try: - if _libwarpx.geometry_dim == '3d': + if _libwarpx.libwarpx.geometry_dim == '3d': idir = ['x', 'y', 'z'].index(direction) celldir = idir - elif _libwarpx.geometry_dim == '2d': + elif _libwarpx.libwarpx.geometry_dim == '2d': idir = ['x', 'z'].index(direction) celldir = 2*idir - elif _libwarpx.geometry_dim == 'rz': + elif _libwarpx.libwarpx.geometry_dim == 'rz': idir = ['r', 'z'].index(direction) celldir = 2*idir elif _libwarpx.geometry_dim == '1d': @@ -299,7 +299,7 @@ class _MultiFABWrapper(object): if ncomps > 1 and ic is None: sss = tuple(list(sss) + [ncomps]) # --- Create the array to be returned. - resultglobal = np.zeros(sss, dtype=_libwarpx._numpy_real_dtype) + resultglobal = np.zeros(sss, dtype=_libwarpx.libwarpx._numpy_real_dtype) datalist = [] for i in range(len(fields)): diff --git a/Python/pywarpx/timestepper.py b/Python/pywarpx/timestepper.py index 180bd845e..f75bc8c2b 100644 --- a/Python/pywarpx/timestepper.py +++ b/Python/pywarpx/timestepper.py @@ -12,7 +12,7 @@ # Note that this is intended to be an example only and may not be functional. The # onestep routine as written here is out of date and is not consistent with WarpX::Evolve. -from ._libwarpx import libwarpx +from . import libwarpx from . import callbacks @@ -26,8 +26,8 @@ class TimeStepper(object): callbacks._beforestep() - self.cur_time = libwarpx.warpx_gett_new(0) - self.istep = libwarpx.warpx_getistep(0) + self.cur_time = libwarpx.libwarpx_so.warpx_gett_new(0) + self.istep = libwarpx.libwarpx_so.warpx_getistep(0) #if mpi.rank == 0: print("\nSTEP %d starts ..."%(self.istep + 1)) @@ -35,48 +35,48 @@ class TimeStepper(object): #if (ParallelDescriptor::NProcs() > 1) # if (okToRegrid(step)) RegridBaseLevel(); - dt = libwarpx.warpx_getdt(0) + dt = libwarpx.libwarpx_so.warpx_getdt(0) # --- At the beginning, we have B^{n-1/2} and E^{n}. # --- Particles have p^{n-1/2} and x^{n}. - libwarpx.warpx_FillBoundaryE() - libwarpx.warpx_EvolveB(0.5*dt,1) # We now B^{n} + libwarpx.libwarpx_so.warpx_FillBoundaryE() + libwarpx.libwarpx_so.warpx_EvolveB(0.5*dt,1) # We now B^{n} - libwarpx.warpx_FillBoundaryB() - libwarpx.warpx_UpdateAuxilaryData() + libwarpx.libwarpx_so.warpx_FillBoundaryB() + libwarpx.libwarpx_so.warpx_UpdateAuxilaryData() # --- Evolve particles to p^{n+1/2} and x^{n+1} # --- Depose current, j^{n+1/2} callbacks._particleinjection() callbacks._particlescraper() callbacks._beforedeposition() - libwarpx.warpx_PushParticlesandDepose(self.cur_time) + libwarpx.libwarpx_so.warpx_PushParticlesandDepose(self.cur_time) callbacks._afterdeposition() - libwarpx.mypc_Redistribute() # Redistribute particles + libwarpx.libwarpx_so.mypc_Redistribute() # Redistribute particles - libwarpx.warpx_FillBoundaryE() - libwarpx.warpx_EvolveB(0.5*dt,2) # We now B^{n+1/2} + libwarpx.libwarpx_so.warpx_FillBoundaryE() + libwarpx.libwarpx_so.warpx_EvolveB(0.5*dt,2) # We now B^{n+1/2} - libwarpx.warpx_SyncCurrent() + libwarpx.libwarpx_so.warpx_SyncCurrent() - libwarpx.warpx_FillBoundaryB() + libwarpx.libwarpx_so.warpx_FillBoundaryB() callbacks._beforeEsolve() - libwarpx.warpx_EvolveE(dt,0) # We now have E^{n+1} + libwarpx.libwarpx_so.warpx_EvolveE(dt,0) # We now have E^{n+1} callbacks._afterEsolve() self.istep += 1 self.cur_time += dt - libwarpx.warpx_MoveWindow(self.istep,True); + libwarpx.libwarpx_so.warpx_MoveWindow(self.istep,True); #if mpi.rank == 0: print("STEP %d ends. TIME = %e DT = %e"%(self.istep, self.cur_time, dt)) # --- Sync up time - for i in range(libwarpx.warpx_finestLevel()+1): - libwarpx.warpx_sett_new(i, self.cur_time) - libwarpx.warpx_setistep(i, self.istep) + for i in range(libwarpx.libwarpx_so.warpx_finestLevel()+1): + libwarpx.libwarpx_so.warpx_sett_new(i, self.cur_time) + libwarpx.libwarpx_so.warpx_setistep(i, self.istep) callbacks._afterstep() diff --git a/Python/pywarpx/wx.py b/Python/pywarpx/wx.py deleted file mode 100644 index e28be62c8..000000000 --- a/Python/pywarpx/wx.py +++ /dev/null @@ -1,20 +0,0 @@ -# Copyright 2018 David Grote -# -# This file is part of WarpX. -# -# License: BSD-3-Clause-LBNL - -from ._libwarpx import * - -from .timestepper import TimeStepper - -from .PGroup import PGroup -from .PGroup import PGroups - -from .callbacks import * - -try: - # This has a dependency on Warp and so is not always imported - from .WarpXPIC import WarpXPIC -except ImportError: - pass |