diff --git a/doc/tutorials/TestImmersedBoundaryTutorial.ipynb b/doc/tutorials/TestImmersedBoundaryTutorial.ipynb index 323526f5..4b39dd31 100644 --- a/doc/tutorials/TestImmersedBoundaryTutorial.ipynb +++ b/doc/tutorials/TestImmersedBoundaryTutorial.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "markdown", - "id": "29256d0a", + "id": "deb0fc74", "metadata": {}, "source": [ "This tutorial is automatically generated from the file /home/kwabena/repo/PyChaste/test/python/cell_based/tutorials/TestImmersedBoundaryTutorial.py.\n", @@ -12,7 +12,7 @@ { "cell_type": "code", "execution_count": null, - "id": "578ccc75", + "id": "ccee77a3", "metadata": {}, "outputs": [], "source": [ @@ -24,7 +24,7 @@ }, { "cell_type": "markdown", - "id": "c3501404", + "id": "de45c720", "metadata": {}, "source": [ "\n", @@ -48,7 +48,7 @@ { "cell_type": "code", "execution_count": null, - "id": "b44b26a2", + "id": "2aa5ec9d", "metadata": {}, "outputs": [], "source": [ @@ -59,6 +59,7 @@ " CellsGeneratorUniformCellCycleModel_2,\n", " DifferentiatedCellProliferativeType,\n", " ForwardEulerNumericalMethod2_2,\n", + " FluidSource2,\n", " ImmersedBoundaryCellPopulation2,\n", " ImmersedBoundaryLinearInteractionForce2,\n", " ImmersedBoundaryLinearMembraneForce2,\n", @@ -73,7 +74,7 @@ }, { "cell_type": "markdown", - "id": "ab95f9ef", + "id": "97f8738f", "metadata": {}, "source": [ "### Simple Immersed Boundary Simulations\n", @@ -95,7 +96,7 @@ { "cell_type": "code", "execution_count": null, - "id": "1bc36a89", + "id": "d208513f", "metadata": {}, "outputs": [], "source": [ @@ -105,7 +106,7 @@ }, { "cell_type": "markdown", - "id": "2e51436d", + "id": "cfb921a4", "metadata": {}, "source": [ " **Tip** Lines of code beginning with `#` are comments in Python\n", @@ -117,7 +118,7 @@ { "cell_type": "code", "execution_count": null, - "id": "bec0e9a3", + "id": "ad339510", "metadata": {}, "outputs": [], "source": [ @@ -128,7 +129,7 @@ }, { "cell_type": "markdown", - "id": "f921e6cd", + "id": "0b8d25bc", "metadata": {}, "source": [ "The first line of code defines an `ImmersedBoundaryPalisadeMeshGenerator`\n", @@ -149,7 +150,7 @@ { "cell_type": "code", "execution_count": null, - "id": "93e72245", + "id": "e391a6b0", "metadata": {}, "outputs": [], "source": [ @@ -159,7 +160,7 @@ }, { "cell_type": "markdown", - "id": "a057b472", + "id": "6f51bb50", "metadata": {}, "source": [ "Next, we set up the cell population\n", @@ -169,7 +170,7 @@ { "cell_type": "code", "execution_count": null, - "id": "e6f17c9e", + "id": "06cffc4d", "metadata": {}, "outputs": [], "source": [ @@ -183,7 +184,7 @@ }, { "cell_type": "markdown", - "id": "b462d292", + "id": "d097dc7d", "metadata": {}, "source": [ "We specify a cell type and cell cycle model. These can be\n", @@ -199,7 +200,7 @@ { "cell_type": "code", "execution_count": null, - "id": "6b81d9c1", + "id": "e84e028b", "metadata": {}, "outputs": [], "source": [ @@ -209,7 +210,7 @@ }, { "cell_type": "markdown", - "id": "668743c8", + "id": "f9a53b09", "metadata": {}, "source": [ "Here, we use an `OffLatticeSimulation` simulator to control the\n", @@ -221,7 +222,7 @@ { "cell_type": "code", "execution_count": null, - "id": "cbed8981", + "id": "84ee8737", "metadata": {}, "outputs": [], "source": [ @@ -234,7 +235,7 @@ }, { "cell_type": "markdown", - "id": "38ab127a", + "id": "5b2852bc", "metadata": {}, "source": [ "As we have an off-lattice simulation, we need a way to model the\n", @@ -250,7 +251,7 @@ { "cell_type": "code", "execution_count": null, - "id": "d1dc695f", + "id": "732f2973", "metadata": {}, "outputs": [], "source": [ @@ -261,7 +262,7 @@ }, { "cell_type": "markdown", - "id": "4399049a", + "id": "a30da25d", "metadata": {}, "source": [ "We must also provide the modifier with a force model to govern\n", @@ -274,7 +275,7 @@ { "cell_type": "code", "execution_count": null, - "id": "2bd27598", + "id": "3142419c", "metadata": {}, "outputs": [], "source": [ @@ -285,7 +286,7 @@ }, { "cell_type": "markdown", - "id": "3f417925", + "id": "94e7c0db", "metadata": {}, "source": [ "The spring constant(`1.0 * 1e7`) defines how stiff the cell boundary\n", @@ -303,7 +304,7 @@ { "cell_type": "code", "execution_count": null, - "id": "5081813f", + "id": "f9788472", "metadata": {}, "outputs": [], "source": [ @@ -321,27 +322,16 @@ }, { "cell_type": "markdown", - "id": "7366874a", + "id": "c05f0d4d", "metadata": {}, "source": [ "### Adding More Cells\n", "\n" ] }, - { - "cell_type": "code", - "execution_count": null, - "id": "dfce16e7", - "metadata": {}, - "outputs": [], - "source": [ - "# Set the start time for the simulation\n", - "SimulationTime.Instance().SetStartTime(0.0)" - ] - }, { "cell_type": "markdown", - "id": "09ab91fb", + "id": "410bb6bb", "metadata": {}, "source": [ "#### Multiple Cells\n", @@ -355,7 +345,7 @@ { "cell_type": "code", "execution_count": null, - "id": "3952328b", + "id": "8b37b5b1", "metadata": {}, "outputs": [], "source": [ @@ -365,7 +355,7 @@ }, { "cell_type": "markdown", - "id": "031d74c1", + "id": "bf004900", "metadata": {}, "source": [ "#### Laminas\n", @@ -389,7 +379,7 @@ { "cell_type": "code", "execution_count": null, - "id": "cfd88229", + "id": "8a05255b", "metadata": {}, "outputs": [], "source": [ @@ -405,6 +395,8 @@ "cell_population = ImmersedBoundaryCellPopulation2(mesh, cells)\n", "# Specify whether the population has active fluid sources\n", "cell_population.SetIfPopulationHasActiveSources(False)\n", + "# Set the start time for the simulation\n", + "SimulationTime.Instance().SetStartTime(0.0)\n", "# Create a simulator to manage our simulation\n", "simulator = OffLatticeSimulation2_2(cell_population)\n", "numerical_method = ForwardEulerNumericalMethod2_2()\n", @@ -418,7 +410,7 @@ }, { "cell_type": "markdown", - "id": "5a53fdf1", + "id": "dbf593e4", "metadata": {}, "source": [ "#### Intercellular Interactions\n", @@ -434,7 +426,7 @@ { "cell_type": "code", "execution_count": null, - "id": "3f190624", + "id": "ab416131", "metadata": {}, "outputs": [], "source": [ @@ -452,6 +444,212 @@ "SimulationTime.Instance().Destroy()\n", "TearDownNotebookTest()" ] + }, + { + "cell_type": "markdown", + "id": "cd6c6d09", + "metadata": {}, + "source": [ + "### Adding Fluid Sources\n", + "Now that we are familiar with how to generate the cells, we will\n", + "introduce fluid sources.\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "id": "cfa8c872", + "metadata": {}, + "source": [ + "#### Adding a Fluid Source\n", + "We begin by constructing a fluid source object.\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "cea19b8c", + "metadata": {}, + "outputs": [], + "source": [ + "source = FluidSource2(0, 0.5, 0.7)" + ] + }, + { + "cell_type": "markdown", + "id": "18b44048", + "metadata": {}, + "source": [ + "This constructs a `FluidSource` object in 2 dimensions. The first\n", + "parameter gives the index of the fluid source. Each source you\n", + "create must have a unique index. The next parameters are the\n", + "`x` and `y` coordinates of the source. Fluid sources in chaste are\n", + "point-like, that is to say they do not have any area/volume.\n", + "\n", + "Having created the fluid source, we set its strength:\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "beae54d5", + "metadata": {}, + "outputs": [], + "source": [ + "source.SetStrength(0.012)" + ] + }, + { + "cell_type": "markdown", + "id": "52ca6674", + "metadata": {}, + "source": [ + "Now, we must associate the source with an element in the simulation\n", + "so that the simulation is aware of the source.\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "30354ec0", + "metadata": {}, + "outputs": [], + "source": [ + "# Create the mesh\n", + "gen = ImmersedBoundaryPalisadeMeshGenerator(5, 128, 0.1, 2.0, 0.0, False)\n", + "mesh = gen.GetMesh()\n", + "mesh.SetNumGridPtsXAndY(64)\n", + "# Associate the fluid source with an element in the mesh\n", + "mesh.GetElement(0).SetFluidSource(source)" + ] + }, + { + "cell_type": "markdown", + "id": "d682896b", + "metadata": {}, + "source": [ + "Finally, we must tell the cell population that fluid sources are present.\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3ec64e67", + "metadata": {}, + "outputs": [], + "source": [ + "# Set up the cell population\n", + "cell_type = DifferentiatedCellProliferativeType()\n", + "cell_generator = CellsGeneratorUniformCellCycleModel_2()\n", + "cells = cell_generator.GenerateBasicRandom(mesh.GetNumElements(), cell_type)\n", + "cell_population = ImmersedBoundaryCellPopulation2(mesh, cells)\n", + "# Specify that fluid sources are present\n", + "cell_population.SetIfPopulationHasActiveSources(True)" + ] + }, + { + "cell_type": "markdown", + "id": "1ee49811", + "metadata": {}, + "source": [ + "#### Varying the Source Location\n", + "You can experiment with the source location. Try moving it closer to\n", + "and further away from the cells.\n", + "\n", + "#### Varying the Source Strength\n", + "Try modifying the source strength to see what impact this has on\n", + "the cell shapes.\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a16602d7", + "metadata": {}, + "outputs": [], + "source": [ + "# Create a simulator\n", + "SimulationTime.Instance().SetStartTime(0.0)\n", + "simulator = OffLatticeSimulation2_2(cell_population)\n", + "numerical_method = ForwardEulerNumericalMethod2_2()\n", + "numerical_method.SetUseUpdateNodeLocation(True)\n", + "simulator.SetNumericalMethod(numerical_method)\n", + "# Add an immersed boundary simulation modifier" + ] + }, + { + "cell_type": "markdown", + "id": "861d9003", + "metadata": {}, + "source": [ + "#### Fluid-Cell Interaction\n", + "Have a go at modifying the spring constant of the\n", + "`ImmersedBoundaryLinearMembraneForce` to see how this changes the\n", + "effect of the fluid source on the cells.\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "65828444", + "metadata": {}, + "outputs": [], + "source": [ + "boundary_force = ImmersedBoundaryLinearMembraneForce2()\n", + "boundary_force.SetElementSpringConst(1.0 * 1e7)\n", + "interaction_force = ImmersedBoundaryLinearInteractionForce2()\n", + "interaction_force.SetSpringConst(1.0 * 1e6)" + ] + }, + { + "cell_type": "markdown", + "id": "03ac75c6", + "metadata": {}, + "source": [ + "#### Adding More Sources\n", + "Try adding second fluid source. You will need to use a unique index,\n", + "and attach it to a different element as each element can only manage\n", + "a single fluid source.\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "945d4565", + "metadata": {}, + "outputs": [], + "source": [ + "# Set simulation properties\n", + "dt = 0.05\n", + "simulator.SetOutputDirectory(\"Python/TestImmersedBoundary\")\n", + "simulator.SetDt(dt)\n", + "simulator.SetSamplingTimestepMultiple(4)\n", + "simulator.SetEndTime(1000 * dt)\n", + "# Perform the simulation\n", + "simulator.Solve()\n", + "SimulationTime.Instance().Destroy()\n", + "TearDownNotebookTest()" + ] + }, + { + "cell_type": "markdown", + "id": "d272679b", + "metadata": {}, + "source": [ + "#### Further Exercises\n", + " * Try integrating a different cell cycle model to introduce cell\n", + " division. See how the presence of a fluid source impacts the\n", + " structure that is formed.\n", + " * Use one of the cell writers to collect some statistics\n", + "\n" + ] } ], "metadata": {}, diff --git a/doc/tutorials/TestImmersedBoundaryTutorial.md b/doc/tutorials/TestImmersedBoundaryTutorial.md index 1c1344b7..8b81ba45 100644 --- a/doc/tutorials/TestImmersedBoundaryTutorial.md +++ b/doc/tutorials/TestImmersedBoundaryTutorial.md @@ -8,7 +8,7 @@ toc: true layout: "single" --- -This tutorial is automatically generated from [TestImmersedBoundaryTutorial](https://github.com/Chaste/PyChaste/blob/develop/test/python/cell_based/tutorials/TestImmersedBoundaryTutorial.py) at revision [404a4809](https://github.com/Chaste/PyChaste/commit/404a4809c03088c8dd7592267a990ae8522fd7af). +This tutorial is automatically generated from [TestImmersedBoundaryTutorial](https://github.com/Chaste/PyChaste/blob/develop/test/python/cell_based/tutorials/TestImmersedBoundaryTutorial.py) at revision [de6c6f92](https://github.com/Chaste/PyChaste/commit/de6c6f9256f00ad5a80ce1e2f5ab1a8c4c9cf58d). Note that the code is given in full at the bottom of the page. @@ -39,6 +39,7 @@ from chaste.cell_based import ( CellsGeneratorUniformCellCycleModel_2, DifferentiatedCellProliferativeType, ForwardEulerNumericalMethod2_2, + FluidSource2, ImmersedBoundaryCellPopulation2, ImmersedBoundaryLinearInteractionForce2, ImmersedBoundaryLinearMembraneForce2, @@ -195,9 +196,6 @@ Finally, we set up the simulation properties and run it. ```python def test_multicell_immersed_boundary_simulation(self): - # Set the start time for the simulation - SimulationTime.Instance().SetStartTime(0.0) - ``` #### Multiple Cells We can use the mesh generator to generate multiple cells. The first @@ -244,6 +242,9 @@ modifying the 5th parameter. # Specify whether the population has active fluid sources cell_population.SetIfPopulationHasActiveSources(False) + # Set the start time for the simulation + SimulationTime.Instance().SetStartTime(0.0) + # Create a simulator to manage our simulation simulator = OffLatticeSimulation2_2(cell_population) numerical_method = ForwardEulerNumericalMethod2_2() @@ -287,6 +288,123 @@ also be modified using the `SetRestLength` method. SimulationTime.Instance().Destroy() TearDownNotebookTest() +``` +### Adding Fluid Sources +Now that we are familiar with how to generate the cells, we will +introduce fluid sources. + +```python + def test_fluid_source_immersed_boundary_simulation(self): + +``` +#### Adding a Fluid Source +We begin by constructing a fluid source object. + +```python + source = FluidSource2(0, 0.5, 0.7) + +``` +This constructs a `FluidSource` object in 2 dimensions. The first +parameter gives the index of the fluid source. Each source you +create must have a unique index. The next parameters are the +`x` and `y` coordinates of the source. Fluid sources in chaste are +point-like, that is to say they do not have any area/volume. + +Having created the fluid source, we set its strength: + +```python + source.SetStrength(0.012) + +``` +Now, we must associate the source with an element in the simulation +so that the simulation is aware of the source. + +```python + # Create the mesh + gen = ImmersedBoundaryPalisadeMeshGenerator(5, 128, 0.1, 2.0, 0.0, False) + mesh = gen.GetMesh() + mesh.SetNumGridPtsXAndY(64) + + # Associate the fluid source with an element in the mesh + mesh.GetElement(0).SetFluidSource(source) + +``` +Finally, we must tell the cell population that fluid sources are present. + +```python + # Set up the cell population + cell_type = DifferentiatedCellProliferativeType() + cell_generator = CellsGeneratorUniformCellCycleModel_2() + cells = cell_generator.GenerateBasicRandom(mesh.GetNumElements(), cell_type) + cell_population = ImmersedBoundaryCellPopulation2(mesh, cells) + + # Specify that fluid sources are present + cell_population.SetIfPopulationHasActiveSources(True) + +``` +#### Varying the Source Location +You can experiment with the source location. Try moving it closer to +and further away from the cells. + +#### Varying the Source Strength +Try modifying the source strength to see what impact this has on +the cell shapes. + +```python + # Create a simulator + SimulationTime.Instance().SetStartTime(0.0) + simulator = OffLatticeSimulation2_2(cell_population) + numerical_method = ForwardEulerNumericalMethod2_2() + numerical_method.SetUseUpdateNodeLocation(True) + simulator.SetNumericalMethod(numerical_method) + + # Add an immersed boundary simulation modifier + main_modifier = ImmersedBoundarySimulationModifier2() + simulator.AddSimulationModifier(main_modifier) + +``` +#### Fluid-Cell Interaction +Have a go at modifying the spring constant of the +`ImmersedBoundaryLinearMembraneForce` to see how this changes the +effect of the fluid source on the cells. + +```python + boundary_force = ImmersedBoundaryLinearMembraneForce2() + boundary_force.SetElementSpringConst(1.0 * 1e7) + main_modifier.AddImmersedBoundaryForce(boundary_force) + + interaction_force = ImmersedBoundaryLinearInteractionForce2() + interaction_force.SetSpringConst(1.0 * 1e6) + main_modifier.AddImmersedBoundaryForce(interaction_force) + +``` +#### Adding More Sources +Try adding second fluid source. You will need to use a unique index, +and attach it to a different element as each element can only manage +a single fluid source. + +```python + # Set simulation properties + dt = 0.05 + simulator.SetOutputDirectory("Python/TestImmersedBoundary") + simulator.SetDt(dt) + simulator.SetSamplingTimestepMultiple(4) + simulator.SetEndTime(1000 * dt) + + # Perform the simulation + simulator.Solve() + + SimulationTime.Instance().Destroy() + TearDownNotebookTest() + +``` +#### Further Exercises + * Try integrating a different cell cycle model to introduce cell + division. See how the presence of a fluid source impacts the + structure that is formed. + * Use one of the cell writers to collect some statistics + +```python if __name__ == "__main__": unittest.main(verbosity=2) @@ -310,6 +428,7 @@ from chaste.cell_based import ( CellsGeneratorUniformCellCycleModel_2, DifferentiatedCellProliferativeType, ForwardEulerNumericalMethod2_2, + FluidSource2, ImmersedBoundaryCellPopulation2, ImmersedBoundaryLinearInteractionForce2, ImmersedBoundaryLinearMembraneForce2, @@ -376,9 +495,6 @@ class TestImmersedBoundaryTutorial(AbstractCellBasedTestSuite): TearDownNotebookTest() def test_multicell_immersed_boundary_simulation(self): - # Set the start time for the simulation - SimulationTime.Instance().SetStartTime(0.0) - # Create a mesh generator gen = ImmersedBoundaryPalisadeMeshGenerator(1, 128, 0.1, 2.0, 0.0, False) @@ -399,6 +515,9 @@ class TestImmersedBoundaryTutorial(AbstractCellBasedTestSuite): # Specify whether the population has active fluid sources cell_population.SetIfPopulationHasActiveSources(False) + # Set the start time for the simulation + SimulationTime.Instance().SetStartTime(0.0) + # Create a simulator to manage our simulation simulator = OffLatticeSimulation2_2(cell_population) numerical_method = ForwardEulerNumericalMethod2_2() @@ -432,6 +551,61 @@ class TestImmersedBoundaryTutorial(AbstractCellBasedTestSuite): SimulationTime.Instance().Destroy() TearDownNotebookTest() + def test_fluid_source_immersed_boundary_simulation(self): + + source = FluidSource2(0, 0.5, 0.7) + + source.SetStrength(0.012) + + # Create the mesh + gen = ImmersedBoundaryPalisadeMeshGenerator(5, 128, 0.1, 2.0, 0.0, False) + mesh = gen.GetMesh() + mesh.SetNumGridPtsXAndY(64) + + # Associate the fluid source with an element in the mesh + mesh.GetElement(0).SetFluidSource(source) + + # Set up the cell population + cell_type = DifferentiatedCellProliferativeType() + cell_generator = CellsGeneratorUniformCellCycleModel_2() + cells = cell_generator.GenerateBasicRandom(mesh.GetNumElements(), cell_type) + cell_population = ImmersedBoundaryCellPopulation2(mesh, cells) + + # Specify that fluid sources are present + cell_population.SetIfPopulationHasActiveSources(True) + + # Create a simulator + SimulationTime.Instance().SetStartTime(0.0) + simulator = OffLatticeSimulation2_2(cell_population) + numerical_method = ForwardEulerNumericalMethod2_2() + numerical_method.SetUseUpdateNodeLocation(True) + simulator.SetNumericalMethod(numerical_method) + + # Add an immersed boundary simulation modifier + main_modifier = ImmersedBoundarySimulationModifier2() + simulator.AddSimulationModifier(main_modifier) + + boundary_force = ImmersedBoundaryLinearMembraneForce2() + boundary_force.SetElementSpringConst(1.0 * 1e7) + main_modifier.AddImmersedBoundaryForce(boundary_force) + + interaction_force = ImmersedBoundaryLinearInteractionForce2() + interaction_force.SetSpringConst(1.0 * 1e6) + main_modifier.AddImmersedBoundaryForce(interaction_force) + + # Set simulation properties + dt = 0.05 + simulator.SetOutputDirectory("Python/TestImmersedBoundary") + simulator.SetDt(dt) + simulator.SetSamplingTimestepMultiple(4) + simulator.SetEndTime(1000 * dt) + + # Perform the simulation + simulator.Solve() + + SimulationTime.Instance().Destroy() + TearDownNotebookTest() + if __name__ == "__main__": unittest.main(verbosity=2) diff --git a/test/python/cell_based/tutorials/TestImmersedBoundaryTutorial.py b/test/python/cell_based/tutorials/TestImmersedBoundaryTutorial.py index e2552504..acc350ea 100644 --- a/test/python/cell_based/tutorials/TestImmersedBoundaryTutorial.py +++ b/test/python/cell_based/tutorials/TestImmersedBoundaryTutorial.py @@ -29,6 +29,7 @@ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """ + #ifndef #define TRIGGER_WIKI @@ -58,6 +59,7 @@ CellsGeneratorUniformCellCycleModel_2, DifferentiatedCellProliferativeType, ForwardEulerNumericalMethod2_2, + FluidSource2, ImmersedBoundaryCellPopulation2, ImmersedBoundaryLinearInteractionForce2, ImmersedBoundaryLinearMembraneForce2, @@ -195,9 +197,6 @@ def test_simple_immersed_boundary_simulation(self): ## ### Adding More Cells def test_multicell_immersed_boundary_simulation(self): - # Set the start time for the simulation - SimulationTime.Instance().SetStartTime(0.0) - ## #### Multiple Cells ## We can use the mesh generator to generate multiple cells. The first ## parameter of the mesh generator constructor controls the number of @@ -240,6 +239,9 @@ def test_multicell_immersed_boundary_simulation(self): # Specify whether the population has active fluid sources cell_population.SetIfPopulationHasActiveSources(False) + # Set the start time for the simulation + SimulationTime.Instance().SetStartTime(0.0) + # Create a simulator to manage our simulation simulator = OffLatticeSimulation2_2(cell_population) numerical_method = ForwardEulerNumericalMethod2_2() @@ -281,6 +283,105 @@ def test_multicell_immersed_boundary_simulation(self): SimulationTime.Instance().Destroy() TearDownNotebookTest() + ## ### Adding Fluid Sources + ## Now that we are familiar with how to generate the cells, we will + ## introduce fluid sources. + + def test_fluid_source_immersed_boundary_simulation(self): + + ## #### Adding a Fluid Source + ## We begin by constructing a fluid source object. + + source = FluidSource2(0, 0.5, 0.7) + + ## This constructs a `FluidSource` object in 2 dimensions. The first + ## parameter gives the index of the fluid source. Each source you + ## create must have a unique index. The next parameters are the + ## `x` and `y` coordinates of the source. Fluid sources in chaste are + ## point-like, that is to say they do not have any area/volume. + ## + ## Having created the fluid source, we set its strength: + + source.SetStrength(0.012) + + ## Now, we must associate the source with an element in the simulation + ## so that the simulation is aware of the source. + + # Create the mesh + gen = ImmersedBoundaryPalisadeMeshGenerator(5, 128, 0.1, 2.0, 0.0, False) + mesh = gen.GetMesh() + mesh.SetNumGridPtsXAndY(64) + + # Associate the fluid source with an element in the mesh + mesh.GetElement(0).SetFluidSource(source) + + ## Finally, we must tell the cell population that fluid sources are present. + + # Set up the cell population + cell_type = DifferentiatedCellProliferativeType() + cell_generator = CellsGeneratorUniformCellCycleModel_2() + cells = cell_generator.GenerateBasicRandom(mesh.GetNumElements(), cell_type) + cell_population = ImmersedBoundaryCellPopulation2(mesh, cells) + + # Specify that fluid sources are present + cell_population.SetIfPopulationHasActiveSources(True) + + ## #### Varying the Source Location + ## You can experiment with the source location. Try moving it closer to + ## and further away from the cells. + ## + ## #### Varying the Source Strength + ## Try modifying the source strength to see what impact this has on + ## the cell shapes. + + # Create a simulator + SimulationTime.Instance().SetStartTime(0.0) + simulator = OffLatticeSimulation2_2(cell_population) + numerical_method = ForwardEulerNumericalMethod2_2() + numerical_method.SetUseUpdateNodeLocation(True) + simulator.SetNumericalMethod(numerical_method) + + # Add an immersed boundary simulation modifier + main_modifier = ImmersedBoundarySimulationModifier2() + simulator.AddSimulationModifier(main_modifier) + + ## #### Fluid-Cell Interaction + ## Have a go at modifying the spring constant of the + ## `ImmersedBoundaryLinearMembraneForce` to see how this changes the + ## effect of the fluid source on the cells. + + boundary_force = ImmersedBoundaryLinearMembraneForce2() + boundary_force.SetElementSpringConst(1.0 * 1e7) + main_modifier.AddImmersedBoundaryForce(boundary_force) + + interaction_force = ImmersedBoundaryLinearInteractionForce2() + interaction_force.SetSpringConst(1.0 * 1e6) + main_modifier.AddImmersedBoundaryForce(interaction_force) + + ## #### Adding More Sources + ## Try adding second fluid source. You will need to use a unique index, + ## and attach it to a different element as each element can only manage + ## a single fluid source. + + # Set simulation properties + dt = 0.05 + simulator.SetOutputDirectory("Python/TestImmersedBoundary") + simulator.SetDt(dt) + simulator.SetSamplingTimestepMultiple(4) + simulator.SetEndTime(1000 * dt) + + # Perform the simulation + simulator.Solve() + + SimulationTime.Instance().Destroy() + TearDownNotebookTest() + + ## #### Further Exercises + ## * Try integrating a different cell cycle model to introduce cell + ## division. See how the presence of a fluid source impacts the + ## structure that is formed. + ## * Use one of the cell writers to collect some statistics + if __name__ == "__main__": unittest.main(verbosity=2)