Using different InsertGenerator3D for the same volume in gengeo

Asked by Enrique Wegmann

Hi all,
I'm using gengeo to create a cubic AVolume3D with particles and I want to introduce the particles using different InsertGenerator3D, so that I can better control the total particles volumes by assigning different radius ranges for each InsertGenerator3D in the same cubic AVolume3D. I can also assign one GroupID for each generated packer and therefore create bonds only between one GroupID and depending on the distance within this groupID.
The problem using two or more InsertGenerator3D with the same Volume3D is that after creating the first generatePacking, lets say with coarse or big particles, I want to introduce the second generatePacking with much smaller particles and fill the same Volume3D "minus" the volume of particles created by the first generatePacking. I'm using a "for...loop" to make a DifferenceVol between the original Volume3D and each created particle by the first generatePacking, but I get an error in the loop, I cannot subtract the volume of the first particle, and then re-use the result to subtract the volume of the second particle and so on, within the same loop. I get a"pure virtual method called" and I don't know if it is my bad programming or because the class AVolume3D cannot be instantiated from python. If you understand my problem and have an idea how to deal with it I would be very thankful!

Here is my code:

from gengeo import *

def makeSample(seed=True):

#create a volume of general particles:
   box = BoxWithPlanes3D (
 minPoint = Vector3(0.0,0.0,0.0),
 maxPoint = Vector3(20.0,20.0,20.0)
   )

#Create a neighbour table to contain the particles:
   table = MNTable3D (
      minPoint = Vector3(0.0,0.0,0.0),
      maxPoint = Vector3(20.0,20.0,20.0),
      gridSize = 1.2*3.5,
      numGroups = 2
   )

#Create a particle packer for inserting particles into the volume:
#general particles:
   packer1 = InsertGenerator3D (
      minRadius = 2.5,
      maxRadius = 3.5,
      insertFails = 100,
      maxIterations = 50,
      tolerance = -1.0e-4,
      seed = True
   )

#Generate the particles packing for the sample:
#general particles:
   packer1.generatePacking(
      volume = box,
      ntable = table,
      groupID = 0,
      tag = 0
   )

#calculate particles volume and print
   partVol = table.getSumVolume(groupID=0)
   print "partVol:", partVol

#create a difference volume from general particles and box:
   sphereList = table.getSphereListFromGroup(0)
   rest = box
   print "rest:", rest

   for i in range (0, len(sphereList)):
        sphere1 = sphereList[i]
        S = SphereVol(sphere1.Centre(), sphere1.Radius())
        rest = DifferenceVol(rest, S)
#
#
#here is the problem when I want to use the residual volume "rest" again and again during the loop to subtract all particle #volumes from "box", and then use "rest" as the volume for the second generatePacking
#
#

#small particles:
   packer2 = InsertGenerator3D (
      minRadius = 0.3,
      maxRadius = 0.5,
      insertFails = 100,
      maxIterations = 50,
      tolerance = -1.0e-4,
      seed = True
   )

#small particles packer generation:
   packer2.generatePacking(
      volume = rest,
      ntable = table,
      groupID = 1,
      tag = 1
   )

#calculate rest volume and print
   partVol2 = table.getSumVolume(groupID=1)
   print "partVol2:", partVol2

#create bonds between neighbouring small particles:
   table.generateBonds(
      groupID = 1,
      tolerance = 0.05,
      bondID = 1
    )

# write a VTK file
   table.write(
      fileName = "box.vtu",
      outputStyle = 2
   )

if __name__=="__main__":
   makeSample()

Thanks!

Question information

Language:
English Edit question
Status:
Solved
For:
ESyS-Particle Edit question
Assignee:
No assignee Edit question
Solved by:
Dion Weatherley
Solved:
Last query:
Last reply:
Revision history for this message
Best Dion Weatherley (d-weatherley) said :
#1

Hi Enrique,

Thanks for the tricky question about gengeo. I am not sure exactly why you have struck this particular error message. Perhaps someone with greater knowledge of the innards of boost-python could fathom that. However, there is a rather simple solution to your problem, to produce your desired model arrangement. The full script is below, but first, a few comments on how to go about it:

1) This concept of groups in the MNTables can be very handy but is typically only useful if packing non-overlapping Volumes. This simplifies neighbour search and facilitates rapid post-packing options such as tagging and bonding particle-pairs. The problem with using groups for overlapping regions is that the InsertGenerator ignores any particles not in the current group when generating the packings. This means particles with different groupIDs will overlap.

