Reading binary particle files in Python - vonkarmaninstitute/pantera-pic-dsmc GitHub Wiki

Particles can be saved at defined time steps from a simulation for later analysis or to restart the simulation. Pantera writes one file per processor and per time step. The resulting files are simple to read when Pantera is set to output files in ASCII format, however this is not desirable in terms of space. When binary output is selected, particle files can be read using the following Python code:

# Script to load all particles from Pantera binary dumps
# written by all processors at the specified time step.

import numpy as np
import matplotlib.pyplot as plt
import struct

timestep = 100  # Select the desired time step
numproc = 8     # Select the number of processors used to run the simulation (1 file per proc)

filenames = ['proc_{:05d}_time_{:08d}'.format(i, timestep) for i in range(numproc)]

particles = [] # Particles will be stored in this list

# Read the files.
for filename in filenames:
    with open(filename, mode='rb') as file: # b is important -> binary
        fileContent = file.read()
        print(len(fileContent)/88)
        length =  int(len(fileContent)/88)
        print('Reading ' + str(length) + ' particles from ' + filename)
        # Records are 80 bytes long with 4 bytes padding at beginning and end of each record.
        particles += [struct.unpack(">ddddddddlld", fileContent[i*88+4:i*88+84]) for i in range(length)]


# Now particles is a list of all particles in the files.
# Quantities in each particle are [x, y, z, vx, vy, vz, Erot, Evib, speciesID, cellID, Tadv]
#                                  0  1  2   3   4   5     6     7          8       9    10

# Example: to plot an histogram of the x-velocity of all particles:
plt.figure()
plt.hist([particle[3] for particle in particles], bins = 100)
plt.show(block=False)

Notice that records in binary files may not have the same exact padding depending on the compiler used to compile Pantera. The example we provide should be compatible with the gfortran compiler.

Once particles have been read into the Python list, it is easy to filter them based on spatial coordinates or species ID. The fastest way is to use list comprehension:

# To filter particles with 0 < x < 0.1
onlyinslice  = [particle for particle in particles if (particle[0] > 0 and particle[0] < 0.1)]

# To filter particles with species id = 2
onlyspecies2 = [particle for particle in particles if (particle[8] == 2)]