Documentation for Release 2024.2
Running Mesh Based Crypt Simulations
This tutorial is automatically generated from TestRunningMeshBasedCryptSimulationsTutorial.hpp at revision 409e06cb314b. Note that the code is given in full at the bottom of the page.
Examples showing how to run crypt simulations on periodic meshes with different cell-cycle models
Introduction
In this tutorial we show how Chaste can be used to simulate a cylindrical model of an intestinal crypt. Full details of the computational model can be found in the paper by van Leeuwen et al. (2009) doi:10.1111/j.1365-2184.2009.00627.x.
As in previous cell-based Chaste tutorials, we begin by including the necessary header files.
The next header file defines a helper class for generating cells for crypt simulations.
The next two header files define two different types of cell-cycle model.
In a FixedG1GenerationalCellCycleModel
, the duration of each phase
of the cell cycle is fixed. In a WntCellCycleModel
, the duration of a cell’s G1 phase
is determined by a system of nonlinear ODEs describing a cell’s response to the local
concentration of Wnt,
a secreted cell–cell signalling molecule that is known to play a key role in cell
proliferation in the crypt. In our crypt simulations, we impose a fixed gradient of
Wnt up the axis of the crypt.
The next header file defines a helper class for generating a suitable triangular mesh for the crypt simulation, such that the cell corresponding to each node is initially in mechanical equilibrium with its neighours and periodic boundary conditions are applied at the left- and right-hand sides of the mesh (hence the “cylindrical”).
The next two header files were encountered in the tutorial Running Mesh Based Simulations.
The first header defines a CellPopulation
class that uses a triangular mesh, and allows
for the inclusion of ‘ghost nodes’: these are nodes in the mesh that do not correspond
to cells, but help ensure that a sensible Delaunay triangulation is generated
at each timestep; this is because the triangulation algorithm requires a convex hull.
The next header file defines a force law, based on a linear spring, for describing
the mechanical interactions between neighbouring cells in the crypt.
The next header file defines the class that simulates the evolution of a CellPopulation
,
specialized to deal with the cylindrical crypt geometry.
The next header file defines a Wnt singleton class, which (if used) deals with the
imposed Wnt gradient in our crypt model. This affects cell proliferation in the case
where we construct each cell with a WntCellCycleModel
.
The final header file defines a cell killer class, which implements sloughing of cells into the lumen once they reach the top of the crypt.
This header ensures that this test is only run on one process, since it doesn’t support parallel execution.
Next, we define the test class.
Test 1: a basic crypt simulation
In the first test, we demonstrate how to create a crypt simulation using a cylindrical mesh, with each cell progressing through a fixed cell-cycle model, and sloughing enforced at the top of the crypt.
First, we generate a mesh. The basic Chaste mesh is a TetrahedralMesh
.
To enforce periodicity at the left- and right-hand sides of the mesh, we
use a subclass called Cylindrical2dMesh
, which has extra methods for
maintaining periodicity. To create a Cylindrical2dMesh
, we can use a helper class called
CylindricalHoneycombMeshGenerator
. This generates a periodic honeycomb-shaped mesh,
in which all nodes are equidistant to their neighbours. Here the first and second arguments
define the size of the mesh - we have chosen a mesh that is 6 nodes (i.e.
cells) wide, and 9 nodes high. The third argument indicates that we require
a double layer of ghost nodes around the mesh (technically, just above
and below the mesh, since it is periodic). We call GetCylindricalMesh()
on the CylindricalHoneycombMeshGenerator
to
return our Cylindrical2dMesh
, and call GetCellLocationIndices()
to return a std::vector
of indices of nodes in the mesh that correspond to real cells (as opposed
to ghost nodes).
Having created a mesh, we now create a std::vector
of CellPtr
s.
To do this, we use the CryptCellsGenerator
helper class, which is templated over the type
of cell-cycle model required (here FixedG1GenerationalCellCycleModel
)
and the dimension. We create an empty vector of cells and pass this into the
method Generate()
along with the mesh. The fourth argument ’true’ indicates that the cells
should be assigned random birth times, to avoid synchronous division. The
cells
vector is populated once the method Generate()
is
called. Note that we only ever deal with shared pointers to cells, named CellPtr
s.
Now we have a mesh, a set of cells to go with it, and a vector of node indices
corresponding to real cells, we can create a CellPopulation
object. In general,
this class associates a collection of cells with a set of nodes or a mesh.
For this test, because we have a mesh and ghost nodes, we use a particular type of
cell population called a MeshBasedCellPopulationWithGhostNodes
.
Next we use the CellPopulation
object to construct a CryptSimulation2d
object,
which will be used to simulate the crypt model.
We must set the output directory on the simulator (relative to
cd $CHASTE_TEST_OUTPUT
) and the end time (in hours).
For longer simulations, we may not want to output the results every time step. In this case we can use the following method, to print results every 12 time steps instead. As the time step used by the simulator, is 30 seconds, this method will cause the simulator to print results every 6 minutes.
Before running the simulation, we must add one or more force laws, which determine the mechanical
behaviour of the cell population. For this test, we use a GeneralisedLinearSpringForce
, which assumes
that every cell experiences a force from each of its neighbours that can be represented as a linear overdamped
spring.
We also add a cell killer to the simulator. This object
dictates under what conditions cells die. For this test, we use
a SloughingCellKiller
, which kills cells above a certain
height (passed as an argument to the constructor).
To run the simulation, we call Solve()
.
Finally, to visualize the results, see Visualizing with Paraview
Test 2: a Wnt-dependent crypt simulation
The next test is very similar to Test 1, except that instead of using a fixed cell-cycle model, we use a Wnt-dependent cell-cycle model, with the Wnt concentration varying within the crypt in a predefined manner.
First we create a cylindrical mesh, and get the cell location indices, exactly as before.
Note that time is re-initialized to zero and random number generator is re-seeded to zero in the AbstractCellBasedTestSuite
.
We create the cells, using the same method as before. Here, though, we use a WntCellCycleModel
.
We create the cell population, as before.
We set the height of the crypt. As well as passing this variable into the sloughingCellKiller
,
we will pass it to the WntConcentration
object (see below).
When using a WntCellCycleModel
, we need a way of telling each cell what the Wnt concentration
is at its location. To do this, we set up a WntConcentration
object. Like SimulationTime
,
WntConcentration
is a singleton class, so when instantiated it is accessible from anywhere in
the code (and in particular, all cells and cell-cycle models can access it). We need to say what
the profile of the Wnt concentation should be up the crypt: here, we say it is LINEAR
(linear
decreasing from 1 to 0 from the bottom of the crypt to the top). We also need to inform the
WntConcentration
of the cell population and the height of the crypt.
Create a simulator as before (except setting a different output directory).
As before, we create a force law and cell killer and pass these objects to the simulator, then call
Solve()
.
Finally, we must tidy up by destroying the WntConcentration
singleton object. This avoids memory leaks occurring.
The results of this test can be visualized as in Test 1, with the correct output directory.