void TestParabolicConstructor()
    {
        // Create PDE and boundary condition objects
        MAKE_PTR_ARGS(UniformSourceParabolicPde<2>, p_pde, (-0.1));
        MAKE_PTR_ARGS(ConstBoundaryCondition<2>, p_bc, (1.0));

        // Create a ChasteCuboid on which to base the finite element mesh used to solve the PDE
        ChastePoint<2> lower(-10.0, -10.0);
        ChastePoint<2> upper(10.0, 10.0);
        MAKE_PTR_ARGS(ChasteCuboid<2>, p_cuboid, (lower, upper));

        // Create a PDE modifier and set the name of the dependent variable in the PDE
        MAKE_PTR_ARGS(ParabolicBoxDomainPdeModifier<2>, p_pde_modifier, (p_pde, p_bc, false, p_cuboid, 2.0));
        p_pde_modifier->SetDependentVariableName("averaged quantity");

        // Test that member variables are initialised correctly
        TS_ASSERT_EQUALS(p_pde_modifier->rGetDependentVariableName(), "averaged quantity");

        // Check mesh
        TS_ASSERT_EQUALS(p_pde_modifier->mpFeMesh->GetNumNodes(),121u);
        TS_ASSERT_EQUALS(p_pde_modifier->mpFeMesh->GetNumBoundaryNodes(),40u);
        TS_ASSERT_EQUALS(p_pde_modifier->mpFeMesh->GetNumElements(),200u);
        TS_ASSERT_EQUALS(p_pde_modifier->mpFeMesh->GetNumBoundaryElements(),40u);

        ChasteCuboid<2> bounding_box = p_pde_modifier->mpFeMesh->CalculateBoundingBox();
        TS_ASSERT_DELTA(bounding_box.rGetUpperCorner()[0],10,1e-5);
        TS_ASSERT_DELTA(bounding_box.rGetUpperCorner()[1],10,1e-5);
        TS_ASSERT_DELTA(bounding_box.rGetLowerCorner()[0],-10,1e-5);
        TS_ASSERT_DELTA(bounding_box.rGetLowerCorner()[1],-10,1e-5);

        // Coverage
        TS_ASSERT_EQUALS(p_pde_modifier->GetOutputGradient(),false); // Defaults to false
        p_pde_modifier->SetOutputGradient(true);
        TS_ASSERT_EQUALS(p_pde_modifier->GetOutputGradient(),true);
    }
Exemplo n.º 2
0
CellPtr Cell::Divide()
{
    // Check we're allowed to divide
    assert(!IsDead());
    assert(mCanDivide);
    mCanDivide = false;

    // Reset properties of parent cell
    mpCellCycleModel->ResetForDivision();
    mpSrnModel->ResetForDivision();

    // Create copy of cell property collection to modify for daughter cell
    CellPropertyCollection daughter_property_collection = mCellPropertyCollection;

    // Remove the CellId from the daughter cell, as a new one will be assigned in the constructor
    daughter_property_collection.RemoveProperty<CellId>();

    // Copy all cell data (note we create a new object not just copying the pointer)
    assert(daughter_property_collection.HasPropertyType<CellData>());

    // Get the existing copy of the cell data and remove it from the daughter cell
    boost::shared_ptr<CellData> p_cell_data = GetCellData();
    daughter_property_collection.RemoveProperty(p_cell_data);

    // Create a new cell data object using the copy constructor and add this to the daughter cell
    MAKE_PTR_ARGS(CellData, p_daughter_cell_data, (*p_cell_data));
    daughter_property_collection.AddProperty(p_daughter_cell_data);

    // Copy all cell Vec data (note we create a new object not just copying the pointer)
    if (daughter_property_collection.HasPropertyType<CellVecData>())
    {
        // Get the existing copy of the cell data and remove it from the daughter cell
        boost::shared_ptr<CellVecData> p_cell_vec_data = GetCellVecData();
        daughter_property_collection.RemoveProperty(p_cell_vec_data);

        // Create a new cell data object using the copy constructor and add this to the daughter cell
        MAKE_PTR_ARGS(CellVecData, p_daughter_cell_vec_data, (*p_cell_vec_data));
        daughter_property_collection.AddProperty(p_daughter_cell_vec_data);
    }

    // Create daughter cell with modified cell property collection
    CellPtr p_new_cell(new Cell(GetMutationState(), mpCellCycleModel->CreateCellCycleModel(), mpSrnModel->CreateSrnModel(), false, daughter_property_collection));

    // Initialise properties of daughter cell
    p_new_cell->GetCellCycleModel()->InitialiseDaughterCell();
    p_new_cell->GetSrnModel()->InitialiseDaughterCell();

    // Set the daughter cell to inherit the apoptosis time of the parent cell
    p_new_cell->SetApoptosisTime(mApoptosisTime);

    return p_new_cell;
}
Exemplo n.º 3
0
OffLatticeSimulation<ELEMENT_DIM,SPACE_DIM>::OffLatticeSimulation(AbstractCellPopulation<ELEMENT_DIM,SPACE_DIM>& rCellPopulation,
                                                bool deleteCellPopulationInDestructor,
                                                bool initialiseCells)
    : AbstractCellBasedSimulation<ELEMENT_DIM,SPACE_DIM>(rCellPopulation, deleteCellPopulationInDestructor, initialiseCells)
{
    if (!dynamic_cast<AbstractOffLatticeCellPopulation<ELEMENT_DIM,SPACE_DIM>*>(&rCellPopulation))
    {
        EXCEPTION("OffLatticeSimulations require a subclass of AbstractOffLatticeCellPopulation.");
    }

    // Different time steps are used for cell-centre and vertex-based simulations
    if (bool(dynamic_cast<AbstractCentreBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>*>(&rCellPopulation)))
    {
        this->mDt = 1.0/120.0; // 30 seconds
    }
    else if (bool(dynamic_cast<VertexBasedCellPopulation<SPACE_DIM>*>(&rCellPopulation)))
    {
        this->mDt = 0.002; // smaller time step required for convergence/stability

        // For VertexBasedCellPopulations we automatically add a T2SwapCellKiller. In order to inhibit T2 swaps
        // the user needs to set the threshold for T2 swaps in the mesh to 0.
        VertexBasedCellPopulation<SPACE_DIM>* p_vertex_based_cell_population = dynamic_cast<VertexBasedCellPopulation<SPACE_DIM>*>(&rCellPopulation);
        MAKE_PTR_ARGS(T2SwapCellKiller<SPACE_DIM>, T2_swap_cell_killer, (p_vertex_based_cell_population));
        this->AddCellKiller(T2_swap_cell_killer);
    }
    else
    {
        // All classes derived from AbstractOffLatticeCellPopulation are covered by the above (except user-derived classes),
        // i.e. if you want to use this class with your own subclass of AbstractOffLatticeCellPopulation, then simply
        // comment out the line below
        NEVER_REACHED;
    }
}
Exemplo n.º 4
0
OffLatticeSimulation<ELEMENT_DIM,SPACE_DIM>::OffLatticeSimulation(AbstractCellPopulation<ELEMENT_DIM,SPACE_DIM>& rCellPopulation,
                                                bool deleteCellPopulationInDestructor,
                                                bool initialiseCells)
    : AbstractCellBasedSimulation<ELEMENT_DIM,SPACE_DIM>(rCellPopulation, deleteCellPopulationInDestructor, initialiseCells)
{
    if (!dynamic_cast<AbstractOffLatticeCellPopulation<ELEMENT_DIM,SPACE_DIM>*>(&rCellPopulation))
    {
        EXCEPTION("OffLatticeSimulations require a subclass of AbstractOffLatticeCellPopulation.");
    }

    // Different time steps are used for cell-centre and vertex-based simulations
    if (dynamic_cast<AbstractCentreBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>*>(&rCellPopulation))
    {
        this->mDt = 1.0/120.0; // 30 seconds
    }
    else
    {
        assert(dynamic_cast<VertexBasedCellPopulation<SPACE_DIM>*>(&rCellPopulation));
        this->mDt = 0.002; // smaller time step required for convergence/stability

        // For VertexBasedCellPopulations we automatically add a T2SwapCellKiller. In order to inhibit T2 swaps
        // the user needs to set the threshold for T2 swaps in the mesh to 0.
        VertexBasedCellPopulation<SPACE_DIM>* p_vertex_based_cell_population = dynamic_cast<VertexBasedCellPopulation<SPACE_DIM>*>(&rCellPopulation);
        MAKE_PTR_ARGS(T2SwapCellKiller<SPACE_DIM>, T2_swap_cell_killer, (p_vertex_based_cell_population));
        this->AddCellKiller(T2_swap_cell_killer);
    }
}
Exemplo n.º 5
0
void AbstractCellPopulation<ELEMENT_DIM, SPACE_DIM>::SetCellAncestorsToLocationIndices()
{
    for (typename AbstractCellPopulation<ELEMENT_DIM, SPACE_DIM>::Iterator cell_iter=this->Begin(); cell_iter!=this->End(); ++cell_iter)
    {
        MAKE_PTR_ARGS(CellAncestor, p_cell_ancestor, (mCellLocationMap[(*cell_iter).get()]));
        cell_iter->SetAncestor(p_cell_ancestor);
    }
}
    /* EMPTYLINE
     *
     *
     * == Test 1 - create a vertex-based crypt simulation ==
     *
     * EMPTYLINE
     *
     * The first test generates a crypt, in which we use a cylindrical vertex mesh,
     * give each cell a fixed cell-cycle model, and enforce sloughing at the top of
     * the crypt.
     */
    void TestVertexBasedCrypt() throw(Exception)
    {
        /* Create a cylindrical mesh, and get the cell location indices. 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.
         */
         CylindricalHoneycombVertexMeshGenerator generator(6, 9);
         Cylindrical2dVertexMesh* p_mesh = generator.GetCylindricalMesh();

        /* Having created a mesh, we now create a {{{std::vector}}} of {{{CellPtr}}}s.
         * To do this, we the `CryptCellsGenerator` helper class, which is templated over the type
         * of cell model required (here {{{FixedDurationGenerationBasedCellCycleModel}}})
         * and the dimension. We create an empty vector of cells and pass this into the
         * method along with the mesh. The third 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.
         * The last four arguments represent the height below which cells belong to generations 0,
         * 1, 2, 3 and 4, respectively.
         */
        std::vector<CellPtr> cells;
        CryptCellsGenerator<FixedDurationGenerationBasedCellCycleModel> cells_generator;
        cells_generator.Generate(cells, p_mesh, std::vector<unsigned>(), true, 1.0, 2.0, 3.0, 4.0);

        /* Create a cell population, as before. */
        VertexBasedCellPopulation<2> crypt(*p_mesh, cells);

        /* Create a simulator as before (except setting a different output directory). */
        CryptSimulation2d simulator(crypt);
        simulator.SetOutputDirectory("VertexCrypt");
        simulator.SetEndTime(0.1);

        /* Before running the simulation, we add a one or more force laws, which determine the mechanics of
         * the cell population.  For this test, we use a {{{NagaiHondaForce}}}.
         */
        MAKE_PTR(NagaiHondaForce<2>, p_force);
        simulator.AddForce(p_force);

        /* The {{{NagaiHondaForce}}} requires us to add a child class of {{{AbstractTargetAreaModifier}}} to the simulation.
         * This modifier assigns and updates target areas to each cell throughout the simulation. The target
         * areas are in turn used by the force law to determine the pressure forces on each vertex.
         */
        MAKE_PTR(SimpleTargetAreaModifier<2>, p_growth_modifier);
        simulator.AddSimulationModifier(p_growth_modifier);

        /* Before running the simulation, we add a cell killer. This object
         * dictates conditions under which cells die. For this test, we use
         * a {{{SloughingCellKiller}}}, which kills cells above a certain height.
         */
        double crypt_length = 6.0;
        MAKE_PTR_ARGS(SloughingCellKiller<2>, p_killer, (&crypt, crypt_length));
        simulator.AddCellKiller(p_killer);

        /* To run the simulation, we call {{{Solve()}}}. */
        simulator.Solve();
    }
    void TestStandardResultForArchivingTestsBelow() throw (Exception)
    {
        EXIT_IF_PARALLEL;    // HoneycombMeshGenereator does not work in parallel.

        // Create a simple mesh
        int num_cells_depth = 5;
        int num_cells_width = 5;
        HoneycombMeshGenerator generator(num_cells_width, num_cells_depth, 0);
        TetrahedralMesh<2,2>* p_generating_mesh = generator.GetMesh();

        // Convert this to a NodesOnlyMesh
        NodesOnlyMesh<2> mesh;
        mesh.ConstructNodesWithoutMesh(*p_generating_mesh, 1.5);

        // Create cells
        std::vector<CellPtr> cells;
        CellsGenerator<FixedDurationGenerationBasedCellCycleModel, 2> cells_generator;
        cells_generator.GenerateBasicRandom(cells, mesh.GetNumNodes());

        // Create a node based cell population
        NodeBasedCellPopulation<2> node_based_cell_population(mesh, cells);

        // Set up cell-based simulation
        OffLatticeSimulation<2> simulator(node_based_cell_population);
        simulator.SetOutputDirectory("TestOffLatticeSimulationWithNodeBasedCellPopulationStandardResult");
        simulator.SetEndTime(2.5);

        // Create a force law and pass it to the simulation
        MAKE_PTR(GeneralisedLinearSpringForce<2>, p_linear_force);
        p_linear_force->SetCutOffLength(1.5);
        simulator.AddForce(p_linear_force);

        // Create some boundary conditions and pass them to the simulation
        c_vector<double,2> normal = zero_vector<double>(2);
        normal(1) =-1.0;
        MAKE_PTR_ARGS(PlaneBoundaryCondition<2>, p_bc, (&node_based_cell_population, zero_vector<double>(2), normal)); // y>0
        simulator.AddCellPopulationBoundaryCondition(p_bc);

        // Solve
        simulator.Solve();

        // Check some results
        mNode3x = 3.0454;
        mNode3y = 0.0000;
        mNode4x = 4.0468;
        mNode4y = 0.0101;

        std::vector<double> node_3_location = simulator.GetNodeLocation(3);
        TS_ASSERT_DELTA(node_3_location[0], mNode3x, 1e-4);
        TS_ASSERT_DELTA(node_3_location[1], mNode3y, 1e-4);

        std::vector<double> node_4_location = simulator.GetNodeLocation(4);
        TS_ASSERT_DELTA(node_4_location[0], mNode4x, 1e-4);
        TS_ASSERT_DELTA(node_4_location[1], mNode4y, 1e-4);
    }
    // Testing Save()
    void TestSave() throw (Exception)
    {
        EXIT_IF_PARALLEL; // HoneycombMeshGenereator does not work in parallel

        // Create a simple mesh
        unsigned num_cells_depth = 5;
        unsigned num_cells_width = 5;
        HoneycombMeshGenerator generator(num_cells_width, num_cells_depth, 0);
        TetrahedralMesh<2,2>* p_generating_mesh = generator.GetMesh();

        // Convert this to a NodesOnlyMesh
        NodesOnlyMesh<2> mesh;
        mesh.ConstructNodesWithoutMesh(*p_generating_mesh, 1.5);

        // Create cells
        std::vector<CellPtr> cells;
        CellsGenerator<FixedDurationGenerationBasedCellCycleModel, 2> cells_generator;
        cells_generator.GenerateBasicRandom(cells, mesh.GetNumNodes());

        // Create a node based cell population
        NodeBasedCellPopulation<2> node_based_cell_population(mesh, cells);

        // Set up cell-based simulation
        OffLatticeSimulation<2> simulator(node_based_cell_population);
        simulator.SetOutputDirectory("TestOffLatticeSimulationWithNodeBasedCellPopulationSaveAndLoad");
        simulator.SetEndTime(0.1);

        // Create a force law and pass it to the simulation
        MAKE_PTR(GeneralisedLinearSpringForce<2>, p_linear_force);
        p_linear_force->SetCutOffLength(1.5);
        simulator.AddForce(p_linear_force);

        // Create some boundary conditions and pass them to the simulation
        c_vector<double,2> normal = zero_vector<double>(2);
        normal(1) =-1.0;
        MAKE_PTR_ARGS(PlaneBoundaryCondition<2>, p_bc, (&node_based_cell_population, zero_vector<double>(2), normal)); // y>0
        simulator.AddCellPopulationBoundaryCondition(p_bc);

        /*
         * For more thorough testing of serialization, we 'turn on' adaptivity.
         * Note that this has no effect on the numerical results, since the
         * conditions under which the time step would be adapted are not invoked
         * in this example.
         */
        boost::shared_ptr<AbstractNumericalMethod<2,2> > p_method(new ForwardEulerNumericalMethod<2,2>());
        p_method->SetUseAdaptiveTimestep(true);
        simulator.SetNumericalMethod(p_method);

        // Solve
        simulator.Solve();

        // Save the results
        CellBasedSimulationArchiver<2, OffLatticeSimulation<2> >::Save(&simulator);
    }
    /*
     * The results may be visualized using {{{Visualize2dCentreCells}}} as described in the
     * previous test, with the results directory changed from {{{CellBasedDemo5}}} to {{{CellBasedDemo6}}}.
     *
     * == Test 7 - basic Potts-based simulation ==
     *
     * In the final test we show how to modify the earlier tests (using off lattice models) to implement a 'Potts-based' simulation,
     * in which cells are represented by collections of sites on a fixed lattice.
     */
    void TestPottsBasedMonolayer() throw (Exception)
    {
        /* In common with the off lattice simulations we begin by creating a mesh. Here we use the {{{PottsMeshGenerator}}}
         * class to generate a {{{PottsMesh}}} each element in the mesh is a collection of lattice sites (represented by nodes at their centres).
         * All the connectivity between lattice sites is defined by the {{{PottsMeshGenerator}}},
         * and there are arguments to make the domains periodic.
         */
        PottsMeshGenerator<2> generator(20, 2, 4, 20, 2, 4); //**Changed**//
        PottsMesh<2>* p_mesh = generator.GetMesh(); //**Changed**//

        /* We generate one cell for each element as in vertex based simulations.*/
        std::vector<CellPtr> cells;
        MAKE_PTR(TransitCellProliferativeType, p_transit_type);
        CellsGenerator<StochasticDurationCellCycleModel, 2> cells_generator;
        cells_generator.GenerateBasicRandom(cells, p_mesh->GetNumElements(), p_transit_type);

        /* As we have a {{{PottsMesh}}} we use a {{{PottsBasedCellPopulation}}}. Note here we also change the
         * "temperature" of the Potts simulation to make cells more motile.*/
        PottsBasedCellPopulation<2> cell_population(*p_mesh, cells);//**Changed**//
        cell_population.SetTemperature(1.0);

        /* As a Potts simulation is restricted to a lattice we create a {{{OnSimulation}}} object and pass in the {{{CellPopulation}}} in much the same
         * way as an {{{OffLatticeSimulation}}} in the above examples. We also set some
         * options on the simulation like output directory and end time.
         */
        OnLatticeSimulation<2> simulator(cell_population);//**Changed**//
        simulator.SetOutputDirectory("CellBasedDemo7"); //**Changed**//
        simulator.SetEndTime(20.0);

        /* In order to specify how cells move around we create "shared pointers" to
         * {{{UpdateRule}}} objects and pass them to the {{{OnLatticeSimulation}}}.
         * This is analogous to {{{Forces}}} in earlier examples.
         */
        MAKE_PTR(VolumeConstraintPottsUpdateRule<2>, p_volume_constraint_update_rule); //**Changed**//
        simulator.AddPottsUpdateRule(p_volume_constraint_update_rule); //**Changed**//
        MAKE_PTR(SurfaceAreaConstraintPottsUpdateRule<2>, p_surface_area_update_rule); //**Changed**//
        simulator.AddPottsUpdateRule(p_surface_area_update_rule); //**Changed**//
        MAKE_PTR(AdhesionPottsUpdateRule<2>, p_adhesion_update_rule); //**Changed**//
        simulator.AddPottsUpdateRule(p_adhesion_update_rule); //**Changed**//

        /* We can add {{{CellKillers}}} as before.*/
        MAKE_PTR_ARGS(RandomCellKiller<2>, p_cell_killer, (&cell_population, 0.01));
        simulator.AddCellKiller(p_cell_killer);

        /* Again we run the simulation by calling the {{{Solve}}} method.*/
        simulator.Solve();

        /* The next two lines are for test purposes only and are not part of this tutorial.
         */
        TS_ASSERT_EQUALS(cell_population.GetNumRealCells(), 16u);
        TS_ASSERT_DELTA(SimulationTime::Instance()->GetTime(), 20.0, 1e-10);
    }
