Skip to content

ParticleGroup

Raul edited this page Sep 11, 2020 · 6 revisions

Most UAMMD modules can be instructed to act only on a subset of particles, this is handled by creating a ParticleGroup.
A group can contain all particles, no particles or anything in between.

Creation

A ParticleGroup is created via a selector (that checks every particle following a certain inclusion rule) or by directly providing a list of ids.

  //By default a ParticleGroup will contain all particles
  auto allParticlesGroup = make_shared<ParticleGroup>(pd, sys, "AGroupWithAllParticles");

  //Different selectors offer different criteria
  //In this case, it will result in a group with particles whose ID lies between 4 and 8
  particle_selector::IDRange selector(4,8);
  auto aGroupWithSomeIDs = make_shared<ParticleGroup>(selector, pd, sys, "SomeName");

  //Equivalently a list of particle IDs can be provided directly
  auto idrange = std::vector<int>(4); std::iota(idrange.begin(), idrange.end(), 4);
  auto anEquivalentGroup = make_shared<ParticleGroup>(idrange.begin(), idrange.end(), pd, sys, "SomeOtherName");

  //A group containing all particles of a certain type (or types) (type being the value of pos.w)
  auto groupOfParticlesWithType0 = make_shared<ParticleGroup>(particle_selector::Type(0), pd, sys, "Type 0 particles");
  auto groupOfParticlesWithType0And3 = make_shared<ParticleGroup>(particle_selector::Type({0,3}), pd, sys, "Type 0 and type 3 particles");

  //A group of 10 random particles
  std::vector<int> randomlyOrderedIds(numberParticles); 
  std::iota(randomlyOrderedIds.begin(), randomlyOrderedIds.end(), 0);
  std::shuffle(randomlyOrderedIds.begin(), randomlyOrderedIds.end(), std::mt19937{std::random_device{}()});
  randomlyOrderedIds.resize(10);
  auto groupOf10RandomParticles = make_shared<ParticleGroup>(randomlyOrderedIds.begin(), randomlyOrderedIds.end(), pd, sys, "10 Random Particles");

Instructions on how to create a selector are located in ParticleGroup.cuh but the easiest way to create a group with a custom criteria is to just pass a list of particle ids as in the examples.

Usage with UAMMD modules

When it makes sense, UAMMD modules will have an optional ParticleGroup argument at creation. See for example PairForces[2].

General usage

ParticleGroup will keep track of its particles and will always provide their up to date global indices.

  //You can request an iterator with the current indices of the particles in a group with:
  auto indicesOfParticlesInGroup = pg->getIndexIterator(access::location::gpu);

  //Or get a plain array with the indices directly, if it exists.
  auto rawMemoryPtrOfIndices = pg->getIndicesRawPtr(access::location::gpu); //or cpu, it will be nullptr if all (or none) particles are in the group

  //You can also request an iterator that will read a ParticleData array using the group indices directly.
  //This allows to write generic code that will work both with a group or with a ParticleData array.
  auto allPositions = pd->getPos(access::location::gpu, access::mode::read);
  auto IteratorWithPositionsInGroup = pg->getPropertyIterator(allPositions);
  ...
  //In device code
  real4 positionOfFirstParticleInGroup = IteratorWithPositionsInGroup[0];

As a general rule, when writing UAMMD code, it is wise to access particle properties using ParticleGroups instead of ParticleData directly. A default group contains all particles, it is a special case and incurs no overhead (besides maybe a couple of registers) when created or used.

References

[1] https://github.com/RaulPPelaez/UAMMD/wiki/ParticleData
[2] https://github.com/RaulPPelaez/UAMMD/wiki/Pair-Forces









Clone this wiki locally