void TestNodeBasedSimulationWithContactInhibition() { EXIT_IF_PARALLEL; // HoneycombMeshGenerator does not work in parallel // Create a simple 2D NodeBasedCellPopulation HoneycombMeshGenerator generator(5, 5, 0); TetrahedralMesh<2,2>* p_generating_mesh = generator.GetMesh(); NodesOnlyMesh<2> mesh; mesh.ConstructNodesWithoutMesh(*p_generating_mesh, 1.5); MAKE_PTR(WildTypeCellMutationState, p_state); MAKE_PTR(TransitCellProliferativeType, p_transit_type); std::vector<CellPtr> cells; for (unsigned i=0; i<mesh.GetNumNodes(); i++) { ContactInhibitionCellCycleModel* p_cycle_model = new ContactInhibitionCellCycleModel(); p_cycle_model->SetDimension(2); p_cycle_model->SetBirthTime(-10.0); p_cycle_model->SetQuiescentVolumeFraction(0.9); p_cycle_model->SetEquilibriumVolume(0.7854); //pi *(0.5)^2 p_cycle_model->SetStemCellG1Duration(0.1); p_cycle_model->SetTransitCellG1Duration(0.1); CellPtr p_cell(new Cell(p_state, p_cycle_model)); p_cell->SetCellProliferativeType(p_transit_type); cells.push_back(p_cell); } NodeBasedCellPopulation<2> cell_population(mesh, cells); cell_population.AddPopulationWriter<CellMutationStatesCountWriter>(); cell_population.AddCellWriter<CellVolumesWriter>(); cell_population.AddPopulationWriter<NodeVelocityWriter>(); // Create a simulation OffLatticeSimulation<2> simulator(cell_population); simulator.SetOutputDirectory("TestNodeBasedSimulationWithVolumeTracked"); TS_ASSERT_EQUALS(simulator.GetDt(), 1.0/120.0); // Default value for off-lattice simulations simulator.SetEndTime(simulator.GetDt()/2.0); // Create a volume-tracking modifier and pass it to the simulation MAKE_PTR(VolumeTrackingModifier<2>, p_modifier); simulator.AddSimulationModifier(p_modifier); // Create a force law and pass it to the simulation MAKE_PTR(GeneralisedLinearSpringForce<2>, p_force); p_force->SetCutOffLength(1.5); simulator.AddForce(p_force); // Run simulation simulator.Solve(); // Test that the node velocities file exists OutputFileHandler output_file_handler("TestNodeBasedSimulationWithVolumeTracked", false); FileFinder generated = output_file_handler.FindFile("results_from_time_0/nodevelocities.dat"); TS_ASSERT(generated.Exists()); // Test that the volumes of the cells are correct in CellData at the first timestep for (AbstractCellPopulation<2>::Iterator cell_iter = cell_population.Begin(); cell_iter != cell_population.End(); ++cell_iter) { TS_ASSERT_DELTA(cell_population.GetVolumeOfCell(*cell_iter), cell_iter->GetCellData()->GetItem("volume"), 1e-4); } simulator.SetEndTime(2.0); // Run simulation simulator.Solve(); // Test that the volumes of the cells are correct in CellData at the end time for (AbstractCellPopulation<2>::Iterator cell_iter = cell_population.Begin(); cell_iter != cell_population.End(); ++cell_iter) { TS_ASSERT_DELTA(cell_population.GetVolumeOfCell(*cell_iter), cell_iter->GetCellData()->GetItem("volume"), 1e-4); } // Check that the correct number of cells are labelled (i.e. experiencing contact inhibition) TS_ASSERT_EQUALS(cell_population.GetCellPropertyRegistry()->Get<CellLabel>()->GetCellCount(), 2u); }
/** * Create a simulation of a NodeBasedCellPopulation with a NodeBasedCellPopulationMechanicsSystem * and a CellKiller. Test that no exceptions are thrown, and write the results to file. */ void TestCellDeath() throw (Exception) { EXIT_IF_PARALLEL; // HoneycombMeshGenereator does not work in parallel. // Create a simple mesh int num_cells_depth = 5; int num_cells_width = 5; HoneycombMeshGenerator generator(num_cells_width, num_cells_depth, 0); TetrahedralMesh<2,2>* p_generating_mesh = generator.GetMesh(); // Convert this to a NodesOnlyMesh NodesOnlyMesh<2> mesh; mesh.ConstructNodesWithoutMesh(*p_generating_mesh, 1.5); // Create cells std::vector<CellPtr> cells; CellsGenerator<FixedDurationGenerationBasedCellCycleModel, 2> cells_generator; cells_generator.GenerateBasicRandom(cells, mesh.GetNumNodes()); // Create a node based cell population NodeBasedCellPopulation<2> node_based_cell_population(mesh, cells); // Set up cell-based simulation OffLatticeSimulation<2> simulator(node_based_cell_population); simulator.SetOutputDirectory("TestOffLatticeSimulationWithNodeBasedCellPopulationCellPtrDeath"); simulator.SetEndTime(0.5); // Create a force law and pass it to the simulation MAKE_PTR(GeneralisedLinearSpringForce<2>, p_linear_force); p_linear_force->SetCutOffLength(1.5); simulator.AddForce(p_linear_force); // Add cell killer MAKE_PTR_ARGS(RandomCellKiller<2>, p_killer, (&node_based_cell_population, 0.997877574)); simulator.AddCellKiller(p_killer); // Solve simulator.Solve(); // Check some results TS_ASSERT_EQUALS(simulator.GetNumBirths(), 0u); TS_ASSERT_EQUALS(simulator.GetNumDeaths(), 20u); std::vector<double> node_8_location = simulator.GetNodeLocation(8); TS_ASSERT_DELTA(node_8_location[0], 3.4729, 1e-4); TS_ASSERT_DELTA(node_8_location[1], 1.0051, 1e-4); std::vector<double> node_3_location = simulator.GetNodeLocation(3); TS_ASSERT_DELTA(node_3_location[0], 2.9895, 1e-4); TS_ASSERT_DELTA(node_3_location[1], 0.3105, 1e-4); // Test the results are written correctly FileFinder generated_type_file("TestOffLatticeSimulationWithNodeBasedCellPopulationCellPtrDeath/results_from_time_0/results.vizcelltypes", RelativeTo::ChasteTestOutput); FileFinder generated_node_file("TestOffLatticeSimulationWithNodeBasedCellPopulationCellPtrDeath/results_from_time_0/results.viznodes", RelativeTo::ChasteTestOutput); FileFinder reference_type_file("cell_based/test/data/TestOffLatticeSimulationWithNodeBasedCellPopulationCellPtrDeath/results.vizcelltypes",RelativeTo::ChasteSourceRoot); FileFinder reference_node_file("cell_based/test/data/TestOffLatticeSimulationWithNodeBasedCellPopulationCellPtrDeath/results.viznodes",RelativeTo::ChasteSourceRoot); FileComparison type_files(generated_type_file,reference_type_file); FileComparison node_files(generated_node_file,reference_node_file); }
void TestOffLatticeSimulationWithMotileCellPropertyAndWriters() throw(Exception) { /* * We begin by creating a {{{NodeBasedCellPopulation}}}, just as in [wiki:UserTutorials/CreatingAndUsingANewCellProperty]. * We add the {{{MotileCellProperty}}} to a random selection of cells. * We also add the {{{CellLabel}}} to these cells so that we can easily visualize the different cell types. */ EXIT_IF_PARALLEL; HoneycombMeshGenerator generator(10, 10); MutableMesh<2,2>* p_generating_mesh = generator.GetCircularMesh(5); NodesOnlyMesh<2> mesh; mesh.ConstructNodesWithoutMesh(*p_generating_mesh, 1.5); MAKE_PTR(MotileCellProperty, p_motile); MAKE_PTR(CellLabel, p_label); MAKE_PTR(WildTypeCellMutationState, p_state); MAKE_PTR(DifferentiatedCellProliferativeType, p_diff_type); std::vector<CellPtr> cells; for (unsigned i=0; i<mesh.GetNumNodes(); i++) { 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); double birth_time = - RandomNumberGenerator::Instance()->ranf() * (p_model->GetStemCellG1Duration() + p_model->GetSG2MDuration()); p_cell->SetBirthTime(birth_time); cells.push_back(p_cell); } NodeBasedCellPopulation<2> cell_population(mesh, cells); /* In order to write cell motility data using our writer, we must add it to the list of writers * used by the population. This is achieved using the {{{AddCellWriter()}}} method, * which is templated. */ cell_population.AddCellWriter<CellMotilityWriter>(); /* 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("TestOffLatticeSimulationWithMotileCellPropertyAndWriters"); simulator.SetSamplingTimestepMultiple(12); simulator.SetEndTime(10.0); /* Next we create a force law and pass it to the {{{OffLatticeSimulation}}}, and call {{{Solve()}}} to run the simulation. */ MAKE_PTR(GeneralisedLinearSpringForce<2>, p_linear_force); p_linear_force->SetCutOffLength(1.5); simulator.AddForce(p_linear_force); simulator.Solve(); }
/** * Create a simulation of a NodeBasedCellPopulation with different cell radii. */ void TestSimpleMonolayerWithDifferentRadii() throw (Exception) { // 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>(1, false, 1.0, 0.0)); NodesOnlyMesh<2> mesh; mesh.ConstructNodesWithoutMesh(nodes, 5.0); // Large cut off as larger cells. // Modify the radii of the cells if (PetscTools::AmMaster()) { mesh.GetNode(0)->SetRadius(1.0); mesh.GetNode(PetscTools::GetNumProcs())->SetRadius(2.0); } // 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); node_based_cell_population.AddCellWriter<CellVolumesWriter>(); node_based_cell_population.Update(); // Set up cell-based simulation OffLatticeSimulation<2> simulator(node_based_cell_population); simulator.SetOutputDirectory("TestOffLatticeSimulationWithNodeBasedCellPopulationAndDifferentRadi"); simulator.SetSamplingTimestepMultiple(12); simulator.SetEndTime(12.0); // Create a force law and pass it to the simulation MAKE_PTR(GeneralisedLinearSpringForce<2>, p_linear_force); p_linear_force->SetCutOffLength(5.0); // Different as bigger cells simulator.AddForce(p_linear_force); simulator.Solve(); // Check that the radii of all the cells are correct // (cell 0 divided into 0 and 3 and cell 1 divided into 1 and 2) if (PetscTools::AmMaster()) { TS_ASSERT_DELTA(mesh.GetNode(0)->GetRadius(), 1.0, 1e-6); TS_ASSERT_DELTA(mesh.GetNode(PetscTools::GetNumProcs())->GetRadius(), 2.0, 1e-6); TS_ASSERT_DELTA(mesh.GetNode(2*PetscTools::GetNumProcs())->GetRadius(), 2.0, 1e-6); TS_ASSERT_DELTA(mesh.GetNode(3*PetscTools::GetNumProcs())->GetRadius(), 1.0, 1e-6); // Check the separation of some node pairs TS_ASSERT_DELTA(norm_2(simulator.rGetCellPopulation().GetNode(0)->rGetLocation()-simulator.rGetCellPopulation().GetNode(PetscTools::GetNumProcs())->rGetLocation()), 2.9710, 1e-1); TS_ASSERT_DELTA(norm_2(simulator.rGetCellPopulation().GetNode(0)->rGetLocation()-simulator.rGetCellPopulation().GetNode(2*PetscTools::GetNumProcs())->rGetLocation()), 4.7067, 1e-1); TS_ASSERT_DELTA(norm_2(simulator.rGetCellPopulation().GetNode(0)->rGetLocation()-simulator.rGetCellPopulation().GetNode(3*PetscTools::GetNumProcs())->rGetLocation()), 2.0, 1e-1); } // Clean up memory for (unsigned i=0; i<nodes.size(); i++) { delete nodes[i]; } }
/** * Create a simulation of a NodeBasedCellPopulation with variable cell radii. */ void TestSimpleMonolayerWithVariableRadii() throw (Exception) { // 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>(1, false, 1.0, 0.0)); NodesOnlyMesh<2> mesh; mesh.ConstructNodesWithoutMesh(nodes, 5.0); // Larger cut off as bigger cells. // 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); // Store the radius of the cells in Cell Data if (PetscTools::AmMaster()) { cells[0]->GetCellData()->SetItem("Radius", 1.0); cells[1]->GetCellData()->SetItem("Radius", 2.0); } // Create a node-based cell population NodeBasedCellPopulation<2> node_based_cell_population(mesh, cells); node_based_cell_population.SetUseVariableRadii(true); node_based_cell_population.AddCellWriter<CellVolumesWriter>(); node_based_cell_population.Update(); // Set up cell-based simulation OffLatticeSimulation<2> simulator(node_based_cell_population); simulator.SetOutputDirectory("TestOffLatticeSimulationWithNodeBasedCellPopulationAndVariableRadii"); simulator.SetSamplingTimestepMultiple(12); simulator.SetEndTime(10.0); // Create a force law and pass it to the simulation MAKE_PTR(GeneralisedLinearSpringForce<2>, p_linear_force); p_linear_force->SetCutOffLength(5.0); // Different as bigger cells simulator.AddForce(p_linear_force); simulator.Solve(); // Check the radii of all the cells are correct; cell 0 divided into 0 and 3 and cell 1 divided into 1 and 2. // This testing is designed for sequential code. if (PetscTools::IsSequential()) { TS_ASSERT_DELTA(mesh.GetNode(0)->GetRadius(), 1.0, 1e-6); TS_ASSERT_DELTA(mesh.GetNode(1)->GetRadius(), 2.0, 1e-6); TS_ASSERT_DELTA(mesh.GetNode(2)->GetRadius(), 2.0, 1e-6); TS_ASSERT_DELTA(mesh.GetNode(3)->GetRadius(), 1.0, 1e-6); // Check the separation of some node pairs TS_ASSERT_DELTA(norm_2(simulator.rGetCellPopulation().GetNode(0)->rGetLocation()-simulator.rGetCellPopulation().GetNode(1)->rGetLocation()), 3.0, 1e-1); TS_ASSERT_DELTA(norm_2(simulator.rGetCellPopulation().GetNode(0)->rGetLocation()-simulator.rGetCellPopulation().GetNode(2)->rGetLocation()), 4.70670, 1e-1); TS_ASSERT_DELTA(norm_2(simulator.rGetCellPopulation().GetNode(0)->rGetLocation()-simulator.rGetCellPopulation().GetNode(3)->rGetLocation()), 2.0, 1e-1); // Now set all the Radii to 2.0 Note this could be done inside a cell cycle model. for (AbstractCellPopulation<2>::Iterator cell_iter = simulator.rGetCellPopulation().Begin(); cell_iter != simulator.rGetCellPopulation().End(); ++cell_iter) { cell_iter->GetCellData()->SetItem("Radius",2.0); } simulator.SetEndTime(12.0); simulator.Solve(); for (unsigned i=0; i<simulator.rGetCellPopulation().GetNumNodes(); i++) { TS_ASSERT_DELTA(mesh.GetNode(i)->GetRadius(), 2.0, 1e-6); } // Check the separation of some node pairs TS_ASSERT_DELTA(norm_2(simulator.rGetCellPopulation().GetNode(0)->rGetLocation()-simulator.rGetCellPopulation().GetNode(1)->rGetLocation()), 4.0, 1e-3); TS_ASSERT_DELTA(norm_2(simulator.rGetCellPopulation().GetNode(0)->rGetLocation()-simulator.rGetCellPopulation().GetNode(2)->rGetLocation()), 6.9282, 1e-3); TS_ASSERT_DELTA(norm_2(simulator.rGetCellPopulation().GetNode(0)->rGetLocation()-simulator.rGetCellPopulation().GetNode(3)->rGetLocation()), 4.0, 1e-3); } // Clean up memory for (unsigned i=0; i<nodes.size(); i++) { delete nodes[i]; } }
void MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::WriteVtkResultsToFile(const std::string& rDirectory) { #ifdef CHASTE_VTK // Store the present time as a string unsigned num_timesteps = SimulationTime::Instance()->GetTimeStepsElapsed(); std::stringstream time; time << num_timesteps; // Store the number of cells for which to output data to VTK unsigned num_cells_from_mesh = GetNumNodes(); if (!mWriteVtkAsPoints && (mpVoronoiTessellation != NULL)) { num_cells_from_mesh = mpVoronoiTessellation->GetNumElements(); } // When outputting any CellData, we assume that the first cell is representative of all cells unsigned num_cell_data_items = this->Begin()->GetCellData()->GetNumItems(); std::vector<std::string> cell_data_names = this->Begin()->GetCellData()->GetKeys(); std::vector<std::vector<double> > cell_data; for (unsigned var=0; var<num_cell_data_items; var++) { std::vector<double> cell_data_var(num_cells_from_mesh); cell_data.push_back(cell_data_var); } if (mOutputMeshInVtk) { // Create mesh writer for VTK output VtkMeshWriter<ELEMENT_DIM, SPACE_DIM> mesh_writer(rDirectory, "mesh_"+time.str(), false); mesh_writer.WriteFilesUsingMesh(rGetMesh()); } if (mWriteVtkAsPoints) { // Create mesh writer for VTK output VtkMeshWriter<SPACE_DIM, SPACE_DIM> cells_writer(rDirectory, "results_"+time.str(), false); // Iterate over any cell writers that are present unsigned num_cells = this->GetNumAllCells(); for (typename std::vector<boost::shared_ptr<AbstractCellWriter<ELEMENT_DIM, SPACE_DIM> > >::iterator cell_writer_iter = this->mCellWriters.begin(); cell_writer_iter != this->mCellWriters.end(); ++cell_writer_iter) { // Create vector to store VTK cell data std::vector<double> vtk_cell_data(num_cells); // Loop over cells for (typename AbstractCellPopulation<ELEMENT_DIM,SPACE_DIM>::Iterator cell_iter = this->Begin(); cell_iter != this->End(); ++cell_iter) { // Get the node index corresponding to this cell unsigned node_index = this->GetLocationIndexUsingCell(*cell_iter); // Populate the vector of VTK cell data vtk_cell_data[node_index] = (*cell_writer_iter)->GetCellDataForVtkOutput(*cell_iter, this); } cells_writer.AddPointData((*cell_writer_iter)->GetVtkCellDataName(), vtk_cell_data); } // Loop over cells for (typename AbstractCellPopulation<ELEMENT_DIM,SPACE_DIM>::Iterator cell_iter = this->Begin(); cell_iter != this->End(); ++cell_iter) { // Get the node index corresponding to this cell unsigned node_index = this->GetLocationIndexUsingCell(*cell_iter); for (unsigned var=0; var<num_cell_data_items; var++) { cell_data[var][node_index] = cell_iter->GetCellData()->GetItem(cell_data_names[var]); } } for (unsigned var=0; var<num_cell_data_items; var++) { cells_writer.AddPointData(cell_data_names[var], cell_data[var]); } // Make a copy of the nodes in a disposable mesh for writing { std::vector<Node<SPACE_DIM>* > nodes; for (unsigned index=0; index<this->mrMesh.GetNumNodes(); index++) { Node<SPACE_DIM>* p_node = this->mrMesh.GetNode(index); nodes.push_back(p_node); } NodesOnlyMesh<SPACE_DIM> mesh; mesh.ConstructNodesWithoutMesh(nodes, 1.5); // Arbitrary cut off as connectivity not used. cells_writer.WriteFilesUsingMesh(mesh); } *(this->mpVtkMetaFile) << " <DataSet timestep=\""; *(this->mpVtkMetaFile) << num_timesteps; *(this->mpVtkMetaFile) << "\" group=\"\" part=\"0\" file=\"results_"; *(this->mpVtkMetaFile) << num_timesteps; *(this->mpVtkMetaFile) << ".vtu\"/>\n"; } else if (mpVoronoiTessellation != NULL) { // Create mesh writer for VTK output VertexMeshWriter<ELEMENT_DIM, SPACE_DIM> mesh_writer(rDirectory, "results", false); std::vector<double> cell_volumes(num_cells_from_mesh); // Iterate over any cell writers that are present unsigned num_cells = this->GetNumAllCells(); for (typename std::vector<boost::shared_ptr<AbstractCellWriter<ELEMENT_DIM, SPACE_DIM> > >::iterator cell_writer_iter = this->mCellWriters.begin(); cell_writer_iter != this->mCellWriters.end(); ++cell_writer_iter) { // Create vector to store VTK cell data std::vector<double> vtk_cell_data(num_cells); // Loop over elements of mpVoronoiTessellation for (typename VertexMesh<ELEMENT_DIM, SPACE_DIM>::VertexElementIterator elem_iter = mpVoronoiTessellation->GetElementIteratorBegin(); elem_iter != mpVoronoiTessellation->GetElementIteratorEnd(); ++elem_iter) { // Get index of this element in mpVoronoiTessellation unsigned elem_index = elem_iter->GetIndex(); // Get the cell corresponding to this element, via the index of the corresponding node in mrMesh unsigned node_index = mpVoronoiTessellation->GetDelaunayNodeIndexCorrespondingToVoronoiElementIndex(elem_index); CellPtr p_cell = this->GetCellUsingLocationIndex(node_index); // Populate the vector of VTK cell data vtk_cell_data[elem_index] = (*cell_writer_iter)->GetCellDataForVtkOutput(p_cell, this); } mesh_writer.AddCellData((*cell_writer_iter)->GetVtkCellDataName(), vtk_cell_data); } // Loop over elements of mpVoronoiTessellation for (typename VertexMesh<ELEMENT_DIM, SPACE_DIM>::VertexElementIterator elem_iter = mpVoronoiTessellation->GetElementIteratorBegin(); elem_iter != mpVoronoiTessellation->GetElementIteratorEnd(); ++elem_iter) { // Get index of this element in mpVoronoiTessellation unsigned elem_index = elem_iter->GetIndex(); // Get the cell corresponding to this element, via the index of the corresponding node in mrMesh unsigned node_index = mpVoronoiTessellation->GetDelaunayNodeIndexCorrespondingToVoronoiElementIndex(elem_index); CellPtr p_cell = this->GetCellUsingLocationIndex(node_index); for (unsigned var=0; var<num_cell_data_items; var++) { cell_data[var][elem_index] = p_cell->GetCellData()->GetItem(cell_data_names[var]); } } for (unsigned var=0; var<cell_data.size(); var++) { mesh_writer.AddCellData(cell_data_names[var], cell_data[var]); } mesh_writer.WriteVtkUsingMesh(*mpVoronoiTessellation, time.str()); *(this->mpVtkMetaFile) << " <DataSet timestep=\""; *(this->mpVtkMetaFile) << num_timesteps; *(this->mpVtkMetaFile) << "\" group=\"\" part=\"0\" file=\"results_"; *(this->mpVtkMetaFile) << num_timesteps; *(this->mpVtkMetaFile) << ".vtu\"/>\n"; } #endif //CHASTE_VTK }
/* * === 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, NULL, 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(); }
/* * Create and simulate a simple 3D cell population of about 1000 cells within a cuboid box with sloughing on the top edge */ void Test3dNodeBasedInBoxWithSloughing() { double size_of_box = 8.0; unsigned cells_across = 12; double scaling = size_of_box/(double(cells_across-1)); // Create a simple 3D NodeBasedCellPopulation consisting of cells evenly spaced in a regular grid std::vector<Node<3>*> nodes; unsigned index = 0; for (unsigned i=0; i<cells_across; i++) { for (unsigned j=0; j<cells_across; j++) { for (unsigned k=0; k<cells_across; k++) { nodes.push_back(new Node<3>(index, false, (double) i * scaling , (double) j * scaling, (double) k * scaling)); index++; } } } NodesOnlyMesh<3> mesh; mesh.ConstructNodesWithoutMesh(nodes, 1.5); std::vector<CellPtr> cells; MAKE_PTR(TransitCellProliferativeType, p_transit_type); CellsGenerator<UniformCellCycleModel, 3> cells_generator; cells_generator.GenerateBasicRandom(cells, mesh.GetNumNodes(), p_transit_type); NodeBasedCellPopulation<3> node_based_cell_population(mesh, cells); //node_based_cell_population.AddCellPopulationCountWriter<CellProliferativeTypesCountWriter>(); // Set up cell-based simulation OffLatticeSimulation<3> simulator(node_based_cell_population); simulator.SetOutputDirectory("Representative3dNodeBased"); simulator.SetSamplingTimestepMultiple(12); simulator.SetEndTime(10.0); // Create a force law and pass it to the simulation MAKE_PTR(RepulsionForce<3>, p_linear_force); p_linear_force->SetCutOffLength(1.5); simulator.AddForce(p_linear_force); // Create some plane boundary conditions to restrict to box and pass them to the simulation // Restrict to x>0 MAKE_PTR_ARGS(PlaneBoundaryCondition<3>, p_boundary_condition_1, (&node_based_cell_population, zero_vector<double>(3), -unit_vector<double>(3,0))); simulator.AddCellPopulationBoundaryCondition(p_boundary_condition_1); // Restrict to x < size_of_box MAKE_PTR_ARGS(PlaneBoundaryCondition<3>, p_boundary_condition_2, (&node_based_cell_population, size_of_box*unit_vector<double>(3,0), unit_vector<double>(3,0))); simulator.AddCellPopulationBoundaryCondition(p_boundary_condition_2); // Restrict to y>0 MAKE_PTR_ARGS(PlaneBoundaryCondition<3>, p_boundary_condition_3, (&node_based_cell_population, zero_vector<double>(3), -unit_vector<double>(3,1))); simulator.AddCellPopulationBoundaryCondition(p_boundary_condition_3); // Restrict to y < size_of_box MAKE_PTR_ARGS(PlaneBoundaryCondition<3>, p_boundary_condition_4, (&node_based_cell_population, size_of_box*unit_vector<double>(3,1), unit_vector<double>(3,1))); simulator.AddCellPopulationBoundaryCondition(p_boundary_condition_4); // Restrict to z > 0 MAKE_PTR_ARGS(PlaneBoundaryCondition<3>, p_boundary_condition_5, (&node_based_cell_population, zero_vector<double>(3), -unit_vector<double>(3,2))); simulator.AddCellPopulationBoundaryCondition(p_boundary_condition_5); // Create cell killer at z= size_of_box MAKE_PTR_ARGS(PlaneBasedCellKiller<3>, p_cell_killer,(&node_based_cell_population, size_of_box*unit_vector<double>(3,2), unit_vector<double>(3,2))); simulator.AddCellKiller(p_cell_killer); // Run simulation simulator.Solve(); // Check some results TS_ASSERT_EQUALS(simulator.rGetCellPopulation().GetNumRealCells(), 1128u); AbstractCellPopulation<3>::Iterator cell_iter = simulator.rGetCellPopulation().Begin(); for (unsigned i=0; i<100; i++) { ++cell_iter; } c_vector<double,3> node_location = simulator.rGetCellPopulation().GetLocationOfCellCentre(*cell_iter); TS_ASSERT_DELTA(node_location[0],0.9604, 1e-4); TS_ASSERT_DELTA(node_location[1],8.0, 1e-4); TS_ASSERT_DELTA(node_location[2],3.6539, 1e-4); // Avoid memory leak for (unsigned i=0; i<nodes.size(); i++) { delete nodes[i]; } }
void TestArchivingCellPopulation() throw (Exception) { EXIT_IF_PARALLEL; // This test doesn't work in parallel. FileFinder archive_dir("archive", RelativeTo::ChasteTestOutput); std::string archive_file = "node_based_cell_population_with_particles.arch"; ArchiveLocationInfo::SetMeshFilename("node_based_cell_population_with_particles_mesh"); { // Need to set up time unsigned num_steps = 10; SimulationTime* p_simulation_time = SimulationTime::Instance(); p_simulation_time->SetEndTimeAndNumberOfTimeSteps(1.0, num_steps+1); // 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()); // Create a cell population NodeBasedCellPopulationWithParticles<2>* const p_cell_population = new NodeBasedCellPopulationWithParticles<2>(mesh, cells); // Cells have been given birth times of 0, -1, -2, -3, -4. // loop over them to run to time 0.0; for (AbstractCellPopulation<2>::Iterator cell_iter = p_cell_population->Begin(); cell_iter != p_cell_population->End(); ++cell_iter) { cell_iter->ReadyToDivide(); } // 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(); // Write the cell population to the archive (*p_arch) << static_cast<const SimulationTime&>(*p_simulation_time); (*p_arch) << p_cell_population; // Avoid memory leak SimulationTime::Destroy(); delete p_cell_population; } { // Need to set up time unsigned num_steps = 10; SimulationTime* p_simulation_time = SimulationTime::Instance(); p_simulation_time->SetStartTime(0.0); p_simulation_time->SetEndTimeAndNumberOfTimeSteps(1.0, num_steps+1); p_simulation_time->IncrementTimeOneStep(); NodeBasedCellPopulationWithParticles<2>* p_cell_population; // Restore the cell population 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_simulation_time; (*p_arch) >> p_cell_population; // Cells have been given birth times of 0, -1, -2, -3, -4. // this checks that individual cells and their models are archived. unsigned counter = 0; for (AbstractCellPopulation<2>::Iterator cell_iter = p_cell_population->Begin(); cell_iter != p_cell_population->End(); ++cell_iter) { TS_ASSERT_DELTA(cell_iter->GetAge(), (double)(counter), 1e-7); counter++; } // Check the simulation time has been restored (through the cell) TS_ASSERT_EQUALS(p_simulation_time->GetTime(), 0.0); // Check the cell population has been restored TS_ASSERT_EQUALS(p_cell_population->rGetCells().size(), 5u); TS_ASSERT_DELTA(p_cell_population->GetMechanicsCutOffLength(), 1.5, 1e-6); // Check number of nodes TS_ASSERT_EQUALS(p_cell_population->GetNumNodes(), 5u); // Check some node positions TS_ASSERT_EQUALS(p_cell_population->GetNode(3)->GetIndex(), 3u); TS_ASSERT_EQUALS(p_cell_population->GetNode(4)->GetIndex(), 4u); TS_ASSERT_DELTA(p_cell_population->GetNode(3)->rGetLocation()[0], 0.0, 1e-9); TS_ASSERT_DELTA(p_cell_population->GetNode(3)->rGetLocation()[1], 1.0, 1e-9); TS_ASSERT_DELTA(p_cell_population->GetNode(4)->rGetLocation()[0], 0.5, 1e-9); TS_ASSERT_DELTA(p_cell_population->GetNode(4)->rGetLocation()[1], 0.5, 1e-9); // Check the member variables have been restored TS_ASSERT_DELTA(p_cell_population->GetMechanicsCutOffLength(), 1.5, 1e-9); // Tidy up delete p_cell_population; } }
void TestAddAndRemoveAndAddWithOutUpdate() { 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; for (unsigned i=10; i<mesh.GetNumNodes(); i++) { if (i != 80) { cell_location_indices.push_back(i); } } // Set up cells std::vector<CellPtr> cells; CellsGenerator<FixedDurationGenerationBasedCellCycleModel, 2> cells_generator; cells_generator.GenerateBasic(cells, cell_location_indices.size()); cells[27]->StartApoptosis(); // Create a cell population, with some random particles NodeBasedCellPopulationWithParticles<2> cell_population(mesh, cells, cell_location_indices); TS_ASSERT_EQUALS(mesh.GetNumNodes(), 81u); TS_ASSERT_EQUALS(cell_population.rGetCells().size(), 70u); MAKE_PTR(WildTypeCellMutationState, p_state); MAKE_PTR(StemCellProliferativeType, p_stem_type); FixedDurationGenerationBasedCellCycleModel* p_model = new FixedDurationGenerationBasedCellCycleModel(); CellPtr p_new_cell(new Cell(p_state, p_model)); p_new_cell->SetCellProliferativeType(p_stem_type); p_new_cell->SetBirthTime(0); c_vector<double,2> new_location = zero_vector<double>(2); new_location[0] = 0.3433453454443; new_location[0] = 0.3435346344234; cell_population.AddCell(p_new_cell, new_location, cell_population.rGetCells().front() /*random choice of parent*/); TS_ASSERT_EQUALS(mesh.GetNumNodes(), 82u); TS_ASSERT_EQUALS(cell_population.GetNumRealCells(), 71u); p_simulation_time->IncrementTimeOneStep(); unsigned num_removed = cell_population.RemoveDeadCells(); TS_ASSERT_EQUALS(num_removed, 1u); TS_ASSERT_EQUALS(mesh.GetNumNodes(), 81u); TS_ASSERT_EQUALS(cell_population.GetNumRealCells(), 70u); FixedDurationGenerationBasedCellCycleModel* p_model2 = new FixedDurationGenerationBasedCellCycleModel(); CellPtr p_new_cell2(new Cell(p_state, p_model2)); p_new_cell2->SetCellProliferativeType(p_stem_type); p_new_cell2->SetBirthTime(0); c_vector<double,2> new_location2 = zero_vector<double>(2); new_location2[0] = 0.6433453454443; new_location2[0] = 0.6435346344234; cell_population.AddCell(p_new_cell2, new_location2, cell_population.rGetCells().front() /*random choice of parent*/); TS_ASSERT_EQUALS(mesh.GetNumNodes(), 82u); TS_ASSERT_EQUALS(cell_population.GetNumRealCells(), 71u); }
void TestRemoveDeadCellsAndReMeshWithParticles() { 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; for (unsigned i=10; i<mesh.GetNumNodes(); i++) { if (i != 80) { cell_location_indices.push_back(i); } } // Set up cells std::vector<CellPtr> cells; CellsGenerator<FixedDurationGenerationBasedCellCycleModel, 2> cells_generator; cells_generator.GenerateBasic(cells, cell_location_indices.size()); cells[27]->StartApoptosis(); // Create a cell population, with some random particles NodeBasedCellPopulationWithParticles<2> cell_population_with_particles(mesh, cells, cell_location_indices); TS_ASSERT_EQUALS(mesh.GetNumNodes(), 81u); // Num real cells should be num_nodes (81) - num_particles (11) = 70 TS_ASSERT_EQUALS(cell_population_with_particles.GetNumRealCells(), 70u); p_simulation_time->IncrementTimeOneStep(); unsigned num_removed_with_particles = cell_population_with_particles.RemoveDeadCells(); TS_ASSERT_EQUALS(num_removed_with_particles, 1u); TS_ASSERT_EQUALS(mesh.GetNumNodes(), 80u); TS_ASSERT_DIFFERS(cell_population_with_particles.rGetCells().size(), cells.size()); // CellPopulation now copies cells // Num real cells should be num_nodes (81) - num_particle (11) - 1 deleted node = 69 TS_ASSERT_EQUALS(cell_population_with_particles.GetNumRealCells(), 69u); cell_population_with_particles.Update(); // For coverage NodeMap map(mesh.GetNumAllNodes()); map.ResetToIdentity(); cell_population_with_particles.UpdateParticlesAfterReMesh(map); // Num real cells should be new_num_nodes (80) - num_particles (11) TS_ASSERT_EQUALS(cell_population_with_particles.GetNumRealCells(), 69u); TS_ASSERT_EQUALS(mesh.GetNumNodes(), mesh.GetNumAllNodes()); // Nodes 0-9 should not been renumbered so are still particles. // the particle at node 80 is now at 79 as node 27 was deleted.. for (AbstractMesh<2,2>::NodeIterator node_iter = mesh.GetNodeIteratorBegin(); node_iter != mesh.GetNodeIteratorEnd(); ++node_iter) { unsigned index = node_iter->GetIndex(); // True (ie should be a particle) if i<10 or i==79, else false TS_ASSERT_EQUALS(cell_population_with_particles.IsParticle(index), ((index<10)||(index==80))); } // Finally, check the cells node indices have updated // We expect the cell node indices to be {10,11,...,79} std::set<unsigned> expected_node_indices; for (unsigned i=0; i<cell_population_with_particles.GetNumRealCells(); i++) { if (i!=27) { expected_node_indices.insert(i+10); } } expected_node_indices.insert(79); // Get actual cell node indices std::set<unsigned> node_indices_with_particles; for (AbstractCellPopulation<2>::Iterator cell_iter = cell_population_with_particles.Begin(); cell_iter != cell_population_with_particles.End(); ++cell_iter) { // Record node index corresponding to cell unsigned node_index_with_particles = cell_population_with_particles.GetLocationIndexUsingCell(*cell_iter); node_indices_with_particles.insert(node_index_with_particles); } TS_ASSERT_EQUALS(node_indices_with_particles, expected_node_indices); }
// Test with particles, checking that the Iterator doesn't loop over particles void TestNodeBasedCellPopulationWithParticlesSetup() throw(Exception) { EXIT_IF_PARALLEL; // This test doesn't work in parallel. unsigned num_cells_depth = 11; unsigned num_cells_width = 6; HoneycombMeshGenerator generator(num_cells_width, num_cells_depth, 2); TetrahedralMesh<2,2>* p_generating_mesh = generator.GetMesh(); // Convert this to a NodesOnlyMesh NodesOnlyMesh<2> mesh; mesh.ConstructNodesWithoutMesh(*p_generating_mesh, 1.5); std::vector<unsigned> location_indices = generator.GetCellLocationIndices(); // Set up cells std::vector<CellPtr> cells; CellsGenerator<FixedDurationGenerationBasedCellCycleModel,2> cells_generator; cells_generator.GenerateGivenLocationIndices(cells, location_indices); // Create a cell population NodeBasedCellPopulationWithParticles<2> cell_population(mesh, cells, location_indices); // Create a set of node indices corresponding to particles std::set<unsigned> node_indices; std::set<unsigned> location_indices_set; std::set<unsigned> particle_indices; for (unsigned i=0; i<mesh.GetNumNodes(); i++) { node_indices.insert(mesh.GetNode(i)->GetIndex()); } for (unsigned i=0; i<location_indices.size(); i++) { location_indices_set.insert(location_indices[i]); } std::set_difference(node_indices.begin(), node_indices.end(), location_indices_set.begin(), location_indices_set.end(), std::inserter(particle_indices, particle_indices.begin())); std::vector<bool> is_particle(mesh.GetNumNodes(), false); for (std::set<unsigned>::iterator it=particle_indices.begin(); it!=particle_indices.end(); it++) { TS_ASSERT_EQUALS(cell_population.GetNode(*it)->IsParticle(), true) } // Test the GetParticleIndices method std::set<unsigned> particle_indices2 = cell_population.GetParticleIndices(); TS_ASSERT_EQUALS(particle_indices, particle_indices2); // Check the iterator doesn't loop over particles unsigned counter = 0; for (AbstractCellPopulation<2>::Iterator cell_iter = cell_population.Begin(); cell_iter != cell_population.End(); ++cell_iter) { unsigned node_index = cell_population.GetLocationIndexUsingCell(*cell_iter); TS_ASSERT(!is_particle[node_index]); counter++; } TS_ASSERT_EQUALS(counter, cell_population.GetNumRealCells()); // Check counter = num_nodes - num_particles_nodes TS_ASSERT_EQUALS(counter + particle_indices.size(), mesh.GetNumNodes()); }