Exemplo n.º 10
0
    /*
     * To visualize the results, open a new terminal, {{{cd}}} to the Chaste directory,
     * then {{{cd}}} to {{{anim}}}. Then do: {{{java Visualize2dVertexCells /tmp/$USER/testoutput/CellBasedDemo1/results_from_time_0}}}.
     * We may have to do: {{{javac Visualize2dVertexCells.java}}} beforehand to create the
     * java executable.
     *
     * EMPTYLINE
     *
     * The {{{make_a_movie}}} script can be used to generate a video based on the results of your simulation.
     * To do this, first visualize the results using {{{Visualize2dVertexCells}}} as described above. Click
     * on the box marked "Output" and play through the whole simulation to generate a sequence of {{{.png}}}
     * images, one for each time step. Next, still in the {{{anim}}} folder, do: {{{./make_a_movie}}}.
     * This reads in the {{{.png}}} files and creates a video file called {{{simulation.mpeg}}}.
     *
     * EMPTYLINE
     *
     * Results can also be visualized using Paraview. See the UserTutorials/VisualizingWithParaview tutorial for more information.
     *
     * EMPTYLINE
     *
     * == Test 2 - basic node-based simulation ==
     *
     * We next show how to modify the previous test to implement a 'node-based' simulation,
     * in which cells are represented by overlapping spheres (actually circles, since we're
     * in 2D).
     */
    void TestNodeBasedMonolayer() throw (Exception)
    {
        /* We now need to create a {{{NodesOnlyMesh}}} we do this by first creating a {{{MutableMesh}}}
         * and passing this to a helper method {{{ConstructNodesWithoutMesh}}} along with a interaction cut off length
         * that defines the connectivity in the mesh.
         */
        HoneycombMeshGenerator generator(2, 2); //**Changed**//
        MutableMesh<2,2>* p_generating_mesh = generator.GetMesh(); //**Changed**//
        NodesOnlyMesh<2> mesh; //**Changed**//
        mesh.ConstructNodesWithoutMesh(*p_generating_mesh, 1.5); //**Changed**//

        /* We create the cells as before, only this time we need one cell per node.*/
        std::vector<CellPtr> cells;
        MAKE_PTR(TransitCellProliferativeType, p_transit_type);
        CellsGenerator<StochasticDurationCellCycleModel, 2> cells_generator;
        cells_generator.GenerateBasicRandom(cells, mesh.GetNumNodes(), p_transit_type); //**Changed**//

        /* This time we create a {{{NodeBasedCellPopulation}}} as we are using a {{{NodesOnlyMesh}}}.*/
        NodeBasedCellPopulation<2> cell_population(mesh, cells);//**Changed**//

        /* We create an {{{OffLatticeSimulation}}} object as before, all we change is the output directory
         * and output results more often as a larger default timestep is used for these simulations. */
        OffLatticeSimulation<2> simulator(cell_population);
        simulator.SetOutputDirectory("CellBasedDemo2"); //**Changed**//
        simulator.SetSamplingTimestepMultiple(12); //**Changed**//
        simulator.SetEndTime(20.0);

        /* We use a different {{{Force}}} which is suitable for node based simulations.
         */
        MAKE_PTR(RepulsionForce<2>, p_force); //**Changed**//
        simulator.AddForce(p_force);

        /* In all types of simulation you may specify how cells are removed from the simulation by specifying
         * a {{{CellKiller}}}. You create these in the same was as the {{{Force}}} and pass them to the {{{CellBasedSimulation}}}.
         * Note that here the constructor for {{{RandomCellKiller}}} requires some arguments to be passed to it, therefore we use the
         * {{{MAKE_PTR_ARGS}}} macro.
         */
        MAKE_PTR_ARGS(RandomCellKiller<2>, p_cell_killer, (&cell_population, 0.01)); //**Changed**//
        simulator.AddCellKiller(p_cell_killer);

        /* Again we call the {{{Solve}}} method on the simulation to run the simulation.*/
        simulator.Solve();

        /* The next two lines are for test purposes only and are not part of this tutorial.
         * Again, we are checking that we reached the end time of the simulation
         * with the correct number of cells.
         */
        TS_ASSERT_EQUALS(cell_population.GetNumRealCells(), 7u);
        TS_ASSERT_DELTA(SimulationTime::Instance()->GetTime(), 20.0, 1e-10);
    }
    /*
     * EMPTYLINE
     *
     * To visualize the results, open a new terminal, {{{cd}}} to the Chaste directory,
     * then {{{cd}}} to {{{anim}}}. Then do: {{{java Visualize2dVertexCells /tmp/$USER/testoutput/VertexCrypt/results_from_time_0}}}.
     * You may have to do: {{{javac Visualize2dVertexCells.java}}} beforehand to create the
     * java executable.
     *
     * EMPTYLINE
     *
     * When we visualize the results, we should see three colours of cells: a row of blue stem cells, 3 rows of yellow transit
     * cells, and 5 rows of pink differentiated cells. Cells above 6.0 will be sloughed off immediately.
     *
     * EMPTYLINE
     *
     * == Test 2 - create a vertex-based crypt simulation with a simple wnt dependent cell-cycle model ==
     *
     * EMPTYLINE
     *
     * The next test generates a crypt, in which we use a cylindrical vertex mesh, and
     * impose a linearly decreasing concentration gradient of Wnt. Cells detect the level of Wnt
     * at their centre and those that are in a region of sufficient Wnt are defined to be transit cells,
     * whilst those above this Wnt threshold are defined to be differentiated. The cell cycle length of
     * transit cells is then assigned randomly from a uniform distribution.
     */
    void TestVertexBasedCryptWithSimpleWntCellCycleModel() throw(Exception)
    {
        /* Create a cylindrical mesh, and get the cell location indices, as before. */
        CylindricalHoneycombVertexMeshGenerator generator(6, 9);
        Cylindrical2dVertexMesh* p_mesh = generator.GetCylindricalMesh();

        /* Create a {{{std::vector}}} of {{{CellPtr}}}s.
         * Generate cells, which are assigned a {{{SimpleWntCellCycleModel}}} using
         * the {{{CryptCellsGenerator}}}. The final boolean argument 'true' indicates
         * to assign randomly chosen birth times.
         */
        std::vector<CellPtr> cells;
        CryptCellsGenerator<SimpleWntCellCycleModel> cells_generator;
        cells_generator.Generate(cells, p_mesh, std::vector<unsigned>(), true);

        /* Create a cell population, as before. */
        VertexBasedCellPopulation<2> crypt(*p_mesh, cells);

        /* Define the crypt length; this will be used for sloughing and calculating the Wnt gradient. */
        double crypt_length = 6.0;

        /* Set up a {{{WntConcentration}}} object, as in UserTutorials/RunningMeshBasedCryptSimulations. */
        WntConcentration<2>::Instance()->SetType(LINEAR);
        WntConcentration<2>::Instance()->SetCellPopulation(crypt);
        WntConcentration<2>::Instance()->SetCryptLength(crypt_length);

        /* Create a simulator as before, and add a force law, the target area modifier and a sloughing cell killer to it. */
        CryptSimulation2d simulator(crypt);
        simulator.SetOutputDirectory("VertexCryptWithSimpleWntCellCycleModel");
        simulator.SetEndTime(0.1);

        MAKE_PTR(NagaiHondaForce<2>, p_force);
        simulator.AddForce(p_force);

        MAKE_PTR(SimpleTargetAreaModifier<2>, p_growth_modifier);
        simulator.AddSimulationModifier(p_growth_modifier);

        MAKE_PTR_ARGS(SloughingCellKiller<2>, p_killer, (&crypt, crypt_length));
        simulator.AddCellKiller(p_killer);

        /* Here we impose a boundary condition at the base: that cells
        * at the bottom of the crypt are repelled if they move past 0.*/
        simulator.UseJiggledBottomCells();

        /* Run the simulation, by calling {{{Solve()}}}. */
        simulator.Solve();
    }
    void TestPottsMonolayerWithDeath() throw (Exception)
    {
        EXIT_IF_PARALLEL;    // Potts simulations don't work in parallel because they depend on NodesOnlyMesh for writing.

        // Create a simple 2D PottsMesh
        PottsMeshGenerator<2> generator(16, 4, 4, 24, 8, 2);
        PottsMesh<2>* p_mesh = generator.GetMesh();

        // Create cells
        std::vector<CellPtr> cells;
        MAKE_PTR(DifferentiatedCellProliferativeType, p_diff_type);
        CellsGenerator<FixedDurationGenerationBasedCellCycleModel, 2> cells_generator;
        cells_generator.GenerateBasicRandom(cells, p_mesh->GetNumElements(), p_diff_type);

        // Create cell population
        PottsBasedCellPopulation<2> cell_population(*p_mesh, cells);

        // Set up cell-based simulation
        OnLatticeSimulation<2> simulator(cell_population);
        simulator.SetOutputDirectory("TestPottsMonolayerWithDeath");
        simulator.SetDt(0.1);
        simulator.SetEndTime(1.0);

        // Create update rules and pass to the simulation
        MAKE_PTR(VolumeConstraintPottsUpdateRule<2>, p_volume_constraint_update_rule);
        simulator.AddPottsUpdateRule(p_volume_constraint_update_rule);
        MAKE_PTR(AdhesionPottsUpdateRule<2>, p_adhesion_update_rule);
        simulator.AddPottsUpdateRule(p_adhesion_update_rule);

        // Create cell killer and pass in to simulation
        c_vector<double,2> point = zero_vector<double>(2);
        point(1) = 16.0;
        c_vector<double,2> normal = zero_vector<double>(2);
        normal(1) = 1.0;
        MAKE_PTR_ARGS(PlaneBasedCellKiller<2>, p_killer, (&cell_population, point, normal));
        simulator.AddCellKiller(p_killer);

        // Run simulation
        simulator.Solve();

        // Check the number of cells
        TS_ASSERT_EQUALS(simulator.rGetCellPopulation().GetNumRealCells(), 18u);

        // Test no births or deaths
        TS_ASSERT_EQUALS(simulator.GetNumBirths(), 0u);
        TS_ASSERT_EQUALS(simulator.GetNumDeaths(), 14u);
    }
    // Testing Save
    void TestSave() throw (Exception)
    {
        EXIT_IF_PARALLEL; // HoneycombMeshGenereator does not work in parallel

        // Create a simple mesh
        int num_cells_depth = 5;
        int num_cells_width = 5;
        HoneycombMeshGenerator generator(num_cells_width, num_cells_depth, 0);
        TetrahedralMesh<2,2>* p_generating_mesh = generator.GetMesh();

        // Convert this to a NodesOnlyMesh
        NodesOnlyMesh<2> mesh;
        mesh.ConstructNodesWithoutMesh(*p_generating_mesh, 1.5);

        // Create cells
        std::vector<CellPtr> cells;
        CellsGenerator<FixedDurationGenerationBasedCellCycleModel, 2> cells_generator;
        cells_generator.GenerateBasicRandom(cells, mesh.GetNumNodes());

        // Create a node based cell population
        NodeBasedCellPopulation<2> node_based_cell_population(mesh, cells);

        // Set up cell-based simulation
        OffLatticeSimulation<2> simulator(node_based_cell_population);
        simulator.SetOutputDirectory("TestOffLatticeSimulationWithNodeBasedCellPopulationSaveAndLoad");
        simulator.SetEndTime(0.1);

        // Create a force law and pass it to the simulation
        MAKE_PTR(GeneralisedLinearSpringForce<2>, p_linear_force);
        p_linear_force->SetCutOffLength(1.5);
        simulator.AddForce(p_linear_force);

        // Create some boundary conditions and pass them to the simulation
        c_vector<double,2> normal = zero_vector<double>(2);
        normal(1) =-1.0;
        MAKE_PTR_ARGS(PlaneBoundaryCondition<2>, p_bc, (&node_based_cell_population, zero_vector<double>(2), normal)); // y>0
        simulator.AddCellPopulationBoundaryCondition(p_bc);

        // Solve
        simulator.Solve();

        // Save the results
        CellBasedSimulationArchiver<2, OffLatticeSimulation<2> >::Save(&simulator);
    }
