void TestPottsMonolayerWithNonRandomSweep() 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(6, 2, 2, 6, 2, 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);
        cell_population.SetUpdateNodesInRandomOrder(false);

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

        // 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);

        // Run simulation
        TS_ASSERT_THROWS_NOTHING(simulator.Solve());
    }
    void TestGetLocationOfCellCentre() throw (Exception)
    {
        // Create a Potts-based cell population
        PottsMeshGenerator<2> generator(4, 2, 2, 4, 2, 2);
        PottsMesh<2>* p_mesh = generator.GetMesh();

        std::vector<CellPtr> cells;
        CellsGenerator<FixedDurationGenerationBasedCellCycleModel, 2> cells_generator;
        cells_generator.GenerateBasic(cells, p_mesh->GetNumElements());

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

        // Test GetLocationOfCellCentre()
        AbstractCellPopulation<2>::Iterator cell_iter = cell_population.Begin();

        for (unsigned i=0; i<4; i++)
        {
            c_vector<double, 2> cell_location = cell_population.GetLocationOfCellCentre(*cell_iter);

            c_vector<double, 2> expected;
            expected(0) = 0.5 + 2*(i%2 != 0);
            expected(1) = 0.5 + 2*(i > 1);

            double drift = norm_2(cell_location-expected);
            TS_ASSERT_LESS_THAN(drift, 1e-6);

            ++cell_iter;
        }
    }
    void TestConstructor() throw(Exception)
    {
        EXIT_IF_PARALLEL;

        // Create a cell population
        HoneycombMeshGenerator generator(2, 2, 0);
        MutableMesh<2,2>* p_generating_mesh = generator.GetMesh();
        NodesOnlyMesh<2> mesh;
        mesh.ConstructNodesWithoutMesh(*p_generating_mesh, 1.5);

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

        NodeBasedCellPopulation<2> cell_population(mesh, cells);

        // Create a PDE handler object using this cell population
        CellBasedPdeHandler<2> pde_handler(&cell_population);

        // Test that member variables are initialised correctly
        TS_ASSERT_EQUALS(pde_handler.GetCellPopulation(), &cell_population);
        TS_ASSERT_EQUALS(pde_handler.GetWriteAverageRadialPdeSolution(), false);
        TS_ASSERT_EQUALS(pde_handler.GetWriteDailyAverageRadialPdeSolution(), false);
        TS_ASSERT_EQUALS(pde_handler.GetImposeBcsOnCoarseBoundary(), true);
        TS_ASSERT_EQUALS(pde_handler.GetNumRadialIntervals(), UNSIGNED_UNSET);
        TS_ASSERT(pde_handler.GetCoarsePdeMesh() == NULL);
    }
    /*
     * Note only solves one PDE
     */
    void TestMultipleCaBasedWithoutCoarseMeshUsingPdeHandlerOnCuboid() throw(Exception)
    {
        EXIT_IF_PARALLEL;

        // 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;
        CellsGenerator<FixedDurationGenerationBasedCellCycleModel, 2> cells_generator;
        cells_generator.GenerateBasic(cells, 100);

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

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

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

        // Set up a PDE with mixed boundary conditions (use zero uptake to check analytic solution)
        AveragedSourcePde<2> pde(cell_population, 0.0);
        ConstBoundaryCondition<2> bc(1.0);
        PdeAndBoundaryConditions<2> pde_and_bc(&pde, &bc, false);
        pde_and_bc.SetDependentVariableName("nutrient");

        // Pass this to the simulation object via a PDE handler
        CellBasedPdeHandlerOnCuboid<2> pde_handler(&cell_population);
        pde_handler.AddPdeAndBc(&pde_and_bc);
        pde_handler.SetImposeBcsOnCoarseBoundary(false);
        simulator.SetCellBasedPdeHandler(&pde_handler);

        // Solve the system
        simulator.Solve();

        // Test that PDE solver is working correctly
        for (AbstractCellPopulation<2>::Iterator cell_iter = cell_population.Begin();
             cell_iter != cell_population.End();
             ++cell_iter)
        {
            c_vector<double, 2> cell_location = simulator.rGetCellPopulation().GetLocationOfCellCentre(*cell_iter);

            if (cell_location[1] < 1e-6 || cell_location[1] > 9 - 1e-6)
            {
                TS_ASSERT_DELTA(cell_iter->GetCellData()->GetItem("nutrient"),1.0, 1e-2);
            }
            else
            {
                TS_ASSERT_LESS_THAN(1.0,cell_iter->GetCellData()->GetItem("nutrient"));
            }
        }
    }
    /*
     * The results may be visualized using {{{Visualize2dCentreCells}}} as described in the
     * previous test, with the results directory changed from {{{CellBasedDemo3}}} to {{{CellBasedDemo4}}}.
     *
     * == Test 5 - basic periodic mesh-based simulation ==
     *
     * We next show how to modify the previous test to implement a periodic boundary to the
     * left and right of the domain.
     */
    void TestMeshBasedMonolayerPeriodic() throw (Exception)
    {
        /* We now want to impose periodic boundaries on the domain. To do this we create a {{{Cylindrical2dMesh}}}
         * using a {{{CylindricalHoneycombMeshGenerator}}}.*/
        CylindricalHoneycombMeshGenerator generator(5, 2, 2); //**Changed**//
        Cylindrical2dMesh* p_mesh = generator.GetCylindricalMesh(); //**Changed**//

        /* Again we create one cell for each non ghost node. Note that we have changed back to using a {{{StochasticDurationCellCycleModel}}}.*/
        std::vector<unsigned> location_indices = generator.GetCellLocationIndices();
        std::vector<CellPtr> cells;
        MAKE_PTR(TransitCellProliferativeType, p_transit_type);
        CellsGenerator<StochasticDurationCellCycleModel, 2> cells_generator; //**Changed**//
        cells_generator.GenerateBasicRandom(cells, location_indices.size(), p_transit_type);

        /* We use the same {{{CellPopulation}}}, {{{CellBasedSimulation}}} (only changing the output directory and end time) and {{{Force}}} as before and run the simulation.*/
        MeshBasedCellPopulationWithGhostNodes<2> cell_population(*p_mesh, cells, location_indices);

        /* Again Paraview output is explicitly requested.*/
        cell_population.AddPopulationWriter<VoronoiDataWriter>();

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

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

        simulator.Solve();

        /* The next two lines are for test purposes only and are not part of this tutorial.
         */
        TS_ASSERT_EQUALS(cell_population.GetNumRealCells(), 29u);
        TS_ASSERT_DELTA(SimulationTime::Instance()->GetTime(), 20.0, 1e-10);
    }
    void TestUpdateCellLocations()
    {
        // Create a simple 2D PottsMesh with two cells
        PottsMeshGenerator<2> generator(4, 2, 2, 2, 1, 2);
        PottsMesh<2>* p_mesh = generator.GetMesh();

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

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

        // Set node selection to non-random lattice sweeping: this will loop over the nodes in index order
        TS_ASSERT_EQUALS(true, cell_population.GetUpdateNodesInRandomOrder());
        cell_population.SetUpdateNodesInRandomOrder(false);

        // Increase temperature: allows swaps to be more likely
        TS_ASSERT_EQUALS(cell_population.GetTemperature(),0.1);
        cell_population.SetTemperature(10.0);

        // Create a volume update rule and pass to the population
        MAKE_PTR(VolumeConstraintPottsUpdateRule<2>, p_volume_constraint_update_rule);
        cell_population.AddUpdateRule(p_volume_constraint_update_rule);

        // Commence lattice sweeping, updating where necessary
        // (Sensitive to changes in random number generation)
        cell_population.UpdateCellLocations(1.0);
        TS_ASSERT_EQUALS(cell_population.rGetCells().size(), 2u);
        TS_ASSERT_EQUALS(cell_population.rGetMesh().GetElement(0)->GetNumNodes(), 3u);
        TS_ASSERT_EQUALS(cell_population.rGetMesh().GetElement(1)->GetNumNodes(), 5u);
    }
    void TestUpdateCellLocationsRandomly()
    {
        // Create a simple 2D PottsMesh with two cells
        PottsMeshGenerator<2> generator(4, 2, 2, 2, 1, 2);
        PottsMesh<2>* p_mesh = generator.GetMesh();

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

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

        // Set node selection to random lattice sweeping and (for coverage) random iteration over update rules
        cell_population.SetUpdateNodesInRandomOrder(true);
        cell_population.SetIterateRandomlyOverUpdateRuleCollection(true);

        // Increase temperature: allows swaps to be more likely
        TS_ASSERT_EQUALS(cell_population.GetTemperature(),0.1);
        cell_population.SetTemperature(10.0);

        // Create a volume update rule and pass to the population
        MAKE_PTR(VolumeConstraintPottsUpdateRule<2>, p_volume_constraint_update_rule);
        cell_population.AddUpdateRule(p_volume_constraint_update_rule);

        // Commence lattice sweeping, updating where necessary
        cell_population.UpdateCellLocations(1.0);

        // Note that these results differ to those in the above test due to extra random numbers being called
        // (Sensitive to changes in random number generation)
        TS_ASSERT_EQUALS(cell_population.rGetCells().size(), 2u);
        TS_ASSERT_EQUALS(cell_population.rGetMesh().GetElement(0)->GetNumNodes(), 4u);
        TS_ASSERT_EQUALS(cell_population.rGetMesh().GetElement(1)->GetNumNodes(), 4u);
    }
    void TestIsCellAssociatedWithADeletedLocation() throw (Exception)
    {
        // Create a Potts-based cell population but do not try to validate
        PottsMeshGenerator<2> generator(4, 2, 2, 4, 2, 2);
        PottsMesh<2>* p_mesh = generator.GetMesh();
        p_mesh->GetElement(0)->MarkAsDeleted();

        std::vector<CellPtr> cells;
        CellsGenerator<FixedDurationGenerationBasedCellCycleModel, 2> cells_generator;
        cells_generator.GenerateBasic(cells, p_mesh->GetNumElements());

        PottsBasedCellPopulation<2> cell_population(*p_mesh, cells, false, false);

        // Test IsCellAssociatedWithADeletedLocation() method
        for (AbstractCellPopulation<2>::Iterator cell_iter = cell_population.Begin();
             cell_iter != cell_population.End();
             ++cell_iter)
        {
            bool is_deleted = cell_population.IsCellAssociatedWithADeletedLocation(*cell_iter);

            if (cell_population.GetLocationIndexUsingCell(*cell_iter) == 0)
            {
                TS_ASSERT_EQUALS(is_deleted, true);
            }
            else
            {
                TS_ASSERT_EQUALS(is_deleted, false);
            }
        }
    }
    void TestRemoveDeadCellsAndUpdate() throw(Exception)
    {
        // Create a simple 2D PottsMesh
        PottsMeshGenerator<2> generator(4, 2, 2, 4, 2, 2);
        PottsMesh<2>* p_mesh = generator.GetMesh();

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

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

        // Test RemoveDeadCells() method
        TS_ASSERT_EQUALS(cell_population.GetNumElements(), 4u);

        cell_population.Begin()->Kill();

        TS_ASSERT_EQUALS(cell_population.RemoveDeadCells(), 1u);
        TS_ASSERT_EQUALS(cell_population.GetNumElements(), 3u);
        TS_ASSERT_EQUALS(p_mesh->GetNumElements(), 3u);
        TS_ASSERT_EQUALS(p_mesh->GetNumAllElements(), 4u);

        // Test that Update() throws no errors
        TS_ASSERT_THROWS_NOTHING(cell_population.Update());
    }
