def setUp(self): O.reset() r1,r2,p0,p1=1,.5,Vector3.Zero,Vector3(0,0,3) self.idC,(self.id1,self.id2)=O.bodies.appendClumped([ utils.sphere(p0,r1), utils.sphere(p1,r2) ])
def testUserCreatedInteraction(self): O.engines=[ ForceResetter(), InsertionSortCollider([Bo1_Sphere_Aabb(),Bo1_Facet_Aabb(),Bo1_Box_Aabb()],label="collider"), InteractionLoop( [Ig2_Sphere_Sphere_ScGeom(),Ig2_Facet_Sphere_ScGeom(),Ig2_Box_Sphere_ScGeom()], [Ip2_FrictMat_FrictMat_FrictPhys()], #for linear model only [Law2_ScGeom_FrictPhys_CundallStrack(label="law")], #for linear model only label="interactionLoop" ), GlobalStiffnessTimeStepper(timeStepUpdateInterval=10,label="timeStepper"), NewtonIntegrator(label="newton") ] O.bodies.append([utils.sphere((0,0,0),0.5), utils.sphere((2,0,0),0.5), #(0,1) no overlap , no contacts utils.sphere((0.9,0.9,0),0.5), #(0,2) overlapping bounds, no contacts utils.sphere((-0.99,0,0),0.5)]) #(0,3) overlaping + contact O.dt=0 O.dynDt=False O.step() i=utils.createInteraction(0,1) self.assert_(i.iterBorn==1 and i.iterMadeReal==1) j=utils.createInteraction(0,2) self.assert_(j.iterBorn==1 and j.iterMadeReal==1) self.assertRaises(RuntimeError,lambda: utils.createInteraction(0,3))
def testErasedAndNewlyCreatedSphere(self): "Bodies: The bug is described in LP:1001194. If the new body was created after deletion of previous, it has no bounding box" O.reset() id1 = O.bodies.append(utils.sphere([0.0, 0.0, 0.0],0.5)) id2 = O.bodies.append(utils.sphere([0.0, 2.0, 0.0],0.5)) O.engines=[ ForceResetter(), InsertionSortCollider([Bo1_Sphere_Aabb()]), InteractionLoop( [Ig2_Sphere_Sphere_L3Geom()], [Ip2_FrictMat_FrictMat_FrictPhys()], [Law2_L3Geom_FrictPhys_ElPerfPl()] ), NewtonIntegrator(damping=0.1,gravity=(0,0,-9.81)) ] O.dt=.5e-4*utils.PWaveTimeStep() #Before first step the bodies should not have bounds self.assert_(O.bodies[id1].bound==None and O.bodies[id2].bound==None) O.run(1, True) #After first step the bodies should have bounds self.assert_(O.bodies[id1].bound!=None and O.bodies[id2].bound!=None) #Add 3rd body id3 = O.bodies.append(utils.sphere([0.0, 4.0, 0.0],0.5)) O.run(1, True) self.assert_(O.bodies[id1].bound!=None and O.bodies[id2].bound!=None and O.bodies[id3].bound!=None) #Remove 3rd body O.bodies.erase(id3) O.run(1, True) #Add 4th body id4 = O.bodies.append(utils.sphere([0.0, 6.0, 0.0],0.5)) O.run(1, True) self.assert_(O.bodies[id1].bound!=None and O.bodies[id2].bound!=None and O.bodies[id4].bound!=None)
def SpherePack_toSimulation(self,rot=Matrix3.Identity,**kw): """Append spheres directly to the simulation. In addition calling :yref:`O.bodies.append<BodyContainer.append>`, this method also appropriately sets periodic cell information of the simulation. >>> from yade import pack; from math import * >>> sp=pack.SpherePack() Create random periodic packing with 20 spheres: >>> sp.makeCloud((0,0,0),(5,5,5),rMean=.5,rRelFuzz=.5,periodic=True,num=20) 20 Virgin simulation is aperiodic: >>> O.reset() >>> O.periodic False Add generated packing to the simulation, rotated by 45° along +z >>> sp.toSimulation(rot=Quaternion((0,0,1),pi/4),color=(0,0,1)) [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19] Periodic properties are transferred to the simulation correctly, including rotation (this could be avoided by explicitly passing "hSize=O.cell.hSize" as an argument): >>> O.periodic True >>> O.cell.refSize Vector3(5,5,5) >>> O.cell.hSize Matrix3(3.53553,-3.53553,0, 3.53553,3.53553,0, 0,0,5) The current state (even if rotated) is taken as mechanically undeformed, i.e. with identity transformation: >>> O.cell.trsf Matrix3(1,0,0, 0,1,0, 0,0,1) :param Quaternion/Matrix3 rot: rotation of the packing, which will be applied on spheres and will be used to set :yref:`Cell.trsf` as well. :param \*\*kw: passed to :yref:`yade.utils.sphere` :return: list of body ids added (like :yref:`O.bodies.append<BodyContainer.append>`) """ if isinstance(rot,Quaternion): rot=rot.toRotationMatrix() assert(isinstance(rot,Matrix3)) if self.isPeriodic: O.periodic=True if self.cellSize!=Vector3.Zero and self.isPeriodic: O.cell.hSize=rot*Matrix3(self.cellSize[0],0,0, 0,self.cellSize[1],0, 0,0,self.cellSize[2]) O.cell.trsf=Matrix3.Identity if not self.hasClumps(): return O.bodies.append([utils.sphere(rot*c,r,**kw) for c,r in self]) else: standalone,clumps=self.getClumps() ids=O.bodies.append([utils.sphere(rot*c,r,**kw) for c,r in self]) # append all spheres first clumpIds=[] userColor='color' in kw for clump in clumps: clumpIds.append(O.bodies.clump(clump)) # clump spheres with given ids together, creating the clump object as well # make all spheres within one clump a single color, unless color was specified by the user if not userColor: for i in clump[1:]: O.bodies[i].shape.color=O.bodies[clump[0]].shape.color return ids+clumpIds
def textExt(fileName, format='x_y_z_r', shift=Vector3.Zero, scale=1.0, attrs=[], **kw): """Load sphere coordinates from file in specific format, returns a list of corresponding bodies; that may be inserted to the simulation with O.bodies.append(). :param str filename: file name :param str format: the name of output format. Supported `x_y_z_r`(default), `x_y_z_r_matId`, 'x_y_z_r_attrs' :param [float,float,float] shift: [X,Y,Z] parameter moves the specimen. :param float scale: factor scales the given data. :param list attrs: attrs read from file if export.textExt(format='x_y_z_r_attrs') were used ('passed by refernece' style) :param \*\*kw: (unused keyword arguments) is passed to :yref:`yade.utils.sphere` :returns: list of spheres. Lines starting with # are skipped """ infile = open(fileName, "r") lines = infile.readlines() infile.close() ret = [] for line in lines: data = line.split() if (data[0] == "#format"): format = data[1] continue elif (data[0][0] == "#"): continue if (format == 'x_y_z_r'): pos = Vector3(float(data[0]), float(data[1]), float(data[2])) ret.append( utils.sphere(shift + scale * pos, scale * float(data[3]), **kw)) elif (format == 'x_y_z_r_matId'): pos = Vector3(float(data[0]), float(data[1]), float(data[2])) ret.append( utils.sphere(shift + scale * pos, scale * float(data[3]), material=int(data[4]), **kw)) elif (format == 'id_x_y_z_r_matId'): pos = Vector3(float(data[1]), float(data[2]), float(data[3])) ret.append( utils.sphere(shift + scale * pos, scale * float(data[4]), material=int(data[5]), **kw)) elif (format == 'x_y_z_r_attrs'): pos = Vector3(float(data[0]), float(data[1]), float(data[2])) s = utils.sphere(shift + scale * pos, scale * float(data[3]), **kw) ret.append(s) attrs.append(data[4:]) else: raise RuntimeError("Please, specify a correct format output!") return ret
def textClumps(fileName, shift=Vector3.Zero, discretization=0, orientation=Quaternion((0, 1, 0), 0.0), scale=1.0, **kw): """Load clumps-members from file, insert them to the simulation. :param str filename: file name :param str format: the name of output format. Supported `x_y_z_r`(default), `x_y_z_r_clumpId` :param [float,float,float] shift: [X,Y,Z] parameter moves the specimen. :param float scale: factor scales the given data. :param \*\*kw: (unused keyword arguments) is passed to :yref:`yade.utils.sphere` :returns: list of spheres. Lines starting with # are skipped """ infile = open(fileName, "r") lines = infile.readlines() infile.close() ret = [] curClump = [] newClumpId = -1 for line in lines: data = line.split() if (data[0][0] == "#"): continue pos = orientation * Vector3(float(data[0]), float(data[1]), float(data[2])) if (newClumpId < 0 or newClumpId == int(data[4])): idD = curClump.append( utils.sphere(shift + scale * pos, scale * float(data[3]), **kw)) newClumpId = int(data[4]) else: newClumpId = int(data[4]) ret.append( O.bodies.appendClumped(curClump, discretization=discretization)) curClump = [] idD = curClump.append( utils.sphere(shift + scale * pos, scale * float(data[3]), **kw)) if (len(curClump) <> 0): ret.append( O.bodies.appendClumped(curClump, discretization=discretization)) # Set the mask to a clump the same as the first member of it for i in range(len(ret)): O.bodies[ret[i][0]].mask = O.bodies[ret[i][1][0]].mask return ret
def setUp(self): # common setup for all tests in this class O.reset() O.materials.append([ FrictMat(young=1,label='materialZero'), ElastMat(young=100,label='materialOne') ]) O.bodies.append([ utils.sphere([0,0,0],.5,material=0), utils.sphere([1,1,1],.5,material=0), utils.sphere([1,1,1],.5,material=1) ])
def setUp(self): # common setup for all tests in this class O.reset() O.materials.append([ FrictMat(young=1, label='materialZero'), ElastMat(young=100, label='materialOne') ]) O.bodies.append([ utils.sphere([0, 0, 0], .5, material=0), utils.sphere([1, 1, 1], .5, material=0), utils.sphere([1, 1, 1], .5, material=1) ])
def setUp(self): O.reset(); O.periodic=True; O.cell.setBox(2.5,2.5,3) self.cellDist=Vector3i(0,0,10) # how many cells away we go self.relDist=Vector3(0,.999999999999999999,0) # rel position of the 2nd ball within the cell self.initVel=Vector3(0,0,5) O.bodies.append(utils.sphere((1,1,1),.5)) self.initPos=Vector3([O.bodies[0].state.pos[i]+self.relDist[i]+self.cellDist[i]*O.cell.refSize[i] for i in (0,1,2)]) O.bodies.append(utils.sphere(self.initPos,.5)) #print O.bodies[1].state.pos O.bodies[1].state.vel=self.initVel O.engines=[NewtonIntegrator(warnNoForceReset=False)] O.cell.velGrad=Matrix3(0,0,0, 0,0,0, 0,0,-1) O.dt=0 # do not change positions with dt=0 in NewtonIntegrator, but still update velocities from velGrad
def filterSpherePack(predicate, spherePack, returnSpherePack=None, **kw): """Using given SpherePack instance, return spheres that satisfy predicate. It returns either a :yref:`yade._packSpheres.SpherePack` (if returnSpherePack) or a list. The packing will be recentered to match the predicate and warning is given if the predicate is larger than the packing.""" if returnSpherePack == None: warnings.warn( 'The default behavior will change; specify returnSpherePack=True for the new behavior, and False to get rid of this warning (your code will break in the future, however). The returned SpherePack object can be added to the simulation using SpherePack.toSimulation()', category=FutureWarning) returnSpherePack = False mn, mx = predicate.aabb() dimP, centP = predicate.dim(), predicate.center() dimS, centS = spherePack.dim(), spherePack.center() if dimP[0] > dimS[0] or dimP[1] > dimS[1] or dimP[2] > dimS[2]: warnings.warn( "Packing's dimension (%s) doesn't fully contain dimension of the predicate (%s)." % (dimS, dimP)) spherePack.translate(centP - centS) if returnSpherePack: ret = SpherePack() for c, r in spherePack: if predicate(c, r): ret.add(c, r) return ret else: # return particles to be added to O.bodies ret = [] for s in spherePack: if predicate(s[0], s[1]): ret += [utils.sphere(s[0], radius=s[1], **kw)] return ret
def testUserCreatedInteraction(self): O.bodies.append([ utils.sphere((0, 0, 0), 0.5), utils.sphere((2, 0, 0), 0.5), #(0,1) no overlap , no contacts utils.sphere((0.9, 0.9, 0), 0.5), #(0,2) overlapping bounds, no contacts utils.sphere((-0.99, 0, 0), 0.5) ]) #(0,3) overlaping + contact O.dt = 0 O.dynDt = False O.step() i = utils.createInteraction(0, 1) self.assert_(i.iterBorn == 1 and i.iterMadeReal == 1) j = utils.createInteraction(0, 2) self.assert_(j.iterBorn == 1 and j.iterMadeReal == 1) self.assertRaises(RuntimeError, lambda: utils.createInteraction(0, 3))
def regularHexa(predicate, radius, gap, **kw): """Return set of spheres in regular hexagonal grid, clipped inside solid given by predicate. Created spheres will have given radius and will be separated by gap space.""" ret = [] a = 2 * radius + gap hy, hz = a * sqrt(3) / 2., a * sqrt(6) / 3. mn, mx = predicate.aabb() dim = [mx[i] - mn[i] for i in (0, 1, 2)] if (max(dim) == float('inf')): raise ValueError( "Aabb of the predicate must not be infinite (didn't you use union | instead of intersection & for unbounded predicate such as notInNotch?" ) ii, jj, kk = [ list(range(0, int(dim[0] / a) + 1)), list(range(0, int(dim[1] / hy) + 1)), list(range(0, int(dim[2] / hz) + 1)) ] for i, j, k in itertools.product(ii, jj, kk): #Simple HCP-lattice packing #http://en.wikipedia.org/wiki/Close-packing_of_equal_spheres#Simple_hcp_lattice coordSph = Vector3((2 * i + ((j + k) % 2)), (sqrt(3.) * (j + 1. / 3. * (k % 2))), (2. * sqrt(6.) / 3. * k)) * (a / 2.0) + mn if predicate(coordSph, radius): ret += [utils.sphere(coordSph, radius=radius, **kw)] if (len(ret) == 0): warnings.warn('No spheres are produced by regularHexa-function', category=RuntimeWarning) return ret
def randomPeriPack(radius,initSize,rRelFuzz=0.0,memoizeDb=None,noPrint=False): """Generate periodic dense packing. A cell of initSize is stuffed with as many spheres as possible, then we run periodic compression with PeriIsoCompressor, just like with randomDensePack. :param radius: mean sphere radius :param rRelFuzz: relative fuzz of sphere radius (equal distribution); see the same param for randomDensePack. :param initSize: initial size of the periodic cell. :return: SpherePack object, which also contains periodicity information. """ from math import pi sp=_getMemoizedPacking(memoizeDb,radius,rRelFuzz,initSize[0],initSize[1],initSize[2],fullDim=Vector3(0,0,0),wantPeri=True,fillPeriodic=False,spheresInCell=-1,memoDbg=True,noPrint=noPrint) if sp: return sp O.switchScene(); O.resetThisScene() sp=SpherePack() O.periodic=True #O.cell.refSize=initSize O.cell.setBox(initSize) sp.makeCloud(Vector3().Zero,O.cell.refSize,radius,rRelFuzz,-1,True) O.engines=[ForceResetter(),InsertionSortCollider([Bo1_Sphere_Aabb()],verletDist=.05*radius),InteractionLoop([Ig2_Sphere_Sphere_ScGeom()],[Ip2_FrictMat_FrictMat_FrictPhys()],[Law2_ScGeom_FrictPhys_CundallStrack()]),PeriIsoCompressor(charLen=2*radius,stresses=[-100e9,-1e8],maxUnbalanced=1e-2,doneHook='O.pause();',globalUpdateInt=20,keepProportions=True),NewtonIntegrator(damping=.8)] O.materials.append(FrictMat(young=30e9,frictionAngle=.1,poisson=.3,density=1e3)) for s in sp: O.bodies.append(utils.sphere(s[0],s[1])) O.dt=utils.PWaveTimeStep() O.timingEnabled=True O.run(); O.wait() ret=SpherePack() ret.fromSimulation() _memoizePacking(memoizeDb,ret,radius,rRelFuzz,wantPeri=True,fullDim=Vector3(0,0,0),noPrint=noPrint) # fullDim unused O.switchScene() return ret
def gengeo(mntable,shift=Vector3.Zero,scale=1.0,**kw): """ Imports geometry from LSMGenGeo library and creates spheres. Since 2012 the package is available in Debian/Ubuntu and known as python-demgengeo http://packages.qa.debian.org/p/python-demgengeo.html :Parameters: `mntable`: mntable object, which creates by LSMGenGeo library, see example `shift`: [float,float,float] [X,Y,Z] parameter moves the specimen. `scale`: float factor scales the given data. `**kw`: (unused keyword arguments) is passed to :yref:`yade.utils.sphere` LSMGenGeo library allows one to create pack of spheres with given [Rmin:Rmax] with null stress inside the specimen. Can be useful for Mining Rock simulation. Example: :ysrc:`examples/packs/packs.py`, usage of LSMGenGeo library in :ysrc:`examples/test/genCylLSM.py`. * https://answers.launchpad.net/esys-particle/+faq/877 * http://www.access.edu.au/lsmgengeo_python_doc/current/pythonapi/html/GenGeo-module.html * https://svn.esscc.uq.edu.au/svn/esys3/lsm/contrib/LSMGenGeo/""" try: from GenGeo import MNTable3D,Sphere except ImportError: from gengeo import MNTable3D,Sphere ret=[] sphereList=mntable.getSphereListFromGroup(0) for i in range(0, len(sphereList)): r=sphereList[i].Radius() c=sphereList[i].Centre() ret.append(utils.sphere([shift[0]+scale*float(c.X()),shift[1]+scale*float(c.Y()),shift[2]+scale*float(c.Z())],scale*float(r),**kw)) return ret
def testEraseBodiesInInteraction(self): O.reset() id1 = O.bodies.append(utils.sphere([0.5, 0.5, 0.0 + 0.095], .1)) id2 = O.bodies.append(utils.sphere([0.5, 0.5, 0.0 + 0.250], .1)) O.engines = [ ForceResetter(), InsertionSortCollider([Bo1_Sphere_Aabb()]), InteractionLoop([Ig2_Sphere_Sphere_L3Geom()], [Ip2_FrictMat_FrictMat_FrictPhys()], [Law2_L3Geom_FrictPhys_ElPerfPl()]), NewtonIntegrator(damping=0.1, gravity=(0, 0, -9.81)) ] O.dt = .5e-4 * utils.PWaveTimeStep() O.step() O.bodies.erase(id1) O.step()
def regularHexa(predicate, radius, gap, **kw): """Return set of spheres in regular hexagonal grid, clipped inside solid given by predicate. Created spheres will have given radius and will be separated by gap space.""" ret = [] a = 2 * radius + gap # thanks to Nasibeh Moradi for finding bug here: # http://www.mail-archive.com/[email protected]/msg01424.html hy, hz = a * sqrt(3) / 2., a * sqrt(6) / 3. mn, mx = predicate.aabb() dim = [mx[i] - mn[i] for i in 0, 1, 2] if (max(dim) == float('inf')): raise ValueError( "Aabb of the predicate must not be infinite (didn't you use union | instead of intersection & for unbounded predicate such as notInNotch?" ) ii, jj, kk = [ range(0, int(dim[0] / a) + 1), range(0, int(dim[1] / hy) + 1), range(0, int(dim[2] / hz) + 1) ] for i, j, k in itertools.product(ii, jj, kk): x, y, z = mn[0] + radius + i * a, mn[1] + radius + j * hy, mn[ 2] + radius + k * hz if j % 2 == 0: x += a / 2. if k % 2 == 0 else -a / 2. if k % 2 != 0: x += a / 2. y += hy / 2. if predicate((x, y, z), radius): ret += [utils.sphere((x, y, z), radius=radius, **kw)] return ret
def filterSpherePack(predicate, spherePack, returnSpherePack=None, **kw): """Using given SpherePack instance, return spheres the satisfy predicate. The packing will be recentered to match the predicate and warning is given if the predicate is larger than the packing.""" if returnSpherePack == None: warnings.warn( 'The default behavior will change; specify returnSpherePack=True for the new behavior, and False to get rid of this warning (your code will break in the future, however). The returned SpherePack object can be added to the simulation using SpherePack.toSimulation()', category=FutureWarning) returnSpherePack = False mn, mx = predicate.aabb() dimP, centP = predicate.dim(), predicate.center() dimS, centS = spherePack.dim(), spherePack.center() if dimP[0] > dimS[0] or dimP[1] > dimS[1] or dimP[2] > dimS[2]: warnings.warn( "Packing's dimension (%s) doesn't fully contain dimension of the predicate (%s)." % (dimS, dimP)) spherePack.translate(centP - centS) if returnSpherePack: ret = SpherePack() for c, r in spherePack: if predicate(c, r): ret.add(c, r) return ret else: # return particles to be added to O.bodies ret = [] for s in spherePack: if predicate(s[0], s[1]): ret += [utils.sphere(s[0], radius=s[1], **kw)] return ret
def randomPeriPack(radius,initSize,rRelFuzz=0.0,memoizeDb=None,noPrint=False): """Generate periodic dense packing. A cell of initSize is stuffed with as many spheres as possible, then we run periodic compression with PeriIsoCompressor, just like with randomDensePack. :param radius: mean sphere radius :param rRelFuzz: relative fuzz of sphere radius (equal distribution); see the same param for randomDensePack. :param initSize: initial size of the periodic cell. :return: SpherePack object, which also contains periodicity information. """ from math import pi sp=_getMemoizedPacking(memoizeDb,radius,rRelFuzz,initSize[0],initSize[1],initSize[2],fullDim=Vector3(0,0,0),wantPeri=True,fillPeriodic=False,spheresInCell=-1,memoDbg=True,noPrint=noPrint) if sp: return sp O.switchScene(); O.resetThisScene() sp=SpherePack() O.periodic=True #O.cell.refSize=initSize O.cell.setBox(initSize) sp.makeCloud(Vector3().Zero,O.cell.refSize,radius,rRelFuzz,-1,True) O.engines=[ForceResetter(),InsertionSortCollider([Bo1_Sphere_Aabb()],nBins=2,verletDist=.05*radius),InteractionLoop([Ig2_Sphere_Sphere_ScGeom()],[Ip2_FrictMat_FrictMat_FrictPhys()],[Law2_ScGeom_FrictPhys_CundallStrack()]),PeriIsoCompressor(charLen=2*radius,stresses=[-100e9,-1e8],maxUnbalanced=1e-2,doneHook='O.pause();',globalUpdateInt=20,keepProportions=True),NewtonIntegrator(damping=.8)] O.materials.append(FrictMat(young=30e9,frictionAngle=.1,poisson=.3,density=1e3)) for s in sp: O.bodies.append(utils.sphere(s[0],s[1])) O.dt=utils.PWaveTimeStep() O.timingEnabled=True O.run(); O.wait() ret=SpherePack() ret.fromSimulation() _memoizePacking(memoizeDb,ret,radius,rRelFuzz,wantPeri=True,fullDim=Vector3(0,0,0),noPrint=noPrint) # fullDim unused O.switchScene() return ret
def testEraseBodiesInInteraction(self): O.reset() id1 = O.bodies.append(utils.sphere([0.5,0.5,0.0+0.095],.1)) id2 = O.bodies.append(utils.sphere([0.5,0.5,0.0+0.250],.1)) O.engines=[ ForceResetter(), InsertionSortCollider([Bo1_Sphere_Aabb()]), InteractionLoop( [Ig2_Sphere_Sphere_L3Geom()], [Ip2_FrictMat_FrictMat_FrictPhys()], [Law2_L3Geom_FrictPhys_ElPerfPl()] ), NewtonIntegrator(damping=0.1,gravity=(0,0,-9.81)) ] O.dt=.5e-4*utils.PWaveTimeStep() O.step() O.bodies.erase(id1) O.step()
def textExt(fileName,format='x_y_z_r',shift=Vector3.Zero,scale=1.0,attrs=[],**kw): """Load sphere coordinates from file in specific format, returns a list of corresponding bodies; that may be inserted to the simulation with O.bodies.append(). :param str filename: file name :param str format: the name of output format. Supported `x_y_z_r`(default), `x_y_z_r_matId`, 'x_y_z_r_attrs' :param [float,float,float] shift: [X,Y,Z] parameter moves the specimen. :param float scale: factor scales the given data. :param list attrs: attrs read from file if export.textExt(format='x_y_z_r_attrs') were used ('passed by refernece' style) :param \*\*kw: (unused keyword arguments) is passed to :yref:`yade.utils.sphere` :returns: list of spheres. Lines starting with # are skipped """ infile = open(fileName,"r") lines = infile.readlines() infile.close() ret=[] for line in lines: data = line.split() if (data[0] == "#format"): format=data[1] continue elif (data[0][0] == "#"): continue if (format=='x_y_z_r'): pos = Vector3(float(data[0]),float(data[1]),float(data[2])) ret.append(utils.sphere(shift+scale*pos,scale*float(data[3]),**kw)) elif (format=='x_y_z_r_matId'): pos = Vector3(float(data[0]),float(data[1]),float(data[2])) ret.append(utils.sphere(shift+scale*pos,scale*float(data[3]),material=int(data[4]),**kw)) elif (format=='id_x_y_z_r_matId'): pos = Vector3(float(data[1]),float(data[2]),float(data[3])) ret.append(utils.sphere(shift+scale*pos,scale*float(data[4]),material=int(data[5]),**kw)) elif (format=='x_y_z_r_attrs'): pos = Vector3(float(data[0]),float(data[1]),float(data[2])) s = utils.sphere(shift+scale*pos,scale*float(data[3]),**kw) ret.append(s) attrs.append(data[4:]) else: raise RuntimeError("Please, specify a correct format output!"); return ret
def regularOrtho(predicate,radius,gap,**kw): """Return set of spheres in regular orthogonal grid, clipped inside solid given by predicate. Created spheres will have given radius and will be separated by gap space.""" ret=[] mn,mx=predicate.aabb() if(max([mx[i]-mn[i] for i in 0,1,2])==float('inf')): raise ValueError("Aabb of the predicate must not be infinite (didn't you use union | instead of intersection & for unbounded predicate such as notInNotch?"); xx,yy,zz=[arange(mn[i]+radius,mx[i]-radius,2*radius+gap) for i in 0,1,2] for xyz in itertools.product(xx,yy,zz): if predicate(xyz,radius): ret+=[utils.sphere(xyz,radius=radius,**kw)] return ret
def setUp(self): O.reset() self.count = 100 O.bodies.append([ utils.sphere([random.random(), random.random(), random.random()], random.random()) for i in range(0, self.count) ]) random.seed()
def textClumps(fileName,shift=Vector3.Zero,discretization=0,orientation=Quaternion((0,1,0),0.0),scale=1.0,**kw): """Load clumps-members from file, insert them to the simulation. :param str filename: file name :param str format: the name of output format. Supported `x_y_z_r`(default), `x_y_z_r_clumpId` :param [float,float,float] shift: [X,Y,Z] parameter moves the specimen. :param float scale: factor scales the given data. :param \*\*kw: (unused keyword arguments) is passed to :yref:`yade.utils.sphere` :returns: list of spheres. Lines starting with # are skipped """ infile = open(fileName,"r") lines = infile.readlines() infile.close() ret=[] curClump=[] newClumpId = -1 for line in lines: data = line.split() if (data[0][0] == "#"): continue pos = orientation*Vector3(float(data[0]),float(data[1]),float(data[2])) if (newClumpId<0 or newClumpId==int(data[4])): idD = curClump.append(utils.sphere(shift+scale*pos,scale*float(data[3]),**kw)) newClumpId = int(data[4]) else: newClumpId = int(data[4]) ret.append(O.bodies.appendClumped(curClump,discretization=discretization)) curClump=[] idD = curClump.append(utils.sphere(shift+scale*pos,scale*float(data[3]),**kw)) if (len(curClump)<>0): ret.append(O.bodies.appendClumped(curClump,discretization=discretization)) # Set the mask to a clump the same as the first member of it for i in range(len(ret)): O.bodies[ret[i][0]].mask = O.bodies[ret[i][1][0]].mask return ret
def textExt(fileName,format='x_y_z_r',shift=Vector3.Zero,scale=1.0,**kw): """Load sphere coordinates from file in specific format, create spheres, insert them to the simulation. :Parameters: `filename`: string `format`: the name of output format. Supported `x_y_z_r`(default), `x_y_z_r_matId` `shift`: [float,float,float] [X,Y,Z] parameter moves the specimen. `scale`: float factor scales the given data. `**kw`: (unused keyword arguments) is passed to :yref:`yade.utils.sphere` :Returns: list of spheres. Lines starting with # are skipped """ infile = open(fileName,"r") lines = infile.readlines() infile.close() ret=[] for line in lines: data = line.split() if (data[0] == "#format"): format=data[1] continue elif (data[0][0] == "#"): continue if (format=='x_y_z_r'): pos = Vector3(float(data[0]),float(data[1]),float(data[2])) ret.append(utils.sphere(shift+scale*pos,scale*float(data[3]),**kw)) elif (format=='x_y_z_r_matId'): pos = Vector3(float(data[0]),float(data[1]),float(data[2])) ret.append(utils.sphere(shift+scale*pos,scale*float(data[3]),material=int(data[4]),**kw)) elif (format=='id_x_y_z_r_matId'): pos = Vector3(float(data[1]),float(data[2]),float(data[3])) ret.append(utils.sphere(shift+scale*pos,scale*float(data[4]),material=int(data[5]),**kw)) else: raise RuntimeError("Please, specify a correct format output!"); return ret
def fill_cylinder_with_spheres(sphereRadius,cylinderRadius,cylinderHeight,cylinderOrigin,cylinderSlope): spheresCount=0 for h in xrange(0,int(cylinderHeight/sphereRadius/2)): for r in xrange(1,int(cylinderRadius/sphereRadius/2)): dfi = asin(0.5/r)*2 for a in xrange(0,int(6.28/dfi)): x = cylinderOrigin[0]+2*r*sphereRadius*cos(dfi*a) y = cylinderOrigin[1]+2*r*sphereRadius*sin(dfi*a) z = cylinderOrigin[2]+h*2*sphereRadius s=utils.sphere([x,y*cos(cylinderSlope)+z*sin(cylinderSlope),z*cos(cylinderSlope)-y*sin(cylinderSlope)],sphereRadius) O.bodies.append(s) spheresCount+=1 return spheresCount
def testUserCreatedInteraction(self): O.engines = [ ForceResetter(), InsertionSortCollider( [Bo1_Sphere_Aabb(), Bo1_Facet_Aabb(), Bo1_Box_Aabb()], label="collider"), InteractionLoop( [ Ig2_Sphere_Sphere_ScGeom(), Ig2_Facet_Sphere_ScGeom(), Ig2_Box_Sphere_ScGeom() ], [Ip2_FrictMat_FrictMat_FrictPhys()], #for linear model only [Law2_ScGeom_FrictPhys_CundallStrack(label="law") ], #for linear model only label="interactionLoop"), GlobalStiffnessTimeStepper(timeStepUpdateInterval=10, label="timeStepper"), NewtonIntegrator(label="newton") ] O.bodies.append([ utils.sphere((0, 0, 0), 0.5), utils.sphere((2, 0, 0), 0.5), #(0,1) no overlap , no contacts utils.sphere((0.9, 0.9, 0), 0.5), #(0,2) overlapping bounds, no contacts utils.sphere((-0.99, 0, 0), 0.5) ]) #(0,3) overlaping + contact O.dt = 0 O.dynDt = False O.step() i = utils.createInteraction(0, 1) self.assert_(i.iterBorn == 1 and i.iterMadeReal == 1) j = utils.createInteraction(0, 2) self.assert_(j.iterBorn == 1 and j.iterMadeReal == 1) self.assertRaises(RuntimeError, lambda: utils.createInteraction(0, 3))
def fill_cylinder_with_spheres(sphereRadius, cylinderRadius, cylinderHeight, cylinderOrigin, cylinderSlope): spheresCount = 0 for h in xrange(0, int(cylinderHeight / sphereRadius / 2)): for r in xrange(1, int(cylinderRadius / sphereRadius / 2)): dfi = asin(0.5 / r) * 2 for a in xrange(0, int(6.28 / dfi)): x = cylinderOrigin[0] + 2 * r * sphereRadius * cos(dfi * a) y = cylinderOrigin[1] + 2 * r * sphereRadius * sin(dfi * a) z = cylinderOrigin[2] + h * 2 * sphereRadius s = utils.sphere([ x, y * cos(cylinderSlope) + z * sin(cylinderSlope), z * cos(cylinderSlope) - y * sin(cylinderSlope) ], sphereRadius) O.bodies.append(s) spheresCount += 1 return spheresCount
def gengeoFile(fileName="file.geo", shift=Vector3.Zero, scale=1.0, orientation=Quaternion((0, 1, 0), 0.0), **kw): """ Imports geometry from LSMGenGeo .geo file and creates spheres. Since 2012 the package is available in Debian/Ubuntu and known as python-demgengeo http://packages.qa.debian.org/p/python-demgengeo.html :Parameters: `filename`: string file which has 4 colums [x, y, z, radius]. `shift`: Vector3 Vector3(X,Y,Z) parameter moves the specimen. `scale`: float factor scales the given data. `orientation`: quaternion orientation of the imported geometry `**kw`: (unused keyword arguments) is passed to :yref:`yade.utils.sphere` :Returns: list of spheres. LSMGenGeo library allows one to create pack of spheres with given [Rmin:Rmax] with null stress inside the specimen. Can be useful for Mining Rock simulation. Example: :ysrc:`examples/packs/packs.py`, usage of LSMGenGeo library in :ysrc:`examples/test/genCylLSM.py`. * https://answers.launchpad.net/esys-particle/+faq/877 * http://www.access.edu.au/lsmgengeo_python_doc/current/pythonapi/html/GenGeo-module.html * https://svn.esscc.uq.edu.au/svn/esys3/lsm/contrib/LSMGenGeo/""" from yade.utils import sphere infile = open(fileName, "r") lines = infile.readlines() infile.close() numSpheres = int(lines[6].split()[0]) ret = [] for line in lines[7:numSpheres + 7]: data = line.split() pos = orientation * Vector3(float(data[0]), float(data[1]), float(data[2])) ret.append( utils.sphere(shift + scale * pos, scale * float(data[3]), **kw)) return ret
def regularHexa(predicate,radius,gap,**kw): """Return set of spheres in regular hexagonal grid, clipped inside solid given by predicate. Created spheres will have given radius and will be separated by gap space.""" ret=[] a=2*radius+gap hy,hz=a*sqrt(3)/2.,a*sqrt(6)/3. mn,mx=predicate.aabb() dim=[mx[i]-mn[i] for i in 0,1,2] if(max(dim)==float('inf')): raise ValueError("Aabb of the predicate must not be infinite (didn't you use union | instead of intersection & for unbounded predicate such as notInNotch?"); ii,jj,kk=[range(0,int(dim[0]/a)+1),range(0,int(dim[1]/hy)+1),range(0,int(dim[2]/hz)+1)] for i,j,k in itertools.product(ii,jj,kk): #Simple HCP-lattice packing #http://en.wikipedia.org/wiki/Close-packing_of_equal_spheres#Simple_hcp_lattice coordSph = Vector3((2*i + ((j + k) % 2 ) ), (sqrt(3.)*(j + 1./3.*(k % 2))), (2.*sqrt(6.)/3.*k))*(a/2.0) + mn if predicate(coordSph,radius): ret+=[utils.sphere(coordSph,radius=radius,**kw)] if (len(ret)==0): warnings.warn('No spheres are produced by regularHexa-function',category=RuntimeWarning) return ret
def testMatchMakerCollisions(self): fr = 0.5;rho=2000 tc = 0.001; en = 0.5; et = 0.5; mat1 = O.materials.append(ViscElMat(frictionAngle=fr,tc=tc,en=en,et=et,density=rho)) mat2 = O.materials.append(ViscElMat(frictionAngle=fr,tc=tc,en=en,et=et,density=rho)) mat3 = O.materials.append(ViscElMat(frictionAngle=fr,tc=tc,en=en,et=et,density=rho)) r1 = 0.002381 r2 = 0.002381 id11 = O.bodies.append(utils.sphere(center=[0,0,0],radius=r1,material=mat1,fixed=True,color=[0,0,1])) id12 = O.bodies.append(utils.sphere(center=[0,0,(r1+r2)],radius=r2,material=mat2,fixed=False,color=[0,0,1])) id21 = O.bodies.append(utils.sphere(center=[3*r1,0,0],radius=r1,material=mat1,fixed=True,color=[0,1,0])) id22 = O.bodies.append(utils.sphere(center=[3*r1,0,(r1+r2)],radius=r2,material=mat3,fixed=False,color=[0,1,0])) id31 = O.bodies.append(utils.sphere(center=[6*r1,0,0],radius=r1,material=mat2,fixed=True,color=[1,0,0])) id32 = O.bodies.append(utils.sphere(center=[6*r1,0,(r1+r2)],radius=r2,material=mat3,fixed=False,color=[1,0,0])) O.engines = [ ForceResetter(), InsertionSortCollider([Bo1_Sphere_Aabb()],verletDist=r1*10.0), InteractionLoop( [Ig2_Sphere_Sphere_ScGeom()], [Ip2_ViscElMat_ViscElMat_ViscElPhys( en=MatchMaker(matches=((mat1,mat2,.1),(mat1,mat3,.2),(mat2,mat3,.4))), et=MatchMaker(matches=((mat1,mat2,.7),(mat1,mat3,.8),(mat2,mat3,.9))), frictAngle=MatchMaker(matches=((mat1,mat2,.1),(mat1,mat3,.2),(mat2,mat3,.3))) )], [Law2_ScGeom_ViscElPhys_Basic()], ), NewtonIntegrator(damping=0,gravity=[0,0,-9.81]), ] O.step() self.assertTrue((atan(O.interactions[id11,id12].phys.tangensOfFrictionAngle)-0.1)==0) if(yade.math.needsMpmathAtN(1)): # looks like with high precision there are some dangling bits at the end self.assertAlmostEqual(atan(O.interactions[id21,id22].phys.tangensOfFrictionAngle),0.2) else: self.assertTrue((atan(O.interactions[id21,id22].phys.tangensOfFrictionAngle)-0.2)==0) self.assertTrue((atan(O.interactions[id31,id32].phys.tangensOfFrictionAngle)-0.3)==0) self.assertTrue(round(O.interactions[id11,id12].phys.cn, 3) - 0.26 == 0) self.assertTrue(round(O.interactions[id21,id22].phys.cn, 3) - 0.182 == 0) self.assertTrue(round(O.interactions[id31,id32].phys.cn, 3) - 0.104 == 0) self.assertTrue(round(O.interactions[id11,id12].phys.cs, 3) - 0.012== 0) self.assertTrue(round(O.interactions[id21,id22].phys.cs, 3) - 0.007 == 0) self.assertTrue(round(O.interactions[id31,id32].phys.cs, 3) - 0.003 == 0)
def gengeoFile(fileName="file.geo",shift=Vector3.Zero,scale=1.0,orientation=Quaternion((0,1,0),0.0),**kw): """ Imports geometry from LSMGenGeo .geo file and creates spheres. Since 2012 the package is available in Debian/Ubuntu and known as python-demgengeo http://packages.qa.debian.org/p/python-demgengeo.html :Parameters: `filename`: string file which has 4 colums [x, y, z, radius]. `shift`: Vector3 Vector3(X,Y,Z) parameter moves the specimen. `scale`: float factor scales the given data. `orientation`: quaternion orientation of the imported geometry `**kw`: (unused keyword arguments) is passed to :yref:`yade.utils.sphere` :Returns: list of spheres. LSMGenGeo library allows one to create pack of spheres with given [Rmin:Rmax] with null stress inside the specimen. Can be useful for Mining Rock simulation. Example: :ysrc:`examples/packs/packs.py`, usage of LSMGenGeo library in :ysrc:`examples/test/genCylLSM.py`. * https://answers.launchpad.net/esys-particle/+faq/877 * http://www.access.edu.au/lsmgengeo_python_doc/current/pythonapi/html/GenGeo-module.html * https://svn.esscc.uq.edu.au/svn/esys3/lsm/contrib/LSMGenGeo/""" from yade.utils import sphere infile = open(fileName,"r") lines = infile.readlines() infile.close() numSpheres = int(lines[6].split()[0]) ret=[] for line in lines[7:numSpheres+7]: data = line.split() pos = orientation*Vector3(float(data[0]),float(data[1]),float(data[2])) ret.append(utils.sphere(shift+scale*pos,scale*float(data[3]),**kw)) return ret
def testMatchMakerCollisions(self): fr = 0.5;rho=2000 tc = 0.001; en = 0.5; et = 0.5; mat1 = O.materials.append(ViscElMat(frictionAngle=fr,tc=tc,en=en,et=et,density=rho)) mat2 = O.materials.append(ViscElMat(frictionAngle=fr,tc=tc,en=en,et=et,density=rho)) mat3 = O.materials.append(ViscElMat(frictionAngle=fr,tc=tc,en=en,et=et,density=rho)) r1 = 0.002381 r2 = 0.002381 id11 = O.bodies.append(utils.sphere(center=[0,0,0],radius=r1,material=mat1,fixed=True,color=[0,0,1])) id12 = O.bodies.append(utils.sphere(center=[0,0,(r1+r2)],radius=r2,material=mat2,fixed=False,color=[0,0,1])) id21 = O.bodies.append(utils.sphere(center=[3*r1,0,0],radius=r1,material=mat1,fixed=True,color=[0,1,0])) id22 = O.bodies.append(utils.sphere(center=[3*r1,0,(r1+r2)],radius=r2,material=mat3,fixed=False,color=[0,1,0])) id31 = O.bodies.append(utils.sphere(center=[6*r1,0,0],radius=r1,material=mat2,fixed=True,color=[1,0,0])) id32 = O.bodies.append(utils.sphere(center=[6*r1,0,(r1+r2)],radius=r2,material=mat3,fixed=False,color=[1,0,0])) O.engines = [ ForceResetter(), InsertionSortCollider([Bo1_Sphere_Aabb()],verletDist=r1*10.0), InteractionLoop( [Ig2_Sphere_Sphere_ScGeom()], [Ip2_ViscElMat_ViscElMat_ViscElPhys( en=MatchMaker(matches=((mat1,mat2,.1),(mat1,mat3,.2),(mat2,mat3,.4))), et=MatchMaker(matches=((mat1,mat2,.7),(mat1,mat3,.8),(mat2,mat3,.9))), frictAngle=MatchMaker(matches=((mat1,mat2,.1),(mat1,mat3,.2),(mat2,mat3,.3))) )], [Law2_ScGeom_ViscElPhys_Basic()], ), NewtonIntegrator(damping=0,gravity=[0,0,-9.81]), ] O.step() self.assertTrue((atan(O.interactions[id11,id12].phys.tangensOfFrictionAngle)-0.1)==0) self.assertTrue((atan(O.interactions[id21,id22].phys.tangensOfFrictionAngle)-0.2)==0) self.assertTrue((atan(O.interactions[id31,id32].phys.tangensOfFrictionAngle)-0.3)==0) self.assertTrue(round(O.interactions[id11,id12].phys.cn, 3) - 0.26 == 0) self.assertTrue(round(O.interactions[id21,id22].phys.cn, 3) - 0.182 == 0) self.assertTrue(round(O.interactions[id31,id32].phys.cn, 3) - 0.104 == 0) self.assertTrue(round(O.interactions[id11,id12].phys.cs, 3) - 0.012== 0) self.assertTrue(round(O.interactions[id21,id22].phys.cs, 3) - 0.007 == 0) self.assertTrue(round(O.interactions[id31,id32].phys.cs, 3) - 0.003 == 0)
def testKinematicEngines(self): 'Engines: kinematic engines' tolerance = 1e-5 rotIndex=1.0 angVelTemp = pi/rotIndex O.reset() id_fixed_transl = O.bodies.append(utils.sphere((0.0,0.0,0.0),1.0,fixed=True)) id_nonfixed_transl = O.bodies.append(utils.sphere((0.0,5.0,0.0),1.0,fixed=False)) id_fixed_rot = O.bodies.append(utils.sphere((0.0,10.0,10.0),1.0,fixed=True)) id_nonfixed_rot = O.bodies.append(utils.sphere((0.0,15.0,10.0),1.0,fixed=False)) id_fixed_helix = O.bodies.append(utils.sphere((0.0,20.0,10.0),1.0,fixed=True)) id_nonfixed_helix = O.bodies.append(utils.sphere((0.0,25.0,10.0),1.0,fixed=False)) O.engines=[ TranslationEngine(velocity = 1.0, translationAxis = [1.0,0,0], ids = [id_fixed_transl]), TranslationEngine(velocity = 1.0, translationAxis = [1.0,0,0], ids = [id_nonfixed_transl]), RotationEngine(angularVelocity = pi/angVelTemp, rotationAxis = [0.0,1.0,0.0], rotateAroundZero = True, zeroPoint = [0.0,0.0,0.0], ids = [id_fixed_rot]), RotationEngine(angularVelocity = pi/angVelTemp, rotationAxis = [0.0,1.0,0.0], rotateAroundZero = True, zeroPoint = [0.0,5.0,0.0], ids = [id_nonfixed_rot]), HelixEngine(angularVelocity = pi/angVelTemp, rotationAxis = [0.0,1.0,0.0], linearVelocity = 1.0, zeroPoint = [0.0,0.0,0.0], ids = [id_fixed_helix]), HelixEngine(angularVelocity = pi/angVelTemp, rotationAxis = [0.0,1.0,0.0], linearVelocity = 1.0, zeroPoint = [0.0,5.0,0.0], ids = [id_nonfixed_helix]), ForceResetter(), NewtonIntegrator() ] O.dt = 1.0 for i in range(0,2): O.step() self.assertTrue(abs(O.bodies[id_fixed_transl].state.pos[0] - O.iter) < tolerance) #Check translation of fixed bodies self.assertTrue(abs(O.bodies[id_nonfixed_transl].state.pos[0] - O.iter) < tolerance) #Check translation of nonfixed bodies self.assertTrue(abs(O.bodies[id_fixed_rot].state.pos[0]-10.0*sin(pi/angVelTemp*O.iter))<tolerance) #Check rotation of fixed bodies X self.assertTrue(abs(O.bodies[id_fixed_rot].state.pos[2]-10.0*cos(pi/angVelTemp*O.iter))<tolerance) #Check rotation of fixed bodies Y self.assertTrue(abs(O.bodies[id_fixed_rot].state.ori.toAxisAngle()[1]-Quaternion(Vector3(0.0,1.0,0.0),pi/angVelTemp*O.iter).toAxisAngle()[1])<tolerance) #Check rotation of fixed bodies, angle self.assertTrue(abs(O.bodies[id_nonfixed_rot].state.pos[0] - 10*sin(pi/angVelTemp*O.iter))<tolerance) #Check rotation of nonfixed bodies X self.assertTrue(abs(O.bodies[id_nonfixed_rot].state.pos[2] - 10*cos(pi/angVelTemp*O.iter))<tolerance) #Check rotation of nonfixed bodies Y self.assertTrue(abs(O.bodies[id_nonfixed_rot].state.ori.toAxisAngle()[1]-Quaternion(Vector3(0.0,1.0,0.0),pi/angVelTemp*O.iter).toAxisAngle()[1])<tolerance) #Check rotation of nonfixed bodies, angle self.assertTrue(abs(O.bodies[id_fixed_helix].state.pos[0] - 10*sin(pi/angVelTemp*O.iter))<tolerance) #Check helixEngine of fixed bodies X self.assertTrue(abs(O.bodies[id_fixed_helix].state.pos[2] - 10*cos(pi/angVelTemp*O.iter))<tolerance) #Check helixEngine of fixed bodies Y self.assertTrue(abs(O.bodies[id_fixed_helix].state.pos[1]-20.0 - O.iter)<tolerance) #Check helixEngine of fixed bodies Z self.assertTrue(abs(O.bodies[id_nonfixed_helix].state.pos[0] - 10*sin(pi/angVelTemp*O.iter))<tolerance) #Check helixEngine of nonfixed bodies X self.assertTrue(abs(O.bodies[id_nonfixed_helix].state.pos[2] - 10*cos(pi/angVelTemp*O.iter))<tolerance) #Check helixEngine of nonfixed bodies Y self.assertTrue(abs(O.bodies[id_nonfixed_helix].state.pos[1]-25.0 - O.iter)<tolerance) #Check helixEngine of nonfixed bodies Z
from yade import * from yade import utils, export O.bodies.append([ utils.sphere((0, 0, 0), 1), utils.sphere((0, 2, 0), 1), utils.sphere((0, 2, 3), 2), utils.facet([Vector3(0, -3, -1), Vector3(0, -2, 5), Vector3(5, 4, 0)]), utils.facet([Vector3(0, -3, -1), Vector3(0, -2, 5), Vector3(-5, 4, 0)]) ]) vtkExporter = export.VTKExporter('vtkExporterTesting') vtkExporter.exportSpheres(what=[('dist', 'b.state.pos.norm()')]) vtkExporter.exportFacets(what=[('pos', 'b.state.pos')])
[Law2_ScGeom_FrictPhys_CundallStrack()]), NewtonIntegrator(damping=.2, gravity=(0, 0, -9.81)), ### ### NOTE this extra engine: ### ### You want snapshot to be taken every 1 sec (realTimeLim) or every 50 iterations (iterLim), ### whichever comes soones. virtTimeLim attribute is unset, hence virtual time period is not taken into account. PyRunner(iterPeriod=20, command='myAddPlotData()') ] from yade import utils O.bodies.append( utils.box(center=[0, 0, 0], extents=[.5, .5, .5], fixed=True, color=[1, 0, 0])) O.bodies.append(utils.sphere([0, 0, 2], 1, color=[0, 1, 0])) O.dt = .002 * utils.PWaveTimeStep() ############################################ ##### now the part pertaining to plots ##### ############################################ from math import * from yade import plot ## we will have 2 plots: ## 1. t as function of i (joke test function) ## 2. i as function of t on left y-axis ('|||' makes the separation) and z_sph, v_sph (as green circles connected with line) and z_sph_half again as function of t plot.plots = {'i': ('t'), 't': ('z_sph', None, ('v_sph', 'go-'), 'z_sph_half')} ## this function is called by plotDataCollector
""" Show basic wall functionality (infinite axis-aligned planes). """ from yade import utils O.materials.append(FrictMat(young=30e9,density=1000,poisson=.2,frictionAngle=.5) O.bodies.append([ utils.wall(1,axis=2,sense=-1), utils.wall(-5,axis=0,sense=1), utils.wall(1,axis=1), utils.wall((1,0,0),0), utils.sphere([0,0,0],.5), utils.sphere([-5,-4,-3],.5) ]) Gl1_Wall(div=10) from yade import qt qt.Controller() qt.View() O.engines=[ ForceResetter(), InsertionSortCollider([Bo1_Sphere_Aabb(),Bo1_Facet_Aabb(),Bo1_Wall_Aabb()]), InteractionLoop( [Ig2_Sphere_Sphere_Dem3DofGeom(),Ig2_Facet_Sphere_Dem3DofGeom(),Ig2_Wall_Sphere_Dem3DofGeom()], [Ip2_FrictMat_FrictMat_FrictPhys()], [Law2_Dem3DofGeom_FrictPhys_CundallStrack()], ), GravityEngine(gravity=[1e2,1e2,1e2]), NewtonIntegrator(damping=0.01), ]
poisson=poisson, density=4800, sigmaT=sigmaT, crackOpening=crackOpening, epsCrackOnset=epsCrackOnset, poisson=poisson, isoPrestress=isoPrestress)) sphDict = pickle.load(open(packingFile)) from yade import pack sp = pack.SpherePack() sp.fromList(sphDict['spheres']) sp.cellSize = sphDict['cell'] import numpy avgRadius = numpy.average([r for c, r in sp]) O.bodies.append([utils.sphere(c, r, color=utils.randomColor()) for c, r in sp]) O.periodic = True #O.cell.setBox=sp.cellSize #doesnt work correctly, periodic cell is too big!!!! O.cell.refSize = sp.cellSize axis = 2 ax1 = (axis + 1) % 3 ax2 = (axis + 2) % 3 O.dt = dtSafety * utils.PWaveTimeStep() import yade.plot as yp O.engines = [ ForceResetter(), InsertionSortCollider([ Bo1_Sphere_Aabb(aabbEnlargeFactor=intRadius, label='is2aabb'), ]),
def randomDensePack(predicate, radius, material=-1, dim=None, cropLayers=0, rRelFuzz=0., spheresInCell=0, memoizeDb=None, useOBB=False, memoDbg=False, color=None, returnSpherePack=None, seed=0): """Generator of random dense packing with given geometry properties, using TriaxialTest (aperiodic) or PeriIsoCompressor (periodic). The periodicity depens on whether the spheresInCell parameter is given. *O.switchScene()* magic is used to have clean simulation for TriaxialTest without deleting the original simulation. This function therefore should never run in parallel with some code accessing your simulation. :param predicate: solid-defining predicate for which we generate packing :param spheresInCell: if given, the packing will be periodic, with given number of spheres in the periodic cell. :param radius: mean radius of spheres :param rRelFuzz: relative fuzz of the radius -- e.g. radius=10, rRelFuzz=.2, then spheres will have radii 10 ± (10*.2)), with an uniform distribution. 0 by default, meaning all spheres will have exactly the same radius. :param cropLayers: (aperiodic only) how many layers of spheres will be added to the computed dimension of the box so that there no (or not so much, at least) boundary effects at the boundaries of the predicate. :param dim: dimension of the packing, to override dimensions of the predicate (if it is infinite, for instance) :param memoizeDb: name of sqlite database (existent or nonexistent) to find an already generated packing or to store the packing that will be generated, if not found (the technique of caching results of expensive computations is known as memoization). Fuzzy matching is used to select suitable candidate -- packing will be scaled, rRelFuzz and dimensions compared. Packing that are too small are dictarded. From the remaining candidate, the one with the least number spheres will be loaded and returned. :param useOBB: effective only if a inGtsSurface predicate is given. If true (not default), oriented bounding box will be computed first; it can reduce substantially number of spheres for the triaxial compression (like 10× depending on how much asymmetric the body is), see examples/gts-horse/gts-random-pack-obb.py :param memoDbg: show packings that are considered and reasons why they are rejected/accepted :param returnSpherePack: see the corresponding argument in :yref:`yade.pack.filterSpherePack` :return: SpherePack object with spheres, filtered by the predicate. """ import sqlite3, os.path, pickle, time, sys, numpy from math import pi from yade import _packPredicates wantPeri = (spheresInCell > 0) if 'inGtsSurface' in dir(_packPredicates) and type( predicate) == inGtsSurface and useOBB: center, dim, orientation = gtsSurfaceBestFitOBB(predicate.surf) print( "Best-fit oriented-bounding-box computed for GTS surface, orientation is", orientation) dim *= 2 # gtsSurfaceBestFitOBB returns halfSize else: if not dim: dim = predicate.dim() if max(dim) == float('inf'): raise RuntimeError( "Infinite predicate and no dimension of packing requested.") center = predicate.center() orientation = None if not wantPeri: fullDim = tuple([dim[i] + 4 * cropLayers * radius for i in (0, 1, 2)]) else: # compute cell dimensions now, as they will be compared to ones stored in the db # they have to be adjusted to not make the cell to small WRT particle radius fullDim = dim cloudPorosity = 0.25 # assume this number for the initial cloud (can be underestimated) beta, gamma = fullDim[1] / fullDim[0], fullDim[2] / fullDim[ 0] # ratios β=y₀/x₀, γ=z₀/x₀ N100 = spheresInCell / cloudPorosity # number of spheres for cell being filled by spheres without porosity x1 = radius * (1 / (beta * gamma) * N100 * (4 / 3.) * pi)**(1 / 3.) y1, z1 = beta * x1, gamma * x1 vol0 = x1 * y1 * z1 maxR = radius * (1 + rRelFuzz) x1 = max(x1, 8 * maxR) y1 = max(y1, 8 * maxR) z1 = max(z1, 8 * maxR) vol1 = x1 * y1 * z1 N100 *= vol1 / vol0 # volume might have been increased, increase number of spheres to keep porosity the same sp = _getMemoizedPacking(memoizeDb, radius, rRelFuzz, x1, y1, z1, fullDim, wantPeri, fillPeriodic=True, spheresInCell=spheresInCell, memoDbg=False) if sp: if orientation: sp.cellSize = ( 0, 0, 0) # resetting cellSize avoids warning when rotating sp.rotate(*orientation.toAxisAngle()) return filterSpherePack(predicate, sp, material=material, returnSpherePack=returnSpherePack) else: print("No suitable packing in database found, running", 'PERIODIC compression' if wantPeri else 'triaxial') sys.stdout.flush() O.switchScene() O.resetThisScene() ### !! if wantPeri: # x1,y1,z1 already computed above sp = SpherePack() O.periodic = True #O.cell.refSize=(x1,y1,z1) O.cell.setBox((x1, y1, z1)) #print cloudPorosity,beta,gamma,N100,x1,y1,z1,O.cell.refSize #print x1,y1,z1,radius,rRelFuzz O.materials.append(FrictMat(young=3e10, density=2400)) num = sp.makeCloud(Vector3().Zero, O.cell.refSize, radius, rRelFuzz, spheresInCell, True) O.engines = [ ForceResetter(), InsertionSortCollider([Bo1_Sphere_Aabb()], verletDist=.05 * radius), InteractionLoop([Ig2_Sphere_Sphere_ScGeom()], [Ip2_FrictMat_FrictMat_FrictPhys()], [Law2_ScGeom_FrictPhys_CundallStrack()]), PeriIsoCompressor(charLen=2 * radius, stresses=[-100e9, -1e8], maxUnbalanced=1e-2, doneHook='O.pause();', globalUpdateInt=5, keepProportions=True), NewtonIntegrator(damping=.6) ] O.materials.append( FrictMat(young=30e9, frictionAngle=.5, poisson=.3, density=1e3)) for s in sp: O.bodies.append(utils.sphere(s[0], s[1])) O.dt = utils.PWaveTimeStep() O.run() O.wait() sp = SpherePack() sp.fromSimulation() #print 'Resulting cellSize',sp.cellSize,'proportions',sp.cellSize[1]/sp.cellSize[0],sp.cellSize[2]/sp.cellSize[0] # repetition to the required cell size will be done below, after memoizing the result else: assumedFinalDensity = 0.6 V = (4.0 / 3.0) * pi * radius**3.0 N = assumedFinalDensity * fullDim[0] * fullDim[1] * fullDim[2] / V TriaxialTest( numberOfGrains=int(N), radiusMean=radius, radiusStdDev=rRelFuzz, # upperCorner is just size ratio, if radiusMean is specified upperCorner=fullDim, seed=seed, ## no need to touch any the following noFiles=True, lowerCorner=[0, 0, 0], sigmaIsoCompaction=-4e4, sigmaLateralConfinement=-5e2, compactionFrictionDeg=1, StabilityCriterion=.02, strainRate=.2, thickness=0, maxWallVelocity=.1, wallOversizeFactor=1.5, autoUnload=True, autoCompressionActivation=False, internalCompaction=True).load() while (numpy.isnan(utils.unbalancedForce()) or utils.unbalancedForce() > 0.005): O.run(500, True) sp = SpherePack() sp.fromSimulation() O.switchScene() ### !! _memoizePacking(memoizeDb, sp, radius, rRelFuzz, wantPeri, fullDim) if wantPeri: sp.cellFill(Vector3(fullDim[0], fullDim[1], fullDim[2])) if orientation: sp.cellSize = (0, 0, 0) # reset periodicity to avoid warning when rotating periodic packing sp.rotate(*orientation.toAxisAngle()) return filterSpherePack(predicate, sp, material=material, color=color, returnSpherePack=returnSpherePack)
def hexaNet( radius, cornerCoord=[0,0,0], xLength=1., yLength=0.5, mos=0.08, a=0.04, b=0.04, startAtCorner=True, isSymmetric=False, **kw ): """Definition of the particles for a hexagonal wire net in the x-y-plane for the WireMatPM. :param radius: radius of the particle :param cornerCoord: coordinates of the lower left corner of the net :param xLenght: net length in x-direction :param yLenght: net length in y-direction :param mos: mesh opening size (horizontal distance between the double twists) :param a: length of double-twist :param b: height of single wire section :param startAtCorner: if true the generation starts with a double-twist at the lower left corner :param isSymmetric: defines if the net is symmetric with respect to the y-axis :return: set of spheres which defines the net (net) and exact dimensions of the net (lx,ly). note:: This packing works for the WireMatPM only. The particles at the corner are always generated first. For examples on how to use this packing see examples/WireMatPM. In order to create the proper interactions for the net the interaction radius has to be adapted in the simulation. """ # check input dimension if(xLength<mos): raise ValueError("xLength must be greater than mos!"); if(yLength<2*a+b): raise ValueError("yLength must be greater than 2*a+b!"); xstart = cornerCoord[0] ystart = cornerCoord[1] z = cornerCoord[2] ab = a+b # number of double twisted sections in y-direction and real length ly ny = int( (yLength-a)/ab ) + 1 ly = ny*a+(ny-1)*b jump=0 # number of sections in x-direction and real length lx if isSymmetric: nx = int( xLength/mos ) + 1 lx = (nx-1)*mos if not startAtCorner: nx+=-1 else: nx = int( (xLength-0.5*mos)/mos ) + 1 lx = (nx-1)*mos+0.5*mos net = [] # generate corner particles if startAtCorner: if (ny%2==0): # if ny even no symmetry in y-direction net+=[utils.sphere((xstart,ystart+ly,z),radius=radius,**kw)] # upper left corner if isSymmetric: net+=[utils.sphere((xstart+lx,ystart+ly,z),radius=radius,**kw)] # upper right corner else: net+=[utils.sphere((xstart+lx,ystart,z),radius=radius,**kw)] # lower right corner else: # if ny odd symmetry in y-direction if not isSymmetric: net+=[utils.sphere((xstart+lx,ystart,z),radius=radius,**kw)] # lower right corner net+=[utils.sphere((xstart+lx,ystart+ly,z),radius=radius,**kw)] # upper right corner jump=1 else: # do not start at corner if (ny%2==0): # if ny even no symmetry in y-direction net+=[utils.sphere((xstart,ystart,z),radius=radius,**kw)] # lower left corner if isSymmetric: net+=[utils.sphere((xstart+lx,ystart,z),radius=radius,**kw)] # lower right corner else: net+=[utils.sphere((xstart+lx,ystart+ly,z),radius=radius,**kw)] # upper right corner else: # if ny odd symmetry in y-direction net+=[utils.sphere((xstart,ystart,z),radius=radius,**kw)] # lower left corner net+=[utils.sphere((xstart,ystart+ly,z),radius=radius,**kw)] # upper left corner if isSymmetric: net+=[utils.sphere((xstart+lx,ystart,z),radius=radius,**kw)] # lower right corner net+=[utils.sphere((xstart+lx,ystart+ly,z),radius=radius,**kw)] # upper right corner xstart+=0.5*mos # generate other particles if isSymmetric: for i in range(ny): y = ystart + i*ab for j in range(nx): x = xstart + j*mos # add two particles of one vertical section (double-twist) net+=[utils.sphere((x,y,z),radius=radius,**kw)] net+=[utils.sphere((x,y+a,z),radius=radius,**kw)] # set values for next section xstart = xstart - 0.5*mos*pow(-1,i+jump) nx = int(nx + 1*pow(-1,i+jump)) else: for i in range(ny): y = ystart + i*ab for j in range(nx): x = xstart + j*mos # add two particles of one vertical section (double-twist) net+=[utils.sphere((x,y,z),radius=radius,**kw)] net+=[utils.sphere((x,y+a,z),radius=radius,**kw)] # set values for next section xstart = xstart - 0.5*mos*pow(-1,i+jump) return [net,lx,ly]
def SpherePack_toSimulation(self, rot=Matrix3.Identity, **kw): """Append spheres directly to the simulation. In addition calling :yref:`O.bodies.append<BodyContainer.append>`, this method also appropriately sets periodic cell information of the simulation. >>> from yade import pack; from math import * >>> sp=pack.SpherePack() Create random periodic packing with 20 spheres: >>> sp.makeCloud((0,0,0),(5,5,5),rMean=.5,rRelFuzz=.5,periodic=True,num=20) 20 Virgin simulation is aperiodic: >>> O.reset() >>> O.periodic False Add generated packing to the simulation, rotated by 45° along +z >>> sp.toSimulation(rot=Quaternion((0,0,1),pi/4),color=(0,0,1)) [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19] Periodic properties are transferred to the simulation correctly, including rotation (this could be avoided by explicitly passing "hSize=O.cell.hSize" as an argument): >>> O.periodic True >>> O.cell.refSize Vector3(5,5,5) """ #The following 2 lines do not work, because of accuaracy #>>> O.cell.hSize #Matrix3(3.53553,-3.53553,0, 3.53553,3.53553,0, 0,0,5) """ The current state (even if rotated) is taken as mechanically undeformed, i.e. with identity transformation: >>> O.cell.trsf Matrix3(1,0,0, 0,1,0, 0,0,1) :param Quaternion/Matrix3 rot: rotation of the packing, which will be applied on spheres and will be used to set :yref:`Cell.trsf` as well. :param \*\*kw: passed to :yref:`yade.utils.sphere` :return: list of body ids added (like :yref:`O.bodies.append<BodyContainer.append>`) """ if isinstance(rot, Quaternion): rot = rot.toRotationMatrix() assert (isinstance(rot, Matrix3)) if self.isPeriodic: O.periodic = True if self.cellSize != Vector3.Zero and self.isPeriodic: O.cell.hSize = rot * Matrix3(self.cellSize[0], 0, 0, 0, self.cellSize[1], 0, 0, 0, self.cellSize[2]) O.cell.trsf = Matrix3.Identity if not self.hasClumps(): return O.bodies.append( [utils.sphere(rot * c, r, **kw) for c, r in self]) else: standalone, clumps = self.getClumps() ids = O.bodies.append([ utils.sphere(rot * c, r, **kw) for c, r in self ]) # append all spheres first clumpIds = [] userColor = 'color' in kw for clump in clumps: clumpIds.append( O.bodies.clump([ids[i] for i in clump]) ) # clump spheres with given ids together, creating the clump object as well # make all spheres within one clump a single color, unless color was specified by the user if not userColor: for i in clump[1:]: O.bodies[ids[i]].shape.color = O.bodies[ids[ clump[0]]].shape.color return ids + clumpIds
from yade import utils sphereRadius=0.1 tc=0.001# collision time en=1 # normal restitution coefficient es=1 # tangential restitution coefficient density=2700 frictionAngle=radians(35)# params=utils.getViscoelasticFromSpheresInteraction(tc,en,es) sphereMat=O.materials.append(ViscElMat(density=density,frictionAngle=frictionAngle,**params)) # Spheres sphId=O.bodies.append([ utils.sphere( (0.4,0.5,0.5), 0.1, material=sphereMat), utils.sphere( (0.6,0.5,0.5), 0.1, material=sphereMat) ]) O.bodies[sphId[-1]].state.vel=(0.5,0,0) O.bodies[sphId[0]].state.vel=(-0.5,0,0) ## Engines O.engines=[ ForceResetter(), InsertionSortCollider([Bo1_Sphere_Aabb(),Bo1_Facet_Aabb()]), InteractionLoop( [Ig2_Sphere_Sphere_ScGeom()], [Ip2_ViscElMat_ViscElMat_ViscElPhys()], [Law2_ScGeom_ViscElPhys_Basic()], ), NewtonIntegrator(damping=0),
# -*- coding: utf-8 -*- O.engines=[ ForceResetter(), InsertionSortCollider([Bo1_Sphere_Aabb(),]), IGeomDispatcher([Ig2_Sphere_Sphere_Dem3DofGeom()]), IPhysDispatcher([Ip2_2xFrictMat_CSPhys()]), LawDispatcher([Law2_Dem3Dof_CSPhys_CundallStrack()]), NewtonIntegrator(damping = 0.01,gravity=[0,0,-9.81]) ] from yade import utils O.bodies.append(utils.sphere([0,0,6],1,fixed=False, color=[0,1,0])) O.bodies.append(utils.sphere([0,0,0],1,fixed=True, color=[0,0,1])) O.dt=.2*utils.PWaveTimeStep() from yade import qt qt.Controller() qt.View()
# facets material params=utils.getViscoelasticFromSpheresInteraction(tc,en,es) facetMat=O.materials.append(ViscElMat(frictionAngle=frictionAngle,**params)) # **params sets kn, cn, ks, cs # default spheres material dfltSpheresMat=O.materials.append(ViscElMat(density=density,frictionAngle=frictionAngle,**params)) O.dt=.05*tc # time step Rs=0.1 # particle radius # Create geometry box = O.bodies.append(geom.facetBox((0,0,0),(1,1,1),wallMask=31,material=facetMat)) # Create clumps... for j in xrange(10): clpId,sphId=O.bodies.appendClumped([utils.sphere(Vector3(0,Rs*2*i,(j+1)*Rs*2),Rs,material=dfltSpheresMat) for i in xrange(4)]) # ... and spheres sphAloneId=O.bodies.append( [utils.sphere( Vector3(0.5,Rs*2*i,(j+1)*Rs*2), Rs, material=dfltSpheresMat) for i in xrange(4) ] ) # Create engines O.engines=[ ForceResetter(), InsertionSortCollider([Bo1_Sphere_Aabb(),Bo1_Facet_Aabb()]), InteractionLoop( [Ig2_Sphere_Sphere_ScGeom(), Ig2_Facet_Sphere_ScGeom()], [Ip2_ViscElMat_ViscElMat_ViscElPhys()], [Law2_ScGeom_ViscElPhys_Basic()], ), NewtonIntegrator(damping=0,gravity=[0,0,-9.81]),
def regularOrtho(predicate, radius, gap, **kw): """Return set of spheres in regular orthogonal grid, clipped inside solid given by predicate. Created spheres will have given radius and will be separated by gap space.""" ret = [] mn, mx = predicate.aabb() if (max([mx[i] - mn[i] for i in 0, 1, 2]) == float('inf')): raise ValueError( "Aabb of the predicate must not be infinite (didn't you use union | instead of intersection & for unbounded predicate such as notInNotch?" ) xx, yy, zz = [ arange(mn[i] + radius, mx[i] - radius, 2 * radius + gap) for i in 0, 1, 2 ] for xyz in itertools.product(xx, yy, zz): if predicate(xyz, radius): ret += [utils.sphere(xyz, radius=radius, **kw)] return ret def regularHexa(predicate, radius, gap, **kw): """Return set of spheres in regular hexagonal grid, clipped inside solid given by predicate. Created spheres will have given radius and will be separated by gap space.""" ret = [] a = 2 * radius + gap # thanks to Nasibeh Moradi for finding bug here: # http://www.mail-archive.com/[email protected]/msg01424.html hy, hz = a * sqrt(3) / 2., a * sqrt(6) / 3. mn, mx = predicate.aabb() dim = [mx[i] - mn[i] for i in 0, 1, 2] if (max(dim) == float('inf')): raise ValueError(
# from yade import utils, plot import random random.seed() # sphere's radii r1, r2 = .1, .2 # place sphere 1 at the origin pt1 = Vector3(0, 0, 0) # random orientation of the interaction normal = Vector3(random.random() - .5, random.random() - .5, random.random() - .5) normal = Vector3.UnitX O.bodies.append([ utils.sphere(pt1, r1, wire=True, color=(.7, .7, .7)), utils.sphere(pt1 + .999999 * (r1 + r2) * normal.normalized(), r2, wire=True, color=(0, 0, 0)) ]) O.engines = [ ForceResetter(), PyRunner(iterPeriod=1, command='import time; time.sleep(.05)'), InsertionSortCollider([Bo1_Sphere_Aabb()]), InteractionLoop( #[Ig2_Sphere_Sphere_ScGeom()], [Ip2_FrictMat_FrictMat_FrictPhys()], [Law2_ScGeom_FrictPhys_CundallStrack()] # ScGeom #[Ig2_Sphere_Sphere_L3Geom(approxMask=63)],[Ip2_FrictMat_FrictMat_FrictPhys()],[Law2_L3Geom_FrictPhys_ElPerfPl(noBreak=True,noSlip=False)] # L3Geom [Ig2_Sphere_Sphere_L6Geom(approxMask=63)], [Ip2_FrictMat_FrictMat_FrictPhys()],
# define piecewise lineare stress-strain curve strainStressValues=[(0.0019230769,2.5e8),(0.0192,3.2195e8),(0.05,3.8292e8),(0.15,5.1219e8),(0.25,5.5854e8),(0.3,5.6585e8),(0.35,5.6585e8)] # elastic material properties particleVolume = 4./3.*pow(radius,3)*pi particleMass = 3.9/1000. density = particleMass/particleVolume young = strainStressValues[0][1] / strainStressValues[0][0] poisson = 0.3 #### material definition netMat = O.materials.append(WireMat(young=young,poisson=poisson,frictionAngle=radians(30),density=density,isDoubleTwist=False,diameter=d,strainStressValues=strainStressValues,lambdaEps=0.4,lambdak=0.21)) #### create boddies, default: dynamic=True O.bodies.append( utils.sphere([0,0,0], radius, wire=False, color=[1,0,0], highlight=False, material=netMat) ) O.bodies.append( utils.sphere([0,a,0], radius, wire=False, color=[0,1,0], highlight=False, material=netMat) ) FixedSphere=O.bodies[0] MovingSphere=O.bodies[1] FixedSphere.dynamic=True MovingSphere.dynamic=True #### initialize values for UniaxialStrainer bb = utils.uniaxialTestFeatures(axis=1) negIds,posIds,axis,crossSectionArea=bb['negIds'],bb['posIds'],bb['axis'],bb['area'] strainRateTension = 1./a setSpeeds = True
Rs=0.02 # mean particle radius Rf=0.01 # dispersion (Rs±Rf*Rs) nSpheres=1000# number of particles # Create geometry pln=Plane( (-.5, -.5, 0), (.5, -.5, -.05), (.5, .5, 0), (-.5, .5, -.05) ); plnIds=O.bodies.append(pack.gtsSurface2Facets(pln,material=facetMat,color=(0,1,0))) fct=Plane( (-.25, -.25, .5), (.25, -.25, .5), (.25, .25, .5), (-.25, .25, .5) ); fctIds=O.bodies.append(pack.gtsSurface2Facets(fct,material=facetMat,color=(1,0,0),noBound=True)) # Create spheres sp=pack.SpherePack(); sp.makeCloud(Vector3(-.5, -.5, 0),Vector3(.5, .5, .2), Rs, Rf, int(nSpheres), False) spheres=O.bodies.append([utils.sphere(s[0],s[1],color=(0.929,0.412,0.412),material=dfltSpheresMat) for s in sp]) # Create engines O.engines=[ ForceResetter(), InsertionSortCollider([Bo1_Sphere_Aabb(),Bo1_Facet_Aabb()]), InteractionLoop( [Ig2_Sphere_Sphere_ScGeom(), Ig2_Facet_Sphere_ScGeom()], [Ip2_ViscElMat_ViscElMat_ViscElPhys()], [Law2_ScGeom_ViscElPhys_Basic()], ), NewtonIntegrator(damping=0,gravity=[0,0,-9.81]), ResetRandomPosition(virtPeriod=0.01,factoryFacets=fctIds,velocity=(0,0,-2),subscribedBodies=spheres,point=(0,0,-.5),normal=(0,0,1),maxAttempts=100), ] renderer = qt.Renderer()
Rs=0.02 # mean particle radius Rf=0.01 # dispersion (Rs±Rf*Rs) nSpheres=1000# number of particles # Create geometry pln=Plane( (-.5, -.5, 0), (.5, -.5, -.05), (.5, .5, 0), (-.5, .5, -.05) ); plnIds=O.bodies.append(pack.gtsSurface2Facets(pln.faces(),material=facetMat,color=(0,1,0))) fct=Plane( (-.25, -.25, .5), (.25, -.25, .5), (.25, .25, .5), (-.25, .25, .5) ); fctIds=O.bodies.append(pack.gtsSurface2Facets(fct.faces(),material=facetMat,color=(1,0,0),noBound=True)) # Create spheres sp=pack.SpherePack(); sp.makeCloud(Vector3(-.5, -.5, 0),Vector3(.5, .5, .2), Rs, Rf, int(nSpheres), False) spheres=O.bodies.append([utils.sphere(s[0],s[1],color=(0.929,0.412,0.412),material=dfltSpheresMat) for s in sp]) for id in spheres: s=O.bodies[id] p=utils.getViscoelasticFromSpheresInteraction(s.state['mass'],tc,en,es) s.mat['kn'],s.mat['cn'],s.mat['ks'],s.mat['cs']=p['kn'],p['cn'],p['ks'],p['cs'] # Create engines O.engines=[ ForceResetter(), InsertionSortCollider([Bo1_Sphere_Aabb(),Bo1_Facet_Aabb()]), InteractionLoop( [Ig2_Sphere_Sphere_ScGeom(), Ig2_Facet_Sphere_ScGeom()], [Ip2_ViscElMat_ViscElMat_ViscElPhys()], [Law2_ScGeom_ViscElPhys_Basic()], ), GravityEngine(gravity=[0,0,-9.81]),
else: print "No suitable packing in database found, running",'PERIODIC compression' if wantPeri else 'triaxial' sys.stdout.flush() O.switchScene(); O.resetThisScene() ### !! if wantPeri: # x1,y1,z1 already computed above sp=SpherePack() O.periodic=True #O.cell.refSize=(x1,y1,z1) O.cell.setBox((x1,y1,z1)) #print cloudPorosity,beta,gamma,N100,x1,y1,z1,O.cell.refSize #print x1,y1,z1,radius,rRelFuzz O.materials.append(FrictMat(young=3e10,density=2400)) num=sp.makeCloud(Vector3().Zero,O.cell.refSize,radius,rRelFuzz,spheresInCell,True) O.engines=[ForceResetter(),InsertionSortCollider([Bo1_Sphere_Aabb()],nBins=5,verletDist=.05*radius),InteractionLoop([Ig2_Sphere_Sphere_ScGeom()],[Ip2_FrictMat_FrictMat_FrictPhys()],[Law2_ScGeom_FrictPhys_CundallStrack()]),PeriIsoCompressor(charLen=2*radius,stresses=[-100e9,-1e8],maxUnbalanced=1e-2,doneHook='O.pause();',globalUpdateInt=5,keepProportions=True),NewtonIntegrator(damping=.6)] O.materials.append(FrictMat(young=30e9,frictionAngle=.5,poisson=.3,density=1e3)) for s in sp: O.bodies.append(utils.sphere(s[0],s[1])) O.dt=utils.PWaveTimeStep() O.run(); O.wait() sp=SpherePack(); sp.fromSimulation() #print 'Resulting cellSize',sp.cellSize,'proportions',sp.cellSize[1]/sp.cellSize[0],sp.cellSize[2]/sp.cellSize[0] # repetition to the required cell size will be done below, after memoizing the result else: assumedFinalDensity=0.6 V=(4/3)*pi*radius**3; N=assumedFinalDensity*fullDim[0]*fullDim[1]*fullDim[2]/V; TriaxialTest( numberOfGrains=int(N),radiusMean=radius,radiusStdDev=rRelFuzz, # upperCorner is just size ratio, if radiusMean is specified upperCorner=fullDim, ## no need to touch any the following noFiles=True,lowerCorner=[0,0,0],sigmaIsoCompaction=1e7,sigmaLateralConfinement=1e5,compactionFrictionDeg=1,StabilityCriterion=.05,strainRate=.2,thickness=-1,maxWallVelocity=.1,wallOversizeFactor=1.5,autoUnload=True,autoCompressionActivation=False).load() while ( numpy.isnan(utils.unbalancedForce()) or utils.unbalancedForce()>0.005 ) :
def hexaNet(radius, cornerCoord=[0, 0, 0], xLength=1., yLength=0.5, mos=0.08, a=0.04, b=0.04, startAtCorner=True, isSymmetric=False, **kw): """Definition of the particles for a hexagonal wire net in the x-y-plane for the WireMatPM. :param radius: radius of the particle :param cornerCoord: coordinates of the lower left corner of the net :param xLenght: net length in x-direction :param yLenght: net length in y-direction :param mos: mesh opening size (horizontal distance between the double twists) :param a: length of double-twist :param b: height of single wire section :param startAtCorner: if true the generation starts with a double-twist at the lower left corner :param isSymmetric: defines if the net is symmetric with respect to the y-axis :return: set of spheres which defines the net (net) and exact dimensions of the net (lx,ly). .. note:: This packing works for the WireMatPM only. The particles at the corner are always generated first. For examples on how to use this packing see examples/WireMatPM. In order to create the proper interactions for the net the interaction radius has to be adapted in the simulation. """ # check input dimension if (xLength < mos): raise ValueError("xLength must be greater than mos!") if (yLength < 2 * a + b): raise ValueError("yLength must be greater than 2*a+b!") xstart = cornerCoord[0] ystart = cornerCoord[1] z = cornerCoord[2] ab = a + b # number of double twisted sections in y-direction and real length ly ny = int((yLength - a) / ab) + 1 ly = ny * a + (ny - 1) * b jump = 0 # number of sections in x-direction and real length lx if isSymmetric: nx = int(xLength / mos) + 1 lx = (nx - 1) * mos if not startAtCorner: nx += -1 else: nx = int((xLength - 0.5 * mos) / mos) + 1 lx = (nx - 1) * mos + 0.5 * mos net = [] # generate corner particles if startAtCorner: if (ny % 2 == 0): # if ny even no symmetry in y-direction net += [ utils.sphere((xstart, ystart + ly, z), radius=radius, **kw) ] # upper left corner if isSymmetric: net += [ utils.sphere((xstart + lx, ystart + ly, z), radius=radius, **kw) ] # upper right corner else: net += [ utils.sphere((xstart + lx, ystart, z), radius=radius, **kw) ] # lower right corner else: # if ny odd symmetry in y-direction if not isSymmetric: net += [ utils.sphere((xstart + lx, ystart, z), radius=radius, **kw) ] # lower right corner net += [ utils.sphere((xstart + lx, ystart + ly, z), radius=radius, **kw) ] # upper right corner jump = 1 else: # do not start at corner if (ny % 2 == 0): # if ny even no symmetry in y-direction net += [utils.sphere((xstart, ystart, z), radius=radius, **kw)] # lower left corner if isSymmetric: net += [ utils.sphere((xstart + lx, ystart, z), radius=radius, **kw) ] # lower right corner else: net += [ utils.sphere((xstart + lx, ystart + ly, z), radius=radius, **kw) ] # upper right corner else: # if ny odd symmetry in y-direction net += [utils.sphere((xstart, ystart, z), radius=radius, **kw)] # lower left corner net += [ utils.sphere((xstart, ystart + ly, z), radius=radius, **kw) ] # upper left corner if isSymmetric: net += [ utils.sphere((xstart + lx, ystart, z), radius=radius, **kw) ] # lower right corner net += [ utils.sphere((xstart + lx, ystart + ly, z), radius=radius, **kw) ] # upper right corner xstart += 0.5 * mos # generate other particles if isSymmetric: for i in range(ny): y = ystart + i * ab for j in range(nx): x = xstart + j * mos # add two particles of one vertical section (double-twist) net += [utils.sphere((x, y, z), radius=radius, **kw)] net += [utils.sphere((x, y + a, z), radius=radius, **kw)] # set values for next section xstart = xstart - 0.5 * mos * pow(-1, i + jump) nx = int(nx + 1 * pow(-1, i + jump)) else: for i in range(ny): y = ystart + i * ab for j in range(nx): x = xstart + j * mos # add two particles of one vertical section (double-twist) net += [utils.sphere((x, y, z), radius=radius, **kw)] net += [utils.sphere((x, y + a, z), radius=radius, **kw)] # set values for next section xstart = xstart - 0.5 * mos * pow(-1, i + jump) return [net, lx, ly]
InteractionLoop( [Ig2_Sphere_Sphere_ScGeom(),Ig2_Box_Sphere_ScGeom()], [Ip2_FrictMat_FrictMat_FrictPhys()], [Law2_ScGeom_FrictPhys_CundallStrack()] ), NewtonIntegrator(damping=.2,gravity=(0,0,-9.81)), ### ### NOTE this extra engine: ### ### You want snapshot to be taken every 1 sec (realTimeLim) or every 50 iterations (iterLim), ### whichever comes soones. virtTimeLim attribute is unset, hence virtual time period is not taken into account. PyRunner(iterPeriod=20,command='myAddPlotData()') ] from yade import utils O.bodies.append(utils.box(center=[0,0,0],extents=[.5,.5,.5],fixed=True,color=[1,0,0])) O.bodies.append(utils.sphere([0,0,2],1,color=[0,1,0])) O.dt=.002*utils.PWaveTimeStep() ############################################ ##### now the part pertaining to plots ##### ############################################ from math import * from yade import plot ## we will have 2 plots: ## 1. t as function of i (joke test function) ## 2. i as function of t on left y-axis ('|||' makes the separation) and z_sph, v_sph (as green circles connected with line) and z_sph_half again as function of t plot.plots={'i':('t'),'t':('z_sph',None,('v_sph','go-'),'z_sph_half')} ## this function is called by plotDataCollector
pack.gtsSurface2Facets(pln, material=facetMat, color=(0, 1, 0))) fct = Plane((-.25, -.25, .5), (.25, -.25, .5), (.25, .25, .5), (-.25, .25, .5)) fctIds = O.bodies.append( pack.gtsSurface2Facets(fct, material=facetMat, color=(1, 0, 0), noBound=True)) # Create spheres sp = pack.SpherePack() sp.makeCloud(Vector3(-.5, -.5, 0), Vector3(.5, .5, .2), Rs, Rf, int(nSpheres), False) spheres = O.bodies.append([ utils.sphere(s[0], s[1], color=(0.929, 0.412, 0.412), material=dfltSpheresMat) for s in sp ]) # Create engines O.engines = [ ForceResetter(), InsertionSortCollider([Bo1_Sphere_Aabb(), Bo1_Facet_Aabb()]), InteractionLoop( [Ig2_Sphere_Sphere_ScGeom(), Ig2_Facet_Sphere_ScGeom()], [Ip2_ViscElMat_ViscElMat_ViscElPhys()], [Law2_ScGeom_ViscElPhys_Basic()], ), NewtonIntegrator(damping=0, gravity=[0, 0, -9.81]),
""" Show basic wall functionality (infinite axis-aligned planes). """ from yade import utils O.materials.append( FrictMat(young=30e9, density=1000, poisson=.2, frictionAngle=.5)) O.bodies.append([ utils.wall(1, axis=2, sense=-1), utils.wall(-5, axis=0, sense=1), utils.wall(1, axis=1), utils.wall((1, 0, 0), 0), utils.sphere([0, 0, 0], .5), utils.sphere([-4, -4, -3], .5) ]) Gl1_Wall(div=10) from yade import qt qt.Controller() qt.View() O.engines = [ ForceResetter(), InsertionSortCollider( [Bo1_Sphere_Aabb(), Bo1_Facet_Aabb(), Bo1_Wall_Aabb()]), InteractionLoop( [ Ig2_Sphere_Sphere_ScGeom(),
def setUp(self): O.reset() self.count=100 O.bodies.append([utils.sphere([random.random(),random.random(),random.random()],random.random()) for i in range(0,self.count)]) random.seed()