/* * 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"); }
/* * 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]; } }
void TestConstruct2dParallelPopulation() throw (Exception) { NodesOnlyMesh<2> mesh; mesh.SetMaximumInteractionDistance(0.5); std::vector<CellPtr> cells; ParallelCellsGenerator<StochasticDurationGenerationBasedCellCycleModel, 2> generator; c_vector<double, 4> bounding_box = generator.GetArchiveBoundingBox("cell_based/test/data/TestParallelConstruction/Population2d.dat"); TS_ASSERT_DELTA(bounding_box[0], 0.0, 1e-4); TS_ASSERT_DELTA(bounding_box[1], 1.0, 1e-4); TS_ASSERT_DELTA(bounding_box[2], 0.0, 1e-4); TS_ASSERT_DELTA(bounding_box[3], 1.0, 1e-4); generator.GenerateParallelCells("cell_based/test/data/TestParallelConstruction/Population2d.dat", cells, mesh, CellPropertyRegistry::Instance()->Get<TransitCellProliferativeType>()); unsigned num_nodes = mesh.GetNumNodes(); unsigned total_nodes; MPI_Allreduce(&num_nodes, &total_nodes, 1, MPI_UNSIGNED, MPI_SUM, PetscTools::GetWorld()); TS_ASSERT_EQUALS(total_nodes, 4u); unsigned num_cells = cells.size(); unsigned total_cells; MPI_Allreduce(&num_cells, &total_cells, 1, MPI_UNSIGNED, MPI_SUM, PetscTools::GetWorld()); TS_ASSERT_EQUALS(total_cells, 4u); for (unsigned i=0; i<cells.size(); i++) { TS_ASSERT(cells[i]->GetCellProliferativeType()->IsType<TransitCellProliferativeType>()); } }
void TestConstruct1dParallelPopulation() throw (Exception) { NodesOnlyMesh<1> mesh; mesh.SetMaximumInteractionDistance(0.5); std::vector<CellPtr> cells; ParallelCellsGenerator<FixedDurationGenerationBasedCellCycleModel, 1> generator; c_vector<double, 2> bounding_box = generator.GetArchiveBoundingBox("cell_based/test/data/TestParallelConstruction/Population1d.dat"); TS_ASSERT_DELTA(bounding_box[0], 0.0, 1e-4); TS_ASSERT_DELTA(bounding_box[1], 1.0, 1e-4); // Check an assertion which tests whether the space dimensions of the mesh and archive file are consistent. TS_ASSERT_THROWS_THIS(generator.GetArchiveBoundingBox("cell_based/test/data/TestParallelConstruction/Population2d.dat"), "Space dimension of ParallelCellsGenerator and archive file do not match"); generator.GenerateParallelCells("cell_based/test/data/TestParallelConstruction/Population1d.dat", cells, mesh, CellPropertyRegistry::Instance()->Get<DifferentiatedCellProliferativeType>()); unsigned num_nodes = mesh.GetNumNodes(); unsigned total_nodes; MPI_Allreduce(&num_nodes, &total_nodes, 1, MPI_UNSIGNED, MPI_SUM, PetscTools::GetWorld()); TS_ASSERT_EQUALS(total_nodes, 2u); unsigned num_cells = cells.size(); unsigned total_cells; MPI_Allreduce(&num_cells, &total_cells, 1, MPI_UNSIGNED, MPI_SUM, PetscTools::GetWorld()); TS_ASSERT_EQUALS(total_cells, 2u); for (unsigned i=0; i<cells.size(); i++) { TS_ASSERT(cells[i]->GetCellProliferativeType()->IsType<DifferentiatedCellProliferativeType>()); } }
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); }
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 TestStandardResultForArchivingTestsBelow() throw (Exception) { EXIT_IF_PARALLEL; // HoneycombMeshGenereator does not work in parallel. // Create a simple mesh int num_cells_depth = 5; int num_cells_width = 5; HoneycombMeshGenerator generator(num_cells_width, num_cells_depth, 0); TetrahedralMesh<2,2>* p_generating_mesh = generator.GetMesh(); // Convert this to a NodesOnlyMesh NodesOnlyMesh<2> mesh; mesh.ConstructNodesWithoutMesh(*p_generating_mesh, 1.5); // Create cells std::vector<CellPtr> cells; CellsGenerator<FixedDurationGenerationBasedCellCycleModel, 2> cells_generator; cells_generator.GenerateBasicRandom(cells, mesh.GetNumNodes()); // Create a node based cell population NodeBasedCellPopulation<2> node_based_cell_population(mesh, cells); // Set up cell-based simulation OffLatticeSimulation<2> simulator(node_based_cell_population); simulator.SetOutputDirectory("TestOffLatticeSimulationWithNodeBasedCellPopulationStandardResult"); simulator.SetEndTime(2.5); // Create a force law and pass it to the simulation MAKE_PTR(GeneralisedLinearSpringForce<2>, p_linear_force); p_linear_force->SetCutOffLength(1.5); simulator.AddForce(p_linear_force); // Create some boundary conditions and pass them to the simulation c_vector<double,2> normal = zero_vector<double>(2); normal(1) =-1.0; MAKE_PTR_ARGS(PlaneBoundaryCondition<2>, p_bc, (&node_based_cell_population, zero_vector<double>(2), normal)); // y>0 simulator.AddCellPopulationBoundaryCondition(p_bc); // Solve simulator.Solve(); // Check some results mNode3x = 3.0454; mNode3y = 0.0000; mNode4x = 4.0468; mNode4y = 0.0101; std::vector<double> node_3_location = simulator.GetNodeLocation(3); TS_ASSERT_DELTA(node_3_location[0], mNode3x, 1e-4); TS_ASSERT_DELTA(node_3_location[1], mNode3y, 1e-4); std::vector<double> node_4_location = simulator.GetNodeLocation(4); TS_ASSERT_DELTA(node_4_location[0], mNode4x, 1e-4); TS_ASSERT_DELTA(node_4_location[1], mNode4y, 1e-4); }
void TestUpdateCellProcessLocation() throw (Exception) { if (PetscTools::GetNumProcs() > 1) { if (PetscTools::AmMaster()) { // Move node to the next location. c_vector<double, 3> new_location = zero_vector<double>(3); new_location[2] = 1.6; ChastePoint<3> point(new_location); mpNodesOnlyMesh->GetNode(0)->SetPoint(point); } if (PetscTools::GetMyRank() == 1) { // Move node to the next location. c_vector<double, 3> new_location = zero_vector<double>(3); new_location[2] = 0.5; ChastePoint<3> point(new_location); mpNodesOnlyMesh->GetNode(1)->SetPoint(point); } #if BOOST_VERSION < 103700 TS_ASSERT_THROWS_THIS(mpNodeBasedCellPopulation->SendCellsToNeighbourProcesses(), "Parallel cell-based Chaste requires Boost >= 1.37"); #else mpNodeBasedCellPopulation->UpdateCellProcessLocation(); if (PetscTools::AmMaster()) { TS_ASSERT_EQUALS(mpNodesOnlyMesh->GetNumNodes(), 1u); TS_ASSERT_EQUALS(mpNodeBasedCellPopulation->GetNumRealCells(), 1u); } if (PetscTools::GetMyRank() == 1) { TS_ASSERT_EQUALS(mpNodesOnlyMesh->GetNumNodes(), 1u); TS_ASSERT_EQUALS(mpNodeBasedCellPopulation->GetNumRealCells(), 1u); AbstractMesh<3,3>::NodeIterator node_iter = mpNodesOnlyMesh->GetNodeIteratorBegin(); TS_ASSERT_DELTA(node_iter->rGetLocation()[2], 1.6, 1e-4); } #endif } }
// Testing Save() void TestSave() throw (Exception) { EXIT_IF_PARALLEL; // HoneycombMeshGenereator does not work in parallel // Create a simple mesh unsigned num_cells_depth = 5; unsigned num_cells_width = 5; HoneycombMeshGenerator generator(num_cells_width, num_cells_depth, 0); TetrahedralMesh<2,2>* p_generating_mesh = generator.GetMesh(); // Convert this to a NodesOnlyMesh NodesOnlyMesh<2> mesh; mesh.ConstructNodesWithoutMesh(*p_generating_mesh, 1.5); // Create cells std::vector<CellPtr> cells; CellsGenerator<FixedDurationGenerationBasedCellCycleModel, 2> cells_generator; cells_generator.GenerateBasicRandom(cells, mesh.GetNumNodes()); // Create a node based cell population NodeBasedCellPopulation<2> node_based_cell_population(mesh, cells); // Set up cell-based simulation OffLatticeSimulation<2> simulator(node_based_cell_population); simulator.SetOutputDirectory("TestOffLatticeSimulationWithNodeBasedCellPopulationSaveAndLoad"); simulator.SetEndTime(0.1); // Create a force law and pass it to the simulation MAKE_PTR(GeneralisedLinearSpringForce<2>, p_linear_force); p_linear_force->SetCutOffLength(1.5); simulator.AddForce(p_linear_force); // Create some boundary conditions and pass them to the simulation c_vector<double,2> normal = zero_vector<double>(2); normal(1) =-1.0; MAKE_PTR_ARGS(PlaneBoundaryCondition<2>, p_bc, (&node_based_cell_population, zero_vector<double>(2), normal)); // y>0 simulator.AddCellPopulationBoundaryCondition(p_bc); /* * For more thorough testing of serialization, we 'turn on' adaptivity. * Note that this has no effect on the numerical results, since the * conditions under which the time step would be adapted are not invoked * in this example. */ boost::shared_ptr<AbstractNumericalMethod<2,2> > p_method(new ForwardEulerNumericalMethod<2,2>()); p_method->SetUseAdaptiveTimestep(true); simulator.SetNumericalMethod(p_method); // Solve simulator.Solve(); // Save the results CellBasedSimulationArchiver<2, OffLatticeSimulation<2> >::Save(&simulator); }
/** * Create a simulation of a NodeBasedCellPopulation with a NodeBasedCellPopulationMechanicsSystem. * Test that no exceptions are thrown, and write the results to file. */ void TestSimpleMonolayer() throw (Exception) { EXIT_IF_PARALLEL; // HoneycombMeshGenereator does not work in parallel. // Create a simple mesh unsigned num_cells_depth = 5; unsigned num_cells_width = 5; HoneycombMeshGenerator generator(num_cells_width, num_cells_depth, 0); TetrahedralMesh<2,2>* p_generating_mesh = generator.GetMesh(); // Convert this to a NodesOnlyMesh NodesOnlyMesh<2> mesh; mesh.ConstructNodesWithoutMesh(*p_generating_mesh, 1.5); // Create cells std::vector<CellPtr> cells; CellsGenerator<FixedDurationGenerationBasedCellCycleModel, 2> cells_generator; cells_generator.GenerateBasicRandom(cells, mesh.GetNumNodes()); // Create a node-based cell population NodeBasedCellPopulation<2> node_based_cell_population(mesh, cells); // Set up cell-based simulation OffLatticeSimulation<2> simulator(node_based_cell_population); simulator.SetOutputDirectory("TestOffLatticeSimulationWithNodeBasedCellPopulation"); // No need to go for long, don't want any birth or regular grid will be disrupted. simulator.SetEndTime(0.5); // Create a force law and pass it to the simulation MAKE_PTR(GeneralisedLinearSpringForce<2>, p_linear_force); p_linear_force->SetCutOffLength(1.5); simulator.AddForce(p_linear_force); simulator.Solve(); // Check that nothing's gone badly wrong by testing that nodes aren't too close together double min_distance_between_cells = 1.0; for (unsigned i=0; i<simulator.rGetCellPopulation().GetNumNodes(); i++) { for (unsigned j=i+1; j<simulator.rGetCellPopulation().GetNumNodes(); j++) { double distance = norm_2(simulator.rGetCellPopulation().GetNode(i)->rGetLocation()-simulator.rGetCellPopulation().GetNode(j)->rGetLocation()); if (distance < min_distance_between_cells) { min_distance_between_cells = distance; } } } TS_ASSERT(min_distance_between_cells > 0.999); }
/** * Create a simulation of a NodeBasedCellPopulation with a BuskeCompressionForce system. * Test that no exceptions are thrown, and write the results to file. */ void TestSimpleMonolayerWithBuskeCompressionForce() throw (Exception) { EXIT_IF_PARALLEL; // HoneycombMeshGenerator doesn't work in parallel // Create a simple mesh unsigned num_cells_depth = 5; unsigned num_cells_width = 5; HoneycombMeshGenerator generator(num_cells_width, num_cells_depth, 0); TetrahedralMesh<2,2>* p_generating_mesh = generator.GetMesh(); // Convert this to a NodesOnlyMesh NodesOnlyMesh<2> mesh; mesh.ConstructNodesWithoutMesh(*p_generating_mesh, 1.5); // Create cells std::vector<CellPtr> cells; MAKE_PTR(TransitCellProliferativeType, p_transit_type); CellsGenerator<FixedDurationGenerationBasedCellCycleModel, 2> cells_generator; cells_generator.GenerateBasicRandom(cells, mesh.GetNumNodes(), p_transit_type); // Create a node-based cell population NodeBasedCellPopulation<2> node_based_cell_population(mesh, cells); // Set up cell-based simulation OffLatticeSimulation<2> simulator(node_based_cell_population); simulator.SetOutputDirectory("TestOffLatticeSimulationWithBuskeCompressionForce"); simulator.SetEndTime(5.0); // Create a force law and pass it to the simulation MAKE_PTR(BuskeCompressionForce<2>, buske_compression_force); buske_compression_force->SetCompressionEnergyParameter(0.01); simulator.AddForce(buske_compression_force); simulator.Solve(); // Check that nothing's gone badly wrong by testing that nodes aren't too close together double min_distance_between_cells = 1.0; for (unsigned i=0; i<simulator.rGetCellPopulation().GetNumNodes(); i++) { for (unsigned j=i+1; j<simulator.rGetCellPopulation().GetNumNodes(); j++) { double distance = norm_2(simulator.rGetCellPopulation().GetNode(i)->rGetLocation()-simulator.rGetCellPopulation().GetNode(j)->rGetLocation()); if (distance < min_distance_between_cells) { min_distance_between_cells = distance; } } } TS_ASSERT(min_distance_between_cells > 1e-3); }
void TestVolumeDependentAveragedSourcePdeMethods() throw(Exception) { EXIT_IF_PARALLEL; // Create a 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); // Create a PDE object VolumeDependentAveragedSourcePde<2> pde(cell_population, 0.05); // Test that the member variables have been initialised correctly TS_ASSERT(pde.mpStaticCastCellPopulation != NULL); // For simplicity we create a very large coarse mesh, so we know that all cells are contained in one element TrianglesMeshReader<2,2> mesh_reader("mesh/test/data/square_2_elements"); TetrahedralMesh<2,2> coarse_mesh; coarse_mesh.ConstructFromMeshReader(mesh_reader); coarse_mesh.Scale(10.0, 10.0); // Test SetupSourceTerms() when no map between cells and coarse mesh elements is supplied pde.SetupSourceTerms(coarse_mesh); TS_ASSERT_EQUALS(pde.mCellDensityOnCoarseElements.size(), 2u); // The first element has area 0.5*10*10 = 50 and there are 5*5 = 25 cells, so the cell density is 25/50 = 0.5 // The radius of each node is 0.5 and the density is normalized with cell area (1/4.0) in `VolumeDependentAveragedSourcePde`. TS_ASSERT_DELTA(pde.mCellDensityOnCoarseElements[0], 0.5/4.0, 1e-6); // The first element doesn't contain any cells, so the cell density is zero TS_ASSERT_DELTA(pde.mCellDensityOnCoarseElements[1], 0.0, 1e-6); // Now test SetupSourceTerms() when a map between cells and coarse mesh elements is supplied std::map<CellPtr, unsigned> cell_pde_element_map; for (AbstractCellPopulation<2>::Iterator cell_iter = cell_population.Begin(); cell_iter != cell_population.End(); ++cell_iter) { cell_pde_element_map[*cell_iter] = 0; } pde.SetupSourceTerms(coarse_mesh, &cell_pde_element_map); TS_ASSERT_DELTA(pde.mCellDensityOnCoarseElements[0], 0.5/4.0, 1e-6); TS_ASSERT_DELTA(pde.mCellDensityOnCoarseElements[1], 0.0, 1e-6); }
void TestInitialiseCellPdeElementMapAndFindCoarseElementContainingCell() throw(Exception) { EXIT_IF_PARALLEL; // Create a cell population HoneycombMeshGenerator generator(4, 4, 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); TS_ASSERT_EQUALS(pde_handler.mCellPdeElementMap.size(), 0u); // Test that InitialiseCellPdeElementMap() throws an exception if mpCoarsePdeMesh is not set up TS_ASSERT_THROWS_THIS(pde_handler.InitialiseCellPdeElementMap(), "InitialiseCellPdeElementMap() should only be called if mpCoarsePdeMesh is set up."); // Set up PDE and pass to handler AveragedSourcePde<2> pde(cell_population, -0.1); ConstBoundaryCondition<2> bc(1.0); PdeAndBoundaryConditions<2> pde_and_bc(&pde, &bc, false); pde_handler.AddPdeAndBc(&pde_and_bc); // Use a coarse PDE mesh ChastePoint<2> lower(0.0, 0.0); ChastePoint<2> upper(9.0, 9.0); ChasteCuboid<2> cuboid(lower, upper); pde_handler.UseCoarsePdeMesh(3.0, cuboid, true); // Test that mCellPdeElementMap is initialised correctly pde_handler.InitialiseCellPdeElementMap(); TS_ASSERT_EQUALS(pde_handler.mCellPdeElementMap.size(), cell_population.GetNumRealCells()); for (AbstractCellPopulation<2>::Iterator cell_iter = cell_population.Begin(); cell_iter != cell_population.End(); ++cell_iter) { unsigned containing_element_index = pde_handler.mCellPdeElementMap[*cell_iter]; TS_ASSERT_LESS_THAN(containing_element_index, pde_handler.GetCoarsePdeMesh()->GetNumElements()); TS_ASSERT_EQUALS(containing_element_index, pde_handler.FindCoarseElementContainingCell(*cell_iter)); } }
/* * To visualize the results, open a new terminal, {{{cd}}} to the Chaste directory, * then {{{cd}}} to {{{anim}}}. Then do: {{{java Visualize2dVertexCells /tmp/$USER/testoutput/CellBasedDemo1/results_from_time_0}}}. * We may have to do: {{{javac Visualize2dVertexCells.java}}} beforehand to create the * java executable. * * EMPTYLINE * * The {{{make_a_movie}}} script can be used to generate a video based on the results of your simulation. * To do this, first visualize the results using {{{Visualize2dVertexCells}}} as described above. Click * on the box marked "Output" and play through the whole simulation to generate a sequence of {{{.png}}} * images, one for each time step. Next, still in the {{{anim}}} folder, do: {{{./make_a_movie}}}. * This reads in the {{{.png}}} files and creates a video file called {{{simulation.mpeg}}}. * * EMPTYLINE * * Results can also be visualized using Paraview. See the UserTutorials/VisualizingWithParaview tutorial for more information. * * EMPTYLINE * * == Test 2 - basic node-based simulation == * * We next show how to modify the previous test to implement a 'node-based' simulation, * in which cells are represented by overlapping spheres (actually circles, since we're * in 2D). */ void TestNodeBasedMonolayer() throw (Exception) { /* We now need to create a {{{NodesOnlyMesh}}} we do this by first creating a {{{MutableMesh}}} * and passing this to a helper method {{{ConstructNodesWithoutMesh}}} along with a interaction cut off length * that defines the connectivity in the mesh. */ HoneycombMeshGenerator generator(2, 2); //**Changed**// MutableMesh<2,2>* p_generating_mesh = generator.GetMesh(); //**Changed**// NodesOnlyMesh<2> mesh; //**Changed**// mesh.ConstructNodesWithoutMesh(*p_generating_mesh, 1.5); //**Changed**// /* We create the cells as before, only this time we need one cell per node.*/ std::vector<CellPtr> cells; MAKE_PTR(TransitCellProliferativeType, p_transit_type); CellsGenerator<StochasticDurationCellCycleModel, 2> cells_generator; cells_generator.GenerateBasicRandom(cells, mesh.GetNumNodes(), p_transit_type); //**Changed**// /* This time we create a {{{NodeBasedCellPopulation}}} as we are using a {{{NodesOnlyMesh}}}.*/ NodeBasedCellPopulation<2> cell_population(mesh, cells);//**Changed**// /* We create an {{{OffLatticeSimulation}}} object as before, all we change is the output directory * and output results more often as a larger default timestep is used for these simulations. */ OffLatticeSimulation<2> simulator(cell_population); simulator.SetOutputDirectory("CellBasedDemo2"); //**Changed**// simulator.SetSamplingTimestepMultiple(12); //**Changed**// simulator.SetEndTime(20.0); /* We use a different {{{Force}}} which is suitable for node based simulations. */ MAKE_PTR(RepulsionForce<2>, p_force); //**Changed**// simulator.AddForce(p_force); /* In all types of simulation you may specify how cells are removed from the simulation by specifying * a {{{CellKiller}}}. You create these in the same was as the {{{Force}}} and pass them to the {{{CellBasedSimulation}}}. * Note that here the constructor for {{{RandomCellKiller}}} requires some arguments to be passed to it, therefore we use the * {{{MAKE_PTR_ARGS}}} macro. */ MAKE_PTR_ARGS(RandomCellKiller<2>, p_cell_killer, (&cell_population, 0.01)); //**Changed**// simulator.AddCellKiller(p_cell_killer); /* Again we call the {{{Solve}}} method on the simulation to run the simulation.*/ simulator.Solve(); /* The next two lines are for test purposes only and are not part of this tutorial. * Again, we are checking that we reached the end time of the simulation * with the correct number of cells. */ TS_ASSERT_EQUALS(cell_population.GetNumRealCells(), 7u); TS_ASSERT_DELTA(SimulationTime::Instance()->GetTime(), 20.0, 1e-10); }
void TestUseCoarsePdeMeshNotCentredOnPopulation() throw(Exception) { EXIT_IF_PARALLEL; // Create a cell population HoneycombMeshGenerator generator(4, 4, 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 UseCoarsePdeMesh() throws an exception if no PDEs are specified ChastePoint<2> lower(0.0, 0.0); ChastePoint<2> upper(9.0, 9.0); ChasteCuboid<2> cuboid(lower, upper); // Set up PDE and pass to handler AveragedSourcePde<2> pde(cell_population, -0.1); ConstBoundaryCondition<2> bc(1.0); PdeAndBoundaryConditions<2> pde_and_bc(&pde, &bc, false); pde_handler.AddPdeAndBc(&pde_and_bc); // Test UseCoarsePdeMesh() again pde_handler.UseCoarsePdeMesh(3.0, cuboid); // Check that the centre of the mesh co-incides with centre of the cuboid. c_vector<double,2> centre_of_coarse_mesh = zero_vector<double>(2); for (unsigned i=0; i<pde_handler.GetCoarsePdeMesh()->GetNumNodes(); i++) { centre_of_coarse_mesh += pde_handler.GetCoarsePdeMesh()->GetNode(i)->rGetLocation(); } centre_of_coarse_mesh /= pde_handler.GetCoarsePdeMesh()->GetNumNodes(); c_vector<double,2> centre_of_cuboid = 0.5*(lower.rGetLocation() + upper.rGetLocation()); TS_ASSERT_DELTA(norm_2(centre_of_cuboid - centre_of_coarse_mesh), 0.0, 1e-4); }
// Testing Save void TestSave() throw (Exception) { EXIT_IF_PARALLEL; // HoneycombMeshGenereator does not work in parallel // Create a simple mesh int num_cells_depth = 5; int num_cells_width = 5; HoneycombMeshGenerator generator(num_cells_width, num_cells_depth, 0); TetrahedralMesh<2,2>* p_generating_mesh = generator.GetMesh(); // Convert this to a NodesOnlyMesh NodesOnlyMesh<2> mesh; mesh.ConstructNodesWithoutMesh(*p_generating_mesh, 1.5); // Create cells std::vector<CellPtr> cells; CellsGenerator<FixedDurationGenerationBasedCellCycleModel, 2> cells_generator; cells_generator.GenerateBasicRandom(cells, mesh.GetNumNodes()); // Create a node based cell population NodeBasedCellPopulation<2> node_based_cell_population(mesh, cells); // Set up cell-based simulation OffLatticeSimulation<2> simulator(node_based_cell_population); simulator.SetOutputDirectory("TestOffLatticeSimulationWithNodeBasedCellPopulationSaveAndLoad"); simulator.SetEndTime(0.1); // Create a force law and pass it to the simulation MAKE_PTR(GeneralisedLinearSpringForce<2>, p_linear_force); p_linear_force->SetCutOffLength(1.5); simulator.AddForce(p_linear_force); // Create some boundary conditions and pass them to the simulation c_vector<double,2> normal = zero_vector<double>(2); normal(1) =-1.0; MAKE_PTR_ARGS(PlaneBoundaryCondition<2>, p_bc, (&node_based_cell_population, zero_vector<double>(2), normal)); // y>0 simulator.AddCellPopulationBoundaryCondition(p_bc); // Solve simulator.Solve(); // Save the results CellBasedSimulationArchiver<2, OffLatticeSimulation<2> >::Save(&simulator); }
void TestUpdateCellLocationsAndTopologyWithNoForce() { // Creates nodes and mesh std::vector<Node<2>*> nodes; nodes.push_back(new Node<2>(0, false, 0.0, 0.0)); nodes.push_back(new Node<2>(0, false, 0.0, 0.3)); NodesOnlyMesh<2> mesh; mesh.ConstructNodesWithoutMesh(nodes, 1.5); // Create cells std::vector<CellPtr> cells; CellsGenerator<FixedDurationGenerationBasedCellCycleModel, 2> cells_generator; cells_generator.GenerateBasicRandom(cells, mesh.GetNumNodes()); // Create a node based cell population NodeBasedCellPopulation<2> node_based_cell_population(mesh, cells); node_based_cell_population.SetAbsoluteMovementThreshold(1e-6); // Set up cell-based simulation OffLatticeSimulation<2> simulator(node_based_cell_population); simulator.SetEndTime(0.1); simulator.SetOutputDirectory("TestOffLatticeSimulationUpdateCellLocationsAndTopologyWithNoForce"); simulator.SetupSolve(); simulator.UpdateCellLocationsAndTopology(); if (PetscTools::AmMaster()) { for (AbstractMesh<2,2>::NodeIterator node_iter = mesh.GetNodeIteratorBegin(); node_iter != mesh.GetNodeIteratorEnd(); ++node_iter) { for (unsigned d=0; d<2; d++) { TS_ASSERT_DELTA(node_iter->rGetAppliedForce()[d], 0.0, 1e-15); } } } // Avoid memory leak delete nodes[0]; delete nodes[1]; }
/** * Test that two nodes relax to the equilibrium distance. */ void TestBuskeRelaxationForces() throw (Exception) { EXIT_IF_PARALLEL; // Create a simple mesh with two nodes HoneycombMeshGenerator generator(2, 1, 0, 0.9); TetrahedralMesh<2,2>* p_generating_mesh = generator.GetMesh(); // Convert this to a NodesOnlyMesh NodesOnlyMesh<2> mesh; mesh.ConstructNodesWithoutMesh(*p_generating_mesh, 1.5); // Create cells std::vector<CellPtr> cells; MAKE_PTR(DifferentiatedCellProliferativeType, p_diff_type); CellsGenerator<FixedDurationGenerationBasedCellCycleModel, 2> cells_generator_buske; cells_generator_buske.GenerateBasicRandom(cells, mesh.GetNumNodes(), p_diff_type); // Create a node-based cell population NodeBasedCellPopulation<2> node_based_cell_population_buske(mesh, cells); // Set up cell-based simulation OffLatticeSimulation<2> simulator(node_based_cell_population_buske); simulator.SetOutputDirectory("TestBuskeRelaxation"); simulator.SetEndTime(1.0); // Create all three Buske force laws and pass to the simulation MAKE_PTR(BuskeCompressionForce<2>, p_buske_compression_force); MAKE_PTR(BuskeElasticForce<2>, p_buske_elastic_force); MAKE_PTR(BuskeAdhesiveForce<2>, p_buske_adhesive_force); simulator.AddForce(p_buske_compression_force); simulator.AddForce(p_buske_elastic_force); simulator.AddForce(p_buske_adhesive_force); // Solve simulator.Solve(); // The nodes should be about 0.85 apart as this is the minimum of the sum of the energies. TS_ASSERT_DELTA(simulator.rGetCellPopulation().GetNode(0)->rGetLocation()[0], 0.0155, 1e-4); TS_ASSERT_DELTA(simulator.rGetCellPopulation().GetNode(1)->rGetLocation()[0], 0.8844, 1e-4); }
void TestVertexCryptBoundaryForceForceWithNonVertexCellPopulation() throw (Exception) { // Create a NodeBasedCellPopulation std::vector<Node<2>*> nodes; unsigned num_nodes = 10; for (unsigned i=0; i<num_nodes; i++) { double x = (double)(i); double y = (double)(i); nodes.push_back(new Node<2>(i, true, x, y)); } // Convert this to a NodesOnlyMesh NodesOnlyMesh<2> mesh; mesh.ConstructNodesWithoutMesh(nodes, 1.5); std::vector<CellPtr> cells; CellsGenerator<FixedDurationGenerationBasedCellCycleModel, 2> cells_generator; cells_generator.GenerateBasic(cells, mesh.GetNumNodes()); NodeBasedCellPopulation<2> non_vertex_cell_population(mesh, cells); for (AbstractMesh<2,2>::NodeIterator node_iter = mesh.GetNodeIteratorBegin(); node_iter != mesh.GetNodeIteratorEnd(); ++node_iter) { node_iter->ClearAppliedForce(); } // Test that VertexCryptBoundaryForce throws the correct exception VertexCryptBoundaryForce<2> force(100); TS_ASSERT_THROWS_THIS(force.AddForceContribution(non_vertex_cell_population), "VertexCryptBoundaryForce is to be used with VertexBasedCellPopulations only"); // Avoid memory leak for (unsigned i=0; i<nodes.size(); i++) { delete nodes[i]; } }
void TestCellBasedPdeHandlerOutputParameters() throw(Exception) { EXIT_IF_PARALLEL; std::string output_directory = "TestCellBasedPdeHandlerOutputParameters"; OutputFileHandler output_file_handler(output_directory, false); // 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 output methods TS_ASSERT_EQUALS(pde_handler.GetIdentifier(), "CellBasedPdeHandler-2"); out_stream pde_handler_parameter_file = output_file_handler.OpenOutputFile("CellBasedPdeHandler.parameters"); pde_handler.OutputParameters(pde_handler_parameter_file); pde_handler_parameter_file->close(); { // Compare the generated file in test output with a reference copy in the source code. FileFinder generated = output_file_handler.FindFile("CellBasedPdeHandler.parameters"); FileFinder reference("cell_based/test/data/TestCellBasedPdeHandler/CellBasedPdeHandler.parameters", RelativeTo::ChasteSourceRoot); FileComparison comparer(generated, reference); TS_ASSERT(comparer.CompareFiles()); } }
/** * Create a simulation of a NodeBasedCellPopulation to test movement threshold. */ void TestMovementThreshold() throw (Exception) { EXIT_IF_PARALLEL; // This test doesn't work in parallel because only one process will throw. // Creates nodes and mesh std::vector<Node<2>*> nodes; nodes.push_back(new Node<2>(0, false, 0.0, 0.0)); nodes.push_back(new Node<2>(0, false, 0.0, 0.3)); NodesOnlyMesh<2> mesh; mesh.ConstructNodesWithoutMesh(nodes, 1.5); // Create cells std::vector<CellPtr> cells; CellsGenerator<FixedDurationGenerationBasedCellCycleModel, 2> cells_generator; cells_generator.GenerateBasicRandom(cells, mesh.GetNumNodes()); // Create a node based cell population NodeBasedCellPopulation<2> node_based_cell_population(mesh, cells); node_based_cell_population.SetAbsoluteMovementThreshold(1e-6); // Set up cell-based simulation OffLatticeSimulation<2> simulator(node_based_cell_population); simulator.SetEndTime(0.1); simulator.SetOutputDirectory("TestOffLatticeSimulationWithNodeBasedCellPopulationThreshold"); // Create a force law and pass it to the simulation MAKE_PTR(GeneralisedLinearSpringForce<2>, p_linear_force); p_linear_force->SetCutOffLength(1.5); simulator.AddForce(p_linear_force); // Solve TS_ASSERT_THROWS_CONTAINS(simulator.Solve(), "which is more than the AbsoluteMovementThreshold:"); // Avoid memory leak delete nodes[0]; delete nodes[1]; }
void TestOnLatticeSimulationExceptions() { EXIT_IF_PARALLEL; // Create a simple tetrahedral mesh HoneycombMeshGenerator generator(3, 3, 0); TetrahedralMesh<2,2>* p_generating_mesh = generator.GetMesh(); // Convert this to a NodesOnlyMesh NodesOnlyMesh<2> mesh; mesh.ConstructNodesWithoutMesh(*p_generating_mesh, 1.5); // Create cells std::vector<CellPtr> cells; CellsGenerator<FixedDurationGenerationBasedCellCycleModel, 2> cells_generator; cells_generator.GenerateBasicRandom(cells, mesh.GetNumNodes()); // Create a node-based cell population NodeBasedCellPopulation<2> node_based_cell_population(mesh, cells); TS_ASSERT_THROWS_THIS(OnLatticeSimulation<2> simulator(node_based_cell_population), "OnLatticeSimulations require a subclass of AbstractOnLatticeCellPopulation."); }
/* * === Using the modifier in a cell-based simulation === * * We conclude with a brief test demonstrating how {{{CellHeightTrackingModifier}}} can be used * in a cell-based simulation. */ void TestOffLatticeSimulationWithCellHeightTrackingModifier() { /* * In this case, we choose to create a small {{{NodeBasedCellPopulation}}} comprising 25 cells. * We choose a cut-off for mechanical interactions between cells of 1.5 units and add a * simple {{{ReplusionForce}}} to the simulation. We use a {{{UniformCellCycleModel}}} * to implement some random proliferation in the simulation. */ HoneycombMeshGenerator generator(2, 2, 0); TetrahedralMesh<2,2>* p_generating_mesh = generator.GetMesh(); NodesOnlyMesh<2> mesh; mesh.ConstructNodesWithoutMesh(*p_generating_mesh, 1.5); std::vector<CellPtr> cells; MAKE_PTR(TransitCellProliferativeType, p_transit_type); CellsGenerator<UniformCellCycleModel, 2> cells_generator; cells_generator.GenerateBasicRandom(cells, mesh.GetNumNodes(), p_transit_type); NodeBasedCellPopulation<2> cell_population(mesh, cells); OffLatticeSimulation<2> simulator(cell_population); simulator.SetOutputDirectory("TestOffLatticeSimulationWithCellHeightTrackingModifier"); simulator.SetSamplingTimestepMultiple(12); simulator.SetEndTime(20.0); MAKE_PTR(RepulsionForce<2>, p_force); simulator.AddForce(p_force); /* * Finally, we add a {{{CellHeightTrackingModifier}}} to the simulation. */ MAKE_PTR(CellHeightTrackingModifier, p_modifier); simulator.AddSimulationModifier(p_modifier); /* To run the simulation, we call {{{Solve()}}}. */ simulator.Solve(); }
/** * Create a simulation of a NodeBasedCellPopulation with all Buske forces. * Test that no exceptions are thrown. */ void TestAllBuskeForces() throw (Exception) { EXIT_IF_PARALLEL; // HoneycombMeshGenerator doesn't work in parallel // Create a simple mesh HoneycombMeshGenerator generator(5, 5, 0); TetrahedralMesh<2,2>* p_generating_mesh = generator.GetMesh(); // Convert this to a NodesOnlyMesh NodesOnlyMesh<2> mesh; mesh.ConstructNodesWithoutMesh(*p_generating_mesh, 1.5); // Create cells std::vector<CellPtr> cells; MAKE_PTR(TransitCellProliferativeType, p_transit_type); CellsGenerator<FixedDurationGenerationBasedCellCycleModel, 2> cells_generator; cells_generator.GenerateBasicRandom(cells, mesh.GetNumNodes(), p_transit_type); // Create a node-based cell population NodeBasedCellPopulation<2> node_based_cell_population(mesh, cells); // Set up cell-based simulation OffLatticeSimulation<2> simulator(node_based_cell_population); simulator.SetOutputDirectory("TestAllBuskeForces"); simulator.SetEndTime(5.0); // Create a force law and pass it to the simulation MAKE_PTR(BuskeCompressionForce<2>, p_buske_compression_force); MAKE_PTR(BuskeElasticForce<2>, p_buske_elastic_force); MAKE_PTR(BuskeAdhesiveForce<2>, p_buske_adhesive_force); p_buske_compression_force->SetCompressionEnergyParameter(0.01); simulator.AddForce(p_buske_compression_force); simulator.AddForce(p_buske_elastic_force); simulator.AddForce(p_buske_adhesive_force); simulator.Solve(); }
void setUp() { AbstractCellBasedTestSuite::setUp(); std::vector<Node<3>* > nodes; for (unsigned i=0; i<PetscTools::GetNumProcs(); i++) { nodes.push_back(new Node<3>(0, false, 0.0, 0.0, 0.5+(double)i)); } mpNodesOnlyMesh = new NodesOnlyMesh<3>; mpNodesOnlyMesh->ConstructNodesWithoutMesh(nodes, 1.0); std::vector<CellPtr> cells; CellsGenerator<FixedDurationGenerationBasedCellCycleModel, 3> cells_generator; cells_generator.GenerateBasic(cells, mpNodesOnlyMesh->GetNumNodes()); mpNodeBasedCellPopulation = new NodeBasedCellPopulation<3>(*mpNodesOnlyMesh, cells); for (unsigned i=0; i<nodes.size(); i++) { delete nodes[i]; } }
/* * === Using the cell property in a cell-based simulation === * * We conclude with a brief test demonstrating how {{{MotileCellProperty}}} can be used * in a cell-based simulation. */ void TestOffLatticeSimulationWithMotileCellProperty() throw(Exception) { /* Note that HoneycombMeshGenerator, used in this test, is not * yet implemented in parallel. */ /* We use the {{{HoneycombMeshGenerator}}} to create a honeycomb mesh covering a * circular domain of given radius, and use this to generate a {{{NodesOnlyMesh}}} * as follows. */ HoneycombMeshGenerator generator(10, 10); MutableMesh<2,2>* p_generating_mesh = generator.GetCircularMesh(5); NodesOnlyMesh<2> mesh; /* We construct the mesh using the generating mesh and a cut-off 1.5 which defines the * connectivity in the mesh. */ mesh.ConstructNodesWithoutMesh(*p_generating_mesh, 1.5); /* We now create a shared pointer to our new property, as follows. */ MAKE_PTR(MotileCellProperty, p_motile); /* * Also create a shared pointer to a cell label so we can visualize the * different cell types. Note that this is also a {{{CellProperty}}}. */ MAKE_PTR(CellLabel, p_label); /* Next, we create some cells. We don't use a Generator as we want to give some cells the new cell property, therefore * we create the cells in a loop, as follows.*/ MAKE_PTR(WildTypeCellMutationState, p_state); MAKE_PTR(DifferentiatedCellProliferativeType, p_diff_type); std::vector<CellPtr> cells; for (unsigned i=0; i<mesh.GetNumNodes(); i++) { /* For each node we create a cell with our cell-cycle model and the wild-type cell mutation state. * We then add the property {{{MotileCellProperty}}} to a random selection of the cells, as follows. */ FixedDurationGenerationBasedCellCycleModel* p_model = new FixedDurationGenerationBasedCellCycleModel(); CellPropertyCollection collection; if (RandomNumberGenerator::Instance()->ranf() < 0.2) { collection.AddProperty(p_motile); collection.AddProperty(p_label); } CellPtr p_cell(new Cell(p_state, p_model, false, collection)); p_cell->SetCellProliferativeType(p_diff_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_model->GetStemCellG1Duration() + p_model->GetSG2MDuration()); /* Finally, we 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. The constructor * takes in the mesh and the cells vector. */ NodeBasedCellPopulation<2> cell_population(mesh, cells); /* In order to visualize labelled cells we need to use the following command.*/ cell_population.AddCellPopulationCountWriter<CellMutationStatesCountWriter>(); /* We then pass in the cell population into an {{{OffLatticeSimulation}}}, * and set the output directory, output multiple, and end time. */ OffLatticeSimulation<2> simulator(cell_population); simulator.SetOutputDirectory("TestOffLatticeSimulationWithMotileCellProperty"); simulator.SetSamplingTimestepMultiple(12); simulator.SetEndTime(10.0); /* We create a force law and pass it to the {{{OffLatticeSimulation}}}. */ MAKE_PTR(GeneralisedLinearSpringForce<2>, p_linear_force); p_linear_force->SetCutOffLength(1.5); simulator.AddForce(p_linear_force); /* Now create a {{{MotlieForce}}} and pass it to the {{{OffLatticeSimulation}}}. */ MAKE_PTR(MyMotiveForce, p_motive_force); simulator.AddForce(p_motive_force); /* To run the simulation, we call {{{Solve()}}}. */ simulator.Solve(); }
void TestWritingToFile() throw(Exception) { EXIT_IF_PARALLEL; std::string output_directory = "TestCellBasedPdeHandlerWritingToFile"; // Create a cell population HoneycombMeshGenerator generator(4, 4, 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()); TS_ASSERT_EQUALS(cells.size(), mesh.GetNumNodes()); NodeBasedCellPopulation<2> cell_population(mesh, cells); cell_population.SetDataOnAllCells("variable", 1.0); // Create a PDE handler object using this cell population CellBasedPdeHandler<2> pde_handler(&cell_population); TS_ASSERT_THROWS_THIS(pde_handler.OpenResultsFiles(output_directory), "Trying to solve a PDE on a cell population that doesn't have a mesh. Try calling UseCoarsePdeMesh()."); // Use a coarse PDE mesh since we are using a node-based cell population AveragedSourcePde<2> pde(cell_population, -0.1); ConstBoundaryCondition<2> bc(1.0); PdeAndBoundaryConditions<2> pde_and_bc(&pde, &bc, false); pde_and_bc.SetDependentVariableName("variable"); pde_handler.AddPdeAndBc(&pde_and_bc); ChastePoint<2> lower(0.0, 0.0); ChastePoint<2> upper(9.0, 9.0); ChasteCuboid<2> cuboid(lower, upper); pde_handler.UseCoarsePdeMesh(3.0, cuboid, true); // For coverage, call SetWriteAverageRadialPdeSolution() prior to output pde_handler.SetWriteAverageRadialPdeSolution("variable", 5, true); // Test that output files are opened correctly pde_handler.OpenResultsFiles(output_directory); FileFinder file_finder(output_directory + "/results.vizcoarsepdesolution", RelativeTo::ChasteTestOutput); TS_ASSERT(file_finder.Exists()); TS_ASSERT(file_finder.IsFile()); FileFinder file_finder2(output_directory + "/radial_dist.dat", RelativeTo::ChasteTestOutput); TS_ASSERT(file_finder2.Exists()); TS_ASSERT(file_finder2.IsFile()); TS_ASSERT_THROWS_NOTHING(pde_handler.CloseResultsFiles()); // For coverage, also test that output files are opened correctly when not using a coarse PDE mesh HoneycombMeshGenerator generator2(5, 5, 0); MutableMesh<2,2>* p_mesh2 = generator2.GetMesh(); std::vector<CellPtr> cells2; CellsGenerator<FixedDurationGenerationBasedCellCycleModel, 2> cells_generator2; cells_generator2.GenerateBasic(cells2, p_mesh2->GetNumNodes()); MeshBasedCellPopulation<2> cell_population2(*p_mesh2, cells2); cell_population2.SetDataOnAllCells("another variable", 1.0); CellBasedPdeHandler<2> pde_handler2(&cell_population2); pde_handler2.OpenResultsFiles(output_directory); FileFinder file_finder3(output_directory + "/results.vizpdesolution", RelativeTo::ChasteTestOutput); TS_ASSERT(file_finder3.Exists()); TS_ASSERT(file_finder3.IsFile()); pde_handler2.CloseResultsFiles(); }
void TestUseCoarsePdeMesh() throw(Exception) { EXIT_IF_PARALLEL; // Create a cell population HoneycombMeshGenerator generator(4, 4, 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 UseCoarsePdeMesh() throws an exception if no PDEs are specified ChastePoint<2> lower(0.0, 0.0); ChastePoint<2> upper(9.0, 9.0); ChasteCuboid<2> cuboid(lower, upper); TS_ASSERT_THROWS_THIS(pde_handler.UseCoarsePdeMesh(3.0, cuboid, true), "mPdeAndBcCollection should be populated prior to calling UseCoarsePdeMesh()."); // Set up PDE and pass to handler AveragedSourcePde<2> pde(cell_population, -0.1); ConstBoundaryCondition<2> bc(1.0); PdeAndBoundaryConditions<2> pde_and_bc(&pde, &bc, false); pde_handler.AddPdeAndBc(&pde_and_bc); // Test UseCoarsePdeMesh() again pde_handler.UseCoarsePdeMesh(3.0, cuboid, true); // Test that the coarse mesh has the correct number of nodes and elements TetrahedralMesh<2,2>* p_coarse_mesh = pde_handler.GetCoarsePdeMesh(); TS_ASSERT_EQUALS(p_coarse_mesh->GetNumNodes(), 16u); TS_ASSERT_EQUALS(p_coarse_mesh->GetNumElements(), 18u); // Find centre of cell population c_vector<double,2> centre_of_cell_population = cell_population.GetCentroidOfCellPopulation(); // Find centre of coarse PDE mesh c_vector<double,2> centre_of_coarse_pde_mesh = zero_vector<double>(2); for (unsigned i=0; i<p_coarse_mesh->GetNumNodes(); i++) { centre_of_coarse_pde_mesh += p_coarse_mesh->GetNode(i)->rGetLocation(); } centre_of_coarse_pde_mesh /= p_coarse_mesh->GetNumNodes(); // Test that the two centres match c_vector<double,2> centre_difference = centre_of_cell_population - centre_of_coarse_pde_mesh; TS_ASSERT_DELTA(norm_2(centre_difference), 0.0, 1e-4); // Test that UseCoarsePdeMesh() throws an exception if the wrong type of PDE is specified SimpleUniformSourcePde<2> pde2(-0.1); ConstBoundaryCondition<2> bc2(1.0); PdeAndBoundaryConditions<2> pde_and_bc2(&pde2, &bc2, false); pde_and_bc2.SetDependentVariableName("second variable"); pde_handler.AddPdeAndBc(&pde_and_bc2); TS_ASSERT_THROWS_THIS(pde_handler.UseCoarsePdeMesh(3.0, cuboid, true), "UseCoarsePdeMesh() should only be called if averaged-source PDEs are specified."); // Now test the 1D case std::vector<Node<1>*> nodes_1d; nodes_1d.push_back(new Node<1>(0, true, 0.0)); NodesOnlyMesh<1> mesh_1d; mesh_1d.ConstructNodesWithoutMesh(nodes_1d, 1.5); std::vector<CellPtr> cells_1d; CellsGenerator<FixedDurationGenerationBasedCellCycleModel, 1> cells_generator_1d; cells_generator_1d.GenerateBasic(cells_1d, mesh_1d.GetNumNodes()); NodeBasedCellPopulation<1> cell_population_1d(mesh_1d, cells_1d); CellBasedPdeHandler<1> pde_handler_1d(&cell_population_1d); AveragedSourcePde<1> pde_1d(cell_population_1d, -0.1); ConstBoundaryCondition<1> bc_1d(1.0); PdeAndBoundaryConditions<1> pde_and_bc_1d(&pde_1d, &bc_1d, false); pde_handler_1d.AddPdeAndBc(&pde_and_bc_1d); ChastePoint<1> lower1(0.0); ChastePoint<1> upper1(9.0); ChasteCuboid<1> cuboid1(lower1, upper1); pde_handler_1d.UseCoarsePdeMesh(3.0, cuboid1, true); // Test that the coarse mesh has the correct number of nodes and elements TetrahedralMesh<1,1>* p_coarse_mesh_1d = pde_handler_1d.GetCoarsePdeMesh(); TS_ASSERT_EQUALS(p_coarse_mesh_1d->GetNumNodes(), 4u); TS_ASSERT_EQUALS(p_coarse_mesh_1d->GetNumElements(), 3u); // Now test the 3D case std::vector<Node<3>*> nodes_3d; nodes_3d.push_back(new Node<3>(0, true, 0.0)); NodesOnlyMesh<3> mesh_3d; mesh_3d.ConstructNodesWithoutMesh(nodes_3d, 1.5); std::vector<CellPtr> cells_3d; CellsGenerator<FixedDurationGenerationBasedCellCycleModel, 3> cells_generator_3d; cells_generator_3d.GenerateBasic(cells_3d, mesh_3d.GetNumNodes()); NodeBasedCellPopulation<3> cell_population_3d(mesh_3d, cells_3d); CellBasedPdeHandler<3> pde_handler_3d(&cell_population_3d); AveragedSourcePde<3> pde_3d(cell_population_3d, -0.1); ConstBoundaryCondition<3> bc_3d(1.0); PdeAndBoundaryConditions<3> pde_and_bc_3d(&pde_3d, &bc_3d, false); pde_handler_3d.AddPdeAndBc(&pde_and_bc_3d); ChastePoint<3> lower3(0.0, 0.0, 0.0); ChastePoint<3> upper3(9.0, 9.0, 9.0); ChasteCuboid<3> cuboid3(lower3, upper3); pde_handler_3d.UseCoarsePdeMesh(3.0, cuboid3, true); // Test that the coarse mesh has the correct number of nodes and elements TetrahedralMesh<3,3>* p_coarse_mesh_3d = pde_handler_3d.GetCoarsePdeMesh(); TS_ASSERT_EQUALS(p_coarse_mesh_3d->GetNumNodes(), 64u); TS_ASSERT_EQUALS(p_coarse_mesh_3d->GetNumElements(), 162u); // Avoid memory leak for (unsigned i=0; i<nodes_1d.size(); i++) { delete nodes_1d[i]; delete nodes_3d[i]; } }
void TestArchivingOfPdeHandlerOnCuboid() throw(Exception) { EXIT_IF_PARALLEL; FileFinder archive_dir("archive", RelativeTo::ChasteTestOutput); std::string archive_file = "CellBasedPdeHandlerOnCuboid.arch"; ArchiveLocationInfo::SetMeshFilename("pde_handler_mesh"); { // 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 CellBasedPdeHandlerOnCuboid<2>* const p_pde_handler = new CellBasedPdeHandlerOnCuboid<2>(&cell_population); // Set member variables for testing p_pde_handler->SetWriteAverageRadialPdeSolution("averaged quantity", 5, true); p_pde_handler->SetImposeBcsOnCoarseBoundary(false); // Set up PDE and pass to handler AveragedSourcePde<2> pde(cell_population, -0.1); ConstBoundaryCondition<2> bc(1.0); PdeAndBoundaryConditions<2> pde_and_bc(&pde, &bc, false); pde_and_bc.SetDependentVariableName("averaged quantity"); p_pde_handler->AddPdeAndBc(&pde_and_bc); // Test UseCoarsePdeMesh() again ChastePoint<2> lower(0.0, 0.0); ChastePoint<2> upper(9.0, 9.0); ChasteCuboid<2> cuboid(lower, upper); p_pde_handler->UseCoarsePdeMesh(3.0, cuboid, true); // Create an output archive ArchiveOpener<boost::archive::text_oarchive, std::ofstream> arch_opener(archive_dir, archive_file); boost::archive::text_oarchive* p_arch = arch_opener.GetCommonArchive(); // Archive object SimulationTime* p_simulation_time = SimulationTime::Instance(); p_simulation_time->SetEndTimeAndNumberOfTimeSteps(1.0, 11); (*p_arch) << static_cast<const SimulationTime&>(*p_simulation_time); (*p_arch) << p_pde_handler; // Tidy up SimulationTime::Destroy(); delete p_pde_handler; } { CellBasedPdeHandlerOnCuboid<2>* p_pde_handler; // Create an input archive ArchiveOpener<boost::archive::text_iarchive, std::ifstream> arch_opener(archive_dir, archive_file); boost::archive::text_iarchive* p_arch = arch_opener.GetCommonArchive(); // Restore object from the archive SimulationTime* p_simulation_time = SimulationTime::Instance(); (*p_arch) >> *p_simulation_time; (*p_arch) >> p_pde_handler; // Test that the member variables were archived correctly TS_ASSERT_EQUALS(p_pde_handler->mpCellPopulation->GetNumRealCells(), 4u); TS_ASSERT_EQUALS(p_pde_handler->GetWriteAverageRadialPdeSolution(), true); TS_ASSERT_EQUALS(p_pde_handler->GetWriteDailyAverageRadialPdeSolution(), true); TS_ASSERT_EQUALS(p_pde_handler->GetImposeBcsOnCoarseBoundary(), false); TS_ASSERT_EQUALS(p_pde_handler->GetNumRadialIntervals(), 5u); TS_ASSERT_EQUALS(p_pde_handler->mAverageRadialSolutionVariableName, "averaged quantity"); ///\todo we currently do not archive mpCoarsePdeMesh - consider doing this (#1891) TS_ASSERT(p_pde_handler->GetCoarsePdeMesh() == NULL); TS_ASSERT_EQUALS(p_pde_handler->mPdeAndBcCollection.size(), 1u); TS_ASSERT_EQUALS(p_pde_handler->mPdeAndBcCollection[0]->IsNeumannBoundaryCondition(), false); // Tidy up delete p_pde_handler->mpCellPopulation; delete p_pde_handler; } }
void TestSetMethods() 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 set and get methods pde_handler.SetWriteAverageRadialPdeSolution("averaged quantity"); TS_ASSERT_EQUALS(pde_handler.GetWriteAverageRadialPdeSolution(), true); TS_ASSERT_EQUALS(pde_handler.GetWriteDailyAverageRadialPdeSolution(), false); TS_ASSERT_EQUALS(pde_handler.GetNumRadialIntervals(), 10u); pde_handler.SetWriteAverageRadialPdeSolution("averaged quantity", 5, true); TS_ASSERT_EQUALS(pde_handler.GetWriteAverageRadialPdeSolution(), true); TS_ASSERT_EQUALS(pde_handler.GetWriteDailyAverageRadialPdeSolution(), true); TS_ASSERT_EQUALS(pde_handler.GetNumRadialIntervals(), 5u); pde_handler.SetImposeBcsOnCoarseBoundary(false); TS_ASSERT_EQUALS(pde_handler.GetImposeBcsOnCoarseBoundary(), false); // Test AddPdeAndBc() SimpleUniformSourcePde<2> pde(-0.1); ConstBoundaryCondition<2> bc(1.0); PdeAndBoundaryConditions<2> pde_and_bc(&pde, &bc, false); pde_and_bc.SetDependentVariableName("averaged quantity"); unsigned num_nodes = mesh.GetNumNodes(); std::vector<double> data(num_nodes); for (unsigned i=0; i<num_nodes; i++) { data[i] = i + 0.45; } Vec vector = PetscTools::CreateVec(data); pde_and_bc.SetSolution(vector); pde_handler.AddPdeAndBc(&pde_and_bc); TS_ASSERT_EQUALS(pde_handler.mPdeAndBcCollection[0]->IsNeumannBoundaryCondition(), false); TS_ASSERT_EQUALS(pde_handler.mPdeAndBcCollection[0]->HasAveragedSourcePde(), false); ReplicatableVector solution(pde_handler.GetPdeSolution()); TS_ASSERT_EQUALS(solution.GetSize(), num_nodes); for (unsigned i=0; i<num_nodes; i++) { TS_ASSERT_DELTA(solution[i], i + 0.45, 1e-4); } }