How to clump spheres and facet obtained from stl format

Asked by Irfaan Peerun on 2019-08-27

Hi everyone,

I am trying to create a surface obtained from an stl file, fill the surface with spheres and clump the surface (facet) and spheres as one particle.

This is very similar to this question: https://answers.launchpad.net/yade/+question/662544

From yade doc, triangulated surfaces can be imported from gts and stl formats.
I have imported the surface using the 'ymport.stl' function.
However, for generating spheres within the surface, there are no commands for stl format. The example below is for gts format.
Appreciate if someone could help me with:
[1] similar commands for generating spheres in a surface (stl format) or any conversion method for stl to gts format.
[2] command for generating spheres with multiple sizes to fill the surface. This is to ensure the sphere clump is of the same volume as the surface.

#example for sphere packing in surface
if surf.is_closed():
 O1=O.bodies.append(pack.gtsSurface2Facets(surf,fixed=False,noBound=True,material=m))
 sp=pack.randomDensePack(pack.inGtsSurface(surf),radius=0.1,memoizeDb=memoizeDb,returnSpherePack=True)
 Otemp=sp.toSimulation()
 O3=O1+Otemp
 #O3=Otemp

Looking forward to any suggestion.
Irfaan

Question information

Language:
English Edit question
Status:
Expired
For:
Yade Edit question
Assignee:
No assignee Edit question
Last query:
2019-09-02
Last reply:
2019-09-18
Irfaan Peerun (irfaan) said : #1

Just an update:

I have managed to convert the .stl file to .gts using the following command: stl2gts -r < filename.stl > filename.gts
gmsh and libgts-bin need to be installed to do so.

So now I have a surface which was imported in .gts format using the command: surf=gts.read(open('filename.gts'))

My next step is to fill the surface with spheres of various sizes and clump them together to produce a body of the same volume and geometry as the surface. This would require overlapping of spheres.

I used the pack.randomDensePack function with sphere radius=0.00005 and realfuzz=0.000005. The average range diameter of the surface 2.36mm to 1.18mm. Hence, my questions are:

[1] Is the pack.randomDensePack function appropriate for this situation? Any rule of thumb in deciding the sphere radius? Does the function include overlapping of spheres?

[2] By adding memoizeDb='/tmp/gts-packings.sqlite', does it mean that a temporary sqlite file will be created to store the packing that will be generated?

[3] Is there any function to obtain the clump volume as comparison to the imported gts surface.

When running the script, I received the following error along with a blank view (no sphere or surface):
WARN /build/yade-fDuCoe/yade-2018.02b/pkg/common/InsertionSortCollider.cpp:242 action: verletDist is set to 0 because no spheres were found. It will result in suboptimal performances, consider setting a positive verletDist in your script.

Appreciate if anyone could guide me in solving this. The script is as follows:

# ========= Script ===================
from yade import pack,ymport
import gts

#Add material for spheres
m=FrictMat(young = 1E8, poisson = 0.25, frictionAngle = 0.0, density = 2650)

# import surface
surf=gts.read(open('/home/Desktop/SphereClumping/sample.gts'))

# parameters for radom packing in imported surface
memoizeDb='/tmp/gts-packings.sqlite'
sp=SpherePack()

# generate lists of spheres and outer surface
if surf.is_closed():
 O1=O.bodies.append(pack.gtsSurface2Facets(surf,fixed=False,noBound=True,material=m))
 sp=pack.randomDensePack(pack.inGtsSurface(surf),radius=0.00005,rRelFuzz=0.000005,memoizeDb=memoizeDb,returnSpherePack=True)
 Otemp=sp.toSimulation()

 #clump spheres and surface together
 idClump=O.bodies.clump(Otemp)

O.engines=[
   ForceResetter(),
   InsertionSortCollider([Bo1_Sphere_Aabb(),Bo1_Facet_Aabb()]),
   InteractionLoop(
      # handle sphere+sphere and facet+sphere collisions
      [Ig2_Sphere_Sphere_ScGeom(),Ig2_Facet_Sphere_ScGeom()],
      [Ip2_FrictMat_FrictMat_FrictPhys()],
      [Law2_ScGeom_FrictPhys_CundallStrack()]
   ),
 NewtonIntegrator(gravity=(0,0,-9.81),damping=0.4),
]

# set timestep to a fraction of the critical timestep
O.dt=0.5*PWaveTimeStep()

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

from yade import qt
qt.View()

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

Hello,

> Is the pack.randomDensePack function appropriate for this situation?

if you do not need precise particle size distribution, then randomDensePack is one option

> Any rule of thumb in deciding the sphere radius?

no, depends on your needs

> Does the function include overlapping of spheres?

no. But you can then enlarge the spheres to create overlaps

> By adding memoizeDb='/tmp/gts-packings.sqlite', does it mean that a temporary sqlite file will be created to store the packing that will be generated?

