Ejemplo n.º 1
0
def cell(o, us, ua, fm):
    m = Matrix2_Identity + us + ua
    d = dim
    vs = [Vector2(x, y) for x, y in ((0, 0), (d, 0), (d, -d), (0, -d))]
    vs = [m * v for v in vs]
    vs = [Vector2(o) + v for v in vs]
    (x1, y1), (x2, y2), (x3, y3), (x4, y4) = vs
    paper.path(["M", o[0], o[1], "h", +1.1 * d])
    paper.path(["M", o[0], o[1], "v", -1.1 * d])
    paper.path(["M", x1, y1, "L", x2, y2, "L", x3, y3, "L", x4, y4,
                "Z"]).normal().fill("#ddd")
    #
    d1, d3 = [dim * v for v in (.3, .7)]
    cs = [
        Vector2(x, y) for x, y in ((d1, -d1), (d3, -d1), (d3, -d3), (d1, -d3))
    ]
    cs = [m * c for c in cs]
    cs = [Vector2(o) + c for c in cs]
    r = .15 * d
    rr = .2 * d
    a = -ua[0, 1] - fm[0, 1]
    co, si = [f(a) for f in cos, sin]
    for c in cs:
        paper.circle(c[0], c[1], r).fill("white")
        paper.path([
            "M",
            c[0],
            c[1],
            "l",
            +co * rr,
            +si * rr,
            "M",
            c[0],
            c[1],
            "l",
            -co * rr,
            -si * rr,
            "M",
            c[0],
            c[1],
            "l",
            -si * rr,
            +co * rr,
            "M",
            c[0],
            c[1],
            "l",
            +si * rr,
            -co * rr,
        ]).normal()
Ejemplo n.º 2
0
def aarrow(c, d, text=None, rev=False):
    d = Vector2(d).normalized()
    t = Vector2(-d[1], d[0])
    v0 = c + t * r
    v1 = c - t * r
    if rev:
        v0, v1 = v1, v0
    paper.path(
        ["M", v0[0], v0[1], "A", r, r, 0, 0, 1 if rev else 0, v1[0],
         v1[1]]).mediumThick().arrow()
    ret = c + r * d
    if text is not None:
        papertext(ret[0], ret[1], text)
    return c + r * d
Ejemplo n.º 3
0
def larrow(c, d, text=None):
    d = Vector2(d).normalized() * a
    paper.path(["M", c[0], c[1], "l", d[0], d[1]]).mediumThick().arrow()
    ret = c + d
    if text is not None:
        papertext(ret[0], ret[1], text)
    return ret
Ejemplo n.º 4
0
 def flat(v):
     return Vector2(v[0], v[1])
