aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xExec/Langmuir/python/Langmuir.py550
-rw-r--r--Exec/Langmuir/python/README19
-rw-r--r--Exec/Langmuir/python/inputs47
-rw-r--r--Exec/Make.WarpX24
-rw-r--r--Source/WarpX.H6
-rw-r--r--Source/WarpXWrappers.cpp94
-rw-r--r--Source/WarpXWrappers.h25
7 files changed, 749 insertions, 16 deletions
diff --git a/Exec/Langmuir/python/Langmuir.py b/Exec/Langmuir/python/Langmuir.py
new file mode 100755
index 000000000..9bc1ff7e7
--- /dev/null
+++ b/Exec/Langmuir/python/Langmuir.py
@@ -0,0 +1,550 @@
+#!/usr/bin/env python
+
+import sys
+import ctypes
+from ctypes.util import find_library
+import numpy as np
+from numpy.ctypeslib import ndpointer
+import matplotlib.pyplot as plt
+
+libwarpx = ctypes.CDLL("libwarpx.so")
+libc = ctypes.CDLL(find_library('c'))
+
+# some useful data structures and typenames
+class Particle(ctypes.Structure):
+ _fields_ = [('x', ctypes.c_double),
+ ('y', ctypes.c_double),
+ ('z', ctypes.c_double),
+ ('id', ctypes.c_int),
+ ('cpu', ctypes.c_int)]
+
+
+p_dtype = np.dtype([('x', 'f8'), ('y', 'f8'), ('z', 'f8'),
+ ('id', 'i4'), ('cpu', 'i4')])
+
+c_double_p = ctypes.POINTER(ctypes.c_double)
+LP_c_char = ctypes.POINTER(ctypes.c_char)
+LP_LP_c_char = ctypes.POINTER(LP_c_char)
+
+# from where do I import these? this might only work for CPython...
+PyBuf_READ = 0x100
+PyBUF_WRITE = 0x200
+
+# this is a function for converting a ctypes pointer to a numpy array
+def array1d_from_pointer(pointer, dtype, size):
+ if sys.version_info.major >= 3:
+ buffer_from_memory = ctypes.pythonapi.PyMemoryView_FromMemory
+ buffer_from_memory.argtypes = (ctypes.c_void_p, ctypes.c_int, ctypes.c_int)
+ buffer_from_memory.restype = ctypes.py_object
+ buf = buffer_from_memory(pointer, dtype.itemsize*size, PyBUF_WRITE)
+ else:
+ buffer_from_memory = ctypes.pythonapi.PyBuffer_FromReadWriteMemory
+ buffer_from_memory.restype = ctypes.py_object
+ buf = buffer_from_memory(pointer, dtype.itemsize*size)
+ return np.frombuffer(buf, dtype=dtype, count=size)
+
+
+# set the arg and return types of the wrapped functions
+f = libwarpx.amrex_init
+f.argtypes = (ctypes.c_int, LP_LP_c_char)
+
+f = libwarpx.warpx_getParticleStructs
+f.restype = ctypes.POINTER(ctypes.POINTER(Particle))
+
+f = libwarpx.warpx_getParticleArrays
+f.restype = ctypes.POINTER(c_double_p)
+
+f = libwarpx.warpx_getEfield
+f.restype = ctypes.POINTER(c_double_p)
+
+f = libwarpx.warpx_getBfield
+f.restype = ctypes.POINTER(c_double_p)
+
+f = libwarpx.warpx_getCurrentDensity
+f.restype = ctypes.POINTER(c_double_p)
+
+f = libwarpx.warpx_addNParticles
+f.argtypes = (ctypes.c_int, ctypes.c_int,
+ ndpointer(ctypes.c_double, flags="C_CONTIGUOUS"),
+ ndpointer(ctypes.c_double, flags="C_CONTIGUOUS"),
+ ndpointer(ctypes.c_double, flags="C_CONTIGUOUS"),
+ ndpointer(ctypes.c_double, flags="C_CONTIGUOUS"),
+ ndpointer(ctypes.c_double, flags="C_CONTIGUOUS"),
+ ndpointer(ctypes.c_double, flags="C_CONTIGUOUS"),
+ ctypes.c_int,
+ ndpointer(ctypes.c_double, flags="C_CONTIGUOUS"),
+ ctypes.c_int)
+
+def initialize():
+ '''
+
+ Initialize WarpX and AMReX. Must be called before
+ doing anything else.
+
+ '''
+
+ # convert command line args to pass into amrex
+ argc = len(sys.argv)
+ argv = (LP_c_char * (argc+1))()
+ for i, arg in enumerate(sys.argv):
+ enc_arg = arg.encode('utf-8')
+ argv[i] = ctypes.create_string_buffer(enc_arg)
+
+ libwarpx.amrex_init(argc, argv)
+ libwarpx.warpx_init()
+
+
+def finalize():
+ '''
+
+ Call finalize for WarpX and AMReX. Must be called at
+ the end of your script.
+
+ '''
+ libwarpx.warpx_finalize()
+ libwarpx.amrex_finalize()
+
+
+def evolve(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
+
+ '''
+
+ libwarpx.warpx_evolve(num_steps);
+
+def add_particles(species_number, N,
+ x, y, z, ux, uy, uz, nattr, attr, unique_particles):
+ '''
+
+ A function for adding particles to the WarpX simulation.
+
+ Parameters
+ ----------
+
+ species_number : the species to add the particle to
+ N : the number of particles
+ x, y, z : numpy arrays of the particle positions
+ ux, uy, uz : numpy arrays of the particle momenta
+ nattr : the number of particle attributes to add
+ attr : a 2D numpy array with the particle attributes
+ unique_particles : whether the particles are unique or duplicated on
+ several processes
+
+ '''
+ libwarpx.warpx_addNParticles(species_number, N,
+ x, y, z, ux, uy, uz,
+ nattr, attr, unique_particles)
+
+def get_particle_structs(species_number):
+ '''
+
+ This returns a list of numpy arrays containing the particle struct data
+ on each tile for this process. The particle data is represented as a structured
+ numpy array and contains the particle 'x', 'y', 'z', 'id', and 'cpu'.
+
+ The data for the numpy arrays are not copied, but share the underlying
+ memory buffer with WarpX. The numpy arrays are fully writeable.
+
+ Parameters
+ ----------
+
+ species_number : the species id that the data will be returned for
+
+ Returns
+ -------
+
+ A List of numpy arrays.
+
+ '''
+
+ particles_per_tile = ctypes.POINTER(ctypes.c_int)()
+ num_tiles = ctypes.c_int(0)
+ data = libwarpx.warpx_getParticleStructs(species_number,
+ ctypes.byref(num_tiles),
+ ctypes.byref(particles_per_tile))
+
+ particle_data = []
+ for i in range(num_tiles.value):
+ arr = array1d_from_pointer(data[i], p_dtype, particles_per_tile[i])
+ particle_data.append(arr)
+
+ libc.free(particles_per_tile)
+ libc.free(data)
+ return particle_data
+
+
+def get_particle_arrays(species_number, comp):
+ '''
+
+ This returns a list of numpy arrays containing the particle array data
+ on each tile for this process.
+
+ The data for the numpy arrays are not copied, but share the underlying
+ memory buffer with WarpX. The numpy arrays are fully writeable.
+
+ Parameters
+ ----------
+
+ species_number : the species id that the data will be returned for
+ comp : the component of the array data that will be returned.
+
+ Returns
+ -------
+
+ A List of numpy arrays.
+
+ '''
+
+ particles_per_tile = ctypes.POINTER(ctypes.c_int)()
+ num_tiles = ctypes.c_int(0)
+ data = libwarpx.warpx_getParticleArrays(species_number, comp,
+ ctypes.byref(num_tiles),
+ ctypes.byref(particles_per_tile))
+
+ particle_data = []
+ for i in range(num_tiles.value):
+ arr = np.ctypeslib.as_array(data[i], (particles_per_tile[i],))
+ arr.setflags(write=1)
+ particle_data.append(arr)
+
+ libc.free(particles_per_tile)
+ libc.free(data)
+ return particle_data
+
+
+def get_particle_x(species_number):
+ '''
+
+ Return a list of numpy arrays containing the particle 'x'
+ positions on each tile.
+
+ '''
+ structs = get_particle_structs(species_number)
+ return [struct['x'] for struct in structs]
+
+
+def get_particle_y(species_number):
+ '''
+
+ Return a list of numpy arrays containing the particle 'y'
+ positions on each tile.
+
+ '''
+ structs = get_particle_structs(species_number)
+ return [struct['y'] for struct in structs]
+
+
+def get_particle_z(species_number):
+ '''
+
+ Return a list of numpy arrays containing the particle 'z'
+ positions on each tile.
+
+ '''
+ structs = get_particle_structs(species_number)
+ return [struct['z'] for struct in structs]
+
+
+def get_particle_id(species_number):
+ '''
+
+ Return a list of numpy arrays containing the particle 'z'
+ positions on each tile.
+
+ '''
+ structs = get_particle_structs(species_number)
+ return [struct['id'] for struct in structs]
+
+
+def get_particle_cpu(species_number):
+ '''
+
+ Return a list of numpy arrays containing the particle 'z'
+ positions on each tile.
+
+ '''
+ structs = get_particle_structs(species_number)
+ return [struct['cpu'] for struct in structs]
+
+
+def get_particle_weight(species_number):
+ '''
+
+ Return a list of numpy arrays containing the particle
+ weight on each tile.
+
+ '''
+
+ return get_particle_arrays(species_number, 0)
+
+
+def get_particle_ux(species_number):
+ '''
+
+ Return a list of numpy arrays containing the particle
+ x momentum on each tile.
+
+ '''
+
+ return get_particle_arrays(species_number, 1)
+
+
+def get_particle_uy(species_number):
+ '''
+
+ Return a list of numpy arrays containing the particle
+ y momentum on each tile.
+
+ '''
+
+ return get_particle_arrays(species_number, 2)
+
+
+def get_particle_uz(species_number):
+ '''
+
+ Return a list of numpy arrays containing the particle
+ z momentum on each tile.
+
+ '''
+
+ return get_particle_arrays(species_number, 3)
+
+
+def get_particle_Ex(species_number):
+ '''
+
+ Return a list of numpy arrays containing the particle
+ x electric field on each tile.
+
+ '''
+
+ return get_particle_arrays(species_number, 4)
+
+
+def get_particle_Ey(species_number):
+ '''
+
+ Return a list of numpy arrays containing the particle
+ y electric field on each tile.
+
+ '''
+
+ return get_particle_arrays(species_number, 5)
+
+
+def get_particle_Ez(species_number):
+ '''
+
+ Return a list of numpy arrays containing the particle
+ z electric field on each tile.
+
+ '''
+
+ return get_particle_arrays(species_number, 6)
+
+
+def get_particle_Bx(species_number):
+ '''
+
+ Return a list of numpy arrays containing the particle
+ x magnetic field on each tile.
+
+ '''
+
+ return get_particle_arrays(species_number, 7)
+
+
+def get_particle_By(species_number):
+ '''
+
+ Return a list of numpy arrays containing the particle
+ y magnetic field on each tile.
+
+ '''
+
+ return get_particle_arrays(species_number, 8)
+
+
+def get_particle_Bz(species_number):
+ '''
+
+ Return a list of numpy arrays containing the particle
+ z magnetic field on each tile.
+
+ '''
+
+ return get_particle_arrays(species_number, 9)
+
+
+def get_mesh_electric_field(level, direction, include_ghosts=True):
+ '''
+
+ This returns a list of numpy arrays containing the mesh electric field
+ data on each grid for this process.
+
+ The data for the numpy arrays are not copied, but share the underlying
+ memory buffer with WarpX. The numpy arrays are fully writeable.
+
+ Parameters
+ ----------
+
+ level : the AMR level to get the data for
+ direction : the component of the data you want
+ include_ghosts : whether to include ghost zones or not
+
+ Returns
+ -------
+
+ A List of numpy arrays.
+
+ '''
+
+ assert(level == 0)
+
+ shapes = ctypes.POINTER(ctypes.c_int)()
+ size = ctypes.c_int(0)
+ ngrow = ctypes.c_int(0)
+ data = libwarpx.warpx_getEfield(level, direction,
+ ctypes.byref(size), ctypes.byref(ngrow),
+ ctypes.byref(shapes))
+ ng = ngrow.value
+ grid_data = []
+ for i in range(size.value):
+ shape=(shapes[3*i+0], shapes[3*i+1], shapes[3*i+2])
+ arr = np.ctypeslib.as_array(data[i], shape)
+ arr.setflags(write=1)
+ if include_ghosts:
+ grid_data.append(arr)
+ else:
+ grid_data.append(arr[ng:-ng,ng:-ng,ng:-ng])
+
+ libc.free(shapes)
+ libc.free(data)
+ return grid_data
+
+
+def get_mesh_magnetic_field(level, direction, include_ghosts=True):
+ '''
+
+ This returns a list of numpy arrays containing the mesh magnetic field
+ data on each grid for this process.
+
+ The data for the numpy arrays are not copied, but share the underlying
+ memory buffer with WarpX. The numpy arrays are fully writeable.
+
+ Parameters
+ ----------
+
+ level : the AMR level to get the data for
+ direction : the component of the data you want
+ include_ghosts : whether to include ghost zones or not
+
+ Returns
+ -------
+
+ A List of numpy arrays.
+
+ '''
+
+ assert(level == 0)
+
+ shapes = ctypes.POINTER(ctypes.c_int)()
+ size = ctypes.c_int(0)
+ ngrow = ctypes.c_int(0)
+ data = libwarpx.warpx_getBfield(level, direction,
+ ctypes.byref(size), ctypes.byref(ngrow),
+ ctypes.byref(shapes))
+ ng = ngrow.value
+ grid_data = []
+ for i in range(size.value):
+ shape=(shapes[3*i+0], shapes[3*i+1], shapes[3*i+2])
+ arr = np.ctypeslib.as_array(data[i], shape)
+ arr.setflags(write=1)
+ if include_ghosts:
+ grid_data.append(arr)
+ else:
+ grid_data.append(arr[ng:-ng,ng:-ng,ng:-ng])
+
+ libc.free(shapes)
+ libc.free(data)
+ return grid_data
+
+
+def get_mesh_current_density(level, direction, include_ghosts=True):
+ '''
+
+ This returns a list of numpy arrays containing the mesh current density
+ data on each grid for this process.
+
+ The data for the numpy arrays are not copied, but share the underlying
+ memory buffer with WarpX. The numpy arrays are fully writeable.
+
+ Parameters
+ ----------
+
+ level : the AMR level to get the data for
+ direction : the component of the data you want
+ include_ghosts : whether to include ghost zones or not
+
+ Returns
+ -------
+
+ A List of numpy arrays.
+
+ '''
+
+ assert(level == 0)
+
+ shapes = ctypes.POINTER(ctypes.c_int)()
+ size = ctypes.c_int(0)
+ ngrow = ctypes.c_int(0)
+ data = libwarpx.warpx_getCurrentDensity(level, direction,
+ ctypes.byref(size), ctypes.byref(ngrow),
+ ctypes.byref(shapes))
+ ng = ngrow.value
+ grid_data = []
+ for i in range(size.value):
+ shape=(shapes[3*i+0], shapes[3*i+1], shapes[3*i+2])
+ arr = np.ctypeslib.as_array(data[i], shape)
+ arr.setflags(write=1)
+ if include_ghosts:
+ grid_data.append(arr)
+ else:
+ grid_data.append(arr[ng:-ng,ng:-ng,ng:-ng])
+
+ libc.free(shapes)
+ libc.free(data)
+ return grid_data
+
+
+# here begins the actual simulation script
+initialize()
+
+# run for ten time steps
+evolve(10)
+
+x = get_particle_x(0)
+y = get_particle_y(0)
+plt.plot(x[0], y[0], '.')
+plt.savefig("particles.png")
+
+# this returns a list of numpy arrays that hold the magnetic field
+# data in the x-direction on each grid for level 0
+grid_data = get_mesh_magnetic_field(0, 0, False)
+
+# plot a slice through the second grid
+plt.clf()
+plt.pcolormesh(grid_data[1][9,:,:])
+plt.savefig("field.png")
+
+finalize()
diff --git a/Exec/Langmuir/python/README b/Exec/Langmuir/python/README
new file mode 100644
index 000000000..e61333279
--- /dev/null
+++ b/Exec/Langmuir/python/README
@@ -0,0 +1,19 @@
+To run in Python mode, do the following steps:
+
+1. In the warpx/Exec/Langmuir directory, type:
+
+ make -j4 USE_PYTHON_MAIN=TRUE
+
+This should result in a library called libwarxp.so.
+
+2. Copy the library into the warpx/Exec/Langmuir/python directory.
+
+This step can be streamlined in the future.
+
+3. Run the Langmuir.py script in warpx/Exec/Langmuir/python, like so:
+
+ python Langmuir.py inputs
+
+This script initializes the simulation and runs it for 10 steps. It also
+gets a numpy array of the particle positions and uses them to make a simple
+plot using matplotlib. \ No newline at end of file
diff --git a/Exec/Langmuir/python/inputs b/Exec/Langmuir/python/inputs
new file mode 100644
index 000000000..bca90c657
--- /dev/null
+++ b/Exec/Langmuir/python/inputs
@@ -0,0 +1,47 @@
+# Maximum number of time steps
+max_step = 10
+
+# number of grid points
+amr.n_cell = 32 32 32
+
+# Maximum allowable size of each subdomain in the problem domain;
+# this is used to decompose the domain for parallel calculations.
+amr.max_grid_size = 16
+
+# Maximum level in hierarchy (for now must be 0, i.e., one level in total)
+amr.max_level = 0
+
+amr.plot_int = 0 # How often to write plotfiles. "<= 0" means no plotfiles.
+
+# Geometry
+geometry.coord_sys = 0 # 0: Cartesian
+geometry.is_periodic = 1 1 1 # Is periodic?
+geometry.prob_lo = -20.e-6 -20.e-6 -20.e-6 # physical domain
+geometry.prob_hi = 20.e-6 20.e-6 20.e-6
+
+# Verbosity
+warpx.verbose = 1
+warpx.do_moving_window = 0
+warpx.moving_window_dir = x
+warpx.moving_window_v = 0.0 # in units of the speed of light
+
+# Algorithms
+algo.current_deposition = 3
+algo.charge_deposition = 0
+algo.field_gathering = 0
+algo.particle_pusher = 0
+
+# CFL
+warpx.cfl = 1.0
+
+particles.nspecies = 1
+
+langmuirwave.particle_xmin = -20.e-6
+langmuirwave.particle_xmax = 0.e-6
+langmuirwave.particle_ymin = -20.e-6
+langmuirwave.particle_ymax = 20.e-6
+langmuirwave.particle_zmin = -20.e-6
+langmuirwave.particle_zmax = 20.e-6
+langmuirwave.num_particles_per_cell = 10
+langmuirwave.n_e = 1.e25 # number of electrons per m^3
+langmuirwave.ux = 0.01 # ux = gamma*beta_x
diff --git a/Exec/Make.WarpX b/Exec/Make.WarpX
index 7d5c6ebec..10179f139 100644
--- a/Exec/Make.WarpX
+++ b/Exec/Make.WarpX
@@ -48,17 +48,19 @@ else
SHARED_OPTION = -shared
endif
-pyinstallswig: libwarpx.a warpxC.i classwrapper.i
- @echo Making and installing python wrapper ...
- # touch warpxC.i to force the rebuilding of the swig interface
- touch warpxC.i
- LDFLAGS="$(LDFLAGS) $(libraries)" CC=$(CXX) CXX=$(CXX) CFLAGS="$(CXXFLAGS) $(CPPFLAGS)" CXXFLAGS="$(CXXFLAGS) $(CPPFLAGS)" DEFINES="$(DEFINES)" python setup.py install --force
- @echo SUCCESS
-
-pybuild: libwarpx.a warpxC.i classwrapper.i
- @echo Making python wrapper ...
- LDFLAGS="$(LDFLAGS) $(libraries)" CC=$(CXX) CXX=$(CXX) CFLAGS="$(CXXFLAGS) $(CPPFLAGS)" CXXFLAGS="$(CXXFLAGS) $(CPPFLAGS)" DEFINES="$(DEFINES)" python setup.py build
- @echo SUCCESS
+all: libwarpx.so
+
+#pyinstallswig: libwarpx.a warpxC.i classwrapper.i
+# @echo Making and installing python wrapper ...
+# # touch warpxC.i to force the rebuilding of the swig interface
+# touch warpxC.i
+# LDFLAGS="$(LDFLAGS) $(libraries)" CC=$(CXX) CXX=$(CXX) CFLAGS="$(CXXFLAGS) $(CPPFLAGS)" CXXFLAGS="$(CXXFLAGS) $(CPPFLAGS)" DEFINES="$(DEFINES)" python setup.py install --force
+# @echo SUCCESS
+#
+#pybuild: libwarpx.a warpxC.i classwrapper.i
+# @echo Making python wrapper ...
+# LDFLAGS="$(LDFLAGS) $(libraries)" CC=$(CXX) CXX=$(CXX) CFLAGS="$(CXXFLAGS) $(CPPFLAGS)" CXXFLAGS="$(CXXFLAGS) $(CPPFLAGS)" DEFINES="$(DEFINES)" python setup.py build
+# @echo SUCCESS
libwarpx.a: $(objForExecs)
@echo Making static library $@ ...
diff --git a/Source/WarpX.H b/Source/WarpX.H
index 47cc271c8..0067361a1 100644
--- a/Source/WarpX.H
+++ b/Source/WarpX.H
@@ -56,9 +56,9 @@ public:
static bool use_laser;
- amrex::MultiFab * getcurrent (int lev, int direction) {return current[lev][direction].get();}
- amrex::MultiFab * getEfield (int lev, int direction) {return Efield[lev][direction].get();}
- amrex::MultiFab * getBfield (int lev, int direction) {return Bfield[lev][direction].get();}
+ const amrex::MultiFab& getcurrent (int lev, int direction) {return *current[lev][direction];}
+ const amrex::MultiFab& getEfield (int lev, int direction) {return *Efield[lev][direction];}
+ const amrex::MultiFab& getBfield (int lev, int direction) {return *Bfield[lev][direction];}
void ComputeDt ();
void MoveWindow ();
diff --git a/Source/WarpXWrappers.cpp b/Source/WarpXWrappers.cpp
index f8a839434..2df4cb549 100644
--- a/Source/WarpXWrappers.cpp
+++ b/Source/WarpXWrappers.cpp
@@ -5,6 +5,26 @@
#include <WarpXWrappers.h>
#include <WarpX.H>
+namespace
+{
+ double** getMultiFabPointers(const amrex::MultiFab& mf, int *num_boxes, int *ngrow, int **shapes)
+ {
+ *ngrow = mf.nGrow();
+ *num_boxes = mf.local_size();
+ *shapes = (int*) malloc(3*(*num_boxes)*sizeof(int));
+ double** data = (double**) malloc((*num_boxes)*sizeof(double*));
+
+ int i = 0;
+ for ( amrex::MFIter mfi(mf, false); mfi.isValid(); ++mfi, ++i ) {
+ data[i] = (double*) mf[mfi].dataPtr();
+ for (int j = 0; j < 3; ++j) {
+ (*shapes)[3*i+j] = mf[mfi].box().length(j);
+ }
+ }
+ return data;
+ }
+}
+
extern "C"
{
void amrex_init (int argc, char* argv[])
@@ -41,7 +61,10 @@ extern "C"
warpx.Evolve(numsteps);
}
- void addNParticles(int speciesnumber, int lenx, double* x, double* y, double* z, double* vx, double* vy, double* vz, int nattr, double* attr, int uniqueparticles)
+ void warpx_addNParticles(int speciesnumber, int lenx,
+ double* x, double* y, double* z,
+ double* vx, double* vy, double* vz,
+ int nattr, double* attr, int uniqueparticles)
{
auto & mypc = WarpX::GetInstance().GetPartContainer();
auto & myspc = mypc.GetParticleContainer(speciesnumber);
@@ -61,5 +84,74 @@ extern "C"
const amrex::Geometry& geom = warpx.Geom(0);
return geom.ProbHi(dir);
}
+
+ long warpx_getNumParticles(int speciesnumber) {
+ auto & mypc = WarpX::GetInstance().GetPartContainer();
+ auto & myspc = mypc.GetParticleContainer(speciesnumber);
+ return myspc.TotalNumberOfParticles();
+ }
+
+ double** warpx_getEfield(int lev, int direction,
+ int *return_size, int *ngrow, int **shapes) {
+ auto & mf = WarpX::GetInstance().getEfield(lev, direction);
+ return getMultiFabPointers(mf, return_size, ngrow, shapes);
+ }
+
+ double** warpx_getBfield(int lev, int direction,
+ int *return_size, int *ngrow, int **shapes) {
+
+ auto & mf = WarpX::GetInstance().getBfield(lev, direction);
+ return getMultiFabPointers(mf, return_size, ngrow, shapes);
+ }
+
+ double** warpx_getCurrentDensity(int lev, int direction,
+ int *return_size, int *ngrow, int **shapes) {
+
+ auto & mf = WarpX::GetInstance().getcurrent(lev, direction);
+ return getMultiFabPointers(mf, return_size, ngrow, shapes);
+ }
+
+ double** warpx_getParticleStructs(int speciesnumber,
+ int* num_tiles, int** particles_per_tile) {
+ auto & mypc = WarpX::GetInstance().GetPartContainer();
+ auto & myspc = mypc.GetParticleContainer(speciesnumber);
+
+ const int level = 0;
+
+ WarpXParIter pti(myspc, level);
+ *num_tiles = pti.numTiles();
+ *particles_per_tile = (int*) malloc(*num_tiles*sizeof(int));
+
+ double** data = (double**) malloc(*num_tiles*sizeof(typename WarpXParticleContainer::ParticleType*));
+ int i = 0;
+ for (WarpXParIter pti(myspc, level); pti.isValid(); ++pti, ++i) {
+ auto& aos = pti.GetArrayOfStructs();
+ data[i] = (double*) aos.data();
+ (*particles_per_tile)[i] = pti.numParticles();
+ }
+ return data;
+ }
+
+ double** warpx_getParticleArrays(int speciesnumber, int comp,
+ int* num_tiles, int** particles_per_tile) {
+ auto & mypc = WarpX::GetInstance().GetPartContainer();
+ auto & myspc = mypc.GetParticleContainer(speciesnumber);
+
+ const int level = 0;
+
+ WarpXParIter pti(myspc, level);
+ *num_tiles = pti.numTiles();
+ *particles_per_tile = (int*) malloc(*num_tiles*sizeof(int));
+
+ double** data = (double**) malloc(*num_tiles*sizeof(double*));
+ int i = 0;
+ for (WarpXParIter pti(myspc, level); pti.isValid(); ++pti, ++i) {
+ auto& soa = pti.GetStructOfArrays();
+ data[i] = (double*) soa[comp].dataPtr();
+ (*particles_per_tile)[i] = pti.numParticles();
+ }
+ return data;
+ }
+
}
diff --git a/Source/WarpXWrappers.h b/Source/WarpXWrappers.h
index 2721ea6bf..28ee28a0c 100644
--- a/Source/WarpXWrappers.h
+++ b/Source/WarpXWrappers.h
@@ -23,12 +23,35 @@ extern "C" {
void warpx_evolve (int numsteps); // -1 means the inputs parameter will be used.
- void addNParticles(int speciesnumber, int lenx, double* x, double* y, double* z, double* vx, double* vy, double* vz, int nattr, double* attr, int uniqueparticles);
+ void warpx_addNParticles(int speciesnumber, int lenx,
+ double* x, double* y, double* z,
+ double* vx, double* vy, double* vz,
+ int nattr, double* attr, int uniqueparticles);
double warpx_getProbLo(int dir);
double warpx_getProbHi(int dir);
+ long warpx_getNumParticles(int speciesnumber);
+
+ double** warpx_getEfield(int lev, int direction,
+ int *return_size, int* ngrow, int **shapes);
+
+ double** warpx_getBfield(int lev, int direction,
+ int *return_size, int* ngrow, int **shapes);
+
+ double** warpx_getCurrentDensity(int lev, int direction,
+ int *return_size, int* ngrow, int **shapes);
+
+ double** warpx_getParticleStructs(int speciesnumber,
+ int* num_tiles, int** particles_per_tile);
+
+ double** warpx_getParticleArrays(int speciesnumber, int comp,
+ int* num_tiles, int** particles_per_tile);
+
+
+
+
#ifdef __cplusplus
}
#endif