void TestGenerateBasicRandomWithFixedDurationGenerationBasedCellCycleModel() throw(Exception) { // Create mesh TrianglesMeshReader<2,2> mesh_reader("mesh/test/data/square_2_elements"); TetrahedralMesh<2,2> mesh; mesh.ConstructFromMeshReader(mesh_reader); // Create cells MAKE_PTR(TransitCellProliferativeType, p_transit_type); std::vector<CellPtr> cells; CellsGenerator<FixedDurationGenerationBasedCellCycleModel, 2> cells_generator; cells_generator.GenerateBasicRandom(cells, mesh.GetNumNodes(), p_transit_type); // Test that cells were generated correctly TS_ASSERT_EQUALS(cells.size(), mesh.GetNumNodes()); for (unsigned i=0; i<cells.size(); i++) { // Should lie between -24 and 0 TS_ASSERT_LESS_THAN_EQUALS(cells[i]->GetBirthTime(), 0.0); TS_ASSERT_LESS_THAN_EQUALS(-24.0, cells[i]->GetBirthTime()); TS_ASSERT_EQUALS(cells[i]->GetCellCycleModel()->GetDimension(), 2u); TS_ASSERT_EQUALS(cells[i]->GetCellProliferativeType(), p_transit_type); } // Test exact random numbers as test re-seeds random number generator. TS_ASSERT_DELTA(cells[0]->GetBirthTime(), -7.1141, 1e-4); TS_ASSERT_DELTA(cells[1]->GetBirthTime(), -10.1311, 1e-4); TS_ASSERT_DELTA(cells[2]->GetBirthTime(), -10.2953, 1e-4); }
void TestGenerateBasicRandomWithFixedDurationGenerationBasedCellCycleModelandVertexCells() throw(Exception) { EXIT_IF_PARALLEL; // Create mesh HoneycombVertexMeshGenerator mesh_generator(2, 2); VertexMesh<2,2>* p_mesh = mesh_generator.GetMesh(); // Create cells std::vector<CellPtr> cells; MAKE_PTR(TransitCellProliferativeType, p_transit_type); CellsGenerator<FixedDurationGenerationBasedCellCycleModel, 2> cells_generator; cells_generator.GenerateBasicRandom(cells, p_mesh->GetNumElements(), p_transit_type); // Test that cells were generated correctly TS_ASSERT_EQUALS(cells.size(), p_mesh->GetNumElements()); for (unsigned i=0; i<cells.size(); i++) { // Shold lie between -24 and 0 TS_ASSERT_LESS_THAN_EQUALS(cells[i]->GetBirthTime(), 0.0); TS_ASSERT_LESS_THAN_EQUALS(-24.0, cells[i]->GetBirthTime()); TS_ASSERT_EQUALS(cells[i]->GetCellCycleModel()->GetDimension(), 2u); TS_ASSERT_EQUALS(cells[i]->GetCellProliferativeType(), p_transit_type); } // Test exact random numbers as test re-seeds random number generator. TS_ASSERT_DELTA(cells[0]->GetBirthTime(), -7.1141, 1e-4); TS_ASSERT_DELTA(cells[1]->GetBirthTime(), -10.1311, 1e-4); TS_ASSERT_DELTA(cells[2]->GetBirthTime(), -10.2953, 1e-4); }
void CheckMonoLr91Vars(MonodomainProblem<ELEMENT_DIM, SPACE_DIM>& problem) { DistributedVector voltage = problem.rGetMesh().GetDistributedVectorFactory()->CreateDistributedVector(problem.GetSolution()); for (DistributedVector::Iterator index = voltage.Begin(); index != voltage.End(); ++index) { // assuming LR model has Ena = 54.4 and Ek = -77 double Ena = 54.4; double Ek = -77.0; TS_ASSERT_LESS_THAN_EQUALS( voltage[index] , Ena + 30); TS_ASSERT_LESS_THAN_EQUALS(-voltage[index] + (Ek-30), 0); std::vector<double> ode_vars = problem.GetMonodomainTissue()->GetCardiacCell(index.Global)->GetStdVecStateVariables(); for (int j=0; j<8; j++) { // if not voltage or calcium ion conc, test whether between 0 and 1 if ((j!=0) && (j!=7)) { TS_ASSERT_LESS_THAN_EQUALS( ode_vars[j], 1.0); TS_ASSERT_LESS_THAN_EQUALS( -ode_vars[j], 0.0); } } } }
void TestSloughingCellKillerTopAndSides() throw(Exception) { // Create mesh TrianglesMeshReader<2,2> mesh_reader("mesh/test/data/square_128_elements"); MutableMesh<2,2> mesh; mesh.ConstructFromMeshReader(mesh_reader); mesh.Translate(-0.25,-0.25); // Create cells std::vector<CellPtr> cells; CellsGenerator<FixedDurationGenerationBasedCellCycleModel, 2> cells_generator; cells_generator.GenerateBasic(cells, mesh.GetNumNodes()); // Create cell population MeshBasedCellPopulation<2> cell_population(mesh, cells); // Create cell killer and kill cells SloughingCellKiller<2> sloughing_cell_killer(&cell_population, 0.5, true, 0.5); sloughing_cell_killer.CheckAndLabelCellsForApoptosisOrDeath(); TS_ASSERT_EQUALS(sloughing_cell_killer.GetIdentifier(), "SloughingCellKiller-2"); // Check that cells were labelled for death correctly for (AbstractCellPopulation<2>::Iterator cell_iter = cell_population.Begin(); cell_iter != cell_population.End(); ++cell_iter) { double x = cell_population.GetLocationOfCellCentre(*cell_iter)[0]; double y = cell_population.GetLocationOfCellCentre(*cell_iter)[1]; if ((x<0) || (x>0.5) || (y>0.5)) { TS_ASSERT_EQUALS(cell_iter->IsDead(), true); } else { TS_ASSERT_EQUALS(cell_iter->IsDead(), false); } } cell_population.RemoveDeadCells(); for (AbstractCellPopulation<2>::Iterator cell_iter = cell_population.Begin(); cell_iter != cell_population.End(); ++cell_iter) { double x = cell_population.GetLocationOfCellCentre(*cell_iter)[0]; double y = cell_population.GetLocationOfCellCentre(*cell_iter)[1]; TS_ASSERT_LESS_THAN_EQUALS(x, 0.5); TS_ASSERT_LESS_THAN_EQUALS(y, 0.5); } }
/** * Initializes a matrix with the specified id. * Global matrices are set to the corresponding values, * local matrices initialized with random values. * * @param i_id id of the matrix {0, .., 51} -> flux matrix, {52} -> jacobian (flux solver), {53, 54, 55} -> stiffness matrices, {56, 57, 58} -> transposed stiffness matrices, {59} -> jacobian (star matrix) * @param i_numberOfRows number of rows. * @param i_numberOfColumns number of columns. * @param o_matrix matrix, which is initialized. **/ void initializeMatrix( unsigned int i_id, unsigned int i_numberOfRows, unsigned int i_numberOfColumns, real* o_matrix ) { // assert the matrices have been read assert( m_matrixIds.size() > 0 ); // get the position of our matrix unsigned int l_position; for( l_position = 0; l_position < m_matrixIds.size(); l_position++ ) { if( i_id == m_matrixIds[l_position] ) { break; } else { // matrix with the given id couldn't be found TS_ASSERT_DIFFERS( l_position, m_matrixIds.size() -1 ); } } // flux solver -> random values if( i_id == 52 ) { // assert correct matrix id TS_ASSERT_EQUALS( m_matrixIds[l_position], 52 ); setRandomValues( i_numberOfRows * i_numberOfColumns, o_matrix ); } // flux matrix, stiffness matrix or star matrix else { std::fill( o_matrix, o_matrix + i_numberOfRows * i_numberOfColumns, 0 ); for( unsigned int l_element = 0; l_element < m_matrixRows[l_position].size(); l_element++ ) { // assert that we can save the non-zero element TS_ASSERT_LESS_THAN_EQUALS( m_matrixRows[l_position][l_element], i_numberOfRows); TS_ASSERT_LESS_THAN_EQUALS( m_matrixColumns[l_position][l_element], i_numberOfColumns); unsigned int l_denseIndex = (m_matrixColumns[l_position][l_element]-1) * i_numberOfRows + (m_matrixRows[l_position][l_element]-1); // assert this a valid index TS_ASSERT_LESS_THAN( l_denseIndex, i_numberOfRows*i_numberOfColumns ); if( i_id == 59 ) { // star matrix o_matrix[ l_denseIndex ] = ((real)rand()/(real)RAND_MAX)*10.0; } else if( i_id >= 56 && i_id <= 58 ) { // add minus-sign for time kernel o_matrix[ l_denseIndex ] = -m_matrixValues[l_position][l_element]; } else{ // flux or stiffness matrix o_matrix[ l_denseIndex ] = m_matrixValues[l_position][l_element]; } } } }
void TestGenerateBasicRandomWithNoSpecifiedProliferativeCellType() throw(Exception) { // Create mesh TrianglesMeshReader<2,2> mesh_reader("mesh/test/data/square_2_elements"); TetrahedralMesh<2,2> mesh; mesh.ConstructFromMeshReader(mesh_reader); // Create cells std::vector<CellPtr> cells; CellsGenerator<FixedDurationGenerationBasedCellCycleModel, 2> cells_generator; cells_generator.GenerateBasicRandom(cells, mesh.GetNumNodes()); // Test that cells were generated correctly TS_ASSERT_EQUALS(cells.size(), mesh.GetNumNodes()); for (unsigned i=0; i<cells.size(); i++) { TS_ASSERT_EQUALS(cells[i]->GetCellCycleModel()->GetDimension(), 2u); TS_ASSERT_EQUALS(cells[i]->GetCellProliferativeType()->IsType<StemCellProliferativeType>(), true); // Should lie between -24 and 0 double birth_time=cells[i]->GetBirthTime(); ///\todo Breaks Intel 10? TS_ASSERT_LESS_THAN_EQUALS(birth_time, 0.0); TS_ASSERT_LESS_THAN_EQUALS(-24.0, birth_time); } }
void testSize() { TS_TRACE(std::string("sizeof(float) is ") + std::to_string(sizeof(float))); TS_TRACE(std::string("sizeof(vec2) is ") + std::to_string(sizeof(glam::vec2))); TS_TRACE(std::string("sizeof(vec4) is ") + std::to_string(sizeof(glam::vec4))); TS_TRACE(std::string("sizeof(bool) is ") + std::to_string(sizeof(bool))); TS_TRACE(std::string("sizeof(bvec4) is ") + std::to_string(sizeof(glam::bvec4))); TS_TRACE(std::string("sizeof(int) is ") + std::to_string(sizeof(int))); TS_TRACE(std::string("sizeof(ivec2) is ") + std::to_string(sizeof(glam::ivec2))); TS_TRACE(std::string("sizeof(double) is ") + std::to_string(sizeof(double))); TS_TRACE(std::string("sizeof(dvec3) is ") + std::to_string(sizeof(glam::dvec3))); // A vectorized implementation may pad to up to 4 vector elements to improve SIMD performance, but not more TS_ASSERT_LESS_THAN_EQUALS(sizeof(glam::Vector<float, 4>), sizeof(float) * 4); TS_ASSERT_LESS_THAN_EQUALS(sizeof(glam::Vector<double, 2>), sizeof(double) * 4); TS_ASSERT_LESS_THAN_EQUALS(sizeof(glam::Vector<bool, 4>), sizeof(bool) * 4); TS_ASSERT_LESS_THAN_EQUALS(sizeof(glam::Vector<int, 256>), sizeof(int) * 256); }
/* * Check that the submatrix of A with size B matches B. * * @param i_A values of matrix A. * @param i_aNumberOfRows number of rows of A. * @param i_aNumberOfColumns number of columns of A. * @param o_B values of matrix B, which will be set. * @param i_bNumberOfRows number of rows of matrix B. * @param i_bNumberOfColumns number of columns of matrix B */ void checkSubMatrix( const real* i_A, const unsigned int i_aNumberOfRows, const unsigned int i_aNumberOfColumns, const real* i_B, const unsigned int i_bNumberOfRows, const unsigned int i_bNumberOfColumns ) { // assert that B is a submatrix of A TS_ASSERT_LESS_THAN_EQUALS( i_bNumberOfRows, i_aNumberOfRows ); TS_ASSERT_LESS_THAN_EQUALS( i_bNumberOfColumns, i_aNumberOfColumns ); for( unsigned int l_column = 0; l_column < i_bNumberOfColumns; l_column++ ) { unsigned int l_aStart = l_column*i_aNumberOfRows; unsigned int l_bStart = l_column*i_bNumberOfRows; // check result column wise checkResult( i_bNumberOfRows, &i_A[l_aStart], &i_B[l_bStart] ); } }
void TestEndBranchDistanceLimit() throw(Exception) { #if defined(CHASTE_VTK) && ( (VTK_MAJOR_VERSION >= 5 && VTK_MINOR_VERSION >= 6) || VTK_MAJOR_VERSION >= 6) EXIT_IF_PARALLEL; vtkSmartPointer<vtkPolyData> sphere = CreateSphere(100, 100.0); //lung sized sphere to test distance limit double min_branch_length = 0.1; unsigned point_limit = 1; double angle_limit = 180.0; double branching_fraction = 0.4; bool applyPointReassignmentLimit = true; AirwayGenerator generator(sphere, min_branch_length, point_limit, angle_limit, branching_fraction, applyPointReassignmentLimit); std::deque<AirwayGeneration>& generations = generator.GetGenerations(); //The bounding box of the sphere is (-100,-100,-100) and (100,100,100), the diagonal of the bounding box is of size //sqrt(dx^2 + dy^2 + dz^2) where dx = dy = dz = 200.0 double lobe_bound_size = sqrt(120000); for(unsigned generation_number = 0; generation_number < generations.size(); ++generation_number) { double scale_distance_limit = lobe_bound_size/30; //30 is the expected total number of generations TS_ASSERT_DELTA(generations[generation_number].GetDistributionRadius(), std::max(lobe_bound_size - scale_distance_limit*generation_number, 5.0), 1e-1); } double origin[3] = {0.0, 1.0, 0.0}; double direction[3] = {1.0, 0.0, 0.0}; double parent_direction[3] = {1.0, 0.0, 0.0}; //Check that all points are distributed to an apex in generation 0 generator.AddInitialApex(origin, direction, parent_direction, 10.0, 0); vtkSmartPointer<vtkPolyData> cloud = generator.CreatePointCloudUsingTargetPoints(1000); std::set<unsigned> invalid_ids; generations[0].DistributeGrowthPoints(cloud, invalid_ids); unsigned assigned_points = generations[0].GetApices()[0].mPointCloud->GetNumberOfPoints(); unsigned total_points = cloud->GetNumberOfPoints(); TS_ASSERT_EQUALS(assigned_points, total_points); //Check that the number of distributed points becomes less with each generation unsigned previous_assigned_points = assigned_points; for(unsigned generation_number = 1; generation_number < generations.size(); ++generation_number) { generator.AddInitialApex(origin, direction, parent_direction, 10.0, generation_number); generations[generation_number].DistributeGrowthPoints(cloud, invalid_ids); assigned_points = generations[generation_number].GetApices()[0].mPointCloud->GetNumberOfPoints(); TS_ASSERT_LESS_THAN_EQUALS(assigned_points, previous_assigned_points); previous_assigned_points = assigned_points; } #endif }
void TestSloughingCellKillerIn1d() throw(Exception) { // Create 1D mesh unsigned num_cells = 14; MutableMesh<1,1> mesh; mesh.ConstructLinearMesh(num_cells-1); // Create cells std::vector<CellPtr> cells; CellsGenerator<FixedDurationGenerationBasedCellCycleModel, 2> cells_generator; cells_generator.GenerateBasic(cells, mesh.GetNumNodes()); // Create cell population MeshBasedCellPopulation<1> cell_population(mesh, cells); // Set the crypt length so that 2 cells should be sloughed off double crypt_length = 12.5; // Create cell killer and kill cells SloughingCellKiller<1> sloughing_cell_killer(&cell_population, crypt_length); sloughing_cell_killer.CheckAndLabelCellsForApoptosisOrDeath(); // Check that cells were labelled for death correctly for (AbstractCellPopulation<1>::Iterator cell_iter = cell_population.Begin(); cell_iter != cell_population.End(); ++cell_iter) { double x = cell_population.GetLocationOfCellCentre(*cell_iter)[0]; if (x > crypt_length) { TS_ASSERT_EQUALS(cell_iter->IsDead(), true); } else { TS_ASSERT_EQUALS(cell_iter->IsDead(), false); } } // Check that dead cells were correctly removed cell_population.RemoveDeadCells(); for (AbstractCellPopulation<1>::Iterator cell_iter = cell_population.Begin(); cell_iter != cell_population.End(); ++cell_iter) { double x = cell_population.GetLocationOfCellCentre(*cell_iter)[0]; TS_ASSERT_LESS_THAN_EQUALS(x, crypt_length); } }
/** * Create a simulation of a NodeBasedCellPopulation with a BuskeInteractionForce system. * Test that no exceptions are thrown, and write the results to file. */ void TestSimpleMonolayerWithBuskeAdhesiveForce() 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; 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("TestOffLatticeSimulationWithBuskeAdhesiveForce"); simulator.SetEndTime(5.0); // Create a force law and pass it to the simulation MAKE_PTR(BuskeAdhesiveForce<2>, p_buske_adhesive_force); p_buske_adhesive_force->SetAdhesionEnergyParameter(0.002); simulator.AddForce(p_buske_adhesive_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_LESS_THAN_EQUALS(1e-3, min_distance_between_cells); }
void TestSolvePdeAndWriteResultsToFileWithCoarsePdeMesh() throw(Exception) { EXIT_IF_PARALLEL; // Set up SimulationTime SimulationTime::Instance()->SetEndTimeAndNumberOfTimeSteps(0.05, 6); // Create a cell population HoneycombMeshGenerator generator(5, 5, 0); MutableMesh<2,2>* p_mesh = generator.GetMesh(); std::vector<CellPtr> cells; CellsGenerator<FixedDurationGenerationBasedCellCycleModel, 2> cells_generator; cells_generator.GenerateBasic(cells, p_mesh->GetNumNodes()); MeshBasedCellPopulation<2> cell_population(*p_mesh, cells); // Create a PDE handler object using this cell population CellBasedPdeHandler<2> pde_handler(&cell_population); // 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("quantity 1"); pde_handler.AddPdeAndBc(&pde_and_bc); // Set up second PDE and pass to handler AveragedSourcePde<2> pde2(cell_population, -0.5); PdeAndBoundaryConditions<2> pde_and_bc2(&pde2, &bc, false); TS_ASSERT_THROWS_THIS(pde_handler.AddPdeAndBc(&pde_and_bc2), "When adding more than one PDE to CellBasedPdeHandler set the dependent variable name using SetDependentVariableName(name)."); pde_and_bc2.SetDependentVariableName("quantity 1"); TS_ASSERT_THROWS_THIS(pde_handler.AddPdeAndBc(&pde_and_bc2), "The name quantity 1 has already been used in the PDE collection"); pde_and_bc2.SetDependentVariableName("quantity 2"); pde_handler.AddPdeAndBc(&pde_and_bc2); // Solve PDEs on a coarse mesh ChastePoint<2> lower(0.0, 0.0); ChastePoint<2> upper(50.0, 50.0); ChasteCuboid<2> cuboid(lower, upper); pde_handler.UseCoarsePdeMesh(10.0, cuboid, true); pde_handler.SetImposeBcsOnCoarseBoundary(false); // Open result file ourselves OutputFileHandler output_file_handler("TestSolvePdeAndWriteResultsToFileWithCoarsePdeMesh", false); pde_handler.mpVizPdeSolutionResultsFile = output_file_handler.OpenOutputFile("results.vizpdesolution"); // Solve PDEs and (for coverage) write results to file pde_handler.SolvePdeAndWriteResultsToFile(1); // Close result file ourselves pde_handler.mpVizPdeSolutionResultsFile->close(); TetrahedralMesh<2,2>* p_coarse_mesh = pde_handler.GetCoarsePdeMesh(); TS_ASSERT(p_coarse_mesh != NULL); TS_ASSERT_THROWS_THIS(pde_handler.GetPdeSolution("quantity 3"), "The PDE collection does not contain a PDE named quantity 3"); ReplicatableVector pde_solution0(pde_handler.GetPdeSolution("quantity 1")); ReplicatableVector pde_solution1(pde_handler.GetPdeSolution("quantity 2")); TS_ASSERT_EQUALS(pde_solution0.GetSize(), pde_solution1.GetSize()); // Test that the solution is 1.0 at each coarse mesh node far from the cells for (unsigned i=0; i<pde_solution0.GetSize(); i++) { c_vector<double,2> centre; centre(0) = 2.5; // assuming 5x5 honeycomb mesh centre(1) = 2.5; c_vector<double,2> position = p_coarse_mesh->GetNode(i)->rGetLocation(); double dist = norm_2(centre - position); double u0 = pde_solution0[i]; double u1 = pde_solution1[i]; if (dist > 4.0) { TS_ASSERT_DELTA(u0, 1.0, 1e-5); TS_ASSERT_DELTA(u1, 1.0, 1e-5); } } /* * Loop over cells, find the coarse mesh element containing it, then * check the interpolated PDE solution is between the min and max of * the PDE solution on the nodes of that element. */ for (AbstractCellPopulation<2>::Iterator cell_iter = cell_population.Begin(); cell_iter != cell_population.End(); ++cell_iter) { c_vector<double,2> cell_location = cell_population.GetLocationOfCellCentre(*cell_iter); unsigned elem_index = p_coarse_mesh->GetContainingElementIndex(cell_location); Element<2,2>* p_element = p_coarse_mesh->GetElement(elem_index); unsigned node_0_index = p_element->GetNodeGlobalIndex(0); unsigned node_1_index = p_element->GetNodeGlobalIndex(1); unsigned node_2_index = p_element->GetNodeGlobalIndex(2); double max0 = std::max(pde_solution0[node_0_index], pde_solution0[node_1_index]); max0 = std::max(max0, pde_solution0[node_2_index]); double max1 = std::max(pde_solution1[node_0_index], pde_solution1[node_1_index]); max1 = std::max(max1, pde_solution1[node_2_index]); double min0 = std::min(pde_solution0[node_0_index], pde_solution0[node_1_index]); min0 = std::min(min0, pde_solution0[node_2_index]); double min1 = std::min(pde_solution1[node_0_index], pde_solution1[node_1_index]); min1 = std::min(min1, pde_solution1[node_2_index]); double value0_at_cell = cell_iter->GetCellData()->GetItem("quantity 1"); double value1_at_cell = cell_iter->GetCellData()->GetItem("quantity 2"); TS_ASSERT_LESS_THAN_EQUALS(value1_at_cell, value0_at_cell); TS_ASSERT_LESS_THAN_EQUALS(min0, value0_at_cell + DBL_EPSILON); TS_ASSERT_LESS_THAN_EQUALS(value0_at_cell, max0 + DBL_EPSILON); TS_ASSERT_LESS_THAN_EQUALS(min1, value1_at_cell + DBL_EPSILON); TS_ASSERT_LESS_THAN_EQUALS(value1_at_cell, max1 + DBL_EPSILON); // Now check the GetPdeSolutionAtPoint method matches TS_ASSERT_DELTA(pde_handler.GetPdeSolutionAtPoint(cell_location, "quantity 1"), value0_at_cell, 1e-6); TS_ASSERT_DELTA(pde_handler.GetPdeSolutionAtPoint(cell_location, "quantity 2"), value1_at_cell, 1e-6); } }
void TestRadialSloughingCellKillerMethods() throw(Exception) { // Create mesh TrianglesMeshReader<2,2> mesh_reader("mesh/test/data/square_128_elements"); MutableMesh<2,2> mesh; mesh.ConstructFromMeshReader(mesh_reader); mesh.Translate(-0.5,-0.5); // Get centre of mesh (we know it's at the origin, really) c_vector<double,2> centre(2); centre[0] = 0.0; centre[1] = 0.0; for (unsigned i=0; i<mesh.GetNumNodes(); i++) { centre += mesh.GetNode(i)->rGetLocation(); } centre = centre/mesh.GetNumNodes(); // Choose radius of cell killer double radius = 0.4; // Create cells std::vector<CellPtr> cells; CellsGenerator<FixedDurationGenerationBasedCellCycleModel, 2> cells_generator; cells_generator.GenerateBasic(cells, mesh.GetNumNodes()); // Create cell population MeshBasedCellPopulation<2> cell_population(mesh, cells); // Create cell killer and kill cells RadialSloughingCellKiller radial_cell_killer(&cell_population, centre, radius); radial_cell_killer.CheckAndLabelCellsForApoptosisOrDeath(); // Check that cells were labelled for death correctly for (AbstractCellPopulation<2>::Iterator cell_iter = cell_population.Begin(); cell_iter != cell_population.End(); ++cell_iter) { double r = norm_2(cell_population.GetLocationOfCellCentre(*cell_iter) - centre); if (r > radius) { TS_ASSERT_EQUALS(cell_iter->IsDead(), true); } else { TS_ASSERT_EQUALS(cell_iter->IsDead(), false); } } // Now get rid of dead cells cell_population.RemoveDeadCells(); // Check that we are correctly left with cells inside the circle of death for (AbstractCellPopulation<2>::Iterator cell_iter = cell_population.Begin(); cell_iter != cell_population.End(); ++cell_iter) { double r = norm_2(cell_population.GetLocationOfCellCentre(*cell_iter) - centre); TS_ASSERT_LESS_THAN_EQUALS(r, radius); } }
/** * Create a simulation of a NodeBasedCellPopulation with a Cylindrical2dNodesOnlyMesh * to test periodicity. */ void TestSimplePeriodicMonolayer() throw (Exception) { EXIT_IF_PARALLEL; // HoneycombMeshGenereator does not work in parallel. // Create a simple periodic mesh unsigned num_cells_depth = 3; unsigned num_cells_width = 3; HoneycombMeshGenerator generator(num_cells_width, num_cells_depth, 0); TetrahedralMesh<2,2>* p_generating_mesh = generator.GetMesh(); // Convert this to a Cylindrical2dNodesOnlyMesh double periodic_width = 4.0; Cylindrical2dNodesOnlyMesh mesh(periodic_width); mesh.ConstructNodesWithoutMesh(*p_generating_mesh, periodic_width); // 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("TestOffLatticeSimulationWithPeriodicNodeBasedCellPopulation"); // Run for long enough to see the periodic bounday influencing the cells 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(1.5); simulator.AddForce(p_linear_force); simulator.Solve(); // Check that nothing's gone badly wrong by testing that nodes aren't outside the domain for (unsigned i=0; i<simulator.rGetCellPopulation().GetNumNodes(); i++) { TS_ASSERT_LESS_THAN_EQUALS(0,simulator.rGetCellPopulation().GetNode(i)->rGetLocation()[0]); TS_ASSERT_LESS_THAN_EQUALS(simulator.rGetCellPopulation().GetNode(i)->rGetLocation()[0],periodic_width); } // Now run the simulation again with the periodic boundary in a different place and check its the same // First reset the singletons SimulationTime::Instance()->Destroy(); SimulationTime::Instance()->SetStartTime(0.0); RandomNumberGenerator::Instance()->Reseed(0); double x_offset = periodic_width/2.0; p_generating_mesh->Translate(x_offset,0.0); // Convert this to a Cylindrical2dNodesOnlyMesh Cylindrical2dNodesOnlyMesh mesh_2(periodic_width); mesh_2.ConstructNodesWithoutMesh(*p_generating_mesh, periodic_width); // Create cells std::vector<CellPtr> cells_2; CellsGenerator<FixedDurationGenerationBasedCellCycleModel, 2> cells_generator_2; cells_generator_2.GenerateBasicRandom(cells_2, mesh_2.GetNumNodes()); // Create a node-based cell population NodeBasedCellPopulation<2> node_based_cell_population_2(mesh_2, cells_2); // Set up cell-based simulation OffLatticeSimulation<2> simulator_2(node_based_cell_population_2); simulator_2.SetOutputDirectory("TestOffLatticeSimulationWith2ndPeriodicNodeBasedCellPopulation"); // Run for long enough to see the periodic boundary influencing the cells simulator_2.SetEndTime(10.0); // Pass the same force law to the simulation simulator_2.AddForce(p_linear_force); simulator_2.Solve(); // Check that nothing's gone badly wrong by testing that nodes aren't outside the domain for (unsigned i=0; i<simulator.rGetCellPopulation().GetNumNodes(); i++) { double x_1 = simulator.rGetCellPopulation().GetNode(i)->rGetLocation()[0]; double x_2 = simulator_2.rGetCellPopulation().GetNode(i)->rGetLocation()[0]; if (x_1 < x_offset) { TS_ASSERT_DELTA(x_1+x_offset, x_2, 1e-6) } else { TS_ASSERT_DELTA(x_1-x_offset, x_2, 1e-6) } TS_ASSERT_DELTA(simulator.rGetCellPopulation().GetNode(i)->rGetLocation()[1],simulator_2.rGetCellPopulation().GetNode(i)->rGetLocation()[1],1e-6); } }
void TestDistancesToCorner() throw (Exception) { TrianglesMeshReader<3,3> mesh_reader("mesh/test/data/cube_21_nodes_side/Cube21"); // 5x5x5mm cube (internode distance = 0.25mm) TetrahedralMesh<3,3> mesh; mesh.ConstructFromMeshReader(mesh_reader); unsigned num_nodes=9261u; TS_ASSERT_EQUALS(mesh.GetNumNodes(), num_nodes); // 21x21x21 nodes TS_ASSERT_EQUALS(mesh.GetNumElements(), 48000u); TS_ASSERT_EQUALS(mesh.GetNumBoundaryElements(), 4800u); DistributedTetrahedralMesh<3,3> parallel_mesh(DistributedTetrahedralMeshPartitionType::DUMB); // No reordering; parallel_mesh.ConstructFromMeshReader(mesh_reader); TS_ASSERT_EQUALS(parallel_mesh.GetNumNodes(), num_nodes); // 21x21x21 nodes TS_ASSERT_EQUALS(parallel_mesh.GetNumElements(), 48000u); TS_ASSERT_EQUALS(parallel_mesh.GetNumBoundaryElements(), 4800u); unsigned far_index=9260u; c_vector<double,3> far_corner=mesh.GetNode(far_index)->rGetLocation(); TS_ASSERT_DELTA( far_corner[0], 0.25, 1e-11); TS_ASSERT_DELTA( far_corner[1], 0.25, 1e-11); TS_ASSERT_DELTA( far_corner[2], 0.25, 1e-11); try { c_vector<double,3> parallel_far_corner=parallel_mesh.GetNode(far_index)->rGetLocation(); TS_ASSERT_DELTA( parallel_far_corner[0], 0.25, 1e-11); TS_ASSERT_DELTA( parallel_far_corner[1], 0.25, 1e-11); TS_ASSERT_DELTA( parallel_far_corner[2], 0.25, 1e-11); } catch (Exception&) { } std::vector<unsigned> map_far_corner; map_far_corner.push_back(far_index); DistanceMapCalculator<3,3> distance_calculator(mesh); std::vector<double> distances; distance_calculator.ComputeDistanceMap(map_far_corner, distances); DistanceMapCalculator<3,3> parallel_distance_calculator(parallel_mesh); std::vector<double> parallel_distances; parallel_distance_calculator.ComputeDistanceMap(map_far_corner, parallel_distances); TS_ASSERT_EQUALS(distance_calculator.mRoundCounter, 1u); //Nodes in mesh are order such that a dumb partitioning will give a sequential handover from proc0 to proc1... TS_ASSERT_EQUALS(parallel_distance_calculator.mRoundCounter, PetscTools::GetNumProcs()); //Note unsigned division is okay here TS_ASSERT_DELTA(parallel_distance_calculator.mPopCounter, num_nodes/PetscTools::GetNumProcs(), 1u); TS_ASSERT_DELTA(distance_calculator.mPopCounter, num_nodes, 1u); for (unsigned index=0; index<distances.size(); index++) { c_vector<double, 3> node = mesh.GetNode(index)->rGetLocation(); //Straightline distance double euclidean_distance = norm_2(far_corner - node); // x + y + z distance double manhattan_distance = norm_1(far_corner - node); //If they differ, then allow the in-mesh distance to be in between double error_bound = (manhattan_distance - euclidean_distance)/2.0; //If they don't differ, then we expect the in-mesh distance to be similar if (error_bound < 1e-15) { error_bound = 1e-15; } TS_ASSERT_LESS_THAN_EQUALS(distances[index], manhattan_distance+DBL_EPSILON); TS_ASSERT_LESS_THAN_EQUALS(euclidean_distance, distances[index]+DBL_EPSILON); TS_ASSERT_DELTA(distances[index], euclidean_distance, error_bound); TS_ASSERT_DELTA(distances[index], parallel_distances[index], 1e-15); } // Test some point-to-point distances RandomNumberGenerator::Instance()->Reseed(1); unsigned trials=25; unsigned pops=0; unsigned sequential_pops=0; for (unsigned i=0; i<trials; i++) { unsigned index=RandomNumberGenerator::Instance()->randMod(parallel_distances.size()); TS_ASSERT_DELTA(parallel_distance_calculator.SingleDistance(9260u, index), parallel_distances[index], 1e-15); TS_ASSERT_DELTA(distance_calculator.SingleDistance(9260u, index), parallel_distances[index], 1e-15); pops += parallel_distance_calculator.mPopCounter; sequential_pops += distance_calculator.mPopCounter; TS_ASSERT_LESS_THAN_EQUALS(parallel_distance_calculator.mRoundCounter, PetscTools::GetNumProcs()+2); } // Without A*: TS_ASSERT_DELTA(sequential_pops/(double)trials, num_nodes/2, 300); TS_ASSERT_LESS_THAN(sequential_pops/(double)trials, num_nodes/20.0); if (PetscTools::IsSequential()) { //Early termination TS_ASSERT_EQUALS(pops, sequential_pops); } else { //Early termination on remote processes is not yet possible //This may lead to multiple updates from remote //A* Leads to even more updates on average // Without A*: TS_ASSERT_DELTA(pops/(double)trials, num_nodes/PetscTools::GetNumProcs(), 700.0); TS_ASSERT_LESS_THAN(pops/(double)trials, num_nodes/10.0 ); } //Reverse - to check that cached information is flushed. for (unsigned i=0; i<3; i++) { unsigned index=RandomNumberGenerator::Instance()->randMod(parallel_distances.size()); TS_ASSERT_DELTA(parallel_distance_calculator.SingleDistance(index, 9260u), parallel_distances[index], 1e-15); } }
void TestBetterThanNoPreconditioning() { unsigned num_nodes = 1331; DistributedVectorFactory factory(num_nodes); Vec parallel_layout = factory.CreateVec(2); unsigned point_jacobi_its; unsigned block_diag_its; Timer::Reset(); { Mat system_matrix; // Note that this test deadlocks if the file's not on the disk PetscTools::ReadPetscObject(system_matrix, "linalg/test/data/matrices/cube_6000elems_half_activated.mat", parallel_layout); Vec system_rhs; // Note that this test deadlocks if the file's not on the disk PetscTools::ReadPetscObject(system_rhs, "linalg/test/data/matrices/cube_6000elems_half_activated.vec", parallel_layout); LinearSystem ls = LinearSystem(system_rhs, system_matrix); ls.SetAbsoluteTolerance(1e-9); ls.SetKspType("cg"); ls.SetPcType("none"); Vec solution = ls.Solve(); point_jacobi_its = ls.GetNumIterations(); PetscTools::Destroy(system_matrix); PetscTools::Destroy(system_rhs); PetscTools::Destroy(solution); } Timer::PrintAndReset("No preconditioning"); { Mat system_matrix; // Note that this test deadlocks if the file's not on the disk PetscTools::ReadPetscObject(system_matrix, "linalg/test/data/matrices/cube_6000elems_half_activated.mat", parallel_layout); Vec system_rhs; // Note that this test deadlocks if the file's not on the disk PetscTools::ReadPetscObject(system_rhs, "linalg/test/data/matrices/cube_6000elems_half_activated.vec", parallel_layout); LinearSystem ls = LinearSystem(system_rhs, system_matrix); ls.SetAbsoluteTolerance(1e-9); ls.SetKspType("cg"); ls.SetPcType("blockdiagonal"); Vec solution = ls.Solve(); block_diag_its = ls.GetNumIterations(); // Coverage (setting PC type after using blockdiagonal solve) ls.SetPcType("blockdiagonal"); PetscTools::Destroy(system_matrix); PetscTools::Destroy(system_rhs); PetscTools::Destroy(solution); } Timer::Print("Block diagonal preconditioner"); std::cout << block_diag_its << " " << point_jacobi_its << std::endl; TS_ASSERT_LESS_THAN_EQUALS(block_diag_its, point_jacobi_its); PetscTools::Destroy(parallel_layout); }