Exemplo n.º 14
0
    /*
     * The results may be visualized using {{{Visualize2dCentreCells}}} as described in the
     * previous test, with the results directory changed from {{{CellBasedDemo4}}} to {{{CellBasedDemo5}}}.
     *
     * == Test 6 - basic periodic mesh-based simulation with obstructions ==
     *
     * We next show how to modify the previous test to include one
     * or more 'obstructions' within the domain.
     */
    void TestMeshBasedMonolayerPeriodicSolidBottomBoundary() throw (Exception)
    {
        /* We make the same {{{Mesh}}}, {{{Cells}}}, {{{CellPopulation}}},
         * {{{CellBasedSimulation}}} and forces as before, all we change is the output directory.*/
        CylindricalHoneycombMeshGenerator generator(5, 2, 2);
        Cylindrical2dMesh* p_mesh = generator.GetCylindricalMesh();

        std::vector<unsigned> location_indices = generator.GetCellLocationIndices();
        std::vector<CellPtr> cells;
        MAKE_PTR(StemCellProliferativeType, p_stem_type);
        CellsGenerator<StochasticDurationCellCycleModel, 2> cells_generator;
        cells_generator.GenerateBasicRandom(cells, location_indices.size(), p_stem_type);

        MeshBasedCellPopulationWithGhostNodes<2> cell_population(*p_mesh, cells, location_indices);
        cell_population.AddPopulationWriter<VoronoiDataWriter>();

        OffLatticeSimulation<2> simulator(cell_population);
        simulator.SetOutputDirectory("CellBasedDemo6"); //**Changed**//
        simulator.SetSamplingTimestepMultiple(50);
        simulator.SetEndTime(20.0);

        MAKE_PTR(GeneralisedLinearSpringForce<2>, p_force);
        simulator.AddForce(p_force);

        /* We now want to impose the condition y>0 on the cells. To do this we create a "shared pointer" to a {{{PlaneBoundaryCondition}}}.
         * Much like the {{{RandomCellKiller}}} earlier we pass arguments to the constructor (a point (0,0) on the plane (line in 2D) and an outward pointing normal to the plane (0,-1) ) using the {{{MAKE_PTR_ARGS}}} macro.*/
        c_vector<double,2> point = zero_vector<double>(2);
        c_vector<double,2> normal = zero_vector<double>(2);
        normal(1) = -1.0;
        MAKE_PTR_ARGS(PlaneBoundaryCondition<2>, p_bc, (&cell_population, point, normal));
        simulator.AddCellPopulationBoundaryCondition(p_bc);

        /* Finally we call the {{{Solve}}} method as in all other simulations.*/
        simulator.Solve();

        /* The next two lines are for test purposes only and are not part of this tutorial.
         */
        TS_ASSERT_EQUALS(cell_population.GetNumRealCells(), 20u);
        TS_ASSERT_DELTA(SimulationTime::Instance()->GetTime(), 20.0, 1e-10);
    }
    /*
     * Cellular death has been tested in TestCaMonolayerWithDeath for one cell per lattice site.
     * This test is just to ensure that the above test works when there are multiple cells per lattice site.
     */
    void TestMultipleCellsPerLatticeSiteWithDeath() throw (Exception)
    {
        EXIT_IF_PARALLEL;

        // Reset the maximum cell ID to zero (to account for previous tests)
        CellId::ResetMaxCellId();

        // Create a simple 2D PottsMesh
        PottsMeshGenerator<2> generator(10, 0, 0, 10, 0, 0);
        PottsMesh<2>* p_mesh = generator.GetMesh();

        // Create cells
        std::vector<CellPtr> cells;
        MAKE_PTR(DifferentiatedCellProliferativeType, p_diff_type);
        CellsGenerator<FixedDurationGenerationBasedCellCycleModel, 2> cells_generator;
        cells_generator.GenerateBasicRandom(cells, 2*p_mesh->GetNumNodes(), p_diff_type);

        // Specify where cells lie
        std::vector<unsigned> location_indices;
        for (unsigned index=0; index<p_mesh->GetNumNodes(); index++)
        {
            //adding two cells per lattice site
            location_indices.push_back(index);
            location_indices.push_back(index);
        }
        TS_ASSERT_EQUALS(location_indices.size(),2*p_mesh->GetNumNodes());

        // Create cell population
        CaBasedCellPopulation<2> cell_population(*p_mesh, cells, location_indices, 2);

        // Set up cell-based simulation
        OnLatticeSimulation<2> simulator(cell_population);
        simulator.SetOutputDirectory("TestMultipleCellsPerLatticeSiteWithDeath");
        simulator.SetDt(0.1);
        simulator.SetEndTime(0.1); //only one step as only care about cells being killed

        // No movement rule, as we only care about cell death

        // Add a cell killer that will kill all cells in the top half of the domain
        c_vector<double,2> point = zero_vector<double>(2);
        point[1] = 4.5;
        c_vector<double,2> normal = unit_vector<double>(2,1);
        MAKE_PTR_ARGS(PlaneBasedCellKiller<2>, p_killer, (&cell_population, point, normal)); // v>4.5
        simulator.AddCellKiller(p_killer);

        // Run simulation
        simulator.Solve();

        // Check the number of cells
        TS_ASSERT_EQUALS(simulator.rGetCellPopulation().GetNumRealCells(), 100u);

        // Test no deaths and some births
        TS_ASSERT_EQUALS(simulator.GetNumBirths(), 0u);
        TS_ASSERT_EQUALS(simulator.GetNumDeaths(), 100u);

        // Check cells above y=5.5 (i.e. above index 50) have been killed and removed.
        for (unsigned i=0; i<simulator.rGetCellPopulation().GetNumNodes(); i++)
        {
            if (i < 50)
            {
                TS_ASSERT_EQUALS(simulator.rGetCellPopulation().GetCellsUsingLocationIndex(i).size(), 2u);
            }
            else
            {
                TS_ASSERT_EQUALS(simulator.rGetCellPopulation().GetCellsUsingLocationIndex(i).size(), 0u);
            }
        }
    }
    void TestCaBasedSquareMonolayer()
    {
        PottsMeshGenerator<2> generator(10, 0, 0, 10, 0, 0);
        PottsMesh<2>* p_mesh = generator.GetMesh();

        // Scale so cells are on top of those in the above centre based tests
        p_mesh->Scale(1.0,sqrt(3.0)*0.5);

        // Specify where cells lie
        std::vector<unsigned> location_indices;
        for (unsigned i=0; i<100; i++)
        {
            location_indices.push_back(i);
        }

        std::vector<CellPtr> cells;
        MAKE_PTR(DifferentiatedCellProliferativeType, p_differentiated_type);
        CellsGenerator<UniformCellCycleModel, 2> cells_generator;
        cells_generator.GenerateBasicRandom(cells, location_indices.size(), p_differentiated_type);

        // Make cells with x<5.0 apoptotic (so no source term)
        boost::shared_ptr<AbstractCellProperty> p_apoptotic_property =
            cells[0]->rGetCellPropertyCollection().GetCellPropertyRegistry()->Get<ApoptoticCellProperty>();
        for (unsigned i=0; i<cells.size(); i++)
        {
            c_vector<double,2> cell_location;
            cell_location = p_mesh->GetNode(i)->rGetLocation();
            if (cell_location(0) < 5.0)
            {
                cells[i]->AddCellProperty(p_apoptotic_property);
            }
            // Set initial condition for PDE
            cells[i]->GetCellData()->SetItem("variable",1.0);
        }
        TS_ASSERT_EQUALS(p_apoptotic_property->GetCellCount(), 50u);

        CaBasedCellPopulation<2> cell_population(*p_mesh, cells, location_indices);

        // Set up simulation time for file output
        SimulationTime::Instance()->SetEndTimeAndNumberOfTimeSteps(1.0, 10);

        // Create PDE and boundary condition objects
        MAKE_PTR_ARGS(AveragedSourceParabolicPde<2>, p_pde, (cell_population, 0.1, 1.0, -1.0));
        MAKE_PTR_ARGS(ConstBoundaryCondition<2>, p_bc, (1.0));

        // Create a ChasteCuboid on which to base the finite element mesh used to solve the PDE
        ChastePoint<2> lower(-5.0, -5.0);
        ChastePoint<2> upper(15.0, 15.0);
        MAKE_PTR_ARGS(ChasteCuboid<2>, p_cuboid, (lower, upper));

        // Create a PDE modifier and set the name of the dependent variable in the PDE
        MAKE_PTR_ARGS(ParabolicBoxDomainPdeModifier<2>, p_pde_modifier, (p_pde, p_bc, false, p_cuboid));
        p_pde_modifier->SetDependentVariableName("variable");

        // For coverage, output the solution gradient
        p_pde_modifier->SetOutputGradient(true);
        p_pde_modifier->SetupSolve(cell_population,"TestAveragedParabolicPdeWithNodeOnSquare");

        // Run for 10 time steps
        for (unsigned i=0; i<10; i++)
        {
            SimulationTime::Instance()->IncrementTimeOneStep();
            p_pde_modifier->UpdateAtEndOfTimeStep(cell_population);
            p_pde_modifier->UpdateAtEndOfOutputTimeStep(cell_population);
        }

        // Test the solution at some fixed points to compare with other cell populations
        CellPtr p_cell_0 = cell_population.GetCellUsingLocationIndex(0);
        TS_ASSERT_DELTA(cell_population.GetLocationOfCellCentre(p_cell_0)[0], 0, 1e-4);
        TS_ASSERT_DELTA(cell_population.GetLocationOfCellCentre(p_cell_0)[1], 0.0, 1e-4);
        TS_ASSERT_DELTA( p_cell_0->GetCellData()->GetItem("variable"), 0.8513, 2e-2); // Low tolerance as mesh is slightly larger than for off-lattice models

        // Checking it doesn't change for this cell population
        TS_ASSERT_DELTA(p_cell_0->GetCellData()->GetItem("variable"), 0.8343, 1e-4);
    }
    void TestNodeBasedSquareMonolayer()
    {
        HoneycombMeshGenerator generator(10,10,0);
        MutableMesh<2,2>* p_generating_mesh = generator.GetMesh();
        NodesOnlyMesh<2>* p_mesh = new NodesOnlyMesh<2>;
        p_mesh->ConstructNodesWithoutMesh(*p_generating_mesh, 1.5);

        std::vector<CellPtr> cells;
        MAKE_PTR(DifferentiatedCellProliferativeType, p_differentiated_type);
        CellsGenerator<UniformCellCycleModel, 2> cells_generator;
        cells_generator.GenerateBasicRandom(cells, p_mesh->GetNumNodes(), p_differentiated_type);

        // Make cells with x<5.0 apoptotic (so no source term)
        boost::shared_ptr<AbstractCellProperty> p_apoptotic_property =
                        cells[0]->rGetCellPropertyCollection().GetCellPropertyRegistry()->Get<ApoptoticCellProperty>();
        for (unsigned i=0; i<cells.size(); i++)
        {
            c_vector<double,2> cell_location;
            cell_location = p_mesh->GetNode(i)->rGetLocation();
            if (cell_location(0) < 5.0)
            {
                cells[i]->AddCellProperty(p_apoptotic_property);
            }
            // Set initial condition for PDE
            cells[i]->GetCellData()->SetItem("variable",1.0);
        }
        TS_ASSERT_EQUALS(p_apoptotic_property->GetCellCount(), 50u);

        NodeBasedCellPopulation<2> cell_population(*p_mesh, cells);

        // Set up simulation time for file output
        SimulationTime::Instance()->SetEndTimeAndNumberOfTimeSteps(1.0, 10);

        // Create PDE and boundary condition objects
        MAKE_PTR_ARGS(AveragedSourceParabolicPde<2>, p_pde, (cell_population, 0.1, 1.0, -1.0));
        MAKE_PTR_ARGS(ConstBoundaryCondition<2>, p_bc, (1.0));

        // Create a ChasteCuboid on which to base the finite element mesh used to solve the PDE
        ChastePoint<2> lower(-5.0, -5.0);
        ChastePoint<2> upper(15.0, 15.0);
        MAKE_PTR_ARGS(ChasteCuboid<2>, p_cuboid, (lower, upper));

        // Create a PDE modifier and set the name of the dependent variable in the PDE
        MAKE_PTR_ARGS(ParabolicBoxDomainPdeModifier<2>, p_pde_modifier, (p_pde, p_bc, false, p_cuboid));
        p_pde_modifier->SetDependentVariableName("variable");

        // For coverage, output the solution gradient
        p_pde_modifier->SetOutputGradient(true);
        p_pde_modifier->SetupSolve(cell_population,"TestAveragedParabolicPdeWithNodeOnSquare");

        // Run for 10 time steps
        for (unsigned i=0; i<10; i++)
        {
            SimulationTime::Instance()->IncrementTimeOneStep();
            p_pde_modifier->UpdateAtEndOfTimeStep(cell_population);
            p_pde_modifier->UpdateAtEndOfOutputTimeStep(cell_population);
        }

        // Test the solution at some fixed points to compare with other cell populations
        CellPtr p_cell_0 = cell_population.GetCellUsingLocationIndex(0);
        TS_ASSERT_DELTA(cell_population.GetLocationOfCellCentre(p_cell_0)[0], 0, 1e-4);
        TS_ASSERT_DELTA(cell_population.GetLocationOfCellCentre(p_cell_0)[1], 0.0, 1e-4);
        TS_ASSERT_DELTA( p_cell_0->GetCellData()->GetItem("variable"), 0.8513, 1e-4);

        // Clear memory
        delete p_mesh;
    }
    void TestArchiveParabolicBoxDomainPdeModifier()
    {
        // Create a file for archiving
        OutputFileHandler handler("archive", false);
        handler.SetArchiveDirectory();
        std::string archive_filename = handler.GetOutputDirectoryFullPath() + "ParabolicBoxDomainPdeModifier.arch";

        // Separate scope to write the archive
        {
            // Create PDE and boundary condition objects
            MAKE_PTR_ARGS(UniformSourceParabolicPde<2>, p_pde, (-0.1));
            MAKE_PTR_ARGS(ConstBoundaryCondition<2>, p_bc, (1.0));

            // Create a ChasteCuboid on which to base the finite element mesh used to solve the PDE
            ChastePoint<2> lower(-10.0, -10.0);
            ChastePoint<2> upper(10.0, 10.0);
            MAKE_PTR_ARGS(ChasteCuboid<2>, p_cuboid, (lower, upper));

            // Create a PDE modifier and set the name of the dependent variable in the PDE
            std::vector<double> data(10);
            for (unsigned i=0; i<10; i++)
            {
                data[i] = i + 0.45;
            }
            Vec vector = PetscTools::CreateVec(data);
            ParabolicBoxDomainPdeModifier<2> modifier(p_pde, p_bc, false, p_cuboid, 2.0, vector);
            modifier.SetDependentVariableName("averaged quantity");

            // Create an output archive
            std::ofstream ofs(archive_filename.c_str());
            boost::archive::text_oarchive output_arch(ofs);

            // Serialize via pointer
            AbstractCellBasedSimulationModifier<2,2>* const p_modifier = &modifier;
            output_arch << p_modifier;
        }

        // Separate scope to read the archive
        {
            AbstractCellBasedSimulationModifier<2,2>* p_modifier2;

            // Restore the modifier
            std::ifstream ifs(archive_filename.c_str());
            boost::archive::text_iarchive input_arch(ifs);

            input_arch >> p_modifier2;

            // Test that member variables are correct
            TS_ASSERT_EQUALS((static_cast<ParabolicBoxDomainPdeModifier<2>*>(p_modifier2))->rGetDependentVariableName(), "averaged quantity");
            TS_ASSERT_DELTA((static_cast<ParabolicBoxDomainPdeModifier<2>*>(p_modifier2))->GetStepSize(), 2.0, 1e-5);
            TS_ASSERT_EQUALS((static_cast<ParabolicBoxDomainPdeModifier<2>*>(p_modifier2))->AreBcsSetOnBoxBoundary(), true);

            Vec solution = (static_cast<ParabolicBoxDomainPdeModifier<2>*>(p_modifier2))->GetSolution();
            ReplicatableVector solution_repl(solution);

            TS_ASSERT_EQUALS(solution_repl.GetSize(), 10u);
            for (unsigned i=0; i<10; i++)
            {
                TS_ASSERT_DELTA(solution_repl[i], i + 0.45, 1e-6);
            }

            delete p_modifier2;
        }
    }
    /*
     * This test can be used to generate steady state crypts for use
     * as the starting points of other simulations.
     *
     * You need to specify :
     * the kind of cell-cycle model to use on line 64,
     * WntConcentration on line 69,
     * change any model parameters around line 90,
     * and give the simulator options around line 95.
     */
    void TestGenerateSteadyStateCryptArchives() throw (Exception)
    {
        std::string output_directory = "SteadyStateCrypt";

        double end_of_simulation = 150.0; // hours
        double time_of_each_run = 10.0; // for each run - the more saves and loads the better for testing this

        // Create mesh
        unsigned cells_across = 13;
        unsigned cells_up = 25;
        double crypt_width = 12.1;
        unsigned thickness_of_ghost_layer = 3;

        CylindricalHoneycombMeshGenerator generator(cells_across, cells_up,thickness_of_ghost_layer, crypt_width/cells_across);
        Cylindrical2dMesh* p_mesh = generator.GetCylindricalMesh();

        double crypt_length = cells_up*(sqrt(3.0)/2.0)*crypt_width/cells_across;

        // Get location indices corresponding to real cells
        std::vector<unsigned> location_indices = generator.GetCellLocationIndices();

        SimulationTime* p_simulation_time = SimulationTime::Instance();
        p_simulation_time->SetStartTime(0.0);

        // Set up cells
        std::vector<CellPtr> cells;
        CryptCellsGenerator<StochasticWntCellCycleModel> cells_generator;
        cells_generator.Generate(cells, p_mesh, location_indices, true);

        MeshBasedCellPopulationWithGhostNodes<2> crypt(*p_mesh, cells, location_indices, false, 30.0); // Last parameter adjusts Ghost spring stiffness in line with the linear_force later on

        // Set cell population to output cell types
        crypt.AddCellPopulationCountWriter<CellMutationStatesCountWriter>();

        WntConcentration<2>::Instance()->SetType(LINEAR);
        WntConcentration<2>::Instance()->SetWntConcentrationParameter(1.0/3.0);
        WntConcentration<2>::Instance()->SetCellPopulation(crypt);
        WntConcentration<2>::Instance()->SetCryptLength(crypt_length);

        CryptSimulation2d simulator(crypt);
        simulator.SetOutputDirectory(output_directory);

        // Set length of simulation here
        simulator.SetEndTime(time_of_each_run);

        // Create a force law and pass it to the simulation
        MAKE_PTR(GeneralisedLinearSpringForce<2>, p_linear_force);
        simulator.AddForce(p_linear_force);

        MAKE_PTR_ARGS(SloughingCellKiller<2>, p_killer, (&simulator.rGetCellPopulation(), crypt_length));
        simulator.AddCellKiller(p_killer);

        // UNUSUAL SET UP HERE /////////////////////////////////////
        p_linear_force->SetMeinekeSpringStiffness(30.0); //normally 15.0;
        // 0.3/30 = 0.01 (i.e. Meineke's values)

        simulator.UseJiggledBottomCells();
        // END OF UNUSUAL SET UP! //////////////////////////////////

        simulator.Solve();
        CellBasedSimulationArchiver<2, CryptSimulation2d>::Save(&simulator);

        /*
        * HOW_TO_TAG Cell Based/Simulation
        * Save and load ('checkpoint') a cell-based simulation to file.
        */
        for (double t=time_of_each_run; t<end_of_simulation+0.5; t += time_of_each_run)
        {
            CryptSimulation2d* p_simulator = CellBasedSimulationArchiver<2, CryptSimulation2d>::Load("SteadyStateCrypt",t);
            p_simulator->SetEndTime(t+time_of_each_run);
            p_simulator->Solve();
            CellBasedSimulationArchiver<2, CryptSimulation2d>::Save(p_simulator);
            delete p_simulator;
        }

        SimulationTime::Destroy();
        RandomNumberGenerator::Destroy();
        WntConcentration<2>::Destroy();
    }
    void Test2DVertexCryptRepresentativeSimulationForProfiling()
    {
        // Set start time
        SimulationTime::Instance()->SetStartTime(0.0);

        // Create mesh
        unsigned crypt_width = 18;
        unsigned crypt_height = 25;
        CylindricalHoneycombVertexMeshGenerator generator(crypt_width, crypt_height, true);
        Cylindrical2dVertexMesh* p_mesh = generator.GetCylindricalMesh();

        // Make crypt shorter for sloughing
        double crypt_length = 20.0;

        // Create cells
        std::vector<CellPtr> cells;
        MAKE_PTR(WildTypeCellMutationState, p_state);
        MAKE_PTR(TransitCellProliferativeType, p_transit_type);
        for (unsigned elem_index=0; elem_index<p_mesh->GetNumElements(); elem_index++)
        {
            SimpleWntCellCycleModel* p_model = new SimpleWntCellCycleModel;
            p_model->SetDimension(2);

            double birth_time = - RandomNumberGenerator::Instance()->ranf()*
                                             ( p_model->GetTransitCellG1Duration()
                                                + p_model->GetSG2MDuration() );

            CellPtr p_cell(new Cell(p_state, p_model));
            p_cell->SetCellProliferativeType(p_transit_type);
            p_cell->SetBirthTime(birth_time);
            cells.push_back(p_cell);
        }

        // Create cell population
        VertexBasedCellPopulation<2> crypt(*p_mesh, cells);

        // Set up Wnt gradient
        WntConcentration<2>::Instance()->SetType(LINEAR);
        WntConcentration<2>::Instance()->SetCellPopulation(crypt);
        WntConcentration<2>::Instance()->SetCryptLength(crypt_length);

        // Create crypt simulation from cell population and force law
        CryptSimulation2d simulator(crypt);
        simulator.SetSamplingTimestepMultiple(50);
        simulator.SetEndTime(30.0);
        simulator.SetOutputDirectory("Test2DVertexCryptRepresentativeSimulationForProfiling");

        // Create a force law and pass it to the simulation
        MAKE_PTR(NagaiHondaForce<2>, p_nagai_honda_force);
        simulator.AddForce(p_nagai_honda_force);

        // ...and with that the target area modifier
        MAKE_PTR(SimpleTargetAreaModifier<2>, p_growth_modifier);
        simulator.AddSimulationModifier(p_growth_modifier);

        // Add a cell killer
        MAKE_PTR_ARGS(SloughingCellKiller<2>, p_killer, (&crypt, crypt_length));
        simulator.AddCellKiller(p_killer);

        // Run simulation
        simulator.Solve();

        // Tidy up
        WntConcentration<2>::Destroy();
    }
