Lattices

Tissue Forge provides built-in methods to quickly assemble lattices of particles in Python. Along with a number of convenience methods to generate standard lattices with particular particle types and bonded interactions, Tissue Forge also provides basic infrastructure to create custom unit cells and construct lattices with them. All built-in methods are provided in the lattice module.

In general, constructing a lattice of particles consists of two steps:

  1. Constructing a unit cell

  2. Creating the lattice

Built-in Unit Cells

Creating a lattice with a built-in unit cell is as simple as calling the corresponding lattice function while providing necessary and optional specification for the cell. For example, the method lattice.sq constructs a two-dimensional square unit cell.

import tissue_forge as tf

class LatticeType(tf.ParticleTypeSpec):
    """A particle type for lattices"""
    radius = 0.1

lattice_type = LatticeType.get()  # Get the particle type
# Construct a square unit cell with
# - a lattice constant of 3 times the particle type radius
# - all particles of type "LatticeType"
unit_cell_sq = tf.lattice.sq(3*lattice_type.radius, lattice_type)

All methods that construct built-in unit cells support optional features to add to the corresponding unit cell, like adding bonded interactions to pairs of particles. Specifying bonded interactions among particles in a lattice requires providing at least a callable that takes two particles as arguments and returns a newly created bond.

# Create a potential for bonded interactions in a lattice
pot = tf.Potential.power(r0=2.0 * lattice_type.radius, alpha=2)
# Construct a body center cubic with bonded interactions
uc_bcc = tf.lattice.bcc(3*lattice_type.radius,
                        lattice_type,
                        lambda i, j: tf.Bond.create(pot, i, j))

Each method provides even more granularity, like specifying particular groups of bonded interactions to create or not create.

# Construct a face centered cubic with only bonds between corner and center particles
uc_fcc = tf.lattice.fcc(3*lattice_type.radius,
                        lattice_type,
                        lambda i, j: tf.Bond.create(pot, i, j),
                        (False, True))

Currently, Tissue Forge provides built-in methods to construct the following unit cells,

For details on all built-in unit cells, see the Tissue Forge Python API Reference.

Custom Unit Cells

Custom unit cells can be designed for creating arbitrarily complex lattices of Tissue Forge objects. Custom unit cells are created by constructing a unitcell instance. A unitcell includes a prescription of a box that defines its spatial extent, as well as details about the particles that constitute it.

The box of a unitcell is defined by three vectors that define a right-handed coordinate system, each of which defines the extent of the box along its particular direction such that patterning the unitcell along a particular direction places a unitcell instances at intervals according to the vector. For example, a unitcell that generates a lattice with spatial intervals of 1, 2, and 3 along the x-, y- and z-directions, respectively, has vectors [1, 0, 0], [0, 2, 0] and [0, 0, 3]. The unitcell definition supports both two- and three-dimensional unit cells, though even two-dimensional unitcell instances require three vectors for their box definition, each with three coordinates. Rather, unitcell instances are declared two- or three-dimensional using the integer argument dimensions.

The particles of a unitcell are defined by declaring the number of particles and the position and type of each particles. The position of each particle is defined with respect to the origin of the coordinate system of the unitcell. For example, to create a unitcell for a two-dimensional square lattice with unit length of 1,

# Construct a 2D square unit cell
uc_sq_custom = tf.lattice.unitcell(N=1,                   # One particle
                                   a1=[1, 0, 0],          # Length 1 along x
                                   a2=[0, 1, 0],          # Length 1 along y
                                   a3=[0, 0, 1],          # Length 1 along z
                                   dimensions=2,          # 2D
                                   types=[lattice_type],  # Of type "lattice_type"
                                   position=[[0, 0, 0]])  # One particle at the origin

The unitcell also supports embedding information about bonded interactions between particles of each unitcell when used to create a lattice. Bonded interactions can be attached to a unitcell definition by specifying a tuple, each element of which contains three pieces of information in a BondRule,

  1. a callable that takes two particles as arguments and returns a newly created bond

  2. a tuple of two integers identify the index of each particles of the bond, according to the ordering of arguments passed to the unitcell constructor, where at least the first integer refers to a particle in the current unitcell.

  3. a lattice offset vector referring to the displacement from the current unitcell to the unitcell to which the second particle of the bond belongs, where an offset vector of [0, 0, 0] refers to the current unitcell.

For example, to create a two-dimensional square lattice with unit length of 1 and bonds between all particles in a lattice,

# Create a callable for constructing uniform bonded interactions in a lattice
bond_callable = lambda i, j: tf.Bond.create(pot, i, j)
# Construct a 2D square unit cell with bonded interactions
uc_sq_bonded = tf.lattice.unitcell(
    N=1,                   # One particle
    a1=[1, 0, 0],          # Length 1 along x
    a2=[0, 1, 0],          # Length 1 along y
    a3=[0, 0, 1],          # Length 1 along z
    dimensions=2,          # 2D
    types=[lattice_type],  # Of type "lattice_type"
    position=[[0, 0, 0]],  # One particle at the origin
    bonds=[                # Declare bonded interactions...
        tf.lattice.BondRule(bond_callable, (0, 0), (1, 0, 0)),  # ... +x cell
        tf.lattice.BondRule(bond_callable, (0, 0), (0, 1, 0)),  # ... +y cell
        tf.lattice.BondRule(bond_callable, (0, 0), (0, 0, 1))]  # ... +z cell
)

Creating a Lattice

Creating a lattice with an available unitcell is as simple as calling lattice.create_lattice while providing details about the patterning of the lattice, and also optionally about where to place the lattice. In the simplest case, passing a unitcell and an integer n creates a lattice consisting of n instances of the unitcell in each direction (in the xy plane for two-dimensional unit cells) centered at the center of the universe.

# Create a body center cubic lattice at the origin with 10 unit cells per direction
tf.lattice.create_lattice(uc_bcc, 10)

Instead of passing an integer for the number of unit cells, the number of unit cells can be passed per unit cell direction.

# Create a square lattice with 10 cells along x, and 20 cells along y
tf.lattice.create_lattice(unit_cell_sq, [10, 20])

Passing a position as a third optional argument instructs Tissue Forge about where to begin constructing the lattice.

# Create a face center cubic lattice beginning at (1, 2, 3) with 15 unit cells per direction
tf.lattice.create_lattice(uc_fcc, 15, [1, 2, 3])