woo.dem

Inheritance diagram of woo.dem

Stress/strain control

TODO

PeriIsoCompressor

ObjectEnginePeriIsoCompressor

class woo.dem.PeriIsoCompressor(*args, **kwargs)

Compress/decompress cloud of spheres by controlling periodic cell size until it reaches prescribed average stress, then moving to next stress value in given stress series.

Overloaded function.

  1. __init__(self: woo.dem.PeriIsoCompressor) -> None

  2. __init__(self: woo.dem.PeriIsoCompressor, *args, **kwargs) -> None

stresses(= [])

Stresses that should be reached, one after another

[type: vector<Real>]

charLen(= -1.0)

Characteristic length, should be something like mean particle diameter (default -1=invalid value))

[type: Real]

maxSpan(= -1.0)

Maximum body span in terms of bbox, to prevent periodic cell getting too small.

[type: Real, read-only in python]

maxUnbalanced(= 0.0001)

if actual unbalanced force is smaller than this number, the packing is considered stable,

[type: Real]

globalUpdateInt(= 20)

how often to recompute average stress, stiffness and unbalanced force

[type: int]

state(= 0)

Where are we at in the stress series

[type: size_t]

doneHook(= '')

Python command to be run when reaching the last specified stress

[type: string]

keepProportions(= True)