Exemplo n.º 21
0
    void TestMeshBasedCryptWithMutations() throw(Exception)
    {
    	EXIT_IF_PARALLEL;

      double time_of_each_run = 10.0;
      double end_simulations = 600.0;

      CylindricalHoneycombMeshGenerator generator(10, 10, 2);
      Cylindrical2dMesh* p_mesh = generator.GetCylindricalMesh();

      std::vector<unsigned> location_indices = generator.GetCellLocationIndices();

      std::vector<CellPtr> cells;
      CryptCellsGenerator<StochasticWntCellCycleModel> cells_generator;
      cells_generator.Generate(cells, p_mesh, location_indices, true);

      boost::shared_ptr<AbstractCellProperty> p_state(CellPropertyRegistry::Instance()->Get<ApcTwoHitCellMutationState>());

      MeshBasedCellPopulationWithGhostNodes<2> cell_population(*p_mesh, cells, location_indices);

      cell_population.AddCellPopulationCountWriter<CellMutationStatesCountWriter>();
      cell_population.SetCellAncestorsToLocationIndices();

      double crypt_height = 8.0;

      WntConcentration<2>::Instance()->SetType(LINEAR);
      WntConcentration<2>::Instance()->SetCellPopulation(cell_population);
      WntConcentration<2>::Instance()->SetCryptLength(crypt_height);

      CryptSimulation2d simulator(cell_population);
      simulator.SetOutputDirectory("MeshBasedCryptWithMutations");
      simulator.SetSamplingTimestepMultiple(100);
      simulator.SetEndTime(10);

      //modify at end of timestep

      MAKE_PTR(SimulationEndTimeModifier<2>, p_modifier);
      simulator.AddSimulationModifier(p_modifier);
 

      cell_population.AddCellWriter<CellAncestorWriter>();

      MAKE_PTR(GeneralisedLinearSpringForce<2>, p_linear_force);
      simulator.AddForce(p_linear_force);
      MAKE_PTR_ARGS(SloughingCellKiller<2>, p_killer, (&cell_population, crypt_height));
      simulator.AddCellKiller(p_killer);

      simulator.Solve();

      for (AbstractCellPopulation<2>::Iterator cell_iter = cell_population.Begin();
          cell_iter != cell_population.End();
          ++cell_iter)
      {
        unsigned node_index = cell_population.GetLocationIndexUsingCell(*cell_iter);

        if (node_index == 132) // Chosen from looking at the results from steady state
        {
          cell_iter->SetMutationState(p_state);
        }
      }

      double normal_damping_constant = cell_population.GetDampingConstantNormal();
      cell_population.SetDampingConstantMutant(10*normal_damping_constant);

      CellBasedSimulationArchiver<2, CryptSimulation2d>::Save(&simulator);

      simulator.SetEndTime(20);

      for (double t = time_of_each_run; t<end_simulations+0.5; t += time_of_each_run)
      {
        CryptSimulation2d* p_simulator = CellBasedSimulationArchiver<2, CryptSimulation2d>::Load("MeshBasedCryptWithMutations",t);
        p_simulator->SetEndTime(t+time_of_each_run);
        p_simulator->Solve();
        CellBasedSimulationArchiver<2, CryptSimulation2d>::Save(p_simulator);
        delete p_simulator;
      }

      CellBasedEventHandler::Headings();
      CellBasedEventHandler::Report();

      WntConcentration<2>::Destroy();


    }
