the correct use of collider.avoidSelfInteractionMask ?

Asked by Luc OGER on 2019-07-24

Hello,

 I am trying to setup properly the possible interaction between different group of sphere: some can interact with other, some cannot interact with themselves

here the basic code
# basic simulation showing sphere falling ball gravity,
# bouncing against another sphere representing the support

# DATA COMPONENTS

# add 2 particles to the simulation
# they the default material (utils.defaultMat)
mask1=0b10
mask2=0b01
mask3=0b11

O.bodies.append([
 # fixed: particle's positionin space will not change (support)
 sphere(center=(0,0,0),radius=.5,fixed=True,mask=mask1,color=(0,0,1)), #fond immobile
 sphere(center=(0,0,2),radius=.5,fixed=False,mask=mask2,color=(0,1,0)),
        # these particles are free, subject to dynamics
 sphere(center=(0,0,4),radius=.5,fixed=False,mask=mask3,color=(1,0,0)),
 sphere(center=(0,0,6),radius=.5,fixed=False,mask=mask3,color=(1,0,0)),
        # fixed: particle's positionin space will not change (support)
        sphere(center=(3,0,0),radius=.5,fixed=True,mask=mask1,color=(0,0,1)), #fond immobile
        sphere(center=(3,0,2),radius=.5,fixed=False,mask=mask3,color=(1,0,0)),
        # these particles are free, subject to dynamics
        sphere(center=(3,0,4),radius=.5,fixed=False,mask=mask2,color=(0,1,0)),
        sphere(center=(3,0,6),radius=.5,fixed=False,mask=mask2,color=(0,1,0)),
        # fixed: particle's positionin space will not change (support)
        sphere(center=(6,0,0),radius=.5,fixed=True,mask=mask3,color=(1,0,0)), #fond immobile
        sphere(center=(6,0,2),radius=.5,fixed=False,mask=mask1,color=(0,0,1)),
        # these particles are free, subject to dynamics
        sphere(center=(6,0,4),radius=.5,fixed=False,mask=mask3,color=(1,0,0)),
        sphere(center=(6,0,6),radius=.5,fixed=False,mask=mask2,color=(0,1,0)),
        # fixed: particle's positionin space will not change (support)
        sphere(center=(9,0,0),radius=.5,fixed=True,mask=mask2,color=(0,1,0)), #fond immobile
        sphere(center=(9,0,2),radius=.5,fixed=False,mask=mask1,color=(0,0,1)),
        # these particles are free, subject to dynamics
        sphere(center=(9,0,4),radius=.5,fixed=False,mask=mask3,color=(1,0,0)),
        sphere(center=(9,0,6),radius=.5,fixed=False,mask=mask2,color=(0,1,0)),
        # fixed: particle's positionin space will not change (support)
        sphere(center=(12,0,0),radius=.5,fixed=True,mask=mask1,color=(0,0,1)), #fond immobile
        sphere(center=(12,0,2),radius=.5,fixed=False,mask=mask1,color=(0,0,1)),
        # these particles are free, subject to dynamics
        sphere(center=(12,0,4),radius=.5,fixed=False,mask=mask3,color=(1,0,0)),
        sphere(center=(12,0,6),radius=.5,fixed=False,mask=mask2,color=(0,1,0)),

])

# FUNCTIONAL COMPONENTS
collider.avoidSelfInteractionMask = 0b00

# simulation loop -- see presentation for the explanation
O.engines=[
 ForceResetter(),
 InsertionSortCollider([Bo1_Sphere_Aabb()]),
 InteractionLoop(
  [Ig2_Sphere_Sphere_ScGeom()], # collision geometry
  [Ip2_FrictMat_FrictMat_FrictPhys()], # collision "physics"
  [Law2_ScGeom_FrictPhys_CundallStrack()] # contact law -- apply forces
 ),
 # Apply gravity force to particles. damping: numerical dissipation of energy.
 NewtonIntegrator(gravity=(0,0,-9.81),damping=0.1)

]

# set timestep to a fraction of the critical timestep
# the fraction is very small, so that the simulation is not too fast
# and the motion can be observed
O.dt=.5e-4*PWaveTimeStep()

