# Particle Data to and from a Grid

In a particle in cell code such as Warp, it is common to need to retrieve data from an input grid to the particle positions (examples: applied field data from a rf cavity or magnetic design code) or to need to deposit particle data on a grid (example: to calculate fluid moments of the particle phase-space distribution). It is common to call retrieval of data from a grid to particle locations as "weighting" and deposition of particle data to a grid as "binning." Fortunately, Warp has numerous efficient tools to aid the user in these common tasks. Routines are efficiently written in fast complied code in dtop.F and linked to the python interpreter where they can be called with broad flexibility for the specific tasks needed by the user. These tools are grouped into several categories covered below: "getting" data from a grid to particle positions, "setting" particle position data on a grid, "depositing" particle quantities on a grid based on particle positions, and special purpose routines. Many of these routines have variants for 1d, 2d, and 3d geometry with some 2d routines being specifically designed for use in r-z cylindrical geometry. Consistent with the usual Warp structure, grids/meshes are assumed to be uniformly spaced and interpolations of data retrievals or depositions are low-order "linear" (linear, area, or volume in 1d, 2d, and 3d) methods, or in some cases, lowest-order nearest grid point methods. Users can examine Fortran code in dtop.F for details of specific routines.

**Getting Data from a Grid to Particle Positions**

Routines to "get" or "weight" gridded data to the particle coordinates using linear interpolation from the grid nodes to the particle coordinates include:

getgrid1d(...)

getgrid2d(...)

getgrid3d(...)

for 1d, 2d, and 3d cases using linear (linear, area, and volume in 1d, 2d, and 3d) interpolation. Arguments of the routines are not shown. For getgrid1d(), they are:

getgrid1d(np:integer,x(np):real,z(np):real,

nx:integer,grid(0:nx):real,xmin:real,xmax:real)

and arguments for getgrid2d() and getgrid3d() are analogously extended to higher dimensions for uniform 2d and 3d grids and can be found using doc(). For getgrid1d(), arguments correspond to

np number of particles

x(np) array of particle x-coordinates that grid data will be retrieved from

z(np) array of interpolated values grid data to particle positions

nx upper grid index of data

grid(0:nx) array of gridded data values

xmin min x-value of gridded data corresponding to grid(0)

xmax max x-value of gridded data corresponding to grid(nx)

Note that the x-grid values are *not* input because the grid is assumed to be uniformly spaced from x=xmin (grid node n=0) to x=xmax (grid node n=nx). Linearly interpolated z-data is passed to the python interpreter via the argument list (linked to a subroutine call complied code).

Nearest grid point variants of the linear interpolation getgridxd() routines are also available in 1d, 2d, and 3d versions:

getgridngp1d(...)

getgridngp2d(...)

getgridngp3d(...)

Arguments are the same as the corresponding linear interpolation routines.

The "getgrid" routines are commonly used for tasks such as interpolating applied field data exported from some other code into Warp (see Saving/Retrieving Warp Data in External Files) to the particle positions or in constructing various diagnostic measures.

**Setting Particle Position Data on a Grid**

Routines to deposit (bin) particles onto a node centered grid using linear interpolation include:

setgrid1d(...)

setgrid2d(...)

setgrid3d(...)

for 1d, 2d, and 3d cases using linear (linear, area, and volume in 1d, 2d, and 3d) interpolation. Arguments of the routines are not shown. For setgrid1d(), they are:

setgrid1d(np:integer,x(np):real,nx:integer,grid(0:nx):real,xmin:real,xmax:real)

and arguments for setgrid2d() and setgrid3d() are analogously extended to higher dimensions for uniform 2d and 3d grids and can be found using doc(). For setgrid1d(), arguments correspond to

np number of particles

x(np) array of particle positions to deposit on grid

nx upper grid index of deposition x-grid

grid(0:nx) array of deposition grid particle counts

xmin min x-value of deposition grid corresponding to grid(0)

xmax max x-value of deposition grid corresponding to grid(nx)

Note that the x-grid values of the deposition grid are *not* input because the grid is assumed to be uniformly spaced from x=xmin [corresponding to count grid(0)] to x=xmax [corresponding to count grid(nx)]. Linearly interpolated counts in grid are passed to the python interpreter via the argument list (linked to a subroutine call complied code). grid() is *not* zeroed when the routine is called so statistics can be accumulated over multiple passes. This also means the user must use caution to initialize (zero) the grid before calling, when appropriate.

There is also a 1d nearest grid point version of setgrid1d():

setgrid1dngp(...)

