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()); }
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 }
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); }
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); }
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); }
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); }
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"); }