# save the simulation, so that it can be reloaded later, for experimentation
O.saveTmp()

so the three masks are :
mask1=0b10 blue
mask2=0b01 green
mask3=0b11 red

and the result for collider.avoidSelfInteractionMask
0b00 full interaction
0b01 full no interaction
0b10 full interaction
0b11 full no interaction

 according to the definiton of the mask "This mask is used to avoid the interactions inside a group of particles. To do so, the particles must have the exact same mask and that mask should have one bit in common with this avoidSelfInteractionMask as for their binary representations" this should not be ful or zero interactions???

where I made a mistake?

Question information

Language:
English Edit question
Status:
Answered
For:
Yade Edit question
Assignee:
No assignee Edit question
Last query:
2019-08-16
Last reply:
2019-08-16
Jérôme Duriez (jduriez) said : #1

Hi,

As far as I'm concerned I did not completely get your objectives/question, sorry..
Just to rephrase the doc, and in your example of 3 mask values assigned to particles (0b10 = "blue", or 0b01 = "green", or 0b11 = "red"), and a with collider.avoidSelfInteractionMask = 0b00:

blue particles would not interact with other blue particles,
green particles would not interact with green particles,
and all other interactions would be possible.

(Assuming collider is defined e.g. as the label of the collider instance in your O.engines, which does not seem to be the case in the Python lines you showed us here)

Jérôme Duriez (jduriez) said : #2

It turns out my example in #1 is incorrect because of a somewhat special treatment of 0b00 in binary comparisons (see also [*])..
Let me rephrase again:

for 3 mask values assigned to particles (0b10 = "blue", or 0b01 = "green", or 0b11 = "red"), and a with collider.avoidSelfInteractionMask = 0b01:

green particles would not interact with other green particles,
red particles would not interact with other red particles,
and all other interactions would be possible.

[*]https://gitlab.com/yade-dev/trunk/issues/106#note_199825825

Jérôme Duriez (jduriez) said : #3

It again turns out that both #1 and #2 are somewhat incorrect... (thank you Jan Stransky !)

I overlooked the fact that interaction possibility depends on mask compatibility in the first place, before any avoidSelfInteractionMask consideration..

So, in an example with 3 mask values assigned to particles (0b10 = "blue", or 0b01 = "green", or 0b11 = "red"), and a with collider.avoidSelfInteractionMask = 0b01:

green particles would not interact with blue particles because they are not mask-compatible (do not share any "1" bit in common)
green particles would not interact with other green particles because of avoidSelfInteractionMask,
red particles would not interact with themselves either, for the same reason
blue particles would interact with themselves, on the contrary

For the complete list of possibilities, see https://gitlab.com/yade-dev/trunk/blob/master/pkg/common/Collider.cpp#L15.
It can anyway not be more confusing than my comments here...

Janek Kozicki (cosurgi) said : #4

Thank you Jerome for your great explanations. Maybe you and Luc Oger can think of a better description into the documentation about this? You can write as much as you want. Only make sure that it is clearly explained. I have just prepared a "placeholder" merge request for you [1], where I have just copied a part of your explanation.

[1] https://gitlab.com/yade-dev/trunk/merge_requests/223

Is there really anything missing in the original doc?
I would actually remove the last words of it :
"This mask is used to avoid the interactions inside a group of particles. To do so, the particles must have the exact same mask and that mask should have one bit in common with this Collider.avoidSelfInteractionMask"

The current text in [1] is excessively long.
[1] https://gitlab.com/yade-dev/trunk/merge_requests/223

Also, for consistency, let's keep masks as integers in the doc.

Janek Kozicki (cosurgi) said : #7

I started this MR, because I had a feeling that this question is asked more often than necessary. I am not sure though if this is the right place for these detailed explanations. Maybe move it to a section in manual which discusses these masks?
That wuold be restructuredtext command: :ref:`interaction-flow`

I have just added a link to https://en.cppreference.com/w/c/language/operator_arithmetic#Bitwise_logic
in case if someone is not familiar with that :)

