Custom Potential
While Tissue Forge provides an ever-growing inventory of built-in potentials, Tissue Forge also provides the ability to create and use custom potentials. This example demonstrates how to create a Pseudo-Gaussian potential directly in python and test it in a one-dimensional scenario.
For details on the specifics of the Pseudo-Gaussian potential, see
Cotăescu, Ion I., Paul Grăvilă, and Marius Paulescu. “Pseudo-Gaussian oscillators.” International Journal of Modern Physics C 19.10 (2008): 1607-1615.
Basic Setup
Begin by initializing Tissue Forge with no-slip boundary conditions along x
, which will be the direction along which particles will be placed and tested in a one-dimensional scenario.
[1]:
import tissue_forge as tf
from math import exp, factorial
tf.init(cutoff=5, bc={'x': 'noslip'})
Particle Types
The test scenario considers an invisible, fixed source of a Pseudo-Gaussian potential at the center of the domain that displaces particles along the x
-direction. Create two particles types,
A fixed, invisible type
A particle type that cannot move along the
y
- andz
-directions.
[2]:
class WellType(tf.ParticleTypeSpec):
"""A particle type to act as a fixed source of a Pseudo-Gaussian potential"""
frozen = True
style = {'visible': False}
class SmallType(tf.ParticleTypeSpec):
"""A particle type that displaces in a fixed Pseudo-Gaussian potential"""
radius = 0.1
@classmethod
def get(cls):
result = super().get()
result.frozen_y = result.frozen_z = True
return result
well_type, small_type = WellType.get(), SmallType.get()
Potential Definition
Generally, Tissue Forge can create custom potentials in python using at least a function that takes the distance between two particles as an argument and returns the value of the potential. Additionally, Tissue Forge can also use functions for the first and sixth derivatives of the potential, and approximates whichever of these two when they are not provided using finite difference.
Create a python function for Tissue Forge to create a potential of the form,
$ V \left`( r :nbsphinx-math:right`) = \sum_{0 \leq `k :nbsphinx-math:leq s} :nbsphinx-math:frac{left( lambda + k right) mu^k}{k!}` r^{2k} \exp `:nbsphinx-math:left`( - \mu `r^2 :nbsphinx-math:right`) $
[3]:
# Custom potential function parameters
lam, mu, s = -0.5, 1.0, 3
def f(r: float):
"""Pseudo-Gaussian potential evaluated at r"""
return sum([(lam + k) / factorial(k) * mu ** k * r ** (2 * k) for k in range(s+1)]) * exp(-mu * r * r)
Custom Potential
Create and verify a potential object using the custom potential function definition, give it a name, and apply it to the particle types of the test scenario.
[4]:
pot_c = tf.Potential.custom(min=0, max=5, f=f)
pot_c.name = "Pseudo-Gaussian"
tf.bind.types(p=pot_c, a=well_type, b=small_type)
pot_c.plot(min=0, max=5, potential=True, force=False)
ymax: 0.9808318614959717 ymin: -0.5 yrange: 1.4808318614959717
Ylim: -0.6480831861495971 1.128915047645569
[4]:
[<matplotlib.lines.Line2D at 0x1f1dd63d490>]
Particle Construction
Place a single well particle and the center of the domain, and small particles at regular intervals along the x
-axis.
[5]:
# Create particles
well_type(position=tf.Universe.center, velocity=tf.FVector3(0))
num_particles = 20
for i in range(num_particles):
small_type(position=tf.FVector3((i+1)/(num_particles + 1) * tf.Universe.dim[0],
tf.Universe.center[1],
tf.Universe.center[2]),
velocity=tf.FVector3(0))
[6]:
tf.system.camera_view_top()
tf.show()