示例#10
0
    void TestChemotaxisPottsUpdateRuleIn2d() throw (Exception)
    {
        // Create a simple 2D PottsMesh with 2 elements
        PottsMeshGenerator<2> generator(4, 1, 2, 4, 1, 2);
        PottsMesh<2>* p_mesh = generator.GetMesh();

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

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

        // Create an update law system
        ChemotaxisPottsUpdateRule<2> chemotaxis_update;

        // Test EvaluateHamiltonianContribution()

        // target site above current site
        double contribution = chemotaxis_update.EvaluateHamiltonianContribution(10, 14, cell_population);
        TS_ASSERT_DELTA(contribution, -0.2, 1e-6);

        // target site below current site
        contribution = chemotaxis_update.EvaluateHamiltonianContribution(6, 2, cell_population);
        TS_ASSERT_DELTA(contribution, 0.2, 1e-6);

        // target site diagonally above current site (to right)
        contribution = chemotaxis_update.EvaluateHamiltonianContribution(10, 15, cell_population);
        TS_ASSERT_DELTA(contribution, -0.4, 1e-6);

        // target site diagonally above current site (to left)
        contribution = chemotaxis_update.EvaluateHamiltonianContribution(10, 13, cell_population);
        TS_ASSERT_DELTA(contribution, 0.0, 1e-6);
    }
    void TestCellwiseDataGradientVerySmallMesh() throw(Exception)
    {
        // Create a simple mesh
        TrianglesMeshReader<2,2> mesh_reader("mesh/test/data/square_2_elements");
        MutableMesh<2,2> mesh;
        mesh.ConstructFromMeshReader(mesh_reader);

        // Create a cell population
        std::vector<CellPtr> cells;
        CellsGenerator<FixedDurationGenerationBasedCellCycleModel, 2> cells_generator;
        cells_generator.GenerateBasic(cells, mesh.GetNumNodes());
        MeshBasedCellPopulation<2> cell_population(mesh, cells);

        // Set up data: C(x,y) = x^2
        for (unsigned i=0; i<mesh.GetNumNodes(); i++)
        {
            double x = mesh.GetNode(i)->rGetLocation()[0];
            CellPtr p_cell = cell_population.GetCellUsingLocationIndex(mesh.GetNode(i)->GetIndex());
            p_cell->GetCellData()->SetItem("x^2", x*x);
        }

        CellwiseDataGradient<2> gradient;
        gradient.SetupGradients(cell_population, "x^2");

        // With the algorithm being used, the numerical gradient is (1,0)
        // for each of the nodes
        for (unsigned i=0; i<mesh.GetNumNodes(); i++)
        {
            TS_ASSERT_DELTA(gradient.rGetGradient(i)(0), 1.0, 1e-9);
            TS_ASSERT_DELTA(gradient.rGetGradient(i)(1), 0.0, 1e-9);
        }
    }
    /*
     * EMPTYLINE
     *
     * To visualize the results, open a new terminal, {{{cd}}} to the Chaste directory,
     * then {{{cd}}} to {{{anim}}}. Then do: {{{java Visualize2dCentreCells /tmp/$USER/testoutput/NodeBasedMonolayer/results_from_time_0}}}.
     * we need to select the 'Cells as circles` option to be able to visualize the cells, as opposed
     * to just the centres.
     * We may have to do: {{{javac Visualize2dCentreCells.java}}} beforehand to create the
     * java executable.
     *
     * Alternatively, to view in Paraview, load the file {{{/tmp/$USER/testoutput/NodeBasedMonolayer/results_from_time_0/results.pvd}}}
     * and add glyphs to represent cells. An option is to use 3D spherical glyphs and then make a planar cut.
     * Note that, for larger simulations, you may need to unclick "Mask Points" (or similar) so as not to limit the number of glyphs
     * displayed by Paraview.
     *
     *
     *
     * EMPTYLINE
     *
     * == Test 2 - a basic node-based simulation in 3D ==
     *
     * EMPTYLINE
     *
     * In the second test we run a simple node-based simulation in 3D. This is very similar
     * to the 2D test with the dimension template (<2,2> and <2>) changed from 2 to 3 and instead of using a mesh
     * generator we generate the nodes directly.
     */
    void TestSpheroid()
    {
        /** The next line is needed because we cannot currently run node based simulations in parallel. */
        EXIT_IF_PARALLEL;

        /*
         * First, we generate a nodes only mesh. This time we specify the nodes manually by first
         * creating a vector of nodes. */
        std::vector<Node<3>*> nodes;
        /* We then create some nodes to add to this vector. */
        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));
        /* Finally a {{{NodesOnlyMesh}}} is created and the vector of nodes is passed to
         * the {{{ConstructNodesWithoutMesh}}} method. */
        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);

        /*
         * Having created a mesh, we now create a {{{std::vector}}} of {{{CellPtr}}}s.
         * As before, we do this with the `CellsGenerator` helper class (this time with dimension 3).
         */
        std::vector<CellPtr> cells;
        MAKE_PTR(TransitCellProliferativeType, p_transit_type);
        CellsGenerator<UniformCellCycleModel, 3> cells_generator;
        cells_generator.GenerateBasicRandom(cells, mesh.GetNumNodes(), p_transit_type);

        /* We make a {{{NodeBasedCellPopulation}}} (this time with dimension 3) as before.
         */
        NodeBasedCellPopulation<3> cell_population(mesh, cells);

        /* We then pass in the cell population into an {{{OffLatticeSimulation}}},
         * (this time with dimension 3) and set the output directory, output multiple and end time. */
        OffLatticeSimulation<3> simulator(cell_population);
        simulator.SetOutputDirectory("NodeBasedSpheroid");
        simulator.SetSamplingTimestepMultiple(12);
        simulator.SetEndTime(10.0);

        /* Again we create a force law (this time with dimension 3), and pass it to the {{{OffLatticeSimulation}}}.*/
        MAKE_PTR(GeneralisedLinearSpringForce<3>, p_force);
        simulator.AddForce(p_force);

        /* 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];
        }
    }
    /*
     * == Using the SRN model in a cell-based simulation ==
     *
     * We conclude with a brief test demonstrating how {{{MySrnModel}}} can be used
     * in a cell-based simulation.
     */
    void TestOffLatticeSimulationWithMySrnModel() throw(Exception)
    {
        /* We use the honeycomb vertex mesh generator to create a vertex mesh.
         */
        HoneycombVertexMeshGenerator generator(2, 2);
        MutableVertexMesh<2,2>* p_mesh = generator.GetMesh();

        /* Next, we create some cells. First, define the cells vector. */
        std::vector<CellPtr> cells;
        /* We must create a shared_ptr to a {{{CellMutationState}}} with which to bestow the cells.
         * We make use of the macro MAKE_PTR to do this: the first argument is the class and
         * the second argument is the name of the shared_ptr. */
        MAKE_PTR(WildTypeCellMutationState, p_state);
        MAKE_PTR(StemCellProliferativeType, p_stem_type);
        /* Then we loop over the nodes. */
        for (unsigned i=0; i<p_mesh->GetNumElements(); i++)
        {
            /* For each node we create a cell with our SRN model and simple Stochastic cell cycle model. */
            StochasticDurationCellCycleModel* p_cell_cycle_model = new StochasticDurationCellCycleModel();
            MySrnModel* p_srn_model = new MySrnModel;

            /* We choose to initialise the concentrations to random levels in each cell. */
            std::vector<double> initial_conditions;
            initial_conditions.push_back(1.0-2.0*RandomNumberGenerator::Instance()->ranf());
            initial_conditions.push_back(1.0-2.0*RandomNumberGenerator::Instance()->ranf());
            p_srn_model->SetInitialConditions(initial_conditions);

            CellPtr p_cell(new Cell(p_state, p_cell_cycle_model, p_srn_model));
            p_cell->SetCellProliferativeType(p_stem_type);


            /* Now, we define a random birth time, chosen from [-T,0], where
             * T = t,,1,, + t,,2,,, where t,,1,, is a parameter representing the G,,1,, duration
             * of a stem cell, and t,,2,, is the basic S+G,,2,,+M phases duration.
             */
            double birth_time = - RandomNumberGenerator::Instance()->ranf() * (p_cell_cycle_model->GetStemCellG1Duration() + p_cell_cycle_model->GetSG2MDuration());
            /* We then set the birth time and push the cell back into the vector of cells. */
            p_cell->SetBirthTime(birth_time);
            cells.push_back(p_cell);
        }


        /* Now that we have defined the mesh and cells, we can define the cell population, forces, areas modifier, and simulation
         * in the same way as the other tutorials. */
        VertexBasedCellPopulation<2> cell_population(*p_mesh, cells);

        OffLatticeSimulation<2> simulator(cell_population);
        simulator.SetOutputDirectory("TestOffLatticeSimulationWithMySrnModel");
        simulator.SetEndTime(10.0);
        simulator.SetSamplingTimestepMultiple(50);

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

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

        /* Finally to run the simulation, we call {{{Solve()}}}. */
        simulator.Solve();
    }
    void TestAllCases()
    {
        TrianglesMeshReader<2,2> mesh_reader("mesh/test/data/square_2_elements");
        MutableMesh<2,2> mesh;
        mesh.ConstructFromMeshReader(mesh_reader);

        TS_ASSERT_DELTA(mesh.GetAngleBetweenNodes(2,0), -0.75*M_PI, 1e-12);
        TS_ASSERT_DELTA(mesh.GetAngleBetweenNodes(2,1), -0.5*M_PI, 1e-12);

        CellsGenerator<FixedG1GenerationalCellCycleModel, 2> cells_generator;
        std::vector<CellPtr> cells;
        cells_generator.GenerateBasic(cells, mesh.GetNumNodes());

        MeshBasedCellPopulation<2> cell_population(mesh, cells);

        MAKE_PTR(GeneralisedLinearSpringForce<2>, p_force);
        std::vector<boost::shared_ptr<AbstractTwoBodyInteractionForce<2> > > force_collection;
        force_collection.push_back(p_force);

        DiscreteSystemForceCalculator calculator(cell_population, force_collection);

        double epsilon = 0.5*M_PI;
        calculator.SetEpsilon(epsilon);

        TS_ASSERT_THROWS_NOTHING(calculator.GetSamplingAngles(2));
    }
    void TestAddingUpdateRules() throw(Exception)
    {
        // Create a simple 2D PottsMesh with one cell
        PottsMeshGenerator<2> generator(2, 1, 2, 2, 1, 2);
        PottsMesh<2>* p_mesh = generator.GetMesh();

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

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

        // Test we have the correct number of cells and elements
        TS_ASSERT_EQUALS(cell_population.GetNumElements(), 1u);
        TS_ASSERT_EQUALS(cell_population.rGetCells().size(), 1u);

        // Create an update rule and pass to the population
        MAKE_PTR(VolumeConstraintPottsUpdateRule<2>, p_volume_constraint_update_rule);
        cell_population.AddUpdateRule(p_volume_constraint_update_rule);

        // Check the update rules are correct
        std::vector<boost::shared_ptr<AbstractPottsUpdateRule<2> > > update_rule_collection = cell_population.rGetUpdateRuleCollection();
        TS_ASSERT_EQUALS(update_rule_collection.size(),1u);
        TS_ASSERT_EQUALS((*update_rule_collection[0]).GetIdentifier(), "VolumeConstraintPottsUpdateRule-2");
    }
    void TestCellPopulationIteratorWithNoCells() throw(Exception)
    {
        EXIT_IF_PARALLEL;    // This test doesn't work in parallel.

        SimulationTime* p_simulation_time = SimulationTime::Instance();
        p_simulation_time->SetEndTimeAndNumberOfTimeSteps(10.0, 1);

        // Create a simple mesh
        TrianglesMeshReader<2,2> mesh_reader("mesh/test/data/square_128_elements");
        TetrahedralMesh<2,2> generating_mesh;
        generating_mesh.ConstructFromMeshReader(mesh_reader);

        // Convert this to a NodesOnlyMesh
        NodesOnlyMesh<2> mesh;
        mesh.ConstructNodesWithoutMesh(generating_mesh, 1.2);

        // Create vector of cell location indices
        std::vector<unsigned> cell_location_indices;
        cell_location_indices.push_back(80);

        // Create a single cell
        std::vector<CellPtr> cells;
        CellsGenerator<FixedDurationGenerationBasedCellCycleModel, 2> cells_generator;
        cells_generator.GenerateBasic(cells, cell_location_indices.size());
        cells[0]->StartApoptosis();

        // Create a cell population
        NodeBasedCellPopulationWithParticles<2> cell_population(mesh, cells, cell_location_indices);

        // Iterate over cell population and check there is a single cell
        unsigned counter = 0;
        for (AbstractCellPopulation<2>::Iterator cell_iter = cell_population.Begin();
                cell_iter != cell_population.End();
                ++cell_iter)
        {
            counter++;
        }
        TS_ASSERT_EQUALS(counter, 1u);
        TS_ASSERT_EQUALS(cell_population.rGetCells().empty(), false);

        // Increment simulation time and update cell population
        p_simulation_time->IncrementTimeOneStep();

        unsigned num_cells_removed = cell_population.RemoveDeadCells();
        TS_ASSERT_EQUALS(num_cells_removed, 1u);

        cell_population.Update();

        // Iterate over cell population and check there are now no cells
        counter = 0;
        for (AbstractCellPopulation<2>::Iterator cell_iter = cell_population.Begin();
                cell_iter != cell_population.End();
                ++cell_iter)
        {
            counter++;
        }
        TS_ASSERT_EQUALS(counter, 0u);
        TS_ASSERT_EQUALS(cell_population.rGetCells().empty(), true);
    }
    /*
     * Cellular birth has been tested in TestCaSingleCellWithBirth for one cell per lattice site.
     * This test adds to the above by further testing cellular birth considering multiple cells per lattice site.
     * A  two-lattice mesh was created and only one lattice had free space to add one daughter cell.
     */
    void TestMultipleCellsPerLatticeSiteWithBirth() throw (Exception)
    {
        EXIT_IF_PARALLEL;

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

        // Create cells
        std::vector<CellPtr> cells;
        MAKE_PTR(StemCellProliferativeType, p_stem_type);
        CellsGenerator<FixedDurationGenerationBasedCellCycleModel, 2> cells_generator;
        cells_generator.GenerateBasicRandom(cells, 3, p_stem_type);

        // Specify where cells lie
        std::vector<unsigned> location_indices;
        location_indices.push_back(0);
        location_indices.push_back(0);
        location_indices.push_back(1);

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

        // Set up cell-based simulation
        OnLatticeSimulation<2> simulator(cell_population);
        std::string output_directory = "TestMultipleCellsPerLatticeSiteWithBirth";
        simulator.SetOutputDirectory(output_directory);
        simulator.SetDt(0.1);
        simulator.SetEndTime(40);

        // Add update rule
        MAKE_PTR(DiffusionCaUpdateRule<2u>, p_diffusion_update_rule);
        p_diffusion_update_rule->SetDiffusionParameter(0.5);
        simulator.AddCaUpdateRule(p_diffusion_update_rule);

        // Run simulation
        simulator.Solve();

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

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

#ifdef CHASTE_VTK
        // Test that VTK writer has produced a file
        OutputFileHandler output_file_handler(output_directory, false);
        std::string results_dir = output_file_handler.GetOutputDirectoryFullPath();

        // Initial condition file
        FileFinder vtk_file(results_dir + "results_from_time_0/results_0.vtu", RelativeTo::Absolute);
        TS_ASSERT(vtk_file.Exists());

        // Final file
        FileFinder vtk_file2(results_dir + "results_from_time_0/results_400.vtu", RelativeTo::Absolute);
        TS_ASSERT(vtk_file2.Exists());
#endif //CHASTE_VTK
    }