Ejemplo n.º 5
0
class EllGroup(woo.core.Preprocessor, woo.pyderived.PyWooObject):
    'Simulation of group of ellipsoids moving in 2-dimensional box.'
    _classTraits = None
    _PAT = woo.pyderived.PyAttrTrait  # less typing
    _attrTraits = [
        _PAT(
            Vector2,
            'rRange',
            Vector2(.02, .04),
            unit='m',
            doc=
            'Range (minimum and maximum) for particle radius (greatest semi-axis); if both are the same, all particles will have the same radius.'
        ),
        _PAT(bool,
             'spheres',
             False,
             doc='Use spherical particles instead of elliptical'),
        _PAT(
            float,
            'semiMinRelRnd',
            0,
            hideIf='self.spheres',
            doc=
            'Minimum semi-axis length relative to particle radius; minor semi-axes are randomly selected from (:obj:`semiMinRelRnd` … 1) × greatest semi-axis. If non-positive, :obj:`semiRelFixed` is used instead.'
        ),
        _PAT(
            Vector3,
            'semiRelFixed',
            Vector3(1., .5, .5),
            hideIf='self.spheres',
            doc=
            'Fixed sizes of semi-axes relative (all elements should be ≤ 1). The :math:`z`-component is the out-of-plane size which only indirectly influences contact stiffnesses. This variable is only used if semi-axes are not assigned randomly (see :obj:`semiMinRelRnd`).'
        ),
        _PAT(Vector2,
             'boxSize',
             Vector2(2, 2),
             unit='m',
             doc='Size of the 2d domain in which particles move.'),
        _PAT(
            float,
            'vMax',
            1.,
            unit='m/s',
            doc=
            'Maximum initial velocity of particle; assigned randomly from 0 to this value; intial angular velocity of all particles is zero.'
        ),
        _PAT(
            woo.models.ContactModelSelector,
            'model',
            woo.models.ContactModelSelector(name='Schwarz',
                                            restitution=1.,
                                            damping=0.01,
                                            numMat=(1, 2),
                                            matDesc=['ellipsoids', 'walls'],
                                            mats=[
                                                woo.dem.HertzMat(density=5000,
                                                                 young=1e6,
                                                                 tanPhi=0.0,
                                                                 surfEnergy=4.,
                                                                 alpha=.6)
                                            ]),
            doc=
            'Select contact model. The first material is for particles; the second, optional, material is for walls at the boundary (the first material is used if there is no second one).'
        ),
        _PAT(
            str,
            'exportFmt',
            "/tmp/ell2d-{tid}-",
            filename=True,
            doc=
            "Prefix for saving :obj:`woo.dem.VtkExport` data, and :obj:`woo.pre.ell2d.ell2plot` data; formatted with ``format()`` providing :obj:`woo.core.Scene.tags` as keys."
        ),
        _PAT(
            int, 'vtkStep', 0,
            "How often should :obj:`woo.dem.VtkExport` run. If non-positive, never run the export."
        ),
        _PAT(
            int, 'vtkEllLev', 1,
            'Tesselation level of ellipsoids when expored as VTK meshes (see :obj:`woo.dem.VtkExport.ellLev`).'
        ),
        _PAT(
            int, 'ell2Step', 0,
            "How often should :obj:`woo.pre.ell2d.ell2plot` run. If non-positive, never run that one."
        ),
        _PAT(
            float, 'dtSafety', .5,
            'Safety coefficient for critical timestep; should be smaller than one.'
        ),
    ]

    def __init__(self, **kw):
        woo.core.Preprocessor.__init__(self)
        self.wooPyInit(self.__class__, woo.core.Preprocessor, **kw)

    def __call__(self):
        import woo
        woo.master.usesApi = 10102
        # preprocessor builds the simulation when called
        pre = self  # more readable
        S = woo.core.Scene(fields=[woo.dem.DemField()], pre=self.deepcopy())
        # material definitions
        ellMat = pre.model.mats[0]
        wallMat = (pre.model.mats[1] if len(pre.model.mats) > 1 else ellMat)

        ZZ = pre.rRange[1] * 3
        # only generate spheres randomly in 2d box
        S.engines = [
            woo.dem.BoxInlet2d(
                axis=2,
                box=((0, 0, ZZ), (pre.boxSize[0], pre.boxSize[1], ZZ)),
                materials=[ellMat],
                generator=woo.dem.MinMaxSphereGenerator(dRange=2 * pre.rRange),
                massRate=0),
            woo.dem.InsertionSortCollider([woo.dem.Bo1_Sphere_Aabb()])
        ]
        S.one()
        posRad = [(p.pos, p.shape.radius) for p in S.dem.par]
        # clear the dem field
        S.fields = [woo.dem.DemField()]

        import random

        def rndOri2d():
            q = Quaternion((0, 0, 1), 2 * math.pi * random.random())
            q.normalize()
            return q

        S.energy['kin0'] = 0
        for pos, rad in posRad:
            if not pre.spheres:
                if pre.semiMinRelRnd > 0:
                    semiAxes = [
                        random.uniform(pre.semiMinRelRnd, 1) * rad
                        for i in (0, 1, 2)
                    ]
                else:
                    semiAxes = Vector3(pre.semiRelFixed) * rad
                p = woo.utils.ellipsoid(center=pos,
                                        semiAxes=semiAxes,
                                        ori=rndOri2d(),
                                        mat=ellMat)
            else:
                p = woo.utils.sphere(center=pos, radius=rad, mat=ellMat)
            p.vel = rndOri2d() * Vector3(pre.vMax * random.random(), 0, 0)
            S.energy['kin0'] -= p.Ek
            p.blocked = 'zXY'
            S.dem.par.add(p)
        #for coord,axis,sense in [(0,0,+1),(pre.boxSize[0],0,-1),(0,1,+1),(pre.boxSize[1],1,-1)]:
        #    S.dem.par.add(woo.utils.wall(coord,axis=axis,sense=sense,mat=wallMat,visible=False))
        S.dem.par.add([
            woo.dem.Wall.make(0, axis=0, mat=wallMat, visible=True),
            woo.dem.Wall.make(0, axis=1, mat=wallMat, visible=True)
        ])
        S.periodic = True
        S.cell.setBox((pre.boxSize[0], pre.boxSize[1], 2 * ZZ))

        S.engines = woo.dem.DemField.minimalEngines(
            model=pre.model, dynDtPeriod=10
        ) + [
            # trace particles and color by z-angVel
            woo.dem.Tracer(num=100,
                           compress=4,
                           compSkip=1,
                           glSmooth=True,
                           glWidth=2,
                           scalar=woo.dem.Tracer.scalarAngVel,
                           vecAxis=2,
                           stepPeriod=40,
                           minDist=pre.rRange[0]),
            woo.core.PyRunner(
                100,
                'S.plot.addData(i=S.step,t=S.time,total=S.energy.total(),relErr=(S.energy.relErr() if S.step>100 else 0),**S.energy)'
            ),
            woo.dem.VtkExport(stepPeriod=pre.vtkStep,
                              out=pre.exportFmt,
                              ellLev=pre.vtkEllLev,
                              dead=(pre.vtkStep <= 0)),
            woo.core.PyRunner(
                pre.ell2Step,
                'import woo.pre.ell2d; mx=woo.pre.ell2d.ell2plot(out="%s-%05d.png"%(S.expandTags(S.pre.exportFmt),engine.nDone),S=S,colorRange=(0,S.lab.maxEll2Color),bbox=((0,0),S.pre.boxSize)); S.lab.maxEll2Color=max(mx,S.lab.maxEll2Color)',
                dead=(pre.ell2Step <= 0)),
            woo.dem.WeirdTriaxControl(goal=(-0, -0, 0),
                                      stressMask=0,
                                      maxStrainRate=(.1, .1, 0),
                                      mass=1.,
                                      label='triax'),
        ]

        S.lab.leapfrog.kinSplit = True

        S.dtSafety = pre.dtSafety
        S.trackEnergy = True

        S.uiBuild = 'import woo.pre.ell2d; woo.pre.ell2d.ellGroupUiBuild(S,area)'

        S.lab.maxEll2Color = 0.  # max |angVel| for the start when plotting

        S.plot.plots = {'i': ('total', '**S.energy'), ' t': ('relErr')}
        S.plot.data = {
            'i': [nan],
            'total': [nan],
            'relErr': [nan]
        }  # to make plot displayable from the very start

        try:
            import woo.gl
            S.gl.renderer = woo.gl.Renderer(iniUp=(0, 1, 0),
                                            iniViewDir=(0, 0, -1),
                                            grid=4)
        except ImportError:
            pass

        return S
Ejemplo n.º 6
0
 def flat(v): return Vector2(v[0],v[1])
 for p in S.dem.par:
Ejemplo n.º 7
0
 def __init__(self, c, r):
     self.center = Vector2(c)
     self.radius = r
     self.extra = {}
Ejemplo n.º 8
0
def arrow(p, d, l):
    d = l * Vector2(d).normalized()
    d = p + d
    line(p, d).mediumThick().arrow()
Ejemplo n.º 9
0
y += dy
paper.path(["M", x, y, "h", l]).normal().dotted().stroke('red')
y += dy
paper.path(["M", x, y, "h", l]).normal().arrow().stroke('red')
#
paper.sphere(200, 100, 50, "#440")
#
paper.save()
######################################################################

######################################################################
# periodic packing
######################################################################
w, h = 520, 500
d = 200
trans = Vector2(165, 350)
ps = (
    Vector2(0, 0),
    Vector2(d, 0),
    Vector2(d, -d),
    Vector2(0, -d),
)
cs1 = (
    Vector2(35, -50),
    Vector2(135, -65),
    Vector2(150, -165),
    Vector2(50, -150),
)
kss = (
    ((1, 0), (0, -1), (1, -1)),
    ((-1, 0), (0, -1)),