Exemplo n.º 22
0
    /**
     * This test runs multiple crypt simulations and records whether
     * or not labelled cells are in a randomly chosen crypt section.
     */
    void TestMultipleCryptSimulations() throw (Exception)
    {
        std::string output_directory = "MakeMoreMeinekeGraphs";

        double crypt_length = 22.0;

        // Create mesh
        unsigned cells_across = 13;
        unsigned cells_up = 25;
        double crypt_width = 12.1;
        unsigned thickness_of_ghost_layer = 3;

        unsigned num_simulations = 2;

        // Guess of maximum number of cells a crypt section may contain
        unsigned max_length_of_crypt_section = 5 * (unsigned)sqrt(pow(cells_across/2.0+1,2.0) + pow((double)cells_up,2.0));

        std::vector<unsigned> labelled_cells_counter(max_length_of_crypt_section);

        for (unsigned i=0; i<max_length_of_crypt_section; i++)
        {
            labelled_cells_counter[i] = 0;
        }

        double time_of_each_run;
        std::vector<bool> labelled;

        CryptStatistics* p_crypt_statistics;

        // Create cell population
        MeshBasedCellPopulationWithGhostNodes<2>* p_crypt;

        CylindricalHoneycombMeshGenerator generator(cells_across, cells_up, thickness_of_ghost_layer, crypt_width/cells_across);
        std::vector<unsigned> location_indices;

        Cylindrical2dMesh* p_mesh;
        SimulationTime* p_simulation_time;

        // Loop over the number of simulations
        for (unsigned simulation_index=0; simulation_index<num_simulations; simulation_index++)
        {
            // Create new structures for each simulation
            p_mesh = generator.GetCylindricalMesh();
            location_indices = generator.GetCellLocationIndices();

            // Reset start time
            SimulationTime::Destroy();
            p_simulation_time = SimulationTime::Instance();
            p_simulation_time->SetStartTime(0.0);

            // Set up cells
            std::vector<CellPtr> temp_cells;
            CryptCellsGenerator<StochasticDurationGenerationBasedCellCycleModel> cells_generator;
            cells_generator.Generate(temp_cells, p_mesh, std::vector<unsigned>(), true, 0.3, 2.0, 3.0, 4.0, true);

            // This awkward way of setting up the cells is a result of #430
            std::vector<CellPtr> cells;
            for (unsigned i=0; i<location_indices.size(); i++)
            {
                cells.push_back(temp_cells[location_indices[i]]);
            }

            // Set up crypt
            p_crypt = new MeshBasedCellPopulationWithGhostNodes<2>(*p_mesh, cells, location_indices);

            // Set cell population to output cell types
            p_crypt->AddPopulationWriter<CellMutationStatesCountWriter>();

            // Set up crypt simulation
            CryptSimulation2d simulator(*p_crypt, false, false);
            simulator.SetOutputDirectory(output_directory);

            // Set length of simulation here
            time_of_each_run = 10.0*simulator.GetDt(); // for each run
            simulator.SetEndTime(time_of_each_run);

            // Create a force laws and pass it to the simulation
            MAKE_PTR(GeneralisedLinearSpringForce<2>, p_linear_force);
            p_linear_force->SetMeinekeSpringStiffness(30.0); // normally 15.0;
            simulator.AddForce(p_linear_force);

            // Set up cell killer
            MAKE_PTR_ARGS(SloughingCellKiller<2>, p_killer, (&simulator.rGetCellPopulation(), crypt_length));
            simulator.AddCellKiller(p_killer);

            simulator.UseJiggledBottomCells();

            // Set up crypt statistics
            p_crypt_statistics = new CryptStatistics(*p_crypt);

            // Run for a bit
            simulator.Solve();
            p_crypt_statistics->LabelSPhaseCells();

            simulator.SetEndTime(2.0*time_of_each_run);
            simulator.Solve();

            std::vector<CellPtr> crypt_section = p_crypt_statistics->GetCryptSection(crypt_length + 2.0, 8.0, 8.0);
            labelled = p_crypt_statistics->AreCryptSectionCellsLabelled(crypt_section);

            // Store information from this simulation in a global vector
            for (unsigned cell_index=0; cell_index < labelled.size(); cell_index++)
            {
                TS_ASSERT(cell_index < labelled_cells_counter.size());

                if (labelled[cell_index])
                {
                    labelled_cells_counter[cell_index]++;
                }
            }

            // Tidy up
            cells.clear();
            labelled.clear();
            WntConcentration<2>::Destroy();

            delete p_crypt_statistics;
            delete p_crypt;
        }

        // Calculate percentage of labelled cells at each position in 'labelled_cells_counter'
        std::vector<double> percentage_of_labelled_cells(max_length_of_crypt_section);
        for (unsigned index=0; index < max_length_of_crypt_section; index ++)
        {
            percentage_of_labelled_cells[index] = (double) labelled_cells_counter[index]/num_simulations;
        }

        // Write data to file
        SimpleDataWriter writer1(output_directory, "percentage_of_labelled_cells.dat", percentage_of_labelled_cells, false);

        // Test against previous run
        // ... and checking visualization of labelled cells against previous run
        OutputFileHandler handler(output_directory, false);
        std::string results_file = handler.GetOutputDirectoryFullPath() + "percentage_of_labelled_cells.dat";
        FileComparison( results_file, "crypt/test/data/MakeMoreMeinekeGraphs/percentage_of_labelled_cells.dat").CompareFiles();

        RandomNumberGenerator::Destroy();
    }
    /*
     * === Testing the cell property ===
     *
     * We begin by testing that our new cell property is implemented correctly.
     */
    void TestMotileCellProperty() throw(Exception)
    {
        /* We begin by testing that some of the base class methods work correctly.
         * We typically use shared pointers to create and access a cell property
         * like {{{MotileCellProperty}}}, for which it makes sense for all cells
         * that have the same mutation to share a pointer to the same cell property
         * object (although strictly speaking, they are not required to). Observe that
         * in this case we have provided a value for the member variable {{{mColour}}}
         * in the {{{MotileCellProperty}}} constructor.*/
        MAKE_PTR_ARGS(MotileCellProperty, p_property, (8));

        /* Each cell property has a member variable, {{{mCellCount}}}, which
         * stores the number of cells with this cell property. We can test whether
         * {{{mCellCount}}} is being updated correctly by our cell property, as follows. */
        TS_ASSERT_EQUALS(p_property->GetCellCount(), 0u);
        p_property->IncrementCellCount();
        TS_ASSERT_EQUALS(p_property->GetCellCount(), 1u);
        p_property->DecrementCellCount();
        TS_ASSERT_EQUALS(p_property->GetCellCount(), 0u);
        TS_ASSERT_THROWS_THIS(p_property->DecrementCellCount(),
                "Cannot decrement cell count: no cells have this cell property");

        /* We can also test whether our cell property is of a given type, as follows. */
        TS_ASSERT_EQUALS(p_property->IsType<WildTypeCellMutationState>(), false);
        TS_ASSERT_EQUALS(p_property->IsType<MotileCellProperty>(), true);

        /* We can also test that archiving is implemented correctly for our cell
         * property, as follows (further details on how to implement and
         * test archiving can be found at ChasteGuides/BoostSerialization).  */
        OutputFileHandler handler("archive", false);
        std::string archive_filename = handler.GetOutputDirectoryFullPath() + "property.arch";

        {
            AbstractCellProperty* const p_const_property = new MotileCellProperty(7);
            p_const_property->IncrementCellCount();

            TS_ASSERT_EQUALS(p_const_property->GetCellCount(), 1u);
            TS_ASSERT_EQUALS(dynamic_cast<MotileCellProperty*>(p_const_property)->GetColour(), 7u);

            std::ofstream ofs(archive_filename.c_str());
            boost::archive::text_oarchive output_arch(ofs);

            output_arch << p_const_property;

            delete p_const_property;
        }

        {
            AbstractCellProperty* p_arch_property;

            std::ifstream ifs(archive_filename.c_str());
            boost::archive::text_iarchive input_arch(ifs);

            input_arch >> p_arch_property;

            TS_ASSERT_EQUALS(p_arch_property->GetCellCount(), 1u);

            MotileCellProperty* p_real_property = dynamic_cast<MotileCellProperty*>(p_arch_property);
            TS_ASSERT(p_real_property != NULL);
            TS_ASSERT_EQUALS(p_real_property->GetColour(), 7u);

            delete p_arch_property;
        }
    }
    /**
     * Create a simulation of a NodeBasedCellPopulation with a NodeBasedCellPopulationMechanicsSystem
     * and a CellKiller. Test that no exceptions are thrown, and write the results to file.
     */
    void TestCellDeath() throw (Exception)
    {
        EXIT_IF_PARALLEL;    // HoneycombMeshGenereator does not work in parallel.

        // Create a simple mesh
        int num_cells_depth = 5;
        int num_cells_width = 5;
        HoneycombMeshGenerator generator(num_cells_width, num_cells_depth, 0);
        TetrahedralMesh<2,2>* p_generating_mesh = generator.GetMesh();

        // Convert this to a NodesOnlyMesh
        NodesOnlyMesh<2> mesh;
        mesh.ConstructNodesWithoutMesh(*p_generating_mesh, 1.5);

        // Create cells
        std::vector<CellPtr> cells;
        CellsGenerator<FixedDurationGenerationBasedCellCycleModel, 2> cells_generator;
        cells_generator.GenerateBasicRandom(cells, mesh.GetNumNodes());

        // Create a node based cell population
        NodeBasedCellPopulation<2> node_based_cell_population(mesh, cells);

        // Set up cell-based simulation
        OffLatticeSimulation<2> simulator(node_based_cell_population);
        simulator.SetOutputDirectory("TestOffLatticeSimulationWithNodeBasedCellPopulationCellPtrDeath");
        simulator.SetEndTime(0.5);

        // Create a force law and pass it to the simulation
        MAKE_PTR(GeneralisedLinearSpringForce<2>, p_linear_force);
        p_linear_force->SetCutOffLength(1.5);
        simulator.AddForce(p_linear_force);

        // Add cell killer
        MAKE_PTR_ARGS(RandomCellKiller<2>, p_killer, (&node_based_cell_population, 0.997877574));
        simulator.AddCellKiller(p_killer);

        // Solve
        simulator.Solve();

        // Check some results
        TS_ASSERT_EQUALS(simulator.GetNumBirths(), 0u);
        TS_ASSERT_EQUALS(simulator.GetNumDeaths(), 20u);

        std::vector<double> node_8_location = simulator.GetNodeLocation(8);
        TS_ASSERT_DELTA(node_8_location[0], 3.4729, 1e-4);
        TS_ASSERT_DELTA(node_8_location[1], 1.0051, 1e-4);

        std::vector<double> node_3_location = simulator.GetNodeLocation(3);
        TS_ASSERT_DELTA(node_3_location[0], 2.9895, 1e-4);
        TS_ASSERT_DELTA(node_3_location[1], 0.3105, 1e-4);

        // Test the results are written correctly
        FileFinder generated_type_file("TestOffLatticeSimulationWithNodeBasedCellPopulationCellPtrDeath/results_from_time_0/results.vizcelltypes", RelativeTo::ChasteTestOutput);
        FileFinder generated_node_file("TestOffLatticeSimulationWithNodeBasedCellPopulationCellPtrDeath/results_from_time_0/results.viznodes", RelativeTo::ChasteTestOutput);

        FileFinder reference_type_file("cell_based/test/data/TestOffLatticeSimulationWithNodeBasedCellPopulationCellPtrDeath/results.vizcelltypes",RelativeTo::ChasteSourceRoot);
        FileFinder reference_node_file("cell_based/test/data/TestOffLatticeSimulationWithNodeBasedCellPopulationCellPtrDeath/results.viznodes",RelativeTo::ChasteSourceRoot);

        FileComparison type_files(generated_type_file,reference_type_file);
        FileComparison node_files(generated_node_file,reference_node_file);
    }
    /*
     * EMPTYLINE
     *
     * Note that you '''cannot view the results of a 3D simulation using the Java visualiser''' but
     * to visualize the results, use Paraview. See the UserTutorials/VisualizingWithParaview tutorial for more information.
     *
     * Load the file {{{/tmp/$USER/testoutput/NodeBasedSpheroid/results_from_time_0/results.pvd}}},
     * and add spherical glyphs to represent cells.
     *
     * EMPTYLINE
     *
     * == Test 3 - a node-based simulation on a restricted geometry ==
     *
     * EMPTYLINE
     *
     * In the third test we run a node-based simulation restricted to the surface of a sphere.
     */
    void TestOnSurfaceOfSphere()
    {
        /** The next line is needed because we cannot currently run node based simulations in parallel. */
        EXIT_IF_PARALLEL;

        /*
         * We begin with exactly the same code as the previous test: we create a cell population
         * from a mesh and vector of cells, and use this in turn to create
         * a simulation object.
         */

        std::vector<Node<3>*> nodes;
        nodes.push_back(new Node<3>(0u,  false,  0.5, 0.0, 0.0));
        nodes.push_back(new Node<3>(1u,  false,  -0.5, 0.0, 0.0));
        nodes.push_back(new Node<3>(2u,  false,  0.0, 0.5, 0.0));
        nodes.push_back(new Node<3>(3u,  false,  0.0, -0.5, 0.0));
        NodesOnlyMesh<3> mesh;
        /* To run node-based simulations you need to define a cut off length (second argument in
         * {{{ConstructNodesWithoutMesh}}}), which defines the connectivity of the nodes by defining
         * a radius of interaction. */
        mesh.ConstructNodesWithoutMesh(nodes, 1.5);

        std::vector<CellPtr> cells;
        MAKE_PTR(TransitCellProliferativeType, p_transit_type);
        CellsGenerator<UniformCellCycleModel, 3> cells_generator;
        cells_generator.GenerateBasicRandom(cells, mesh.GetNumNodes(), p_transit_type);

        NodeBasedCellPopulation<3> cell_population(mesh, cells);

        OffLatticeSimulation<3> simulator(cell_population);
        simulator.SetOutputDirectory("NodeBasedOnSphere");
        simulator.SetSamplingTimestepMultiple(12);
        simulator.SetEndTime(10.0);

        /* As before, we create a linear spring force and pass it to the simulation object. */
        MAKE_PTR(GeneralisedLinearSpringForce<3>, p_force);
        simulator.AddForce(p_force);

        /*
         * This time we create a {{{CellPopulationBoundaryCondition}}} and pass this to
         * the {{{OffLatticeSimulation}}}. Here we use a {{{SphereGeometryBoundaryCondition}}}
         * which restricts cells to lie on a sphere (in 3D) or circle (in 2D).
         *
         * For a list of possible boundary conditions see subclasses of {{{AbstractCellPopulationBoundaryCondition}}}.
         * These can be found in the inheritance diagram, here, [class:AbstractCellPopulationBoundaryCondition AbstractCellPopulationBoundaryCondition].
         * Note that some of these boundary conditions are not compatible with node-based simulations see the specific class documentation for details,
         * if you try to use an incompatible class then you will receive a warning.
         *
         * First we set the centre (0,0,1) and radius of the sphere (1).
         */
        c_vector<double,3> centre = zero_vector<double>(3);
        centre(2) = 1.0;
        double radius = 1.0;
        /* We then make a pointer to the boundary condition using the MAKE_PTR_ARGS macro, and pass
         * it to the {{{OffLatticeSimulation}}}. */
        MAKE_PTR_ARGS(SphereGeometryBoundaryCondition<3>, p_boundary_condition, (&cell_population, centre, radius));
        simulator.AddCellPopulationBoundaryCondition(p_boundary_condition);

        /* To run the simulation, we call {{{Solve()}}}. */
        simulator.Solve();

        /* The next two lines are for test purposes only and are not part of this tutorial.
         */
        TS_ASSERT_EQUALS(cell_population.GetNumRealCells(), 8u);
        TS_ASSERT_DELTA(SimulationTime::Instance()->GetTime(), 10.0, 1e-10);

        /* To avoid memory leaks, we conclude by deleting any pointers that we created in the test.*/
        for (unsigned i=0; i<nodes.size(); i++)
        {
            delete nodes[i];
        }
    }
    void TestArchivingOfCell() throw(Exception)
    {
        OutputFileHandler handler("archive", false);
        handler.SetArchiveDirectory();
        std::string archive_filename = handler.GetOutputDirectoryFullPath() + "cell.arch";

        // Archive a cell
        {
            SimulationTime* p_simulation_time = SimulationTime::Instance();
            p_simulation_time->SetEndTimeAndNumberOfTimeSteps(2.0, 4);

            // Create mutation state
            boost::shared_ptr<AbstractCellProperty> p_healthy_state(CellPropertyRegistry::Instance()->Get<WildTypeCellMutationState>());
            boost::shared_ptr<AbstractCellProperty> p_type(CellPropertyRegistry::Instance()->Get<StemCellProliferativeType>());

            // Create cell-cycle model
            FixedDurationGenerationBasedCellCycleModel* p_cell_model = new FixedDurationGenerationBasedCellCycleModel();

            // Create SRN
            Goldbeter1991SrnModel* p_srn_model = new Goldbeter1991SrnModel();

            // Create cell property collection
            CellPropertyCollection collection;
            MAKE_PTR(CellLabel, p_label);
            collection.AddProperty(p_label);

            // Create cell
            CellPtr p_cell(new Cell(p_healthy_state, p_cell_model, p_srn_model,  false, collection));
            p_cell->SetCellProliferativeType(p_type);
            p_cell->InitialiseCellCycleModel();
            p_cell->InitialiseSrnModel();
            p_simulation_time->IncrementTimeOneStep();

            TS_ASSERT_EQUALS(p_cell->GetAge(), 0.5);
            TS_ASSERT_EQUALS(p_cell->GetAncestor(), UNSIGNED_UNSET);

            // Set ancestor
            MAKE_PTR_ARGS(CellAncestor, p_cell_ancestor, (2u));
            p_cell->SetAncestor(p_cell_ancestor);
            TS_ASSERT_EQUALS(p_cell->GetAncestor(), 2u);

            // Set CellVecData with some actual content
            boost::shared_ptr<AbstractCellProperty> p_vec_data(CellPropertyRegistry::Instance()->Get<CellVecData>());
            p_cell->AddCellProperty(p_vec_data);
            Vec item_1 = PetscTools::CreateAndSetVec(2, -17.3); // <-17.3, -17.3>
            p_cell->GetCellVecData()->SetItem("item 1", item_1);

            // Check properties set correctly
            CellPropertyCollection& final_collection = p_cell->rGetCellPropertyCollection();
            TS_ASSERT_EQUALS(final_collection.GetSize(), 7u);
            TS_ASSERT_EQUALS(final_collection.HasProperty<WildTypeCellMutationState>(), true);
            TS_ASSERT_EQUALS(final_collection.HasProperty<ApcOneHitCellMutationState>(), false);
            TS_ASSERT_EQUALS(final_collection.HasProperty<ApcTwoHitCellMutationState>(), false);
            TS_ASSERT_EQUALS(final_collection.HasProperty<CellLabel>(), true);
            TS_ASSERT_EQUALS(final_collection.HasPropertyType<AbstractCellProperty>(), true);
            TS_ASSERT_EQUALS(final_collection.HasPropertyType<AbstractCellMutationState>(), true);
            TS_ASSERT_EQUALS(final_collection.HasPropertyType<CellAncestor>(), true);
            TS_ASSERT_EQUALS(final_collection.HasPropertyType<CellId>(), true);
            TS_ASSERT_EQUALS(p_cell->GetAncestor(), 2u);

            for (CellPropertyCollection::Iterator it = final_collection.Begin(); it != final_collection.End(); ++it)
            {
                TS_ASSERT_EQUALS(final_collection.HasProperty(*it), true);

                bool is_wildtype = (*it)->IsType<WildTypeCellMutationState>();
                bool is_label = (*it)->IsType<CellLabel>();
                bool is_ancestor = (*it)->IsType<CellAncestor>();
                bool is_cellid = (*it)->IsType<CellId>();
                bool is_data = (*it)->IsType<CellData>();
                bool is_vec_data = (*it)->IsType<CellVecData>();
                bool is_stem = (*it)->IsType<StemCellProliferativeType>();

                bool is_any_of_above = is_wildtype || is_label || is_ancestor || is_cellid || is_data || is_vec_data || is_stem;
                TS_ASSERT_EQUALS(is_any_of_above, true);
            }

            // Create another cell
            boost::shared_ptr<AbstractCellProperty> p_another_healthy_state(CellPropertyRegistry::Instance()->Get<WildTypeCellMutationState>());
            FixedDurationGenerationBasedCellCycleModel* p_another_cell_model = new FixedDurationGenerationBasedCellCycleModel();
            Goldbeter1991SrnModel* p_another_srn_model = new Goldbeter1991SrnModel();
            CellPtr p_another_cell(new Cell(p_another_healthy_state, p_another_cell_model, p_another_srn_model, false, collection));
            boost::shared_ptr<AbstractCellProperty> p_another_vec_data(new CellVecData);
            p_another_cell->AddCellProperty(p_another_vec_data);
            TS_ASSERT_EQUALS(p_cell->GetCellVecData()->GetNumItems(), 1u);
            TS_ASSERT_EQUALS(p_another_cell->GetCellVecData()->GetNumItems(), 0u);
            Vec another_item_1 = PetscTools::CreateAndSetVec(2, 42.0); // <42, 42>

            p_another_cell->GetCellVecData()->SetItem("item 1", another_item_1);

            // Create an output archive
            std::ofstream ofs(archive_filename.c_str());
            boost::archive::text_oarchive output_arch(ofs);

            CellPtr const p_const_cell = p_cell;

            // Write the cell to the archive
            output_arch << static_cast<const SimulationTime&> (*p_simulation_time);
            output_arch << p_const_cell;
            // Write the second cell also
            CellPtr const p_another_const_cell = p_another_cell;
            output_arch << p_another_const_cell;

            // Tidy up
            SimulationTime::Destroy();
            PetscTools::Destroy(item_1);
            PetscTools::Destroy(another_item_1);
        }

        // Restore CellPtr
        {
            // Need to set up time to initialize a cell
            SimulationTime* p_simulation_time = SimulationTime::Instance();
            p_simulation_time->SetStartTime(1.0);
            p_simulation_time->SetEndTimeAndNumberOfTimeSteps(2.0, 1); // will be restored

            // Initialize a cell

            CellPtr p_cell;

            // Restore the cell
            std::ifstream ifs(archive_filename.c_str(), std::ios::binary);
            boost::archive::text_iarchive input_arch(ifs);

            input_arch >> *p_simulation_time;
            input_arch >> p_cell;

            // Check the simulation time has been restored (through the cell)
            TS_ASSERT_EQUALS(p_simulation_time->GetTime(), 0.5);
            TS_ASSERT_EQUALS(p_simulation_time->GetTimeStep(), 0.5);

            TS_ASSERT_EQUALS(p_cell->GetAge(), 0.5);
            TS_ASSERT_EQUALS(static_cast<FixedDurationGenerationBasedCellCycleModel*>(p_cell->GetCellCycleModel())->GetGeneration(), 0u);
            TS_ASSERT(dynamic_cast<Goldbeter1991SrnModel*>(p_cell->GetSrnModel()));
            TS_ASSERT_EQUALS(p_cell->GetCellProliferativeType()->IsType<StemCellProliferativeType>(), true);

            AbstractCellCycleModel* p_cc_model = p_cell->GetCellCycleModel();
            TS_ASSERT_EQUALS(p_cc_model->GetCell(), p_cell);

            AbstractSrnModel* p_srn_model = p_cell->GetSrnModel();
            TS_ASSERT_EQUALS(p_srn_model->GetCell(), p_cell);

            CellPropertyCollection& collection = p_cell->rGetCellPropertyCollection();
            TS_ASSERT_EQUALS(collection.GetSize(), 7u);
            TS_ASSERT_EQUALS(collection.HasProperty<WildTypeCellMutationState>(), true);
            TS_ASSERT_EQUALS(collection.HasProperty<ApcOneHitCellMutationState>(), false);
            TS_ASSERT_EQUALS(collection.HasProperty<ApcTwoHitCellMutationState>(), false);
            TS_ASSERT_EQUALS(collection.HasProperty<CellLabel>(), true);
            TS_ASSERT_EQUALS(collection.HasPropertyType<AbstractCellProperty>(), true);
            TS_ASSERT_EQUALS(collection.HasPropertyType<AbstractCellMutationState>(), true);
            TS_ASSERT_EQUALS(collection.HasPropertyType<CellAncestor>(), true);
            TS_ASSERT_EQUALS(collection.HasPropertyType<CellId>(), true);
            TS_ASSERT_EQUALS(p_cell->GetAncestor(), 2u);

            // Check explicitly for CellVecData as it is not available by default as CellData
            TS_ASSERT_EQUALS(collection.HasPropertyType<CellVecData>(), true);

            // Check that the Vec stored in CellVecData was unarchived correctly
            boost::shared_ptr<CellVecData> p_cell_vec_data = boost::static_pointer_cast<CellVecData>(collection.GetPropertiesType<CellVecData>().GetProperty());
            PetscInt vec_size;
            VecGetSize(p_cell_vec_data->GetItem("item 1"), &vec_size);
            TS_ASSERT_EQUALS(vec_size, 2);
            ReplicatableVector rep_item_1(p_cell_vec_data->GetItem("item 1"));
            TS_ASSERT_DELTA(rep_item_1[0], -17.3, 2e-14);

            for (CellPropertyCollection::Iterator it = collection.Begin(); it != collection.End(); ++it)
            {
                TS_ASSERT_EQUALS(collection.HasProperty(*it), true);

                bool is_wildtype = (*it)->IsType<WildTypeCellMutationState>();
                bool is_label = (*it)->IsType<CellLabel>();
                bool is_ancestor = (*it)->IsType<CellAncestor>();
                bool is_cellid = (*it)->IsType<CellId>();
                bool is_data = (*it)->IsType<CellData>();
                bool is_vec_data = (*it)->IsType<CellVecData>();
                bool is_stem = (*it)->IsType<StemCellProliferativeType>();

                bool is_any_of_above = is_wildtype || is_label || is_ancestor || is_cellid || is_data || is_vec_data || is_stem;
                TS_ASSERT_EQUALS(is_any_of_above, true);
            }

            // Try another cell
            CellPtr p_another_cell;
            input_arch >> p_another_cell;
            ReplicatableVector rep_another_item_1(p_another_cell->GetCellVecData()->GetItem("item 1"));
            TS_ASSERT_DELTA(rep_another_item_1[0], 42.0, 2e-14);
        }
    }