(I notice that gitlab is sluggish now, and the new push is not visible in the www interface yet)

If you want to remove some words, please go ahead. I did not fully understood which last words you want to remove.

The general goal is of course to reduce number of questions regarding this topic.

My commits there are by no means final. I hope that you will improve this ;)

Well, questions on bitmasks happen indeed, questions on avoidSelfInteractionMask are not really frequent AFAIK.

This is my suggestion (a shorter rephrasing of the original doc):
"This mask is used to avoid the interactions inside a group of particles. If two particles have the exact same mask and that mask is compatible with Collider.avoidSelfInteractionMask then the particles do not collide."

Expanding this if needed could be easier than trying to summarize that long answer by Jérôme.
Feel free to add anything missing.

Bruno

p.s. If general considerations are needed they may fit in user manual or in the docstring of groupMask, probably.
:ref:`interaction-flow` is more or less already here (with no mention of bitmasks):
https://yade-dem.org/doc/formulation.html#creating-interaction-between-particles

Luc OGER (luc-oger) said : #9

sorry for the creation of this long discussion but i am still not happy with the results of this Collider.avoidSelfInteractionMask functionnality:
according to the comment by Jérome (06-08-2019) if the Collider.avoidSelfInteractionMask=0b01 the blue would interact with themselves
but when I modified the line with the collider to 0b01 and run my example, in the 5th column the blue one on the column is not interacting with the fixed blue one at the bottom????

it was part of the analysis and the bottom of the initial post witht th four possible choices for the collider and the full no or yes interaction for all of them??? = not really linked to the bit mask position

back here:
and the result for collider.avoidSelfInteractionMask
0b00 full interaction
0b01 full no interaction
0b10 full interaction
0b11 full no interaction

Janek Kozicki (cosurgi) said : #10

I don't understand. Do you want blue to interact with other blue or not?

Maybe you need to change the color (actually the bitmask) of these at the bottom?

As far as I understand you have mask= 2, 1, and 3.
At this point the possible interactions are 1-1, 2-2, 3-1, 3-2, 3-3.
The impossible ones are 1-2, they will never exist.
Agreed?

Then:
- if you set avoidSelf=1 you kill the 1-1 interactions.
- if you set avoidSelf=2 you kill the 2-2 interactions.
- if you set avoidSelf=3 you kill 1-1, 2-2, and 3-3; only 3-1 and 3-2 are left.