with identical arguments to setgrid1d(). 1d and 2d versions of the setgrid routines that deposit particle weights instead of particle counts also exist:

setgrid1dw(...)

setgrid2dw(...)

The argument list for setgrid1dw() is:

setgrid1dw(np:integer,x(np):real,w(np):real,

nx:integer,grid(0:nx):real,xmin:real,xmax:real)

where arguments are the same as setgrid1d() with the addition of

w(np) array of particle weights

which are deposited on the x-grid and returned in grid():nx) instead of counts of x(np). The deposition is based on the locations of x(np) on the x-grid. Of course, quantities other than the particle weights can be deposited.

Special versions of setgrid2d() and setgrid2dw() also exist:

setgrid2dcylindrical(...)

setgrid2dcylindricalw(...)

The arguments can be found with doc() and are analogous to those in other setgrid() routines. However, in this case, depositions are modified to be appropriate for r-z cylindrical geometry to account for radial Jacobian factors.

**Depositing Particle Quantities on a Grid Based on Particle Positions**

Routines to deposit (bin) data associated with particles onto a node centered grid based on the particle coordinate location on the coordinate grid include:

deposgrid1d(...)

deposgrid2d(...)

deposgrid3d(...)

for 1d, 2d, and 3d cases using linear (linear, area, and volume in 1d, 2d, and 3d) interpolation. Arguments of the routines are not shown. For getgrid1d(), they are:

deposgrid1d(itask:integer,np:integer,x(np):real,z(np):real,

nx:integer,grid(0:nx):real,gridcount(0:nx),xmin:real,xmax:real)

and arguments for deposgrid2d() and deposgrid3d() are analogously extended to higher dimensions for uniform 2d and 3d grids and can be found using doc(). For deposgrid1d(), arguments correspond to

itask integer control flag

0: grid is set to zero before accumulation and grid divided by gridcount

nonzero: grid is not reset

np number of particles

x(np) array of particle positions

z(np) array of particle quantities to deposit based on x(np) locations on x-grid

nx upper grid index of deposition x-grid

grid(0:nx) array of z deposition values on x-grid

gridcount(0:nx) array of x particle deposition counts on x-grid

xmin min x-value of deposition x-grid

xmax max x-value of deposition x-grid

If itask is passed as zero, grid values returned will be average values. itask passed as nonzero allows the routine to be used in multiple passes to accumulate statistics. Note that the x-grid values of the deposition grid are *not* input because the grid is assumed to be uniformly spaced from x=xmin [corresponding to deposition value grid(0)] to x=xmax [corresponding to deposition value grid(nx)]. Linearly interpolated counts in grid are passed to the python interpreter via the argument list (linked to a subroutine call complied code). Note that the routines setgrid1dw() and deposgrid1d() provide similar functionality with the addition of the itask argument in deposgrid1d() making it more flexible.

Nearest grid point weighting versions of deposgrid1d() and deposgrid2d() are defined:

deposgrid1dngp(...)

deposgrid2dngp(...)

Use of these are analogous to the corresponding linear weighting versions. Also, versions of deposgrid1d() and deposgrid2d() including individual particle weights in the z deposition are defined:

deposgrid1dw(...)

deposgrid2dw(...)

Arguments of deposgrid1dw() are the same as for deposgrid1d() with the addition of

w(np) array of particle weights

deposgrid1dw() essentially deposits z*w rather than z.

**Special Purpose Routines**

A common utility need is to deposit data from one grid to another. Warp includes a routine for this purpose based on linear (volume) interpolation:

gridtogrid3d(nxin:integer,nyin:integer,nzin:integer,

xminin:real,xmaxin:real,yminin:real,ymaxin:real,zminin:real,zmaxin:real

gridin(0:nxin,0:nyin,0:nzin):real,

nxout:integer,nyout:integer,nzout:integer,

xminout:real,xmaxout:real,yminout:real,ymaxout:real,

zminout:real,zmaxout:real

gridout(0:nxout,0:nyout,0:nzout):real)

Arguments correspond to:

nxin input number x-nodes

xminin input min x-value of mesh

xmaxin input max x-value of mesh

gridin(0:nxin,0:nyin,0:nzin) input 3d grid data

nxout output number of x-nodes

xminout output min x-value of mesh

xmaxout output max x-value of mesh

gridout(0:nxout,0:nyout,0:nzout) output 3d grid data

Here we have suppressed argument definitions in y and z that have obvious generalization from x. Note this routine can be used for 3d and 1d arrays if the corresponding n values are set to zero.