示例#18
0
    void TestAdhesionPottsUpdateRuleIn3d() throw (Exception)
    {
        // Create a simple 2D PottsMesh with 2 elements
        PottsMeshGenerator<3> generator(4, 2, 2, 2, 1, 2, 4, 1, 2, true);
        PottsMesh<3>* p_mesh = generator.GetMesh();

        TS_ASSERT_EQUALS(p_mesh->GetNumElements(), 2u);
        TS_ASSERT_EQUALS(p_mesh->GetNumNodes(), 32u);

        // Create cells
        std::vector<CellPtr> cells;
        CellsGenerator<FixedDurationGenerationBasedCellCycleModel, 3> cells_generator;
        cells_generator.GenerateBasic(cells, p_mesh->GetNumElements());

        // Label cells 0 and 1
        MAKE_PTR(CellLabel, p_label);
        cells[0]->AddCellProperty(p_label);
        cells[1]->AddCellProperty(p_label);

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

        // Create an update law system
        AdhesionPottsUpdateRule<3> adhesion_update;

        // Set the parameters to facilitate calculations below.
        adhesion_update.SetCellCellAdhesionEnergyParameter(0.1);
        adhesion_update.SetCellBoundaryAdhesionEnergyParameter(0.2);

        // Test EvaluateHamiltonianContribution(). Note that the boundary of the domain is a void not medium.

        double gamma_cell_cell = adhesion_update.GetCellCellAdhesionEnergyParameter();
        double gamma_cell_boundary = adhesion_update.GetCellBoundaryAdhesionEnergyParameter();

        // Both points lie within cell 0
        TS_ASSERT_THROWS_THIS(adhesion_update.EvaluateHamiltonianContribution(0, 1, cell_population),
                              "The current node and target node must not be in the same element.");

        // Both points lie within cell 1
        TS_ASSERT_THROWS_THIS(adhesion_update.EvaluateHamiltonianContribution(2, 3, cell_population),
                              "The current node and target node must not be in the same element.");

        // Both points lie within cell medium
        TS_ASSERT_THROWS_THIS(adhesion_update.EvaluateHamiltonianContribution(16, 17, cell_population),
                               "At least one of the current node or target node must be in an element.");

        // Current site in cell 0; target site in cell medium
        double contribution = adhesion_update.EvaluateHamiltonianContribution(9, 17, cell_population);
        TS_ASSERT_DELTA(contribution, 3.0*gamma_cell_boundary, 1e-6);

        // Current site in cell medium; target site in cell 0
        contribution = adhesion_update.EvaluateHamiltonianContribution(17, 9, cell_population);
        TS_ASSERT_DELTA(contribution, 3.0*gamma_cell_boundary - gamma_cell_cell, 1e-6);

        // Current site in cell 0; target site in cell 1
        contribution = adhesion_update.EvaluateHamiltonianContribution(9, 10, cell_population);
        TS_ASSERT_DELTA(contribution, 2.0*gamma_cell_cell, 1e-6);
    }
