Counting particle-particle collisions

Submitted by FelixV on Fri, 02/07/2014 - 17:07

Dear all,

i'm simulating granular particles flowing through a pipe. Does LIGGGHTS provide a method to count particle-particle collisions per timestep?

Best Regards
Felix

ckloss's picture

ckloss | Mon, 02/17/2014 - 19:09

Hi Felix,

yes - see compute contact/atom and compute coord/atom for details

Cheers
Christoph

rodolfo | Tue, 04/30/2019 - 17:18

Hello Mr Christoph,
I aplied the compute/atom, compute/atom/gran and the coord/atom to see which one is more suitable to understand my problem. If it is not a problem, could you please answer me some questions?
These commands calculate the contact number (minimium contact time required) or collision (complete impacts, regardless of how long the elements stay in contact for)?
Are these calculation accumulative within the dump file frequency or just store the last time-step?

kalei | Tue, 05/31/2016 - 16:59

I want to count the number of particle-particle collisions over all timesteps.
As far as I can see compute col contact/atom allows to track the number of collisions per timestep. However the output c_col jumps back to zero again as soon as the particles loose contact.
Is there an easy way to access the overall number of collisions per particle over the whole calculation time?

richti83's picture

richti83 | Tue, 05/31/2016 - 20:01

The overall number is not stored. You can modify the compute_contact_atom to sum every contact for each particle in a fix/property/atom in a way like this:
in constructor:

updFix = NULL;
updFix = static_cast(modify->find_fix_id("fppacc"));
if (updFix == NULL) error->all(FLERR,"did not find fppacc");

note: you need to add #include "fix_property_atom.h" in cpp file and to add class FixPropertyAtom* updFix; in compute_contact_atom.h to access the FixPropertyAtom Class
in ComputeContactAtom::compute_peratom() method access the new updFix like this:

...
if (rsq <= radsumsq) {
contact[i] += 1.0;
contact[j] += 1.0;
updFix->vector_atom[i] += 1; //sum contacts
updFix->vector_atom[j] += 1; //sum contacts
}

Now recompile liggghts !!

On scriptlevel you need an additional fix fppacc all property/atom fppacc scalar yes yes yes 0 in front of compute cc all contact/atom because we did not created it on c++ level (which is easiely possible).
To dump the new counter to paraview add f_fppacc to your dump custom command.
dump dmp all custom 1000 post/dump*.liggghts id type x y z vx vy vz fx fy fz omegax omegay omegaz radius c_cc f_fppacc #adds current #of contacts and sum of all contacts to dumpfile

good luck,
Christian.

I'm not an associate of DCS GmbH and not a core developer of LIGGGHTS®
ResearchGate | Contact

kalei | Mon, 06/06/2016 - 17:07

Dear Christian,

I tried to implement particle counting as you described, however I get a compilation error:

../compute_contact_atom.cpp: In constructor ‘LAMMPS_NS::ComputeContactAtom::ComputeContactAtom(LAMMPS_NS::LAMMPS*, int, char**)’:
../compute_contact_atom.cpp:75:21: error: expected ‘<’ before ‘(’ token
updFix = static_cast(modify->find_fix_id("fpacc"));//kl
^
../compute_contact_atom.cpp:75:21: error: expected type-specifier before ‘(’ token
../compute_contact_atom.cpp:75:21: error: expected ‘>’ before ‘(’ token
make[1]: *** [compute_contact_atom.o] Fehler 1

As far I could figure out its a problem related to this line: updFix = static_cast(modify->find_fix_id("fppacc"));

I added the three lines you described in fix_property_atom.h:

ComputeContactAtom::ComputeContactAtom(LAMMPS *lmp, int narg, char **arg) :
Compute(lmp, narg, arg)
{
//NP modified C.K. begin
if (narg < 3) error->all(FLERR,"Illegal compute contact/atom command");
skin = 0.;
if(narg > 3)
{
if (narg < 5) error->all(FLERR,"Illegal compute contact/atom command");
if(strcmp("skin",arg[3])) error->all(FLERR,"Illegal compute contact/atom command, expecting keyword 'skin'");
skin = atof(arg[4]);
}
//NP modified C.K. end
peratom_flag = 1;
size_peratom_cols = 0;
comm_reverse = 1;
nmax = 0;
contact = NULL;
updFix = NULL;//kl
updFix = static_cast(modify->find_fix_id("fpacc"));//kl
if (updFix == NULL) error->all(FLERR,"did not find fppacc");//kl
// error checks
if (!atom->sphere_flag)
error->all(FLERR,"Compute contact/atom requires atom style sphere");
}

Is my error a syntax problem or a problem of initialisation position of updFix?

Luton | Sat, 08/13/2016 - 07:34

Hello Christian,

Is it possible to use this method to count the number of contact for each pair [i][ j] independently.

I tried to imitate your method by adding the following formula to the code instead of the above one :

updFix->array_atom[i][j] += 1; //sum contacts
updFix->array_atom[j][i] += 1; //sum contacts

and for script I changed that to:

fix fppacc all property/atom fppacc vector yes yes yes 0 0

This method sometimes works fine with me and gives me the right counting number and sometimes not. I noticed that changing in "Total # of neighbors " and "Ave neighs/atom " changes my counting output every time. I spent some time trying to understand how this work and how neighbors list are built but I am really started to get quite confused.

Any help with how to count number of contact for each pair independetly either modifying my method or any different method would very appreciated.

Thanks in advance,

Luton

richti83's picture

richti83 | Mon, 06/06/2016 - 21:12

ups, the forum software has eaten the "greater than" and "smaller than" symbols in the code tag block
2nd line should be:
updFix = static_cast SMALLERTHAN FixPropertyAtom*GREATERTHAN(modify->find_fix_id("fppacc"));

SMALLERTHAN <
GRATERTHAN >

I'm not an associate of DCS GmbH and not a core developer of LIGGGHTS®
ResearchGate | Contact

charlie115 | Wed, 06/08/2016 - 22:39

Dear all,

I would like to count the overall number of collisions between different types of particles.
For example, I have particles type 1 and particle type 2, I want to know how many times
during my simulation a 1 particle collides with a 2 particle. Is there a way that I can do this?

Best,
Charlie

richti83's picture

richti83 | Mon, 06/13/2016 - 12:40

Hey Charlie,

just add an if (atom->type[i]!=atom->type[j]) in front of if (rsq <= radsumsq) {
to only count contact of different atom-types.

Best,
Christian.

I'm not an associate of DCS GmbH and not a core developer of LIGGGHTS®
ResearchGate | Contact

charlie115 | Mon, 06/20/2016 - 22:20

Hi Christian,

Thank you for your response. I added the specified code in the specified location in the compute_contact_atom.ccp file in the src folder. However, the results that I am getting are exactly the same as they are when i use compute contact/atom without the added code. Is my location correct, is there something else I need to do?

Sincerely,

Charlie

charlie115 | Tue, 06/21/2016 - 23:16

Christian,

Thank you again for your response. I am new to liggghts and ubuntu 16.04, which I am using to run it. How do I go about recompiling liggghts? If it is simple, or if you could point me in the direction of a source of information for performing this I would appreciate it greatly.

Sincerely,

Charlie

richti83's picture

richti83 | Wed, 06/22/2016 - 18:06

How did you installed liggghts? Apt get or make Ubuntu?
2nd one: CD where you cloned liggghts CD Liggghts public / src Type make clean-all and than make Ubuntu or make Fedora
Than check if you symlinked from usr bin to the correct lmp_whatever executable

Sent from a mobile so some path should be uppercase..

I'm not an associate of DCS GmbH and not a core developer of LIGGGHTS®
ResearchGate | Contact

charlie115 | Wed, 06/22/2016 - 21:32

I installed initially with apt get. I tried recompiling with make ubuntu and got errors. When I recompiled with make fedora, it worked. After I recompiled, the results were still the same as before. Here is what my the altered portion of my compute_contact_atom.cpp file looks like:

if (atom->type[i]!=atom->type[j]) if (rsq <= radsumsq) {
contact[i] += 1.0;
contact[j] += 1.0;
}
}
}
}

The following is my liggghts file:

#Mixing Simulation

#General setup for all simulations
atom_style granular
#atom_modify sort
boundary p p p
newton off
communicate single vel yes
units si
region nice_box block 0 0.33 0 0.2 0 0.2
create_box 3 nice_box

group sub type 1
group bub type 2

neighbor 0.012 bin
neigh_modify delay 0 check yes

#Particle properties
fix m1 all property/global youngsModulus peratomtype 8.e6 8.e6 8.e6
fix m2 all property/global poissonsRatio peratomtype 0.3 0.3 0.3
fix m3 all property/global coefficientRestitution peratomtypepair 3 0.81 0.81 0.81 0.81 0.81 0.81 0.81 0.81 0.81
fix m4 all property/global coefficientFriction peratomtypepair 3 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4
fix m5 all property/global coefficientRollingFriction peratomtypepair 3 0.01 0.01 0.01 0.01 0.01 0.01 0.01 0.01 0.01

#Contact model specification
pair_style gran model hertz tangential history
pair_coeff * *

timestep 0.000001
fix gravi all gravity 9.81 vector 0.0 0.0 -1.0

#Insert Cylinder
fix cad all mesh/surface file meshes/hollow_cylinder.stl type 3

#Geometry specification
fix caddy all wall/gran model hertz tangential history mesh n_meshes 1 meshes cad

#Create insertion regions
region bblock1 block 0.001 0.299 0.05 0.16 0.1025 0.2125

#Specify types of particles
fix atomtype1 sub particletemplate/sphere 10000 atom_type 1 density constant 2650 radius constant 0.004

fix atomtype2 bub particletemplate/sphere 10212 atom_type 2 density constant 2650 radius gaussian number 0.01 0.00333

#Specify particle distributions
fix pdd1 all particledistribution/discrete 1296 2 atomtype1 0.3 atomtype2 0.7

#Insert particles

fix ins1 all insert/rate/region seed 100001 distributiontemplate pdd1 nparticles 1260 particlerate 500000 insert_every 500 overlapcheck yes region bblock1 ntry_mc 10000

#Perform NVE integration
fix integr all nve/sphere

#Output settings
compute atomtrack all contact/atom

dump myDump all custom 1000 post/dump*.myforce id type x y z fx
dump dmpvtk all custom/vtk 200 post/dump*.myforce.vtk id type vx fx
dump collide all custom 200 CSVs/dump*.doll.csv c_atomtrack

run 250000

Is there something in either the compute_contact file or my liggghts file that is causing my results to track all particle collisions instead of just those between atomtype1 and atomtype2? Thank you for your continued patience.

richti83's picture

richti83 | Thu, 06/23/2016 - 06:35

I guess you are still starting the package liggghts version via global /usr/bin and not your self compiled one
You can see a build Date of LIGGGHTS in the first line of log
To identify your spezial Version modify liggghts_branch_version.txt
Remove all instances you get from whereis liggghts and create a new symlink from your spezial Version in /usr/bin

I'm not an associate of DCS GmbH and not a core developer of LIGGGHTS®
ResearchGate | Contact

charlie115 | Wed, 06/29/2016 - 16:40

Christian, thank you very much! I followed the instructions above and I am now able to track the collisions between different species of particles.

-Charlie

charlie115 | Wed, 06/29/2016 - 17:29

I have one more question as it pertains to counting the collisions between different species of particles, and I apologize for
being a bother and for my general lack of knowledge as it pertains to c++, liggghts, and ubuntu. I would like my output to give me
discrete values for the collisions between species. So if I have 3 particle types, I would like to know how many collisions between
particle type 1 and particle type 2, how many between particle type 1 and particle type 3, and how many between particle type 2
and particle type 3. Is there an easy way to implement this in the compute_contact_atom.cpp file so that when I dump to a csv file
I get a few columns that count the collisions in this manner rather than a single column with a sum of all inter-species collisions?

-Charles

richti83's picture

richti83 | Thu, 06/30/2016 - 10:21

easy way: duplicate ComputeContactAtom 3-time, rename to compute_contact_atom12.h and compute_contact_atom12.cpp (also 13,23)
in cpp and h file change all class-names (ComputeContactAtom::) to ComputeContactAtom12 ComputeContactAtom13 ComputeContactAtom23

change in every header file line ComputeStyle(contact/atom,ComputeContactAtom) to ComputeStyle(contact/atom12,ComputeContactAtom12)
change in cpp file line if (atom->type[i]!=atom->type[j]) to if (((atom->type[i]==0) && (atom->type[j]==1)) or ((atom->type[i]==1) && (atom->type[j]==0))) { //1-2 or 2-1, internal type starts at 0 !
recompile,
use compute contact/atom12,contact/atom13,contact/atom23 in your inputskript.

better, but more complicated: introduce two new parameters to original compute contact/atom to get wanted types from inputskript (sry, its to hard to explain how one would do this bc. you need to change the code at some other places in the cpp file)

good luck

I'm not an associate of DCS GmbH and not a core developer of LIGGGHTS®
ResearchGate | Contact

charlie115 | Thu, 06/30/2016 - 22:00

I am looking to run a simulation with >1000 particle types, and I also need to track the collisions between particles of the same species as well (particle type 1 with particle type 1, particle type 2 with particle type 2, etc.), I think the easy method will be too cumbersome to work for me. Does the complicated way use loops? If that is the case and it isn't too much work, can you show me how to implement it?

richti83's picture

richti83 | Mon, 07/04/2016 - 09:25

Have a look in compute_rigid.cpp line 58-60, there the input skript value of "property" is read in, you have to adapt this logic to store your pair-combinations in two new private variables (let's call them type0_ and type1_)
Than write if (((atom->type[i]==type0_) && (atom->type[j]==type1_)) or ((atom->type[i]==type1_) && (atom->type[j]==type0_))) as condition.
Than you can use a loop in your inputskript:

variable type1 loop 1 1000
label type1loop
variable type2 loop 1 1000
label type2loop
compute ${type1}_${type2} contact/atom ${type1} ${type2}
next type2
jump SELF type2loop
next type1
jump SELF type1loop

I'm not an associate of DCS GmbH and not a core developer of LIGGGHTS®
ResearchGate | Contact

cs222 | Thu, 03/30/2017 - 19:40

The changes do work! But I a confused what each of the output stands for ? Is c_cc the collision count and f_fppacc is the collision frequency

Thank you!

Chai

richti83's picture

richti83 | Mon, 04/03/2017 - 08:24

Hi Chai,

no c_cc is compute collision count, fppacc is fix-property-particle-all-collision count, the prefix c_ and f_ is used in variable.cpp to check if the input is a fix or compute. The compute holds the collision for every atom at one timestep, while the fix stores the sum over all timesteps for all particles.

best,
Christian.

I'm not an associate of DCS GmbH and not a core developer of LIGGGHTS®
ResearchGate | Contact

cs222 | Tue, 04/04/2017 - 23:41

Hi Christian,
Thank you for your reply. This does help me out with my calculations.
I would also like to know if we could come to know include the each pairwise collision data? Can we just introduce new variables to store in the source code, where we computed the collisions?

Thank you.

Regards
Chai

NvNR | Thu, 01/31/2019 - 10:51

Hello

Is there a similar way to count the particle-wall collision also?

Thanks in advance

Regards
Naveen R

NvNR

richti83's picture

richti83 | Wed, 02/06/2019 - 08:32

No. But have a look in mesh_module_stress.cpp in method add_particle_contribution(), it is easy to add an counter there with reference to previously introduced updFix = static_cast(modify->find_fix_id("fppacc"));
If you want to dump the sum of particle contacts of a mesh you would need a new mesh->prop which holds the counter. (have a look how wear is stored and dumped for mesh elements).

I'm not an associate of DCS GmbH and not a core developer of LIGGGHTS®
ResearchGate | Contact

NvNR | Sun, 03/31/2019 - 08:41

I did the mentioned changes in compute_contact_atom.cpp file. I did the following changes in compute_contact_atom.cpp

1. included the: #include "fix_property_atom.h"
2. defined the class: class FixPropertyAtom* updFix;
3. Added the three lines as
if(narg > 3)
{
if (narg < 5) error->all(FLERR,"Illegal compute contact/atom command");
if(strcmp("skin",arg[3])) error->all(FLERR,"Illegal compute contact/atom command, expecting keyword 'skin'");
skin = atof(arg[4]);
}

peratom_flag = 1;
size_peratom_cols = 0;
comm_reverse = 1;

nmax = 0;
contact = NULL;

updFix = NULL;
updFix = static_cast (modify->find_fix_id("fppacc"));
if (updFix == NULL) error->all(FLERR,"did not find fppacc");

4. delx = xtmp - x[j][0];
dely = ytmp - x[j][1];
delz = ztmp - x[j][2];
rsq = delx*delx + dely*dely + delz*delz;
radsum = radi + radius[j] + skin;
radsumsq = radsum*radsum;
if (rsq <= radsumsq) {
contact[i] += 1.0;
contact[j] += 1.0;
updFix->vector_atom[i] += 1; //sum of contacts
updFix->vector_atom[j] += 1; //sum of contacts
}

And following changes in file:
1. added:
fix fppacc all property/atom fppacc scalar yes yes yes 0
compute cc all contact/atom
2. dumping as:
dump dmp all custom 500 ../DEM/post1/dumpres*.liggghts id type type x y z c_2 ix iy iz vx vy vz fx fy fz omegax omegay omegaz radius f_fppacc c_cc

But I am getting different results everytime as I change the dumping interval time from 500 to 200 and so on. I am getting higher and unpractical values as I am decreasing the dumping interval.

Please suggest where did I make the mistake.

Thanks in advance.

Regards
Naveen R

NvNR