We provide a flexible data structure to store data on a per-particle basis. The number of elements per particle and the data type are specified.

Particle properties are stored within `ParticleDat` containers. These can be considered as two dimensional matrices with each row storing data for a particle. For example the velocities of \(N\) particles would be stored within a \(N\) X \(3\) ParticleDat.

```
from ppmd import *
ParticleDat = data.ParticleDat
vel = ParticleDat(npart=N, ncomp=3)
```

ParticleDats may contain ctypes.c_double, ctypes.c_int and ctypes.c_long data. To specifiy a data type other than the default ctypes.c_double the `dtype` keyword should be used.

```
import ctypes
num_neighbours = ParticleDat(npart=N, ncomp=1, dtype=ctypes.c_int)
```

These data structures are specialised wrappers around Numpy objects and the underlying numpy data may be accessed by using the standard PythonNumpy indexing. For example to initialise the `vel` ParticleDat above with values drawn from a standard normal distribution we may do the following.

```
import numpy as np
vel[:,:] = np.random.normal(size=(N,3))
```

To create a `CUDA` ParticleDat use the ParticleDat from `ppmd.cuda`:

```
from ppmd.cuda import *
ParticleDat = cuda_data.ParticleDat
vel = ParticleDat(npart=N, ncomp=3)
vel[:,:] = np.random.normal(size=(N,3))
```

The code above creates a ParticleDat on a CUDA device and assigns the values drawn from a standard normal distribution. The copying of data between the host and the CUDA device is handled automatically by the framework.