示例#19
0
    void TestSurfaceAreaConstraintPottsUpdateRuleIn3d() throw (Exception)
    {
        // Create a simple 3D PottsMesh with 2 elements
        PottsMeshGenerator<3> generator(4, 2, 2, 4, 1, 2, 4, 1, 2, true);
        PottsMesh<3>* p_mesh = generator.GetMesh();

        TS_ASSERT_EQUALS(p_mesh->GetNumElements(), 2u);
        TS_ASSERT_EQUALS(p_mesh->GetNumNodes(), 64u);

        // Create cells
        std::vector<CellPtr> cells;
        CellsGenerator<FixedDurationGenerationBasedCellCycleModel, 3> cells_generator;
        cells_generator.GenerateBasic(cells, p_mesh->GetNumElements());

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

        // Create an update law system
        SurfaceAreaConstraintPottsUpdateRule<3> surface_area_constraint;

        surface_area_constraint.SetDeformationEnergyParameter(0.5);
        surface_area_constraint.SetMatureCellTargetSurfaceArea(24.0);

        // Test EvaluateHamiltonianContribution()
        double gamma = surface_area_constraint.GetDeformationEnergyParameter();

        // Both points lie within cell 0
        TS_ASSERT_THROWS_THIS(surface_area_constraint.EvaluateHamiltonianContribution(0, 1, cell_population),
                              "The current node and target node must not be in the same element.");

        // Both points lie within cell 1
        TS_ASSERT_THROWS_THIS(surface_area_constraint.EvaluateHamiltonianContribution(2, 3, cell_population),
                              "The current node and target node must not be in the same element.");

        // Both points lie within cell medium
        TS_ASSERT_THROWS_THIS(surface_area_constraint.EvaluateHamiltonianContribution(8, 9, cell_population),
                               "At least one of the current node or target node must be in an element.");

        // Current site in cell 0; target site in cell medium Cell on edge of domain
        double contribution = surface_area_constraint.EvaluateHamiltonianContribution(4, 8, cell_population);
        TS_ASSERT_DELTA(contribution, 4.0*4.0*gamma, 1e-6);

        // Current site in cell medium; target site in cell 1
        contribution = surface_area_constraint.EvaluateHamiltonianContribution(10, 6, cell_population);
        TS_ASSERT_DELTA(contribution, 0.0, 1e-6);

        // Current site in cell 0; target site in cell 1
        contribution = surface_area_constraint.EvaluateHamiltonianContribution(17, 18, cell_population);
        TS_ASSERT_DELTA(contribution, 4.0*4.0*gamma, 1e-6);

        // Current site in cell 0; target site in cell 1 (diagonal switch)
        contribution = surface_area_constraint.EvaluateHamiltonianContribution(1, 18, cell_population);
        TS_ASSERT_DELTA(contribution, 4.0*4.0*gamma, 1e-6);

        // Current site in cell 0; target site in medium
        contribution = surface_area_constraint.EvaluateHamiltonianContribution(5, 9, cell_population);
        TS_ASSERT_DELTA(contribution, 4.0*4.0*gamma, 1e-6);
    }
