glotzerlab / hoomd-blue

Molecular dynamics and Monte Carlo soft matter simulation on GPUs.
http://glotzerlab.engin.umich.edu/hoomd-blue
BSD 3-Clause "New" or "Revised" License
335 stars 130 forks source link

`sim.state.cpu_local_snapshot` changing particle types randomly #1592

Closed MasterChief1O7 closed 1 year ago

MasterChief1O7 commented 1 year ago

Description

When using sim.state.cpu_local_snapshot, it is changing particle typeid of random particles rather than of what I have defined. For example in the test script, it should change particle typeid of first 150 particles to 1 (from 0) but it changed randomly. However, if I use sim.state.get_snapshot method it works fine, as expected. But, if I use sim.state.get_snapshot method at least once before using sim.state.cpu_local_snapshot, it also starts working as expected!

I tried it with both CPU and GPU as device but the problem remains the same. And the output are consistent on multiple runs, i.e. which particles get modified typeid is also fixed.

Also I tried sim.state.gpu_local_snapshot but I'm always getting the error: TypeError: 'HOOMDGPUArray' object does not support item assignment, which I guess could be a different and unrelated issue?

Script

import hoomd
import numpy
import gsd.hoomd
import math
import itertools

print(hoomd.version.version)

m = 4
N_particles = 4 * m**3

spacing = 1.3
K = math.ceil(N_particles**(1 / 3))
L = K * spacing
x = numpy.linspace(-L / 2, L / 2, K, endpoint=False)
position = list(itertools.product(x, repeat=3))

snapshot = gsd.hoomd.Snapshot()
snapshot.particles.N = N_particles
snapshot.particles.position = position[0:N_particles]
snapshot.particles.typeid = [0] * N_particles
snapshot.configuration.box = [L, L, L, 0, 0, 0]

snapshot.particles.types = ['A','B']

with gsd.hoomd.open(name='lattice.gsd', mode='wb') as f:
    f.append(snapshot)

gpu = hoomd.device.GPU()
sim = hoomd.Simulation(device=gpu, seed=1)
sim.create_state_from_gsd(filename='lattice.gsd')

integrator = hoomd.md.Integrator(dt=0.005)
cell = hoomd.md.nlist.Cell(buffer=0.4)
lj = hoomd.md.pair.LJ(nlist=cell)
lj.params[('A', 'A')] = dict(epsilon=1, sigma=1)
lj.r_cut[('A', 'A')] = 2.5
lj.params[('A', 'B')] = dict(epsilon=1, sigma=1)
lj.r_cut[('A', 'B')] = 2.5
lj.params[('B', 'B')] = dict(epsilon=1, sigma=1)
lj.r_cut[('B', 'B')] = 2.5

integrator.forces.append(lj)
nvt = hoomd.md.methods.NVT(kT=1.5, filter=hoomd.filter.All(), tau=1.0)
integrator.methods.append(nvt)

sim.operations.integrator = integrator
sim.state.thermalize_particle_momenta(filter=hoomd.filter.All(), kT=1.5)
thermodynamic_properties = hoomd.md.compute.ThermodynamicQuantities(
    filter=hoomd.filter.All())

sim.operations.computes.append(thermodynamic_properties)
sim.run(100)

snapshot = sim.state.get_snapshot()
print("particle typesid at the start:\n")
print(snapshot.particles.typeid)
print("\n")

N = 150
print(f"changing first {N} particles::\n")

for i in range(N):
    with sim.state.cpu_local_snapshot as data:
        data.particles.typeid[i] = 1
snapshot = sim.state.get_snapshot()
print("particle typesid after using sim.state.cpu_local_snapshot:\n")
print(snapshot.particles.typeid)
print("\n")

for i in range(N):
    data = sim.state.get_snapshot()
    data.particles.typeid[i] = 0
    sim.state.set_snapshot(data)
snapshot = sim.state.get_snapshot()
print("particle typesid after using sim.state.get_snapshot:\n")
print(snapshot.particles.typeid)

Input files

No response

Output

This is what I am getting at the moment for snapshot.particles.typeid:
[1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 1 1 1 0 0
 0 0 1 1 1 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
 1 1 1 0 0 0 0 1 1 1 0 0 0 0 1 1 1 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 1 1 1 0 0 0 0 1 1 1 0 0 0 0 1 1 1 1
 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 1 1 1 0 0 0
 0 1 1 1 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]

Expected output

I'd expect the particles typeid (snapshot.particles.typeid) should be after using sim.state.cpu_local_snapshot as in the test script:

[1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]

Platform

GPU, Linux

Installation method

Conda package

HOOMD-blue version

3.7.0

Python version

3.9.16

joaander commented 1 year ago

This is not a bug, it is documented behavior. The local snapshot provides zero-copy access to internal memory buffers which are 1) Split across domains and 2) sorted on a space filling curve (not randomly) to improve performance.