void TestStatechart() throw(Exception)
    {
        /** The next line is needed because we cannot currently run node based simulations in parallel. */
        EXIT_IF_PARALLEL;

        //Specify distal arm dimensions
        double cylinderRadius=10;
        double cylinderLength=200;

        /*
         * CREATE CELL POPULATION
         * Seed a few cells at the end of a cylinder representing the distal gonad arm.
         */
        std::vector<Node<3>*> nodes;
        for(double i=0; i<15; i+=5){
        	for(double j=0; j<12; j++){
                	double xcoord= cylinderLength+cylinderRadius-i;
                    Node<3>* my_node;
        			my_node=new Node<3>(12*(i/5)+j,  false,  xcoord, (cylinderRadius-5)*sin(2*3.14159*(j/12)), (cylinderRadius-5)*cos(2*3.14159*(j/12)));
                	nodes.push_back(my_node);
        	}
        }

        //MAKE CELL POPULATION
        NodesOnlyMesh<3>* p_mesh = new NodesOnlyMesh<3>;
        /* Define a cut off length for the connectivity of the nodes by setting a radius of interaction. */
        p_mesh->ConstructNodesWithoutMesh(nodes, 30.0);
        std::vector<CellPtr> cells;

        MAKE_PTR(TransitCellProliferativeType, p_transit_type);
        CellsGenerator<StatechartCellCycleModel, 3> cells_generator;
        cells_generator.GenerateBasicRandom(cells, p_mesh->GetNumNodes(), p_transit_type);
        NodeBasedCellPopulation<3> cell_population(*p_mesh, cells);


    	//loop through cells and initialise cell data properties that will be used in interfacing
        //with the statechart
        cell_population.SetUseVariableRadii(true);
    	for (NodeBasedCellPopulation<3>::Iterator cell_iter = cell_population.Begin();
    	         cell_iter != cell_population.End();
    	         ++cell_iter){

    		 Node<3>* cell_centre_node = cell_population.GetNode(cell_population.GetLocationIndexUsingCell(*cell_iter));
    		 cell_centre_node->SetRadius(2.5);
    		 (*cell_iter)->GetCellData()->SetItem("Radius",2.5);
    		 (*cell_iter)->GetCellData()->SetItem("Proliferating",1.0);
    		 (*cell_iter)->GetCellData()->SetItem("DistanceAwayFromDTC",0.0);

    	}
    	 cell_population.Update();

		//SET SIMULATION PROPERTIES, ADD REPULSION FORCE
        OffLatticeSimulation<3> simulator(cell_population);
        simulator.SetOutputDirectory("StatechartsGeneratedTest");
        simulator.SetSamplingTimestepMultiple(12);
        simulator.SetDt(1.0/300.0);
        simulator.SetEndTime(15.0);
        MAKE_PTR(RepulsionForce<3>, p_force1);
        simulator.AddForce(p_force1);


        //ADD CYLINDRICAL BOUNDARY CONDITION
        c_vector<double,3> left_end;
        left_end[0]=0; left_end[1]=0; left_end[2]=0;
        MAKE_PTR_ARGS(DistalArmBoundaryCondition<3>, p_boundary_condition, (&cell_population,left_end,cylinderLength,cylinderRadius,1e-5));
        simulator.AddCellPopulationBoundaryCondition(p_boundary_condition);

        //ADD A CELL KILLER ON FAR END
        //Plane based, corresponds to egg laying
        c_vector<double,3> pointOnKillerPlane=zero_vector<double>(3);
        c_vector<double,3> normalToKillerPlane=zero_vector<double>(3);
        pointOnKillerPlane[0]=0;
        pointOnKillerPlane[1]=0;
        normalToKillerPlane[0]=-1;
        MAKE_PTR_ARGS(PlaneBasedCellKiller<3>, cell_killer, (&cell_population, pointOnKillerPlane, normalToKillerPlane));
        simulator.AddCellKiller(cell_killer);

        /* RUN */
        simulator.Solve();

        /* GARBAGE COLLECTION*/
        for (unsigned i=0; i<nodes.size(); i++)
        {
            delete nodes[i];
        }
        delete p_mesh;

    };
