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 } }
/** * 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]; } }
// 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()); }