示例#20
0
    void TestVolumeConstraintPottsUpdateRuleIn2d() throw (Exception)
    {
        // Create a simple 2D PottsMesh with 2 elements
        PottsMeshGenerator<2> generator(4, 1, 2, 4, 2, 2, 1, 1, 1, true); // last bool makes elements start in bottom left
        PottsMesh<2>* p_mesh = generator.GetMesh();

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

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

        // Create an update law system
        VolumeConstraintPottsUpdateRule<2> volume_constraint;

        // Test get/set methods
        TS_ASSERT_DELTA(volume_constraint.GetDeformationEnergyParameter(), 0.5, 1e-12);
        TS_ASSERT_DELTA(volume_constraint.GetMatureCellTargetVolume(), 16.0, 1e-12);

        volume_constraint.SetDeformationEnergyParameter(1.0);
        volume_constraint.SetMatureCellTargetVolume(0.6);

        TS_ASSERT_DELTA(volume_constraint.GetDeformationEnergyParameter(), 1.0, 1e-12);
        TS_ASSERT_DELTA(volume_constraint.GetMatureCellTargetVolume(), 0.6, 1e-12);

        volume_constraint.SetDeformationEnergyParameter(0.5);
        volume_constraint.SetMatureCellTargetVolume(4.0);

        // Test EvaluateHamiltonianContribution()

        double alpha = volume_constraint.GetDeformationEnergyParameter();

        // Both points lie within cell 0
        TS_ASSERT_THROWS_THIS(volume_constraint.EvaluateHamiltonianContribution(0, 1, cell_population),
                              "The current node and target node must not be in the same element.");

        // Both points lie within cell 1
        TS_ASSERT_THROWS_THIS(volume_constraint.EvaluateHamiltonianContribution(8, 9, cell_population),
                              "The current node and target node must not be in the same element.");

        // Both points lie within cell medium
        TS_ASSERT_THROWS_THIS(volume_constraint.EvaluateHamiltonianContribution(2, 3, cell_population),
                              "At least one of the current node or target node must be in an element.");

        // Current site in cell 0; target site in cell medium
        double contribution = volume_constraint.EvaluateHamiltonianContribution(5, 6, cell_population);
        TS_ASSERT_DELTA(contribution, alpha, 1e-6);

        // Current site in cell medium; target site in cell 0
        contribution = volume_constraint.EvaluateHamiltonianContribution(6, 5, cell_population);
        TS_ASSERT_DELTA(contribution, alpha, 1e-6);

        // Current site in cell 0; target site in cell 1
        contribution = volume_constraint.EvaluateHamiltonianContribution(5, 9, cell_population);
        TS_ASSERT_DELTA(contribution, 2.0*alpha, 1e-6);
    }
