""" CAUTION: Running this script can take very long! """ from numpy import arange from yade import pack import pylab # define the section shape as polygon in 2d; repeat first point at the end to close the polygon poly=((1e-2,5e-2),(5e-2,2e-2),(7e-2,-2e-2),(1e-2,-5e-2),(1e-2,5e-2)) # show us the meridian shape #pylab.plot(*zip(*poly)); pylab.xlim(xmin=0); pylab.grid(); pylab.title('Meridian of the revolution surface\n(close to continue)'); pylab.gca().set_aspect(aspect='equal',adjustable='box'); pylab.show() # angles at which we want this polygon to appear thetas=arange(0,pi/2,pi/24) # create 3d points from the 2d ones, turning the 2d meridian around the +y axis # for each angle, put the poly a little bit higher (+2e-3*theta); # this is just to demonstrate that you can do whatever here as long as the resulting # meridian has the same number of points # # There is origin (translation) and orientation arguments, allowing to transform all the 3d points once computed. # # without these transformation, it would look a little simpler: # pts=pack.revolutionSurfaceMeridians([[(pt[0],pt[1]+2e-3*theta) for pt in poly] for theta in thetas],thetas # pts=pack.revolutionSurfaceMeridians([[(pt[0],pt[1]+1e-2*theta) for pt in poly] for theta in thetas],thetas,origin=Vector3(0,-.05,.1),orientation=Quaternion((1,1,0),pi/4)) # connect meridians to make surfaces # caps will close it at the beginning and the end # threshold will merge points closer than 1e-4; this is important: we want it to be closed for filling surf=pack.sweptPolylines2gtsSurface(pts,capStart=True,capEnd=True,threshold=1e-4) # add the surface as facets to the simulation, to make it visible O.bodies.append(pack.gtsSurface2Facets(surf,color=(1,0,1))) # now fill the inGtsSurface predicate constructed form the same surface with sphere packing generated by TriaxialTest # with given radius and standard deviation (see documentation of pack.randomDensePack) # # The memoizeDb will save resulting packing into given file and next time, if you run with the same # parameters (or parameters that can be scaled to the same one), # it will load the packing instead of running the triaxial compaction again. # Try running for the second time to see the speed difference! memoizeDb='/tmp/gts-triax-packings.sqlite' sp=SpherePack() sp=pack.randomDensePack(pack.inGtsSurface(surf),radius=5e-3,rRelFuzz=1e-4,memoizeDb=memoizeDb,returnSpherePack=True) sp.toSimulation() # We could also fill the horse with triaxial packing, but have nice approximation, the triaxial would run terribly long, # since horse discard most volume of its bounding box # Here, we would use a very crude one, however if 1: import gts horse=gts.read(open('horse.coarse.gts')) #; horse.scale(.25,.25,.25) O.bodies.append(pack.gtsSurface2Facets(horse)) sp=pack.randomDensePack(pack.inGtsSurface(horse),radius=5e-3,memoizeDb=memoizeDb,returnSpherePack=True) sp.toSimulation() horse.translate(.07,0,0) O.bodies.append(pack.gtsSurface2Facets(horse)) # specifying spheresInCell makes the packing periodic, with the given number of spheres, proportions being equal to that of the predicate sp=pack.randomDensePack(pack.inGtsSurface(horse),radius=1e-3,spheresInCell=2000,memoizeDb=memoizeDb,returnSpherePack=True) sp.toSimulation()