Exemplo n.º 28
0
    void TestMakeMeinekeGraphs() throw (Exception)
    {
        // Specify output directory
        std::string output_directory = "MakeMeinekeGraphs";

        // Create mesh
        double crypt_length = 22.0;
        unsigned cells_across = 13;
        unsigned cells_up = 25;
        double crypt_width = 12.1;
        unsigned thickness_of_ghost_layer = 3;
        CylindricalHoneycombMeshGenerator generator(cells_across, cells_up, thickness_of_ghost_layer, crypt_width/cells_across);
        Cylindrical2dMesh* p_mesh = generator.GetCylindricalMesh();

        // Get location indices corresponding to real cells
        std::vector<unsigned> location_indices = generator.GetCellLocationIndices();

        // Set up cells
        std::vector<CellPtr> temp_cells;
        CryptCellsGenerator<StochasticDurationGenerationBasedCellCycleModel> cells_generator;
        cells_generator.Generate(temp_cells, p_mesh, std::vector<unsigned>(), true, 0.3, 2.0, 3.0, 4.0, true);

        // This awkward way of setting up the cells is a result of #430
        std::vector<CellPtr> cells;
        for (unsigned i=0; i<location_indices.size(); i++)
        {
            cells.push_back(temp_cells[location_indices[i]]);
        }

        // Create cell population
        MeshBasedCellPopulationWithGhostNodes<2> crypt(*p_mesh, cells, location_indices, false, 30.0); // Last parameter adjusts Ghost spring stiffness in line with the linear_force later on

        // Set cell population to output cell types
        crypt.AddPopulationWriter<CellMutationStatesCountWriter>();

        // Create and configure simulation
        CryptSimulation2d simulator(crypt, false, false);
        simulator.SetOutputDirectory(output_directory);

        double time_of_each_run = simulator.GetDt(); // for each run
        simulator.SetEndTime(time_of_each_run);

        // Create a force law and cell killer and pass then to the simulation
        MAKE_PTR(GeneralisedLinearSpringForce<2>, p_linear_force);
        p_linear_force->SetMeinekeSpringStiffness(30.0); // normally 15.0;
        simulator.AddForce(p_linear_force);
        MAKE_PTR_ARGS(SloughingCellKiller<2>, p_killer, (&simulator.rGetCellPopulation(), crypt_length));
        simulator.AddCellKiller(p_killer);

        // Specify unusual set up
        simulator.UseJiggledBottomCells();

        // Test CryptStatistics::GetCryptSectionPeriodic() by labelling a column of cells...
        CryptStatistics crypt_statistics(crypt);
        std::vector<CellPtr> test_section = crypt_statistics.GetCryptSectionPeriodic(crypt_length + 2.0, 8.0, 8.0);
        for (unsigned i=0; i<test_section.size(); i++)
        {
            test_section[i]->AddCellProperty(crypt.GetCellPropertyRegistry()->Get<CellLabel>());
        }

        simulator.Solve();
        CellBasedSimulationArchiver<2, CryptSimulation2d>::Save(&simulator);

        // ... and checking visualization of labelled cells against previous run
        OutputFileHandler handler(output_directory, false);
        std::string results_file = handler.GetOutputDirectoryFullPath() + "results_from_time_0/results.viznodes";
        TS_ASSERT(NumericFileComparison( results_file, "crypt/test/data/MakeMeinekeGraphs/results.viznodes").CompareFiles());

        std::string results_file2 = handler.GetOutputDirectoryFullPath() + "results_from_time_0/results.vizcelltypes";
        FileComparison( results_file2, "crypt/test/data/MakeMeinekeGraphs/results.vizcelltypes").CompareFiles();

        // Next, test LabelSPhaseCells()
        for (AbstractCellPopulation<2>::Iterator cell_iter = crypt.Begin();
             cell_iter != crypt.End();
             ++cell_iter)
        {
            cell_iter->RemoveCellProperty<CellLabel>();
        }
        crypt_statistics.LabelSPhaseCells();

        // Iterate over cells checking for correct labels
        unsigned counter = 0;
        for (AbstractCellPopulation<2>::Iterator cell_iter = crypt.Begin();
             cell_iter != crypt.End();
             ++cell_iter)
        {
            bool is_labelled = cell_iter->HasCellProperty<CellLabel>();
            bool in_s_phase = (cell_iter->GetCellCycleModel()->GetCurrentCellCyclePhase() == S_PHASE);

            TS_ASSERT_EQUALS(is_labelled, in_s_phase);

            if (in_s_phase)
            {
                counter++;
            }
        }

        TS_ASSERT_EQUALS(counter, 28u);

        // Test that LabelAllCellsAsHealthy sets all cells back to be UNLABELLED wild type cells
        crypt_statistics.LabelAllCellsAsHealthy();

        // Iterate over cells checking for correct labels
        counter = 0;
        for (AbstractCellPopulation<2>::Iterator cell_iter = crypt.Begin();
             cell_iter != crypt.End();
             ++cell_iter)
        {
            TS_ASSERT_EQUALS(cell_iter->GetMutationState()->IsType<WildTypeCellMutationState>(), true);
            TS_ASSERT_EQUALS(cell_iter->HasCellProperty<CellLabel>(), false);
            counter++;
        }

        TS_ASSERT_EQUALS(counter, simulator.rGetCellPopulation().GetNumRealCells());

        crypt_statistics.LabelSPhaseCells();

        simulator.SetEndTime(2*time_of_each_run);
        simulator.Solve();

        // TEST CryptStatistics::AreCryptSectionCellsLabelled

        // Set cells which are not in the crypt section to be in state APC +/-, so that we can
        // see the section
        test_section = crypt_statistics.GetCryptSectionPeriodic(crypt_length + 2.0, 8.0, 8.0);

        MAKE_PTR(ApcOneHitCellMutationState, p_apc1);

        for (AbstractCellPopulation<2>::Iterator cell_iter = crypt.Begin();
             cell_iter != crypt.End();
             ++cell_iter)
        {
            bool in_section = false;
            for (unsigned vector_index=0; vector_index<test_section.size(); vector_index++)
            {
                if (test_section[vector_index] == *cell_iter)
                {
                    in_section = true;
                }
            }
            if (!in_section)
            {
                cell_iter->SetMutationState(p_apc1);
            }
        }
        simulator.SetEndTime(3*time_of_each_run);
        simulator.Solve();

        std::vector<CellPtr> crypt_section = crypt_statistics.GetCryptSection(crypt_length + 2.0, 8.0, 8.0);
        std::vector<bool> labelled = crypt_statistics.AreCryptSectionCellsLabelled(crypt_section);

        // Test that the vector of booleans corresponds with a visualisation of the data -
        // only the first few cells at the base of the crypt have been labelled
        for (unsigned vector_index=0; vector_index<labelled.size(); vector_index++)
        {
            if (vector_index == 2u || vector_index == 3u || vector_index == 4u)
            {
                TS_ASSERT_EQUALS(labelled[vector_index], true);
            }
            else
            {
                TS_ASSERT_EQUALS(labelled[vector_index], false);
            }
        }
        RandomNumberGenerator::Destroy();
    }
    /**
     * Test a cell-based simulation with a non-Meineke spring system.
     *
     * This test consists of a standard crypt projection model simulation with a
     * radial sloughing cell killer, a crypt projection cell-cycle model that
     * depends on a radial Wnt gradient, and the crypt projection model spring
     * system, and store the results for use in later archiving tests.
     */
    void TestOffLatticeSimulationWithCryptProjectionSpringSystem() throw (Exception)
    {
        double a = 0.2;
        double b = 2.0;
        WntConcentration<2>::Instance()->SetCryptProjectionParameterA(a);
        WntConcentration<2>::Instance()->SetCryptProjectionParameterB(b);

        // Set up mesh
        int num_cells_depth = 20;
        int num_cells_width = 20;
        unsigned thickness_of_ghost_layer = 3;

        HoneycombMeshGenerator generator(num_cells_width, num_cells_depth, thickness_of_ghost_layer);
        MutableMesh<2,2>* p_mesh = generator.GetMesh();

        double crypt_length = (double)num_cells_depth *sqrt(3.0)/2.0;

        std::vector<unsigned> location_indices = generator.GetCellLocationIndices();

        ChasteCuboid<2> bounding_box=p_mesh->CalculateBoundingBox();
        double width_of_mesh = (num_cells_width/(num_cells_width+2.0*thickness_of_ghost_layer))*(bounding_box.GetWidth(0));
        double height_of_mesh = (num_cells_depth/(num_cells_depth+2.0*thickness_of_ghost_layer))*(bounding_box.GetWidth(1));

        p_mesh->Translate(-width_of_mesh/2, -height_of_mesh/2);

        // To start off with, set up all cells to have TransitCellProliferativeType
        std::vector<CellPtr> cells;
        MAKE_PTR(WildTypeCellMutationState, p_state);
        MAKE_PTR(TransitCellProliferativeType, p_transit_type);
        for (unsigned i=0; i<location_indices.size(); i++)
        {
            SimpleWntCellCycleModel* p_model = new SimpleWntCellCycleModel();
            p_model->SetDimension(2);
            p_model->SetWntStemThreshold(0.95);

            CellPtr p_cell(new Cell(p_state, p_model));
            p_cell->SetCellProliferativeType(p_transit_type);
            p_cell->InitialiseCellCycleModel();

            double birth_time = - RandomNumberGenerator::Instance()->ranf()*
                                  ( p_model->GetTransitCellG1Duration()
                                   +p_model->GetSG2MDuration());
            p_cell->SetBirthTime(birth_time);
            cells.push_back(p_cell);
        }

        // Make a cell population
        MeshBasedCellPopulationWithGhostNodes<2> crypt(*p_mesh, cells, location_indices);

        // Set up the Wnt gradient
        WntConcentration<2>::Instance()->SetType(RADIAL);
        WntConcentration<2>::Instance()->SetCellPopulation(crypt);
        WntConcentration<2>::Instance()->SetCryptLength(crypt_length);

        // Make a cell-based simulation
        OffLatticeSimulation<2> crypt_projection_simulator(crypt, false, false);

        // Create a force law and pass it to the simulation
        MAKE_PTR(CryptProjectionForce, p_force);
        crypt_projection_simulator.AddForce(p_force);

        // Create a radial cell killer and pass it in to the cell-based simulation
        c_vector<double,2> centre = zero_vector<double>(2);
        double crypt_radius = pow(crypt_length/a, 1.0/b);

        MAKE_PTR_ARGS(RadialSloughingCellKiller, p_killer, (&crypt, centre, crypt_radius));
        crypt_projection_simulator.AddCellKiller(p_killer);

        // Set up the simulation
        crypt_projection_simulator.SetOutputDirectory("CryptProjectionSimulation");
        crypt_projection_simulator.SetEndTime(0.25);

        // Run the simulation
        TS_ASSERT_THROWS_NOTHING(crypt_projection_simulator.Solve());

        // These cells just divided and have been gradually moving apart.
        // This is happening around (4, -1).  The exact spring length is slightly
        // compiler/architecture dependent.
        // These results are from time 0.25.
        std::vector<double> node_a_location = crypt_projection_simulator.GetNodeLocation(301);
        std::vector<double> node_b_location = crypt_projection_simulator.GetNodeLocation(504);

        c_vector<double, 2> distance_between;
        distance_between(0) = node_a_location[0] - node_b_location[0];
        distance_between(1) = node_a_location[1] - node_b_location[1];
        // Note that this distance varies based on the quality of the original honeycomb mesh,
        // the precision of the machine and the optimisation level
        TS_ASSERT_DELTA(norm_2(distance_between), 0.6516, 4.0e-3);

        // Test the Wnt concentration result
        WntConcentration<2>* p_wnt = WntConcentration<2>::Instance();
        TS_ASSERT_DELTA(p_wnt->GetWntLevel(crypt.GetCellUsingLocationIndex(257)), 0.7781, 1e-3);
        TS_ASSERT_DELTA(p_wnt->GetWntLevel(crypt.GetCellUsingLocationIndex(503)), 0.9038, 1e-3);
      // Tidy up
        WntConcentration<2>::Destroy();
    }
    /*
     * Create and simulate a simple 3D cell population of about 1000 cells within a cuboid box with sloughing on the top edge
     */
    void Test3dNodeBasedInBoxWithSloughing()
    {
        double size_of_box = 8.0;
        unsigned cells_across = 12;
        double scaling = size_of_box/(double(cells_across-1));

        // Create a simple 3D NodeBasedCellPopulation consisting of cells evenly spaced in a regular grid
        std::vector<Node<3>*> nodes;
        unsigned index = 0;
        for (unsigned i=0; i<cells_across; i++)
        {
            for (unsigned j=0; j<cells_across; j++)
            {
                for (unsigned k=0; k<cells_across; k++)
                {
                    nodes.push_back(new Node<3>(index, false,  (double) i * scaling , (double) j * scaling, (double) k * scaling));
                    index++;
                }
            }
        }

        NodesOnlyMesh<3> mesh;
        mesh.ConstructNodesWithoutMesh(nodes, 1.5);

        std::vector<CellPtr> cells;
        MAKE_PTR(TransitCellProliferativeType, p_transit_type);
        CellsGenerator<UniformCellCycleModel, 3> cells_generator;
        cells_generator.GenerateBasicRandom(cells, mesh.GetNumNodes(), p_transit_type);

        NodeBasedCellPopulation<3> node_based_cell_population(mesh, cells);
        //node_based_cell_population.AddCellPopulationCountWriter<CellProliferativeTypesCountWriter>();

        // Set up cell-based simulation
        OffLatticeSimulation<3> simulator(node_based_cell_population);
        simulator.SetOutputDirectory("Representative3dNodeBased");
        simulator.SetSamplingTimestepMultiple(12);
        simulator.SetEndTime(10.0);

        // Create a force law and pass it to the simulation
        MAKE_PTR(RepulsionForce<3>, p_linear_force);
        p_linear_force->SetCutOffLength(1.5);
        simulator.AddForce(p_linear_force);

        // Create some plane boundary conditions to restrict to box and pass them to the simulation

        // Restrict to x>0
        MAKE_PTR_ARGS(PlaneBoundaryCondition<3>, p_boundary_condition_1, (&node_based_cell_population, zero_vector<double>(3), -unit_vector<double>(3,0)));
        simulator.AddCellPopulationBoundaryCondition(p_boundary_condition_1);

        // Restrict to x < size_of_box
        MAKE_PTR_ARGS(PlaneBoundaryCondition<3>, p_boundary_condition_2, (&node_based_cell_population, size_of_box*unit_vector<double>(3,0), unit_vector<double>(3,0)));
        simulator.AddCellPopulationBoundaryCondition(p_boundary_condition_2);

        // Restrict to y>0
        MAKE_PTR_ARGS(PlaneBoundaryCondition<3>, p_boundary_condition_3, (&node_based_cell_population, zero_vector<double>(3), -unit_vector<double>(3,1)));
        simulator.AddCellPopulationBoundaryCondition(p_boundary_condition_3);

        // Restrict to y < size_of_box
        MAKE_PTR_ARGS(PlaneBoundaryCondition<3>, p_boundary_condition_4, (&node_based_cell_population, size_of_box*unit_vector<double>(3,1), unit_vector<double>(3,1)));
        simulator.AddCellPopulationBoundaryCondition(p_boundary_condition_4);

        // Restrict to z > 0
        MAKE_PTR_ARGS(PlaneBoundaryCondition<3>, p_boundary_condition_5, (&node_based_cell_population, zero_vector<double>(3), -unit_vector<double>(3,2)));
        simulator.AddCellPopulationBoundaryCondition(p_boundary_condition_5);

        // Create cell killer at z= size_of_box
        MAKE_PTR_ARGS(PlaneBasedCellKiller<3>, p_cell_killer,(&node_based_cell_population,  size_of_box*unit_vector<double>(3,2), unit_vector<double>(3,2)));
        simulator.AddCellKiller(p_cell_killer);


        // Run simulation
        simulator.Solve();

        // Check some results
        TS_ASSERT_EQUALS(simulator.rGetCellPopulation().GetNumRealCells(), 1128u);

        AbstractCellPopulation<3>::Iterator cell_iter = simulator.rGetCellPopulation().Begin();

        for (unsigned i=0; i<100; i++)
        {
            ++cell_iter;
        }
        c_vector<double,3> node_location = simulator.rGetCellPopulation().GetLocationOfCellCentre(*cell_iter);
        TS_ASSERT_DELTA(node_location[0],0.9604, 1e-4);
        TS_ASSERT_DELTA(node_location[1],8.0, 1e-4);
        TS_ASSERT_DELTA(node_location[2],3.6539, 1e-4);

        // Avoid memory leak
        for (unsigned i=0; i<nodes.size(); i++)
        {
            delete nodes[i];
        }
    }