Help Needed with Computing Global Pressure and Stress Tensor from LAMMPS Dump File

Hello Matsci community,

I al writing here since it is more a materials/algorithm than LAMMPS question, though related to LAMMPS and MD.

I am currently working on calculating the global pressure (similar to the pressure option in the LAMMPS thermo output) and stress tensor (specifically, the stress/atom tensor) using a LAMMPS dump file. I am not using the compute stress/atom from LAMMPS since the pair style I am using does not compute the stress/atom (RANN).
The dump file includes the following columns: ‘id’, ‘type’, ‘x’, ‘y’, ‘z’, ‘vx’, ‘vy’, ‘vz’, ‘fx’, ‘fy’, ‘fz’.

I started with computing the global pressure, as it is easier to compare with the pressure output in the LAMMPS log, but I’ve run into an issue. I’m using the virial stress definitions from the paper “General formulation of pressure and stress tensor for arbitrary many-body interaction potentials under periodic boundary conditions” and the LAMMPS documentation. The virial contribution I am using is: Capture d’écran de 2025-01-13 12-21-19.

However, when I calculate the global pressure, the result is significantly lower than expected. For example, my system is equilibrated to 50 GPa (using Fe as a test case), but the calculated global pressure is around 2 GPa. I suspect I may be missing something important, either in terms of what can be computed from the dump file data, or there may be an arithmetic step I’m overlooking. Unfortunately, I believe this aspect isn’t discussed elsewhere?.
Bellow is a snippet of the code I am using:

# Conversion of columns so the pressure unit is GPa
df.x *=angstrom_to_meter
df.y *=angstrom_to_meter
df.z *=angstrom_to_meter

df.vx *=angstrom_ps_to_m_s
df.vy *=angstrom_ps_to_m_s
df.vz *=angstrom_ps_to_m_s

df.fx *= eV_to_J/angstrom_to_meter
df.fy *= eV_to_J/angstrom_to_meter
df.fz *= eV_to_J/angstrom_to_meter

#################### Calculations
# Kinetic energy tensor
velocities = df[['vx', 'vy', 'vz']].to_numpy()
kinetic_tensor = np.einsum('ij,ik->jk', velocities, velocities) * mass / volume

# Compute virial contribution
positions = df[['x', 'y', 'z']].to_numpy()
forces = df[['fx', 'fy', 'fz']].to_numpy()
virial_tensor = np.einsum('ij,ik->jk', positions, forces) / volume

# Total stress tensor
total_tensor = kinetic_tensor + virial_tensor

# Pressure (GPa)
pressure_gpa = -np.trace(total_tensor) / 3 / 1e9

# Print results
print("Kinetic Tensor (GPa):")
print(kinetic_tensor/ 1e9)
print("Virial Tensor (GPa):")
print(virial_tensor/ 1e9)
print("Total Tensor (GPa):")
print(total_tensor/ 1e9)
print("Pressure (GPa):", pressure_gpa)

If anyone has experience with this or can offer guidance on the correct procedure for calculating global pressure and stress/atom from LAMMPS dump, I would greatly appreciate your input.

Thank you in advance for any advice or suggestions!

Best regards,

Marco

1 Like

Perhaps @athomps can help clarify.

The issue lies with the periodic boundaries. This is discussed in detail in the paper that you mentioned. On the doc page, the second sum is over N’, the total number of local and ghost atoms. The doc page also says “Only when running … without periodic boundary conditions is N’=N.” If you turn off periodic boundaries, your script should match the LAMMPS output.