yes. The next run, this packing is read and is not generated again

[3] Is there any function to obtain the clump volume as comparison to the imported gts surface.

> When running the script, I received the following error along with a blank view (no sphere or surface):
> WARN /build/yade-fDuCoe/yade-2018.02b/pkg/common/InsertionSortCollider.cpp:242 action: verletDist is set to 0 because no spheres were found. It will result in suboptimal performances, consider setting a positive verletDist in your script.

It is not error, but warning. Not inportant for now

To help you more, we would need a compete script and all data (i.e. sample.gts file). For testing purposes, a simple tetrahedron should be enough. So please provide the data to help you more.

cheers
Jan

Irfaan Peerun (irfaan) said : #3

Hi Jan,

Thank you for your reply.

Kindly find script and surface.gts from the link below:
https://www.dropbox.com/sh/stdv163suddsbl0/AACAz3Egwl82k8d2s7mM3Pkja?dl=0

[1] When running the simulation, it still gives me a blank screen (no surface or spheres can be seen). Appreciate if you could guide me in solving this.

[2] No, I do not require a specific PSD. I am trying to reproduce a realistic scanned particle using the gts surface. Since interaction between facet to facet cannot occur, I will need to create a clump representing the d surface. Is there a way to obtain the volume of the clump? This is to check if the clump is comparable to the scanned surface.

[3] Is there any other options to fill the surface with sphere clumps?

Appreciate your support.

Thanks and kind regards,
Irfaan

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

Hello,

> When running the simulation, it still gives me a blank screen (no surface or spheres can be seen).
>
> if surf.is_closed():
> O1=O.bodies.append(pack.gtsSurface2Facets(surf,fixed=False,noBound=True,material=m))
> sp=pack.randomDensePack(pack.inGtsSurface(surf),...)
> Otemp=sp.toSimulation()

surf.is_closed() returns False. Then no facets or spheres are created..

cheers
Jan

Irfaan Peerun (irfaan) said : #5

Hi Jan,

Thanks again for your prompt reply.

I have removed the "if surf.is_closed():" as follows:

#if surf.is_closed():
O1=O.bodies.append(pack.gtsSurface2Facets(surf,fixed=False,noBound=True,material=m))
sp=pack.randomDensePack(pack.inGtsSurface(surf),radius=100,rRelFuzz=10,memoizeDb=memoizeDb,returnSpherePack=True)
Otemp=sp.toSimulation()

#clump spheres and surface together
idClump=O.bodies.clump(Otemp)

Once I load the script, I receive the following error that the surface is not closed:
Traceback (most recent call last):
  File "/usr/bin/yade", line 182, in runScript
    execfile(script,globals())
  File "/home/irfaan/Desktop/SphereClumpingInsideSurface/SphereClumping.py", line 18, in <module>
    sp=pack.randomDensePack(pack.inGtsSurface(surf),radius=100,rRelFuzz=10,memoizeDb=memoizeDb,returnSpherePack=True)
ValueError: Surface is not closed.

And when I start the simulation, I received another error:
WARN /build/yade-fDuCoe/yade-2018.02b/pkg/common/InsertionSortCollider.cpp:242 action: verletDist is set to 0 because no spheres were found. It will result in suboptimal performances, consider setting a positive verletDist in your script.
WARN /build/yade-fDuCoe/yade-2018.02b/pkg/dem/Shop_01.cpp:423 PWaveTimeStep: PWaveTimeStep has not found any suitable spherical body to calculate dt. dt is set to 1.0

As you said the timestep error is not to worry.
The surface is visible when the script is loaded but once I start the simulation, it disappears at iter #20 (within few seconds).
There is still no spheres, even if I let it run for more than 10 minutes.
I tried using bigger sphere radius, still no difference.

Am I missing anything important here?

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

Sorry for not being precise enough. The problem is that the surface is not closed.
Either you have sphere generation inside "if surf.is_closed()" (which is not evaluated and no spheres are generated), or you delete/comment the condition which ends with error and no spheres are generated, too.

Could you provide the original stl?

Jan

Irfaan Peerun (irfaan) said : #7

Hi Jan,

I have uploaded the stl file, link below:
https://www.dropbox.com/sh/stdv163suddsbl0/AACAz3Egwl82k8d2s7mM3Pkja?dl=0

If the surface is not closed and spheres cannot be generated, is there a way to produce a closed surface?
Note that I converted the stl to gts using the command: stl2gts -r < filename.stl > filename.gts

Kind regards,
Irfaan

Launchpad Janitor (janitor) said : #8

This question was expired because it remained in the 'Open' state without activity for the last 15 days.

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

What about the stl? is it closed and the problem comes from the format conversion?
If yes, there should be some solution.
If no, then the surface should be closed, but I don't know about very easy methods..
Also note the gts.Surface.cleanup method, which should merge close vertices (and possibly close the surface, but I did not test it).
cheers
Jan