示例#21
0
    void TestVolumeDependentAveragedSourcePdeArchiving() throw(Exception)
    {
        EXIT_IF_PARALLEL;

        // Set up simulation time
        SimulationTime::Instance()->SetEndTimeAndNumberOfTimeSteps(1.0, 1);

        // Set up cell population
        HoneycombMeshGenerator generator(5, 5, 0);
        MutableMesh<2,2>* p_generating_mesh = generator.GetMesh();
        NodesOnlyMesh<2> mesh;
        mesh.ConstructNodesWithoutMesh(*p_generating_mesh, 1.5);
        std::vector<CellPtr> cells;
        CellsGenerator<FixedDurationGenerationBasedCellCycleModel, 2> cells_generator;
        cells_generator.GenerateBasic(cells, mesh.GetNumNodes());
        NodeBasedCellPopulation<2> cell_population(mesh, cells);

        FileFinder archive_dir("archive", RelativeTo::ChasteTestOutput);
        std::string archive_file = "VolumeDependentAveragedSourcePde.arch";
        ArchiveLocationInfo::SetMeshFilename("VolumeDependentAveragedSourcePde");

        {
            // Create a PDE object
            AbstractLinearEllipticPde<2,2>* const p_pde = new VolumeDependentAveragedSourcePde<2>(cell_population, 0.05);

            // Create output archive and archive PDE object
            ArchiveOpener<boost::archive::text_oarchive, std::ofstream> arch_opener(archive_dir, archive_file);
            boost::archive::text_oarchive* p_arch = arch_opener.GetCommonArchive();
            (*p_arch) << p_pde;

            // Avoid memory leak
            delete p_pde;
        }

        {
            AbstractLinearEllipticPde<2,2>* p_pde;

            // Create an input archive and restore PDE object from archive
            ArchiveOpener<boost::archive::text_iarchive, std::ifstream> arch_opener(archive_dir, archive_file);
            boost::archive::text_iarchive* p_arch = arch_opener.GetCommonArchive();
            (*p_arch) >> p_pde;

            // Test that the PDE and its member variables were archived correctly
            TS_ASSERT(dynamic_cast<VolumeDependentAveragedSourcePde<2>*>(p_pde) != NULL);

            VolumeDependentAveragedSourcePde<2>* p_static_cast_pde = static_cast<VolumeDependentAveragedSourcePde<2>*>(p_pde);
            TS_ASSERT_DELTA(p_static_cast_pde->GetCoefficient(), 0.05, 1e-6);
            TS_ASSERT_EQUALS(p_static_cast_pde->mrCellPopulation.GetNumRealCells(), 25u);
            TS_ASSERT(p_static_cast_pde->mpStaticCastCellPopulation != NULL);
            TS_ASSERT_EQUALS(p_static_cast_pde->mpStaticCastCellPopulation->GetNumRealCells(), 25u);

            // Avoid memory leaks
            delete &(p_static_cast_pde->mrCellPopulation);
            delete p_pde;
        }
    }
    void TestVertexCryptBoundaryForceMethods() throw (Exception)
    {
        // Create a simple 2D VertexMesh
        HoneycombVertexMeshGenerator generator(5, 5, false, 0.1, 0.5);
        MutableVertexMesh<2,2>* p_mesh = generator.GetMesh();

        // Translate mesh so that some points are below y=0
        p_mesh->Translate(0.0, -3.0);

        // Set up cells, one for each VertexElement. Give each cell
        // a birth time of -elem_index, so its age is elem_index
        std::vector<CellPtr> cells;
        boost::shared_ptr<AbstractCellMutationState> p_state(new WildTypeCellMutationState);
        boost::shared_ptr<AbstractCellProliferativeType> p_diff_type(new DifferentiatedCellProliferativeType);
        for (unsigned elem_index=0; elem_index<p_mesh->GetNumElements(); elem_index++)
        {
            FixedDurationGenerationBasedCellCycleModel* p_model = new FixedDurationGenerationBasedCellCycleModel();
            CellPtr p_cell(new Cell(p_state, p_model));
            p_cell->SetCellProliferativeType(p_diff_type);
            double birth_time = 0.0 - elem_index;
            p_cell->SetBirthTime(birth_time);
            cells.push_back(p_cell);
        }

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

        // Create a force system
        VertexCryptBoundaryForce<2> force(100);

        for (unsigned i=0; i<cell_population.GetNumNodes(); i++)
        {
            cell_population.GetNode(i)->ClearAppliedForce();
        }

        force.AddForceContribution(cell_population);

        // Check forces are correct
        for (unsigned i=0; i<cell_population.GetNumNodes(); i++)
        {
            TS_ASSERT_DELTA(cell_population.GetNode(i)->rGetAppliedForce()[0], 0.0, 1e-4);

            double y = cell_population.GetNode(i)->rGetLocation()[1];
            if (y >= 0.0)
            {
                // If y > 0, the force contribution should be zero...
                TS_ASSERT_DELTA(cell_population.GetNode(i)->rGetAppliedForce()[1], 0.0, 1e-4);
            }
            else
            {
                // ...otherwise, the force contribution should be quadratic in y
                double expected_force = force.GetForceStrength()*y*y;
                TS_ASSERT_DELTA(cell_population.GetNode(i)->rGetAppliedForce()[1], expected_force, 1e-4);
            }
        }
    }
    /*
     * == Test 1 - a basic vertex-based simulation ==
     *
     * In the first test, we run a simple vertex-based simulation of an epithelial monolayer.
     * Each cell in the simulation is assigned a simple stochastic cell-cycle model, the cells will divide randomly and never stop proliferating.
     */
    void TestVertexBasedMonolayer() throw (Exception)
    {
        /* The first thing we define is a 2D (specified by the <2,2>) mesh which holds the spatial information of the simulation. To do this we use one of a
         * number of {{{MeshGenerators}}}.*/
        HoneycombVertexMeshGenerator generator(2, 2);
        MutableVertexMesh<2,2>* p_mesh = generator.GetMesh();

        /* We now generate a collection of cells. We do this by using a {{{CellsGenerator}}} and we specify the proliferative
         * behaviour of the cell by choosing a {{{CellCycleModel}}}, here we choose a {{{StochasticDurationCellCycleModel}}} where
         * each cell is given a division time, drawn from a uniform distribution, when it is created. For a vertex simulation
         * we need as may cells as elements in the mesh.*/
        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);

        /* We now create a {{{CellPopulation}}} object (passing in the mesh and cells) to connect the mesh and the cells together.
         * Here that is a {{{VertexBasedCellPopulation}}} and the dimension is <2>.*/
        VertexBasedCellPopulation<2> cell_population(*p_mesh, cells);

        /*
         * We now create an {{{OffLatticeSimulation}}} object and pass in the
         * {{{CellPopulation}}}. We also set some options on the simulation
         * like output directory, output multiple (so we don't visualize every
         * timestep), and end time.
         */
        OffLatticeSimulation<2> simulator(cell_population);
        simulator.SetOutputDirectory("CellBasedDemo1");
        simulator.SetSamplingTimestepMultiple(200);
        simulator.SetEndTime(20.0);

        /* In order to specify how cells move around we create a "shared pointer" to a
         * {{{Force}}} object and pass it to the {{{OffLatticeSimulation}}}. This is done using the MAKE_PTR macro as follows.
         */
        MAKE_PTR(NagaiHondaForce<2>, p_force);
        simulator.AddForce(p_force);

        /* A {{{NagaiHondaForce}}} has to be used together with a child class of {{{AbstractTargetAreaModifier}}}.
         * This modifies the target area of individual cells and thus alters the relative forces
         * between neighbouring cells.
         */
        MAKE_PTR(SimpleTargetAreaModifier<2>, p_growth_modifier);
        simulator.AddSimulationModifier(p_growth_modifier);

        /* Finally 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.
         * We are checking that we reached the end time of the simulation
         * with the correct number of cells. If different simulation input parameters are being explored
         * the lines should be removed.
         */
        TS_ASSERT_EQUALS(cell_population.GetNumRealCells(), 16u);
        TS_ASSERT_DELTA(SimulationTime::Instance()->GetTime(), 20.0, 1e-10);
    }
