src/boundary.jl

MEDYAN.Boundary

Mechanical boundary

A set of soft planes and capsules that push beads back inside the domain. Apply it with set_mech_boundary!.

Rather than filling in the fields by hand, use one of the constructors:

Combine boundaries with . Boundary() is the empty boundary, which applies no forces.

  • planes::Vector{StaticArraysCore.SVector{4, Float64}}: Planes that make up the mechanical boundary of the simulation.

    E = 1//2 * relu(pos ⋅ planes[bi][1:3] - planes[bi][4])^2

    For example, a mech bounding plane [1,0,0,3] would try and make x < 3 nm with a spring constant of 1 pN/nm.

    2.0*[1,0,0,3] would try and make x < 3 nm with a spring constant of 4 pN/nm.

  • plane_layers::Vector{UInt32}: Collision layers for each plane. Empty for chemical boundaries.

  • plane_ncmask::Vector{UInt32}: No-collide mask for each plane. Empty for chemical boundaries.

  • capsules::Vector{StaticArraysCore.SVector{8, Float64}}: Capsules that make up the mechanical boundary of the simulation.

    capsules[bi][1:3] is the starting point of the spine line segment (nm). capsules[bi][4:6] is the axis of the spine line segment (nm). capsules[bi][7] is the radius (nm). If the radius is negative, the domain is the outside of the capsule, if the radius is positive the domain is inside the capsule. capsules[bi][8] is the spring constant (pN/nm).

    if capsules[bi][4:6] is zero then the capsule is a sphere. Capsule boundaries can be combined with plane boundaries to create cylinder boundaries.

    E = 1//2*k*relu(sign(r0)*d - r0)^2 where:

    • d is the distance of the point to the spine line segment described by capsules[bi][1:6].
    • r0 is capsules[bi][7]
    • k is capsules[bi][8]
  • capsule_layers::Vector{UInt32}: Collision layers for each capsule. Empty for chemical boundaries.

  • capsule_ncmask::Vector{UInt32}: No-collide mask for each capsule. Empty for chemical boundaries.

MEDYAN.boundary_plane

boundary_plane(
;
    normal,
    point,
    stiffness,
    collision_layers,
    no_collide_mask
) -> MEDYAN.Boundary

Return a plane boundary.

A bead a distance d past the plane has energy 1/2 * stiffness * d^2 and is pushed back along -normal.

normal::SVector{3,Float64}=SA[1.0,0.0,0.0](unit vector): Vector normal to the plane, pointing outside of the boundary.

point::SVector{3,Float64}=SA[0.0,0.0,0.0](nm): Point on the plane.

stiffness::Float64=1.0(pN/nm): How strong the boundary is.

collision_layers::UInt32=UInt32(1): Collision layers bitmask.

no_collide_mask::UInt32=UInt32(0): No-collide mask bitmask. Bits set = layers this plane will not collide with. The default collides with everything. See the “Collision Layers and No-Collide Masks” explanation page.

Example

A floor keeping beads above z = -200 nm:

boundary_plane(; normal=SA[0.0, 0.0, -1.0], point=SA[0.0, 0.0, -200.0], stiffness=100.0)

See also Boundary, set_mech_boundary!

MEDYAN.boundary_box

boundary_box(
    grid::MEDYAN.CubicGrid;
    offset,
    stiffness,
    collision_layers,
    no_collide_mask
) -> MEDYAN.Boundary

Return a box boundary at the edge of a grid.

The box boundary has one plane per face of the grid, with normals pointing out of the grid. Each plane acts like boundary_plane.

grid::CubicGrid: The planes sit on the faces of this grid.

offset::Float64=0.0(nm): How far the bounding planes should be moved in from the edge of the grid. Positive is inside the grid, negative is outside the grid.

stiffness::Float64=1.0(pN/nm): How strong the boundary is.

collision_layers::UInt32=UInt32(1): Collision layers bitmask, applied to all six planes.

no_collide_mask::UInt32=UInt32(0): No-collide mask bitmask. Bits set = layers this box will not collide with. The default collides with everything. See the “Collision Layers and No-Collide Masks” explanation page.

Example

grid = CubicGrid(SA[4, 4, 4], 250.0)
boundary_box(grid; stiffness=100.0)

See also Boundary, set_mech_boundary!

MEDYAN.boundary_capsule

boundary_capsule(
;
    radius,
    center,
    axis,
    stiffness,
    collision_layers,
    no_collide_mask
)

Return a capsule boundary.

A bead a distance d past the capsule surface has energy 1/2 * stiffness * d^2 and is pushed back toward the surface.

radius::Float64(nm): Radius of capsule, the full length of the capsule is norm(axis) + 2*abs(radius). If negative, the domain is the outside of the capsule, if positive the domain is the inside of the capsule.

center::SVector{3,Float64}=SA[0.0,0.0,0.0](nm): The center of the capsule.

axis::SVector{3,Float64}=SA[0.0,0.0,0.0](nm): The direction and length of the capsule spine. The spine line segment goes from center - axis/2 to center + axis/2. If zero the capsule is a sphere.

stiffness::Float64=1.0(pN/nm): How strong the boundary is.

collision_layers::UInt32=UInt32(1): Collision layers bitmask.

no_collide_mask::UInt32=UInt32(0): No-collide mask bitmask. Bits set = layers this capsule will not collide with. The default collides with everything. See the “Collision Layers and No-Collide Masks” explanation page.

Example

# inside a sphere of radius 400 nm
boundary_capsule(; radius=400.0, stiffness=100.0)

# outside a ball of radius 50 nm at z = 300 nm
boundary_capsule(; center=SA[0.0, 0.0, 300.0], radius=-50.0, stiffness=100.0)

See also Boundary, set_mech_boundary!

MEDYAN.boundary_cylinder

boundary_cylinder(
;
    axis,
    radius,
    center,
    stiffness,
    collision_layers,
    no_collide_mask
)

Return a cylinder boundary.

The domain is the inside of the cylinder. The cylinder boundary is a boundary_capsule for the curved wall and a boundary_plane at each end.

axis::SVector{3,Float64}(nm): The direction and length of the cylinder. Must be nonzero. The spine line segment goes from center - axis/2 to center + axis/2, so the full length of the cylinder is norm(axis).

radius::Float64(nm): Radius of cylinder. Must be nonnegative.

center::SVector{3,Float64}=SA[0.0,0.0,0.0](nm): The center of the cylinder.

stiffness::Float64=1.0(pN/nm): How strong the boundary is.

collision_layers::UInt32=UInt32(1): Collision layers bitmask, applied to the capsule and both end planes.

no_collide_mask::UInt32=UInt32(0): No-collide mask bitmask. Bits set = layers this cylinder will not collide with. The default collides with everything. See the “Collision Layers and No-Collide Masks” explanation page.

Example

A tube along z, 1000 nm long and 200 nm across:

boundary_cylinder(; axis=SA[0.0, 0.0, 1000.0], radius=100.0, stiffness=100.0)

See also Boundary, set_mech_boundary!