2) Another way to delineate different "classes" of particles is to use different particle tags but the same groupID. For your problem, first pack the cubic volume (your 'box') with large particles using your first InsertGenerator, assigning these particles a tag=0 say. Next pack the same cubic volume using your second InsertGenerator, assigning these smaller particles a tag=1. For both packing steps, use identical groupIDs and the same MNTable (your 'table'). Once both packings are complete, use MNTable3D.generateBondsTagged(..) to bond together only neighbouring small particles.

3) If your application requires it, you can bond small particles together with bonds of a given tag, large particles via bonds with a different tag, and large-small particles with bonds of a third tag.

3) In some instances, you may wish for all the particles to end up with the same particle tag. This can be done with MNTable3D.tagParticlesInVolume(...) using your original 'box' volume as the specified volume.

A script illustrating all this is below. I hope this helps and have fun!

Cheers,

Dion.

--------------------------
from gengeo import *

def makeSample(seed=True):

#create a volume of general particles:
   box = BoxWithPlanes3D (
      minPoint = Vector3(0.0,0.0,0.0),
      maxPoint = Vector3(20.0,20.0,20.0)
   )

#Create a neighbour table to contain the particles:
   table = MNTable3D (
      minPoint = Vector3(0.0,0.0,0.0),
      maxPoint = Vector3(20.0,20.0,20.0),
      gridSize = 1.2*3.5,
      numGroups = 1
   )

#Create a particle packer for inserting particles into the volume:
#general particles:
   packer1 = InsertGenerator3D (
      minRadius = 2.5,
      maxRadius = 3.5,
      insertFails = 100,
      maxIterations = 50,
      tolerance = -1.0e-4,
      seed = True
   )

#Generate the particles packing for the sample:
#general particles:
   packer1.generatePacking(
      volume = box,
      ntable = table,
      groupID = 0,
      tag = 0
   )

#calculate particles volume and print
   partVol = table.getSumVolume(groupID=0)
   print "partVol:", partVol

#small particles:
   packer2 = InsertGenerator3D (
      minRadius = 0.3,
      maxRadius = 0.5,
      insertFails = 100,
      maxIterations = 50,
      tolerance = -1.0e-4,
      seed = True
   )

#small particles packer generation:
   packer2.generatePacking(
      volume = box,
      ntable = table,
      groupID = 0,
      tag = 1
   )

#calculate rest volume and print
   partVol2 = table.getSumVolume(groupID=0) - partVol
   print "partVol2:", partVol2

#create bonds between neighbouring small particles:
   table.generateBondsTagged(
      groupID = 0,
      tolerance = 0.05,
      bondID = 1,
      particleTag1 = 1,
      particleTag2 = 1
    )

   #should you require it, re-tag all particles with the same tag:
   table.tagParticlesInVolume(
      volume = box,
      tag = 0,
      groupID = 0
   )

# write a VTK file
   table.write(
      fileName = "box.vtu",
      outputStyle = 2
   )

if __name__=="__main__":
   makeSample()

Revision history for this message
Enrique Wegmann (ewegmannv) said :
#2

Thanks Dion Weatherley, that solved my question.

Revision history for this message
Enrique Wegmann (ewegmannv) said :
#3

Thanks a lot Dion for your fast response! I was dealing with this for three days before I decided to ask you...
However I found something interesting regarding this problem. I printed each step within the loop like this:

   sphereList = table.getSphereListFromGroup(0)
   rest = box
   print "rest:", rest

   for i in range (0, len(sphereList)):
      sphere1 = sphereList[i]
      print "sphere:", sphere1
      S = SphereVol(sphere1.Centre(), sphere1.Radius())
      print "S:", S
      rest = DifferenceVol(rest, S)
      print "rest:", rest
   box1 = rest
   print "box1:", box1

and till here there is no error, the error comes when I used "box1" or "rest" in the second packer:

   packer2.generatePacking(
      volume = box1,
      ntable = table,
      groupID = 0,
      tag = 1
   )

So I did the following, without using a "for...loop":

   sphere0 = sphereList[0]
   sphere1 = sphereList[1]
   sphere2 = sphereList[2]
   sphere3 = sphereList[3]
   S0 = SphereVol(sphere0.Centre(), sphere0.Radius())
   rest0 = DifferenceVol(box, S0)
   S1 = SphereVol(sphere1.Centre(), sphere1.Radius())
   rest1 = DifferenceVol(rest0, S1)
   S2 = SphereVol(sphere2.Centre(), sphere2.Radius())
   rest2 = DifferenceVol(rest1, S2)
   S3 = SphereVol(sphere3.Centre(), sphere3.Radius())
   rest3 = DifferenceVol(rest2, S3)

And then by using "rest3" in the second packer it didn't make any arror, the new small particles were placed around the first ones without problem. I dont know if it is some kind of bug...

I've already tried your recommendation and it works fine for me. Thanks a lot again!