示例#24
0
        void TestContractility()
        {
            HoneycombVertexMeshGenerator generator(4, 4);
            MutableVertexMesh<2,2>* p_mesh = generator.GetMesh();
            p_mesh->SetCellRearrangementThreshold(0.1);

            MAKE_PTR(DifferentiatedCellProliferativeType, p_diff_type);
            std::vector<CellPtr> cells;

            CellsGenerator<StochasticDurationCellCycleModel, 2> cells_generator;
            cells_generator.GenerateBasic(cells, p_mesh->GetNumElements(), std::vector<unsigned>(), p_diff_type);

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

            boost::shared_ptr<AbstractCellProperty> type_1(new CellType(1, 5));
            boost::shared_ptr<AbstractCellProperty> type_2(new CellType(2, 5));
            boost::shared_ptr<AbstractCellProperty> label(new CellLabel(1));

            unsigned index = 0;
            for (AbstractCellPopulation<2>::Iterator cell_iter = cell_population.Begin();
                    cell_iter != cell_population.End();
                    ++cell_iter, index++)
            {
                cell_iter->AddCellProperty(type_1);
                cell_iter->GetCellData()->SetItem("contractility", (double)index);
            }

            OffLatticeSimulation<2> simulator(cell_population);
            simulator.SetOutputDirectory("ContractilityTest");
            simulator.SetSamplingTimestepMultiple(10);
            simulator.SetEndTime(5.0);

            MAKE_PTR(NagaiHondaMultipleDifferentialAdhesionForce<2>, p_force);

            std::vector<std::vector<double> > adhesion_matrix(4, std::vector<double>(4, 0.0));

            adhesion_matrix[0][1] = adhesion_matrix[1][0] = 2.0;
            adhesion_matrix[1][1] = 1.0;

            //double contractility = 5.0;
            //double lambda = 10.0;

            p_force->SetNagaiHondaAdhesionMatrix(adhesion_matrix);
            p_force->SetNagaiHondaDeformationEnergyParameter(30.0);
            //p_force->SetNagaiHondaDeformationEnergyParameter(lambda + contractility);
            p_force->SetNagaiHondaMembraneSurfaceEnergyParameter(20.0);
            simulator.AddForce(p_force);

            //double target_area = 1.0;
            MAKE_PTR(SimpleTargetAreaModifier<2>, p_growth_modifier);
            //p_growth_modifier->SetReferenceTargetArea(target_area*(lambda/(lambda + contractility)));
            simulator.AddSimulationModifier(p_growth_modifier);

            simulator.Solve();
        }
    void TestNodeAndMeshMethods() throw(Exception)
    {
        // Create a Potts-based cell population
        PottsMeshGenerator<2> generator(4, 2, 2, 4, 2, 2);
        PottsMesh<2>* p_mesh = generator.GetMesh();

        std::vector<CellPtr> cells;
        CellsGenerator<FixedDurationGenerationBasedCellCycleModel, 2> cells_generator;
        cells_generator.GenerateBasic(cells, p_mesh->GetNumElements());

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

        // Test GetNumNodes()
        TS_ASSERT_EQUALS(cell_population.GetNumNodes(), 16u);

        // Test GetNode()
        for (unsigned index=0; index<cell_population.GetNumNodes(); index++)
        {
            Node<2>* p_node = cell_population.GetNode(index);
            TS_ASSERT_EQUALS(p_node->GetIndex(), index);

            c_vector<double, 2> node_location = p_node->rGetLocation();
            c_vector<double, 2> expected;
            expected(0) = (double)(index%4);
            expected(1) = (double)(index>3) + (double)(index>7) + (double)(index>11);

            double drift = norm_2(node_location-expected);
            TS_ASSERT_LESS_THAN(drift, 1e-6);
        }

        // Test GetElement()
        for (unsigned index=0; index<cell_population.GetNumElements(); index++)
        {
            PottsElement<2>* p_element = cell_population.GetElement(index);
            TS_ASSERT_EQUALS(p_element->GetIndex(), index);

            TS_ASSERT_EQUALS(p_element->GetNumNodes(), 4u);
        }

        // Test SetNode()
        ChastePoint<2> unused_point;
        TS_ASSERT_THROWS_THIS(cell_population.SetNode(0, unused_point),
                              "SetNode() cannot be called on a subclass of AbstractOnLatticeCellPopulation.");

        // Test GetWidth() method
        double width_x = cell_population.GetWidth(0);
        TS_ASSERT_DELTA(width_x, 3.0, 1e-4);

        double width_y = cell_population.GetWidth(1);
        TS_ASSERT_DELTA(width_y, 3.0, 1e-4);

        // Test GetNeighbouringNodeIndices() method
        TS_ASSERT_THROWS_THIS(cell_population.GetNeighbouringNodeIndices(10),
            "Cannot call GetNeighbouringNodeIndices() on a subclass of AbstractOnLatticeCellPopulation, need to go through the PottsMesh instead");
    }
    void TestSloughingCellKillerTopAndSides() throw(Exception)
    {
        // Create mesh
        TrianglesMeshReader<2,2> mesh_reader("mesh/test/data/square_128_elements");
        MutableMesh<2,2> mesh;
        mesh.ConstructFromMeshReader(mesh_reader);
        mesh.Translate(-0.25,-0.25);

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

        // Create cell population
        MeshBasedCellPopulation<2> cell_population(mesh, cells);

        // Create cell killer and kill cells
        SloughingCellKiller<2> sloughing_cell_killer(&cell_population, 0.5, true, 0.5);

        sloughing_cell_killer.CheckAndLabelCellsForApoptosisOrDeath();

        TS_ASSERT_EQUALS(sloughing_cell_killer.GetIdentifier(), "SloughingCellKiller-2");

        // Check that cells were labelled for death correctly
        for (AbstractCellPopulation<2>::Iterator cell_iter = cell_population.Begin();
             cell_iter != cell_population.End();
             ++cell_iter)
        {
            double x = cell_population.GetLocationOfCellCentre(*cell_iter)[0];
            double y = cell_population.GetLocationOfCellCentre(*cell_iter)[1];

            if ((x<0) || (x>0.5) || (y>0.5))
            {
                TS_ASSERT_EQUALS(cell_iter->IsDead(), true);
            }
            else
            {
                TS_ASSERT_EQUALS(cell_iter->IsDead(), false);
            }
        }

        cell_population.RemoveDeadCells();

        for (AbstractCellPopulation<2>::Iterator cell_iter = cell_population.Begin();
             cell_iter != cell_population.End();
             ++cell_iter)
        {
            double x = cell_population.GetLocationOfCellCentre(*cell_iter)[0];
            double y = cell_population.GetLocationOfCellCentre(*cell_iter)[1];

            TS_ASSERT_LESS_THAN_EQUALS(x, 0.5);
            TS_ASSERT_LESS_THAN_EQUALS(y, 0.5);
        }
    }
    void TestWriter() throw (Exception)
    {
        EXIT_IF_PARALLEL;

        // Set up a small MeshBasedCellPopulationWithGhostNodes using an appropriate cell-cycle model class
        CylindricalHoneycombMeshGenerator generator(5, 4, 1);
        Cylindrical2dMesh* p_mesh = generator.GetCylindricalMesh();
        double domain_length_for_wnt = 4.0*(sqrt(3.0)/2);
        std::vector<unsigned> location_indices = generator.GetCellLocationIndices();

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

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

        // Create an instance of a Wnt concentration
        WntConcentration<2>::Instance()->SetType(LINEAR);
        WntConcentration<2>::Instance()->SetCellPopulation(cell_population);
        WntConcentration<2>::Instance()->SetCryptLength(domain_length_for_wnt);

        // Initialise the cell population to set up the ODE system associated with each cell-cycle model object
        cell_population.InitialiseCells();

        // Create an output directory for the writer
        std::string output_directory = "TestCellBetaCateninWriter";
        OutputFileHandler output_file_handler(output_directory, false);
        std::string results_dir = output_file_handler.GetOutputDirectoryFullPath();

        // Create a CellBetaCateninWriter and test that the correct output is generated
        CellBetaCateninWriter<2,2> cell_writer;
        cell_writer.OpenOutputFile(output_file_handler);
        cell_writer.WriteTimeStamp();
        for (AbstractCellPopulation<2,2>::Iterator cell_iter = cell_population.Begin();
             cell_iter != cell_population.End();
             ++cell_iter)
        {
            cell_writer.VisitCell(*cell_iter, &cell_population);
        }
        cell_writer.CloseFile();

        /*
         * To verify this test, we can eyeball the results file to check that the correct default
         * initial conditions are output (see VanLeeuwen2009WntSwatCellCycleOdeSystem.hpp).
         */
        FileComparison(results_dir + "results.vizbetacatenin", "crypt/test/data/TestCellBetaCateninWriter/results.vizbetacatenin").CompareFiles();

        // Test the correct data are returned for VTK output for the first cell
        double vtk_data = cell_writer.GetCellDataForVtkOutput(*(cell_population.Begin()), &cell_population);
        TS_ASSERT_DELTA(vtk_data, 14.6088, 1e-4);

        // Avoid memory leak
        WntConcentration<2>::Destroy();
    }
    void TestPottsMonolayerCellSorting() throw (Exception)
    {
        EXIT_IF_PARALLEL;

        // Create a simple 2D PottsMesh
        PottsMeshGenerator<2> generator(60, 10, 4, 60, 10, 4);
        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);

        // Make this pointer first as if we move it after creating the cell population the label numbers aren't tracked
        MAKE_PTR(CellLabel, p_label);

        // Create cell population
        PottsBasedCellPopulation<2> cell_population(*p_mesh, cells);
        cell_population.AddCellPopulationCountWriter<CellMutationStatesCountWriter>(); // So outputs the labelled cells

        for (AbstractCellPopulation<2>::Iterator cell_iter = cell_population.Begin();
             cell_iter != cell_population.End();
             ++cell_iter)
        {
            if (RandomNumberGenerator::Instance()->ranf() < 0.5)
            {
                (*cell_iter)->AddCellProperty(p_label);
            }
        }

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

        // Create update rules and pass to the simulation
        MAKE_PTR(VolumeConstraintPottsUpdateRule<2>, p_volume_constraint_update_rule);
        p_volume_constraint_update_rule->SetMatureCellTargetVolume(16);
        p_volume_constraint_update_rule->SetDeformationEnergyParameter(0.2);
        simulator.AddPottsUpdateRule(p_volume_constraint_update_rule);

        MAKE_PTR(DifferentialAdhesionPottsUpdateRule<2>, p_differential_adhesion_update_rule);
        p_differential_adhesion_update_rule->SetLabelledCellLabelledCellAdhesionEnergyParameter(0.16);
        p_differential_adhesion_update_rule->SetLabelledCellCellAdhesionEnergyParameter(0.11);
        p_differential_adhesion_update_rule->SetCellCellAdhesionEnergyParameter(0.02);
        p_differential_adhesion_update_rule->SetLabelledCellBoundaryAdhesionEnergyParameter(0.16);
        p_differential_adhesion_update_rule->SetCellBoundaryAdhesionEnergyParameter(0.16);
        simulator.AddPottsUpdateRule(p_differential_adhesion_update_rule);

        // Run simulation
        simulator.Solve();
    }
    /*
    * Here we set up a test with 5 nodes, make a cell for each. We then set cell
    * 0 to be associated with node 1 instead of node 0, and Validate() throws an
    * exception. We then set node 0 to be a particle node, and Validate() passes.
    */
    void TestValidateNodeBasedCellPopulationWithParticles() throw(Exception)
    {
        EXIT_IF_PARALLEL;    // This test doesn't work in parallel.

        // Create a simple mesh
        TrianglesMeshReader<2,2> mesh_reader("mesh/test/data/square_4_elements");
        TetrahedralMesh<2,2> generating_mesh;
        generating_mesh.ConstructFromMeshReader(mesh_reader);

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

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

        std::vector<unsigned> cell_location_indices;
        for (unsigned i=0; i<cells.size(); i++)
        {
            cell_location_indices.push_back(i);
        }

        // Fails as the cell population constructor is not given the location indices
        // corresponding to real cells, so cannot work out which nodes are
        // particles
        std::vector<CellPtr> cells_copy(cells);
        TS_ASSERT_THROWS_THIS(NodeBasedCellPopulationWithParticles<2> dodgy_cell_population(mesh, cells_copy),
                              "Node 4 does not appear to be a particle or has a cell associated with it");

        // Passes as the cell population constructor automatically works out which
        // cells are particles using the mesh and cell_location_indices
        NodeBasedCellPopulationWithParticles<2> cell_population(mesh, cells, cell_location_indices);

        // Here we set the particles to what they already are
        std::set<unsigned> particle_indices;
        particle_indices.insert(mesh.GetNumNodes()-1);
        cell_population.SetParticles(particle_indices);

        // So validate passes at the moment
        cell_population.Validate();

        // Test GetCellUsingLocationIndex()
        TS_ASSERT_THROWS_NOTHING(cell_population.GetCellUsingLocationIndex(0)); // real cell
        TS_ASSERT_THROWS_THIS(cell_population.GetCellUsingLocationIndex(mesh.GetNumNodes()-1u),"Location index input argument does not correspond to a Cell"); // particles

        // Now we label a real cell's node as particle
        particle_indices.insert(1);

        // Validate detects this inconsistency
        TS_ASSERT_THROWS_THIS(cell_population.SetParticles(particle_indices),"Node 1 is labelled as a particle and has a cell attached");
    }
    /*
     * This tests that a sensible error is thrown if the coarse mesh is too small/
     */
    void TestMultipleCaBasedCellsOutsideMesh() throw(Exception)
    {
        EXIT_IF_PARALLEL;

        // 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;
        CellsGenerator<FixedDurationGenerationBasedCellCycleModel, 2> cells_generator;
        cells_generator.GenerateBasic(cells, 100);

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

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

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

        // Set up PDE and pass to simulation via handler (zero uptake to check analytic solution)
        AveragedSourcePde<2> pde(cell_population, 0.0);
        ConstBoundaryCondition<2> bc(1.0);
        PdeAndBoundaryConditions<2> pde_and_bc(&pde, &bc, false);
        pde_and_bc.SetDependentVariableName("nutrient");

        CellBasedPdeHandler<2> pde_handler(&cell_population);
        pde_handler.AddPdeAndBc(&pde_and_bc);
        pde_handler.SetImposeBcsOnCoarseBoundary(true);

        // Create coarse mesh smaller than the PottsMesh
        ChastePoint<2> lower(0.0, 0.0);
        ChastePoint<2> upper(5.0, 5.0);

        ChasteCuboid<2> cuboid(lower, upper);
        pde_handler.UseCoarsePdeMesh(1.0, cuboid);


        simulator.SetCellBasedPdeHandler(&pde_handler);


        // Solve the system
        TS_ASSERT_THROWS_THIS(simulator.Solve(), "Point [6,0] is not in mesh - all elements tested");
    }