Boundary Reset

This example demonstrates how to use the “reset” boundary condition to simulate convection through a channel. In reset conditions, the initial concentration of a species is restored for a particle that crosses a reseting boundary.

Basic Setup

Initialize Tissue Forge for flow through a channel along the x-direction with reset conditions.

[1]:
import tissue_forge as tf

# Initialize a domain like a tunnel, with flow along the x-direction
tf.init(dim=[20, 10, 10],
        cells=[5, 5, 5],
        cutoff=5,
        bc={'x': ('periodic', 'reset'), 'y': 'free_slip', 'z': 'free_slip'})

Particle Types

Create two particle types,

  1. one to represent parcels of fluid materials carrying a concentration of a species with entry concentration of 1.0, and

  2. one to act like a flow barrier and concentration sink, with constant species concentration of 0.0.

[2]:
class CarrierType(tf.ParticleTypeSpec):
    """A particle type to carry stuff"""

    radius = 0.5
    mass = 0.1
    species = ['S1']
    style = {'colormap': {'species': 'S1', range: (0, 1)}}


class SinkType(tf.ParticleTypeSpec):
    """A particle type to absorb stuff"""

    frozen = True
    radius = 1.0
    species = ['S1']
    style = {'colormap': {'species': 'S1', range: (0, 1)}}


carrier_type, sink_type = CarrierType.get(), SinkType.get()

carrier_type.species.S1.initial_concentration = 1.0
sink_type.species.S1.constant = True

Fluid Interactions

Construct fluid interactions for the following cases.

  1. Fluid particles in the domain interact according to dissipative particle dynamics (DPD).

  2. Sink particles act like a barrier for fluid flow.

[3]:
# Carrier type like a fluid
dpd = tf.Potential.dpd(alpha=1, gamma=1, sigma=0.1, cutoff=3 * CarrierType.radius)
tf.bind.types(dpd, carrier_type, carrier_type)

# Sink type like a barrier
rep = cp = tf.Potential.harmonic(k=1000,
                                 r0=carrier_type.radius + 1.05 * sink_type.radius,
                                 min=carrier_type.radius + sink_type.radius,
                                 max=carrier_type.radius + 1.05 * sink_type.radius,
                                 tol=0.001)
tf.bind.types(rep, carrier_type, sink_type)
[3]:
0

Convection

Apply a constant force to drive fluid flow towards +x, and diffusive transport between fluid particles and, at a faster rate, between fluid and sink particles.

[4]:
force = tf.CustomForce([0.01, 0, 0])
tf.bind.force(force, carrier_type)

tf.Fluxes.flux(carrier_type, carrier_type, "S1", 0.001)
tf.Fluxes.flux(carrier_type, sink_type, "S1", 0.5)
[4]:
<tissue_forge.tissue_forge.Fluxes; proxy of <Swig Object of type 'TissueForge::Fluxes *' at 0x000002BED7DBBFC0> >

Particle Construction

Create a randomly distributed initial population of fluid particles, and place one sink particle at the center of the domain. Be sure that no fluid particles are initialized inside the sink particle.

[5]:
# Put a sink at the center and carrier types randomly, though not in the sink
st = sink_type(tf.Universe.center)
[carrier_type() for _ in range(2000)]
to_destroy = []
for p in carrier_type.items():
    if p.relativePosition(tf.Universe.center).length() < (sink_type.radius + carrier_type.radius) * 1.1:
        to_destroy.append(p)
[p.destroy() for p in to_destroy]
[5]:
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[6]:
tf.rendering.ClipPlanes.create(tf.Universe.center, tf.FVector3(0, 1, 0))

tf.show()
../../_images/examples_notebooks_boundary_reset_11_0.png