Exactly keep proportions of the cell (stress is controlled based on average, not its components

[type: bool]

currUnbalanced(= nan)

Current unbalanced force (updated internally)

[type: Real, read-only in python]

avgStiffness(= nan)

Value of average stiffness (updated internally)

[type: Real, read-only in python]

sigma(= Vector3(nan, nan, nan))

Current value of average stress (update internally)

[type: Vector3r, read-only in python]

WeirdTriaxControl

ObjectEngineWeirdTriaxControl

class woo.dem.WeirdTriaxControl(*args, **kwargs)

Engine for independently controlling stress or strain in periodic simulations.

strainStress contains absolute values for the controlled quantity, and stressMask determines meaning of those values (0 for strain, 1 for stress): e.g. ( 1<<0 | 1<<2 ) = 1 | 4 = 5 means that strainStress[0] and strainStress[2] are stress values, and strainStress[1] is strain.

See scripts/test/periodic-triax.py for a simple example.

Overloaded function.

  1. __init__(self: woo.dem.WeirdTriaxControl) -> None

  2. __init__(self: woo.dem.WeirdTriaxControl, *args, **kwargs) -> None

goal(= Vector3(0, 0, 0))

Desired stress or strain values (depending on stressMask), strains defined as strain(i)=log(Fii).

Warning

Strains are relative to the woo.core.Scene.cell.refSize (reference cell size), not the current one (e.g. at the moment when the new strain value is set).

[type: Vector3r]

stressMask(= 0)

mask determining strain/stress (0/1) meaning for goal components

[type: int]

maxStrainRate(= Vector3(1, 1, 1))

Maximum strain rate of the periodic cell.

[type: Vector3r]

maxUnbalanced(= 0.0001)

maximum unbalanced force.

[type: Real]

absStressTol(= 1000.0)

Absolute stress tolerance

[type: Real]

relStressTol(= 3e-05)

Relative stress tolerance; if negative, it is relative to the largest stress value along all axes, where strain is prescribed.

[type: Real]

maxStrainedStress(= nan)

Current abs-maximum stress in strain-controlled directions; useda as reference when relStressTol is negative.

[type: Real, read-only in python]

growDamping(= 0.25)

Damping of cell resizing (0=perfect control, 1=no control at all).

[type: Real]

relVol(= 1.0)

For stress computation, use volume of the periodic cell multiplied by this constant.

[type: Real]

globUpdate(= 5)

How often to recompute average stress, stiffness and unbalaced force.

[type: int]

doneHook(= '')

python command to be run when the desired state is reached

[type: string]

stress(= Matrix3(0, 0, 0, 0, 0, 0, 0, 0, 0))

Stress tensor

[type: Matrix3r]

strain(= Vector3(0, 0, 0))

cell strain, updated automatically

[type: Vector3r]

strainRate(= Vector3(0, 0, 0))

cell strain rate, updated automatically

[type: Vector3r]

currUnbalanced(= nan)

current unbalanced force (updated every globUpdate)

[type: Real]

prevGrow(= Vector3(0, 0, 0))

previous cell grow

[type: Vector3r]

mass(= nan)

mass of the cell (user set); if not set, it will be computed as sum of masses of all particles.

[type: Real]

externalWork(= 0.0)

Work input from boundary controller.

[type: Real]

gradVWorkIx(= -1)

Index for work done by velocity gradient, if tracking energy

[type: int, not saved, not accessible from python]

leapfrogChecked(= False)

Whether we already checked that we come before Leapfrog (otherwise setting nextGradV will have no effect.

[type: bool, not accessible from python]

Contacts

TODO

Contact

ObjectContact

class woo.dem.Contact(*args, **kwargs)

Contact in DEM

Overloaded function.

  1. __init__(self: woo.dem.Contact) -> None

  2. __init__(self: woo.dem.Contact, *args, **kwargs) -> None

geom(= None)

Contact geometry

[type: shared_ptr<CGeom>, read-only in python]

phys(= None)

Physical properties of contact

[type: shared_ptr<CPhys>, read-only in python]

data(= None)

Optional data stored by the functor for its own use

[type: shared_ptr<CData>, read-only in python]

pA

First particle of the contact

[type: weak_ptr<Particle>, read-only in python]

pB

Second particle of the contact

[type: weak_ptr<Particle>, read-only in python]

cellDist(= Vector3i(0, 0, 0))

Distace in the number of periodic cells by which pB must be shifted to get to the right relative position.

[type: Vector3i, read-only in python]

color(= 0.0)

(Normalized) color value for this contact

[type: Real]

stepCreated(= -1)

Step in which this contact was created by the collider, or step in which it was made real (if geom and phys exist). This number is NOT reset by Contact::reset(). If negative, it means the collider does not want to keep this contact around anymore (this happens if the contact is real but there is no overlap anymore).

[type: int, read-only in python]

minDist00Sq(= -1.0)

Minimum distance between nodes[0] of both shapes so that the contact can exist. Set in ContactLoop by geometry functor once, and is used to check for possible contact without having to call the functor. If negative, not used. Currently, only Sphere-Sphere contacts use this information.

[type: Real, read-only in python]

stepLastSeen(= -1)

[type: int, read-only in python]

linIx(= 0)

Position in the linear view (ContactContainer)

[type: size_t, not shown in the UI, read-only in python]

dPos(self: woo.dem.Contact)_wooEigen11.Vector3

Return position difference vector pB-pA, taking Contact.cellDist in account properly. Both particles must be uninodal, exception is raised otherwise.

dist(self: woo.dem.Contact)float

Shorthand for dPos.norm().

forceSign(*args, **kwargs)

Overloaded function.

  1. forceSign(self: woo.dem.Contact, p: woo.dem.Particle) -> int

Return sign of CPhys.force as it appies on the particle passed, i.e. +1 if p==C.pA and -1 if p==C.pB. Raise an exception if p is neither pA or pB.

  1. forceSign(self: woo.dem.Contact, id: int) -> int

Return sign of CPhys.force as it appies on the particle with id id, i.e. id==C.id1 and -1 if id==id2. Raise an exception if id is neither id1 or id2.

property id1

Particle.id of the first contacting particle.

property id2

Particle.id of the second contacting particle.

property ids

IDs of both contacting particles as 2-tuple.

isFresh(self: woo.dem.Contact, scene: woo.core.Scene)bool

Say whether this contact has just been created. Equivalent to C.stepCreated==scene.step.

property real

Whether the contact is real (has geom and phys); unreal contacts are created by broadband collisions detection and have no physical significance.

resetPhys(self: woo.dem.Contact)None

Set phys to None (to force its re-evaluation)

ContactLoop

ObjectEngineContactLoop

class woo.dem.ContactLoop(*args, **kwargs)

Loop over all contacts, possible in a parallel manner.

Special constructor

Constructs from 3 lists of Cg2, Cp2, Law functors respectively; they will be passed to interal dispatchers.

Overloaded function.

  1. __init__(self: woo.dem.ContactLoop) -> None

  2. __init__(self: woo.dem.ContactLoop, *args, **kwargs) -> None

geoDisp(= <CGeomDispatcher @ 0x1601b50>)

CGeomDispatcher object that is used for dispatch.

[type: shared_ptr<CGeomDispatcher>, read-only in python]

phyDisp(= <CPhysDispatcher @ 0x15f3ba0>)

CPhysDispatcher object used for dispatch.

[type: shared_ptr<CPhysDispatcher>, read-only in python]

lawDisp(= <LawDispatcher @ 0x1601a70>)

LawDispatcher object used for dispatch.

[type: shared_ptr<LawDispatcher>, read-only in python]

hook(= None)

ContactHook objects, empty by default.

[type: shared_ptr<ContactHook>]

alreadyWarnedNoCollider(= False)

Keep track of whether the user was already warned about missing collider.

[type: bool, not shown in the UI]

evalStress(= False)

Evaluate stress tensor, in periodic simluations; if energy tracking is enabled, increments gradV energy.

[type: bool]

applyForces(= True)

Apply forces directly; this avoids IntraForce engine, but will silently skip multinodal particles.

[type: bool]

updatePhys(= 0)

Call CPhysFunctor even for contacts which already have Contact.phys (to reflect changes in particle’s material, for example). ‘once’ will update only once and then set this back to ‘never’.

[type: int, named enum, possible values are: ‘never’ (0), ‘always’ (1), ‘once’ (2)]

dist00(= True)

Whether to apply the Contact.minDist00Sq optimization (for mesuring the speedup only)

[type: bool]

stress(= Matrix3(0, 0, 0, 0, 0, 0, 0, 0, 0))

Stress value, used to compute gradV energy if trackWork is True.

[type: Matrix3r, read-only in python]

reorderEvery(= 1000)

Reorder contacts so that real ones are at the beginning in the linear sequence, making the OpenMP loop traversal (hopefully) less unbalanced.

[type: int]

prevVol(= nan)

Previous value of cell volume

[type: Real, not accessible from python]

prevStress(= Matrix3(0, 0, 0, 0, 0, 0, 0, 0, 0))

Previous value of stress, used to compute mid-step stress

[type: Matrix3r]

gradVIx(= -1)

Cache energy index for gradV work

[type: int, not saved, not accessible from python]

ContactHook

ObjectContactHook

digraph ContactHook {
        rankdir=LR;
        margin=.2;
        "ContactHook" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.ContactHook"];
        "CountContactsHook" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.ContactHook"];
        "ContactHook" -> "CountContactsHook" [arrowsize=0.5,style="setlinewidth(0.5)"]
}
class woo.dem.ContactHook(*args, **kwargs)

Functor called from ContactLoop for some specific events on contacts; currently, these events are contact creation and contact deletion. This base class does nothing.

Overloaded function.

  1. __init__(self: woo.dem.ContactHook) -> None

  2. __init__(self: woo.dem.ContactHook, *args, **kwargs) -> None

mask(= 0)

Mask which must be matched by both particles in the contact.

[type: int]

CountContactsHook

ObjectContactHookCountContactsHook

class woo.dem.CountContactsHook(*args, **kwargs)

Functor counting contacts created and deleted in ContactLoop (contacts being deleted e.g. as a result of particle deletion are not counted), restricted by mask.

Overloaded function.

  1. __init__(self: woo.dem.CountContactsHook) -> None

  2. __init__(self: woo.dem.CountContactsHook, *args, **kwargs) -> None

nNew

Total number of new (real) contacts.

[type: OpenMPAccumulator<int>]

nDel

Total number of deleted contacts.

[type: OpenMPAccumulator<int>]

Geometry

TODO

CGeom

ObjectCGeom

digraph CGeom {
        rankdir=LR;
        margin=.2;
        "CGeom" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.CGeom"];
        "G3Geom" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.CGeom"];
        "CGeom" -> "G3Geom" [arrowsize=0.5,style="setlinewidth(0.5)"]           "L6Geom" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.CGeom"];
        "CGeom" -> "L6Geom" [arrowsize=0.5,style="setlinewidth(0.5)"]
}
class woo.dem.CGeom(*args, **kwargs)

Geometrical configuration of contact

Overloaded function.

  1. __init__(self: woo.dem.CGeom) -> None

  2. __init__(self: woo.dem.CGeom, *args, **kwargs) -> None

node(= <Node @ 0x15e9870, at (0, 0, 0)>)

Local coordinates definition.

[type: shared_ptr<Node>]

dispHierarchy(self: woo.dem.CGeom, names: bool = True)list

Return list of dispatch classes (from down upwards), starting with the class instance itself, top-level indexable at last. If names is true (default), return class names rather than numerical indices.

property dispIndex

Return class index of this instance.

L6Geom

ObjectCGeomL6Geom

class woo.dem.L6Geom(*args, **kwargs)

Geometry of particles in contact, defining relative velocities.

Overloaded function.

  1. __init__(self: woo.dem.L6Geom) -> None

  2. __init__(self: woo.dem.L6Geom, *args, **kwargs) -> None

vel(= Vector3(0, 0, 0))

Relative displacement rate in local coordinates, defined by CGeom.node

[type: Vector3r, unit: m/s]

angVel(= Vector3(0, 0, 0))

Relative rotation rate in local coordinates

[type: Vector3r, unit: rad/s]

uN(= nan)

Normal displacement, distace of separation of particles (mathematically equal to integral of vel[0], but given here for numerically more stable results, as this component can be usually computed directly).

[type: Real]

lens(= Vector2(0, 0))

Hint for Cp2 functor on how to distribute material stiffnesses according to lengths on both sides of the contact; their sum should be equal to the initial contact length.

[type: Vector2r, unit: m]

contA(= nan)

(Fictious) contact area, used by Cp2 functor to compute stiffness.

[type: Real, unit: m²]

trsf(= Matrix3(1, 0, 0, 0, 1, 0, 0, 0, 1))

Transformation (rotation) from global to local coordinates; only used internally, and is synchronized with woo.core.Node.ori automatically. If the algorithm works with pure quaternions at some point (it is not stable now), can be removed safely.

[type: Matrix3r]

G3Geom

ObjectCGeomG3Geom

class woo.dem.G3Geom(*args, **kwargs)

Geometry of particles in contact, defining relative velocities.

Overloaded function.

  1. __init__(self: woo.dem.G3Geom) -> None

  2. __init__(self: woo.dem.G3Geom, *args, **kwargs) -> None

uN(= nan)

Normal displacement, distace of separation of particles (mathematically equal to integral of vel[0], but given here for numerically more stable results, as this component can be usually computed directly).

[type: Real]

dShear(= Vector3(0, 0, 0))

Shear displacement delta during last step.

[type: Vector3r]

twistAxis(= Vector3(nan, nan, nan))

Axis of twisting rotation

[type: Vector3r, read-only in python]

orthonormalAxis(= Vector3(nan, nan, nan))

Axis normal to twisting axis

[type: Vector3r, read-only in python]

normal(= Vector3(nan, nan, nan))

Contact normal in global coordinates; G3Geom doesn’t touch Contact.node.ori (which is identity), therefore orientation must be kep separately

[type: Vector3r, read-only in python]

CGeomFunctor

ObjectFunctorCGeomFunctor

digraph CGeomFunctor {
        rankdir=LR;
        margin=.2;
        "CGeomFunctor" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.CGeomFunctor"];
        "Cg2_Cone_Sphere_L6Geom" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.CGeomFunctor"];
        "Cg2_Any_Any_L6Geom__Base" -> "Cg2_Cone_Sphere_L6Geom" [arrowsize=0.5,style="setlinewidth(0.5)"]                "Cg2_Capsule_Capsule_L6Geom" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.CGeomFunctor"];
        "Cg2_Any_Any_L6Geom__Base" -> "Cg2_Capsule_Capsule_L6Geom" [arrowsize=0.5,style="setlinewidth(0.5)"]            "Cg2_Ellipsoid_Ellipsoid_L6Geom" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.CGeomFunctor"];
        "Cg2_Any_Any_L6Geom__Base" -> "Cg2_Ellipsoid_Ellipsoid_L6Geom" [arrowsize=0.5,style="setlinewidth(0.5)"]                "Cg2_Sphere_Sphere_L6Geom" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.CGeomFunctor"];
        "Cg2_Any_Any_L6Geom__Base" -> "Cg2_Sphere_Sphere_L6Geom" [arrowsize=0.5,style="setlinewidth(0.5)"]              "Cg2_Facet_Sphere_L6Geom" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.CGeomFunctor"];
        "Cg2_Any_Any_L6Geom__Base" -> "Cg2_Facet_Sphere_L6Geom" [arrowsize=0.5,style="setlinewidth(0.5)"]               "Cg2_Wall_Facet_L6Geom" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.CGeomFunctor"];
        "Cg2_Any_Any_L6Geom__Base" -> "Cg2_Wall_Facet_L6Geom" [arrowsize=0.5,style="setlinewidth(0.5)"]         "Cg2_Wall_Sphere_L6Geom" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.CGeomFunctor"];
        "Cg2_Any_Any_L6Geom__Base" -> "Cg2_Wall_Sphere_L6Geom" [arrowsize=0.5,style="setlinewidth(0.5)"]                "Cg2_Any_Any_L6Geom__Base" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.CGeomFunctor"];
        "CGeomFunctor" -> "Cg2_Any_Any_L6Geom__Base" [arrowsize=0.5,style="setlinewidth(0.5)"]          "Cg2_Facet_Ellipsoid_L6Geom" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.CGeomFunctor"];
        "Cg2_Any_Any_L6Geom__Base" -> "Cg2_Facet_Ellipsoid_L6Geom" [arrowsize=0.5,style="setlinewidth(0.5)"]            "Cg2_InfCylinder_Capsule_L6Geom" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.CGeomFunctor"];
        "Cg2_Any_Any_L6Geom__Base" -> "Cg2_InfCylinder_Capsule_L6Geom" [arrowsize=0.5,style="setlinewidth(0.5)"]                "Cg2_Facet_InfCylinder_L6Geom" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.CGeomFunctor"];
        "Cg2_Any_Any_L6Geom__Base" -> "Cg2_Facet_InfCylinder_L6Geom" [arrowsize=0.5,style="setlinewidth(0.5)"]          "Cg2_Wall_Sphere_G3Geom" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.CGeomFunctor"];
        "CGeomFunctor" -> "Cg2_Wall_Sphere_G3Geom" [arrowsize=0.5,style="setlinewidth(0.5)"]            "Cg2_Wall_Ellipsoid_L6Geom" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.CGeomFunctor"];
        "Cg2_Any_Any_L6Geom__Base" -> "Cg2_Wall_Ellipsoid_L6Geom" [arrowsize=0.5,style="setlinewidth(0.5)"]             "Cg2_Sphere_Sphere_G3Geom" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.CGeomFunctor"];
        "CGeomFunctor" -> "Cg2_Sphere_Sphere_G3Geom" [arrowsize=0.5,style="setlinewidth(0.5)"]          "Cg2_Wall_Capsule_L6Geom" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.CGeomFunctor"];
        "Cg2_Any_Any_L6Geom__Base" -> "Cg2_Wall_Capsule_L6Geom" [arrowsize=0.5,style="setlinewidth(0.5)"]               "Cg2_InfCylinder_Sphere_L6Geom" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.CGeomFunctor"];
        "Cg2_Any_Any_L6Geom__Base" -> "Cg2_InfCylinder_Sphere_L6Geom" [arrowsize=0.5,style="setlinewidth(0.5)"]         "Cg2_Sphere_Ellipsoid_L6Geom" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.CGeomFunctor"];
        "Cg2_Ellipsoid_Ellipsoid_L6Geom" -> "Cg2_Sphere_Ellipsoid_L6Geom" [arrowsize=0.5,style="setlinewidth(0.5)"]             "Cg2_Sphere_Capsule_L6Geom" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.CGeomFunctor"];
        "Cg2_Any_Any_L6Geom__Base" -> "Cg2_Sphere_Capsule_L6Geom" [arrowsize=0.5,style="setlinewidth(0.5)"]             "Cg2_Facet_Capsule_L6Geom" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.CGeomFunctor"];
        "Cg2_Any_Any_L6Geom__Base" -> "Cg2_Facet_Capsule_L6Geom" [arrowsize=0.5,style="setlinewidth(0.5)"]              "Cg2_Rod_Sphere_L6Geom" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.CGeomFunctor"];
        "Cg2_Any_Any_L6Geom__Base" -> "Cg2_Rod_Sphere_L6Geom" [arrowsize=0.5,style="setlinewidth(0.5)"]         "Cg2_Facet_Facet_L6Geom" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.CGeomFunctor"];
        "Cg2_Any_Any_L6Geom__Base" -> "Cg2_Facet_Facet_L6Geom" [arrowsize=0.5,style="setlinewidth(0.5)"]
}
class woo.dem.CGeomFunctor(*args, **kwargs)

Functor for creating/updating Contact.geom objects.

Overloaded function.

  1. __init__(self: woo.dem.CGeomFunctor) -> None

  2. __init__(self: woo.dem.CGeomFunctor, *args, **kwargs) -> None

Cg2_Sphere_Sphere_G3Geom

ObjectFunctorCGeomFunctorCg2_Sphere_Sphere_G3Geom

class woo.dem.Cg2_Sphere_Sphere_G3Geom(*args, **kwargs)

Incrementally compute G3Geom for contact of 2 spheres. Detailed documentation in py/_extraDocs.py

Overloaded function.

  1. __init__(self: woo.dem.Cg2_Sphere_Sphere_G3Geom) -> None

  2. __init__(self: woo.dem.Cg2_Sphere_Sphere_G3Geom, *args, **kwargs) -> None

noRatch(= True)

FIXME: document what it really does.

[type: bool]

useAlpha(= True)

Use alpha correction proposed by McNamara, see source code for details

[type: bool]

Cg2_Any_Any_L6Geom__Base

ObjectFunctorCGeomFunctorCg2_Any_Any_L6Geom__Base

digraph Cg2_Any_Any_L6Geom__Base {
        rankdir=LR;
        margin=.2;
        "Cg2_Any_Any_L6Geom__Base" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.Cg2_Any_Any_L6Geom__Base"];
        "Cg2_Cone_Sphere_L6Geom" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.Cg2_Any_Any_L6Geom__Base"];
        "Cg2_Any_Any_L6Geom__Base" -> "Cg2_Cone_Sphere_L6Geom" [arrowsize=0.5,style="setlinewidth(0.5)"]                "Cg2_Capsule_Capsule_L6Geom" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.Cg2_Any_Any_L6Geom__Base"];
        "Cg2_Any_Any_L6Geom__Base" -> "Cg2_Capsule_Capsule_L6Geom" [arrowsize=0.5,style="setlinewidth(0.5)"]            "Cg2_Ellipsoid_Ellipsoid_L6Geom" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.Cg2_Any_Any_L6Geom__Base"];
        "Cg2_Any_Any_L6Geom__Base" -> "Cg2_Ellipsoid_Ellipsoid_L6Geom" [arrowsize=0.5,style="setlinewidth(0.5)"]                "Cg2_Sphere_Sphere_L6Geom" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.Cg2_Any_Any_L6Geom__Base"];
        "Cg2_Any_Any_L6Geom__Base" -> "Cg2_Sphere_Sphere_L6Geom" [arrowsize=0.5,style="setlinewidth(0.5)"]              "Cg2_Facet_Sphere_L6Geom" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.Cg2_Any_Any_L6Geom__Base"];
        "Cg2_Any_Any_L6Geom__Base" -> "Cg2_Facet_Sphere_L6Geom" [arrowsize=0.5,style="setlinewidth(0.5)"]               "Cg2_Wall_Facet_L6Geom" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.Cg2_Any_Any_L6Geom__Base"];
        "Cg2_Any_Any_L6Geom__Base" -> "Cg2_Wall_Facet_L6Geom" [arrowsize=0.5,style="setlinewidth(0.5)"]         "Cg2_Wall_Sphere_L6Geom" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.Cg2_Any_Any_L6Geom__Base"];
        "Cg2_Any_Any_L6Geom__Base" -> "Cg2_Wall_Sphere_L6Geom" [arrowsize=0.5,style="setlinewidth(0.5)"]                "Cg2_Facet_Ellipsoid_L6Geom" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.Cg2_Any_Any_L6Geom__Base"];
        "Cg2_Any_Any_L6Geom__Base" -> "Cg2_Facet_Ellipsoid_L6Geom" [arrowsize=0.5,style="setlinewidth(0.5)"]            "Cg2_InfCylinder_Capsule_L6Geom" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.Cg2_Any_Any_L6Geom__Base"];
        "Cg2_Any_Any_L6Geom__Base" -> "Cg2_InfCylinder_Capsule_L6Geom" [arrowsize=0.5,style="setlinewidth(0.5)"]                "Cg2_Facet_InfCylinder_L6Geom" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.Cg2_Any_Any_L6Geom__Base"];
        "Cg2_Any_Any_L6Geom__Base" -> "Cg2_Facet_InfCylinder_L6Geom" [arrowsize=0.5,style="setlinewidth(0.5)"]          "Cg2_Wall_Ellipsoid_L6Geom" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.Cg2_Any_Any_L6Geom__Base"];
        "Cg2_Any_Any_L6Geom__Base" -> "Cg2_Wall_Ellipsoid_L6Geom" [arrowsize=0.5,style="setlinewidth(0.5)"]             "Cg2_Wall_Capsule_L6Geom" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.Cg2_Any_Any_L6Geom__Base"];
        "Cg2_Any_Any_L6Geom__Base" -> "Cg2_Wall_Capsule_L6Geom" [arrowsize=0.5,style="setlinewidth(0.5)"]               "Cg2_InfCylinder_Sphere_L6Geom" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.Cg2_Any_Any_L6Geom__Base"];
        "Cg2_Any_Any_L6Geom__Base" -> "Cg2_InfCylinder_Sphere_L6Geom" [arrowsize=0.5,style="setlinewidth(0.5)"]         "Cg2_Sphere_Ellipsoid_L6Geom" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.Cg2_Any_Any_L6Geom__Base"];
        "Cg2_Ellipsoid_Ellipsoid_L6Geom" -> "Cg2_Sphere_Ellipsoid_L6Geom" [arrowsize=0.5,style="setlinewidth(0.5)"]             "Cg2_Sphere_Capsule_L6Geom" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.Cg2_Any_Any_L6Geom__Base"];
        "Cg2_Any_Any_L6Geom__Base" -> "Cg2_Sphere_Capsule_L6Geom" [arrowsize=0.5,style="setlinewidth(0.5)"]             "Cg2_Facet_Capsule_L6Geom" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.Cg2_Any_Any_L6Geom__Base"];
        "Cg2_Any_Any_L6Geom__Base" -> "Cg2_Facet_Capsule_L6Geom" [arrowsize=0.5,style="setlinewidth(0.5)"]              "Cg2_Rod_Sphere_L6Geom" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.Cg2_Any_Any_L6Geom__Base"];
        "Cg2_Any_Any_L6Geom__Base" -> "Cg2_Rod_Sphere_L6Geom" [arrowsize=0.5,style="setlinewidth(0.5)"]         "Cg2_Facet_Facet_L6Geom" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.Cg2_Any_Any_L6Geom__Base"];
        "Cg2_Any_Any_L6Geom__Base" -> "Cg2_Facet_Facet_L6Geom" [arrowsize=0.5,style="setlinewidth(0.5)"]
}
class woo.dem.Cg2_Any_Any_L6Geom__Base(*args, **kwargs)

Common base for L6Geom-computing functors such as Cg2_Sphere_Sphere_L6Geom, holding common approximation flags.

Overloaded function.

  1. __init__(self: woo.dem.Cg2_Any_Any_L6Geom__Base) -> None

  2. __init__(self: woo.dem.Cg2_Any_Any_L6Geom__Base, *args, **kwargs) -> None

noRatch(= False)

FIXME: document what it really does.

[type: bool]

iniLensTouch(= True)

Set L6Geom.lens to touch distance (e.g. radii sum for spheres). If false, L6Geom.lens is set to the initial contact distance (which is less than the touch distance, with overlap subtracted); this implies path-dependent L6Geom.lens and unpredictable stiffness. Do not set to false unless you know what you are doing.

[type: bool]

trsfRenorm(= 100)

How often to renormalize trsf; if non-positive, never renormalized (simulation might be unstable)

[type: int]

approxMask(= 0)

Selectively enable geometrical approximations (bitmask); add the values for approximations to be enabled.

1

use previous normal instead of mid-step normal for computing tangent velocity

2

do not re-normalize average (mid-step) normal, if used.

4

use previous rotation instead of mid-step rotation to transform velocities

8

use current branches instead of mid-step branches to evaluate incident velocity (used without noRatch)

By default, the mask is zero, wherefore none of these approximations is used.

[type: int, range: 0−15]

Cg2_Facet_Capsule_L6Geom

ObjectFunctorCGeomFunctorCg2_Any_Any_L6Geom__BaseCg2_Facet_Capsule_L6Geom

class woo.dem.Cg2_Facet_Capsule_L6Geom(*args, **kwargs)

Compute L6Geom for contact of Capsule and Facet.

Overloaded function.

  1. __init__(self: woo.dem.Cg2_Facet_Capsule_L6Geom) -> None

  2. __init__(self: woo.dem.Cg2_Facet_Capsule_L6Geom, *args, **kwargs) -> None

Cg2_Wall_Facet_L6Geom

ObjectFunctorCGeomFunctorCg2_Any_Any_L6Geom__BaseCg2_Wall_Facet_L6Geom

class woo.dem.Cg2_Wall_Facet_L6Geom(*args, **kwargs)

Incrementally compute L6Geom for contact between Wall and Facet.

Overloaded function.

  1. __init__(self: woo.dem.Cg2_Wall_Facet_L6Geom) -> None

  2. __init__(self: woo.dem.Cg2_Wall_Facet_L6Geom, *args, **kwargs) -> None

Cg2_Facet_InfCylinder_L6Geom

ObjectFunctorCGeomFunctorCg2_Any_Any_L6Geom__BaseCg2_Facet_InfCylinder_L6Geom

class woo.dem.Cg2_Facet_InfCylinder_L6Geom(*args, **kwargs)

Incrementally compute L6Geom for contact between Facet and InfCylinder.

Overloaded function.

  1. __init__(self: woo.dem.Cg2_Facet_InfCylinder_L6Geom) -> None

  2. __init__(self: woo.dem.Cg2_Facet_InfCylinder_L6Geom, *args, **kwargs) -> None

Cg2_Wall_Capsule_L6Geom

ObjectFunctorCGeomFunctorCg2_Any_Any_L6Geom__BaseCg2_Wall_Capsule_L6Geom

class woo.dem.Cg2_Wall_Capsule_L6Geom(*args, **kwargs)

Compute L6Geom for contact of Capsule and Wall (axis-aligned plane).

Overloaded function.

  1. __init__(self: woo.dem.Cg2_Wall_Capsule_L6Geom) -> None

  2. __init__(self: woo.dem.Cg2_Wall_Capsule_L6Geom, *args, **kwargs) -> None

Cg2_Wall_Sphere_L6Geom

ObjectFunctorCGeomFunctorCg2_Any_Any_L6Geom__BaseCg2_Wall_Sphere_L6Geom

class woo.dem.Cg2_Wall_Sphere_L6Geom(*args, **kwargs)

Incrementally compute L6Geom for contact between Wall and Sphere. Uses attributes of Cg2_Sphere_Sphere_L6Geom.

Overloaded function.

  1. __init__(self: woo.dem.Cg2_Wall_Sphere_L6Geom) -> None

  2. __init__(self: woo.dem.Cg2_Wall_Sphere_L6Geom, *args, **kwargs) -> None

Cg2_Facet_Facet_L6Geom

ObjectFunctorCGeomFunctorCg2_Any_Any_L6Geom__BaseCg2_Facet_Facet_L6Geom

class woo.dem.Cg2_Facet_Facet_L6Geom(*args, **kwargs)

Incrementally compute L6Geom for contact between two Facet shapes.

Overloaded function.

  1. __init__(self: woo.dem.Cg2_Facet_Facet_L6Geom) -> None

  2. __init__(self: woo.dem.Cg2_Facet_Facet_L6Geom, *args, **kwargs) -> None

Cg2_Ellipsoid_Ellipsoid_L6Geom

ObjectFunctorCGeomFunctorCg2_Any_Any_L6Geom__BaseCg2_Ellipsoid_Ellipsoid_L6Geom

digraph Cg2_Ellipsoid_Ellipsoid_L6Geom {
        rankdir=LR;
        margin=.2;
        "Cg2_Ellipsoid_Ellipsoid_L6Geom" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.Cg2_Ellipsoid_Ellipsoid_L6Geom"];
        "Cg2_Sphere_Ellipsoid_L6Geom" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.Cg2_Ellipsoid_Ellipsoid_L6Geom"];
        "Cg2_Ellipsoid_Ellipsoid_L6Geom" -> "Cg2_Sphere_Ellipsoid_L6Geom" [arrowsize=0.5,style="setlinewidth(0.5)"]
}
class woo.dem.Cg2_Ellipsoid_Ellipsoid_L6Geom(*args, **kwargs)

Incrementally compute L6Geom for contact of 2 ellipsoids. Uses the Perram-Wertheim potential function ([PW85], [PRPraestgaardL96], [DTS05]). See example scripts examples/ell0.py and examples/ell1.py.

Overloaded function.

  1. __init__(self: woo.dem.Cg2_Ellipsoid_Ellipsoid_L6Geom) -> None

  2. __init__(self: woo.dem.Cg2_Ellipsoid_Ellipsoid_L6Geom, *args, **kwargs) -> None

brent(= True)

Use Brent iteration for finding maximum of the Perram-Wertheim potential. If false, use Newton-Raphson (not yet implemented).

[type: bool]

brentBits(= 32)

Precision for the Brent method, as number of bits.

[type: int]

Cg2_Sphere_Ellipsoid_L6Geom

ObjectFunctorCGeomFunctorCg2_Any_Any_L6Geom__BaseCg2_Ellipsoid_Ellipsoid_L6GeomCg2_Sphere_Ellipsoid_L6Geom

class woo.dem.Cg2_Sphere_Ellipsoid_L6Geom(*args, **kwargs)

Compute the geometry of Ellipsoid + Sphere collision. Uses the code from Cg2_Ellipsoid_Ellipsoid_L6Geom, representing the sphere as an ellipsoid with all semiaxes equal to the radius.

Overloaded function.

  1. __init__(self: woo.dem.Cg2_Sphere_Ellipsoid_L6Geom) -> None

  2. __init__(self: woo.dem.Cg2_Sphere_Ellipsoid_L6Geom, *args, **kwargs) -> None

Cg2_Sphere_Capsule_L6Geom

ObjectFunctorCGeomFunctorCg2_Any_Any_L6Geom__BaseCg2_Sphere_Capsule_L6Geom

class woo.dem.Cg2_Sphere_Capsule_L6Geom(*args, **kwargs)

Compute L6Geom for contact of Capsule and Sphere.

Overloaded function.

  1. __init__(self: woo.dem.Cg2_Sphere_Capsule_L6Geom) -> None

  2. __init__(self: woo.dem.Cg2_Sphere_Capsule_L6Geom, *args, **kwargs) -> None

Cg2_Facet_Sphere_L6Geom

ObjectFunctorCGeomFunctorCg2_Any_Any_L6Geom__BaseCg2_Facet_Sphere_L6Geom

class woo.dem.Cg2_Facet_Sphere_L6Geom(*args, **kwargs)

Incrementally compute L6Geom for contact between Facet and Sphere.

Overloaded function.

  1. __init__(self: woo.dem.Cg2_Facet_Sphere_L6Geom) -> None

  2. __init__(self: woo.dem.Cg2_Facet_Sphere_L6Geom, *args, **kwargs) -> None

Cg2_Capsule_Capsule_L6Geom

ObjectFunctorCGeomFunctorCg2_Any_Any_L6Geom__BaseCg2_Capsule_Capsule_L6Geom

class woo.dem.Cg2_Capsule_Capsule_L6Geom(*args, **kwargs)

Collision of two Capsule shapes.

Overloaded function.

  1. __init__(self: woo.dem.Cg2_Capsule_Capsule_L6Geom) -> None

  2. __init__(self: woo.dem.Cg2_Capsule_Capsule_L6Geom, *args, **kwargs) -> None

Cg2_Rod_Sphere_L6Geom

ObjectFunctorCGeomFunctorCg2_Any_Any_L6Geom__BaseCg2_Rod_Sphere_L6Geom

class woo.dem.Cg2_Rod_Sphere_L6Geom(*args, **kwargs)

Incrementally compute L6Geom for contact between Rod and Sphere. Uses attributes of Cg2_Sphere_Sphere_L6Geom.

Overloaded function.

  1. __init__(self: woo.dem.Cg2_Rod_Sphere_L6Geom) -> None

  2. __init__(self: woo.dem.Cg2_Rod_Sphere_L6Geom, *args, **kwargs) -> None

Cg2_Facet_Ellipsoid_L6Geom

ObjectFunctorCGeomFunctorCg2_Any_Any_L6Geom__BaseCg2_Facet_Ellipsoid_L6Geom

class woo.dem.Cg2_Facet_Ellipsoid_L6Geom(*args, **kwargs)

Compute L6Geom for contact of ellipsoid and facet.

Warning

This class does not work (the result is correct only for face contact, otherwise bogus) and is by default not returned in woo.dem.DemField.minimalEngines. See this question for a brief discussion.

Overloaded function.

  1. __init__(self: woo.dem.Cg2_Facet_Ellipsoid_L6Geom) -> None

  2. __init__(self: woo.dem.Cg2_Facet_Ellipsoid_L6Geom, *args, **kwargs) -> None

Cg2_Cone_Sphere_L6Geom

ObjectFunctorCGeomFunctorCg2_Any_Any_L6Geom__BaseCg2_Cone_Sphere_L6Geom

class woo.dem.Cg2_Cone_Sphere_L6Geom(*args, **kwargs)

Incrementally compute L6Geom for contact between Cone and Sphere. Uses attributes of Cg2_Sphere_Sphere_L6Geom.

Overloaded function.

  1. __init__(self: woo.dem.Cg2_Cone_Sphere_L6Geom) -> None

  2. __init__(self: woo.dem.Cg2_Cone_Sphere_L6Geom, *args, **kwargs) -> None

Cg2_InfCylinder_Sphere_L6Geom

ObjectFunctorCGeomFunctorCg2_Any_Any_L6Geom__BaseCg2_InfCylinder_Sphere_L6Geom

class woo.dem.Cg2_InfCylinder_Sphere_L6Geom(*args, **kwargs)

Incrementally compute L6Geom for contact between InfCylinder and Sphere. Uses attributes of Cg2_Sphere_Sphere_L6Geom.

Overloaded function.

  1. __init__(self: woo.dem.Cg2_InfCylinder_Sphere_L6Geom) -> None

  2. __init__(self: woo.dem.Cg2_InfCylinder_Sphere_L6Geom, *args, **kwargs) -> None

Cg2_InfCylinder_Capsule_L6Geom

ObjectFunctorCGeomFunctorCg2_Any_Any_L6Geom__BaseCg2_InfCylinder_Capsule_L6Geom

class woo.dem.Cg2_InfCylinder_Capsule_L6Geom(*args, **kwargs)

Compute L6Geom for contact of Capsule and InfCylinder.

Overloaded function.

  1. __init__(self: woo.dem.Cg2_InfCylinder_Capsule_L6Geom) -> None

  2. __init__(self: woo.dem.Cg2_InfCylinder_Capsule_L6Geom, *args, **kwargs) -> None

Cg2_Sphere_Sphere_L6Geom

ObjectFunctorCGeomFunctorCg2_Any_Any_L6Geom__BaseCg2_Sphere_Sphere_L6Geom

class woo.dem.Cg2_Sphere_Sphere_L6Geom(*args, **kwargs)

Functor for computing incrementally configuration of 2 Spheres stored in L3Geom; the configuration is positioned in global space by local origin \(\vec{c}\) (contact point) and rotation matrix \(\mat{T}\) (orthonormal transformation matrix), and its degrees of freedom are local displacement \(\vec{u}\) (in one normal and two shear directions); with Ig2_Sphere_Sphere_L6Geom and L6Geom, there is additionally \(\vec{\phi}\). The first row of \(\mat{T}\), i.e. local \(x\)-axis, is the contact normal noted \(\vec{n}\) for brevity. Additionally, quasi-constant values of \(\vec{u}_0\) (and \(\vec{\phi}_0\)) are stored as shifted origins of \(\vec{u}\) (and \(\vec{\phi}\)); therefore, current value of displacement is always \(\curr{\vec{u}}-\vec{u}_0\).

Suppose two spheres with radii \(r_i\), positions \(\vec{x}_i\), velocities \(\vec{v}_i\), angular velocities \(\vec{\omega}_i\).

When there is not yet contact, it will be created if \(u_N=|\curr{\vec{x}}_2-\curr{\vec{x}}_1|-|f_d|(r_1+r2)<0\), where \(f_d\) is distFactor (sometimes also called “interaction radius”). If \(f_d>0\), then \(\vec{u}_{0x}\) will be initalized to \(u_N\), otherwise to 0. In another words, contact will be created if spheres enlarged by \(|f_d|\) touch, and the “equilibrium distance” (where \(\vec{u}_x-\vec{u}-{0x}\) is zero) will be set to the current distance if \(f_d\) is positive, and to the geometrically-touching distance if negative.

Local axes (rows of \(\mat{T}\)) are initially defined as follows:

  • local \(x\)-axis is \(\vec{n}=\vec{x}_l=\normalized{\vec{x}_2-\vec{x}_1}\);

  • local \(y\)-axis positioned arbitrarily, but in a deterministic manner: aligned with the \(xz\) plane (if \(\vec{n}_y<\vec{n}_z\)) or \(xy\) plane (otherwise);

  • local \(z\)-axis \(\vec{z}_l=\vec{x}_l\times\vec{y}_l\).

If there has already been contact between the two spheres, it is updated to keep track of rigid motion of the contact (one that does not change mutual configuration of spheres) and mutual configuration changes. Rigid motion transforms local coordinate system and can be decomposed in rigid translation (affecting \(\vec{c}\)), and rigid rotation (affecting \(\mat{T}\)), which can be split in rotation \(\vec{o}_r\) perpendicular to the normal and rotation \(\vec{o}_t\) (“twist”) parallel with the normal:

\[\pprev{\vec{o}_r}=\prev{\vec{n}}\times\curr{\vec{n}}.\]

Since velocities are known at previous midstep (\(t-\Dt/2\)), we consider mid-step normal

\[\pprev{\vec{n}}=\frac{\prev{\vec{n}}+\curr{\vec{n}}}{2}.\]

For the sake of numerical stability, \(\pprev{\vec{n}}\) is re-normalized after being computed, unless prohibited by approxMask. If approxMask has the appropriate bit set, the mid-normal is not compute, and we simply use \(\pprev{\vec{n}}\approx\prev{\vec{n}}\).

Rigid rotation parallel with the normal is

\[\pprev{\vec{o}_t}=\pprev{\vec{n}}\left(\pprev{\vec{n}}\cdot\frac{\pprev{\vec{\omega}}_1+\pprev{\vec{\omega}}_2}{2}\right)\Dt.\]

Branch vectors \(\vec{b}_1\), \(\vec{b}_2\) (connecting \(\curr{\vec{x}}_1\), \(\curr{\vec{x}}_2\) with \(\curr{\vec{c}}\) are computed depending on noRatch (see here).

\begin{align*} \vec{b}_1&=\begin{cases} r_1 \curr{\vec{n}} & \mbox{with noRatch} \\ \curr{\vec{c}}-\curr{\vec{x}}_1 & \mbox{otherwise} \end{cases} \\ \vec{b}_2&=\begin{cases} -r_2\curr{\vec{n}} & \mbox{with noRatch} \\ \curr{\vec{c}}-\curr{\vec{x}}_2 & \mbox{otherwise} \end{cases} \\ \end{align*}

Relative velocity at \(\curr{\vec{c}}\) can be computed as

\[\pprev{\vec{v}_r}=(\pprev{\vec{\tilde{v}}_2}+\vec{\omega}_2\times\vec{b}_2)-(\vec{v}_1+\vec{\omega}_1\times\vec{b}_1)\]

where \(\vec{\tilde{v}}_2\) is \(\vec{v}_2\) without mean-field velocity gradient in periodic boundary conditions (see Cell.homoDeform). In the numerial implementation, the normal part of incident velocity is removed (since it is computed directly) with \(\pprev{\vec{v}_{r2}}=\pprev{\vec{v}_r}-(\pprev{\vec{n}}\cdot\pprev{\vec{v}_r})\pprev{\vec{n}}\).

Any vector \(\vec{a}\) expressed in global coordinates transforms during one timestep as

\[\curr{\vec{a}}=\prev{\vec{a}}+\pprev{\vec{v}_r}\Dt-\prev{\vec{a}}\times\pprev{\vec{o}_r}-\prev{\vec{a}}\times{\pprev{\vec{t}_r}}\]

where the increments have the meaning of relative shear, rigid rotation normal to \(\vec{n}\) and rigid rotation parallel with \(\vec{n}\). Local coordinate system orientation, rotation matrix \(\mat{T}\), is updated by rows, i.e.

\[\begin{split}\curr{\mat{T}}=\begin{pmatrix} \curr{\vec{n}_x}, \curr{\vec{n}_y}, \curr{\vec{n}_z} \\ \prev{\mat{T}_{1,\bullet}}-\prev{\mat{T}_{1,\bullet}}\times\pprev{\vec{o}_r}-\prev{\mat{T}_{1,\bullet}}\times\pprev{\vec{o}_t} \\ \prev{\mat{T}_{2,\bullet}}-\prev{\mat{T}_{2,\bullet}}\times\pprev{\vec{o}_r}-\prev{\mat{T}_{,\bullet}}\times\pprev{\vec{o}_t} \end{pmatrix}\end{split}\]

This matrix is re-normalized (unless prevented by approxMask) and mid-step transformation is computed using quaternion spherical interpolation as

\[\pprev{\mat{T}}=\mathrm{Slerp}\,\left(\prev{\mat{T}};\curr{\mat{T}};t=1/2\right).\]

Depending on approxMask, this computation can be avoided by approximating \(\pprev{\mat{T}}=\prev{\mat{T}}\).

Finally, current displacement is evaluated as

\[\curr{\vec{u}}=\prev{u}+\pprev{\mat{T}}\pprev{\vec{v}_r}\Dt.\]

For the normal component, non-incremental evaluation is preferred, giving

\[\curr{\vec{u}_x}=|\curr{\vec{x}_2}-\curr{\vec{x}_1}|-(r_1+r_2)\]

If this functor is called for L6Geom, local rotation is updated as

\[\curr{\vec{\phi}}=\prev{\vec{\phi}}+\pprev{\mat{T}}\Dt(\vec{\omega}_2-\vec{\omega}_1)\]

Overloaded function.

  1. __init__(self: woo.dem.Cg2_Sphere_Sphere_L6Geom) -> None

  2. __init__(self: woo.dem.Cg2_Sphere_Sphere_L6Geom, *args, **kwargs) -> None

distFactor(= -1.0)

removed in API 10103, set DemField.distFactor instead.

[type: Real, not shown in the UI, not dumped, DEPRECATED, raises ValueError when accessed]

Cg2_Wall_Ellipsoid_L6Geom

ObjectFunctorCGeomFunctorCg2_Any_Any_L6Geom__BaseCg2_Wall_Ellipsoid_L6Geom

class woo.dem.Cg2_Wall_Ellipsoid_L6Geom(*args, **kwargs)

Compute L6Geom for contact of ellipsoid and wall (axis-aligned plane).

Overloaded function.

  1. __init__(self: woo.dem.Cg2_Wall_Ellipsoid_L6Geom) -> None

  2. __init__(self: woo.dem.Cg2_Wall_Ellipsoid_L6Geom, *args, **kwargs) -> None

Cg2_Wall_Sphere_G3Geom

ObjectFunctorCGeomFunctorCg2_Wall_Sphere_G3Geom

class woo.dem.Cg2_Wall_Sphere_G3Geom(*args, **kwargs)

Incrementally compute G3Geom for contact of 2 spheres. Detailed documentation in py/_extraDocs.py

Overloaded function.

  1. __init__(self: woo.dem.Cg2_Wall_Sphere_G3Geom) -> None

  2. __init__(self: woo.dem.Cg2_Wall_Sphere_G3Geom, *args, **kwargs) -> None

CGeomDispatcher

ObjectEngineDispatcherCGeomDispatcher

class woo.dem.CGeomDispatcher(*args, **kwargs)

Dispatcher calling functors based on received argument type(s).

Overloaded function.

  1. __init__(self: woo.dem.CGeomDispatcher) -> None

  2. __init__(self: woo.dem.CGeomDispatcher, *args, **kwargs) -> None

functors(= [])

Functors active in the dispatch mechanism [overridden below].

[type: vector<shared_ptr<CGeomFunctor>>]

dispFunctor(self: woo.dem.CGeomDispatcher, arg0: woo.dem.Shape, arg1: woo.dem.Shape)woo.dem.CGeomFunctor

Return functor that would be dispatched for given argument(s); None if no dispatch; ambiguous dispatch throws.

dispMatrix(self: woo.dem.CGeomDispatcher, names: bool = True)dict

Return dictionary with contents of the dispatch matrix.

Physical properties

TODO

CPhys

ObjectCPhys

digraph CPhys {
        rankdir=LR;
        margin=.2;
        "CPhys" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.CPhys"];
        "FrictPhys" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.CPhys"];
        "CPhys" -> "FrictPhys" [arrowsize=0.5,style="setlinewidth(0.5)"]                "HertzPhys" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.CPhys"];
        "FrictPhys" -> "HertzPhys" [arrowsize=0.5,style="setlinewidth(0.5)"]            "ConcretePhys" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.CPhys"];
        "FrictPhys" -> "ConcretePhys" [arrowsize=0.5,style="setlinewidth(0.5)"]         "PelletPhys" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.CPhys"];
        "FrictPhys" -> "PelletPhys" [arrowsize=0.5,style="setlinewidth(0.5)"]           "IcePhys" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.CPhys"];
        "FrictPhys" -> "IcePhys" [arrowsize=0.5,style="setlinewidth(0.5)"]              "LudingPhys" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.CPhys"];
        "FrictPhys" -> "LudingPhys" [arrowsize=0.5,style="setlinewidth(0.5)"]
}
class woo.dem.CPhys(*args, **kwargs)

Physical properties of contact.

Overloaded function.

  1. __init__(self: woo.dem.CPhys) -> None

  2. __init__(self: woo.dem.CPhys, *args, **kwargs) -> None

force(= Vector3(0, 0, 0))

Force applied on the first particle in the contact

[type: Vector3r, unit: N]

torque(= Vector3(0, 0, 0))

Torque applied on the first particle in the contact

[type: Vector3r, unit: N·m]

dispHierarchy(self: woo.dem.CPhys, names: bool = True)list

Return list of dispatch classes (from down upwards), starting with the class instance itself, top-level indexable at last. If names is true (default), return class names rather than numerical indices.

property dispIndex

Return class index of this instance.

FrictPhys

ObjectCPhysFrictPhys

digraph FrictPhys {
        rankdir=LR;
        margin=.2;
        "FrictPhys" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.FrictPhys"];
        "HertzPhys" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.FrictPhys"];
        "FrictPhys" -> "HertzPhys" [arrowsize=0.5,style="setlinewidth(0.5)"]            "ConcretePhys" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.FrictPhys"];
        "FrictPhys" -> "ConcretePhys" [arrowsize=0.5,style="setlinewidth(0.5)"]         "PelletPhys" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.FrictPhys"];
        "FrictPhys" -> "PelletPhys" [arrowsize=0.5,style="setlinewidth(0.5)"]           "IcePhys" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.FrictPhys"];
        "FrictPhys" -> "IcePhys" [arrowsize=0.5,style="setlinewidth(0.5)"]              "LudingPhys" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.FrictPhys"];
        "FrictPhys" -> "LudingPhys" [arrowsize=0.5,style="setlinewidth(0.5)"]
}
class woo.dem.FrictPhys(*args, **kwargs)

Physical parameters of contact with sliding

Overloaded function.

  1. __init__(self: woo.dem.FrictPhys) -> None

  2. __init__(self: woo.dem.FrictPhys, *args, **kwargs) -> None

tanPhi(= nan)

Tangent of friction angle

[type: Real]

kn(= nan)

Normal stiffness

[type: Real]

kt(= nan)

Tangent stiffness

[type: Real]

PelletPhys

ObjectCPhysFrictPhysPelletPhys

class woo.dem.PelletPhys(*args, **kwargs)

Physical properties of a contact of two PelletMat.

Overloaded function.

  1. __init__(self: woo.dem.PelletPhys) -> None

  2. __init__(self: woo.dem.PelletPhys, *args, **kwargs) -> None

normPlastCoeff(= nan)

Normal plasticity coefficient.

[type: Real]

ka(= nan)

Adhesive stiffness.

[type: Real]

LudingPhys

ObjectCPhysFrictPhysLudingPhys

class woo.dem.LudingPhys(*args, **kwargs)

Physical properties for luding-contact-model.

Overloaded function.

  1. __init__(self: woo.dem.LudingPhys) -> None

  2. __init__(self: woo.dem.LudingPhys, *args, **kwargs) -> None

kn1(= nan)

Normal plastic (loading) stiffness.

[type: Real]

kna(= nan)

Normal adhesive stiffness.

[type: Real]

k2hat(= nan)

Maximum stiffness.

[type: Real]

deltaMax(= 0.0)

Historically maximum overlap value.

[type: Real]

deltaLim(= nan)

Upper limit for deltaMax.

[type: Real]

kr(= nan)

Roll stiffness.

[type: Real]

kw(= nan)

Twist stiffness.

[type: Real]

viscN(= nan)

Normal viscosity.

[type: Real]

viscT(= nan)

Tangent viscosity.

[type: Real]

viscR(= nan)

Roll viscosity.

[type: Real]

viscW(= nan)

Twist viscosity.

[type: Real]

dynDivStat(= nan)

Dynamic to static friction.

[type: Real]

statR(= nan)

Roll static friction.

[type: Real]

statW(= nan)

Twist static friction.

[type: Real]

xiT(= Vector2(0, 0))

Tangent elastic displacement.

[type: Vector2r]

xiR(= Vector2(0, 0))

Tangent elastic rotation.

[type: Vector2r]

xiW(= 0.0)

Twist elastic rotation.

[type: Real]

work(= [])

Per-contact dissipation (unallocated when energy tracking is not enabled).

[type: vector<Real>]

IcePhys

ObjectCPhysFrictPhysIcePhys

class woo.dem.IcePhys(*args, **kwargs)

Physical properties of a contact of two IceMat.

Overloaded function.

  1. __init__(self: woo.dem.IcePhys) -> None

  2. __init__(self: woo.dem.IcePhys, *args, **kwargs) -> None

kWR(= Vector2(nan, nan))

Twisting and rolling stiffness.

[type: Vector2r]

brkNT(= Vector2(nan, nan))

Limits of breakage in normal & tangential senses.

[type: Vector2r, unit: N]

brkWR(= Vector2(nan, nan))

Limits of breakage in twisting & rolling senses.

[type: Vector2r, unit: N·m]

mu(= nan)

Kinetic (rolling) friction coefficient.

[type: Real]

bonds(= 0)

Bits specifying whether the contact is bonded (in 4 senses) and whether it is breakable (in 4 senses).

[type: int, bit accessors: bondN, bondT, bondW, bondR, brkN, brkT, brkW, brkR]

uN0(= 0.0)

Initial value of normal overlap; set automatically by Law_L6Geom_IcePhys when iniEqlb is true (default).

[type: Real]

isBondX(self: woo.dem.IcePhys, arg0: int)bool

Whether the contact is bonded in the x sense (0..3)

isBrkBondX(self: woo.dem.IcePhys, arg0: int)bool

Whether the contact is breakable and bonded in the x sense (0..3)

isBrkX(self: woo.dem.IcePhys, arg0: int)bool

Whether the contact is breakable in the x sense (0..3)

ConcretePhys

ObjectCPhysFrictPhysConcretePhys

class woo.dem.ConcretePhys(*args, **kwargs)

Representation of a single interaction of the Concrete type: storage for relevant parameters.

Overloaded function.

  1. __init__(self: woo.dem.ConcretePhys) -> None

  2. __init__(self: woo.dem.ConcretePhys, *args, **kwargs) -> None

E(= nan)

normal modulus (stiffness / crossSection) [Pa]

[type: Real]

G(= nan)

shear modulus [Pa]

[type: Real]

coh0(= nan)

virgin material cohesion [Pa]

[type: Real]

epsCrackOnset(= nan)

strain at which the material starts to behave non-linearly

[type: Real]

epsFracture(= nan)

strain at which the bond is fully broken [-]

[type: Real]

dmgTau(= -1.0)

characteristic time for damage (if non-positive, the law without rate-dependence is used)

[type: Real]

dmgRateExp(= 0.0)

exponent in the rate-dependent damage evolution

[type: Real]

dmgStrain(= 0.0)

damage strain (at previous or current step)

[type: Real]

dmgOverstress(= 0.0)

damage viscous overstress (at previous step or at current step)

[type: Real]

plTau(= -1.0)

characteristic time for viscoplasticity (if non-positive, no rate-dependence for shear)

[type: Real]

plRateExp(= 0.0)

exponent in the rate-dependent viscoplasticity

[type: Real]

isoPrestress(= 0.0)

“prestress” of this link (used to simulate isotropic stress)

[type: Real]

neverDamage(= False)

the damage evolution function will always return virgin state

[type: bool]

damLaw(= 1)

Law for softening part of uniaxial tension. 0 for linear, 1 for exponential (default)

[type: int]

isCohesive(= False)

if not cohesive, interaction is deleted when distance is greater than zero.

[type: bool]

epsT(= Vector2(0, 0))

Shear strain; updated incrementally from L6Geom.vel.

[type: Vector2r, not saved, read-only in python]

► Auto-computed

omega(= 0.0)

Damage parameter

[type: Real, not saved, read-only in python]

uN0(= nan)

Initial normal displacement (equilibrium state)

[type: Real, read-only in python]

epsN(= 0.0)

Normal strain

[type: Real, not saved, read-only in python]

sigmaN(= 0.0)

Normal force

[type: Real, not saved, read-only in python]

sigmaT(= Vector2(0, 0))

Tangential stress

[type: Vector2r, not saved, read-only in python]

epsNPl(= 0.0)

Normal plastic strain

[type: Real, not saved, read-only in python]

kappaD(= 0.0)

Value of the kappa function

[type: Real, not saved, read-only in python]

relResidualStrength(= 1.0)

Relative residual strength

[type: Real, not saved, read-only in python]

static funcG(kappaD: float, epsCrackOnset: float, epsFracture: float, neverDamage: bool = False, damLaw: int = 1)float

Damage evolution law, evaluating the $omega$ parameter. $kappa_D$ is historically maximum strain, epsCrackOnset ($varepsilon_0$) = epsCrackOnset, epsFracture = epsFracture; if neverDamage is True, the value returned will always be 0 (no damage).

static funcGInv(omega: float, epsCrackOnset: float, epsFracture: float, neverDamage: bool = False, damLaw: int = 1)float

Inversion of damage evolution law, evaluating the $kappa_D$ parameter. $omega$ is damage, for other parameters see funcG function

setDamage(self: woo.dem.ConcretePhys, arg0: float)None

TODO

setRelResidualStrength(self: woo.dem.ConcretePhys, arg0: float)None

TODO

HertzPhys

ObjectCPhysFrictPhysHertzPhys

class woo.dem.HertzPhys(*args, **kwargs)

Physical properties of a contact of two FrictMat with viscous damping enabled (viscosity is currently not provided as material parameter).

Overloaded function.

  1. __init__(self: woo.dem.HertzPhys) -> None

  2. __init__(self: woo.dem.HertzPhys, *args, **kwargs) -> None

kt0(= 0.0)

Constant for computing current normal stiffness.

[type: Real]

alpha_sqrtMK(= 0.0)

Value for computing damping coefficient – see [AE11], eq (10).

[type: Real]

R(= 0.0)

Effective radius (for the Schwarz model)

[type: Real]

K(= 0.0)

Effective stiffness (for the Schwarz model)

[type: Real]

gamma(= 0.0)

Surface energy (for the Schwarz model)

[type: Real]

alpha(= 0.0)

COS alpha coefficient

[type: Real]

contRad(= 0.0)

Contact radius, used for storing previous value as the initial guess in the next step.

[type: Real]

CPhysFunctor

ObjectFunctorCPhysFunctor

digraph CPhysFunctor {
        rankdir=LR;
        margin=.2;
        "CPhysFunctor" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.CPhysFunctor"];
        "Cp2_PelletMat_PelletPhys" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.CPhysFunctor"];
        "Cp2_FrictMat_FrictPhys" -> "Cp2_PelletMat_PelletPhys" [arrowsize=0.5,style="setlinewidth(0.5)"]                "Cp2_LudingMat_LudingPhys" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.CPhysFunctor"];
        "Cp2_FrictMat_FrictPhys" -> "Cp2_LudingMat_LudingPhys" [arrowsize=0.5,style="setlinewidth(0.5)"]                "Cp2_HertzMat_HertzPhys" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.CPhysFunctor"];
        "Cp2_FrictMat_FrictPhys" -> "Cp2_HertzMat_HertzPhys" [arrowsize=0.5,style="setlinewidth(0.5)"]          "Cp2_IceMat_IcePhys" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.CPhysFunctor"];
        "Cp2_FrictMat_FrictPhys" -> "Cp2_IceMat_IcePhys" [arrowsize=0.5,style="setlinewidth(0.5)"]              "Cp2_FrictMat_FrictPhys" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.CPhysFunctor"];
        "CPhysFunctor" -> "Cp2_FrictMat_FrictPhys" [arrowsize=0.5,style="setlinewidth(0.5)"]            "Cp2_FrictMat_FrictPhys_CrossAnisotropic" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.CPhysFunctor"];
        "CPhysFunctor" -> "Cp2_FrictMat_FrictPhys_CrossAnisotropic" [arrowsize=0.5,style="setlinewidth(0.5)"]           "Cp2_ConcreteMat_ConcretePhys" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.CPhysFunctor"];
        "CPhysFunctor" -> "Cp2_ConcreteMat_ConcretePhys" [arrowsize=0.5,style="setlinewidth(0.5)"]
}
class woo.dem.CPhysFunctor(*args, **kwargs)

Functor for creating/updating Contact.phys objects.

Overloaded function.

  1. __init__(self: woo.dem.CPhysFunctor) -> None

  2. __init__(self: woo.dem.CPhysFunctor, *args, **kwargs) -> None

Cp2_FrictMat_FrictPhys_CrossAnisotropic

ObjectFunctorCPhysFunctorCp2_FrictMat_FrictPhys_CrossAnisotropic

class woo.dem.Cp2_FrictMat_FrictPhys_CrossAnisotropic(*args, **kwargs)

Call Cp2_FrictMat_FrictPhys to create a new FrictPhys, but multiply resulting normal and shear stiffnesses by smooth dimensionless anisotropy distribution given by alpha and beta. The functionality is demonstrated in the following movie:

Overloaded function.

  1. __init__(self: woo.dem.Cp2_FrictMat_FrictPhys_CrossAnisotropic) -> None

  2. __init__(self: woo.dem.Cp2_FrictMat_FrictPhys_CrossAnisotropic, *args, **kwargs) -> None

E1(= 1000000.0)

In-plane normal modulus

[type: Real, unit: Pa]

E2(= 100000.0)

Out-of-plane normal modulus

[type: Real, unit: Pa]

G1(= 10000.0)

In-plane shear modulus

[type: Real, unit: Pa]

G2(= 10000.0)

Out-of-plane shear modulus

[type: Real, unit: Pa]

nu1(= 0.4)

Major Poisson’s ratio; dependent value computed as \(\frac{E_1}{2G_1}-1\).

[type: Real, read-only in python]

alpha(= 0.0)

Strike angle for the local axes

[type: Real, unit: rad, range: 0−6.28319]

beta(= 0.0)

Dip angle for the local axes

[type: Real, unit: rad, range: 0−1.5708]

xisoAxis(= Vector3(1, 0, 0))

Axis (normal) of the cross-anisotropy in global coordinates; computed from alpha and beta as \(\vec{n}=(\cos\alpha\sin\beta,-\sin\alpha\sin\beta,\cos\beta)\).

[type: Vector3r, read-only in python]

recomputeStep(= -1)

Keep track of updates to alpha and beta, so that stiffnesses of existing contacts are forced to be updated.

[type: int]

Cp2_ConcreteMat_ConcretePhys

ObjectFunctorCPhysFunctorCp2_ConcreteMat_ConcretePhys

class woo.dem.Cp2_ConcreteMat_ConcretePhys(*args, **kwargs)

Compute ConcretePhys from two ConcreteMat instances. Uses simple (arithmetic) averages if material are different. Simple copy of parameters is performed if the instance of ConcreteMat is shared.

Overloaded function.

  1. __init__(self: woo.dem.Cp2_ConcreteMat_ConcretePhys) -> None

  2. __init__(self: woo.dem.Cp2_ConcreteMat_ConcretePhys, *args, **kwargs) -> None

cohesiveThresholdStep(= 10)

Should new contacts be cohesive? They will before this iter#, they will not be afterwards. If 0, they will never be. If negative, they will always be created as cohesive (10 by default).

[type: long]

Cp2_FrictMat_FrictPhys

ObjectFunctorCPhysFunctorCp2_FrictMat_FrictPhys

digraph Cp2_FrictMat_FrictPhys {
        rankdir=LR;
        margin=.2;
        "Cp2_FrictMat_FrictPhys" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.Cp2_FrictMat_FrictPhys"];
        "Cp2_PelletMat_PelletPhys" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.Cp2_FrictMat_FrictPhys"];
        "Cp2_FrictMat_FrictPhys" -> "Cp2_PelletMat_PelletPhys" [arrowsize=0.5,style="setlinewidth(0.5)"]                "Cp2_LudingMat_LudingPhys" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.Cp2_FrictMat_FrictPhys"];
        "Cp2_FrictMat_FrictPhys" -> "Cp2_LudingMat_LudingPhys" [arrowsize=0.5,style="setlinewidth(0.5)"]                "Cp2_HertzMat_HertzPhys" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.Cp2_FrictMat_FrictPhys"];
        "Cp2_FrictMat_FrictPhys" -> "Cp2_HertzMat_HertzPhys" [arrowsize=0.5,style="setlinewidth(0.5)"]          "Cp2_IceMat_IcePhys" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.Cp2_FrictMat_FrictPhys"];
        "Cp2_FrictMat_FrictPhys" -> "Cp2_IceMat_IcePhys" [arrowsize=0.5,style="setlinewidth(0.5)"]
}
class woo.dem.Cp2_FrictMat_FrictPhys(*args, **kwargs)

TODO

Overloaded function.

  1. __init__(self: woo.dem.Cp2_FrictMat_FrictPhys) -> None

  2. __init__(self: woo.dem.Cp2_FrictMat_FrictPhys, *args, **kwargs) -> None

tanPhi(= None)

Instance of MatchMaker determining how to compute contact friction angle. If None, minimum value is used.

[type: shared_ptr<MatchMaker>]

Cp2_LudingMat_LudingPhys

ObjectFunctorCPhysFunctorCp2_FrictMat_FrictPhysCp2_LudingMat_LudingPhys

class woo.dem.Cp2_LudingMat_LudingPhys(*args, **kwargs)

Compute LudingPhys given two instances of LudingMat.

Overloaded function.

  1. __init__(self: woo.dem.Cp2_LudingMat_LudingPhys) -> None

  2. __init__(self: woo.dem.Cp2_LudingMat_LudingPhys, *args, **kwargs) -> None

Cp2_IceMat_IcePhys

ObjectFunctorCPhysFunctorCp2_FrictMat_FrictPhysCp2_IceMat_IcePhys

class woo.dem.Cp2_IceMat_IcePhys(*args, **kwargs)

Compute IcePhys given two instances of :ref`IceMat`.

Overloaded function.

  1. __init__(self: woo.dem.Cp2_IceMat_IcePhys) -> None

  2. __init__(self: woo.dem.Cp2_IceMat_IcePhys, *args, **kwargs) -> None

bonds0(= 0)

Bonding bits for new contacts, for the initial configuration.

[type: int, bit accessors: bondN, bondT, bondW, bondR, brkN, brkT, brkW, brkR]

bonds1(= 0)

Bonding bits for new contacts, for contacts created after the initial configuration.

[type: int, bit accessors: bondN, bondT, bondW, bondR, brkN, brkT, brkW, brkR]

step01(= 3)

Step after which bonds1 will be used instead of bonds0 for new contacts.

[type: int]

Cp2_HertzMat_HertzPhys

ObjectFunctorCPhysFunctorCp2_FrictMat_FrictPhysCp2_HertzMat_HertzPhys

class woo.dem.Cp2_HertzMat_HertzPhys(*args, **kwargs)

Compute HertzPhys given two instances of :ref`HertzMat`. The value of HertzPhys.alpha is averaged (from HertzMat.alpha) while HertzPhys.gamma is minimum (of HertzMat.gamma).

Overloaded function.

  1. __init__(self: woo.dem.Cp2_HertzMat_HertzPhys) -> None

  2. __init__(self: woo.dem.Cp2_HertzMat_HertzPhys, *args, **kwargs) -> None

poisson(= 0.2)

Poisson ratio for computing contact properties (not provided by the material class currently)

[type: Real]

en(= nan)

Normal coefficient of restitution (if outside the 0-1 range, there will be no damping, making en effectively equal to one).

[type: Real]

Cp2_PelletMat_PelletPhys

ObjectFunctorCPhysFunctorCp2_FrictMat_FrictPhysCp2_PelletMat_PelletPhys

class woo.dem.Cp2_PelletMat_PelletPhys(*args, **kwargs)

Compute PelletPhys given two instances of :ref`PelletMat`. PelletMat.normPlastCoeff is averaged into PelletPhys.normPlastCoeff, while minimum of PelletMat.kaDivKn is taken to compute PelletPhys.ka.

Overloaded function.

  1. __init__(self: woo.dem.Cp2_PelletMat_PelletPhys) -> None

  2. __init__(self: woo.dem.Cp2_PelletMat_PelletPhys, *args, **kwargs) -> None

CPhysDispatcher

ObjectEngineDispatcherCPhysDispatcher

class woo.dem.CPhysDispatcher(*args, **kwargs)

Dispatcher calling functors based on received argument type(s).

Overloaded function.

  1. __init__(self: woo.dem.CPhysDispatcher) -> None

  2. __init__(self: woo.dem.CPhysDispatcher, *args, **kwargs) -> None

functors(= [])

Functors active in the dispatch mechanism [overridden below].

[type: vector<shared_ptr<CPhysFunctor>>]

dispFunctor(self: woo.dem.CPhysDispatcher, arg0: woo.dem.Material, arg1: woo.dem.Material)woo.dem.CPhysFunctor

Return functor that would be dispatched for given argument(s); None if no dispatch; ambiguous dispatch throws.

dispMatrix(self: woo.dem.CPhysDispatcher, names: bool = True)dict

Return dictionary with contents of the dispatch matrix.

Contact law

TODO

CData

ObjectCData

digraph CData {
        rankdir=LR;
        margin=.2;
        "CData" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.CData"];
        "IdealElPlData" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.CData"];
        "CData" -> "IdealElPlData" [arrowsize=0.5,style="setlinewidth(0.5)"]            "G3GeomCData" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.CData"];
        "CData" -> "G3GeomCData" [arrowsize=0.5,style="setlinewidth(0.5)"]              "PelletCData" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.CData"];
        "CData" -> "PelletCData" [arrowsize=0.5,style="setlinewidth(0.5)"]
}
class woo.dem.CData(*args, **kwargs)

Optional data stored in the contact by the Law functor.

Overloaded function.

  1. __init__(self: woo.dem.CData) -> None

  2. __init__(self: woo.dem.CData, *args, **kwargs) -> None

G3GeomCData

ObjectCDataG3GeomCData

class woo.dem.G3GeomCData(*args, **kwargs)

Internal variables for use with G3Geom

Overloaded function.

  1. __init__(self: woo.dem.G3GeomCData) -> None

  2. __init__(self: woo.dem.G3GeomCData, *args, **kwargs) -> None

shearForce(= Vector3(0, 0, 0))

Shear force in global coordinates

[type: Vector3r]

PelletCData

ObjectCDataPelletCData

class woo.dem.PelletCData(*args, **kwargs)

Hold state variables for pellet contact.

Overloaded function.

  1. __init__(self: woo.dem.PelletCData) -> None

  2. __init__(self: woo.dem.PelletCData, *args, **kwargs) -> None

uNPl(= 0.0)

Plastic displacement on the contact.

[type: Real]

uN0(= 0.0)

Initial distance (defines equilibrium).

[type: Real]

IdealElPlData

ObjectCDataIdealElPlData

class woo.dem.IdealElPlData(*args, **kwargs)

Hold (optional) state variables for ideally elasto-plastic contacts.

Overloaded function.

  1. __init__(self: woo.dem.IdealElPlData) -> None

  2. __init__(self: woo.dem.IdealElPlData, *args, **kwargs) -> None

uN0(= 0.0)

Reference (equilibrium) value for uN (normal displacement).

[type: Real]

LawFunctor

ObjectFunctorLawFunctor

digraph LawFunctor {
        rankdir=LR;
        margin=.2;
        "LawFunctor" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.LawFunctor"];
        "Law2_L6Geom_LudingPhys" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.LawFunctor"];
        "LawFunctor" -> "Law2_L6Geom_LudingPhys" [arrowsize=0.5,style="setlinewidth(0.5)"]              "Law2_L6Geom_ConcretePhys" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.LawFunctor"];
        "LawFunctor" -> "Law2_L6Geom_ConcretePhys" [arrowsize=0.5,style="setlinewidth(0.5)"]            "Law2_L6Geom_IcePhys" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.LawFunctor"];
        "LawFunctor" -> "Law2_L6Geom_IcePhys" [arrowsize=0.5,style="setlinewidth(0.5)"]         "Law2_L6Geom_PelletPhys_Pellet" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.LawFunctor"];
        "LawFunctor" -> "Law2_L6Geom_PelletPhys_Pellet" [arrowsize=0.5,style="setlinewidth(0.5)"]               "Law2_L6Geom_HertzPhys_DMT" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.LawFunctor"];
        "LawFunctor" -> "Law2_L6Geom_HertzPhys_DMT" [arrowsize=0.5,style="setlinewidth(0.5)"]           "Law2_G3Geom_FrictPhys_IdealElPl" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.LawFunctor"];
        "LawFunctor" -> "Law2_G3Geom_FrictPhys_IdealElPl" [arrowsize=0.5,style="setlinewidth(0.5)"]             "Law2_L6Geom_FrictPhys_IdealElPl" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.LawFunctor"];
        "LawFunctor" -> "Law2_L6Geom_FrictPhys_IdealElPl" [arrowsize=0.5,style="setlinewidth(0.5)"]             "Law2_L6Geom_FrictPhys_LinEl6" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.LawFunctor"];
        "LawFunctor" -> "Law2_L6Geom_FrictPhys_LinEl6" [arrowsize=0.5,style="setlinewidth(0.5)"]
}
class woo.dem.LawFunctor(*args, **kwargs)

Functor for applying constitutive laws on contact.

Overloaded function.

  1. __init__(self: woo.dem.LawFunctor) -> None

  2. __init__(self: woo.dem.LawFunctor, *args, **kwargs) -> None

Law2_L6Geom_IcePhys

ObjectFunctorLawFunctorLaw2_L6Geom_IcePhys

class woo.dem.Law2_L6Geom_IcePhys(*args, **kwargs)

Contact law implementing ice-contact-model.

Overloaded function.

  1. __init__(self: woo.dem.Law2_L6Geom_IcePhys) -> None

  2. __init__(self: woo.dem.Law2_L6Geom_IcePhys, *args, **kwargs) -> None

iniEqlb(= True)

Set the intial distance as equilibrium distance (saved in IcePhys.uN0, subtracted from L6Geom.uN); enabling during simulation will only affect newly created contacts).

[type: bool]

elastIx(= -1)

Index of elastic energy (cache).

[type: int, read-only in python]

brokenIx(= -1)

Index of energy which disappeared when contacts broke (cache).

[type: int, read-only in python]

plastIx(= -1)

Index of plastically dissipated energy (cache).

[type: int, read-only in python]

Law2_L6Geom_ConcretePhys

ObjectFunctorLawFunctorLaw2_L6Geom_ConcretePhys

class woo.dem.Law2_L6Geom_ConcretePhys(*args, **kwargs)

Constitutive law for concrete.

Overloaded function.

  1. __init__(self: woo.dem.Law2_L6Geom_ConcretePhys) -> None

  2. __init__(self: woo.dem.Law2_L6Geom_ConcretePhys, *args, **kwargs) -> None

yieldSurfType(= 3)

yield function: 0: mohr-coulomb (original); 1: parabolic; 2: logarithmic, 3: log+lin_tension, 4: elliptic, 5: elliptic+log

[type: int, named enum, possible values are: ‘linear’ (‘lin’, ‘MC’, ‘mc’, ‘Mohr-Coulomb’; 0), ‘para’ (‘parabolic’; 1), ‘log’ (‘logarithmic’; 2), ‘log+lin’ (‘logarithmic, linear tension’, ‘loglin’; 3), ‘elliptic’ (‘ell’; 4), ‘elliptic+logarithmic’ (‘ell+log’; 5)]

yieldLogSpeed(= 0.1)

scaling in the logarithmic yield surface (should be <1 for realistic results; >=0 for meaningful results)

[type: Real]

yieldEllipseShift(= nan)

horizontal scaling of the ellipse (shifts on the +x axis as interactions with +y are given)

[type: Real]

omegaThreshold(= 1.0)

damage after which the contact disappears (<1), since omega reaches 1 only for strain →+∞

[type: Real]

epsSoft(= -0.003)

Strain at which softening in compression starts (non-negative to deactivate)

[type: Real]

relKnSoft(= 0.3)

Relative rigidity of the softening branch in compression (0=perfect elastic-plastic, <0 softening, >0 hardening)

[type: Real]

elastPotIx(= -1)

Index for elastic potential energy

[type: int, not saved, not accessible from python]

yieldSigmaTNorm(self: woo.dem.Law2_L6Geom_ConcretePhys, sigmaN: float, omega: float, coh0: float, tanPhi: float)float

Return radius of yield surface for given material and state parameters; uses attributes of the current instance (yieldSurfType etc), change them before calling if you need that.

Law2_L6Geom_FrictPhys_LinEl6

ObjectFunctorLawFunctorLaw2_L6Geom_FrictPhys_LinEl6

class woo.dem.Law2_L6Geom_FrictPhys_LinEl6(*args, **kwargs)

Ideally elastic-plastic behavior.

Overloaded function.

  1. __init__(self: woo.dem.Law2_L6Geom_FrictPhys_LinEl6) -> None

  2. __init__(self: woo.dem.Law2_L6Geom_FrictPhys_LinEl6, *args, **kwargs) -> None

charLen(= -1.0)

Characteristic length, which is equal to stiffnesses ratio kNormal/kTwist and kShear/kBend. Must be non-negative.

[type: Real, unit: m]

elastPotIx(= -1)

Index for elastic potential energy

[type: int, not saved, not accessible from python]

Law2_L6Geom_HertzPhys_DMT

ObjectFunctorLawFunctorLaw2_L6Geom_HertzPhys_DMT

class woo.dem.Law2_L6Geom_HertzPhys_DMT(*args, **kwargs)

Law for Hertz contact with optional adhesion (DMT (Derjaguin-Muller-Toporov) [DMT75]), non-linear viscosity ([AE11]) The formulation is taken mainly from [Joh87]. The parameters are given through Cp2_FrictMat_HertzPhys. More details are given in hertzian_contact_models.

Overloaded function.

  1. __init__(self: woo.dem.Law2_L6Geom_HertzPhys_DMT) -> None

  2. __init__(self: woo.dem.Law2_L6Geom_HertzPhys_DMT, *args, **kwargs) -> None

noAttraction(= True)

Avoid non-physical normal attraction which may result from viscous effects by making the normal force zero if there is attraction (\(F_n>0\)). This condition is only applied to elastic and viscous part of the normal force. Adhesion, if present, is not limited. See [AE11], the ‘Model choice’ section (pg. 5), for discussion of this effect. .. note:: It is technically not possible to break the contact completely while there is still geometrical overlap, so only force is set to zero but the contact still exists.

[type: bool]

nCallsIters

Count number of calls of the functor and of iterations in the Halley solver (if used).

[type: OpenMPArrayAccumulator<int>, not shown in the UI, not dumped]

avgIter(= nan)

Average number of Halley iterations per contact when using the Schwarz model (updated on-demand).

[type: Real, read-only in python]

digits(= 26)

Precision for Halley iteration with the Schwarz model, measured in binary digits; the maximum is the number of digits of the floating point type for given platform. Precision above 2/3 of the maximum will very likely have no effect on the result, but it will require extra (few) iterations before converging.

[type: int, range: 1−53]

plastIx(= -1)

Index of plastically dissipated energy.

[type: int, not saved, not accessible from python]

viscNIx(= -1)

Index of viscous dissipation in the normal sense.

[type: int, not saved, not accessible from python]

viscTIx(= -1)

Index of viscous dissipation in the tangent sense.

[type: int, not saved, not accessible from python]

elastPotIx(= -1)

Index for elastic potential energy.

[type: int, not saved, not accessible from python]

dmtIx(= -1)

Index for elastic energy of new/broken contacts.

[type: int, not saved, not accessible from python]

resetCounters(self: woo.dem.Law2_L6Geom_HertzPhys_DMT)None

Reset nCallsIters and thus avgIter.

Law2_L6Geom_PelletPhys_Pellet

ObjectFunctorLawFunctorLaw2_L6Geom_PelletPhys_Pellet

class woo.dem.Law2_L6Geom_PelletPhys_Pellet(*args, **kwargs)

Contact law with friction and plasticity in compression, designed for pellet behavior. See pellet-contact-model for details.

Overloaded function.

  1. __init__(self: woo.dem.Law2_L6Geom_PelletPhys_Pellet) -> None

  2. __init__(self: woo.dem.Law2_L6Geom_PelletPhys_Pellet, *args, **kwargs) -> None

thinRate(= 0.0)

The amount of reducing particle radius (\(\theta_t\)), relative to plastic deformation increment (non-positive to disable thinning)

[type: Real]

thinRelRMin(= 0.7)

Minimum radius reachable with sphere thinning at plastic deformation, relative to initial particle size (\(r_{\min}^{\mathrm{rel}}\))

[type: Real]

thinExp(= -1.0)

Exponent for reducing the rate of thinning as the minimum radius is being approached (\(\gamma_t\))

[type: Real]

thinRefRad(= 0.0)

Reference radius for thinning; if positive, thinRateExp and thinMinExp are in effect.

[type: Real, unit: m]

thinMinExp(= 0.0)

Multiply minimum radius \(r_0\) by \(\left(\frac{r}{r_{\rm thinRefRad}}\right)^{\rm thinMinExp}\) (size-dependent minimum radius).

[type: Real]

thinRateExp(= 0.0)

Multiply thinning rate \(\theta_t\) (thinRate) by \(\left(\frac{r}{r_{\rm thinRefRad}}\right)^{\rm thinRateExp}\) (size-dependent minimum radius).

[type: Real]

confSigma(= 0.0)

Confinement stress (acting on contact area). Negative values will make particles stick together. The strain-stress diagram is shifted vertically with this parameter. The value of confinement can be further scaled with confRefRad.

Note

Energy computation might be incorrect with confinement (not yet checked).

[type: Real]

confRefRad(= 0.0)

If positive, scale the confining stress (confSigma) using the value of \(\left(\frac{A}{\pi r_{\rm ref}^2}\right)^{\beta_c}\); this allows to introduce confinement which varies depending on particle size.

[type: Real, unit: m]

confExp(= 1.0)

Dimensionless exponent to be used in conjunction with confRefRad.

[type: Real]

iniEqlb(= False)

Use the initial distance as equilibrium.

[type: bool]

plastSplit(= False)

Track energy dissipated in normal and tangential sliding separately

[type: bool]

plastIx(= -1)

Index of plastically dissipated energy

[type: int, not saved, not accessible from python]

normPlastIx(= -1)

Index of plastically dissipated energy in the normal sense

[type: int, not saved, not accessible from python]

elastPotIx(= -1)

Index for elastic potential energy

[type: int, not saved, not accessible from python]

static adhesionForce(uN: float, uNPl: float, ka: float)float

Adhesion force function $h$ evaluated with given parameters

static yieldForce(uN: float, d0: float, kn: float, alpha: float)float

Return yield force for alpha and given parameters.

static yieldForceDerivative(uN: float, d0: float, kn: float, alpha: float)float

Return yield force derivative for given parameters.

Law2_G3Geom_FrictPhys_IdealElPl

ObjectFunctorLawFunctorLaw2_G3Geom_FrictPhys_IdealElPl

class woo.dem.Law2_G3Geom_FrictPhys_IdealElPl(*args, **kwargs)

Ideally elastic-plastic behavior, for use with G3Geom.

Overloaded function.

  1. __init__(self: woo.dem.Law2_G3Geom_FrictPhys_IdealElPl) -> None

  2. __init__(self: woo.dem.Law2_G3Geom_FrictPhys_IdealElPl, *args, **kwargs) -> None

noSlip(= False)

Disable plastic slipping

[type: bool]

noBreak(= False)

Disable removal of contacts when in tension.

[type: bool]

plastDissipIx(= -1)

Index of plastically dissipated energy

[type: int, not saved, not accessible from python]

elastPotIx(= -1)

Index for elastic potential energy

[type: int, not saved, not accessible from python]

watch(= Vector2i(-1, -1))

Print debug information for this couple of IDs

[type: Vector2i]

Law2_L6Geom_FrictPhys_IdealElPl

ObjectFunctorLawFunctorLaw2_L6Geom_FrictPhys_IdealElPl

class woo.dem.Law2_L6Geom_FrictPhys_IdealElPl(*args, **kwargs)

Ideally elastic-plastic behavior.

Overloaded function.

  1. __init__(self: woo.dem.Law2_L6Geom_FrictPhys_IdealElPl) -> None

  2. __init__(self: woo.dem.Law2_L6Geom_FrictPhys_IdealElPl, *args, **kwargs) -> None

iniEqlb(= False)

Consider the intial distance as equilibrium distance (saved in contact data, subtracted from L6Geom.uN); enabling during simulation will only affect newly created contacts; disabling will affect all contacts.

[type: bool]

relRollStiff(= 0.0)

Rolling stiffness relative to FrictPhys.kn × charLen (with w``charLen`` being the sum of L6Geom.lens). If non-positive, there is no rolling/twisting resistance.

[type: Real]

relTwistStiff(= 0.0)

Twisting stiffness relative to rolling stiffness (see relRollStiff).

[type: Real]

rollTanPhi(= 0.0)

Rolling friction angle – the rolling force will not exceed Fn × rollTanPhi. This value is applied separately to twisting as well. If non-positive, there is no rolling/twisting resistance.

[type: Real, range: 0−1.5708]

noSlip(= False)

Disable plastic slipping

[type: bool]

noBreak(= False)

Disable removal of contacts when in tension.

[type: bool]

noFrict(= False)

Turn off friction computation, it will be always zero regardless of material parameters

[type: bool]

plastDissipIx(= -1)

Index of plastically dissipated energy

[type: int, not saved, not accessible from python]

elastPotIx(= -1)

Index for elastic potential energy

[type: int, not saved, not accessible from python]

brokenIx(= -1)

Index for energy lost in broken contacts with non-zero force

[type: int, not saved, not accessible from python]

Law2_L6Geom_LudingPhys

ObjectFunctorLawFunctorLaw2_L6Geom_LudingPhys

class woo.dem.Law2_L6Geom_LudingPhys(*args, **kwargs)

Contact law implementing luding-contact-model.

Overloaded function.

  1. __init__(self: woo.dem.Law2_L6Geom_LudingPhys) -> None

  2. __init__(self: woo.dem.Law2_L6Geom_LudingPhys, *args, **kwargs) -> None

wImmediate(= True)

Increment plastic & viscous work in S.energy in every step rather than commiting the sum when contact dissolves. Note that Particle.matState (if a LudingMatState) is always updated only when the contact dissolves.

[type: bool]

viscIx(= -1)

Index of viscous dissipation.

[type: int, not saved, not accessible from python]

plastIx(= -1)

Index of plastic dissipation.

[type: int, not saved, not accessible from python]

LawDispatcher

ObjectEngineDispatcherLawDispatcher

class woo.dem.LawDispatcher(*args, **kwargs)

Dispatcher calling functors based on received argument type(s).

Overloaded function.

  1. __init__(self: woo.dem.LawDispatcher) -> None

  2. __init__(self: woo.dem.LawDispatcher, *args, **kwargs) -> None

functors(= [])

Functors active in the dispatch mechanism [overridden below].

[type: vector<shared_ptr<LawFunctor>>]

dispFunctor(self: woo.dem.LawDispatcher, arg0: woo.dem.CGeom, arg1: woo.dem.CPhys)woo.dem.LawFunctor

Return functor that would be dispatched for given argument(s); None if no dispatch; ambiguous dispatch throws.

dispMatrix(self: woo.dem.LawDispatcher, names: bool = True)dict

Return dictionary with contents of the dispatch matrix.

Testing contact laws

TODO

LawTester

ObjectEngineLawTester

class woo.dem.LawTester(*args, **kwargs)

Engine for testing contact laws by prescribing various loading scenarios, which are a combination of prescribing force or velocity along given contact-local axes.

Overloaded function.

  1. __init__(self: woo.dem.LawTester) -> None

  2. __init__(self: woo.dem.LawTester, *args, **kwargs) -> None

ids(= Vector2i(5923313, 0))

Ids of particles in contact

[type: Vector2i]

done(= 'tester.dead=True')

Python expression to run once all stages had finished. This is run after LawTesterStage.done of the last stage.

[type: string]

abWeight(= 1.0)

Float, usually ∈〈0,1〉, determining on how are displacements/rotations distributed between particles (0 for A, 1 for B); intermediate values will apply respective part to each of them.

[type: Real]

f(= Vector6(0, 0, 0, 0, 0, 0))

Force on contact, NaN if contact is broken

[type: Vector6r, read-only in python]

k(= Vector6(0, 0, 0, 0, 0, 0))

Tangent contact stiffness, NaN if there is no contact (or the contact model does not define it). Diagonal of the K matrix in df=Kdu.

[type: Vector6r, read-only in python]

smooF(= Vector6(0, 0, 0, 0, 0, 0))

Smoothed value of generalized contact forces.

[type: Vector6r, read-only in python]

u(= Vector6(0, 0, 0, 0, 0, 0))

Cumulative value of contact displacement, NaN if contact is broken

[type: Vector6r, read-only in python]

smooU(= Vector6(0, 0, 0, 0, 0, 0))

Smoothed value of generalized contact displacements.

[type: Vector6r, read-only in python]

v(= Vector6(0, 0, 0, 0, 0, 0))

Relative velocity on contact; NaN if the contact is broken

[type: Vector6r, read-only in python]

smooV(= Vector6(0, 0, 0, 0, 0, 0))

Smoothed value of generalized contact relative velocity.

[type: Vector6r, read-only in python]

fErrRel(= Vector6(inf, inf, inf, inf, inf, inf))

Relative error of contact force (with respect to smoothed value)

[type: Vector6r, read-only in python]

fErrAbs(= Vector6(inf, inf, inf, inf, inf, inf))

Absolute error of contact force (with respect to smoothed value)

[type: Vector6r, read-only in python]

uErrRel(= Vector6(inf, inf, inf, inf, inf, inf))

Relative error of contact displacement (with respect to smoothed value)

[type: Vector6r, read-only in python]

uErrAbs(= Vector6(inf, inf, inf, inf, inf, inf))

Absolute error of contact displacement (with respect to smoothed value)

[type: Vector6r, read-only in python]

vErrRel(= Vector6(inf, inf, inf, inf, inf, inf))

Relative error of contact velocity (with respect to smoothed value)

[type: Vector6r, read-only in python]

vErrAbs(= Vector6(inf, inf, inf, inf, inf, inf))

Absolute error of contact velocity (with respect to smoothed value)

[type: Vector6r, read-only in python]

smoothErr(= -1.0)

Smoothing factor for computing errors; if negative, set to smooth automatically.

[type: Real]

smooth(= 0.0001)

Smoothing factor for computing smoothF

[type: Real]

stage(= 0)

Current stage to be finished

[type: int, read-only in python]

stageT0(= -1.0)

Time at which this stage was entered

[type: Real, read-only in python]

stages(= [])

Stages to be reached during the testing

[type: vector<shared_ptr<LawTesterStage>>]

maxStageSteps(= 100000)

Throw error if stage takes this many steps

[type: int, not shown in the UI]

fuv(self: woo.dem.LawTester)dict

Return python dictionary containing f,u,v,smooF,smooU,smooU; useful for plotting with woo.plot.addData(**tester.fuv())

restart(self: woo.dem.LawTester)None

Reset the tester to initial state; all stages are reset via LawTesterStage.reset, the woo.core.Engine.dead flag is unset.

LawTesterStage

ObjectLawTesterStage

class woo.dem.LawTesterStage(*args, **kwargs)

Stage to be reached by LawTester.

Overloaded function.

  1. __init__(self: woo.dem.LawTesterStage) -> None

  2. __init__(self: woo.dem.LawTesterStage, *args, **kwargs) -> None

values(= Vector6(0, 0, 0, 0, 0, 0))

Prescribed values during this step (DoF-ordering: x,y,z linear, x,y,z angular)

[type: Vector6r]

whats(= Vector6i(0, 0, 0, 0, 0, 0))

Meaning of values components (DoF-odering). The constructor acceps this attribute specified as string of 6 characters, where each of them can be: . for imposing nothing, v for imposing velocity, i for imposing initial velocity only, f for imposing force.

[type: Vector6i]

until(= '')

Stage finishes when until (python expression) evaluates to True. Besides receiving global variables, several local variables are passed: C (contact object; None if contact does not exist), pA (first particle), pB (second particle), scene (current scene object), tester (LawTester object), stage (LawTesterStage object).

[type: string]

untilEvery(= 1)

Test the until expression only every untilEvery steps (this may make the execution faster)

[type: int]

done(= '')

Run this python command when the stage finishes

[type: string]

step(= 0)

Step in this stage

[type: int]

time(= 0.0)

Time in this stage

[type: Real]

hadC(= False)

Flag keeping track of whether there was a contact in this stage at all

[type: bool]

hasC(= False)

Flag keeping track of whether there was a contact in this stage at all

[type: bool]

timeC0(= nan)

Time of creating of the last contact (NaN if there has never been one).

[type: Real]

bounces(= 0)

Number of sign changes of the normal relative velocity in this stage

[type: int]

property broken

Test whether an existing contact broke in this stage; this is useful for saying until='stage.broken' (equivalent to stage.hadC and not stage.hasC). This is different from until='not C', since this condition will be satisfied before any contact exists at all.

property cTime

Time since creation of the last contact (NaN if there has never been one). Useful for testing collision time after the condition until='stage.rebound' has been satisfied. Equivalent to stage.time-stage.timeC0.

property rebound

Test for rebound; rebound is considered complete when sign of relative normal velocity changed more than once (adhesive contacts may never separate once they are created – this catches a single period of the oscillation) or if contact breaks. Equivalent to stage.bounces>=2 or stage.broken.

reset(self: woo.dem.LawTesterStage)None

Reset this stage to its initial stage such that it can be used again as if new. This is called automatically from LawTester.restart.

HalfspaceBuoyancy

ObjectEngineHalfspaceBuoyancy

class woo.dem.HalfspaceBuoyancy(*args, **kwargs)

Apply Buoyancy force for uninodal particles, depending on their position in the \(-z\) half-space in local coordinate system (node). TODO: references to papers, wikipedia with formulas, or write formulas here.

Overloaded function.

  1. __init__(self: woo.dem.HalfspaceBuoyancy) -> None

  2. __init__(self: woo.dem.HalfspaceBuoyancy, *args, **kwargs) -> None

mask(= 5)

Mask for particles Buoyancy is applied to.

[type: uint]

liqRho(= 1000.0)

Density of the medium.

[type: Real]

dragCoef(= 0.47)

Drag coefficient.

[type: Real]

drag(= False)

Flag for turning water drag on or off

[type: bool]

surfPt(= Vector3(0, 0, 0))

Point on liquid surface; the surface is perpendicular to :obj:`woo.dem.DemField.gravity (which must not be zero).

[type: Vector3r]

BoxTraceTimeSetter

ObjectEnginePeriodicEngineBoxTraceTimeSetter

class woo.dem.BoxTraceTimeSetter(*args, **kwargs)

Set TraceVisRep.t0 of nodes inside box to the current time <Scene.time>; this is used for tracking how long has a particle been away from that region.

Overloaded function.

  1. __init__(self: woo.dem.BoxTraceTimeSetter) -> None

  2. __init__(self: woo.dem.BoxTraceTimeSetter, *args, **kwargs) -> None

node(= None)

Optionally define local coordinate system for box.

[type: shared_ptr<Node>]

box(= AlignedBox3((1.7976931348623157e308, 1.7976931348623157e308, 1.7976931348623157e308), (-1.7976931348623157e308, -1.7976931348623157e308, -1.7976931348623157e308)))

Box volume; in local coordinates if node is given, global otherwise.

[type: AlignedBox3r]

glColor(= 0.5)

Color for rendering (NaN disables), mapped using the default colormap.

[type: Real]

MeshVolume

ObjectEnginePeriodicEngineMeshVolume

class woo.dem.MeshVolume(*args, **kwargs)

Compute volume of (possibly deforming) closed triangulated surface; depends on the gts feature.

Overloaded function.

  1. __init__(self: woo.dem.MeshVolume) -> None

  2. __init__(self: woo.dem.MeshVolume, *args, **kwargs) -> None

mask(= 0)

Mask for finding surface triangles

[type: int]

reinit(= False)

If true, recreate internal data from scratch

[type: bool]

nodes(= NodeList[])

List of nodes, in the same order as the GTS surface structure.

[type: vector<shared_ptr<Node>>, not shown in the UI, not saved]

vol(= nan)

Volume as computed when last run

[type: Real]

thickVol(= nan)

Volume of the inner side of the mesh: the mesh is defined by facets' midplanes, but some facets may have non-zero Facet.halfThick. This number is the sum of (initial!) facet area times Facet.halfThick. To get the volume with this part subtracted, use netVol.

[type: Real]

property netVol

Net volume: volume minus thickVol.

Motion integration

TODO

Leapfrog

ObjectEngineLeapfrog

class woo.dem.Leapfrog(*args, **kwargs)

Engine integrating newtonian motion equations, using the leap-frog scheme. See theory-motion-integration for details.

Overloaded function.

  1. __init__(self: woo.dem.Leapfrog) -> None

  2. __init__(self: woo.dem.Leapfrog, *args, **kwargs) -> None

IpLL4h(= Matrix3(0, 0, 0, 0, 0, 0, 0, 0, 0))

\(I+\frac{\nnext{\tens{L}}+\pprev{\tens{L}}}{4}\Dt\)

[type: Matrix3r, not saved, read-only in python]

ImLL4hInv(= Matrix3(0, 0, 0, 0, 0, 0, 0, 0, 0))

\(\left(\tens{I}-\frac{\nnext{\tens{L}}-\pprev{\tens{L}}}{4}\Dt\right)^{-1}\)

[type: Matrix3r, not saved, read-only in python]

LmL(= Matrix3(0, 0, 0, 0, 0, 0, 0, 0, 0))

\(\nnext{\tens{L}}-\pprev{\tens{L}}\)

[type: Matrix3r, not saved, read-only in python]

deltaSpinVec(= Vector3(0, 0, 0))

\(-\frac{1}{2}\epsilon_{ijk}\frac{\pprev{\tens{L}}-{\pprev{\tens{L}}}^T}{2}+\frac{1}{2}\epsilon_{ijk}\frac{\nnext{\tens{L}}-{\nnext{\tens{L}}}^T}{2}\).

[type: Vector3r, not saved, read-only in python]

damping(= 0.2)

damping coefficient for non-viscous damping

[type: Real]

reset(= False)

Reset forces immediately after applying them.

[type: bool]

_forceResetChecked(= False)

Whether we already issued a warning for forces being (probably) not reset

[type: bool, not shown in the UI]

maxVelocitySq(= nan)

store square of max. velocity, for informative purposes; computed again at every step.

[type: Real, read-only in python]

dontCollect(= False)

Don’t attempt to collect DEM nodes when there are none in the first step.

[type: bool, not shown in the UI]

kinSplit(= False)

Whether to separately track translational and rotational kinetic energy.

[type: bool]

nonviscDampIx(= -1)

Index of the energy dissipated using the non-viscous damping (damping).

[type: int, not saved, not accessible from python]

gravWorkIx(= -1)

Index for gravity work

[type: int, not saved, not accessible from python]

kinEnergyIx(= -1)

Index for kinetic energy in scene->energies.

[type: int, not saved, not accessible from python]

kinEnergyTransIx(= -1)

Index for translational kinetic energy in scene->energies.

[type: int, not saved, not accessible from python]

kinEnergyRotIx(= -1)

Index for rotational kinetic energy in scene->energies.

[type: int, not saved, not accessible from python]

ForceResetter

ObjectEngineForceResetter

class woo.dem.ForceResetter(*args, **kwargs)

Reset forces on nodes in DEM field.

Overloaded function.

  1. __init__(self: woo.dem.ForceResetter) -> None

  2. __init__(self: woo.dem.ForceResetter, *args, **kwargs) -> None

DynDt

ObjectEnginePeriodicEngineDynDt

class woo.dem.DynDt(*args, **kwargs)

Adjusts Scene.dt based on current stiffness of particle contacts.

Overloaded function.

  1. __init__(self: woo.dem.DynDt) -> None

  2. __init__(self: woo.dem.DynDt, *args, **kwargs) -> None

maxRelInc(= 0.0001)

Maximum relative increment of timestep within one step, to void abrupt changes in timestep leading to numerical artefacts.

[type: Real]

dryRun(= False)

Only set dt to the value of timestep, don’t apply it really.

[type: bool]

dt(= nan)

New timestep value which would be used if dryRun were not set. Unused when dryRun is false.

[type: Real]

nodalCritDtSq(self: woo.dem.DynDt, node: woo.core.Node)float

DemData

ObjectNodeDataDemData

digraph DemData {
        rankdir=LR;
        margin=.2;
        "DemData" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.DemData"];
        "ClumpData" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.DemData"];
        "DemData" -> "ClumpData" [arrowsize=0.5,style="setlinewidth(0.5)"]              "DemDataTagged" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.DemData"];
        "DemData" -> "DemDataTagged" [arrowsize=0.5,style="setlinewidth(0.5)"]
}
class woo.dem.DemData(*args, **kwargs)

Dynamic state of node.

Overloaded function.

  1. __init__(self: woo.dem.DemData) -> None

  2. __init__(self: woo.dem.DemData, *args, **kwargs) -> None

vel(= Vector3(0, 0, 0))

Linear velocity.

[type: Vector3r, unit: m/s]

angVel(= Vector3(0, 0, 0))

Angular velocity; when set, angMom is reset (and updated from angVel in Leapfrog)..

[type: Vector3r, unit: rad/s]

mass(= 0.0)

Associated mass.

[type: Real, unit: kg]

inertia(= Vector3(0, 0, 0))

Inertia along local (principal) axes

[type: Vector3r, unit: kg·m²]

force(= Vector3(0, 0, 0))

Applied force

[type: Vector3r, unit: N]

torque(= Vector3(0, 0, 0))

Applied torque

[type: Vector3r, unit: N·m]

angMom(= Vector3(nan, nan, nan))

Angular momentum; used with the aspherical integrator. If NaN and aspherical integrator (Leapfrog) is used, the value is initialized to inertia × angVel.

[type: Vector3r, unit: N·m·s]

flags(= 0)

Bit flags storing blocked DOFs, clump status, …

[type: unsigned, read-only in python, bit accessors: blockX, blockY, blockZ, blockRotX, blockRotY, blockRotZ, clumped, clump, energySkip, gravitySkip, tracerSkip, dampingSkip]

linIx(= -1)

Index within DemField.nodes (for efficient removal)

[type: long, not shown in the UI, read-only in python]

parRef(= [])

Back-reference for particles using this node; this is important for knowing when a node may be deleted (no particles referenced) and such. Should be kept consistent.

[type: std::list<Particle*>, not shown in the UI, not saved, not accessible from python]

impose(= None)

Impose arbitrary velocity, angular velocity, … on the node; the functor is called from Leapfrog, after new position and velocity have been computed.

[type: shared_ptr<Impose>]

master

Master node; currently only used with clumps (since this is never set from python, it is safe to use weak_ptr).

[type: weak_ptr<Node>, not shown in the UI, not accessible from python]

addParRef(self: woo.dem.DemData, arg0: woo.dem.Particle)None
property blocked

Degress of freedom where linear/angular velocity will be always constant (equal to zero, or to an user-defined value), regardless of applied force/torque. String that may contain ‘xyzXYZ’ (translations and rotations).

guessMoving(self: woo.dem.DemData)bool

Tell whether the node is likely to be moving or not. Returns true if any of the following is true:

This function is used as heuristics by S.dem.par.add when called with nodes=-1 (default), to decide whether the particle’s nodes should be added to S.dem.nodes.

property isAspherical

Return True when inertia components are not equal.

static setOriMassInertia(arg0: woo.core.Node)None

Lump mass and inertia from all attached particles and attempt to rotate the node so that its axes are principal axes of inertia, if allowed by particles shape (without chaning the geometry).

property useAsphericalLeapfrog

Say whether the node will use aspherical leapfrog integration routine. The criterion is that the node is aspherical and does not have all rotations blocked.

ClumpData

ObjectNodeDataDemDataClumpData

class woo.dem.ClumpData(*args, **kwargs)

Data of a DEM particle which binds multiple particles together.

Overloaded function.

  1. __init__(self: woo.dem.ClumpData) -> None

  2. __init__(self: woo.dem.ClumpData, *args, **kwargs) -> None

nodes(= NodeList[])

Member nodes

[type: vector<shared_ptr<Node>>, not shown in the UI, read-only in python]

relPos(= [])

Relative member’s positions

[type: vector<Vector3r>, read-only in python]

relOri(= [])

Relative member’s orientations

[type: vector<Quaternionr>, read-only in python]

equivRad(= nan)

Equivalent radius, for PSD statistics (e.g. in BoxOutlet).

[type: Real]

static applyToMembers(arg0: woo.core.Node)None

Move/rotate member nodes; this is only useful after setting clump’s node position/orientation by hand, so that memebrs are updated without running Leapfrog.

static forceTorqueFromMembers(arg0: woo.core.Node)tuple

Return the tuple (F,T), summary force and torque values collected from clump members, as acting on the clump node passed as argument.

DemDataTagged

ObjectNodeDataDemDataDemDataTagged

class woo.dem.DemDataTagged(*args, **kwargs)

Add integer tag to each node, used with ForcesToHdf5 so that nodes can be numbered differently than in Woo.

Overloaded function.

  1. __init__(self: woo.dem.DemDataTagged) -> None

  2. __init__(self: woo.dem.DemDataTagged, *args, **kwargs) -> None

tag(= -1)

External identifier of th node (unused by Woo itself).

[type: int]

Impose

ObjectImpose

digraph Impose {
        rankdir=LR;
        margin=.2;
        "Impose" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.Impose"];
        "HarmonicOscillation" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.Impose"];
        "Impose" -> "HarmonicOscillation" [arrowsize=0.5,style="setlinewidth(0.5)"]             "InterpolatedMotion" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.Impose"];
        "Impose" -> "InterpolatedMotion" [arrowsize=0.5,style="setlinewidth(0.5)"]              "VelocityAndReadForce" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.Impose"];
        "Impose" -> "VelocityAndReadForce" [arrowsize=0.5,style="setlinewidth(0.5)"]            "AlignedHarmonicOscillations" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.Impose"];
        "Impose" -> "AlignedHarmonicOscillations" [arrowsize=0.5,style="setlinewidth(0.5)"]             "CombinedImpose" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.Impose"];
        "Impose" -> "CombinedImpose" [arrowsize=0.5,style="setlinewidth(0.5)"]          "VariableVelocity3d" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.Impose"];
        "Impose" -> "VariableVelocity3d" [arrowsize=0.5,style="setlinewidth(0.5)"]              "ReadForce" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.Impose"];
        "Impose" -> "ReadForce" [arrowsize=0.5,style="setlinewidth(0.5)"]               "ConstantForce" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.Impose"];
        "Impose" -> "ConstantForce" [arrowsize=0.5,style="setlinewidth(0.5)"]           "RadialForce" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.Impose"];
        "Impose" -> "RadialForce" [arrowsize=0.5,style="setlinewidth(0.5)"]             "StableCircularOrbit" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.Impose"];
        "CircularOrbit" -> "StableCircularOrbit" [arrowsize=0.5,style="setlinewidth(0.5)"]              "Local6Dofs" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.Impose"];
        "Impose" -> "Local6Dofs" [arrowsize=0.5,style="setlinewidth(0.5)"]              "CircularOrbit" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.Impose"];
        "Impose" -> "CircularOrbit" [arrowsize=0.5,style="setlinewidth(0.5)"]           "VariableAlignedRotation" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.Impose"];
        "Impose" -> "VariableAlignedRotation" [arrowsize=0.5,style="setlinewidth(0.5)"]
}
class woo.dem.Impose(*args, **kwargs)

Impose arbitrary changes in Node and DemData, at certain hook points during motion integration. Velocity is imposed after motion integration (and again after computing acceleration from forces, to make sure forces don’t alter what is prescribed), force is imposed when forces from the previous step are being reset (thus additional force may be applied on the node as usual); readForce is a special imposition before resetting force, which is meant to look at summary force applied onto node(s).

Overloaded function.

  1. __init__(self: woo.dem.Impose) -> None

  2. __init__(self: woo.dem.Impose, *args, **kwargs) -> None

what(= 0)

What values are to be imposed; this is set by the derived engine automatically depending on what is to be prescribed.

[type: int, bit accessors: vel, force, iniVel, readForce]

stepLast(= -1)

Step in which this imposition was last used; updated atomically by callers from c++ by calling isFirstStepRun.

[type: long, read-only in python]

timeLast(= nan)

Time in which this imposition was last used; updated automatically bu callers from c++ via isFirstStepRun, just like stepLast.

[type: Real, read-only in python]

__add__(self: woo.dem.Impose, arg0: woo.dem.Impose)woo.dem.Impose

Return combined imposition, a new instance of CombinedImpose.

CircularOrbit

ObjectImposeCircularOrbit

digraph CircularOrbit {
        rankdir=LR;
        margin=.2;
        "CircularOrbit" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.CircularOrbit"];
        "StableCircularOrbit" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.CircularOrbit"];
        "CircularOrbit" -> "StableCircularOrbit" [arrowsize=0.5,style="setlinewidth(0.5)"]
}
class woo.dem.CircularOrbit(*args, **kwargs)

Imposes circular orbiting around the local z-axis; the velocity is prescribed using approximated midstep position in an incremental manner. This can lead to unstabilities (such as changing radius) when used over millions of steps, but does not require radius to be given explicitly (see also StableCircularOrbit). Angular velocity is touched only when rotate is set.

Overloaded function.

  1. __init__(self: woo.dem.CircularOrbit) -> None

  2. __init__(self: woo.dem.CircularOrbit, *args, **kwargs) -> None

node(= <Node @ 0x17c3330, at (0, 0, 0)>)

Local coordinate system.

[type: shared_ptr<Node>]

rotate(= False)

Impose rotational velocity so that orientation relative to the local z-axis is always the same. If false, angular velocity is left as-is.

[type: bool]

omega(= nan)

Orbiting angular velocity.

[type: Real]

angle(= 0.0)

Cumulative angle turned, incremented at every step.

[type: Real]

StableCircularOrbit

ObjectImposeCircularOrbitStableCircularOrbit

class woo.dem.StableCircularOrbit(*args, **kwargs)

Impose circular orbiting around local z-axis, enforcing constant radius of orbiting. The note about rotate applies to this imposition.

Overloaded function.

  1. __init__(self: woo.dem.StableCircularOrbit) -> None

  2. __init__(self: woo.dem.StableCircularOrbit, *args, **kwargs) -> None

radius(= nan)

Radius, i.e. enforced distance from the rotation axis.

[type: Real]

VariableVelocity3d

ObjectImposeVariableVelocity3d

class woo.dem.VariableVelocity3d(*args, **kwargs)

Impose velocity in 3 independent senses, interpolated from piecewise-linear velocity function values, optional periodic in time; NaN values of velocity will impose nothing in that direction.

Overloaded function.

  1. __init__(self: woo.dem.VariableVelocity3d) -> None

  2. __init__(self: woo.dem.VariableVelocity3d, *args, **kwargs) -> None

times(= [])

Time values for vels.

[type: vector<Real>]

vels(= [])

Components of velocity, in local coordinates defined by ori.

[type: vector<Vector3r>]

angVels(= [])

Components of angular velocity, in local coordinates defined by ori. If empty, angular velocity will not be imposed at all.

Note

Only nodes which are using spherical integration can be prescribed angular velocity, since the aspherical integrator in woo.dem.Leapfrog uses angular momentum rather than angular velocity as input. This can be queried with Node.dem.useAsphericalLeapfrog.

[type: vector<Vector3r>]

ori(= Quaternion((1, 0, 0), 0))

Orientation of coordinate axes (by default, impose velocity along global axes)

[type: Quaternionr]

hooks(= [])

Python hooks to be run when time points are reached (max Δt later than times items). Must be same length than times, or shorter; use empty string for not doing anything at that time point.

[type: vector<string>]

diff(= False)

Prescribed velocity can be applied as total velocity value (with diff==False) or as difference added to the actual nodal velocity (with diff==True).

[type: bool]

wrap(= False)

Wrap time around the last time value (float modulo), if greater.

[type: bool]

t0(= 0.0)

Time offset which is subtracted from t (before wrapping, if wrap is used).

[type: Real]

AlignedHarmonicOscillations

ObjectImposeAlignedHarmonicOscillations

class woo.dem.AlignedHarmonicOscillations(*args, **kwargs)

Imposes three independent harmonic oscillations along global coordinate system axes.

Overloaded function.

  1. __init__(self: woo.dem.AlignedHarmonicOscillations) -> None

  2. __init__(self: woo.dem.AlignedHarmonicOscillations, *args, **kwargs) -> None

freqs(= Vector3(nan, nan, nan))

Frequencies for individual axes. NaN value switches that axis off, the component will not be touched

[type: Vector3r]

amps(= Vector3(0, 0, 0))

Amplitudes along individual axes.

[type: Vector3r]

InterpolatedMotion

ObjectImposeInterpolatedMotion

class woo.dem.InterpolatedMotion(*args, **kwargs)

Impose linear and angular velocity such that given positions and orientations are reached in at given time-points.

Overloaded function.

  1. __init__(self: woo.dem.InterpolatedMotion) -> None

  2. __init__(self: woo.dem.InterpolatedMotion, *args, **kwargs) -> None

poss(= [])

Positions which will be interpolated between.

[type: vector<Vector3r>]

oris(= [])

Orientations which will be interpolated between.

[type: vector<Quaternionr>]

times(= [])

Times at which given positions and orientations should be reached.

[type: vector<Real>]

t0(= 0.0)

Time offset to add to all time points.

[type: Real]

HarmonicOscillation

ObjectImposeHarmonicOscillation

class woo.dem.HarmonicOscillation(*args, **kwargs)

Impose harmonic oscillation around initial center position, with given frequency freq (\(f\)) and amplitude amp (\(A\)), by prescribing velocity. Nodal velocity magnitude along dir is \(x'(t)=A\omega\cos(\omega(t-t_0))\) (with \(\omega=2\pi f\)), which is the derivative of the harmonic motion equation \(x(t)=A\sin(\omega(t-t_0))\). The motion starts in zero (for \(t_0=0\)); to reverse the direction, either reverse dir or assign \(t_0=\frac{1}{2f}=\frac{\pi}{\omega}\).

Overloaded function.

  1. __init__(self: woo.dem.HarmonicOscillation) -> None

  2. __init__(self: woo.dem.HarmonicOscillation, *args, **kwargs) -> None

freq(= nan)

Frequence of oscillation

[type: Real]

amp(= nan)

Amplitude of oscillation

[type: Real]

dir(= Vector3(1, 0, 0))

Direcrtion of oscillation (normalized automatically)

[type: Vector3r]

t0(= 0.0)

Time when the oscillator is in the center position (phase)

[type: Real]

perpFree(= False)

If true, only velocity in the dir sense will be prescribed, velocity in the perpendicular sense will be preserved.

[type: bool]

CombinedImpose

ObjectImposeCombinedImpose

class woo.dem.CombinedImpose(*args, **kwargs)

Combine several impositions and apply them one after another.

Overloaded function.

  1. __init__(self: woo.dem.CombinedImpose) -> None

  2. __init__(self: woo.dem.CombinedImpose, *args, **kwargs) -> None

imps(= [])

Impositions which are combined together, always called in this order.

[type: vector<shared_ptr<Impose>>]

RadialForce

ObjectImposeRadialForce

class woo.dem.RadialForce(*args, **kwargs)

Impose constant force towards an axis in 3d.

Overloaded function.

  1. __init__(self: woo.dem.RadialForce) -> None

  2. __init__(self: woo.dem.RadialForce, *args, **kwargs) -> None

nodeA(= None)

First node defining the axis

[type: shared_ptr<Node>]

nodeB(= None)

Second node defining the axis

[type: shared_ptr<Node>]

F(= 0.0)

Magnitude of the force applied. Positive value means away from the axis given by nodeA and nodeB.

[type: Real]

VariableAlignedRotation

ObjectImposeVariableAlignedRotation

class woo.dem.VariableAlignedRotation(*args, **kwargs)

Impose piecewise-linear angular velocity along axis, based on the timeAngVel.

Overloaded function.

  1. __init__(self: woo.dem.VariableAlignedRotation) -> None

  2. __init__(self: woo.dem.VariableAlignedRotation, *args, **kwargs) -> None

axis(= 0)

Rotation axis.

[type: int]

timeAngVel(= [])

Angular velocity values in time. Time values must be increasing.

[type: vector<Vector2r>]

wrap(= False)

Wrap time around the last time value (float modulo), if greater.

[type: bool]

ReadForce

ObjectImposeReadForce

class woo.dem.ReadForce(*args, **kwargs)

Sum forces and torques acting on all nodes with this imposition; this imposition does not change the behavior of particles in any way.

Overloaded function.

  1. __init__(self: woo.dem.ReadForce) -> None

  2. __init__(self: woo.dem.ReadForce, *args, **kwargs) -> None

node(= None)

Reference CS for forces and torque (they are recomputed as if acting on this point); if not given, everything is summed in global CS.

[type: shared_ptr<Node>]

F

Summary force

[type: OpenMPAccumulator<Vector3r>, not saved, read-only in python]

T

Summary torque

[type: OpenMPAccumulator<Vector3r>, not saved, read-only in python]

ConstantForce

ObjectImposeConstantForce

class woo.dem.ConstantForce(*args, **kwargs)

Impose constant force, which is added to other acting forces.

Overloaded function.

  1. __init__(self: woo.dem.ConstantForce) -> None

  2. __init__(self: woo.dem.ConstantForce, *args, **kwargs) -> None

F(= Vector3(0, 0, 0))

Applied force (in global coordinates)

[type: Vector3r]

Local6Dofs

ObjectImposeLocal6Dofs

class woo.dem.Local6Dofs(*args, **kwargs)

Impose force or velocity along all local 6 axes given by the trsf matrix.

Overloaded function.

  1. __init__(self: woo.dem.Local6Dofs) -> None

  2. __init__(self: woo.dem.Local6Dofs, *args, **kwargs) -> None

ori(= Quaternion((1, 0, 0), 0))

Local coordinates rotation

[type: Quaternionr]

values(= Vector6(0, 0, 0, 0, 0, 0))

Imposed values; their meaning depends on the whats vector

[type: Vector6r]

whats(= Vector6i(0, 0, 0, 0, 0, 0))

Meaning of values components: 0 for nothing imposed (i.e. zero force), 1 for velocity, 2 for force values

[type: Vector6i]

VelocityAndReadForce

ObjectImposeVelocityAndReadForce

class woo.dem.VelocityAndReadForce(*args, **kwargs)

Impose velocity in one direction, and optionally read and sum force on all nodes with this imposition (force is not changed in any way). Velocity lateral to the imposition may be free or zero depending on latBlock.

Overloaded function.

  1. __init__(self: woo.dem.VelocityAndReadForce) -> None

  2. __init__(self: woo.dem.VelocityAndReadForce, *args, **kwargs) -> None

dir(= Vector3(1, 0, 0))

Direction (automatically normalized) for prescribed velocity and force readings.

[type: Vector3r]

vel(= 0.0)

Prescribed velocity magnitude.

[type: Real]

latBlock(= True)

Whether lateral velocity (perpendicular to vel) is set to zero, or left free.

[type: bool]

sumF

Summary force on nodes with this imposition, in the direction of vel.

[type: OpenMPAccumulator<Real>, read-only in python]

invF(= False)

Invert force value (so that it has the meaning of reactin rather than force exerted).

[type: bool]

dist(= 0.0)

Cumulative displacement of this imposition.

[type: Real]

energyName(= '')

If given, and trackEnergy is True, cumulate work done by this imposition under this name

[type: string]

workIx(= -1)

Index for fast access to the energy.

[type: int, not saved, not accessible from python]

Tracer

ObjectEnginePeriodicEngineTracer

class woo.dem.Tracer(*args, **kwargs)

Save trace of node’s movement

Overloaded function.

  1. __init__(self: woo.dem.Tracer) -> None

  2. __init__(self: woo.dem.Tracer, *args, **kwargs) -> None

num(= 50)

Number of positions to save (when creating new glyph)

[type: int]

compress(= 2)

Ratio by which history is compress when all data slots are filled; if 0, cycle and don’t compress.

[type: int]

compSkip(= 2)

Number of leading points to skip during compression; if negative, the value of compress is used.

[type: int]

minDist(= 0.0)

Only add new point when last point is at least minDist away, or no point exists at all.

[type: Real]

scalar(= 0)

Scalars associated with history points (determine line color)

[type: int, named enum, possible values are: ‘none’ (‘-‘, ‘’; 0), ‘time’ (‘t’; 1), ‘trace time’ (‘reltime’; 2), ‘velocity’ (‘vel’, ‘v’; 3), ‘angular velocity’ (‘angVel’, ‘angvel’; 4), ‘signed |accel|’ (5), ‘radius’ (‘rad’, ‘r’; 6), ‘number of contacts’ (‘numCon’, ‘ncon’, ‘numcon’; 7), ‘Shape.color’ (‘color’; 8), ‘kinetic energy’ (‘Ek’; 9), ‘ordinal (+ordinalMod)’ (‘ordinal’, ‘ord’; 10), ‘matState.getScalar’ (‘mat’, ‘material state’; 11)]

vecAxis(= -1)

Scalar to use for vector values.

[type: int, named enum, possible values are: ‘norm’ (-1), ‘x’ (0), ‘y’ (1), ‘z’ (2)]

ordinalMod(= 5)

Modulo value when scalar is scalarOrdinal.

[type: int]

matStateIx(= 0)

Index for getting MatState scalars.

[type: int]

matStateSmooth(= 0.001)

Smoothing coefficient for MatState scalars.

[type: Real]

nextReset(= True)

Reset all traces at the next step (scalar changed)

[type: bool, not accessible from python]

lineColor(= <ScalarRange @ 0x171be60>)

Color range for coloring the trace line

[type: shared_ptr<ScalarRange>, read-only in python]

modulo(= Vector2i(0, 0))

Only add trace to nodes with ordinal number such that (i+modulo[1])%modulo[0]==0.

[type: Vector2i]

rRange(= Vector2(0, 0))

If non-zero, only show traces of spheres of which radius falls into this range. (not applicable to clumps); traces of non-spheres are not shown in this case.

[type: Vector2r]

noneColor(= Vector3(0.3, 0.3, 0.3))

Color for traces without scalars, when scalars are saved (e.g. for non-spheres when radius is saved

[type: Vector3r]

clumps(= True)

Also make traces for clumps (for the central node, not for clumped nodes

[type: bool]

saveTime(= False)

Save time values along with scalars (must be enabled before the trace starts collecting data).

[type: bool]

glSmooth(= False)

Render traced lines with GL_LINE_SMOOTH

[type: bool]

glWidth(= 1)

Width of trace lines in pixels

[type: int, range: 1−10]

resetNodesRep(self: woo.dem.Tracer, setupEmpty: bool = False, includeDead: bool = True)None

Reset woo.core.Node.rep on all woo.dem.DemField.nodes. With setupEmpty, create new instances of TraceVisRep. With includeDead, woo.core.Node.rep on all woo.dem.DemField.deadNodes is also cleared (new are not created, even with setupEmpty).

AxialGravity

ObjectEngineAxialGravity

class woo.dem.AxialGravity(*args, **kwargs)

Apply acceleration (independent of distance) directed towards an axis.

Overloaded function.

  1. __init__(self: woo.dem.AxialGravity) -> None

  2. __init__(self: woo.dem.AxialGravity, *args, **kwargs) -> None

axisPt(= Vector3(0, 0, 0))

Point through which the axis is passing.

[type: Vector3r]

axisDir(= Vector3(1, 0, 0))

direction of the gravity axis (will be normalized automatically)

[type: Vector3r]

accel(= 0.0)

Acceleration magnitude [kgms⁻²]

[type: Real]

ClusterAnalysis

ObjectEnginePeriodicEngineClusterAnalysis

class woo.dem.ClusterAnalysis(*args, **kwargs)

Analyze particle connectivity and assign cluster numbers to them.

Overloaded function.

  1. __init__(self: woo.dem.ClusterAnalysis) -> None

  2. __init__(self: woo.dem.ClusterAnalysis, *args, **kwargs) -> None

box(= AlignedBox3((1.7976931348623157e308, 1.7976931348623157e308, 1.7976931348623157e308), (-1.7976931348623157e308, -1.7976931348623157e308, -1.7976931348623157e308)))

Limit particles considered in the analysis to this box only. If not specified, analyze all particles in the simulation.

[type: AlignedBox3r]

mask(= 0)

Particles to consider in cluster analysis. If 0, consider all particles.

[type: int]

clustMin(= 5)

Minimum number of particles to mark them as clustered.

[type: int]

lastLabels(= [])

Next free labels to be used for respective connectivity level.

[type: vector<int>, read-only in python]

maxConn(= 0)

Maximum connectivity (recursion) for cluster analysis. Only 0 is implemented so far.

[type: int]

replMatState(= 0)

What to do when an existing MatState is attached to a particle but it is not a ClusterMatState.

[type: int, named enum, possible values are: ‘always’ (‘yes’, ‘ok’; 0), ‘never’ (‘no’; 1), ‘error’ (2)]

glColor(= 0.4)

Color for rendering the box (NaN to disable rendering)

[type: Real]

Internal forces

TODO

IntraForce

ObjectEngineDispatcherIntraForce

class woo.dem.IntraForce(*args, **kwargs)

Apply internal forces on integration nodes, by calling appropriate IntraFunctor objects.

Overloaded function.

  1. __init__(self: woo.dem.IntraForce) -> None

  2. __init__(self: woo.dem.IntraForce, *args, **kwargs) -> None

functors(= [])

Functors active in the dispatch mechanism [overridden below].

[type: vector<shared_ptr<IntraFunctor>>]

dispFunctor(self: woo.dem.IntraForce, arg0: woo.dem.Shape, arg1: woo.dem.Material)woo.dem.IntraFunctor

Return functor that would be dispatched for given argument(s); None if no dispatch; ambiguous dispatch throws.

dispMatrix(self: woo.dem.IntraForce, names: bool = True)dict

Return dictionary with contents of the dispatch matrix.

IntraFunctor

ObjectFunctorIntraFunctor

digraph IntraFunctor {
        rankdir=LR;
        margin=.2;
        "IntraFunctor" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.IntraFunctor"];
        "In2_Facet" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.IntraFunctor"];
        "IntraFunctor" -> "In2_Facet" [arrowsize=0.5,style="setlinewidth(0.5)"]         "In2_Wall_ElastMat" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.IntraFunctor"];
        "IntraFunctor" -> "In2_Wall_ElastMat" [arrowsize=0.5,style="setlinewidth(0.5)"]         "woo.fem.In2_Membrane_FrictMat" [shape="box",fontsize=8,style="setlinewidth(0.5),filled",fillcolor=grey,height=0.2,URL="woo.fem.html#woo.fem.IntraFunctor"];
        "woo.fem.In2_Membrane_ElastMat" -> "woo.fem.In2_Membrane_FrictMat" [arrowsize=0.5,style="setlinewidth(0.5)"]            "woo.fem.In2_Membrane_ElastMat" [shape="box",fontsize=8,style="setlinewidth(0.5),filled",fillcolor=grey,height=0.2,URL="woo.fem.html#woo.fem.IntraFunctor"];
        "In2_Facet" -> "woo.fem.In2_Membrane_ElastMat" [arrowsize=0.5,style="setlinewidth(0.5)"]                "woo.fem.In2_Tet4_ElastMat" [shape="box",fontsize=8,style="setlinewidth(0.5),filled",fillcolor=grey,height=0.2,URL="woo.fem.html#woo.fem.IntraFunctor"];
        "IntraFunctor" -> "woo.fem.In2_Tet4_ElastMat" [arrowsize=0.5,style="setlinewidth(0.5)"]         "In2_Sphere_ElastMat" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.IntraFunctor"];
        "IntraFunctor" -> "In2_Sphere_ElastMat" [arrowsize=0.5,style="setlinewidth(0.5)"]               "In2_Truss_ElastMat" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.IntraFunctor"];
        "IntraFunctor" -> "In2_Truss_ElastMat" [arrowsize=0.5,style="setlinewidth(0.5)"]
}
class woo.dem.IntraFunctor(*args, **kwargs)

Functor appying internal forces

Overloaded function.

  1. __init__(self: woo.dem.IntraFunctor) -> None

  2. __init__(self: woo.dem.IntraFunctor, *args, **kwargs) -> None

In2_Sphere_ElastMat

ObjectFunctorIntraFunctorIn2_Sphere_ElastMat

class woo.dem.In2_Sphere_ElastMat(*args, **kwargs)

Apply contact forces on sphere; having one node only, Sphere generates no internal forces as such.

Overloaded function.

  1. __init__(self: woo.dem.In2_Sphere_ElastMat) -> None

  2. __init__(self: woo.dem.In2_Sphere_ElastMat, *args, **kwargs) -> None

alreadyWarned_ContactLoopWithApplyForces(= False)

Keep track of whether the warning on ContactLoop already applying forces was issued.

[type: bool, not shown in the UI]

In2_Wall_ElastMat

ObjectFunctorIntraFunctorIn2_Wall_ElastMat

class woo.dem.In2_Wall_ElastMat(*args, **kwargs)

Apply contact forces on wall. Wall generates no internal forces as such. Torque from applied forces is discarded, as Wall does not rotate.

Overloaded function.

  1. __init__(self: woo.dem.In2_Wall_ElastMat) -> None

  2. __init__(self: woo.dem.In2_Wall_ElastMat, *args, **kwargs) -> None

In2_Truss_ElastMat

ObjectFunctorIntraFunctorIn2_Truss_ElastMat

class woo.dem.In2_Truss_ElastMat(*args, **kwargs)

Compute elastic response of cylinder determined by 2 nodes.

Overloaded function.

  1. __init__(self: woo.dem.In2_Truss_ElastMat) -> None

  2. __init__(self: woo.dem.In2_Truss_ElastMat, *args, **kwargs) -> None

setL0(= True)

Automatically set equilibrium length of truss, when first encountered.

[type: bool]

In2_Facet

ObjectFunctorIntraFunctorIn2_Facet

digraph In2_Facet {
        rankdir=LR;
        margin=.2;
        "In2_Facet" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.In2_Facet"];
        "woo.fem.In2_Membrane_FrictMat" [shape="box",fontsize=8,style="setlinewidth(0.5),filled",fillcolor=grey,height=0.2,URL="woo.fem.html#woo.fem.In2_Facet"];
        "woo.fem.In2_Membrane_ElastMat" -> "woo.fem.In2_Membrane_FrictMat" [arrowsize=0.5,style="setlinewidth(0.5)"]            "woo.fem.In2_Membrane_ElastMat" [shape="box",fontsize=8,style="setlinewidth(0.5),filled",fillcolor=grey,height=0.2,URL="woo.fem.html#woo.fem.In2_Facet"];
        "In2_Facet" -> "woo.fem.In2_Membrane_ElastMat" [arrowsize=0.5,style="setlinewidth(0.5)"]
}
class woo.dem.In2_Facet(*args, **kwargs)

Distribute frce on Facet to its nodes; the algorithm is purely geometrical since Facet has no internal forces, therefore can accept any kind of material.

Overloaded function.

  1. __init__(self: woo.dem.In2_Facet) -> None

  2. __init__(self: woo.dem.In2_Facet, *args, **kwargs) -> None

AnisoPorosityAnalyzer

ObjectEngineAnisoPorosityAnalyzer

class woo.dem.AnisoPorosityAnalyzer(*args, **kwargs)

Engine which analyzes current scene and computes directionaly porosity value by intersecting spheres with lines. The algorithm only works on periodic simulations.

Overloaded function.

  1. __init__(self: woo.dem.AnisoPorosityAnalyzer) -> None

  2. __init__(self: woo.dem.AnisoPorosityAnalyzer, *args, **kwargs) -> None

poro(= Matrix3(0, 0, 0, 0, 0, 0, 0, 0, 0))

Store analysis result here

[type: Matrix3r, read-only in python]

div(= 10)

Fineness of division of interval (0…1) for \(u\),\(v\) ∈〈0…1〉, which are used for uniform distribution over the positive octant as \(\theta= rac{\pi}{2}u\), \(\phi=\arccos v\) (see http://mathworld.wolfram.com/SpherePointPicking.html)

[type: int]

initStep(= -1)

Step in which internal data were last updated

[type: long, not accessible from python]

initNum(= 18446744073709551615)

Number of particles at last update

[type: size_t, not accessible from python]

rayIds(= [])

Particles intersected with ray when oneRay was last called from python.

[type: vector<Particle::id_t>, read-only in python]

rayPts(= [])

Starting and ending points of segments intersecting particles.

[type: vector<Vector3r>, read-only in python]

clearVis(self: woo.dem.AnisoPorosityAnalyzer)None

Clear visualizable intersection segments

oneRay(*args, **kwargs)

Overloaded function.

  1. oneRay(self: woo.dem.AnisoPorosityAnalyzer, A: _wooEigen11.Vector3, B: _wooEigen11.Vector3 = Vector3(0,0,0), vis: bool = True) -> float

  2. oneRay(self: woo.dem.AnisoPorosityAnalyzer, theta: float, phi: float, vis: bool = True) -> float

relSolid(self: woo.dem.AnisoPorosityAnalyzer, theta: float, phi: float, pt0: _wooEigen11.Vector3 = Vector3(0, 0, 0), vis: bool = False)float
static splitRay(theta: float, phi: float, pt0: _wooEigen11.Vector3 = Vector3(0, 0, 0), T: _wooEigen11.Matrix3 = Matrix3(1, 0, 0, 0, 1, 0, 0, 0, 1))List[_wooEigen11.Vector3]

Suspicious

ObjectEnginePeriodicEngineSuspicious

class woo.dem.Suspicious(*args, **kwargs)

Watch the simulation and signal suspicious evolutions, such as sudden increase in contact force beyond usual measure or unsual velocity.

Overloaded function.

  1. __init__(self: woo.dem.Suspicious) -> None

  2. __init__(self: woo.dem.Suspicious, *args, **kwargs) -> None

avgVel(= nan)

Average velocity norm.

[type: Real, read-only in python]

avgForce(= nan)

Average particle force norm.

[type: Real, read-only in python]

avgFn(= nan)

Average normal force norm.

[type: Real, read-only in python]

avgFt(= nan)

Average shear force norm.

[type: Real, read-only in python]

avgUn(= nan)

Average normal overlap.

[type: Real, read-only in python]

relThreshold(= 100.0)

Break on quantity this much larger than the average.

[type: Real]

errPar(= _8ParticleList[])

Particle where there was some error (shown in OpenGL).

[type: vector<shared_ptr<Particle>>]

errCon(= [])

Contacts where there was some error (shown in OpenGL)

[type: vector<shared_ptr<Contact>>]

ForcesToHdf5

ObjectEnginePeriodicEngineForcesToHdf5

digraph ForcesToHdf5 {
        rankdir=LR;
        margin=.2;
        "ForcesToHdf5" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.ForcesToHdf5"];
        "NodalForcesToHdf5" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.ForcesToHdf5"];
        "ForcesToHdf5" -> "NodalForcesToHdf5" [arrowsize=0.5,style="setlinewidth(0.5)"]
}
class woo.dem.ForcesToHdf5(*args, **kwargs)

Periodically export nodal/contact forces to HDF5 file. Nodal forces are only exported for tagged nodes (having DemDataTagged attached, instead of plain DemData) and include both force and torque. Contact forces only export force (not torque, which is zero for most models, but the adaptation would be easy).

Overloaded function.

  1. __init__(self: woo.dem.ForcesToHdf5) -> None

  2. __init__(self: woo.dem.ForcesToHdf5, *args, **kwargs) -> None

what(= 0)

Select whether to export nodal forces (default) or contact forces.

[type: int, named enum, possible values are: ‘node’ (‘nodes’, ‘nodal’; 0), ‘contact’ (‘contacts’; 1)]

contMask(= 2)

Only export contacts where at least one particle matches this mask. If zero, match all contacts. If this Contact.pA has matching mask, inverts force sense; this has as result that (unless both particles match) the force is exported as it acts on the matching particle.

[type: int]

out(= '')

Name of the output file.

[type: string]

deflate(= 9)

Compression level for HDF5 chunked storage; valid values are 0 to 9 (will be clamped if outside).

[type: int]

node(= None)

Local coordinate system; if defined, contact forces, torques and positions will be fransfored to local coordinates.

[type: shared_ptr<Node>]

NodalForcesToHdf5

ObjectEnginePeriodicEngineForcesToHdf5NodalForcesToHdf5

class woo.dem.NodalForcesToHdf5(*args, **kwargs)

Legacy class which only serves for backwards compatibility.

Overloaded function.

  1. __init__(self: woo.dem.NodalForcesToHdf5) -> None

  2. __init__(self: woo.dem.NodalForcesToHdf5, *args, **kwargs) -> None

Collision detection

TODO

Collider

ObjectEngineCollider

digraph Collider {
        rankdir=LR;
        margin=.2;
        "Collider" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.Collider"];
        "AabbTreeCollider" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.Collider"];
        "AabbCollider" -> "AabbTreeCollider" [arrowsize=0.5,style="setlinewidth(0.5)"]          "GridCollider" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.Collider"];
        "Collider" -> "GridCollider" [arrowsize=0.5,style="setlinewidth(0.5)"]          "InsertionSortCollider" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.Collider"];
        "AabbCollider" -> "InsertionSortCollider" [arrowsize=0.5,style="setlinewidth(0.5)"]             "AabbCollider" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.Collider"];
        "Collider" -> "AabbCollider" [arrowsize=0.5,style="setlinewidth(0.5)"]
}
class woo.dem.Collider(*args, **kwargs)

Abstract class for finding spatial collisions between bodies.

Overloaded function.

  1. __init__(self: woo.dem.Collider) -> None

  2. __init__(self: woo.dem.Collider, *args, **kwargs) -> None

nFullRuns(= 0)

Cumulative number of full runs, when collision detection is needed.

[type: int]

static mayCollide(dem: woo.dem.DemField, pA: woo.dem.Particle, pB: woo.dem.Particle)bool

Predicate whether two particles in question may collide or not

probeAabb(self: woo.dem.Collider, mn: _wooEigen11.Vector3, mx: _wooEigen11.Vector3)List[int]

Return list of particles intersected by axis-aligned box with given corners

AabbCollider

ObjectEngineColliderAabbCollider

digraph AabbCollider {
        rankdir=LR;
        margin=.2;
        "AabbCollider" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.AabbCollider"];
        "AabbTreeCollider" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.AabbCollider"];
        "AabbCollider" -> "AabbTreeCollider" [arrowsize=0.5,style="setlinewidth(0.5)"]          "InsertionSortCollider" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.AabbCollider"];
        "AabbCollider" -> "InsertionSortCollider" [arrowsize=0.5,style="setlinewidth(0.5)"]
}
class woo.dem.AabbCollider(*args, **kwargs)

Abstract class for colliders based on axis-aligned bounding boxes.

Overloaded function.

  1. __init__(self: woo.dem.AabbCollider) -> None

  2. __init__(self: woo.dem.AabbCollider, *args, **kwargs) -> None

boundDispatcher(= <BoundDispatcher @ 0x15bec60>)

BoundDispatcher object that is used for creating bounds on collider’s request as necessary.

[type: shared_ptr<BoundDispatcher>, read-only in python]

verletDist(= -0.05)

Length by which to enlarge particle bounds, to avoid running collider at every step. Stride disabled if zero, and bounding boxes are updated at every step. Negative value will trigger automatic computation, so that the real value will be |verletDist| × minimum spherical particle radius and minimum Inlet radius (for particles which don’t exist yet); if there is no minimum radius found, it will be set to 0.0 (with a warning) and disabled.

[type: Real]

noBoundOk(= False)

Allow particles without bounding box. This is currently only useful for testing woo.fem.Tetra which don’t undergo any collisions.

[type: bool]

AabbTreeCollider

ObjectEngineColliderAabbColliderAabbTreeCollider

class woo.dem.AabbTreeCollider(*args, **kwargs)

Collider based on AABB hierarchy.

Overloaded function.

  1. __init__(self: woo.dem.AabbTreeCollider) -> None

  2. __init__(self: woo.dem.AabbTreeCollider, *args, **kwargs) -> None

InsertionSortCollider

ObjectEngineColliderAabbColliderInsertionSortCollider

class woo.dem.InsertionSortCollider(*args, **kwargs)

Collider with O(n log(n)) complexity, using Aabb for bounds.

At the initial step, Bodies’ bounds (along sortAxis) are first std::sort’ed along one axis (sortAxis), then collided. The initial sort has \(O(n^2)\) complexity, see Colliders’ performance for some information (There are scripts in examples/collider-perf for measurements).

Insertion sort is used for sorting the bound list that is already pre-sorted from last iteration, where each inversion calls checkOverlap which then handles either overlap (by creating interaction if necessary) or its absence (by deleting interaction if it is only potential).

Bodies without bounding volume (such as clumps) are handled gracefully and never collide. Deleted bodies are handled gracefully as well.

This collider handles periodic boundary conditions. There are some limitations, notably:

  1. No body can have Aabb larger than cell’s half size in that respective dimension. You get exception it it does and gets in interaction.

  2. No body can travel more than cell’s distance in one step; this would mean that the simulation is numerically exploding, and it is only detected in some cases.

Stride can be used to avoid running collider at every step by enlarging the particle’s bounds, tracking their velocities and only re-run if they might have gone out of that bounds (see Verlet list for brief description and background) . This requires cooperation from Leapfrog as well as BoundDispatcher, which will be found among engines automatically (exception is thrown if they are not found).

If you wish to use strides, set verletDist (length by which bounds will be enlarged in all directions) to some value, e.g. 0.05 × typical particle radius. This parameter expresses the tradeoff between many potential interactions (running collider rarely, but with longer exact interaction resolution phase) and few potential interactions (running collider more frequently, but with less exact resolutions of interactions); it depends mainly on packing density and particle radius distribution.

Overloaded function.

  1. __init__(self: woo.dem.InsertionSortCollider) -> None

  2. __init__(self: woo.dem.InsertionSortCollider, *args, **kwargs) -> None

forceInitSort(= False)

When set to true, full sort will be run regardless of other conditions. This flag is then reset automatically to false

[type: bool]

sortAxis(= 0)

Axis for the initial contact detection.

[type: int]

sortThenCollide(= False)

Separate sorting and colliding phase; it is MUCH slower, but all interactions are processed at every step; this effectively makes the collider non-persistent, not remembering last state. (The default behavior relies on the fact that inversions during insertion sort are overlaps of bounding boxes that just started/ceased to exist, and only processes those; this makes the collider much more efficient.)

[type: bool]

maxVel2(= 0.0)

Maximum encountered velocity of a particle, to compute bounding box shift.

[type: Real, read-only in python]

numReinit(= 0)

Cumulative number of bound array re-initialization.

[type: int, read-only in python]

stepInvs(= Vector3i(0, 0, 0))

Number of inversions in insertion sort in the last step; always zero in the non-debug builds

[type: Vector3i]

numInvs(= Vector3i(0, 0, 0))

Cumulative number of inversions in insertion sort; always zero in the non-debug builds

[type: Vector3i]

ompTuneSort(= Vector3i(1, 1000, 0))

Fine-tuning for the OpenMP-parallellized partial insertion sort. The first number is the number of chunks per CPU (2 means each core will process 2 chunks sequentially, on average). The second number (if positive) is the lower bound on number of particles per chunk; the third number (if positive) is the limit of bounds per one chunk (15000 means that if there are e.g. 300k particles, bounds will be processed in 20 chunks, even if the number of chunks from the first number is smaller).

[type: Vector3i]

sortChunks(= -1)

Number of threads that were actually used during the last parallelized insertion sort.

[type: int, read-only in python]

paraPeri(= False)

(debugging only): enable/disable(default) parallel sort with periodic boundaries.

[type: bool]

periDbgNew(= False)

Compute periodic overlaps and periods twice (with the original and the new algorithm) compare the results and report discrepancies.

[type: bool]

maxSortPass(= -100)

If partial sort is not done after this many passes, give up. Usually more than a few passes (with non-parallelized insertion sort) already means a particle went crazy or the whole simulation is exploding. Negative value is relative to the number of cores as parallel insertion sort is done per chunks and more chunks mean more passes might be necessary.

[type: int]

periodic(= False)

Whether the collider is in periodic mode (read-only; for debugging)

[type: bool, not saved, read-only in python]

dbgInfo(self: woo.dem.InsertionSortCollider)object

Return python distionary with information on some internal structures (debugging only)

dumpBounds(self: woo.dem.InsertionSortCollider)tuple

Return representation of the internal sort data. The format is ([...],[...],[...]) for 3 axes, where each ... is a list of entries (bounds). The entry is a tuple with the fllowing items:

  • coordinate (float)

  • body id (int), but negated for negative bounds

  • period numer (int), if the collider is in the periodic regime.

property maxima

Array of maximum bbox coords; every 3 contiguous values are x, y, z for one particle

property minima

Array of minimum bbox coords; every 3 contiguous values are x, y,z for one particle

spatialOverlap(self: woo.dem.InsertionSortCollider, scene: woo.core.Scene, id1: int, id2: int)object

Debug access to the spatial overlap function.

GridCollider

ObjectEngineColliderGridCollider

class woo.dem.GridCollider(*args, **kwargs)

Grid-based collider.

Overloaded function.

  1. __init__(self: woo.dem.GridCollider) -> None

  2. __init__(self: woo.dem.GridCollider, *args, **kwargs) -> None

► Grid geometry

domain(= AlignedBox3((0, 0, 0), (1, 1, 1)))

Domain spanned by the grid.

[type: AlignedBox3r]

minCellSize(= 1.0)

Minimum cell size which will be used to compute dim.

[type: Real]

dim(= Vector3i(-1, -1, -1))

Number of cells along each axis

[type: Vector3i, read-only in python]

cellSize(= Vector3(nan, nan, nan))

Actual cell size

[type: Vector3r, read-only in python]

► Data

gridPrev(= None)

Previous fully populated grid.

[type: shared_ptr<GridStore>, not saved]

gridCurr(= None)

Current fully populated grid.

[type: shared_ptr<GridStore>, not saved]

gridOld(= None)

Grid containing entries in gridPrev but not in gridCurr.

[type: shared_ptr<GridStore>, not saved]

gridNew(= None)

Grid containing entries in gridCurr but not in gridPrev.

[type: shared_ptr<GridStore>, not saved]

► Rendering

color(= Vector3(1, 1, 0))

Color for rendering the domain

[type: Vector3r]

renderCells(= False)

Render cells.

[type: bool]

minOccup(= 0)

Minimum occupancy for cell to be rendered (zero cells are never rendered).

[type: int]

occupancyRange(= None)

Range for coloring grids based on occupancy (automatically created)

[type: shared_ptr<ScalarRange>]

► Tunables

gridDense(= 6)

Length of dense storage for new GridStore objects.

[type: int]

exIniSize(= 6)

GridStore.exIniSize for new grids.

[type: int]

exNumMaps(= 100)

GridStore.exNumMaps for new grids.

[type: int]

verletDist(= 0.0)

Length by which particle size is enalrged, to avoid running the collider at every timestep.

[type: Real, unit: m]

verletSteps(= 0)

If positive, enlarge boxes of some particle nodes (currently only spheres are supported) so that they will still be inside the box after verletSteps with their current velocity; verletDist is still used when velocity is too small.

[type: int]

complSetMinSize(= -1)

The value of setMinSize when calling GridStore.computeRelativeComplements.

[type: int]

useDiff(= True)

Create new contacts based on set complement of gridPrev with respect to gridCurr if both contain meaningful data and are compatible; if false, always traverse gridCurr and try adding all possible contacts (this should be much slower)

[type: bool]

around(= False)

If frue, particle in every cell is checked with particles in all cells around; this makes the grid storage substantially less loaded, as all particles can be shrunk by one half of the cell size.

Warning

this feature is broken and will raise exception if enabled; the trade-off is not good, since many more cells need to be checked around every cell, and many more potential contacts are created.

[type: bool]

shrink(= 0.0)

The amount of shrinking for each particle (half of the minimum cell size if around is true, zero otherwise.

[type: Real, not shown in the UI, read-only in python]

boundDispatcher(= <GridBoundDispatcher @ 0x1611110>)

Dispatches GridBound creation to GridBoundFuctor based on Shape type.

[type: shared_ptr<GridBoundDispatcher>]

GridStore

ObjectGridStore

class woo.dem.GridStore(*args, **kwargs)

3d grid storing scalar (particles ids) in partially dense array; the grid is actually 4d (gridSize×cellLen), and each cell may contain additional items in separate mapped storage, if the cellLen is not big enough to accomodate required number of items. Appending to cells is guarded via mutexes (with denseLock) optionally, appending to extra storage is mutex-protected always. Write acces from python should be used for testing exclusively.

Overloaded function.

  1. __init__(self: woo.dem.GridStore) -> None

  2. __init__(self: woo.dem.GridStore, *args, **kwargs) -> None

gridSize(= Vector3i(1, 1, 1))

Dimension of the grid.

[type: Vector3i, read-only in python]

cellLen(= 4)

Size of the dense storage in each cell

[type: int, read-only in python]

denseLock(= True)

Whether this grid supports per-cell dense storage locking for appending (must use protected_append)

[type: bool, read-only in python]

exIniSize(= 4)

Initial size of extension vectors, and step of their growth if needed.

[type: int, read-only in python]

exNumMaps(= 10)

Number of maps for extra items not fitting the dense storage (it affects how fine-grained is locking for those extra elements)

[type: int, read-only in python]

lo(= Vector3(nan, nan, nan))

Lower corner of the domain.

[type: Vector3r]

cellSize(= Vector3(nan, nan, nan))

Spatial size of the grid cell.

[type: Vector3r]

__delitem__(self: woo.dem.GridStore, arg0: _wooEigen11.Vector3i)None
__getitem__(self: woo.dem.GridStore, arg0: _wooEigen11.Vector3i)list
__setitem__(self: woo.dem.GridStore, arg0: _wooEigen11.Vector3i, arg1: List[int])None
append(self: woo.dem.GridStore, ijk: _wooEigen11.Vector3i, id: int)None

Append new element; uses mutexes with denseLock

complements(self: woo.dem.GridStore, B: woo.dem.GridStore, setMinSize: int = - 1)tuple
countEx(self: woo.dem.GridStore)dict

Return dictionary mapping ijk to number of items in the extra storage.

counts(self: woo.dem.GridStore)List[int]

Return array with number of cells with given number of elements: [number of cells with 0 elements, number of cells with 1 elements, …]

ijk2box(self: woo.dem.GridStore, ijk: _wooEigen11.Vector3i)_wooEigen11.AlignedBox3

Box for given cell

ijk2lin(self: woo.dem.GridStore, arg0: _wooEigen11.Vector3i)int
lin2ijk(self: woo.dem.GridStore, arg0: int)_wooEigen11.Vector3i
size(self: woo.dem.GridStore, arg0: _wooEigen11.Vector3i)int
xyz2ijk(self: woo.dem.GridStore, arg0: _wooEigen11.Vector3)_wooEigen11.Vector3i

Convert spatial coordinates to cell coordinate (no bound checking is done)

xyzNearIjk(self: woo.dem.GridStore, from: _wooEigen11.Vector3i, ijk: _wooEigen11.Vector3i)_wooEigen11.Vector3

Return point nearest to from (given in cell coords) in cell ijk

xyzNearXyz(self: woo.dem.GridStore, from: _wooEigen11.Vector3, ijk: _wooEigen11.Vector3i)_wooEigen11.Vector3

Return point nearest to from*(given in spatial coords) in cell *ijk (corner, at a face, on an edge, inside)

Bound

ObjectBound

digraph Bound {
        rankdir=LR;
        margin=.2;
        "Bound" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.Bound"];
        "GridBound" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.Bound"];
        "Bound" -> "GridBound" [arrowsize=0.5,style="setlinewidth(0.5)"]                "Aabb" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.Bound"];
        "Bound" -> "Aabb" [arrowsize=0.5,style="setlinewidth(0.5)"]
}
class woo.dem.Bound(*args, **kwargs)

Object bounding the associated body.

Overloaded function.

  1. __init__(self: woo.dem.Bound) -> None

  2. __init__(self: woo.dem.Bound, *args, **kwargs) -> None

box(= AlignedBox3((1.7976931348623157e308, 1.7976931348623157e308, 1.7976931348623157e308), (-1.7976931348623157e308, -1.7976931348623157e308, -1.7976931348623157e308)))

Axis-aligned bounding box.

[type: AlignedBox3r, unit: m, not saved, read-only in python]

dispHierarchy(self: woo.dem.Bound, names: bool = True)list

Return list of dispatch classes (from down upwards), starting with the class instance itself, top-level indexable at last. If names is true (default), return class names rather than numerical indices.

property dispIndex

Return class index of this instance.

GridBound

ObjectBoundGridBound

class woo.dem.GridBound(*args, **kwargs)

Bound defined via grid cell indices (used with GridCollider)

Overloaded function.

  1. __init__(self: woo.dem.GridBound) -> None

  2. __init__(self: woo.dem.GridBound, *args, **kwargs) -> None

nodePlay(= [])

Space in which respective nodes of the shapes may be without triggering new contact detection

[type: vector<AlignedBox3r>, read-only in python]

Aabb

ObjectBoundAabb

class woo.dem.Aabb(*args, **kwargs)

Axis-aligned bounding box, for use with InsertionSortCollider.

Overloaded function.

  1. __init__(self: woo.dem.Aabb) -> None

  2. __init__(self: woo.dem.Aabb, *args, **kwargs) -> None

nodeLastPos(= [])

Node positions when bbox was last updated.

[type: vector<Vector3r>, unit: m, read-only in python]

maxD2(= 0.0)

Maximum allowed squared distance for nodal displacements (i.e. how much was the bbox enlarged last time)

[type: Real, unit: m², not shown in the UI, read-only in python]

maxRot(= nan)

Maximum allowed rotation (in radians, without discriminating different angles) that does not yet invalidate the bbox. Functor sets to -1 (or other negative value) for particles where node rotation does not influence the box (such as spheres or facets); in that case, orientation difference is not computed at all. If it is left at NaN, it is an indication that the functor does not implemnt this behavior and an error will be raised in the collider.

[type: Real, read-only in python]

nodeLastOri(= [])

Node orientations when bbox was last updated.

[type: vector<Quaternionr>, read-only in python]

BoundFunctor

ObjectFunctorBoundFunctor

digraph BoundFunctor {
        rankdir=LR;
        margin=.2;
        "BoundFunctor" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.BoundFunctor"];
        "Bo1_Rod_Aabb" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.BoundFunctor"];
        "BoundFunctor" -> "Bo1_Rod_Aabb" [arrowsize=0.5,style="setlinewidth(0.5)"]              "Bo1_Capsule_Aabb" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.BoundFunctor"];
        "BoundFunctor" -> "Bo1_Capsule_Aabb" [arrowsize=0.5,style="setlinewidth(0.5)"]          "Bo1_Wall_Aabb" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.BoundFunctor"];
        "BoundFunctor" -> "Bo1_Wall_Aabb" [arrowsize=0.5,style="setlinewidth(0.5)"]             "woo.fem.Bo1_Tetra_Aabb" [shape="box",fontsize=8,style="setlinewidth(0.5),filled",fillcolor=grey,height=0.2,URL="woo.fem.html#woo.fem.BoundFunctor"];
        "BoundFunctor" -> "woo.fem.Bo1_Tetra_Aabb" [arrowsize=0.5,style="setlinewidth(0.5)"]            "Bo1_InfCylinder_Aabb" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.BoundFunctor"];
        "BoundFunctor" -> "Bo1_InfCylinder_Aabb" [arrowsize=0.5,style="setlinewidth(0.5)"]              "Bo1_Ellipsoid_Aabb" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.BoundFunctor"];
        "Bo1_Sphere_Aabb" -> "Bo1_Ellipsoid_Aabb" [arrowsize=0.5,style="setlinewidth(0.5)"]             "Bo1_Cone_Aabb" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.BoundFunctor"];
        "BoundFunctor" -> "Bo1_Cone_Aabb" [arrowsize=0.5,style="setlinewidth(0.5)"]             "Bo1_Sphere_Aabb" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.BoundFunctor"];
        "BoundFunctor" -> "Bo1_Sphere_Aabb" [arrowsize=0.5,style="setlinewidth(0.5)"]           "Bo1_Facet_Aabb" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.BoundFunctor"];
        "BoundFunctor" -> "Bo1_Facet_Aabb" [arrowsize=0.5,style="setlinewidth(0.5)"]
}
class woo.dem.BoundFunctor(*args, **kwargs)

Functor for creating/updating woo.dem.Bound.

Overloaded function.

  1. __init__(self: woo.dem.BoundFunctor) -> None

  2. __init__(self: woo.dem.BoundFunctor, *args, **kwargs) -> None

Bo1_Rod_Aabb

ObjectFunctorBoundFunctorBo1_Rod_Aabb

class woo.dem.Bo1_Rod_Aabb(*args, **kwargs)

Compute woo.dem.Aabb of a Rod particle

Overloaded function.

  1. __init__(self: woo.dem.Bo1_Rod_Aabb) -> None

  2. __init__(self: woo.dem.Bo1_Rod_Aabb, *args, **kwargs) -> None

Bo1_Facet_Aabb

ObjectFunctorBoundFunctorBo1_Facet_Aabb

class woo.dem.Bo1_Facet_Aabb(*args, **kwargs)

Creates/updates an Aabb of a Facet.

Overloaded function.

  1. __init__(self: woo.dem.Bo1_Facet_Aabb) -> None

  2. __init__(self: woo.dem.Bo1_Facet_Aabb, *args, **kwargs) -> None

Bo1_InfCylinder_Aabb

ObjectFunctorBoundFunctorBo1_InfCylinder_Aabb

class woo.dem.Bo1_InfCylinder_Aabb(*args, **kwargs)

Creates/updates an Aabb of a InfCylinder

Overloaded function.

  1. __init__(self: woo.dem.Bo1_InfCylinder_Aabb) -> None

  2. __init__(self: woo.dem.Bo1_InfCylinder_Aabb, *args, **kwargs) -> None

Bo1_Sphere_Aabb

ObjectFunctorBoundFunctorBo1_Sphere_Aabb

digraph Bo1_Sphere_Aabb {
        rankdir=LR;
        margin=.2;
        "Bo1_Sphere_Aabb" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.Bo1_Sphere_Aabb"];
        "Bo1_Ellipsoid_Aabb" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.Bo1_Sphere_Aabb"];
        "Bo1_Sphere_Aabb" -> "Bo1_Ellipsoid_Aabb" [arrowsize=0.5,style="setlinewidth(0.5)"]
}
class woo.dem.Bo1_Sphere_Aabb(*args, **kwargs)

Functor creating Aabb from Sphere. Honors DemField.distFactor.

Overloaded function.

  1. __init__(self: woo.dem.Bo1_Sphere_Aabb) -> None

  2. __init__(self: woo.dem.Bo1_Sphere_Aabb, *args, **kwargs) -> None

distFactor(= -1.0)

removed in API 10103, set DemField.distFactor instead.

[type: Real, not shown in the UI, not dumped, DEPRECATED, raises ValueError when accessed]

Bo1_Ellipsoid_Aabb

ObjectFunctorBoundFunctorBo1_Sphere_AabbBo1_Ellipsoid_Aabb

class woo.dem.Bo1_Ellipsoid_Aabb(*args, **kwargs)

Functor creating Aabb from Ellipsoid.

Todo

Handle rotation which is not detected by verlet distance!

Warning

woo.dem.DemField.distFactor is ignored.

Overloaded function.

  1. __init__(self: woo.dem.Bo1_Ellipsoid_Aabb) -> None

  2. __init__(self: woo.dem.Bo1_Ellipsoid_Aabb, *args, **kwargs) -> None

Bo1_Capsule_Aabb

ObjectFunctorBoundFunctorBo1_Capsule_Aabb

class woo.dem.Bo1_Capsule_Aabb(*args, **kwargs)

Creates/updates an Aabb of a Capsule

Overloaded function.

  1. __init__(self: woo.dem.Bo1_Capsule_Aabb) -> None

  2. __init__(self: woo.dem.Bo1_Capsule_Aabb, *args, **kwargs) -> None

Bo1_Cone_Aabb

ObjectFunctorBoundFunctorBo1_Cone_Aabb

class woo.dem.Bo1_Cone_Aabb(*args, **kwargs)

Compute woo.dem.Aabb of a Cone particle

Overloaded function.

  1. __init__(self: woo.dem.Bo1_Cone_Aabb) -> None

  2. __init__(self: woo.dem.Bo1_Cone_Aabb, *args, **kwargs) -> None

Bo1_Wall_Aabb

ObjectFunctorBoundFunctorBo1_Wall_Aabb

class woo.dem.Bo1_Wall_Aabb(*args, **kwargs)

Creates/updates an Aabb of a Wall

Overloaded function.

  1. __init__(self: woo.dem.Bo1_Wall_Aabb) -> None

  2. __init__(self: woo.dem.Bo1_Wall_Aabb, *args, **kwargs) -> None

GridBoundFunctor

ObjectFunctorGridBoundFunctor

digraph GridBoundFunctor {
        rankdir=LR;
        margin=.2;
        "GridBoundFunctor" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.GridBoundFunctor"];
        "Grid1_Wall" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.GridBoundFunctor"];
        "GridBoundFunctor" -> "Grid1_Wall" [arrowsize=0.5,style="setlinewidth(0.5)"]            "Grid1_Facet" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.GridBoundFunctor"];
        "GridBoundFunctor" -> "Grid1_Facet" [arrowsize=0.5,style="setlinewidth(0.5)"]           "Grid1_InfCylinder" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.GridBoundFunctor"];
        "GridBoundFunctor" -> "Grid1_InfCylinder" [arrowsize=0.5,style="setlinewidth(0.5)"]             "Grid1_Sphere" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.GridBoundFunctor"];
        "GridBoundFunctor" -> "Grid1_Sphere" [arrowsize=0.5,style="setlinewidth(0.5)"]
}
class woo.dem.GridBoundFunctor(*args, **kwargs)

Functor for creating/updating woo.dem.GridBound.

Overloaded function.

  1. __init__(self: woo.dem.GridBoundFunctor) -> None

  2. __init__(self: woo.dem.GridBoundFunctor, *args, **kwargs) -> None

Grid1_Sphere

ObjectFunctorGridBoundFunctorGrid1_Sphere

class woo.dem.Grid1_Sphere(*args, **kwargs)

Functor filling GridStore from Sphere, used with GridCollider.

Overloaded function.

  1. __init__(self: woo.dem.Grid1_Sphere) -> None

  2. __init__(self: woo.dem.Grid1_Sphere, *args, **kwargs) -> None

distFactor(= -1.0)

removed in API 10103, set DemField.distFactor instead.

[type: Real, not shown in the UI, not dumped, DEPRECATED, raises ValueError when accessed]

Grid1_Facet

ObjectFunctorGridBoundFunctorGrid1_Facet

class woo.dem.Grid1_Facet(*args, **kwargs)

Functor filling GridStore from Facet, used with GridCollider.

Overloaded function.

  1. __init__(self: woo.dem.Grid1_Facet) -> None

  2. __init__(self: woo.dem.Grid1_Facet, *args, **kwargs) -> None

movable(= False)

Set to allow movable facets (with grid enlarged by GridCollider.verletDist. If false and a moving facet is encountered, an exception is raised.

[type: bool]

Grid1_InfCylinder

ObjectFunctorGridBoundFunctorGrid1_InfCylinder

class woo.dem.Grid1_InfCylinder(*args, **kwargs)

Functor filling GridStore from InfCylinder, used with GridCollider.

Overloaded function.

  1. __init__(self: woo.dem.Grid1_InfCylinder) -> None

  2. __init__(self: woo.dem.Grid1_InfCylinder, *args, **kwargs) -> None

movable(= False)

Set to allow movable cylinders (with grid enlarged by GridCollider.verletDist. If false and a moving cylinder is encountered, an exception is raised.

[type: bool]

Grid1_Wall

ObjectFunctorGridBoundFunctorGrid1_Wall

class woo.dem.Grid1_Wall(*args, **kwargs)

Functor filling GridStore from Wall, used with GridCollider.

Overloaded function.

  1. __init__(self: woo.dem.Grid1_Wall) -> None

  2. __init__(self: woo.dem.Grid1_Wall, *args, **kwargs) -> None

movable(= False)

Set to allow movable walls (with grid enlarged by GridCollider.verletDist. If false and a movable wall is encountered, an exception is raised.

[type: bool]

BoundDispatcher

ObjectEngineDispatcherBoundDispatcher

class woo.dem.BoundDispatcher(*args, **kwargs)

Dispatcher calling functors based on received argument type(s).

Overloaded function.

  1. __init__(self: woo.dem.BoundDispatcher) -> None

  2. __init__(self: woo.dem.BoundDispatcher, *args, **kwargs) -> None

functors(= [])

Functors active in the dispatch mechanism [overridden below].

[type: vector<shared_ptr<BoundFunctor>>]

dispFunctor(self: woo.dem.BoundDispatcher, arg0: woo.dem.Shape)woo.dem.BoundFunctor

Return functor that would be dispatched for given argument(s); None if no dispatch; ambiguous dispatch throws.

dispMatrix(self: woo.dem.BoundDispatcher, names: bool = True)dict

Return dictionary with contents of the dispatch matrix.

GridBoundDispatcher

ObjectEngineDispatcherGridBoundDispatcher

class woo.dem.GridBoundDispatcher(*args, **kwargs)

Dispatcher calling functors based on received argument type(s).

Overloaded function.

  1. __init__(self: woo.dem.GridBoundDispatcher) -> None

  2. __init__(self: woo.dem.GridBoundDispatcher, *args, **kwargs) -> None

functors(= [])

Functors active in the dispatch mechanism [overridden below].

[type: vector<shared_ptr<GridBoundFunctor>>]

dispFunctor(self: woo.dem.GridBoundDispatcher, arg0: woo.dem.Shape)woo.dem.GridBoundFunctor

Return functor that would be dispatched for given argument(s); None if no dispatch; ambiguous dispatch throws.

dispMatrix(self: woo.dem.GridBoundDispatcher, names: bool = True)dict

Return dictionary with contents of the dispatch matrix.

Packings

TODO

ShapePack

ObjectShapePack

class woo.dem.ShapePack(*args, **kwargs)

Representation of geometry of many particles, with the ability of text I/O. It is meant as a replacement for woo.pack.SpherePack, which only handles spherical particles.

Overloaded function.

  1. __init__(self: woo.dem.ShapePack) -> None

  2. __init__(self: woo.dem.ShapePack, *args, **kwargs) -> None

cellSize(= Vector3(0, 0, 0))

Positive components signify periodic boundary along the respective axis.

[type: Vector3r]

movable(= False)

Whether the packing is movable, i.e. should be automatically recentered after filtered with a predicate.

[type: bool]

div(= 5)

Default value for recomputing properties of clumps (relative to the smallest equivalent radius)

[type: int]

raws(= [])

Raw shapes of particles/clumps.

[type: vector<shared_ptr<ShapeClump>>]

userData(= '')

String of arbitrary user data to be loaded/saved with the ShapePack.

[type: string]

loadFrom(= '')

If given when constructing the instance, the file is loaded immediately and the attribute is reset.

[type: string]

add(self: woo.dem.ShapePack, shapes: List[woo.dem.Shape], clumped: bool = True)None
canonicalize(self: woo.dem.ShapePack)None
cellRepeat(self: woo.dem.ShapePack, arg0: _wooEigen11.Vector3i)None
filter(self: woo.dem.ShapePack, predicate: Predicate, recenter: int = - 1)None
filtered(self: woo.dem.ShapePack, predicate: Predicate, recenter: int = - 1)woo.dem.ShapePack
fromDem(self: woo.dem.ShapePack, scene: woo.core.Scene, dem: woo.dem.DemField, mask: int = 0, skipUnsupported: bool = True)None
load(self: woo.dem.ShapePack, arg0: str)None
loadTxt(self: woo.dem.ShapePack, arg0: str)None
save(self: woo.dem.ShapePack, arg0: str)None
saveTxt(self: woo.dem.ShapePack, arg0: str)None
solidVolume(self: woo.dem.ShapePack)float
toDem(self: woo.dem.ShapePack, scene: woo.core.Scene, dem: woo.dem.DemField, mat: woo.dem.Material, mask: int = 5, color: float = nan)None
translate(self: woo.dem.ShapePack, arg0: _wooEigen11.Vector3)None

RawShape

ObjectRawShape

class woo.dem.RawShape(*args, **kwargs)

Object holding raw geometry data for one Shape in a uniform manner: center and radius of bounding sphere, plus an array of raw data. It is used as an intermediary shape-neutral storage format.

Overloaded function.

  1. __init__(self: woo.dem.RawShape) -> None

  2. __init__(self: woo.dem.RawShape, *args, **kwargs) -> None

className(= '')

Name of the Shape subclass.

[type: string]

center(= Vector3(0, 0, 0))

Center of the bounding sphere.

[type: Vector3r]

radius(= 0.0)

Radius of the bounding sphere.

[type: Real]

raw(= [])

Raw data for shape reconstruction; the size of the array is shape-specific.

[type: vector<Real>]

ShapeClump

ObjectShapeClump

digraph ShapeClump {
        rankdir=LR;
        margin=.2;
        "ShapeClump" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.ShapeClump"];
        "RawShapeClump" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.ShapeClump"];
        "ShapeClump" -> "RawShapeClump" [arrowsize=0.5,style="setlinewidth(0.5)"]               "SphereClumpGeom" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.ShapeClump"];
        "ShapeClump" -> "SphereClumpGeom" [arrowsize=0.5,style="setlinewidth(0.5)"]
}
class woo.dem.ShapeClump(*args, **kwargs)

Defines pure geometry of clumps. This is a base class, not to be used as-is.

Overloaded function.

  1. __init__(self: woo.dem.ShapeClump) -> None

  2. __init__(self: woo.dem.ShapeClump, *args, **kwargs) -> None

scaleProb(= [])

Used by particle generators: piecewise-linear function probability(equivRad) given as a sequence of x,y coordinates. If not given, constant function \(p(d)=1\) is assumed. See the documentation of woo.dem.PsdClumpGenerator for details.

[type: vector<Vector2r>]

pos(= Vector3(0, 0, 0))

Centroid position (computed automatically)

[type: Vector3r, not dumped, read-only in python]

ori(= Quaternion((1, 0, 0), 0))

Principal axes orientation (computed automatically)

[type: Quaternionr, not dumped, read-only in python]

volume(= nan)

Volume (computed automatically)

[type: Real, unit: m³, not dumped, read-only in python]

equivRad(= nan)

Equivalent radius of the clump (computed automatically) – mean of radii of gyration, i.e. \(\frac{1}{3}\sum \sqrt{I_{ii}/V}\).

[type: Real, unit: m, not dumped, read-only in python]

inertia(= Vector3(nan, nan, nan))

Geometrical inertia (computed with unit density)

[type: Vector3r, not dumped, read-only in python]

div(= 5)

Sampling grid fineness, when computing volume and other properties, relative to the smallest sphere’s radius. When zero or negative, assume spheres don’t intersect and use a different algorithm (Steiner’s theorem).

[type: int, not dumped]

clumped(= True)

Whether nodes of this shape are clumped together when the particle is created (so far, clumped shapes only are produced).

[type: bool, read-only in python]

makeParticles(self: woo.dem.ShapeClump, mat: woo.dem.Material, pos: _wooEigen11.Vector3, ori: _wooEigen11.Quaternion = Quaternion((1, 0, 0), 0), scale: float = 1.0, mask: int = 5)tuple

Create particle(s) as described by this geometry, positioned in pos and rotated with ori. Geometry will be scaled by scale. Returns tuple ([Node,…],[Particle,..]).

recompute(self: woo.dem.ShapeClump, div: int = 5, failOk: bool = False, fastOnly: bool = False)None

Recompute principal axes of the clump, using div for subdivision (see div for the semantics). failOk (silently return in case of invalid data) and fastOnly (return if there is lots of cells in subdivision) are only to be used internally.

SphereClumpGeom

ObjectShapeClumpSphereClumpGeom

class woo.dem.SphereClumpGeom(*args, **kwargs)

Defines geometry of spherical clumps. Each clump is described by spheres it is made of (position and radius).

Overloaded function.

  1. __init__(self: woo.dem.SphereClumpGeom) -> None

  2. __init__(self: woo.dem.SphereClumpGeom, *args, **kwargs) -> None

centers(= [])

Centers of constituent spheres, in clump-local coordinates.

[type: vector<Vector3r>]

radii(= [])

Radii of constituent spheres

[type: vector<Real>]

static fromSpherePack(pack: SpherePack, div: int = 5)List[woo.dem.SphereClumpGeom]

Return [ SphereClumpGeom ] which contain all clumps and spheres from given SpherePack.

RawShapeClump

ObjectShapeClumpRawShapeClump

class woo.dem.RawShapeClump(*args, **kwargs)

Clump consisting of generic shapes (RawShape).

Overloaded function.

  1. __init__(self: woo.dem.RawShapeClump) -> None

  2. __init__(self: woo.dem.RawShapeClump, *args, **kwargs) -> None

rawShapes(= [])

Data for creating primitive shapes

[type: vector<shared_ptr<RawShape>>]

Export

TODO

VtkExport

ObjectEnginePeriodicEngineVtkExport

class woo.dem.VtkExport(*args, **kwargs)

Export DEM simulation to VTK files for post-processing.

Overloaded function.

  1. __init__(self: woo.dem.VtkExport) -> None

  2. __init__(self: woo.dem.VtkExport, *args, **kwargs) -> None

out(= '')

Filename prefix to write into; woo.core.Scene.tags written as {tagName} are expanded at the first run.

[type: string]

compress(= True)

Compress output XML files

[type: bool]

ascii(= False)

Store data as readable text in the XML file (sets vtkXMLWriter data mode to vtkXMLWriter::Ascii, while the default is Appended

[type: bool]

multiblock(= False)

Write to multi-block VTK files, rather than separate files; currently borken, do not use.

[type: bool]

mask(= 0)

If non-zero, only particles matching the mask will be exported.

[type: int]

what(= 47)

Select data to be saved (e.g. VtkExport.spheres|VtkExport.mesh, or use VtkExport.all for everything)

[type: int]

sphereSphereOnly(= False)

Only export contacts between two spheres (not sphere+facet and such)

[type: bool]

infError(= True)

Raise exception for infinite objects which don’t have the glAB attribute set properly.

[type: bool]

skipInvisible(= True)

Skip invisible particles

[type: bool]

savePos(= False)

Save positions of spheres (redundant information, but useful for coloring by position in Paraview.

[type: bool]

clip(= AlignedBox3((1.7976931348623157e308, 1.7976931348623157e308, 1.7976931348623157e308), (-1.7976931348623157e308, -1.7976931348623157e308, -1.7976931348623157e308)))

Only export particles of which first node is in the clip box (if given).

[type: AlignedBox3r]

staticMeshBit(= 8)

Bit for identifying static mesh particles (Facet, Wall, InfCylinder only) which will be exported only once.

[type: int]

staticMeshDone(= False)

Whether static mesh was already exported

[type: bool]

subdiv(= 16)

Subdivision fineness for circular objects (such as cylinders).

Note

Facets are rendered without rounded edges (they are closed flat).

Note

Ellipsoids triangulation is controlled via the ellLev parameter.

[type: int]

ellLev(= 0)

Tesselation level for exporting ellipsoids (0 = icosahedron, each level subdivides one triangle into three.

[type: int, range: 0−3]

thickFacetDiv(= 1)

Subdivision for woo.dem.Facet objects with non-zero woo.dem.Facet.halfThick; the value of -1 will use subdiv; 0 will render only faces, without edges; 1 will close the edge flat; higher values mean the number of subdivisions.

[type: int]

cylCaps(= True)

Render caps of InfCylinder (at InfCylinder.glAB).

[type: bool]

rodSurf(= False)

Export rods (and derived classes) as capsule-shaped triangulated surfaces; without this option, rods are exported as plain connecting lines.

[type: bool]

nanValue(= 0.0)

Use this number instead of NaN in entries, since VTK cannot read NaNs properly

[type: Real]

outFiles(= {})

Files which have been written out, keyed by what they contain: ‘spheres’,’mesh’,’con’.

[type: map_string_vector_string, not shown in the UI, read-only in python]

outTimes(= [])

Times at which files were written.

[type: vector<Real>, not shown in the UI, read-only in python]

outSteps(= [])

Steps at which files were written.

[type: vector<int>, not shown in the UI, read-only in python]

mkDir(= False)

Attempt to create directory for output files, if not present.

[type: bool]

prevCellNum(= Vector3i(0, 0, 0))

Previous cell array sized, for pre-allocation.

[type: Vector3i, not shown in the UI, not saved, read-only in python]

makePvdFiles(self: woo.dem.VtkExport)dict

Write PVD files (one file for each category) and return dictionary mapping category name to the PVD filename; this requires that all active categories were saved at each step. Time points are output in the PVD file.

FlowAnalysis

ObjectEnginePeriodicEngineFlowAnalysis

class woo.dem.FlowAnalysis(*args, **kwargs)

Collect particle flow data in rectangular grid, watching different particle groups (radius ranges via dLim or groups by mask via masks – only one of them may be specified), and saving averages to as VTK uniform grid once finished.

Note

Only particles returning meaningful woo.dem.Shape.equivRad are considered, all other are ignored.

Overloaded function.

  1. __init__(self: woo.dem.FlowAnalysis) -> None

  2. __init__(self: woo.dem.FlowAnalysis, *args, **kwargs) -> None

box(= AlignedBox3((1.7976931348623157e308, 1.7976931348623157e308, 1.7976931348623157e308), (-1.7976931348623157e308, -1.7976931348623157e308, -1.7976931348623157e308)))

Domain in which the flow is to be analyzed; the box may glow slightly to accomodate integer number of cells. Do not change once there is some data alread. Do not change once there is some data already.

[type: AlignedBox3r]

node(= None)

Defines local coordinates system; it undefined, uses global coordinates.

[type: shared_ptr<Node>]

data

Grid data – 5d since each 3d point contains multiple entries, and there are multiple grids.

[type: boost_multi_array_real_5, not accessible from python]

dLim(= [])

Limiting diameter values, for defining fractions which are analyzed separately. Do not change when there is some data already.

[type: vector<Real>]

masks(= [])

Mask values for fractions; it is an error if a particle matches multiple masks. Do not change when there is some data already.

[type: vector<int>]

nFractions(= -1)

Number of fractions, defined via dLim or masks; set automatically.

[type: int, read-only in python]

cellSize(= nan)

Size of one cell in the box (in all directions); will be satisfied exactly at the expense of perhaps slightly growing box. Do not change once there is some data already.

[type: Real]

boxCells(= Vector3i(0, 0, 0))

Number of cells in the box (computed automatically)

[type: Vector3i, read-only in python]

mask(= 0)

Particles to consider in the flow analysis (0 to consider everything).

[type: int]

cellData(= False)

Write flow rate as cell data rather than point data.

[type: bool]

porosity(= False)

Compute (and export) solid ratio (1-porosity) for all spheroidal particles (requires triangulation of the domain at every step, hence slow and not enabled by default.

[type: bool]

matStateScalar(= -1)

If non-negative, index of material state to analyze.

[type: int]

matStateName(= '')

If given, used for VTK-export of the scalar; if not given, is filled form the first instance encountered automatically.

[type: string]

timeSpan(= 0.0)

Total time that the analysis has been running.

[type: Real]

color(= Vector3(1, 1, 0))

Color for rendering the domain

[type: Vector3r]

reset(self: woo.dem.FlowAnalysis)None

Reset all data so that next analysis will be run from virgin state.

vtkExport(self: woo.dem.FlowAnalysis, out: str)List[str]

Export all fractions separately, and also an overall flow (sum). out specifies prefix for all export filenames, the rest is created to describe the fraction or all for the sum. Exported file names are returned, the sum being at the very end. Internally calls vtkExportFractions for all fractions.

vtkExportFractions(self: woo.dem.FlowAnalysis, out: str, fractions: List[int])str

Export one single fraction to file named out. The extension .vti is added automatically. fractions specifies existing fraction numbers to export. If fractions are an empty list ([]), all fractions are exported at once.

vtkExportVectorOps(self: woo.dem.FlowAnalysis, out: str, fracA: List[int], fracB: List[int])str

Export operations on two fraction sets: cross-product, weighted differences and such, for segregation analysis. Appends .opt.vti to the output filename in out.

POVRayExport

ObjectEnginePeriodicEnginePOVRayExport

class woo.dem.POVRayExport(*args, **kwargs)

Export DEM simulation to POV-Ray input files (work in progress) for ray-tracing.

Overloaded function.

  1. __init__(self: woo.dem.POVRayExport) -> None

  2. __init__(self: woo.dem.POVRayExport, *args, **kwargs) -> None

out(= '')

Filename prefix to write into; woo.core.Scene.tags written as {tagName} are expanded at the first run.

[type: string]

mask(= 0)

If non-zero, only particles matching the mask will be exported.

[type: int]

skipInvisible(= True)

Skip invisible particles

[type: bool]

clip(= AlignedBox3((1.7976931348623157e308, 1.7976931348623157e308, 1.7976931348623157e308), (-1.7976931348623157e308, -1.7976931348623157e308, -1.7976931348623157e308)))

Only export particles of which first node is in the clip box (if given).

[type: AlignedBox3r]

frameCounter(= 0)

Counts exported frames and uses the number to name output files.

[type: int]

colorRange(= <ScalarRange @ 0x16e43d0>)

Range to map woo.dem.Shape.color to RGB for pigment specification.

[type: shared_ptr<ScalarRange>]

colorFuzz(= 0.2)

Relative fuzz for particle color; the texture is called with RGB colors mapped (via colorRange) from Shape.color - colorFuzz and Shape.color + colorFuzz, clamped to (0,1)).

[type: Real]

staticMask(= 8)

Mask for static particles, which will be exported only once into a special incude file separate from the per-frame include files.

[type: int]

masks(= [8, 4, 1])

Masks which will be tried one after another (first match counts) on each particle to determine which texture will be applied to it. Texture names are taken from textures and must be defined in the master file.

[type: vector<int>]

textures(= ['static', 'outlet', 'movable'])

Texture names applied to particles matching masks – the first matching mask counts, textures are named woo_tex_* and must be modified in the master file by the user (only an example definition is written by Woo). Particles not matching any mask will be assigned texture default (woo_tex_default). Each texture receives two rgb arguments which are colormapped from woo.dem.Shape.color using colorRange and colorFuzz.

[type: vector<string>]

cylCapTexture(= '')

If non-empty, InfCylinder objects will be drawn as several objects, with caps having this separate texture type.

[type: string]

wallTexture(= '')

If non-empty, Wall objects will have this texture applied, regardless of their mask. Meant for easily assigning checkerboard texture to wall objects.

[type: string]

texturesInc(= '')

Better textures, conditionally included in every step; if not provided, default filename will be generated.

[type: string]

extraInc(= ['woo-logo.inc'])

If set, these files will be conditionally included at the end of every step.

[type: vector<string>]

camLocation(= Vector3(15, 10, 0))

Default location of the camera

[type: Vector3r]

camLookAt(= Vector3(0, 0, 0))

Default look direction of the camera

[type: Vector3r]

camAngle(= 45.0)

Default camera angle (in degrees)

[type: float]

connMesh(= 1)

Whether to export facets (Facet and derived classes) as connected meshes, and in what cases. This entails building topology and determining connected components of the topology graph, which can demand non-negligible computation; the default is to do it for static mesh only, which is done only once, but not at every simulations steps. It is however necessary to set to always if non-static mesh is moving and should be exported.

Note

Facets are normally exported one-by-one. Mesh allows for more efficient processing in POV-Ray and for things like texture covering more facets.

[type: int, named enum, possible values are: ‘none’ (‘’, ‘never’; 0), ‘static’ (‘stat’, ‘static only’; 1), ‘always’ (‘yes’; 2)]

Particle

Each particles in DEM is defined by its shape (given by multiple nodes) and other parameters.

Particle

ObjectParticle

class woo.dem.Particle(*args, **kwargs)

Particle in DEM

Overloaded function.

  1. __init__(self: woo.dem.Particle) -> None

  2. __init__(self: woo.dem.Particle, *args, **kwargs) -> None

id(= -1)

Index in DemField::particles

[type: id_t, read-only in python]

mask(= 1)

Bitmask for collision detection and other (group 1 by default)

[type: uint]

shape(= None)

Geometrical configuration of the particle

[type: shared_ptr<Shape>]

material(= None)

Material of the particle

[type: shared_ptr<Material>]

matState(= None)

Material state of the particle (such as damage data and similar)

[type: shared_ptr<MatState>]

contacts(= {})

Contacts of this particle, indexed by id of the other particle.

[type: MapParticleContact, not saved, not accessible from python]

property Ek

Summary kinetic energy of the particle, shorthand for p.Ekt+p.Ekr.

property Ekr

Rotational kinetic energy of the particle, computed on-demand as \(\frac{1}{2}\vec{\omega}^T\mat{T}^T\mat{I}\mat{T}\omega\) (where \(\mat{T}\) is p.shape.nodes[0].ori as rotation matrix, \(\mat{I}\) is p.shape.nodes[0].dem.inertia as diagonal matrix – uninodal particles only (raises exception otherwise). Space deformation is not considered here, see getEk.

property Ekt

Translational kinetic energy of the particle, computed on-demand as \(\frac{1}{2}m|\vec{v}|^2\) – uninodal particles only (raises exception otherwise). Space deformation is not considered here, see getEk.

property allContacts

Return dictionary mapping other particles' IDs <Particle.id to Contact objects, including contacts which are not real.

property angVel

Particle angular velocity; shorthand for p.shape.nodes[0].dem.angVel – uninodal particles only (raises exception otherwise).

property blocked

Blocked degrees of freedom of the particle; shorthand for p.shape.nodes[0].dem.blocked – uninodal particles only (raises exception otherwise).

property con

Return list of IDs of contacting particles (real contacts only); shorthand for p.contacts.keys().

property f

Force on particle; shorthand for p.shape.nodes[0].dem.force – uninodal particles only (raises exception otherwise).

getEk(self: woo.dem.Particle, trans: bool = True, rot: bool = True, scene: woo.core.Scene = None)float

Compute kinetic energy (translational and/or rotational); when scene is given, only fluctuation linear/angular velocity will be considered if periodic boundary conditions are active.

property impose

Particle imposed constraints; shorthand for p.shape.nodes[0].dem.impose – uninodal particles only (raises exception otherwise).

property inertia

Particle inertia; shorthand for p.shape.nodes[0].dem.inertia – uninodal particles only (raises exception otherwise).

static make(shape: woo.dem.Shape, mat: woo.dem.Material, fixed: bool = False)woo.dem.Particle

Return Particle instance created from given shape and material; nodes with DemData are automatically added to the shape, mass and inertia is recomuted.

property mass

Particle mass; shorthand for p.shape.nodes[0].dem.mass – uninodal particles only (raises exception otherwise).

property mat

Material of the particle

property nodes

List of particle nodes; shorthand for p.shape.nodes.

property ori

Particle orientation; shorthand for p.shape.nodes[0].ori – uninodal particles only (raises exception otherwise).

property pos

Particle position; shorthand for p.shape.nodes[0].pos – uninodal particles only (raises exception otherwise).

property refPos

Reference particle position; shorthand for p.shape.nodes[0].gl.refPos, and Vector3(nan,nan,nan) if gl is not defined on the node.

property t

Torque on particle; shorthand for p.shape.nodes[0].dem.torque – uninodal particles only (raises exception otherwise).

property tacts

Return list of Contact objects where this particle takes part (real contacts only); shorthand for p.contact.values().

updateMassInertia(self: woo.dem.Particle)None

Internal use only. Recompute mass and inertia of all particle’s nodes; this function is usually called by particle construction routines; interally calls Shape::updateMassInertia and only works for particles without shared nodes.

property vel

Particle velocity; shorthand for p.shape.nodes[0].dem.vel – uninodal particles only (raises exception otherwise).

Shape

ObjectShape

digraph Shape {
        rankdir=LR;
        margin=.2;
        "Shape" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.Shape"];
        "Wall" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.Shape"];
        "Shape" -> "Wall" [arrowsize=0.5,style="setlinewidth(0.5)"]             "Ellipsoid" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.Shape"];
        "Shape" -> "Ellipsoid" [arrowsize=0.5,style="setlinewidth(0.5)"]                "woo.fem.Membrane" [shape="box",fontsize=8,style="setlinewidth(0.5),filled",fillcolor=grey,height=0.2,URL="woo.fem.html#woo.fem.Shape"];
        "Facet" -> "woo.fem.Membrane" [arrowsize=0.5,style="setlinewidth(0.5)"]         "Rod" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.Shape"];
        "Shape" -> "Rod" [arrowsize=0.5,style="setlinewidth(0.5)"]              "Cone" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.Shape"];
        "Shape" -> "Cone" [arrowsize=0.5,style="setlinewidth(0.5)"]             "InfCylinder" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.Shape"];
        "Shape" -> "InfCylinder" [arrowsize=0.5,style="setlinewidth(0.5)"]              "woo.fem.Tetra" [shape="box",fontsize=8,style="setlinewidth(0.5),filled",fillcolor=grey,height=0.2,URL="woo.fem.html#woo.fem.Shape"];
        "Shape" -> "woo.fem.Tetra" [arrowsize=0.5,style="setlinewidth(0.5)"]            "Facet" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.Shape"];
        "Shape" -> "Facet" [arrowsize=0.5,style="setlinewidth(0.5)"]            "Truss" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.Shape"];
        "Rod" -> "Truss" [arrowsize=0.5,style="setlinewidth(0.5)"]              "woo.fem.Tet4" [shape="box",fontsize=8,style="setlinewidth(0.5),filled",fillcolor=grey,height=0.2,URL="woo.fem.html#woo.fem.Shape"];
        "woo.fem.Tetra" -> "woo.fem.Tet4" [arrowsize=0.5,style="setlinewidth(0.5)"]             "Capsule" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.Shape"];
        "Shape" -> "Capsule" [arrowsize=0.5,style="setlinewidth(0.5)"]          "Sphere" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.Shape"];
        "Shape" -> "Sphere" [arrowsize=0.5,style="setlinewidth(0.5)"]
}
class woo.dem.Shape(*args, **kwargs)

Particle geometry

Overloaded function.

  1. __init__(self: woo.dem.Shape) -> None

  2. __init__(self: woo.dem.Shape, *args, **kwargs) -> None

bound(= None)

Bound of the particle, for use by collision detection only

[type: shared_ptr<Bound>]

nodes(= NodeList[])

Nodes associated with this particle

[type: vector<shared_ptr<Node> >]

color(= 0.9161950680037007)

Normalized color for rendering; negative values render with wire (rather than solid), \(|\text{color}|\)>2 means invisible. (use wire, hi and visible to manipulate those)

[type: Real]

asRaw(self: woo.dem.Shape)tuple
dispHierarchy(self: woo.dem.Shape, names: bool = True)list

Return list of dispatch classes (from down upwards), starting with the class instance itself, top-level indexable at last. If names is true (default), return class names rather than numerical indices.

property dispIndex

Return class index of this instance.

property equivRadius

Volumetrically equivalent radius of this shape. Returns NaN if the shape is multinodal or infinite.

property hi

Display this shape as highlighted (blinking color); internally encoded in color.

isInside(self: woo.dem.Shape, pt: _wooEigen11.Vector3)bool

Fast predicate testing whether pt is inside or outside this shape.

lumpMassInertia(self: woo.dem.Shape, arg0: woo.core.Node, arg1: float)tuple
setFromRaw(self: woo.dem.Shape, arg0: _wooEigen11.Vector3, arg1: float, arg2: woo.core.NodeList, arg3: List[float])None
property visible

Set the shape as invisible; internally encoded in color.

property volume

Volume of this shape; returns NaN for multinodal or infinite shapes.

property wire

Display this shape as wire or non-wire (unless overrideden by GL functor); internally encoded in color.

InfCylinder

ObjectShapeInfCylinder

class woo.dem.InfCylinder(*args, **kwargs)

Object representing infinite plane aligned with the coordinate system (axis-aligned wall).

Overloaded function.

  1. __init__(self: woo.dem.InfCylinder) -> None

  2. __init__(self: woo.dem.InfCylinder, *args, **kwargs) -> None

radius(= nan)

Radius of the cylinder

[type: Real]

axis(= 0)

Axis of the normal; can be 0,1,2 for +x, +y, +z respectively (Node’s orientation is disregarded for walls)

[type: int]

glAB(= Vector2(nan, nan))

Endpoints between which the infinite cylinder is drawn, in local coordinate system along axis; if NaN, taken from scene view to be visible

[type: Vector2r]

static make(position, radius, axis, glAB=None, fixed=True, mass=0, color=None, wire=False, angVel=None, mat=<function defaultMaterial>, mask=5)

Return a ready-made infinite cylinder particle.

Wall

ObjectShapeWall

class woo.dem.Wall(*args, **kwargs)

Object representing infinite plane aligned with the coordinate system (axis-aligned wall).

Overloaded function.

  1. __init__(self: woo.dem.Wall) -> None

  2. __init__(self: woo.dem.Wall, *args, **kwargs) -> None

sense(= 0)

Which side of the wall interacts: -1 for negative only, 0 for both, +1 for positive only.

[type: int]

axis(= 0)

Axis of the normal; can be 0,1,2 for +x, +y, +z respectively (Node’s orientation is disregarded for walls)

[type: int]

glAB(= AlignedBox2((nan, nan), (nan, nan)))

Points between which the wall is drawn (if NaN, computed automatically to cover the visible part of the scene)

[type: AlignedBox2r]

static make(position, axis, sense=0, glAB=None, fixed=True, mass=0, color=None, mat=<function defaultMaterial>, visible=True, mask=3)

Return ready-made wall body.

Parameters
  • position (float-or-Vector3-or-Node) – center of the wall. If float, it is the position along given axis, the other 2 components being zero

  • axis (∈{0,1,2}) – orientation of the wall normal (0,1,2) for x,y,z (sc. planes yz, xz, xy)

  • sense (∈{-1,0,1}) – sense in which to interact (0: both, -1: negative, +1: positive; see woo.dem.Wall)

See woo.utils.sphere’s documentation for meaning of other parameters.

static makeBox(box, which=(1, 1, 1, 1, 1, 1), **kw)

Return box delimited by walls, created by woo.dem.Wall.make, which receives most arguments. Wall.glAB are computed automatically so that walls visually end at the edges.

Note

Since walls are infinite, they will still interact with other particle beyond this box; use woo.triangulated.box for true box with arbitrary orientation.

Parameters
  • box – axis-aligned box determining positions of walls.

  • which – determines which of the 6 walls are created (boolean values), in the order -x, -y, -z, +x, +y, +z. For instance, to create a box which does not have the top, say which=(1,1,1,1,1,0)).

Returns

list of Particle objects.

Sphere

ObjectShapeSphere

class woo.dem.Sphere(*args, **kwargs)

Spherical particle.

Overloaded function.

  1. __init__(self: woo.dem.Sphere) -> None

  2. __init__(self: woo.dem.Sphere, *args, **kwargs) -> None

radius(= nan)

Radius.

[type: Real, unit: m]

static make(center, radius, mat=<function defaultMaterial>, fixed=False, wire=False, color=None, highlight=False, mask=5, vel=None)

Create sphere with given parameters; mass and inertia computed automatically.

Parameters
  • center (Vector3) – center

  • radius (float) – radius

  • float-or-None – particle’s color as float; random color will be assigned if None.

  • mat

    specify woo.dem.Particle.material; different types are accepted:
    • woo.dem.Material instance: this instance will be used

    • callable: will be called without arguments; returned Material value will be used (Material factory object, if you like)

  • mask (int) – woo.dem.Particle.mask for the body

Returns

Particle instance with desired characteristics.

Instance of material can be given:

>>> from woo import utils
>>> s1=utils.sphere((0,0,0),1,wire=False,color=.7,mat=ElastMat(young=30e9,density=2e3))
>>> s1.shape.wire
False
>>> s1.shape.color
0.7
>>> s1.mat.density
2000.0

Finally, material can be a callable object (taking no arguments), which returns a Material instance. Use this if you don’t call this function directly (for instance, through woo.pack.randomDensePack), passing only 1 material parameter, but you don’t want material to be shared.

For instance, randomized material properties can be created like this:

>>> import random
>>> def matFactory(): return ElastMat(young=1e10*random.random(),density=1e3+1e3*random.random())
...
>>> s2=utils.sphere([0,2,0],1,mat=matFactory)
>>> s3=utils.sphere([1,2,0],1,mat=matFactory)

Ellipsoid

ObjectShapeEllipsoid

class woo.dem.Ellipsoid(*args, **kwargs)

Ellipsoidal particle.

Overloaded function.

  1. __init__(self: woo.dem.Ellipsoid) -> None

  2. __init__(self: woo.dem.Ellipsoid, *args, **kwargs) -> None

semiAxes(= Vector3(nan, nan, nan))

Semi-principal axes.

[type: Vector3r, unit: m]

static make(center, semiAxes, ori=Quaternion((1, 0, 0), 0), angVel=None, color=None, mat=<function defaultMaterial>, fixed=False, wire=False, visible=True, mask=5, **kw)

Return an woo.dem.Ellipsoid particle.

Rod

ObjectShapeRod

digraph Rod {
        rankdir=LR;
        margin=.2;
        "Rod" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.Rod"];
        "Truss" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.Rod"];
        "Rod" -> "Truss" [arrowsize=0.5,style="setlinewidth(0.5)"]
}
class woo.dem.Rod(*args, **kwargs)

Line element without internal forces, with circular cross-section and hemi-spherical caps at both ends. Geometrically the same Capsule, but with 2 nodes.

Overloaded function.

  1. __init__(self: woo.dem.Rod) -> None

  2. __init__(self: woo.dem.Rod, *args, **kwargs) -> None

radius(= nan)

Radius of the rod.

[type: Real]

static make(vertices, radius, fixed=True, wire=True, color=None, mat=<function defaultMaterial>, visible=True, mask=3, __class=<class 'woo.dem.Rod'>)

Create Rod with given parameters:

Parameters
  • vertices – endpoints given as coordinates (Vector3) or nodes

  • radius – radius of the rod

  • wire – render as wire by default

  • color – color as scalar (0…1); if not given, random color is assigned

  • mat – material; if not given, default material is assigned

  • visible

  • mask

Truss

ObjectShapeRodTruss

class woo.dem.Truss(*args, **kwargs)

Describes line element (cylinder) with optional caps and with free or constrained rotations at either end.

Overloaded function.

  1. __init__(self: woo.dem.Truss) -> None

  2. __init__(self: woo.dem.Truss, *args, **kwargs) -> None

l0(= nan)

Initial (usually equilibrium) length

[type: Real]

axialStress(= 0.0)

Current normal stress (informative only)

[type: Real]

preStress(= 0.0)

Pre-stress (stress at zero strain)

[type: Real]

Facet

ObjectShapeFacet

digraph Facet {
        rankdir=LR;
        margin=.2;
        "Facet" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.Facet"];
        "woo.fem.Membrane" [shape="box",fontsize=8,style="setlinewidth(0.5),filled",fillcolor=grey,height=0.2,URL="woo.fem.html#woo.fem.Facet"];
        "Facet" -> "woo.fem.Membrane" [arrowsize=0.5,style="setlinewidth(0.5)"]
}
class woo.dem.Facet(*args, **kwargs)

Facet (triangle in 3d) particle.

Overloaded function.

  1. __init__(self: woo.dem.Facet) -> None

  2. __init__(self: woo.dem.Facet, *args, **kwargs) -> None

fakeVel(= Vector3(0, 0, 0))

Fake velocity when computing contact, in global coordinates (for modeling moving surface modeled using static triangulation); only in-plane velocity is meaningful, but this is not enforced.

Note

If the x-component is NaN, the meaning is special: fakeVel is taken as zero vector and, in addition, local in-plane facet’s linear velocity at the contact is taken as zero (rather than linearly interpolated between velocity of nodes).

[type: Vector3r]

halfThick(= 0.0)

Geometric thickness (added in all directions)

[type: Real]

n21lim(= Vector3(nan, nan, nan))

Edge & vertex contact: limit value for dot-product with normal (dot-product of normal with in-plane angle of neighboring facet, perpendicular to the edge).

[type: Vector3r]

area(self: woo.dem.Facet)float

Return surface area of the facet

computeNeighborAngles(self: woo.dem.Facet)None

Compute n21Min using beighboring facets so that contact direction can be adjusted (only some Facet-X functors support that currently).

getCentroid(self: woo.dem.Facet)_wooEigen11.Vector3

Return centroid of the facet

getNormal(self: woo.dem.Facet)_wooEigen11.Vector3

Return normal vector of the facet

static make(vertices, fakeVel=None, halfThick=0.0, fixed=True, wire=True, color=None, highlight=False, mat=<function defaultMaterial>, visible=True, mask=3, flex=None, __class=<class 'woo.dem.Facet'>)

Create facet with given parameters.

Parameters
  • vertices ([Vector3,Vector3,Vector3]) – coordinates of vertices in the global coordinate system.

  • wire (bool) – if True, facets are shown as skeleton; otherwise facets are filled

See woo.utils.sphere’s documentation for meaning of other parameters.

outerEdgeNormals(self: woo.dem.Facet)List[_wooEigen11.Vector3]

Return outer edge normal vectors

Cone

ObjectShapeCone

class woo.dem.Cone(*args, **kwargs)

Line element without internal forces, with circular cross-section and hemi-spherical caps at both ends. Geometrically the same Capsule, but with 2 nodes.

Overloaded function.

  1. __init__(self: woo.dem.Cone) -> None

  2. __init__(self: woo.dem.Cone, *args, **kwargs) -> None

radii(= Vector2(nan, nan))

Radii of the cone. One of them can be zero (for full cone). When both radii are non-zero, the result is conical frustum.

[type: Vector2r]

static make(vertices, radii, *, fixed=True, wire=False, color=None, angVel=None, mat=<function defaultMaterial>, visible=True, mask=3)

Create cone with given parameters.

Capsule

ObjectShapeCapsule

class woo.dem.Capsule(*args, **kwargs)

Cylinder with half-spherical caps on both sides, Mindowski sum of segment with sphere.

Overloaded function.

  1. __init__(self: woo.dem.Capsule) -> None

  2. __init__(self: woo.dem.Capsule, *args, **kwargs) -> None

radius(= nan)

Radius of the capsule – of half-spherical caps and also of the middle part.

[type: Real, unit: m]

shaft(= nan)

Length of the middle segment

[type: Real, unit: m]

endPt(self: woo.dem.Capsule, i: int)_wooEigen11.Vector3

Return one of capsule endpoints. The first (negative on local \(x\)-axis) is returned with *i=0, otherwise the second one is returned.

static make(center, radius, shaft, ori=Quaternion((1, 0, 0), 0), fixed=False, color=None, wire=False, mat=<function defaultMaterial>, mask=5)

Return a ready-made capsule particle.

Material properties

TODO

Material

ObjectMaterial

digraph Material {
        rankdir=LR;
        margin=.2;
        "Material" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.Material"];
        "ConcreteMat" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.Material"];
        "FrictMat" -> "ConcreteMat" [arrowsize=0.5,style="setlinewidth(0.5)"]           "FrictMat" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.Material"];
        "ElastMat" -> "FrictMat" [arrowsize=0.5,style="setlinewidth(0.5)"]              "IceMat" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.Material"];
        "FrictMat" -> "IceMat" [arrowsize=0.5,style="setlinewidth(0.5)"]                "HertzMat" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.Material"];
        "FrictMat" -> "HertzMat" [arrowsize=0.5,style="setlinewidth(0.5)"]              "ElastMat" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.Material"];
        "Material" -> "ElastMat" [arrowsize=0.5,style="setlinewidth(0.5)"]              "PelletMat" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.Material"];
        "FrictMat" -> "PelletMat" [arrowsize=0.5,style="setlinewidth(0.5)"]             "LudingMat" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.Material"];
        "FrictMat" -> "LudingMat" [arrowsize=0.5,style="setlinewidth(0.5)"]
}
class woo.dem.Material(*args, **kwargs)

Particle material

Overloaded function.

  1. __init__(self: woo.dem.Material) -> None

  2. __init__(self: woo.dem.Material, *args, **kwargs) -> None

density(= 1000.0)

Density

[type: Real, unit: kg/m³]

id(= -1)

Some number identifying this material; used with MatchMaker objects, useless otherwise

[type: int, not shown in the UI]

dispHierarchy(self: woo.dem.Material, names: bool = True)list

Return list of dispatch classes (from down upwards), starting with the class instance itself, top-level indexable at last. If names is true (default), return class names rather than numerical indices.

property dispIndex

Return class index of this instance.

ElastMat

ObjectMaterialElastMat

digraph ElastMat {
        rankdir=LR;
        margin=.2;
        "ElastMat" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.ElastMat"];
        "ConcreteMat" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.ElastMat"];
        "FrictMat" -> "ConcreteMat" [arrowsize=0.5,style="setlinewidth(0.5)"]           "IceMat" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.ElastMat"];
        "FrictMat" -> "IceMat" [arrowsize=0.5,style="setlinewidth(0.5)"]                "PelletMat" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.ElastMat"];
        "FrictMat" -> "PelletMat" [arrowsize=0.5,style="setlinewidth(0.5)"]             "HertzMat" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.ElastMat"];
        "FrictMat" -> "HertzMat" [arrowsize=0.5,style="setlinewidth(0.5)"]              "FrictMat" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.ElastMat"];
        "ElastMat" -> "FrictMat" [arrowsize=0.5,style="setlinewidth(0.5)"]              "LudingMat" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.ElastMat"];
        "FrictMat" -> "LudingMat" [arrowsize=0.5,style="setlinewidth(0.5)"]
}
class woo.dem.ElastMat(*args, **kwargs)

Elastic material with contact friction. See also ElastMat.

Overloaded function.

  1. __init__(self: woo.dem.ElastMat) -> None

  2. __init__(self: woo.dem.ElastMat, *args, **kwargs) -> None

young(= 1000000000.0)

Young’s modulus

[type: Real, unit: Pa]

FrictMat

ObjectMaterialElastMatFrictMat

digraph FrictMat {
        rankdir=LR;
        margin=.2;
        "FrictMat" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.FrictMat"];
        "ConcreteMat" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.FrictMat"];
        "FrictMat" -> "ConcreteMat" [arrowsize=0.5,style="setlinewidth(0.5)"]           "IceMat" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.FrictMat"];
        "FrictMat" -> "IceMat" [arrowsize=0.5,style="setlinewidth(0.5)"]                "HertzMat" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.FrictMat"];
        "FrictMat" -> "HertzMat" [arrowsize=0.5,style="setlinewidth(0.5)"]              "PelletMat" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.FrictMat"];
        "FrictMat" -> "PelletMat" [arrowsize=0.5,style="setlinewidth(0.5)"]             "LudingMat" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.FrictMat"];
        "FrictMat" -> "LudingMat" [arrowsize=0.5,style="setlinewidth(0.5)"]
}
class woo.dem.FrictMat(*args, **kwargs)

Elastic material with contact friction. See also ElastMat.

Overloaded function.

  1. __init__(self: woo.dem.FrictMat) -> None

  2. __init__(self: woo.dem.FrictMat, *args, **kwargs) -> None

tanPhi(= 0.5)

Tangent of internal friction angle.

[type: Real]

ktDivKn(= 0.2)

Ratio of tangent and shear modulus on contact.

[type: Real]

PelletMat

ObjectMaterialElastMatFrictMatPelletMat

class woo.dem.PelletMat(*args, **kwargs)

Material describing pellet behavior; see Law2_L6Geom_PelletPhys_Pellet for details of the material model.

Overloaded function.

  1. __init__(self: woo.dem.PelletMat) -> None

  2. __init__(self: woo.dem.PelletMat, *args, **kwargs) -> None

normPlastCoeff(= 0.0)

Coefficient \(\alpha\) in the normal yield function; non-positive deactivates.

[type: Real]

kaDivKn(= 0.0)

Ratio of \(\frac{k_A}{K_N}\) for the adhesion function; non-positive deactivates.

[type: Real]

PelletAgglomerator

ObjectEnginePelletAgglomerator

class woo.dem.PelletAgglomerator(*args, **kwargs)

Compute agglomeration of pellets due to contact some special particles, or wearing due to impacts (only applies to particles with PelletMat.

Overloaded function.

  1. __init__(self: woo.dem.PelletAgglomerator) -> None

  2. __init__(self: woo.dem.PelletAgglomerator, *args, **kwargs) -> None

agglomSrcs(= _8ParticleList[])

Sources of agglomerating mass; particles in contact with this source will have their radius increased based on their relative angular velocity.

[type: vector<shared_ptr<Particle>>]

massIncPerRad(= nan)

Increase of sphere mass per one radian of rolling (radius is increased in such way that mass increase is satisfied).

[type: Real]

dampHalfLife(= -10000.0)

Half-life for rotation damping (includes both rolling and twist); if negative, relative to the (initial) woo.core.Scene.dt; zero deactivates damping. Half-life is \(t_{1/.2}=\frac{\ln 2}{\lambda}\) where \(\lambda\) is decay coefficient applied as \(\d\omega=-\lambda\omega\) (see http://en.wikipedia.org/wiki/Exponential_decay for details).

[type: Real]

currRate(= 0.0)

Current rate of mass increase due to agglomeration.

[type: Real]

currRateSmooth(= 0.001)

Smoothing coefficient for currRate ∈〈0,1〉 (should be rather low, since this engine runs at every step).

[type: Real]

mass(= 0.0)

Total cumulative mass increase due to agglomeration.

[type: Real]

LudingMat

ObjectMaterialElastMatFrictMatLudingMat

class woo.dem.LudingMat(*args, **kwargs)

Material for luding-contact-model.

Overloaded function.

  1. __init__(self: woo.dem.LudingMat) -> None

  2. __init__(self: woo.dem.LudingMat, *args, **kwargs) -> None

► Normal

k1DivKn(= 0.5)

Ratio of plastic (loading) stiffness to maximum normal (elastic, unloading/reloading) stiffness.

[type: Real]

kaDivKn(= 0.2)

Ratio of adhesive ‘stiffness’ to elastic (unloading) stiffness.

[type: Real]

deltaLimRel(= 0.1)

Maximum plasticity depth relative to minimum radius of contacting particles.

[type: Real]

viscN(= 0.0)

Normal viscous coefficient.

[type: Real]

► Tangential

dynDivStat(= 0.7)

Dynamic to static friction ratio (\(\phi_d=\mu_d/\mu_s\)); applied in tangential, rolling and twisting senses.

[type: Real]

viscT(= 0.0)

Tangential viscosity.

[type: Real]

► Rolling

krDivKn(= 0.2)

Rolling stiffness relative to maximal elastic stiffness (divided by average contact radius for dimensional consistency).

[type: Real]

statR(= 0.4)

Rolling static friction coefficient.

[type: Real]

viscR(= 0.1)

Rolling viscous coefficient for rolling.

[type: Real]

► Twisting

kwDivKn(= 0.2)

Twist stiffness relative to maximal elastic stiffness (divided by average contact radius for dimensional consistency).

[type: Real]

statW(= 0.3)

Twisting static friction coefficient.

[type: Real]

viscW(= 0.1)

Twisting viscous coefficient.

[type: Real]

ConcreteMat

ObjectMaterialElastMatFrictMatConcreteMat

class woo.dem.ConcreteMat(*args, **kwargs)

Concrete material, for use with other Concrete classes.

Overloaded function.

  1. __init__(self: woo.dem.ConcreteMat) -> None

  2. __init__(self: woo.dem.ConcreteMat, *args, **kwargs) -> None

sigmaT(= nan)

Initial cohesion [Pa]

[type: Real]

neverDamage(= False)

If true, no damage will occur (for testing only).

[type: bool]

epsCrackOnset(= nan)

Limit elastic strain [-]

[type: Real]

relDuctility(= nan)

relative ductility of bonds in normal direction

[type: Real]

damLaw(= 1)

Law for damage evolution in uniaxial tension. 0 for linear stress-strain softening branch, 1 (default) for exponential damage evolution law

[type: int, named enum, possible values are: ‘linear softening’ (‘lin’; 0), ‘exponential softening’ (‘exp’; 1)]

dmgTau(= -1.0)

Characteristic time for normal viscosity. [s]

[type: Real]

dmgRateExp(= 0.0)

Exponent for normal viscosity function. [-]

[type: Real]

plTau(= -1.0)

Characteristic time for visco-plasticity. [s]

[type: Real]

plRateExp(= 0.0)

Exponent for visco-plasticity function. [-]

[type: Real]

isoPrestress(= 0.0)

Isotropic prestress of the whole specimen. [P a]

[type: Real]

IceMat

ObjectMaterialElastMatFrictMatIceMat

class woo.dem.IceMat(*args, **kwargs)

Ice material; see ice-contact-model for details.

Overloaded function.

  1. __init__(self: woo.dem.IceMat) -> None

  2. __init__(self: woo.dem.IceMat, *args, **kwargs) -> None

breakN(= 0.0001)

Normal strain where cohesion stress is reached.

[type: Real]

alpha(= Vector2(1, 1))

Factors \((\alpha_w, \alpha_t)\) to compute twisting/rolling stiffnesses from \(k_n\) and \(k_t\).

[type: Vector2r]

beta(= Vector3(0.1, 0.1, 0.1))

Factors \((\beta_t,\beta_w,\beta_r)\) for computing cohesion from normal cohesion \(c_n\)

[type: Vector3r]

mu(= 0.05)

Kinetic (rolling) friction coefficient.

[type: Real]

HertzMat

ObjectMaterialElastMatFrictMatHertzMat

class woo.dem.HertzMat(*args, **kwargs)

Material parameters to be used with adhesive (Schwarz) model.

Overloaded function.

  1. __init__(self: woo.dem.HertzMat) -> None

  2. __init__(self: woo.dem.HertzMat, *args, **kwargs) -> None

surfEnergy(= 0.0)

Surface energy parameter [J/m^2] per each unit contact surface, to derive adhesive (DMT, JKR, Schwarz) formulation from HM. If zero, adhesion is disabled.

[type: Real]

alpha(= 0.0)

Parameter interpolating between DMT and JKR extremes in the Schwarz model. \(alpha\) was introduced in [COS99]

[type: Real]

MatState

ObjectMatState

digraph MatState {
        rankdir=LR;
        margin=.2;
        "MatState" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.MatState"];
        "InletMatState" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.MatState"];
        "MatState" -> "InletMatState" [arrowsize=0.5,style="setlinewidth(0.5)"]         "LudingMatState" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.MatState"];
        "MatState" -> "LudingMatState" [arrowsize=0.5,style="setlinewidth(0.5)"]                "ConcreteMatState" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.MatState"];
        "MatState" -> "ConcreteMatState" [arrowsize=0.5,style="setlinewidth(0.5)"]              "ClusterMatState" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.MatState"];
        "MatState" -> "ClusterMatState" [arrowsize=0.5,style="setlinewidth(0.5)"]               "PelletMatState" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.MatState"];
        "MatState" -> "PelletMatState" [arrowsize=0.5,style="setlinewidth(0.5)"]
}
class woo.dem.MatState(*args, **kwargs)

Holds data related to material state of each particle.

Overloaded function.

  1. __init__(self: woo.dem.MatState) -> None

  2. __init__(self: woo.dem.MatState, *args, **kwargs) -> None

getNumScalars(self: woo.dem.MatState)int

Return number of scalars (index to getScalar and getScalarName should be lower than this number).

getScalar(self: woo.dem.MatState, index: int, time: float = 0, step: int = - 1, smooth: float = 0)float

Return scalar value given its numerical index. step is used to check whether data are up-to-date, smooth (if positive) is used to smooth out old data (usually using exponential decay function)

getScalarName(self: woo.dem.MatState, index: int)str

Return name of scalar at given index (human-readable description)

LudingMatState

ObjectMatStateLudingMatState

class woo.dem.LudingMatState(*args, **kwargs)

Hold detailed per-particle data such as dissipated energy, for the Luding model (luding-contact-model.)

Overloaded function.

  1. __init__(self: woo.dem.LudingMatState) -> None

  2. __init__(self: woo.dem.LudingMatState, *args, **kwargs) -> None

total(= 0.0)

Total dissipated energy (sum of the terms below)

[type: Real]

visco(= 0.0)

Energy dissipated by viscous effects.

[type: Real]

plast(= 0.0)

Energy dissipated by plastic effects.

[type: Real]

PelletMatState

ObjectMatStatePelletMatState

class woo.dem.PelletMatState(*args, **kwargs)

Hold dissipated energy data for this particles, to evaluate wear.

Overloaded function.

  1. __init__(self: woo.dem.PelletMatState) -> None

  2. __init__(self: woo.dem.PelletMatState, *args, **kwargs) -> None

normPlast(= 0.0)

Plastic energy dissipated in the normal sense

[type: Real]

shearPlast(= 0.0)

Plastic energy dissipated in the tangential sense

[type: Real]

agglomRate(= nan)

Agglomeration speed

[type: Real]

stepAgglomUpdated(= -1)

Step in which the agglomeration speed was updated for the last time.

[type: long]

cumAgglomMass(= 0.0)

Cumulative mass agglomerated by this particle.

[type: Real]

cumAgglomAngle(= 0.0)

Cumulative length of rolling when agglomeration was active.

[type: Real]

InletMatState

ObjectMatStateInletMatState

class woo.dem.InletMatState(*args, **kwargs)

Hold dissipated energy data for this particles, to evaluate wear.

Overloaded function.

  1. __init__(self: woo.dem.InletMatState) -> None

  2. __init__(self: woo.dem.InletMatState, *args, **kwargs) -> None

timeNew(= -1.0)

Step at which this particle was created by the inlet.

[type: Real]

ClusterMatState

ObjectMatStateClusterMatState

class woo.dem.ClusterMatState(*args, **kwargs)

Hold cluster labels for each degree of connectivity.

Overloaded function.

  1. __init__(self: woo.dem.ClusterMatState) -> None

  2. __init__(self: woo.dem.ClusterMatState, *args, **kwargs) -> None

labels(= [])

Cluster label for 0,1,2,… connectivity.

[type: vector<int>]

ConcreteMatState

ObjectMatStateConcreteMatState

class woo.dem.ConcreteMatState(*args, **kwargs)

State information about body use by the concrete model. None of that is used for computation (at least not now), only for visualization and post-processing.

Overloaded function.

  1. __init__(self: woo.dem.ConcreteMatState) -> None

  2. __init__(self: woo.dem.ConcreteMatState, *args, **kwargs) -> None

numBrokenCohesive(= 0)

Number of (cohesive) contacts that damaged completely

[type: int]

Inlets & Outlets

TODO

Inlet

ObjectEnginePeriodicEngineInlet

digraph Inlet {
        rankdir=LR;
        margin=.2;
        "Inlet" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.Inlet"];
        "BoxInlet" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.Inlet"];
        "RandomInlet" -> "BoxInlet" [arrowsize=0.5,style="setlinewidth(0.5)"]           "BoxInlet2d" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.Inlet"];
        "BoxInlet" -> "BoxInlet2d" [arrowsize=0.5,style="setlinewidth(0.5)"]            "CylinderInlet" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.Inlet"];
        "RandomInlet" -> "CylinderInlet" [arrowsize=0.5,style="setlinewidth(0.5)"]              "ConveyorInlet" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.Inlet"];
        "Inlet" -> "ConveyorInlet" [arrowsize=0.5,style="setlinewidth(0.5)"]            "RandomInlet" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.Inlet"];
        "Inlet" -> "RandomInlet" [arrowsize=0.5,style="setlinewidth(0.5)"]              "ArcInlet" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.Inlet"];
        "RandomInlet" -> "ArcInlet" [arrowsize=0.5,style="setlinewidth(0.5)"]
}
class woo.dem.Inlet(*args, **kwargs)

Inlet generating new particles. This is an abstract base class which in itself does not generate anything, but provides some unified interface to derived classes.

Overloaded function.

  1. __init__(self: woo.dem.Inlet) -> None

  2. __init__(self: woo.dem.Inlet, *args, **kwargs) -> None

mask(= 5)

mask for new particles.

[type: int]

maxMass(= -1.0)

Mass at which the engine will not produce any particles (inactive if not positive)

[type: Real, unit: kg]

maxNum(= -1)

Number of generated particles after which no more will be produced (inactive if not positive)

[type: long]

doneHook(= '')

Python string to be evaluated when maxMass or maxNum have been reached (or with RandomInlet, maxAttempts were exhausted and RandomInlet.atMaxAttempts equals 'done'). The engine is made dead automatically even if doneHook is not specified.

[type: string]

mass(= 0.0)

Generated mass total

[type: Real, unit: kg]

num(= 0)

Number of generated particles

[type: long]

currRate(= nan)

Current value of mass flow rate

[type: Real, unit: kg/s, read-only in python]

zeroRateAtStop(= True)

When the generator stops (mass/number of particles reached, …), set currRate to zero immediately

[type: bool]

currRateSmooth(= 1.0)

Smoothing factor for currRate ∈〈0,1〉

[type: Real, range: 0−1]

glColor(= 0.0)

Color for rendering (nan disables rendering)

[type: Real, not shown in the UI]

minMaxDiam(self: woo.dem.Inlet)_wooEigen11.Vector2

RandomInlet

ObjectEnginePeriodicEngineInletRandomInlet

digraph RandomInlet {
        rankdir=LR;
        margin=.2;
        "RandomInlet" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.RandomInlet"];
        "ArcInlet" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.RandomInlet"];
        "RandomInlet" -> "ArcInlet" [arrowsize=0.5,style="setlinewidth(0.5)"]           "BoxInlet" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.RandomInlet"];
        "RandomInlet" -> "BoxInlet" [arrowsize=0.5,style="setlinewidth(0.5)"]           "BoxInlet2d" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.RandomInlet"];
        "BoxInlet" -> "BoxInlet2d" [arrowsize=0.5,style="setlinewidth(0.5)"]            "CylinderInlet" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.RandomInlet"];
        "RandomInlet" -> "CylinderInlet" [arrowsize=0.5,style="setlinewidth(0.5)"]
}
class woo.dem.RandomInlet(*args, **kwargs)

Inlet generating new particles. This class overrides woo.core.Engine.critDt, which in turn calls woo.dem.ParticleGenerator.critDt with all possible materials one by one.

Overloaded function.

  1. __init__(self: woo.dem.RandomInlet) -> None

  2. __init__(self: woo.dem.RandomInlet, *args, **kwargs) -> None

massRate(= nan)

Mass flow rate; if non-positive, keep generating and placing new particles until maxAttempts is exhausted and atMaxAttempts is used to decide what to do next.

[type: Real, unit: kg/s]

materials(= [])

Set of materials for new particles, randomly picked from

[type: vector<shared_ptr<Material>>]

matStates(= [])

Set of material states; when material is picked from materials, MatState at the same index is assigned to the particle; if it is None or matStates is shorter than requested index, no material state will be assigned.

[type: vector<shared_ptr<MatState>>]

generator(= None)

Particle generator instance

[type: shared_ptr<ParticleGenerator>]

shooter(= None)

Particle shooter instance (assigns velocities to generated particles. If not given, particles have zero velocities initially.

[type: shared_ptr<ParticleShooter>]

spatialBias(= None)

Make random position biased based on the radius of the current particle; if unset, distribute uniformly.

[type: shared_ptr<SpatialBias>]

maxAttempts(= 5000)

Maximum attempts to position new particles randomly, without collision. If 0, no limit is imposed. When reached, atMaxAttempts determines, what will be done. Each particle is tried maxAttempts/maxMetaAttempts times, then a new particle is tried.

[type: int]

attemptPar(= 5)

Number of trying a different particle to position (each will be tried maxAttempts/attemptPar times)

[type: int]

atMaxAttempts(= 0)

What to do when maxAttempts is reached.

[type: int, named enum, possible values are: ‘error’ (0), ‘dead’ (1), ‘warn’ (2), ‘silent’ (‘nothing’, ‘ignore’, ‘’; 3), ‘doneHook’ (‘done’; 4)]

padDist(= 0.0)

Pad geometry by this distance inside; random points will be chosen inside the shrunk geometry, whereas boxes will be validated in the larger one. This attribute must be set by the generator.

[type: Real, read-only in python]

kinEnergyIx(= -1)

Index for kinetic energy in scene.energy

[type: int, not saved, not accessible from python]

color(= nan)

Color for new particles (NaN for random; negative for keeping color assigned by the generator).

[type: Real]

stepGoalMass(= 0.0)

Mass to be attained in this step

[type: Real, read-only in python]

collideExisting(= True)

Consider collisions with pre-existing particle; this is generally a good idea, though if e.g. there are no pre-existing particles, it is useful to set to False to avoid having to define collider for no other reason than make RandomInlet happy.

[type: bool]

clear(self: woo.dem.RandomInlet)None
randomPosition(self: woo.dem.RandomInlet, arg0: float, arg1: float)_wooEigen11.Vector3
validateBox(self: woo.dem.RandomInlet, arg0: _wooEigen11.AlignedBox3)bool

ArcInlet

ObjectEnginePeriodicEngineInletRandomInletArcInlet

class woo.dem.ArcInlet(*args, **kwargs)

Inlet generating particles in prismatic arc (revolved rectangle) specified using cylindrical coordinates (with the ISO 31-11 convention, as mentioned at the Wikipedia page) in a local system.

Overloaded function.

  1. __init__(self: woo.dem.ArcInlet) -> None

  2. __init__(self: woo.dem.ArcInlet, *args, **kwargs) -> None

node(= <Node @ 0x1660ce0, at (0, 0, 0)>)

Node defining local coordinate system. Must be given.

[type: shared_ptr<Node>]

cylBox(= AlignedBox3((1.7976931348623157e308, 1.7976931348623157e308, 1.7976931348623157e308), (-1.7976931348623157e308, -1.7976931348623157e308, -1.7976931348623157e308)))

Box in cylindrical coordinates, as: (ρ₀,φ₀,z₀),(ρ₁,φ₁,z₁). ρ must be non-negative, (φ₁-φ₀)≤2π.

[type: AlignedBox3r]

glSlices(= 32)

Number of slices for rendering circle (the arc takes the proportionate value

[type: int]

CylinderInlet

ObjectEnginePeriodicEngineInletRandomInletCylinderInlet

class woo.dem.CylinderInlet(*args, **kwargs)

Generate particle inside an arbitrarily oriented cylinder.

Overloaded function.

  1. __init__(self: woo.dem.CylinderInlet) -> None

  2. __init__(self: woo.dem.CylinderInlet, *args, **kwargs) -> None

node(= None)

Node defining local coordinate system. If not given, global coordinates are used.

[type: shared_ptr<Node>]

height(= nan)

Height along the local \(x\)-axis.

[type: Real, unit: m]

radius(= nan)

Radius of the cylinder (perpendicular to the local \(x\)-axis).

[type: Real, unit: m]

glSlices(= 16)

Number of subdivision slices for rendering.

[type: int]

BoxInlet

ObjectEnginePeriodicEngineInletRandomInletBoxInlet

digraph BoxInlet {
        rankdir=LR;
        margin=.2;
        "BoxInlet" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.BoxInlet"];
        "BoxInlet2d" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.BoxInlet"];
        "BoxInlet" -> "BoxInlet2d" [arrowsize=0.5,style="setlinewidth(0.5)"]
}
class woo.dem.BoxInlet(*args, **kwargs)

Generate particle inside axis-aligned box volume.

Overloaded function.

  1. __init__(self: woo.dem.BoxInlet) -> None

  2. __init__(self: woo.dem.BoxInlet, *args, **kwargs) -> None

box(= AlignedBox3((nan, nan, nan), (nan, nan, nan)))

Box volume specification (lower and upper corners)

[type: AlignedBox3r]

node(= <Node @ 0x165a4f0, at (0, 0, 0)>)

Node defining local coordinate system (optional; if not given, global coordinates are used).

[type: shared_ptr<Node>]

BoxInlet2d

ObjectEnginePeriodicEngineInletRandomInletBoxInletBoxInlet2d

class woo.dem.BoxInlet2d(*args, **kwargs)

Generate particles inside axis-aligned plane (its normal axis is given via the axis attribute; particles are allowed to stick out of that plane.

Overloaded function.

  1. __init__(self: woo.dem.BoxInlet2d) -> None

  2. __init__(self: woo.dem.BoxInlet2d, *args, **kwargs) -> None

axis(= 2)

Axis normal to the plane in which particles are generated.

[type: short]

ConveyorInlet

ObjectEnginePeriodicEngineInletConveyorInlet

class woo.dem.ConveyorInlet(*args, **kwargs)

Inlet producing infinite band of particles from packing periodic in the x-direction. Clumps are fully supported.

Overloaded function.

  1. __init__(self: woo.dem.ConveyorInlet) -> None

  2. __init__(self: woo.dem.ConveyorInlet, *args, **kwargs) -> None

► Particles

material(= None)

Material for new particles

[type: shared_ptr<Material>]

spherePack(= None)

woo.pack.SpherePack object; when specified, centers, radii (and clumps, if clumps are contained) are discarded and will be computed from this SpherePack. The attribute is reset afterwards.

[type: shared_ptr<SpherePack>, not shown in the UI, not saved]

shapePack(= None)

Purely geomerical description of particles to be generated (will replace spherePack, centers, radii, clumps and cellLen in the future).

[type: shared_ptr<ShapePack>, not dumped]

zTrim(= False)

Trim packing from above so that the ratio of vel / packVel is as small as possible. Spheres/clumps will be discarded from above and this flag will be set to false once trimming is done (it will not be called again explicitly even if massRate or vel change.

[type: bool, not shown in the UI]

zTrimHt(= nan)

Height at which the packing was trimmed if zTrim was set.

[type: Real, not shown in the UI]

cellLen(= nan)

Length of the band cell, which is repeated periodically (if spherePack is given and is periodic, this value is deduced)

[type: Real, unit: m]

radii(= [])

Radii for the packing (if spherePack is given, radii are computed)

[type: vector<Real>, not shown in the UI, not dumped]

centers(= [])

Centers of spheres/clumps in the packing (if spherePack is given, centers are computed)

[type: vector<Vector3r>, not shown in the UI, not dumped]

clumps(= [])

Clump geometry, corresponding to each radii and centers. (if spherePack is given, clumps are computed)

[type: vector<shared_ptr<SphereClumpGeom>>, not shown in the UI, not dumped]

massRate(= nan)

Average mass flow rate; if given, vel is adjusted (if both are given, massRate takes precedence).

[type: Real, unit: kg/s]

vel(= nan)

Velocity of particles; if specified, massRate is adjusted (of both are given, such as in constructor, massRate has precedence and a warning is issued if the two don’t match)

[type: Real, unit: m/s]

packVel(= nan)

Velocity by which the packing is traversed and new particles emmited; always smaller than or equal to vel. Computed automatically.

[type: Real, unit: m/s, read-only in python]

relLatVel(= 0.0)

Relative velocity components lateral to vel (local x-axis); both components are assigned with uniform probability from range (-relLatVel*vel,+relLatVel*vel), at the moment the particle leaves the barrier layer.

[type: Real]

► Clipping

clipX(= [])

If given, clip the given packing from above by the given function \(z_max(x)\) given as piecewise-linear function in same-length arrays clipX and clipZ. If clipX is empty, no clipping is done.

[type: vector<Real>, unit: m]

clipZ(= [])

Z-coordinate (max sphere \(z\) coordinate), with points corresponding to clipX.

[type: vector<Real>, unit: m]

clipLastX(= 0.0)

X-coordinate of last-generated particles, for use with clipping (clipping may have different periodicity than the packing, this value can be different from lastX and wraps around cellLen.

[type: Real, read-only in python]

clipPos(= 0)

Internal variable for optimizing interpolation in clipX and clipZ.

[type: size_t, not shown in the UI, read-only in python]

► Tunables

startLen(= nan)

Band to be created at the very start; if NaN, only the usual starting amount is created (depending on feed velocity)

[type: Real]

barrierColor(= 0.2)

Color for barrier particles (NaN for random)

[type: Real]

color(= nan)

Color for non-barrier particles (NaN for random)

[type: Real]

barrierLayer(= -3.0)

Some length of the last part of new particles has all DoFs blocked, so that when new particles are created, there are no sudden contacts in the band; in the next step, DoFs in this layer are unblocked. If barrierLayer is negative, it is relative to the maximum radius in the given packing, and is automatically set to the correct value at the first run

[type: Real]

movingBedZ(= nan)

If given, particles with z coordinate lower than this value will move indefinitely with the conveyor (contact velocity, blocked DOFs), technically not added to the barrier at all.

[type: Real]

movingBedColor(= 0.5)

Color for particles selected with movingBedZ (NaN for random).

[type: Real]

save(= True)

Save generated particles so that PSD can be generated afterwards

[type: bool]

matState(= False)

Endow new particles with InletMatState (for tracking when a particular particle was created and similar.

[type: bool]

► Bookkeeping

nextIx(= -1)

Index of last-generated particles in the packing

[type: int, read-only in python]

lastX(= 0.0)

X-coordinate of last-generated particles in the packing

[type: Real, read-only in python]

barrier(= [])

Nodes which make up the barrier and will be unblocked once they leave barrierLayer.

[type: list<shared_ptr<Node>>, not accessible from python]

node(= <Node @ 0x17864b0, at (0, 0, 0)>)

Position and orientation of the factory; local x-axis is the feed direction.

[type: shared_ptr<Node>]

streamBeginNode(= None)

Node at which the particle stream will start, which can be moving during the simulation without disrupting stream continuity. It is the position of this node, projected onto \(x\)-axis of node, which is relevant.

[type: shared_ptr<Node>]

barrierImpose(= None)

Imposition which is used for barrier nodes, as long as they are in the barrier.

[type: shared_ptr<Impose>]

xDebt(= 0.0)

Length of packing which was not covered in the last step due to streamBeginNode offset.

[type: Real, not shown in the UI, read-only in python]

initSortLimit(= 200)

Limit of number of particles generated in a single step above which woo.dem.InsertionSortCollider.forceInitSort will be set (only useful if InsertionSortCollider is actually used).

[type: int]

avgRate(= nan)

Average feed rate (computed from Material density, packing and and vel

[type: Real, unit: kg/s, read-only in python]

kinEnergyIx(= -1)

Index for kinetic energy in scene.energy

[type: int, not saved, not accessible from python]

genDiamMassTime(= [])

List of generated diameters, masses and times (for making granulometry)

[type: vector<Vector3r>, not shown in the UI, not dumped, read-only in python]

clear(self: woo.dem.ConveyorInlet)None
diamMass(self: woo.dem.ConveyorInlet, zipped: bool = False)object

Return masses and diameters of generated particles. With zipped, return list of (diameter, mass); without zipped, return tuple of 2 arrays, diameters and masses.

massOfDiam(self: woo.dem.ConveyorInlet, min: float = 0, max: float = inf)float

Return mass of particles of which diameters are between min and max.

psd(self: woo.dem.ConveyorInlet, mass: bool = True, cumulative: bool = True, normalize: bool = False, dRange: _wooEigen11.Vector2 = Vector2(nan, nan), tRange: _wooEigen11.Vector2 = Vector2(nan, nan), num: int = 80)object

Return PSD for particles generated.

ParticleGenerator

ObjectParticleGenerator

digraph ParticleGenerator {
        rankdir=LR;
        margin=.2;
        "ParticleGenerator" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.ParticleGenerator"];
        "PharmaCapsuleGenerator" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.ParticleGenerator"];
        "ParticleGenerator" -> "PharmaCapsuleGenerator" [arrowsize=0.5,style="setlinewidth(0.5)"]               "MinMaxSphereGenerator" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.ParticleGenerator"];
        "ParticleGenerator" -> "MinMaxSphereGenerator" [arrowsize=0.5,style="setlinewidth(0.5)"]                "PsdClumpGenerator" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.ParticleGenerator"];
        "PsdSphereGenerator" -> "PsdClumpGenerator" [arrowsize=0.5,style="setlinewidth(0.5)"]           "PsdCapsuleGenerator" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.ParticleGenerator"];
        "PsdSphereGenerator" -> "PsdCapsuleGenerator" [arrowsize=0.5,style="setlinewidth(0.5)"]         "PsdSphereGenerator" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.ParticleGenerator"];
        "ParticleGenerator" -> "PsdSphereGenerator" [arrowsize=0.5,style="setlinewidth(0.5)"]           "PsdEllipsoidGenerator" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.ParticleGenerator"];
        "PsdSphereGenerator" -> "PsdEllipsoidGenerator" [arrowsize=0.5,style="setlinewidth(0.5)"]
}
class woo.dem.ParticleGenerator(*args, **kwargs)

Abstract class for generating particles

Overloaded function.

  1. __init__(self: woo.dem.ParticleGenerator) -> None

  2. __init__(self: woo.dem.ParticleGenerator, *args, **kwargs) -> None

genDiamMassTime(= [])

List of generated particle’s (equivalent) radii and masses (for making granulometry)

[type: vector<Vector3r>, not shown in the UI, not dumped, read-only in python]

save(= True)

Save generated particles so that PSD can be generated afterwards

[type: bool]

__call__(self: woo.dem.ParticleGenerator, mat: woo.dem.Material, time: float = 0)tuple

Call the generation routine, returning one particle (at origin) and its bounding-box when at origin. Useful for debugging.

clear(self: woo.dem.ParticleGenerator)None

Clear stored data about generated particles; only subsequently generated particles will be considered in the PSD.

critDt(self: woo.dem.ParticleGenerator, density: float, young: float)float

Return critical timestep for particles generated by us, given that their density and Young’s modulus are as given in arguments.

diamMass(self: woo.dem.ParticleGenerator, zipped: bool = False)object

With zipped, return list of (diameter, mass); without zipped, return tuple of 2 arrays, diameters and masses.

massOfDiam(self: woo.dem.ParticleGenerator, min: float = 0, max: float = inf)float

Return mass of particles of which diameters are between min and max.

minMaxDiam(self: woo.dem.ParticleGenerator)_wooEigen11.Vector2

Return the range of minimum and maximum diameters.

padDist(self: woo.dem.ParticleGenerator)float

Return padding distance by which the factory geometry should be shrunk before generating a random point.

psd(self: woo.dem.ParticleGenerator, mass: bool = True, cumulative: bool = True, normalize: bool = True, dRange: _wooEigen11.Vector2 = Vector2(nan, nan), tRange: _wooEigen11.Vector2 = Vector2(nan, nan), num: int = 80)object

Return PSD for particles generated.

PharmaCapsuleGenerator

ObjectParticleGeneratorPharmaCapsuleGenerator

class woo.dem.PharmaCapsuleGenerator(*args, **kwargs)

Generate pharmaceutical capsules of fixed size; they consist of body and cap. two caps of differing diameter and are thus represented as two interpenetrated (clumped) capsules. The default value corresponds to Human Cap Size 1 from Torpac <http://www.torpac.com>.

Overloaded function.

  1. __init__(self: woo.dem.PharmaCapsuleGenerator) -> None

  2. __init__(self: woo.dem.PharmaCapsuleGenerator, *args, **kwargs) -> None

len(= 0.0194)

Total (locked) length of the capsule.

[type: Real]

capLen(= 0.00978)

Cut length of the cap.

[type: Real]

extDiam(= Vector2(0.00691, 0.00663))

External diameter of the cap and the body.

[type: Vector2r]

colors(= Vector2(0.5, 0.99))

Color of body and cap; white and red with the default (coolwarm) colormap.

[type: Vector2r]

cutCorr(= 0.5)

Make the cap shorter by this amount relative to the area of outer cap over the inner cap; this is to compensate for the approximation that the cap is not cut sharply.

[type: Real]

MinMaxSphereGenerator

ObjectParticleGeneratorMinMaxSphereGenerator

class woo.dem.MinMaxSphereGenerator(*args, **kwargs)

Generate particles with given minimum and maximum radius

Overloaded function.

  1. __init__(self: woo.dem.MinMaxSphereGenerator) -> None

  2. __init__(self: woo.dem.MinMaxSphereGenerator, *args, **kwargs) -> None

dRange(= Vector2(nan, nan))

Minimum and maximum diameters of generated spheres.

[type: Vector2r]

PsdSphereGenerator

ObjectParticleGeneratorPsdSphereGenerator

digraph PsdSphereGenerator {
        rankdir=LR;
        margin=.2;
        "PsdSphereGenerator" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.PsdSphereGenerator"];
        "PsdEllipsoidGenerator" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.PsdSphereGenerator"];
        "PsdSphereGenerator" -> "PsdEllipsoidGenerator" [arrowsize=0.5,style="setlinewidth(0.5)"]               "PsdClumpGenerator" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.PsdSphereGenerator"];
        "PsdSphereGenerator" -> "PsdClumpGenerator" [arrowsize=0.5,style="setlinewidth(0.5)"]           "PsdCapsuleGenerator" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.PsdSphereGenerator"];
        "PsdSphereGenerator" -> "PsdCapsuleGenerator" [arrowsize=0.5,style="setlinewidth(0.5)"]
}
class woo.dem.PsdSphereGenerator(*args, **kwargs)

Generate spherical particles following a given Particle Size Distribution (PSD)

Overloaded function.

  1. __init__(self: woo.dem.PsdSphereGenerator) -> None

  2. __init__(self: woo.dem.PsdSphereGenerator, *args, **kwargs) -> None

discrete(= False)

The points on the PSD curve will be interpreted as the only allowed diameter values; if false, linear interpolation between them is assumed instead. Do not change once the generator is running.

[type: bool]

psdPts(= [])

Points of the PSD curve; the first component is particle diameter [m] (not radius!), the second component is passing percentage. Both diameter and passing values must be increasing (diameters must be strictly increasing). Passing values are normalized so that the last value is 1.0 (therefore, you can enter the values in percents if you like).

[type: vector<Vector2r>, units: [m,-]]

mass(= True)

PSD has mass percentages; if false, number of particles percentages are assumed. Do not change once the generator is running.

[type: bool]

weightPerBin(= [])

Keep track of mass/number of particles for each point on the PSD so that we get as close to the curve as possible. Only used for discrete PSD.

[type: vector<Real>, not shown in the UI, not dumped, read-only in python]

weightTotal(= 0.0)

Total mass (number, with discrete) of of particles generated.

[type: Real, not shown in the UI, not dumped, read-only in python]

inputPsd(self: woo.dem.PsdSphereGenerator, normalize: bool = True, cumulative: bool = True, num: int = 80)tuple

Return input PSD; it will be a staircase function if discrete is true, otherwise linearly interpolated. With normalize, the maximum is equal to 1.; otherwise, the curve is multiplied with the actually generated mass/numer of particles (depending on whether mass is true or false); the result should then be very similar to the woo.dem.ParticleGenerator.psd output with actually generated spheres. Discrete non-cumulative PSDs are handled specially: discrete distributions return skypline plot with peaks represented as plateaus of the relative width 1/num; continuous distributions return ideal histogram computed for relative bin with 1/num; thus returned histogram will match non-cummulative histogram returned by ParticleGenerator.psd(cumulative=False), provided num is the same in both cases.

Todo

with cumulative=False and when the PSD does not \(x\)-start at 0, the plot is not correct as the hump coming from the jump in the PSD (from 0 to non-zero at the left) is not taken in account.

PsdEllipsoidGenerator

ObjectParticleGeneratorPsdSphereGeneratorPsdEllipsoidGenerator

class woo.dem.PsdEllipsoidGenerator(*args, **kwargs)

Generate ellipsoids following a given Particle Size Distribution; ratio of Ellipsoid.semiAxes is chosen randomly from the semiAxesRatio range; orientation is random.

Overloaded function.

  1. __init__(self: woo.dem.PsdEllipsoidGenerator) -> None

  2. __init__(self: woo.dem.PsdEllipsoidGenerator, *args, **kwargs) -> None

axisRatio2(= Vector2(0.5, 0.5))

Range for second semi-axis ratio.

[type: Vector2r]

axisRatio3(= Vector2(0.5, 0.5))

Range for third semi-axis ratio; if one of the coefficients is non-positive, the thirs semi-axis will be the same as the second one.

[type: Vector2r]

PsdCapsuleGenerator

ObjectParticleGeneratorPsdSphereGeneratorPsdCapsuleGenerator

class woo.dem.PsdCapsuleGenerator(*args, **kwargs)

Generate capsules following a given Particle Size Distribution; elongation is chosen randomly using shaftRadiusRatio; orientation is random.

Overloaded function.

  1. __init__(self: woo.dem.PsdCapsuleGenerator) -> None

  2. __init__(self: woo.dem.PsdCapsuleGenerator, *args, **kwargs) -> None

shaftRadiusRatio(= Vector2(0.5, 1.5))

Range for shaft / radius; the ratio is selected uniformly from this range.

[type: Vector2r]

PsdClumpGenerator

ObjectParticleGeneratorPsdSphereGeneratorPsdClumpGenerator

class woo.dem.PsdClumpGenerator(*args, **kwargs)

Generate clump particles following a given Particle Size Distribution (psd) and selection of clump shapes, using the woo.dem.SphereClumpGeom.scaleProb function.

For example, with psd=[(.1, 0), (.2, .7), (.4, 1.)], the PSD function (which is a cumulative distribution function) looks like

Figure made with TikZ

while the probability density function is

Figure made with TikZ

Now suppose three clumps are given with scaleProb as:

[(.1, 1), (.3, 0)]   # for d>.3, the leftmost value (0) is used
[(.2, .1) ]          # value extends to both left and right with just one point
[(.2, 0), (.4, .6)]  # for d<.2, the rightmost value (0) is used

which define the following piecewise-linear probability functions

Figure made with TikZ

For every diameter \(d\) chosen according to the PSD, values of scaleProb functions are found in \(d\) and used to choose which clump to create. The PDF for diameter combined with clumps probabilities then gives the following probability:

Figure made with TikZ

Selected clump configuration is scaled to \(d\) (using its equivRad).

Overloaded function.

  1. __init__(self: woo.dem.PsdClumpGenerator) -> None

  2. __init__(self: woo.dem.PsdClumpGenerator, *args, **kwargs) -> None

clumps(= [])

Sequence of clump geometry definitions (SphereClumpGeom); for every selected radius from the PSD, clump will be chosen based on the SphereClumpGeom.scaleProb function and scaled to that radius.

[type: vector<shared_ptr<SphereClumpGeom>>]

scaleMethod(= 0)

Method to compute clump scaling. The default uses the equivalent radius to determine scaling to fulfill prescribed PSD. Other methods are to scale according to the radius of the first sphere in the clump, or according to the average sphere radius in the clump.

[type: int, named enum, possible values are: ‘equiv’ (‘equivRad’; 0), ‘firstSphere’ (1), ‘avgSphere’ (2)]

genClumpNo(= [])

If save is set, keeps clump numbers (indices in clumps for each generated clump.

[type: vector<int>, not shown in the UI, read-only in python]

oris(= [])

Base orientations for clumps, in the same order as clumps. If the sequence is shorter than selected clump configuration, its orientation will be completely random.

[type: vector<Quaternionr>]

oriFuzz(= [])

Fuzz (in radians) for orientation, if set based on oris; if oriFuzz is shorter than clump configuration in question, the base orientation (oriFuzz) is used as-is. Random orientation axis is picked first, then rotation angle is taken from 〈-oriFuzz[i],+oriFuzz[i]〉 with uniform probability. Note: this simple algorithm does not generate completely homogeneous probability density in the rotation space.

[type: vector<Real>]

SpatialBias

ObjectSpatialBias

digraph SpatialBias {
        rankdir=LR;
        margin=.2;
        "SpatialBias" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.SpatialBias"];
        "NonuniformAxisPlacementBias" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.SpatialBias"];
        "SpatialBias" -> "NonuniformAxisPlacementBias" [arrowsize=0.5,style="setlinewidth(0.5)"]                "AxialBias" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.SpatialBias"];
        "SpatialBias" -> "AxialBias" [arrowsize=0.5,style="setlinewidth(0.5)"]          "LayeredAxialBias" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.SpatialBias"];
        "AxialBias" -> "LayeredAxialBias" [arrowsize=0.5,style="setlinewidth(0.5)"]             "PsdAxialBias" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.SpatialBias"];
        "AxialBias" -> "PsdAxialBias" [arrowsize=0.5,style="setlinewidth(0.5)"]
}
class woo.dem.SpatialBias(*args, **kwargs)

Functor which biases random position (in unit cube) based on particle diameter, returning the biased position in unit cube. These objects are used with RandomInlet.spatialBias to make possible things like sptially graded distribution of random particles.

Overloaded function.

  1. __init__(self: woo.dem.SpatialBias) -> None

  2. __init__(self: woo.dem.SpatialBias, *args, **kwargs) -> None

unitPos(self: woo.dem.SpatialBias, diam: float)_wooEigen11.Vector3

Return biased position inside a unit cube (caller transforms this to cartesian coordinates in the simulation space.

AxialBias

ObjectSpatialBiasAxialBias

digraph AxialBias {
        rankdir=LR;
        margin=.2;
        "AxialBias" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.AxialBias"];
        "PsdAxialBias" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.AxialBias"];
        "AxialBias" -> "PsdAxialBias" [arrowsize=0.5,style="setlinewidth(0.5)"]         "LayeredAxialBias" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.AxialBias"];
        "AxialBias" -> "LayeredAxialBias" [arrowsize=0.5,style="setlinewidth(0.5)"]
}
class woo.dem.AxialBias(*args, **kwargs)

Bias position (within unit interval) along axis \(p\), so that radii are distributed along axis, as in \(p=\frac{d-d_0}{d_1-d_0}+f\left(a-\frac{1}{2}\right)\), where \(f\) is the fuzz, \(a\) is unit random number, \(d\) is the current particle diameter and \(d_0\) and \(d_1\) are diameters at the lower and upper end (d01). \(p\) is clamped to \(\rangle0,1\langle\) after the computation.

Overloaded function.

  1. __init__(self: woo.dem.AxialBias) -> None

  2. __init__(self: woo.dem.AxialBias, *args, **kwargs) -> None

axis(= 0)

Axis which is biased.

[type: int]

d01(= Vector2(nan, nan))

Diameter at the lower and upper end (the order matters); it is possible that \(r_0>r_1\), in which case the bias is reversed (bigger radii have smaller coordinate).

[type: Vector2r]

fuzz(= 0.0)

Allow for random variations around the position determined from diameter.

[type: Real]

phase(= nan)

If NaN, coordinate after fuzz will be clamped to 0…1. If a number, it will be added to the coordinate after fuzz (zero is allowed) and the value will be modulated to 0…1 (rather than clamped), overflowing between beginning and end.

[type: float]

PsdAxialBias

ObjectSpatialBiasAxialBiasPsdAxialBias

class woo.dem.PsdAxialBias(*args, **kwargs)

Bias position based on PSD curve, so that fractions get the amount of space they require according to their percentage. The PSD must be specified with mass fractions, using With discrete (suitable for use with PsdParticleGenerator.discrete), the whole interval between the current and previous radius will be used with uniform probability, allowing for layered particle arangement. The d01 attribute is ignored with PSD.

Overloaded function.

  1. __init__(self: woo.dem.PsdAxialBias) -> None

  2. __init__(self: woo.dem.PsdAxialBias, *args, **kwargs) -> None

psdPts(= [])

Points of the mapping function, similar to PsdParticleGenerator.psdPts.

[type: vector<Vector2r>]

invert(= False)

Reverse the ordering along the axis, which makes the bigger particles be close to zero.

[type: bool]

discrete(= False)

Interpret psdPts as piecewise-constant (rather than piecewise-linear) function. Each diameter will be distributed uniformly in the whole interval between percentage of the current and previous points.

[type: bool]

reorder(= [])

Reorder the PSD fractions; this is mainly useful for discrete distributions, where the order can be non-increasing, such as with reorder=[1,0,2] which will put the finest fraction in the middle of the other two

[type: vector<int>]

LayeredAxialBias

ObjectSpatialBiasAxialBiasLayeredAxialBias

class woo.dem.LayeredAxialBias(*args, **kwargs)

Bias position so that particles occupy different layers based on their diameter. This is similar to PsdAxialBias with discrete, but allows for more flexibility, such as one fraction occupying multiple non-adjacent layers.

Overloaded function.

  1. __init__(self: woo.dem.LayeredAxialBias) -> None

  2. __init__(self: woo.dem.LayeredAxialBias, *args, **kwargs) -> None

layerSpec(= [])

Vector specifying layering; each item contains the following numbers: dMin, dMax, xMin0, xMax0, xMin1, xMax1, .... A particle which falls within dMin, dMax will be placed, with uniform probability, into intervals specified by other couples. Coordinates are given in normalized space, so xMin..xMax must lie in in 〈0,1〉. Particles which do not fall into any fraction will not be biased (thus placed uniformly randomly), and a warning will be issued.

[type: vector<VectorXr>]

xRangeSum(= [])

Sum of xMax_i-xMin_i for each fraction, for faster lookup. Internal/debugging use only.

[type: vector<Real>, not shown in the UI, not dumped, not saved, read-only in python]

NonuniformAxisPlacementBias

ObjectSpatialBiasNonuniformAxisPlacementBias

class woo.dem.NonuniformAxisPlacementBias(*args, **kwargs)

Distribute particle placement probability non-uniformly along given axis, following a piecewise-linear probability density function.

Overloaded function.

  1. __init__(self: woo.dem.NonuniformAxisPlacementBias) -> None

  2. __init__(self: woo.dem.NonuniformAxisPlacementBias, *args, **kwargs) -> None

axis(= 0)

Biased axis.

[type: int]

pdf(= [])

Probability density function values, on uniform grid spanning the axis unit range. If given, integrated numerically (trapezoid integration) to obtain cdf (which is normalized).

[type: vector<Real>]

cdf(= [])

Cumulative distribution function, either given directly, or computed from pdf, on uniform grid on unit range. Automatically normalized so that it ends at unity.

[type: vector<Real>]

dx(= nan)

Precomputed value of step size.

[type: Real, not shown in the UI, not dumped, read-only in python]

ParticleShooter

ObjectParticleShooter

digraph ParticleShooter {
        rankdir=LR;
        margin=.2;
        "ParticleShooter" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.ParticleShooter"];
        "AlignedMinMaxShooter" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.ParticleShooter"];
        "ParticleShooter" -> "AlignedMinMaxShooter" [arrowsize=0.5,style="setlinewidth(0.5)"]           "ArcShooter" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.ParticleShooter"];
        "ParticleShooter" -> "ArcShooter" [arrowsize=0.5,style="setlinewidth(0.5)"]
}
class woo.dem.ParticleShooter(*args, **kwargs)

Abstract class for assigning initial velocities to generated particles.

Overloaded function.

  1. __init__(self: woo.dem.ParticleShooter) -> None

  2. __init__(self: woo.dem.ParticleShooter, *args, **kwargs) -> None

AlignedMinMaxShooter

ObjectParticleShooterAlignedMinMaxShooter

class woo.dem.AlignedMinMaxShooter(*args, **kwargs)

Shoot particles in one direction, with velocity magnitude constrained by vRange values

Overloaded function.

  1. __init__(self: woo.dem.AlignedMinMaxShooter) -> None

  2. __init__(self: woo.dem.AlignedMinMaxShooter, *args, **kwargs) -> None

dir(= Vector3(1, 0, 0))

Direction (will be normalized).

[type: Vector3r]

vRange(= Vector2(nan, nan))

Minimum and maximum velocities.

[type: Vector2r]

ArcShooter

ObjectParticleShooterArcShooter

class woo.dem.ArcShooter(*args, **kwargs)

Shoot particles in direction defined by (normally-distributed) angles from tangent and base plane (cylindrical coordinates defined by node) in given point, with magnitude constraind by vRange.

Overloaded function.

  1. __init__(self: woo.dem.ArcShooter) -> None

  2. __init__(self: woo.dem.ArcShooter, *args, **kwargs) -> None

node(= <Node @ 0x1661ee0, at (0, 0, 0)>)

Node defining local coordinate system. Must be given.

[type: shared_ptr<Node>]

elevRange(= Vector2(0, 0))

Range for elevation from the plane perpendicular to the local \(z\)-axis (as defined by node). The actual value is chosen with uniform probability from this range.

[type: Vector2r, unit: rad]

azimRange(= Vector2(0, 0))

Range for azimuth angle, where zero is radial connecting particle position and local origin (node) and positive sense defined as rotation around the node \(z\)-axis.

[type: Vector2r, unit: rad]

vRange(= Vector2(nan, nan))

Range for velocity magnitude.

[type: Vector2r, unit: m/s]

Outlet

ObjectEnginePeriodicEngineOutlet

digraph Outlet {
        rankdir=LR;
        margin=.2;
        "Outlet" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.Outlet"];
        "StackedBoxOutlet" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.Outlet"];
        "BoxOutlet" -> "StackedBoxOutlet" [arrowsize=0.5,style="setlinewidth(0.5)"]             "BoxOutlet" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.Outlet"];
        "Outlet" -> "BoxOutlet" [arrowsize=0.5,style="setlinewidth(0.5)"]               "ArcOutlet" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.Outlet"];
        "Outlet" -> "ArcOutlet" [arrowsize=0.5,style="setlinewidth(0.5)"]
}
class woo.dem.Outlet(*args, **kwargs)

Delete/mark particles which fall outside (or inside, if inside is True) given box. Deleted/mark particles are optionally stored in the diamMassTime array for later processing, if needed.

Particle are deleted when markMask is 0, otherwise they are only marked with markMask and not deleted.

Overloaded function.

  1. __init__(self: woo.dem.Outlet) -> None

  2. __init__(self: woo.dem.Outlet, *args, **kwargs) -> None

markMask(= 0)

When non-zero, switch to marking mode – particles of which Particle.mask does not comtain markMask (i.e. (mask&markMask)!=markMask) have markMask bit-added to Particle.mask (this can happen only once for each particle); particles are not deleted, but their diameter/mass added to diamMassTime if save is True.

[type: uint]

mask(= 4)

If non-zero, only particles matching the mask will be candidates for removal

[type: uint]

inside(= False)

Delete particles which fall inside the volume rather than outside

[type: bool]

save(= False)

Save particle data which are deleted in the diamMassTime list

[type: bool]

recoverRadius(= False)

Recover radius of Spheres by computing it back from particle’s mass and its material density (used when radius is changed due to radius thinning (in Law2_L6Geom_PelletPhys_Pellet.thinningFactor). When radius is recovered, the \(r/r_0\) ratio is added to rDivR0 for further processing.

[type: bool]

rDivR0(= [])

List of the \(r/r_0\) ratio of deleted particles, when recoverRadius is true.

[type: vector<Real>, not shown in the UI, not dumped, read-only in python]

diamMassTime(= [])

Radii and masses of deleted particles; not accessible from python (shadowed by the diamMassTime method).

[type: vector<Vector3r>, not accessible from python]

locs(= [])

Integer location specified for particles; -1 by default, derived classes can use this for any purposes (usually more precise location within the outlet volume).

[type: vector<int>, not shown in the UI, not dumped, read-only in python]

num(= 0)

Number of deleted particles

[type: int, read-only in python]

savePar(= False)

Save particles as objects in par

[type: bool]

par(= _8ParticleList[])

Deleted particles (only saved with savePar.

[type: vector<shared_ptr<Particle>>, not shown in the UI, not dumped, read-only in python]

mass(= 0.0)

Total mass of deleted particles

[type: Real, read-only in python]

glColor(= 0.0)

Color for rendering (NaN disables rendering)

[type: Real]

glHideZero(= False)

Show numbers (mass and rate) even if they are zero.

[type: bool]

currRate(= nan)

Current value of mass flow rate

[type: Real, read-only in python]

currRateSmooth(= 1.0)

Smoothing factor for currRate ∈〈0,1〉

[type: Real, range: 0−1]

kinEnergyIx(= -1)

Index for kinetic energy in scene.energy

[type: int, not saved, not accessible from python]

clear(self: woo.dem.Outlet)None

Clear information about saved particles (particle list, if saved, mass and number, rDivR0)

diamMass(self: woo.dem.Outlet, zipped: bool = False)object

With zipped, return list of (diameter, mass); without zipped, return tuple of 2 arrays, diameters and masses.

massOfDiam(self: woo.dem.Outlet, min: float = 0, max: float = inf)float

Return mass of particles of which diameters are between min and max.

psd(self: woo.dem.Outlet, mass: bool = True, cumulative: bool = True, normalize: bool = True, num: int = 80, dRange: _wooEigen11.Vector2 = Vector2(nan, nan), tRange: _wooEigen11.Vector2 = Vector2(nan, nan), zip: bool = False, emptyOk: bool = False, locs: list = [])object

Return particle size distribution of deleted particles (only useful with save), spaced between dRange (a 2-tuple of minimum and maximum radius); )

BoxOutlet

ObjectEnginePeriodicEngineOutletBoxOutlet

digraph BoxOutlet {
        rankdir=LR;
        margin=.2;
        "BoxOutlet" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.BoxOutlet"];
        "StackedBoxOutlet" [shape="box",fontsize=8,style="setlinewidth(0.5),solid",height=0.2,URL="woo.dem.html#woo.dem.BoxOutlet"];
        "BoxOutlet" -> "StackedBoxOutlet" [arrowsize=0.5,style="setlinewidth(0.5)"]
}
class woo.dem.BoxOutlet(*args, **kwargs)

Outlet with box geometry

Overloaded function.

  1. __init__(self: woo.dem.BoxOutlet) -> None

  2. __init__(self: woo.dem.BoxOutlet, *args, **kwargs) -> None

box(= AlignedBox3((1.7976931348623157e308, 1.7976931348623157e308, 1.7976931348623157e308), (-1.7976931348623157e308, -1.7976931348623157e308, -1.7976931348623157e308)))

Box volume specification (lower and upper corners). If node is specified, the box is in local coordinates; otherwise, global coorinates are used.

[type: AlignedBox3r]

node(= None)

Node specifying local coordinates; if not given box is in global coords.

[type: shared_ptr<Node>]

StackedBoxOutlet

ObjectEnginePeriodicEngineOutletBoxOutletStackedBoxOutlet

class woo.dem.StackedBoxOutlet(*args, **kwargs)

Box outlet with subdivision along one axis, so that more precise location can be obtained; this is functionally equivalent to multiple adjacent BoxOutlet's, but faster since it is a single engine.

Overloaded function.

  1. __init__(self: woo.dem.StackedBoxOutlet) -> None

  2. __init__(self: woo.dem.StackedBoxOutlet, *args, **kwargs) -> None

divs(= [])

Coordinates of division between boxes in the stack; must be an increasing sequence.

[type: vector<Real>]

divColors(= [])

Colors for rendering the dividers; if not given, use darkened color, same for all dividers.

[type: vector<Real>]

axis(= 0)

Axis along which the box is subdivided.

[type: short]

loc0(= 0)

Index at which numbering of boxes starts. The first box is 0 by default, but it can be changed using this attribute, e.g. setting loc0=10 will make the first box 10, second 11 etc.

[type: int]

ArcOutlet

ObjectEnginePeriodicEngineOutletArcOutlet

class woo.dem.ArcOutlet(*args, **kwargs)

Outlet detnig/marking particles in prismatic arc (revolved rectangle) specified using cylindrical coordinates (with the ISO 31-11 convention, as mentioned at the Wikipedia page) in a local system. See also analogous ArcInlet.

Overloaded function.

  1. __init__(self: woo.dem.ArcOutlet) -> None

  2. __init__(self: woo.dem.ArcOutlet, *args, **kwargs) -> None

node(= <Node @ 0x1699ca0, at (0, 0, 0)>)

Node defining local coordinates system. Must be given.

[type: shared_ptr<Node>]

cylBox(= AlignedBox3((1.7976931348623157e308, 1.7976931348623157e308, 1.7976931348623157e308), (-1.7976931348623157e308, -1.7976931348623157e308, -1.7976931348623157e308)))

Box in cylindrical coordinates, as: (ρ₀,φ₀,z₀),(ρ₁,φ₁,z₁). ρ must be non-negative, (φ₁-φ₀)≤2π.

[type: AlignedBox3r]

glSlices(= 32)

Number of slices for rendering circle (the arc takes the proportionate value

[type: int]

DetectSteadyState

ObjectEnginePeriodicEngineDetectSteadyState

class woo.dem.DetectSteadyState(*args, **kwargs)

Detect steady state from summary flows of relevant inlets (total influx) and outlets (total efflux), plus waiting times in-between.The detection is done is several stages:

  1. (init) wait for waitInit before doing anything else;

  2. (flow) execute hookFlow, check if \(\sum_i o_i \geq \alpha \sum_j i_j\) (\(\alpha\) is relFlow); if true, proto-steady state was reached and we proceed;

  3. (trans) execute hookTrans, then wait for waitTrans, then proceed to the next stage;

  4. (steady) executed hookSteady, then wait for waitSteady, then proceed;

  5. (done) execute hookDone and do nothing more.

Overloaded function.

  1. __init__(self: woo.dem.DetectSteadyState) -> None

  2. __init__(self: woo.dem.DetectSteadyState, *args, **kwargs) -> None

waitInit(= 0.0)

Time to wait in init stage, before moving to flow.

[type: Real, unit: s]

relFlow(= 1.0)

Relative flow used for comparing influx and efflux in the flow stage.

[type: Real, unit: s]

waitTrans(= 0.0)

Time to wait in trans stage, before moving to steady.

[type: Real, unit: s]

waitSteady(= 0.0)

Time to wait in the steady stage, before moving to done.

[type: Real, unit: s]

hookFlow(= '')

Hook executed when the flow stage is entered.

[type: string]

hookTrans(= '')

Hook executed when the trans stage is entered.

[type: string]

hookSteady(= '')

Hook executed when the steady stage is entered.

[type: string]

hookDone(= 'e.dead=True')

Hook executed when the done stage is entered.

[type: string]

rateSmooth(= 1.0)

Smoothing factor for rates ∈〈0,1〉

[type: Real, range: 0−1]

stage(= 0)

Stage in which we currently are.

[type: int, read-only in python, named enum, possible values are: ‘init’ (0), ‘flow’ (1), ‘trans’ (2), ‘steady’ (3), ‘done’ (4)]

stageEntered(= 0.0)

Time when the current stage was entered.

[type: Real, unit: s, read-only in python]

inlets(= [])

Inlets of which rates are used to compute summary influx.

[type: vector<shared_ptr<Inlet>>]

outlets(= [])

Inlets of which rates are used to compute summary efflux.

[type: vector<shared_ptr<Outlet>>]

influx(= nan)

Smoothed summary influx value.

[type: Real, read-only in python]

efflux(= nan)

Smoothed summary efflux value.

[type: Real, read-only in python]

property stageNum

Return the current stage as numerical value (useful for plotting).

DEM field

TODO

DemField

ObjectFieldDemField

class woo.dem.DemField(*args, **kwargs)

Field describing a discrete element assembly. Each particle references (possibly many) nodes.

Special constructor

When passed the par parameter in constructor, this sequence of particles will be assigned to particles and nodes created as with S.dem.add. An additional optional parameter parNodes will be passed as nodes to S.dem.add(...,nodes=...) to determine which nodes are to be added.

Overloaded function.

  1. __init__(self: woo.dem.DemField) -> None

  2. __init__(self: woo.dem.DemField, *args, **kwargs) -> None

particles(= <ParticleContainer @ 0x16a5640>)

Particles (each particle holds its contacts, and references associated nodes)

[type: shared_ptr<ParticleContainer>, read-only in python]

contacts(= <ContactContainer @ 0x16a5860>)

Linear view on particle contacts

[type: shared_ptr<ContactContainer>, read-only in python]

loneMask(= 2)

Particle groups which have bits in loneMask in common (i.e. (A.mask & B.mask & loneMask)!=0) will not have contacts between themselves

[type: uint]

gravity(= Vector3(0, 0, 0))

Constant gravity acceleration

[type: Vector3r]

distFactor(= -1.0)

Relative enlargement of bounding boxes, and of radii in contacts; only supported by a few functors (Bo1_Sphere_Aabb, Cg2_Sphere_Sphere_L6Geom), storing the value in DemField ensures the values are synchronized between all functors interested. Deactivated if negative; any negative value (-1 by default) is equivalent to 1 (no enlargement at all).

[type: Real]

saveDead(= False)

Save unused nodes of deleted particles, which would be otherwise removed (useful for displaying traces of deleted particles).

[type: bool]

deadNodes(= NodeList[])

List of nodes belonging to deleted particles; only used if saveDead is True

[type: vector<shared_ptr<Node>>, not shown in the UI, read-only in python]

deadParticles(= _8ParticleList[])

Deleted particles; only used if saveDead is True

[type: vector<shared_ptr<Particle>>, not shown in the UI, read-only in python]

clearDead(self: woo.dem.DemField)None
collectNodes(self: woo.dem.DemField, fromCxx: bool = False)int

Collect nodes from all particles and clumps and insert them to nodes defined for this field. Nodes are not added multiple times, even if they are referenced from different particles.

property con

Linear view on particle contacts

static minimalEngines(damping=0.0, gravity=None, verletDist=- 0.05, kinSplit=False, dontCollect=False, noSlip=False, noBreak=False, cp2=None, law=None, model=None, collider='sap', grid=None, dynDtPeriod=100, cpKw={}, lawKw={})

Return default set of engines, suitable for basic simulations during testing.

nodesAppend(*args, **kwargs)

Overloaded function.

  1. nodesAppend(self: woo.dem.DemField, arg0: woo.core.Node) -> None

Append given node to nodes, and set DemData.linIx to the correct value automatically.

  1. nodesAppend(self: woo.dem.DemField, arg0: woo.core.NodeList) -> None

Append given list of nodes to nodes, and set DemData.linIx to the correct value automatically.

nodesAppendFromPar(self: woo.dem.DemField, arg0: std::vector<std::shared_ptr<Particle>, std::allocator<std::shared_ptr<Particle> > >)None

Append nodes of all particles given; nodes may repeat between particles (a set is created first), but nodes already in nodes before calling this method will cause an error.

property par

Particles (each particle holds its contacts, and references associated nodes)

static sceneGetField(arg0: woo.core.Scene)woo.dem.DemField
static sceneHasField(arg0: woo.core.Scene)bool
setNodesRefPos(self: woo.dem.DemField)None

Set reference position and orientation of all nodes to the current one; does nothing (silently) on builds without OpenGL.

splitNode(self: woo.dem.DemField, node: woo.core.Node, pars: std::vector<std::shared_ptr<Particle>, std::allocator<std::shared_ptr<Particle> > >, massMult: float = nan, inertiaMult: float = nan)woo.core.NodeList

For particles pars, replace their node node by a clone (deepcopy) of this node. If massMult and inertiaMult are given, mass/inertia of both original and cloned node are multiplied by those factors. Returns the original and the new node. Both nodes will be co-incident in space. This function is used to un-share node shared by multiple particles, such as when breaking mesh apart.

ContactContainer

ObjectContactContainer

class woo.dem.ContactContainer(*args, **kwargs)

Linear view on all contacts in the DEM field

Overloaded function.

  1. __init__(self: woo.dem.ContactContainer) -> None

  2. __init__(self: woo.dem.ContactContainer, *args, **kwargs) -> None

linView(= [])

Linear storage of references; managed by accessor methods, do not modify directly!

[type: ContainerT, not accessible from python]

dirty(= False)

Flag for notifying the collider that persistent data should be invalidated

[type: bool, not accessible from python]

stepColliderLastRun(= -1)

Step number when a collider was last run; set by the collider, if it wants contacts that were not encoutered in that step to be deleted by ContactLoop (such as SpatialQuickSortCollider). Other colliders (such as InsertionSortCollider) set it it -1, which is the default.

[type: int, read-only in python]

threadsPending(= [[], [], [], [], [], [], [], []])

Contacts which might be deleted by the collider in the next step (separate for each thread, for safe lock-free writes)

[type: std::vector<std::vector<PendingContact>>, not accessible from python]

__getitem__(*args, **kwargs)

Overloaded function.

  1. __getitem__(self: woo.dem.ContactContainer, arg0: _wooEigen11.Vector2i) -> woo.dem.Contact

  2. __getitem__(self: woo.dem.ContactContainer, arg0: int) -> woo.dem.Contact

__iter__(self: woo.dem.ContactContainer)ContactContainer::pyIterator
__len__(self: woo.dem.ContactContainer)int
clear(self: woo.dem.ContactContainer)None
countReal(self: woo.dem.ContactContainer)int
exists(self: woo.dem.ContactContainer, arg0: int, arg1: int)bool
existsReal(self: woo.dem.ContactContainer, arg0: int, arg1: int)bool
realRatio(self: woo.dem.ContactContainer)float
remove(self: woo.dem.ContactContainer, contact: woo.dem.Contact, force: bool = False)None
removeNonReal(self: woo.dem.ContactContainer)None

ParticleContainer

ObjectParticleContainer

class woo.dem.ParticleContainer(*args, **kwargs)

Storage for DEM particles

Overloaded function.

  1. __init__(self: woo.dem.ParticleContainer) -> None

  2. __init__(self: woo.dem.ParticleContainer, *args, **kwargs) -> None

parts(= _8ParticleList[])

Actual particle storage

[type: ContainerT, not accessible from python]

freeIds(= [])

Free particle id’s

[type: list<id_t>, not accessible from python]

__getitem__(self: woo.dem.ParticleContainer, arg0: int)woo.dem.Particle
__iter__(self: woo.dem.ParticleContainer)ParticleContainer::pyIterator
__len__(self: woo.dem.ParticleContainer)int
add(*args, **kwargs)

Overloaded function.

  1. add(self: woo.dem.ParticleContainer, par: woo.dem.Particle, nodes: int = -1) -> int

Add single particle, and maybe also add its nodes to DemField.nodes. nodes can be 1/True (always), 0/False (never) or -1 (maybe – based on heuristics). The heuristics is defined in woo.dem.DemData.guessMoving.

  1. add(self: woo.dem.ParticleContainer, pars: std::vector<std::shared_ptr<Particle>, std::allocator<std::shared_ptr<Particle> > >, nodes: int = -1) -> list

Add list of particles, and optionally also adding its nodes to DemField.nodes; see add for explanation of nodes.

addClumped(self: woo.dem.ParticleContainer, par: std::vector<std::shared_ptr<Particle>, std::allocator<std::shared_ptr<Particle> > >, centralNode: woo.core.Node = None, nodes: int = False)woo.core.Node

Add particles as rigid aggregate. Add resulting clump node (which is not a particle) to Scene.dem.nodes, subject to integration. centralNode must be provided if particles have zero mass (in that case, clump position cannot be computed), all DOFs will be blocked automatically in that case; centralNode.dem will be set with a new instance of ClumpData and the old value, if any, discarded. Clump node is added automatically to DemField.nodes.

Note

Clumped nodes are not added to DemField.nodes by default; this can be changed by nodes=True, but it is to be done only in cases, such as when woo.dem.NodalForcesToHdf5 should use those nodes. Nodes will still be skipped for motion integration, which is done on the clump node itself.

clear(self: woo.dem.ParticleContainer)None

Brute-force removal of all particles; bypasses any consistency checks (like node-particle refcounting), do not use.

disappear(self: woo.dem.ParticleContainer, ids: List[int], mask: int)None

Remask particle (so that it does not have contacts with other particles), remove contacts, which would no longer exist and make it invisible. Shorthand for calling remask(ids,mask,visible=False,removeContacts=True)

exists(self: woo.dem.ParticleContainer, id: int)bool

Tell whether particle with this id exists in the container.

reappear(self: woo.dem.ParticleContainer, ids: List[int], mask: int, removeOverlapping: bool = False)None

Remask particle, remove particles, which would overlap with newly-appeared particle (if removeOverlapping is True), make it visible again. Shorthand for remask(ids,mask,visible=True,removeContacts=False)

remask(self: woo.dem.ParticleContainer, ids: List[int], mask: int, visible: bool, removeContacts: bool, removeOverlapping: bool)None

Change particle mask and visibility; optionally remove contacts, which would no longer exist due to mask change; or remove particles, which would newly overlap with the particle. See also disappear and reappear.

remove(*args, **kwargs)

Overloaded function.

  1. remove(self: woo.dem.ParticleContainer, id: int) -> bool

Remove single particle given its id.

  1. remove(self: woo.dem.ParticleContainer, ids: List[int]) -> list

Remove multiple particles, given their ids as sequence.

TraceVisRep

ObjectNodeVisRepTraceVisRep

class woo.dem.TraceVisRep(*args, **kwargs)

Data with node’s position history; created by Tracer.

Overloaded function.

  1. __init__(self: woo.dem.TraceVisRep) -> None

  2. __init__(self: woo.dem.TraceVisRep, *args, **kwargs) -> None

pts(= [])

History points

[type: vector<Vector3r>, not shown in the UI, read-only in python]

scalars(= [])

History scalars

[type: vector<Real>, not shown in the UI, read-only in python]

times(= [])

History times (only saved with Tracer.saveTime).

[type: vector<Real>, not shown in the UI, read-only in python]

t0(= nan)

Time the trace was created/reset, for plotting relative time; does not change with compression.

[type: Real]

tracer(= None)

Tracer which created (and is, presumably, managing) this object; it is necessary for getting rendering parameters, and is updated automatically.

[type: shared_ptr<Tracer>, read-only in python]

writeIx(= 0)

Index where next data will be written

[type: size_t]

flags(= 0)

Flags for this instance

[type: short]

consolidate(self: woo.dem.TraceVisRep)None

Make pts sequential (normally, the data are stored as circular buffer, with next write position at writeIx, so that they are ordered temporally.

pt(self: woo.dem.TraceVisRep, arg0: int)_wooEigen11.Vector3

Get one history point (to avoid copying arrays), indexed as in python (negative counts backwards).

scalar(self: woo.dem.TraceVisRep, arg0: int)float

Get one history scalar (to avoid copying arrays), indexed as in python (negative counts backwards).

time(self: woo.dem.TraceVisRep, arg0: int)float

Get one history time (to avoid copying arrays), indexed as in python (negative counts backwards).

Tip

Report issues or inclarities to github.