Beispiel #1
0
 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.disk([0, 0, 0], .5, material=0),
         utils.disk([1, 1, 1], .5, material=0),
         utils.disk([1, 1, 1], .5, material=1)
     ])
Beispiel #2
0
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:`sudodem.utils.disk`
	:returns: list of disks.

	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.disk(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.disk(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 Addlayer(r, mat, boxsize, num_s, num_t):
    bottom = gettop()
    coor = Genparticles(r, mat, boxsize, num_s, num_t, bottom)
    for b in coor:
        bb = utils.disk(b, 0.5, material='mat1')
        bb.state.vel = [0, -1]
        O.bodies.append(bb)
Beispiel #4
0
 def testEraseBodiesInInteraction(self):
     O.reset()
     id1 = O.bodies.append(utils.disk([0.5, 0.5, 0.0 + 0.095], .1))
     id2 = O.bodies.append(utils.disk([0.5, 0.5, 0.0 + 0.250], .1))
     O.engines = [
         ForceResetter(),
         InsertionSortCollider([Bo1_Disk_Aabb()]),
         InteractionLoop([Ig2_Disk_Disk_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()
Beispiel #5
0
def regularHexa(predicate, radius, gap, **kw):
    """Return set of disks in regular hexagonal grid, clipped inside solid given by predicate.
	Created disks 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.disk((x, y, z), radius=radius, **kw)]
    if (len(ret) == 0):
        warnings.warn('No disks are produced by regularHexa-function',
                      category=RuntimeWarning)
    return ret
Beispiel #6
0
def filterDiskPack(predicate, diskPack, returnDiskPack=None, **kw):
    """Using given DiskPack instance, return disks that satisfy predicate.
	It returns either a :yref:`sudodem._packDisks.DiskPack` (if returnDiskPack) 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 returnDiskPack == None:
        warnings.warn(
            'The default behavior will change; specify returnDiskPack=True for the new behavior, and False to get rid of this warning (your code will break in the future, however). The returned DiskPack object can be added to the simulation using DiskPack.toSimulation()',
            category=FutureWarning)
        returnDiskPack = False
    mn, mx = predicate.aabb()
    dimP, centP = predicate.dim(), predicate.center()
    dimS, centS = diskPack.dim(), diskPack.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))
    diskPack.translate(centP - centS)
    if returnDiskPack:
        ret = DiskPack()
        for c, r in diskPack:
            if predicate(c, r): ret.add(c, r)
        return ret
    else:
        # return particles to be added to O.bodies
        ret = []
        for s in diskPack:
            if predicate(s[0], s[1]):
                ret += [utils.disk(s[0], radius=s[1], **kw)]
        return ret
Beispiel #7
0
def textExt(fileName, format='x_y_z_r', shift=Vector3.Zero, scale=1.0, **kw):
    """Load disk 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`
	: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:`sudodem.utils.disk`
	:returns: list of disks.

	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.disk(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.disk(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.disk(shift + scale * pos,
                           scale * float(data[4]),
                           material=int(data[5]),
                           **kw))

        else:
            raise RuntimeError("Please, specify a correct format output!")
    return ret
def gen_particles(b_num, r_ball, boxsize):
    for j in range(b_num):
        x = random.uniform(r_ball - 0.5 * boxsize[0],
                           0.5 * boxsize[0] - r_ball)
        y = random.uniform(r_ball - 0.5 * boxsize[1],
                           0.5 * boxsize[1] - r_ball)
        body = utils.disk((x, y), r_ball, material='mat1')
        O.bodies.append(body)
Beispiel #9
0
 def setUp(self):
     O.reset()
     self.count = 100
     O.bodies.append([
         utils.disk([random.random(),
                     random.random(),
                     random.random()], random.random())
         for i in range(0, self.count)
     ])
     random.seed()
Beispiel #10
0
 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.disk((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.disk(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
Beispiel #11
0
 def testErasedAndNewlyCreatedDisk(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.disk([0.0, 0.0, 0.0], 0.5))
     id2 = O.bodies.append(utils.disk([0.0, 2.0, 0.0], 0.5))
     O.engines = [
         ForceResetter(),
         InsertionSortCollider([Bo1_Disk_Aabb()]),
         InteractionLoop([Ig2_Disk_Disk_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.disk([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.disk([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)
Beispiel #12
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 disks.
	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:`sudodem.utils.disk`
	:Returns: list of disks.

	LSMGenGeo library allows one to create pack of disks
	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 sudodem.utils import disk

    infile = open(fileName, "r")
    lines = infile.readlines()
    infile.close()

    numDisks = int(lines[6].split()[0])
    ret = []
    for line in lines[7:numDisks + 7]:
        data = line.split()
        pos = orientation * Vector3(float(data[0]), float(data[1]),
                                    float(data[2]))
        ret.append(
            utils.disk(shift + scale * pos, scale * float(data[3]), **kw))
    return ret
Beispiel #13
0
def gengeo(mntable, shift=Vector3.Zero, scale=1.0, **kw):
    """ Imports geometry from LSMGenGeo library and creates disks.
	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:`sudodem.utils.disk`

	LSMGenGeo library allows one to create pack of disks
	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, Disk
    except ImportError:
        from gengeo import MNTable3D, Disk
    ret = []
    diskList = mntable.getDiskListFromGroup(0)
    for i in range(0, len(diskList)):
        r = diskList[i].Radius()
        c = diskList[i].Centre()
        ret.append(
            utils.disk([
                shift[0] + scale * float(c.X()), shift[1] +
                scale * float(c.Y()), shift[2] + scale * float(c.Z())
            ], scale * float(r), **kw))
    return ret
Beispiel #14
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.disk((0.0, 0.0, 0.0), 1.0, fixed=True))
        id_nonfixed_transl = O.bodies.append(
            utils.disk((0.0, 5.0, 0.0), 1.0, fixed=False))
        id_fixed_rot = O.bodies.append(
            utils.disk((0.0, 10.0, 10.0), 1.0, fixed=True))
        id_nonfixed_rot = O.bodies.append(
            utils.disk((0.0, 15.0, 10.0), 1.0, fixed=False))
        id_fixed_helix = O.bodies.append(
            utils.disk((0.0, 20.0, 10.0), 1.0, fixed=True))
        id_nonfixed_helix = O.bodies.append(
            utils.disk((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
Beispiel #15
0
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 disks 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.disk((xstart, ystart + ly, z), radius=radius,
                               **kw)]  # upper left corner
            if isSymmetric:
                net += [
                    utils.disk((xstart + lx, ystart + ly, z),
                               radius=radius,
                               **kw)
                ]  # upper right corner
            else:
                net += [
                    utils.disk((xstart + lx, ystart, z), radius=radius, **kw)
                ]  # lower right corner
        else:  # if ny odd symmetry in y-direction
            if not isSymmetric:
                net += [
                    utils.disk((xstart + lx, ystart, z), radius=radius, **kw)
                ]  # lower right corner
                net += [
                    utils.disk((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.disk((xstart, ystart, z), radius=radius,
                               **kw)]  # lower left corner
            if isSymmetric:
                net += [
                    utils.disk((xstart + lx, ystart, z), radius=radius, **kw)
                ]  # lower right corner
            else:
                net += [
                    utils.disk((xstart + lx, ystart + ly, z),
                               radius=radius,
                               **kw)
                ]  # upper right corner
        else:  # if ny odd symmetry in y-direction
            net += [utils.disk((xstart, ystart, z), radius=radius,
                               **kw)]  # lower left corner
            net += [utils.disk((xstart, ystart + ly, z), radius=radius,
                               **kw)]  # upper left corner
            if isSymmetric:
                net += [
                    utils.disk((xstart + lx, ystart, z), radius=radius, **kw)
                ]  # lower right corner
                net += [
                    utils.disk((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.disk((x, y, z), radius=radius, **kw)]
                net += [utils.disk((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.disk((x, y, z), radius=radius, **kw)]
                net += [utils.disk((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]
Beispiel #16
0
def randomPeriPack(radius,
                   initSize,
                   rRelFuzz=0.0,
                   memoizeDb=None,
                   noPrint=False):
    """Generate periodic dense packing.

	A cell of initSize is stuffed with as many disks as possible, then we run periodic compression with PeriIsoCompressor, just like with
	randomDensePack.

	:param radius: mean disk radius
	:param rRelFuzz: relative fuzz of disk radius (equal distribution); see the same param for randomDensePack.
	:param initSize: initial size of the periodic cell.

	:return: DiskPack 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,
                             disksInCell=-1,
                             memoDbg=True,
                             noPrint=noPrint)
    if sp: return sp
    O.switchScene()
    O.resetThisScene()
    sp = DiskPack()
    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_Disk_Aabb()], verletDist=.05 * radius),
        InteractionLoop([Ig2_Disk_Disk_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.disk(s[0], s[1]))
    O.dt = utils.PWaveTimeStep()
    O.timingEnabled = True
    O.run()
    O.wait()
    ret = DiskPack()
    ret.fromSimulation()
    _memoizePacking(memoizeDb,
                    ret,
                    radius,
                    rRelFuzz,
                    wantPeri=True,
                    fullDim=Vector3(0, 0, 0),
                    noPrint=noPrint)  # fullDim unused
    O.switchScene()
    return ret
Beispiel #17
0
    def DiskPack_toSimulation(self, rot=Matrix3.Identity, **kw):
        """Append disks 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 sudodem import pack; from math import *
    >>> sp=pack.DiskPack()

  Create random periodic packing with 20 disks:

    >>> 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 disks and will be used to set :yref:`Cell.trsf` as well.
  :param \*\*kw: passed to :yref:`sudodem.utils.disk`
  :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.disk(rot * c, r, **kw) for c, r in self])
        else:
            standalone, clumps = self.getClumps()
            ids = O.bodies.append([
                utils.disk(rot * c, r, **kw) for c, r in self
            ])  # append all disks first
            clumpIds = []
            userColor = 'color' in kw
            for clump in clumps:
                clumpIds.append(
                    O.bodies.clump([ids[i] for i in clump])
                )  # clump disks with given ids together, creating the clump object as well
                # make all disks 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
Beispiel #18
0
 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.disk(p0, r1), utils.disk(p1, r2)])
Beispiel #19
0
def regularOrtho(predicate, radius, gap, **kw):
    """Return set of disks in regular orthogonal grid, clipped inside solid given by predicate.
	Created disks 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.disk(xyz, radius=radius, **kw)]
    if (len(ret) == 0):
        warnings.warn('No disks are produced by regularOrtho-function',
                      category=RuntimeWarning)
    return ret


def regularHexa(predicate, radius, gap, **kw):
    """Return set of disks in regular hexagonal grid, clipped inside solid given by predicate.
	Created disks 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()
Beispiel #20
0
def randomDensePack(predicate,
                    radius,
                    material=-1,
                    dim=None,
                    cropLayers=0,
                    rRelFuzz=0.,
                    disksInCell=0,
                    memoizeDb=None,
                    useOBB=False,
                    memoDbg=False,
                    color=None,
                    returnDiskPack=None):
    """Generator of random dense packing with given geometry properties, using TriaxialTest (aperiodic)
	or PeriIsoCompressor (periodic). The periodicity depens on whether	the disksInCell 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 disksInCell: if given, the packing will be periodic, with given number of disks in the periodic cell.
	:param radius: mean radius of disks
	:param rRelFuzz: relative fuzz of the radius -- e.g. radius=10, rRelFuzz=.2, then disks will have radii 10 ± (10*.2)), with an uniform distribution.
		0 by default, meaning all disks will have exactly the same radius.
	:param cropLayers: (aperiodic only) how many layers of disks 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 disks 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 disks 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 returnDiskPack: see the corresponding argument in :yref:`sudodem.pack.filterDiskPack`

	:return: DiskPack object with disks, filtered by the predicate.
	"""
    import sqlite3, os.path, cPickle, time, sys, _packPredicates, numpy
    from math import pi
    wantPeri = (disksInCell > 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 = disksInCell / cloudPorosity  # number of disks for cell being filled by disks 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 disks to keep porosity the same
        sp = _getMemoizedPacking(memoizeDb,
                                 radius,
                                 rRelFuzz,
                                 x1,
                                 y1,
                                 z1,
                                 fullDim,
                                 wantPeri,
                                 fillPeriodic=True,
                                 disksInCell=disksInCell,
                                 memoDbg=False)
        if sp:
            if orientation:
                sp.cellSize = (
                    0, 0, 0)  # resetting cellSize avoids warning when rotating
                sp.rotate(*orientation.toAxisAngle())
            return filterDiskPack(predicate,
                                  sp,
                                  material=material,
                                  returnDiskPack=returnDiskPack)
        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 = DiskPack()
        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,
                           disksInCell, True)
        O.engines = [
            ForceResetter(),
            InsertionSortCollider([Bo1_Disk_Aabb()], verletDist=.05 * radius),
            InteractionLoop([Ig2_Disk_Disk_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.disk(s[0], s[1]))
        O.dt = utils.PWaveTimeStep()
        O.run()
        O.wait()
        sp = DiskPack()
        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,
            ## 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):
            O.run(100, True)
        sp = DiskPack()
        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 filterDiskPack(predicate,
                          sp,
                          material=material,
                          color=color,
                          returnDiskPack=returnDiskPack)
Beispiel #21
0
        b_num = int(b_num_tot * GSD[i])
        gen_particles(b_num, r_ball, boxsize)


def print_fnt():
    for itr in O.bodies[399].intrs():
        fn = itr.phys.normalForce
        ft = itr.phys.shearForce
        mu = ft.norm() / fn.norm()
        print mu


#particles
#gen_sample(boxsize)
for p in pos:
    body = utils.disk(p, 0.41, material='mat1')
    O.bodies.append(body)


def post_consol():
    O.engines = O.engines[:4]
    #print getStress()
    print O.cell.hSize
    setContactFriction(0.5)
    O.cell.trsf = Matrix2.Identity
    O.cell.velGrad = Matrix2.Zero
    for p in O.bodies:
        p.state.vel = Vector2.Zero
        p.state.angVel = 0.0
        p.state.refPos = p.state.pos
        p.state.refOri = p.state.ori