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 TestTranslationMethod() throw (Exception) { TrianglesMeshReader<3,3> mesh_reader("mesh/test/data/cube_136_elements"); TetrahedralMesh<3,3> mesh; mesh.ConstructFromMeshReader(mesh_reader); // Pick a random node and store spatial position Node<3>* p_node = mesh.GetNode(10); ChastePoint<3> original_coordinate = p_node->GetPoint(); double mesh_volume = mesh.GetVolume(); const double x_movement = 1.0; const double y_movement = 2.5; const double z_movement = -3.75; mesh.Translate(x_movement, y_movement, z_movement); ChastePoint<3> new_coordinate = p_node->GetPoint(); double new_mesh_volume = mesh.GetVolume(); TS_ASSERT_DELTA(mesh_volume, new_mesh_volume, 1e-6); TS_ASSERT_DELTA(original_coordinate[0], new_coordinate[0]-x_movement, 1e-6); TS_ASSERT_DELTA(original_coordinate[1], new_coordinate[1]-y_movement, 1e-6); TS_ASSERT_DELTA(original_coordinate[2], new_coordinate[2]-z_movement, 1e-6); }
void TestTranslation3DWithUblas() { TrianglesMeshReader<3,3> mesh_reader("mesh/test/data/cube_136_elements"); TetrahedralMesh<3,3> mesh; mesh.ConstructFromMeshReader(mesh_reader); double volume = mesh.GetVolume(); double surface_area = mesh.GetSurfaceArea(); Node<3>* p_node1 = mesh.GetNode(36); ChastePoint<3> point1 = p_node1->GetPoint(); Node<3>* p_node2 = mesh.GetNode(23); ChastePoint<3> point2 = p_node2->GetPoint(); c_vector<double, 3> old_location1 = point1.rGetLocation(); c_vector<double, 3> old_location2 = point2.rGetLocation(); // Set translation Vector c_vector<double, 3> trans_vec; trans_vec(0) = 2.0; trans_vec(1) = 2.0; trans_vec(2) = 2.0; // Translate mesh.Translate(trans_vec); c_vector<double, 3> new_location1 = point1.rGetLocation(); c_vector<double, 3> new_location2 = point2.rGetLocation(); // Check Volume and Surface Area are invariant TS_ASSERT_DELTA(mesh.GetVolume(), volume, 1e-6); TS_ASSERT_DELTA(mesh.GetSurfaceArea(), surface_area, 1e-6); // Spot check a couple of nodes TS_ASSERT_DELTA(inner_prod(new_location1-old_location1, trans_vec), 0, 1e-6); TS_ASSERT_DELTA(inner_prod(new_location2-old_location2, trans_vec), 0, 1e-6); }
void Test2DMeshRotation() { TrianglesMeshReader<2,2> mesh_reader("mesh/test/data/2D_0_to_1mm_200_elements"); TetrahedralMesh<2,2> mesh; mesh.ConstructFromMeshReader(mesh_reader); double angle = M_PI; mesh.Rotate(angle); TetrahedralMesh<2,2> original_mesh; original_mesh.ConstructFromMeshReader(mesh_reader); for (unsigned i=0; i<mesh.GetNumNodes(); i++) { // Find new coordinates of the translated node Node<2>* p_node = mesh.GetNode(i); ChastePoint<2> new_coordinate = p_node->GetPoint(); // Get original node Node<2>* p_original_node = original_mesh.GetNode(i); ChastePoint<2> original_coordinate = p_original_node->GetPoint(); // Run a test to make sure the node has gone to the correct place TS_ASSERT_DELTA(original_coordinate[0], -new_coordinate[0], 1e-5); TS_ASSERT_DELTA(original_coordinate[1], -new_coordinate[1], 1e-5); } // Check volume conservation double mesh_volume = mesh.GetVolume(); double original_mesh_volume = original_mesh.GetVolume(); TS_ASSERT_DELTA(mesh_volume, original_mesh_volume, 1e-5); }
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 TestAnyNonZeroNeumannConditionsAndApplyNeumannToMeshBoundary() { // Load a 2D square mesh with 1 central non-boundary node TrianglesMeshReader<2,2> mesh_reader("mesh/test/data/square_4_elements"); TetrahedralMesh<2,2> mesh; mesh.ConstructFromMeshReader(mesh_reader); BoundaryConditionsContainer<2,2,1> bcc; BoundaryConditionsContainer<2,2,2> bcc_2unknowns; TS_ASSERT_EQUALS(bcc.AnyNonZeroNeumannConditions(), false); bcc.DefineZeroNeumannOnMeshBoundary(&mesh); TetrahedralMesh<2,2>::BoundaryElementIterator iter; iter = mesh.GetBoundaryElementIteratorBegin(); while (iter != mesh.GetBoundaryElementIteratorEnd()) { TS_ASSERT(bcc.HasNeumannBoundaryCondition(*iter)); double value = bcc.GetNeumannBCValue(*iter, (*iter)->GetNode(0)->GetPoint()); TS_ASSERT_DELTA(value, 0.0, 1e-8); iter++; } TS_ASSERT_EQUALS(bcc.AnyNonZeroNeumannConditions(), false); iter = mesh.GetBoundaryElementIteratorBegin(); ConstBoundaryCondition<2>* p_boundary_condition2 = new ConstBoundaryCondition<2>(-1); bcc_2unknowns.AddNeumannBoundaryCondition(*iter, p_boundary_condition2); TS_ASSERT_EQUALS(bcc_2unknowns.AnyNonZeroNeumannConditions(), true); }
void TestValidate() { // Load a 2D square mesh with 1 central non-boundary node TrianglesMeshReader<2,2> mesh_reader("mesh/test/data/square_4_elements"); TetrahedralMesh<2,2> mesh; mesh.ConstructFromMeshReader(mesh_reader); BoundaryConditionsContainer<2,2,1> bcc; // No BCs yet, so shouldn't validate TS_ASSERT(!bcc.Validate(&mesh)); // Add some BCs ConstBoundaryCondition<2> *bc = new ConstBoundaryCondition<2>(0.0); bcc.AddDirichletBoundaryCondition(mesh.GetNode(0), bc); bcc.AddDirichletBoundaryCondition(mesh.GetNode(1), bc); bcc.AddDirichletBoundaryCondition(mesh.GetNode(3), bc); TetrahedralMesh<2,2>::BoundaryElementIterator iter = mesh.GetBoundaryElementIteratorEnd(); iter--; bcc.AddNeumannBoundaryCondition(*iter, bc); // 2 to 3 iter--; bcc.AddNeumannBoundaryCondition(*iter, bc); // 1 to 2 TS_ASSERT(bcc.Validate(&mesh)); }
void TestScalingWithMethod() { TrianglesMeshReader<3,3> mesh_reader("mesh/test/data/cube_136_elements"); TetrahedralMesh<3,3> mesh; mesh.ConstructFromMeshReader(mesh_reader); double mesh_volume = mesh.GetVolume(); mesh.Scale(1.0); TS_ASSERT_DELTA(mesh_volume, mesh.GetVolume(), 1e-6); mesh.Scale(2.0, 3.0, 4.0); TS_ASSERT_DELTA(24.0*mesh_volume, mesh.GetVolume(), 1e-6); ChastePoint<3> corner_after = mesh.GetNode(6)->GetPoint(); TS_ASSERT_DELTA(corner_after[0], 2.0, 1e-7); TS_ASSERT_DELTA(corner_after[1], 3.0, 1e-7); TS_ASSERT_DELTA(corner_after[2], 4.0, 1e-7); mesh.Scale(0.5, 1.0/3.0, 0.25); TS_ASSERT_DELTA(mesh_volume,mesh.GetVolume(),1e-6); corner_after = mesh.GetNode(6)->GetPoint(); TS_ASSERT_DELTA(corner_after[0], 1.0, 1e-7); TS_ASSERT_DELTA(corner_after[1], 1.0, 1e-7); TS_ASSERT_DELTA(corner_after[2], 1.0, 1e-7); }
/** * This tests the HDF5 to .txt converter using a 3D example * taken from a bidomain simulation. */ void TestBidomainTxtConversion3D() throw(Exception) { std::string working_directory = "TestHdf5ToTxtConverter_bidomain"; /* * Firstly, copy the .h5 file to CHASTE_TEST_OUTPUT/TestHdf5ToTxtConverter_bidomain, * as that is where the reader reads from. */ CopyToTestOutputDirectory("pde/test/data/cube_2mm_12_elements.h5", working_directory); TrianglesMeshReader<3,3> mesh_reader("mesh/test/data/cube_2mm_12_elements"); TetrahedralMesh<3,3> mesh; mesh.ConstructFromMeshReader(mesh_reader); // Convert Hdf5ToTxtConverter<3,3> converter(FileFinder(working_directory, RelativeTo::ChasteTestOutput), "cube_2mm_12_elements", &mesh); std::vector<std::string> files_to_compare; files_to_compare.push_back("cube_2mm_12_elements_V_0.txt"); files_to_compare.push_back("cube_2mm_12_elements_V_1.txt"); files_to_compare.push_back("cube_2mm_12_elements_Phi_e_0.txt"); files_to_compare.push_back("cube_2mm_12_elements_Phi_e_1.txt"); for (unsigned i=0; i<files_to_compare.size(); i++) { std::cout << "Comparing generated and reference " << files_to_compare[i] << std::endl; FileFinder generated_file(working_directory +"/txt_output/" + files_to_compare[i], RelativeTo::ChasteTestOutput); FileFinder reference_file("pde/test/data/" + files_to_compare[i], RelativeTo::ChasteSourceRoot); NumericFileComparison comparer(generated_file, reference_file); TS_ASSERT(comparer.CompareFiles()); } }
// see also TestPapillaryFibreCalculatorLong() for bigger test of the main method on a cylinder. void TestGetFibreOrientationsOnSimpleCube(void) throw(Exception) { TrianglesMeshReader<3,3> mesh_reader("mesh/test/data/simple_cube"); TetrahedralMesh<3,3> mesh; mesh.ConstructFromMeshReader(mesh_reader); PapillaryFibreCalculator calculator(mesh); std::vector<c_vector<double,3> > fibre_orientations = calculator.CalculateFibreOrientations(); // Not very well defined for a cube (since it's so well structured that there are zero // eigenvectors in the smoothed tensors) but necessary to test coverage. // Nightly test TestPapillaryFibreCalculatorLong.hpp is a better one if you want to understand it! ///\todo There may still be a sign issue between flapack and MKL ///\todo THIS TEST IS KNOWN TO STALL IN LAPACK (dgeev_) // ON THIS CONFIGURATION : // * 32-bit virtual machine on Ubuntu 8.04 LTS // * build=GccOpt // * PETSc: petsc-2.3.2-p10 with f2cblaslapack TS_ASSERT_DELTA(fabs(fibre_orientations[0](0)), 0.7056, 1e-4); TS_ASSERT_DELTA(fabs(fibre_orientations[0](1)), 0.0641, 1e-4); TS_ASSERT_DELTA(fabs(fibre_orientations[0](2)), 0.7056, 1e-4); TS_ASSERT_DELTA(fabs(fibre_orientations[4](0)), 0.0455, 1e-4); TS_ASSERT_DELTA(fabs(fibre_orientations[4](1)), 0.5005, 1e-4); TS_ASSERT_DELTA(fabs(fibre_orientations[4](2)), 0.8645, 1e-4); TS_ASSERT_DELTA(fabs(fibre_orientations[5](0)), 0.6704, 1e-4); TS_ASSERT_DELTA(fabs(fibre_orientations[5](1)), 0.3176, 1e-4); TS_ASSERT_DELTA(fabs(fibre_orientations[5](2)), 0.6704, 1e-4); }
void TestRefreshMeshByScaling() { TrianglesMeshReader<3,3> mesh_reader("mesh/test/data/cube_136_elements"); TetrahedralMesh<3,3> mesh; mesh.ConstructFromMeshReader(mesh_reader); TS_ASSERT_DELTA(mesh.GetVolume(), 1.0, 1e-6); TS_ASSERT_DELTA(mesh.GetSurfaceArea(), 6.0, 1e-6); // Change coordinates for (unsigned i=0; i<mesh.GetNumNodes(); i++) { Node<3>* p_node = mesh.GetNode(i); ChastePoint<3> point = p_node->GetPoint(); point.SetCoordinate(0, point[0]*2.0); point.SetCoordinate(1, point[1]*2.0); point.SetCoordinate(2, point[2]*2.0); p_node->SetPoint(point); } mesh.RefreshMesh(); TS_ASSERT_DELTA(mesh.GetVolume(), 8.0, 1e-6); TS_ASSERT_DELTA(mesh.GetSurfaceArea(), 24.0, 1e-6); }
void TestBidomainMeshalyzerConversion() throw(Exception) { /* * Firstly, copy the .h5 file to CHASTE_TEST_OUTPUT/TestHdf5ToMeshalyzerConverter, * as that is where the reader reads from. */ std::string output_folder("TestHdf5Converters_TestBidomainMeshalyzerConversion"); CopyToTestOutputDirectory("heart/test/data/Bidomain1d/bidomain.h5", output_folder); TrianglesMeshReader<1,1> mesh_reader("mesh/test/data/1D_0_to_1_100_elements"); TetrahedralMesh<1,1> mesh; mesh.ConstructFromMeshReader(mesh_reader); // Convert Hdf5ToMeshalyzerConverter<1,1> converter(FileFinder(output_folder, RelativeTo::ChasteTestOutput), "bidomain", &mesh, true); // Compare the voltage file std::string test_output_directory = OutputFileHandler::GetChasteTestOutputDirectory(); FileComparison(test_output_directory + output_folder + "/output/bidomain_V.dat", "heart/test/data/Bidomain1d/bidomain_V.dat").CompareFiles(); // Compare the Phi_e file FileComparison(test_output_directory + output_folder + "/output/bidomain_Phi_e.dat", "heart/test/data/Bidomain1d/bidomain_Phi_e.dat").CompareFiles(); // Compare the time information file FileComparison(test_output_directory + output_folder + "/output/bidomain_times.info", "heart/test/data/Bidomain1d/bidomain_times.info").CompareFiles(); }
void TestXaxisRotation3DWithHomogeneousUblas() { TrianglesMeshReader<3,3> mesh_reader("mesh/test/data/cube_136_elements"); TetrahedralMesh<3,3> mesh; mesh.ConstructFromMeshReader(mesh_reader); TS_ASSERT_DELTA(mesh.GetVolume(), 1.0, 1e-6); TS_ASSERT_DELTA(mesh.GetSurfaceArea(), 6.0, 1e-6); // Change coordinates c_matrix<double, 4, 4> x_rotation_matrix = identity_matrix<double>(4); double theta = M_PI/2; x_rotation_matrix(1,1) = cos(theta); x_rotation_matrix(1,2) = sin(theta); x_rotation_matrix(2,1) = -sin(theta); x_rotation_matrix(2,2) = cos(theta); ChastePoint<3> corner_before = mesh.GetNode(6)->GetPoint(); TS_ASSERT_EQUALS(corner_before[0], 1.0); TS_ASSERT_EQUALS(corner_before[1], 1.0); TS_ASSERT_EQUALS(corner_before[2], 1.0); for (unsigned i=0; i<mesh.GetNumNodes(); i++) { Node<3>* p_node = mesh.GetNode(i); ChastePoint<3> point = p_node->GetPoint(); c_vector<double, 4> point_location; point_location[0] = point[0]; point_location[1] = point[1]; point_location[2] = point[2]; point_location[3] = 1.0; c_vector<double, 4> new_point_location = prod(x_rotation_matrix, point_location); TS_ASSERT_EQUALS(new_point_location[3], 1.0); point.SetCoordinate(0, new_point_location[0]); point.SetCoordinate(1, new_point_location[1]); point.SetCoordinate(2, new_point_location[2]); p_node->SetPoint(point); } ChastePoint<3> corner_after = mesh.GetNode(6)->GetPoint(); TS_ASSERT_EQUALS(corner_after[0], 1.0); TS_ASSERT_EQUALS(corner_after[1], 1.0); TS_ASSERT_DELTA(corner_after[2], -1.0, 1e-7); mesh.RefreshMesh(); TS_ASSERT_DELTA(mesh.GetVolume(), 1.0, 1e-6); TS_ASSERT_DELTA(mesh.GetSurfaceArea(), 6.0, 1e-6); }
void TestExceptions() { TrianglesMeshReader<1,1> mesh_reader("mesh/test/data/1D_0_to_10_100_elements"); TetrahedralMesh<1,1> mesh; mesh.ConstructFromMeshReader(mesh_reader); TS_ASSERT_THROWS_THIS(mesh.RotateZ(1.4),"This rotation is not valid in less than 2D"); TS_ASSERT_THROWS_THIS(mesh.RotateY(0.3),"This rotation is only valid in 3D"); TS_ASSERT_THROWS_THIS(mesh.RotateX(0.7),"This rotation is only valid in 3D"); }
void TestBathIntracellularStimulation() throw (Exception) { HeartConfig::Instance()->SetSimulationDuration(10.0); //ms HeartConfig::Instance()->SetOutputDirectory("BidomainBath1d"); HeartConfig::Instance()->SetOutputFilenamePrefix("bidomain_bath_1d"); c_vector<double,1> centre; centre(0) = 0.5; BathCellFactory<1> cell_factory(-1e6, centre); // stimulates x=0.5 node BidomainWithBathProblem<1> bidomain_problem( &cell_factory ); TrianglesMeshReader<1,1> reader("mesh/test/data/1D_0_to_1_100_elements"); TetrahedralMesh<1,1> mesh; mesh.ConstructFromMeshReader(reader); // set the x<0.25 and x>0.75 regions as the bath region for(unsigned i=0; i<mesh.GetNumElements(); i++) { double x = mesh.GetElement(i)->CalculateCentroid()[0]; if( (x<0.25) || (x>0.75) ) { mesh.GetElement(i)->SetAttribute(HeartRegionCode::GetValidBathId()); } } bidomain_problem.SetMesh(&mesh); bidomain_problem.Initialise(); bidomain_problem.Solve(); Vec sol = bidomain_problem.GetSolution(); ReplicatableVector sol_repl(sol); // test V = 0 for all bath nodes for(unsigned i=0; i<mesh.GetNumNodes(); i++) { if(HeartRegionCode::IsRegionBath( mesh.GetNode(i)->GetRegion() )) // bath { TS_ASSERT_DELTA(sol_repl[2*i], 0.0, 1e-12); } } // test symmetry of V and phi_e for(unsigned i=0; i<=(mesh.GetNumNodes()-1)/2; i++) { unsigned opposite = mesh.GetNumNodes()-i-1; TS_ASSERT_DELTA(sol_repl[2*i], sol_repl[2*opposite], 2e-3); // V TS_ASSERT_DELTA(sol_repl[2*i+1], sol_repl[2*opposite+1], 2e-3); // phi_e } // a couple of hardcoded values TS_ASSERT_DELTA(sol_repl[2*50], 3.7684, 1e-3); TS_ASSERT_DELTA(sol_repl[2*70], 5.1777, 1e-3); }
/** * Simple Parabolic PDE u' = del squared u * * With u = 0 on the boundaries of the unit cube. Subject to the initial * condition u(0,x,y,z)=sin( PI x)sin( PI y)sin( PI z). */ void TestSimpleLinearParabolicSolver3DZeroDirich() { // read mesh on [0,1]x[0,1]x[0,1] TrianglesMeshReader<3,3> mesh_reader("mesh/test/data/cube_136_elements"); TetrahedralMesh<3,3> mesh; mesh.ConstructFromMeshReader(mesh_reader); // Instantiate PDE object HeatEquation<3> pde; // Boundary conditions - zero dirichlet everywhere on boundary BoundaryConditionsContainer<3,3,1> bcc; bcc.DefineZeroDirichletOnMeshBoundary(&mesh); // Solver SimpleLinearParabolicSolver<3,3> solver(&mesh,&pde,&bcc); /* * Choose initial condition sin(x*pi)*sin(y*pi)*sin(z*pi) as * this is an eigenfunction of the heat equation. */ std::vector<double> init_cond(mesh.GetNumNodes()); for (unsigned i=0; i<mesh.GetNumNodes(); i++) { double x = mesh.GetNode(i)->GetPoint()[0]; double y = mesh.GetNode(i)->GetPoint()[1]; double z = mesh.GetNode(i)->GetPoint()[2]; init_cond[i] = sin(x*M_PI)*sin(y*M_PI)*sin(z*M_PI); } Vec initial_condition = PetscTools::CreateVec(init_cond); double t_end = 0.1; solver.SetTimes(0, t_end); solver.SetTimeStep(0.001); solver.SetInitialCondition(initial_condition); Vec result = solver.Solve(); ReplicatableVector result_repl(result); // Check solution is u = e^{-3*t*pi*pi} sin(x*pi)*sin(y*pi)*sin(z*pi), t=0.1 for (unsigned i=0; i<result_repl.GetSize(); i++) { double x = mesh.GetNode(i)->GetPoint()[0]; double y = mesh.GetNode(i)->GetPoint()[1]; double z = mesh.GetNode(i)->GetPoint()[2]; double u = exp(-3*t_end*M_PI*M_PI)*sin(x*M_PI)*sin(y*M_PI)*sin(z*M_PI); TS_ASSERT_DELTA(result_repl[i], u, 0.1); } PetscTools::Destroy(initial_condition); PetscTools::Destroy(result); }
void TestReadMeshes(void) throw(Exception) { { READER_2D reader("mesh/test/data/square_4_elements_gmsh.msh"); TetrahedralMesh<2,2> mesh; mesh.ConstructFromMeshReader(reader); TS_ASSERT_EQUALS(mesh.GetNumNodes(), 5u); TS_ASSERT_EQUALS(mesh.GetNumElements(), 4u); TS_ASSERT_EQUALS(mesh.GetNumBoundaryElements(), 4u); } { READER_3D reader("mesh/test/data/simple_cube_gmsh.msh"); TetrahedralMesh<3,3> mesh; mesh.ConstructFromMeshReader(reader); TS_ASSERT_EQUALS(mesh.GetNumNodes(), 14u); TS_ASSERT_EQUALS(mesh.GetNumElements(), 24u); TS_ASSERT_EQUALS(mesh.GetNumBoundaryElements(), 24u); } { READER_2D reader("mesh/test/data/quad_square_4_elements_gmsh.msh",2,2); QuadraticMesh<2> mesh; mesh.ConstructFromMeshReader(reader); TS_ASSERT_EQUALS(mesh.GetNumNodes(), 13u); TS_ASSERT_EQUALS(mesh.GetNumElements(), 4u); TS_ASSERT_EQUALS(mesh.GetNumBoundaryElements(), 4u); } { READER_3D reader("mesh/test/data/quad_cube_gmsh.msh",2,2); QuadraticMesh<3> mesh; mesh.ConstructFromMeshReader(reader); TS_ASSERT_EQUALS(mesh.GetNumNodes(), 63u); TS_ASSERT_EQUALS(mesh.GetNumElements(), 24u); TS_ASSERT_EQUALS(mesh.GetNumBoundaryElements(), 24u); } }
void TestDistancesToFaceDumb() { 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); TS_ASSERT_EQUALS(mesh.GetNumNodes(), 9261u); // 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(), 9261u); // 21x21x21 nodes TS_ASSERT_EQUALS(parallel_mesh.GetNumElements(), 48000u); TS_ASSERT_EQUALS(parallel_mesh.GetNumBoundaryElements(), 4800u); std::vector<unsigned> map_left; for (unsigned index=0; index<mesh.GetNumNodes(); index++) { // Get the nodes at the left face of the cube if (mesh.GetNode(index)->rGetLocation()[0] + 0.25 < 1e-6) { map_left.push_back(index); } } TS_ASSERT_EQUALS(map_left.size(), 21u*21u); DistanceMapCalculator<3,3> distance_calculator(mesh); std::vector<double> distances; distance_calculator.ComputeDistanceMap(map_left, distances); DistanceMapCalculator<3,3> parallel_distance_calculator(parallel_mesh); std::vector<double> parallel_distances; parallel_distance_calculator.ComputeDistanceMap(map_left, parallel_distances); TS_ASSERT_EQUALS(distance_calculator.mRoundCounter, 1u); TS_ASSERT_DELTA(parallel_distance_calculator.mRoundCounter, 2u, 1u);// 1 2 or 3 for (unsigned index=0; index<distances.size(); index++) { // The distance should be equal to the x-coordinate of the point (minus the offset of the left face of the cube) c_vector<double, 3> node = mesh.GetNode(index)->rGetLocation(); TS_ASSERT_DELTA(distances[index], node[0]+0.25,1e-11); TS_ASSERT_DELTA(parallel_distances[index], node[0]+0.25,1e-11); } }
void TestRemeshSingleBranch() throw(Exception) { //Load a single branch mesh file TrianglesMeshReader<1,3> reader("mesh/test/data/1D_in_3D_0_to_1mm_10_elements"); TetrahedralMesh<1,3> mesh; mesh.ConstructFromMeshReader(reader); //We need to add some attributes to the mesh for (TetrahedralMesh<1,3>::NodeIterator iter = mesh.GetNodeIteratorBegin(); iter != mesh.GetNodeIteratorEnd(); ++iter) { iter->AddNodeAttribute(0.05); } //Create remesher object AirwayRemesher remesher(mesh, 0u); //Check intermediate elements are removed. Poiseuille resistance of the branch is // C*0.1/((0.05^4) = C*1.6 * 10^4 MutableMesh<1,3> output_mesh_one; remesher.Remesh(output_mesh_one, 1e5); //With this tolerance all intermediate nodes should be removed. TS_ASSERT_EQUALS(output_mesh_one.GetNumNodes(), 2u); TS_ASSERT_EQUALS(output_mesh_one.GetNumElements(), 1u); TS_ASSERT_DELTA(output_mesh_one.GetElement(0)->GetAttribute(), 0.05, 1e-6); MutableMesh<1,3> output_mesh_two; remesher.Remesh(output_mesh_two, 0.8e4); //With this tolerance there should be one intermediate node. TS_ASSERT_EQUALS(output_mesh_two.GetNumNodes(), 3u); TS_ASSERT_EQUALS(output_mesh_two.GetNumElements(), 2u); TS_ASSERT_DELTA(output_mesh_two.GetElement(0)->GetAttribute(), 0.05, 1e-6); MutableMesh<1,3> output_mesh_three; remesher.Remesh(output_mesh_three, 1.6e3); //With this tolerance there should be ten elements. TS_ASSERT_EQUALS(output_mesh_three.GetNumNodes(), 11u); TS_ASSERT_EQUALS(output_mesh_three.GetNumElements(), 10u); TS_ASSERT_DELTA(output_mesh_three.GetElement(0)->GetAttribute(), 0.05, 1e-6); TS_ASSERT_DELTA(output_mesh_three.GetElement(5)->GetAttribute(), 0.05, 1e-6); //To visualise //VtkMeshWriter<1,3> writer("TestAirwayRemesher", "1D_remeshed"); //writer.WriteFilesUsingMesh(output_mesh_three); }
void TestElementReactanceAndInertance() { TetrahedralMesh<1,3> mesh; TrianglesMeshReader<1,3> mesh_reader("mesh/test/data/y_branch_3d_mesh"); mesh.ConstructFromMeshReader(mesh_reader); SimpleImpedanceProblem problem(mesh, 0u); problem.SetRho(M_PI); problem.SetMu(M_PI); double l = 2.0; double r = 2.0; TS_ASSERT_DELTA(problem.CalculateElementResistance(r, l), 8*l/(r*r*r*r), 1e-6); TS_ASSERT_DELTA(problem.CalculateElementInertance(r, l), l/(r*r), 1e-6); }
void TestZaxisRotation3DWithMethod() { TrianglesMeshReader<3,3> mesh_reader("mesh/test/data/cube_136_elements"); TetrahedralMesh<3,3> mesh; mesh.ConstructFromMeshReader(mesh_reader); double mesh_volume = mesh.GetVolume(); mesh.RotateZ(M_PI/2.0); double new_mesh_volume = mesh.GetVolume(); TS_ASSERT_DELTA(mesh_volume, new_mesh_volume, 1e-6); ChastePoint<3> corner_after = mesh.GetNode(6)->GetPoint(); TS_ASSERT_DELTA(corner_after[0], 1.0, 1e-7); TS_ASSERT_DELTA(corner_after[1], -1.0, 1e-7); TS_ASSERT_DELTA(corner_after[2], 1.0, 1e-7); }
void TestMultipleFrequencies() throw(Exception) { TetrahedralMesh<1,3> mesh; //TrianglesMeshReader<1,3> mesh_reader("mesh/test/data/y_branch_3d_mesh"); TrianglesMeshReader<1,3> mesh_reader("lung/test/data/TestSubject002"); mesh.ConstructFromMeshReader(mesh_reader); //Scale all radii by 0.7 to give an FRC equivalent lung for (TetrahedralMesh<1,3>::NodeIterator node_iter = mesh.GetNodeIteratorBegin(); node_iter != mesh.GetNodeIteratorEnd(); ++node_iter) { node_iter->rGetNodeAttributes()[0] *= 0.7; } std::vector<double> test_frequencies; test_frequencies.push_back(1.0); test_frequencies.push_back(2.0); test_frequencies.push_back(3.0); test_frequencies.push_back(5.0); test_frequencies.push_back(10.0); test_frequencies.push_back(20.0); test_frequencies.push_back(30.0); SimpleImpedanceProblem problem(mesh, 0u); problem.SetMeshInMilliMetres(); problem.SetFrequencies(test_frequencies); //Set & get frequencies for coverage std::vector<double>& freqs = problem.rGetFrequencies(); TS_ASSERT_EQUALS(freqs.size(), 7u); problem.Solve(); std::vector<std::complex<double> > impedances = problem.rGetImpedances(); TS_ASSERT_EQUALS(impedances.size(), 7u); //These are hard coded from previous runs, but are as expected for //a patient with moderate to severe asthma TS_ASSERT_DELTA(real(impedances[0])*1e-3/98, 8.45, 1e-2); TS_ASSERT_DELTA(imag(impedances[0])*1e-3/98, -3.65, 1e-2); TS_ASSERT_DELTA(real(impedances[6])*1e-3/98, 5.77, 1e-2); TS_ASSERT_DELTA(imag(impedances[6])*1e-3/98, 4.12, 1e-2); }
void TestAcinarImpedance() throw(Exception) { TetrahedralMesh<1,3> mesh; TrianglesMeshReader<1,3> mesh_reader("mesh/test/data/y_branch_3d_mesh"); mesh.ConstructFromMeshReader(mesh_reader); TS_ASSERT_THROWS_CONTAINS(SimpleImpedanceProblem(mesh, 1u), "Outlet node is not a boundary node"); SimpleImpedanceProblem problem(mesh, 0u); problem.rGetMesh(); //for coverage unsigned node_index = 3; //Arbitrary terminal node problem.SetElastance(2*M_PI/2.0); TS_ASSERT_DELTA(real(problem.CalculateAcinusImpedance(mesh.GetNode(node_index), 0.0)), 0.0, 1e-6); TS_ASSERT_DELTA(real(problem.CalculateAcinusImpedance(mesh.GetNode(node_index), 1.0)), 0.0, 1e-6); TS_ASSERT_DELTA(imag(problem.CalculateAcinusImpedance(mesh.GetNode(node_index), 1.0)), -1.0, 1e-6); }
void TestGetSingleRadiusVector(void) throw(Exception) { TrianglesMeshReader<3,3> mesh_reader("mesh/test/data/simple_cube"); TetrahedralMesh<3,3> mesh; mesh.ConstructFromMeshReader(mesh_reader); TS_ASSERT_EQUALS(mesh.GetNumElements(),12u); PapillaryFibreCalculator calculator(mesh); // Call GetRadiusVectors on an element unsigned element_index = 0; c_vector<double, 3> radius_vector = calculator.GetRadiusVectorForOneElement(element_index); // Check they are right TS_ASSERT_DELTA(radius_vector[0], -0.275, 1e-9); TS_ASSERT_DELTA(radius_vector[1], -0.025, 1e-9); TS_ASSERT_DELTA(radius_vector[2], -0.275, 1e-9); }
void Test3DMeshTranslationWithUblasMethod() { TrianglesMeshReader<3,3> mesh_reader("mesh/test/data/cube_136_elements"); TetrahedralMesh<3,3> mesh; mesh.ConstructFromMeshReader(mesh_reader); // Translations - add a constant vector to each node c_vector<double,3> displacement; displacement(0) = 1; displacement(1) = 1; displacement(2) = 1; // Translate the mesh along the vector displacement mesh.Translate(displacement); TetrahedralMesh<3,3> original_mesh; original_mesh.ConstructFromMeshReader(mesh_reader); for (unsigned i=0; i<mesh.GetNumNodes(); i++) { // Find new coordinates of the translated node Node<3>* p_node = mesh.GetNode(i); ChastePoint<3> new_coordinate = p_node->GetPoint(); // Get original node Node<3>* p_original_node = original_mesh.GetNode(i); ChastePoint<3> original_coordinate = p_original_node->GetPoint(); // Run a test to make sure the node has gone to the correct place TS_ASSERT_DELTA(original_coordinate[0] + displacement[0], new_coordinate[0], 1e-5); TS_ASSERT_DELTA(original_coordinate[1] + displacement[1], new_coordinate[1], 1e-5); TS_ASSERT_DELTA(original_coordinate[2] + displacement[2], new_coordinate[2], 1e-5); } // Check volume conservation double mesh_volume = mesh.GetVolume(); double original_mesh_volume = original_mesh.GetVolume(); TS_ASSERT_DELTA(mesh_volume, original_mesh_volume, 1e-5); }
void TestProblemChecksUsingBathWithMultipleBathConductivities() { TrianglesMeshReader<2,2> reader("mesh/test/data/2D_0_to_1mm_400_elements"); TetrahedralMesh<2,2> mesh; mesh.ConstructFromMeshReader(reader); std::set<unsigned> tissue_ids; tissue_ids.insert(0); std::set<unsigned> bath_ids; bath_ids.insert(1); bath_ids.insert(2); // non-default identifier! HeartConfig::Instance()->SetTissueAndBathIdentifiers(tissue_ids, bath_ids); BathCellFactory<2> cell_factory( 0.0, Create_c_vector(0.0, 0.0) ); BidomainProblem<2> bidomain_problem( &cell_factory ); // non-bath problem, despite specifying bath stuff above! bidomain_problem.SetMesh( &mesh ); TS_ASSERT_THROWS_THIS( bidomain_problem.Initialise() , "User has set bath identifiers, but the BidomainProblem isn't expecting a bath. Did you mean to use BidomainProblem(..., true)? Or alternatively, BidomainWithBathProblem(...)?"); }
void TestGeneralConvolution3DWithMethod() { TrianglesMeshReader<3,3> mesh_reader("mesh/test/data/cube_136_elements"); TetrahedralMesh<3,3> mesh; mesh.ConstructFromMeshReader(mesh_reader); double mesh_volume = mesh.GetVolume(); mesh.Translate(2.3, 3.1, 1.7); mesh.RotateZ(1.4); mesh.RotateY(0.3); mesh.RotateX(0.7); double new_mesh_volume = mesh.GetVolume(); TS_ASSERT_DELTA(mesh_volume, new_mesh_volume, 1e-6); ChastePoint<3> corner_after = mesh.GetNode(6)->GetPoint(); TS_ASSERT_DELTA(corner_after[0], 3.59782, 5e-5); TS_ASSERT_DELTA(corner_after[1], 0.583418, 5e-5); TS_ASSERT_DELTA(corner_after[2], 4.65889, 5e-5); }
void TestDefineZeroDirichletOnMeshBoundary() { // Load a 2D square mesh with 1 central non-boundary node TrianglesMeshReader<2,2> mesh_reader("mesh/test/data/square_4_elements"); TetrahedralMesh<2,2> mesh; mesh.ConstructFromMeshReader(mesh_reader); BoundaryConditionsContainer<2,2,1> bcc; bcc.DefineZeroDirichletOnMeshBoundary(&mesh); // Check boundary nodes have the right condition for (int i=0; i<4; i++) { double value = bcc.GetDirichletBCValue(mesh.GetNode(i)); TS_ASSERT_DELTA(value, 0.0, 1e-12); } // Check non-boundary node has no condition TS_ASSERT(!bcc.HasDirichletBoundaryCondition(mesh.GetNode(4))); }
// This test covers the case when the hdf5 file contains more than 3 variables void TestMeshalyzerConversionLotsOfVariables() throw(Exception) { std::string output_dir = "TestHdf5Converters_TestMeshalyzerConversionLotsOfVariables"; /* * Firstly, copy the .h5 file to CHASTE_TEST_OUTPUT/TestHdf5ToMeshalyzerConverter, * as that is where the reader reads from. */ CopyToTestOutputDirectory("heart/test/data/many_variables/many_variables.h5", output_dir); TrianglesMeshReader<1,1> mesh_reader("heart/test/data/many_variables/1D_65_elements"); TetrahedralMesh<1,1> mesh; mesh.ConstructFromMeshReader(mesh_reader); // Convert Hdf5ToMeshalyzerConverter<1,1> converter(FileFinder(output_dir, RelativeTo::ChasteTestOutput), "many_variables", &mesh, true); std::vector<std::string> variable_names; variable_names.push_back("V"); variable_names.push_back("I_ks"); variable_names.push_back("I_kr"); variable_names.push_back("I_Ca_tot"); variable_names.push_back("I_tot"); variable_names.push_back("I_Na_tot"); std::string test_output_directory = OutputFileHandler::GetChasteTestOutputDirectory(); for (unsigned i=0; i<variable_names.size(); i++) { // Compare the results files FileComparison(test_output_directory + "/" + output_dir + "/output/many_variables_" + variable_names[i] + ".dat", "heart/test/data/many_variables/many_variables_" + variable_names[i] + ".dat").CompareFiles(); } // Compare the time information file FileComparison(test_output_directory + output_dir + "/output/many_variables_times.info", "heart/test/data/many_variables/many_variables_times.info").CompareFiles(); }
void Test3DAngleAxisRotation() { TrianglesMeshReader<3,3> mesh_reader("mesh/test/data/cube_136_elements"); TetrahedralMesh<3,3> mesh; mesh.ConstructFromMeshReader(mesh_reader); c_vector<double,3> axis; axis(0) = 1; axis(1) = 0; axis(2) = 0; double angle = M_PI; mesh.Rotate(axis, angle); TetrahedralMesh<3,3> original_mesh; original_mesh.ConstructFromMeshReader(mesh_reader); for (unsigned i=0; i<mesh.GetNumNodes(); i++) { Node<3>* p_node = mesh.GetNode(i); ChastePoint<3> new_coordinate = p_node->GetPoint(); // Get original node Node<3>* p_original_node = original_mesh.GetNode(i); ChastePoint<3> original_coordinate = p_original_node->GetPoint(); // Run a test to make sure the node has gone to the correct place TS_ASSERT_DELTA(original_coordinate[0], new_coordinate[0], 1e-5); TS_ASSERT_DELTA(original_coordinate[1], -new_coordinate[1], 1e-5); TS_ASSERT_DELTA(original_coordinate[2], -new_coordinate[2], 1e-5); } // Check volume conservation double mesh_volume = mesh.GetVolume(); double original_mesh_volume = original_mesh.GetVolume(); TS_ASSERT_DELTA(mesh_volume, original_mesh_volume, 1e-5); }