This is the expected behavior and it is what you script gives (a good one! what about adding it to examples? it's funny to see the bounding boxes shrinking as velocity decreases). I don't confirm your report in terms of full/full-no.

Bruno

Luc OGER (luc-oger) said : #13

When I run it on my computer this is not what I get :
in the 5th column with avoidSelf=1 all the three balls on top of the blue fixed one passed through this one????
and it is identical for the 5 colums series of events : every thing passed through...

this is what I don't catch especially if it is working on your version of Yade????

I'm using Yade 2019-08-07.git-c9e148a here, but the "avoidSelfInteractionMask" code did not change in the last years.
Not sure which is 1st and which is 5th column, but with avoidSelf=1 I get spheres stuck on both of them (2 superimposed red spheres on one, green+red+blue on the other one).

It's really strange if you get something else. I can't see any explanation.
You change avoidSelf _after_ reloading, right?

Luc OGER (luc-oger) said : #15

Dear Bruno,

 As I don't know what is this function "avoidSelf_after_reloading" I have not played with it.

how i can check its value or its rule?

I meant to type collider.avoidSelfInteractionMask=X after reloading the scene, not before.
But I guess that's what you do already.

You did not mention your yade version. Is it old?

Luc OGER (luc-oger) said : #17

It is a july version
Like 12-07....

Luc OGER (luc-oger) said : #18

I have just tried with yade-2019-08-08.git-775ae74 and I got the same problem!!

I guess that some compiler options are not going well in some bit test?

Jan Stránský (honzik) said : #19

Hi guys,

sorry for coming late to the discussion.

what is "full interaction", "full no interaction" and "ful or zero interactions"?

also, next time please try to make your script minimal and easily understandable. E.g. here 1st, 5th, top, bottom... is ambiguous according to view orientation..

For example:
###
# mask values, "colors"
mb,mg,mr = 0b10, 0b01, 0b11
# mask to string dict
m2c = {mb:"b", mg:"g", mr:"r"}
# testing spheres, 2 of each color
sb1 = sphere((0,0,0),1,mask=mb)
sb2 = sphere((0,0,0),1,mask=mb)
sg1 = sphere((0,0,0),1,mask=mg)
sg2 = sphere((0,0,0),1,mask=mg)
sr1 = sphere((0,0,0),1,mask=mr)
sr2 = sphere((0,0,0),1,mask=mr)
O.bodies.append((sb1,sb2,sg1,sg2,sr1,sr2))
#
collider.avoidSelfInteractionMask = 0b00
O.step()
#
idss = [(i.id1,i.id2) for i in O.interactions] # id couples for each interaction
bss = [[O.bodies[i] for i in ids] for ids in idss] # body couple of each interaction
mss = [[b.mask for b in bs] for bs in bss] # mask couple of each interaction
mss = [tuple(sorted(ms)) for ms in mss] # make the mask couple of type tuple (needs by set below). Also sort it for proper deletion of duplicates
mss = set(mss) # make the entries unique (i.e. deleting duplicates)
css = ["".join(m2c[m] for m in ms) for ms in mss] # convert mask couples to strings
css.sort() # sort the result
css = " ".join(css) # make it one string
print css # print interacting color couples
###

Please, provide your output for different avoidSelfInteractionMask values such that we can test if your installation does wrong bit operations or there is some misunderstanding.

For my case:
0b00: bb br gg gr rr
0b01: bb br gr
0b10: br gg gr
0b11: br gr

cheers
Jan

PS: a note
In your code, you first modify 'collider' and then in O.engines creates a new collider.
Setting avoidSelfInteractionMask works only "by luck" because avoidSelfInteractionMask is defined as static (for other values it could cause problems).
A cleaner way would be:
##
O.engines = [
   ...
   InsertionSortCollider(...,label="collider")
   ...
]
collider.avoidSelfInteractionMask = ...
##

I tried again with yadedaily (2018.02b-290bf6a54e~xenial), the results are correct again.

@Luc, can't you try on a different computer to be sure we are on the same page? I can't imagine that compiler options change the behavior of bitwise operators...

@Jan,
> "by luck" because avoidSelfInteractionMask is defined as static
Interesting... I wonder why it was defined static at all (probably off-topic though).

Jan's script made me realize my mistake, correct list in #12 was:
- if you set avoidSelf=1 you kill the 1-1 and 3-3 interactions.
- if you set avoidSelf=2 you kill the 2-2 and 3-3 interactions.
- if you set avoidSelf=3 you kill 1-1, 2-2, and 3-3; only 3-1 and 3-2 are left.

Below is a modified script which will not break python interpreter (and is Python3 friendly). Note the explicit call to collider and interactions.all() to get virtual interactions.

###
# mask values, "colors"
mb,mg,mr = 0b10, 0b01, 0b11
# mask to string dict
m2c = {mb:"b", mg:"g", mr:"r"}
# testing spheres, 2 of each color
sb1 = sphere((0,0,0),1,mask=mb)
sb2 = sphere((0,0.1,0),1,mask=mb)
sg1 = sphere((0.1,0,0),1,mask=mg)
sg2 = sphere((0,0,0.1),1,mask=mg)
sr1 = sphere((-0.1,0,0),1,mask=mr)
sr2 = sphere((0,-0.1,0),1,mask=mr)
O.bodies.append((sb1,sb2,sg1,sg2,sr1,sr2))
#
collider.avoidSelfInteractionMask = 0b00
collider.boundDispatcher.__call__()
collider.__call__()

idss = [(i.id1,i.id2) for i in O.interactions.all()] # id couples for each interaction
bss = [[O.bodies[i] for i in ids] for ids in idss] # body couple of each interaction
mss = [[b.mask for b in bs] for bs in bss] # mask couple of each interaction
mss = [tuple(sorted(ms)) for ms in mss] # make the mask couple of type tuple (needs by set below). Also sort it for proper deletion of duplicates
mss = set(mss) # make the entries unique (i.e. deleting duplicates)
css = ["".join(m2c[m] for m in ms) for ms in mss] # convert mask couples to strings
css.sort() # sort the result
css = " ".join(css) # make it one string
print(css) # print interacting color couples
###

Luc OGER (luc-oger) said : #21

aSIMask=0b00 full interaction
aSIMask=0b01 full no interaction
aSIMask=0b10 full interaction
aSIMask=0b11 full no interaction

full no interaction = means all the spheres on top of the bottom fixed one are not interacting with this bottom one and are falling down outside the system

full interaction = means all the spheres are bouncing with all the ones like the standard 2spheres bouncing case.

I have no special interaction depending on the avoidSelfInteractionMask choice

PS I don't catch the meaning and the issue of the 10 lines after O.step()???
I have no problem of position or duplicated according to the initial display of the full sphere setup.

This thread is definitely about Luc getting a completely different behaviour on a particular OS.
And it suggests that bitwise operators are completely broken on that OS. I feel helpless.
Still Luc, if you could check correctness on any other OS it would help making sure we are speaking of the same thing.
Are you using really special compile options?

Luc OGER (luc-oger) said : #23

I am using only the basic cmake option plus MPI=OFF only

I have tried with several vesion or Yade but alwaays with OpenSuse 15.1

after my vacations i will install a linux UBUNTU to test and so avoid this kind of problem....

Jan Stránský (honzik) said : #24

Hi Luc,

my code is just to test the interactions and print it in an understandamble, unambiguous, reproducible.. way.
the 10 lines just extracts and prints this info from real interactions.

to be sure the problem is on the OS side, please provide the output for 0b00, 0b01, 0b10, 0b11 avoidSelfInteractionMask values
thanks
Jan

Luc OGER (luc-oger) said : #25

I have installed UBUNTU 19 on one USB HDD and compiled the last yade:, yade-2019-08-11
Then I have run my py code... And I got exactly the same behavior !!!

So I agree with Jan'remark about the luck?

I will modify the collidermask use and position in the ode

Jan Stránský (honzik) said : #26

> I got exactly the same behavior

same as what?

> Jan'remark about the luck?

my remark was only about the order of commands. It works with avoidSelfInteractionMask attribute, but would not work e.g. for allowBiggerThanPeriod attribute

Really please please post here (or test yourself and tell if the result is different or not) the output of the code in #19 and #20

cheers
Jan

Luc OGER (luc-oger) said : #27

Same as reply in#9 every sphere passed through or every sphere interact with all the others

OK I will try tu write as #19 20

Luc OGER (luc-oger) said : #28

I have run #20
and the answer is strange :
Mask=0b00 : bb br gb gg gr rr
Mask=0b10 : bb br gb gg gr rr

Mask = 0b01 or 0b11 = no line ouput ??

Jan Stránský (honzik) said : #29

Thanks for testing and output.
The results corresponds to your description of either all or none interactions.
Now we (at least I) can be sure that the problem is on the side of the program and not the interpretation of the results.
This is really veeeery strange and I see no reason for that (and therefore no solution)...
e.g. the "gb" interaction should not be there at all (independently on avoidSelfInteractionMask) because the masks are 0b01 and 0b10, respectively..
cheers
Jan

Janek Kozicki (cosurgi) said : #30

So we know it is not the linux distribution. Because Luc has the same problem also on ubuntu 19. So it just occurred to me that maybe it is some of the compiler flags used in compilation, because I assume that Luc used the same flags on suse and ubuntu.

Luc, please tell us what cmake invocation exactly did you use on ubuntu?

Janek Kozicki (cosurgi) said : #31

Also, Jan, perhaps it would be useful for us to turn your example into a `yade --check` script?

Luc OGER (luc-oger) said : #32

it is only a "basic" one :
cmake -DCMAKE_VERBOSE_MAKEFILE=ON -DCMAKE_INSTALL_PREFIX=../install -DPYTHON_VERSION=3 -DDISABLE_SAVE_TEMPS=1 -DENABLE_MPI=OFF ../trunk

and to extend some tests :
here the results with 2 or 3 bit long for the mask!!
if mb,mg,mr = 0b10, 0b01, 0b11
0b00 : bb br gb gg gr rr
0b10 : bb br gb gg gr rr
0b01 :
0b11 :

if mb,mg,mr = 0b100, 0b010, 0b110
0b000 : bb br gb gg gr rr
0b010 : bb br gb gg gr rr
0b100 : bb br gb gg gr rr
0b110 : bb br gb gg gr rr

0b001 :
0b011 :
0b101 :
0b111 :

if mb,mg,mr = 0b101, 0b011, 0b111
0b000 : bb br gb gg gr rr
0b010 : bb br gb gg gr rr
0b100 : bb br gb gg gr rr
0b110 : bb br gb gg gr rr

0b001 :
0b011 :
0b101 :
0b111 :

so results only controled from bit in position 0 at right side????

Janek Kozicki (cosurgi) said : #33

This is more and more strange. Because now I start to suspect the hardware. What is the processor model in your computer? You can use `cat /proc/cpuinfo` to find out. Can you try to reproduce this problem on a computer with a different kind of processor?

Luc OGER (luc-oger) said : #34

I have tried with two very different machines:
laptop : hp envy and server Dell R960
BUT I got the same answer???

here the CPUINFO:

server Dell :
processor : 127
vendor_id : GenuineIntel
cpu family : 6
model : 79
model name : Intel(R) Xeon(R) CPU E7-4850 v4 @ 2.10GHz
stepping : 1
microcode : 0xb00002e
cpu MHz : 2094.877
cache size : 40960 KB
physical id : 3
siblings : 32
core id : 15
cpu cores : 16
apicid : 127
initial apicid : 127
fpu : yes
fpu_exception : yes
cpuid level : 20
wp : yes
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid dca sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb cat_l3 cdp_l3 invpcid_single pti ssbd ibrs ibpb stibp tpr_shadow vnmi flexpriority ept vpid fsgsbase tsc_adjust bmi1 hle avx2 smep bmi2 erms invpcid rtm cqm rdt_a rdseed adx smap intel_pt xsaveopt cqm_llc cqm_occup_llc cqm_mbm_total cqm_mbm_local dtherm ida arat pln pts flush_l1d
bugs : cpu_meltdown spectre_v1 spectre_v2 spec_store_bypass l1tf
bogomips : 4191.91
clflush size : 64
cache_alignment : 64
address sizes : 46 bits physical, 48 bits virtual

Laptop HP-ENVY:
processor : 7
vendor_id : GenuineIntel
cpu family : 6
model : 94
model name : Intel(R) Core(TM) i7-6700HQ CPU @ 2.60GHz
stepping : 3
microcode : 0xcc
cpu MHz : 2600.000
cache size : 6144 KB
physical id : 0
siblings : 8
core id : 3
cpu cores : 4
apicid : 7
initial apicid : 7
fpu : yes
fpu_exception : yes
cpuid level : 22
wp : yes
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf tsc_known_freq pni pclmulqdq dtes64 monitor ds_cpl vmx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb invpcid_single pti ssbd ibrs ibpb stibp tpr_shadow vnmi flexpriority ept vpid fsgsbase tsc_adjust bmi1 hle avx2 smep bmi2 erms invpcid rtm mpx rdseed adx smap clflushopt intel_pt xsaveopt xsavec xgetbv1 xsaves dtherm ida arat pln pts hwp hwp_notify hwp_act_window hwp_epp md_clear flush_l1d
bugs : cpu_meltdown spectre_v1 spectre_v2 spec_store_bypass l1tf mds
bogomips : 5184.00
clflush size : 64
cache_alignment : 64
address sizes : 39 bits physical, 48 bits virtual

Can you help with this problem?

Provide an answer of your own, or ask Luc OGER for more information if necessary.

To post a message you must log in.