/** * Check that the elements are read correctly. Checks that the output vector * for a given input file is the correct length and that if the input file * is corrupted (missing elements) then an exception is thrown. */ void TestElementsDataRead() throw(Exception) { TrianglesMeshReader<2,2> mesh_reader("mesh/test/data/disk_984_elements_indexed_from_1"); TS_ASSERT_EQUALS( mesh_reader.GetNumElements(), 984u); ElementData data1 = mesh_reader.GetNextElementData(); TS_ASSERT_EQUALS(data1.NodeIndices.size(), 3u); TS_ASSERT_EQUALS(data1.NodeIndices[0], 309u); TS_ASSERT_EQUALS(data1.NodeIndices[1], 144u); TS_ASSERT_EQUALS(data1.NodeIndices[2], 310u); TS_ASSERT_EQUALS( mesh_reader.GetNumElementAttributes(), 0u); for (unsigned i=1; i<mesh_reader.GetNumElements(); i++) { ElementData data = mesh_reader.GetNextElementData(); TS_ASSERT_EQUALS(data.AttributeValue, 0u); } TrianglesMeshReader<2,2> mesh_reader2("mesh/test/data/baddata/bad_elements_disk_522_elements"); // Reads element 0 from file TS_ASSERT_THROWS_NOTHING(mesh_reader2.GetNextElementData()); // Reads element 2 from file when expecting number 1 TS_ASSERT_THROWS_THIS(mesh_reader2.GetNextElementData(),"Data for item 1 missing"); }
void TestRemoveDeadCellsAndUpdate() throw(Exception) { // Create a simple 2D PottsMesh PottsMeshGenerator<2> generator(4, 2, 2, 4, 2, 2); PottsMesh<2>* p_mesh = generator.GetMesh(); // Create cells std::vector<CellPtr> cells; CellsGenerator<FixedDurationGenerationBasedCellCycleModel, 2> cells_generator; cells_generator.GenerateBasic(cells, p_mesh->GetNumElements()); // Create cell population PottsBasedCellPopulation<2> cell_population(*p_mesh, cells); // Test RemoveDeadCells() method TS_ASSERT_EQUALS(cell_population.GetNumElements(), 4u); cell_population.Begin()->Kill(); TS_ASSERT_EQUALS(cell_population.RemoveDeadCells(), 1u); TS_ASSERT_EQUALS(cell_population.GetNumElements(), 3u); TS_ASSERT_EQUALS(p_mesh->GetNumElements(), 3u); TS_ASSERT_EQUALS(p_mesh->GetNumAllElements(), 4u); // Test that Update() throws no errors TS_ASSERT_THROWS_NOTHING(cell_population.Update()); }
/** * Check that GetNextNode() returns the coordinates of the correct node and the correct node attributes. * Compares the coordinates of the first two nodes with their known * values, checks that no errors are thrown for the remaining nodes and * that an error is thrown if we try to call the function too many times. */ void TestGetNextNode() throw(Exception) { TrianglesMeshReader<2,2> mesh_reader("mesh/test/data/disk_984_elements"); std::vector<double> first_node; first_node = mesh_reader.GetNextNode(); TS_ASSERT_DELTA(first_node[0], 0.9980267283, 1e-6); TS_ASSERT_DELTA(first_node[1], -0.0627905195, 1e-6); // This mesh has zero attributes and one marker in the node file (as the header specifies). // we have to ensure that in such situation the last number in each node line is not mistakenly // read and interpreted as a node attribute (it is a node marker instead). TS_ASSERT_EQUALS(mesh_reader.GetNodeAttributes().size(), 0u); std::vector<double> next_node; next_node = mesh_reader.GetNextNode(); TS_ASSERT_DELTA(next_node[0], 1.0, 1e-6); TS_ASSERT_DELTA(next_node[1], 0.0, 1e-6); for (int i=0; i<541; i++) { TS_ASSERT_THROWS_NOTHING(next_node = mesh_reader.GetNextNode()); } TS_ASSERT_EQUALS(mesh_reader.GetNodeAttributes().size(), 0u); TS_ASSERT_THROWS_THIS(next_node = mesh_reader.GetNextNode(), "File contains incomplete data: unexpected end of file."); }
void TestCheckForBathElementsNoDeadlock() throw (Exception) { HeartConfig::Instance()->SetSimulationDuration(1.0); //ms HeartConfig::Instance()->SetOutputDirectory("bidomain_bath"); HeartConfig::Instance()->SetOutputFilenamePrefix("BidomainLR91_1d"); PlaneStimulusCellFactory<CellLuoRudy1991FromCellML, 1> bidomain_cell_factory; BidomainWithBathProblem<1> bidomain_problem( &bidomain_cell_factory ); TrianglesMeshReader<1,1> reader("mesh/test/data/1D_0_to_1_100_elements"); DistributedTetrahedralMesh<1,1> mesh; mesh.ConstructFromMeshReader(reader); try { mesh.GetElement(0)->SetAttribute(HeartRegionCode::GetValidBathId()); } catch(Exception&) { // I don't own element 0 } bidomain_problem.SetMesh(&mesh); // Fails because no bath TS_ASSERT_THROWS_NOTHING(bidomain_problem.Initialise()); // Prevent an EventHandling exception in later tests HeartEventHandler::EndEvent(HeartEventHandler::EVERYTHING); }
void TestAllCases() { TrianglesMeshReader<2,2> mesh_reader("mesh/test/data/square_2_elements"); MutableMesh<2,2> mesh; mesh.ConstructFromMeshReader(mesh_reader); TS_ASSERT_DELTA(mesh.GetAngleBetweenNodes(2,0), -0.75*M_PI, 1e-12); TS_ASSERT_DELTA(mesh.GetAngleBetweenNodes(2,1), -0.5*M_PI, 1e-12); CellsGenerator<FixedG1GenerationalCellCycleModel, 2> cells_generator; std::vector<CellPtr> cells; cells_generator.GenerateBasic(cells, mesh.GetNumNodes()); MeshBasedCellPopulation<2> cell_population(mesh, cells); MAKE_PTR(GeneralisedLinearSpringForce<2>, p_force); std::vector<boost::shared_ptr<AbstractTwoBodyInteractionForce<2> > > force_collection; force_collection.push_back(p_force); DiscreteSystemForceCalculator calculator(cell_population, force_collection); double epsilon = 0.5*M_PI; calculator.SetEpsilon(epsilon); TS_ASSERT_THROWS_NOTHING(calculator.GetSamplingAngles(2)); }
void TestMeshWriterWithDeletedNode() throw (Exception) { // Create mesh VertexMeshReader<2,2> mesh_reader("mesh/test/data/TestVertexMesh/honeycomb_vertex_mesh_3_by_3"); MutableVertexMesh<2,2> mesh; mesh.ConstructFromMeshReader(mesh_reader); TS_ASSERT_EQUALS(mesh.GetNumNodes(), 30u); TS_ASSERT_EQUALS(mesh.GetNumElements(), 9u); /* * Delete element 0. This element contains 3 nodes that are * not contained in any other element and so will be marked * as deleted. */ mesh.DeleteElementPriorToReMesh(0); // Write mesh to file VertexMeshWriter<2,2> mesh_writer("TestMeshWriterWithDeletedNode", "vertex_mesh"); TS_ASSERT_THROWS_NOTHING(mesh_writer.WriteFilesUsingMesh(mesh)); // Read mesh back in from file std::string output_dir = mesh_writer.GetOutputDirectory(); VertexMeshReader<2,2> mesh_reader2(output_dir + "vertex_mesh"); // We should have one less element and three less nodes TS_ASSERT_EQUALS(mesh_reader2.GetNumNodes(), 27u); TS_ASSERT_EQUALS(mesh_reader2.GetNumElements(), 8u); }
void TestPottsMonolayerWithNonRandomSweep() throw (Exception) { EXIT_IF_PARALLEL; // Potts simulations don't work in parallel because they depend on NodesOnlyMesh for writing. // Create a simple 2D PottsMesh PottsMeshGenerator<2> generator(6, 2, 2, 6, 2, 2); PottsMesh<2>* p_mesh = generator.GetMesh(); // Create cells std::vector<CellPtr> cells; MAKE_PTR(DifferentiatedCellProliferativeType, p_diff_type); CellsGenerator<FixedDurationGenerationBasedCellCycleModel, 2> cells_generator; cells_generator.GenerateBasicRandom(cells, p_mesh->GetNumElements(), p_diff_type); // Create cell population PottsBasedCellPopulation<2> cell_population(*p_mesh, cells); cell_population.SetUpdateNodesInRandomOrder(false); // Set up cell-based simulation OnLatticeSimulation<2> simulator(cell_population); simulator.SetOutputDirectory("TestSimplePottsMonolayerWithRandomSweep"); simulator.SetEndTime(0.1); // Create update rules and pass to the simulation MAKE_PTR(VolumeConstraintPottsUpdateRule<2>, p_volume_constraint_update_rule); simulator.AddPottsUpdateRule(p_volume_constraint_update_rule); MAKE_PTR(AdhesionPottsUpdateRule<2>, p_adhesion_update_rule); simulator.AddPottsUpdateRule(p_adhesion_update_rule); // Run simulation TS_ASSERT_THROWS_NOTHING(simulator.Solve()); }
void TestPetscExceptions() { /* * Note we could test with TS_ASSERT_THROWS_THIS() but PetscException * includes line numbers so it isn't very robust. */ int err = 0; TS_ASSERT_THROWS_NOTHING(PETSCEXCEPT(err)); Vec v; err = VecCreateMPI(PETSC_COMM_WORLD, 2, 1, &v); PetscTools::Destroy(v); //#define PETSC_ERR_ARG_WRONGSTATE 73 /* object in argument is in wrong */ //#define PETSC_ERR_ARG_INCOMP 75 /* two arguments are incompatible */ TS_ASSERT_EQUALS(err, PETSC_ERR_ARG_INCOMP); TS_ASSERT_THROWS(PETSCEXCEPT(err), Exception); err=PETSC_ERR_FILE_OPEN; //#define PETSC_ERR_FILE_OPEN 65 /* unable to open file */ TS_ASSERT_EQUALS(err, PETSC_ERR_FILE_OPEN); TS_ASSERT_THROWS(PETSCEXCEPT(err), Exception); // See if we can do it without a temporary TS_ASSERT_THROWS( PETSCEXCEPT(VecCreateMPI(PETSC_COMM_WORLD, 2, 1, &v)), Exception); PetscTools::Destroy(v); // This test give back an "unknown error" message TS_ASSERT_THROWS( PETSCEXCEPT(-3), Exception); }
void TestAirplaneConstruction() { // 100 - number of seats; 500.0 fuel tank capacity Airplane airplane(201, 500.0); TS_ASSERT_EQUALS(airplane.getFuel(), 0); TS_ASSERT_EQUALS(airplane.getNumberOfPassengers(), 0); TS_ASSERT_EQUALS(airplane.getNumberOfSeats(), 100); TS_ASSERT_EQUALS(airplane.getNumberOfPilots(), 0); TS_ASSERT_EQUALS(airplane.getNumberOfStewardess(), 0); TS_ASSERT_EQUALS(airplane.getFuelTankCapacity(), 500.0); for (size_t seats = 0; seats <= 300; ++seats) { if ((seats >= 10) && (seats <= 200)) { TS_ASSERT_THROWS_NOTHING(Airplane plane(seats, 500)); } else { TS_ASSERT_THROWS(Airplane plane(seats, 500), std::invalid_argument); } } // 50 - number of seats Airplane airplane1(50, 100.0); TS_ASSERT_EQUALS(airplane1.getNumberOfSeats(), 50); TS_ASSERT_EQUALS(airplane1.getFuelTankCapacity(), 100.0); }
void test_DerivedClass() { std::ofstream ofs("archive.txt"); TS_ASSERT(ofs.is_open()); s11n::TextOutArchive ar(ofs); DerivedClass d; TS_ASSERT_THROWS_NOTHING(ar & TAG(d)); }
/** * Check that GetNextEdgeData() works. Checks that no errors are thrown for * all of the edges and that an error is thrown if we try to call the * function too many times. */ void TestGetNextEdgeData() throw(Exception) { TrianglesMeshReader<2,2> mesh_reader("mesh/test/data/disk_984_elements"); std::vector<unsigned> next_edge; TS_ASSERT_THROWS_NOTHING(next_edge = mesh_reader.GetNextFaceData().NodeIndices); TS_ASSERT_THROWS_NOTHING(next_edge = mesh_reader.GetNextFaceData().NodeIndices); for (unsigned i=2; i<mesh_reader.GetNumEdges(); i++) { TS_ASSERT_THROWS_NOTHING(next_edge = mesh_reader.GetNextEdgeData().NodeIndices); } TS_ASSERT_THROWS_THIS(next_edge = mesh_reader.GetNextEdgeData().NodeIndices, "File contains incomplete data: unexpected end of file."); }
void TestHandleHighOrderJunctions() throw (Exception) { /* * We test the method HandleHighOrderJunctions by calling IdentifySwapType on a mesh with suitable nodes, * i.e. when at least one node is contained in more than three elements. */ // Make an empty mesh MutableVertexMesh<2,2> mesh; // Add 6 nodes, three each for two triangular elements mesh.AddNode(new Node<2>(0, true, 0.0, 0.0)); mesh.AddNode(new Node<2>(1, true, 1.0, 0.0)); mesh.AddNode(new Node<2>(2, true, 1.0, 1.0)); mesh.AddNode(new Node<2>(3, true, 2.0, 0.0)); mesh.AddNode(new Node<2>(4, true, 3.0, 0.0)); mesh.AddNode(new Node<2>(5, true, 2.0, 1.0)); // Create two vectors of nodes, one representing each of two triangular elements std::vector<Node<2>* > nodes_elem_1; nodes_elem_1.push_back(mesh.GetNode(0)); nodes_elem_1.push_back(mesh.GetNode(1)); nodes_elem_1.push_back(mesh.GetNode(2)); std::vector<Node<2>* > nodes_elem_2; nodes_elem_2.push_back(mesh.GetNode(3)); nodes_elem_2.push_back(mesh.GetNode(4)); nodes_elem_2.push_back(mesh.GetNode(5)); // Add four copies of each element to the mesh mesh.AddElement(new VertexElement<2,2>(0, nodes_elem_1)); mesh.AddElement(new VertexElement<2,2>(1, nodes_elem_1)); mesh.AddElement(new VertexElement<2,2>(2, nodes_elem_1)); mesh.AddElement(new VertexElement<2,2>(3, nodes_elem_1)); mesh.AddElement(new VertexElement<2,2>(4, nodes_elem_2)); mesh.AddElement(new VertexElement<2,2>(5, nodes_elem_2)); mesh.AddElement(new VertexElement<2,2>(6, nodes_elem_2)); mesh.AddElement(new VertexElement<2,2>(7, nodes_elem_2)); // Get pointers to our two test-nodes Node<2>* p_node_0 = mesh.GetNode(0); Node<2>* p_node_5 = mesh.GetNode(5); /** * Both node 0 and node 5 will be contained in four elements, and we expect an exception to be thrown */ TS_ASSERT_THROWS_THIS(mesh.IdentifySwapType(p_node_0, p_node_5), "Both nodes involved in a swap event are contained in more than three elements"); /** * If we now delete element 7, node 0 will still be contained in four elements while node 5 will only be * contained in three. This is expected behaviour and so no exception should be thrown. */ mesh.DeleteElementPriorToReMesh(7); TS_ASSERT_THROWS_NOTHING(mesh.IdentifySwapType(p_node_0, p_node_5)); }
/* * Here we set up a test with 5 nodes, make a cell for each. We then set cell * 0 to be associated with node 1 instead of node 0, and Validate() throws an * exception. We then set node 0 to be a particle node, and Validate() passes. */ void TestValidateNodeBasedCellPopulationWithParticles() throw(Exception) { EXIT_IF_PARALLEL; // This test doesn't work in parallel. // Create a simple mesh TrianglesMeshReader<2,2> mesh_reader("mesh/test/data/square_4_elements"); TetrahedralMesh<2,2> generating_mesh; generating_mesh.ConstructFromMeshReader(mesh_reader); // Convert this to a NodesOnlyMesh NodesOnlyMesh<2> mesh; mesh.ConstructNodesWithoutMesh(generating_mesh, 1.5); // Create cells std::vector<CellPtr> cells; CellsGenerator<FixedDurationGenerationBasedCellCycleModel, 2> cells_generator; cells_generator.GenerateBasic(cells, mesh.GetNumNodes()-1); std::vector<unsigned> cell_location_indices; for (unsigned i=0; i<cells.size(); i++) { cell_location_indices.push_back(i); } // Fails as the cell population constructor is not given the location indices // corresponding to real cells, so cannot work out which nodes are // particles std::vector<CellPtr> cells_copy(cells); TS_ASSERT_THROWS_THIS(NodeBasedCellPopulationWithParticles<2> dodgy_cell_population(mesh, cells_copy), "Node 4 does not appear to be a particle or has a cell associated with it"); // Passes as the cell population constructor automatically works out which // cells are particles using the mesh and cell_location_indices NodeBasedCellPopulationWithParticles<2> cell_population(mesh, cells, cell_location_indices); // Here we set the particles to what they already are std::set<unsigned> particle_indices; particle_indices.insert(mesh.GetNumNodes()-1); cell_population.SetParticles(particle_indices); // So validate passes at the moment cell_population.Validate(); // Test GetCellUsingLocationIndex() TS_ASSERT_THROWS_NOTHING(cell_population.GetCellUsingLocationIndex(0)); // real cell TS_ASSERT_THROWS_THIS(cell_population.GetCellUsingLocationIndex(mesh.GetNumNodes()-1u),"Location index input argument does not correspond to a Cell"); // particles // Now we label a real cell's node as particle particle_indices.insert(1); // Validate detects this inconsistency TS_ASSERT_THROWS_THIS(cell_population.SetParticles(particle_indices),"Node 1 is labelled as a particle and has a cell attached"); }
/** * Check that GetNextElementData() works. Checks that no errors are thrown for * all of the elements and that an error is thrown if we try to call the * function too many times. */ void TestGetNextElementData() throw(Exception) { VertexMeshReader<2,2> mesh_reader("mesh/test/data/TestVertexMeshWriter/vertex_mesh_2d"); std::vector<unsigned> next_element; for (unsigned i=0; i<mesh_reader.GetNumElements(); i++) { TS_ASSERT_THROWS_NOTHING(next_element = mesh_reader.GetNextElementData().NodeIndices); } TS_ASSERT_THROWS_THIS(next_element = mesh_reader.GetNextElementData().NodeIndices, "Cannot get the next line from node or element file due to incomplete data"); }
/** * Check that the nodes are read correctly. Checks that the output vector * for a given input file is the correct length and that if the input file * is corrupted (missing nodes) then an exception is thrown. */ void TestNodesDataRead() throw(Exception) { TrianglesMeshReader<2,2> mesh_reader("mesh/test/data/disk_984_elements_indexed_from_1"); TS_ASSERT_EQUALS( mesh_reader.GetNumNodes(), 543u); TrianglesMeshReader<2,2> mesh_reader2("mesh/test/data/baddata/bad_nodes_disk_522_elements"); // Reads node 0 from file TS_ASSERT_THROWS_NOTHING(mesh_reader2.GetNextNode()); // Reads node 3 from file when expecting number 1 TS_ASSERT_THROWS_THIS(mesh_reader2.GetNextNode(),"Data for item 1 missing"); }
void TestSimulationWithBoxes() 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("TestOffLatticeSimulationWithNodeBasedCellPopulation"); simulator.SetEndTime(1.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); TS_ASSERT_THROWS_NOTHING(simulator.Solve()); // Check that nothing's gone badly wrong by testing that nodes aren't too close together double min_distance_between_cells = 1.0; for (unsigned i=0; i<simulator.rGetCellPopulation().GetNumNodes(); i++) { for (unsigned j=i+1; j<simulator.rGetCellPopulation().GetNumNodes(); j++) { double distance = norm_2(simulator.rGetCellPopulation().GetNode(i)->rGetLocation()-simulator.rGetCellPopulation().GetNode(j)->rGetLocation()); if (distance < min_distance_between_cells) { min_distance_between_cells = distance; } } } TS_ASSERT(min_distance_between_cells > 1e-3); }
/** * Check that the nodes are read correctly. Checks that the output vector * for a given input file is the correct length and that if the input file * is corrupted (missing nodes) then an exception is thrown. */ void TestNodesDataRead() throw(Exception) { VertexMeshReader<2,2> mesh_reader("mesh/test/data/TestVertexMeshWriter/vertex_mesh_2d"); TS_ASSERT_EQUALS(mesh_reader.GetNumNodes(), 7u); VertexMeshReader<2,2> mesh_reader2("mesh/test/data/baddata/vertex_mesh_bad_nodes"); // Reads node 0 from file TS_ASSERT_THROWS_NOTHING(mesh_reader2.GetNextNode()); // Reads node 3 from file when expecting number 1 TS_ASSERT_THROWS_THIS(mesh_reader2.GetNextNode(), "Data for node 1 missing"); }
void TestWithCvodeAdaptor() throw(Exception) { #ifdef CHASTE_CVODE typedef CellCycleModelOdeSolver<TysonNovakCellCycleModel, CvodeAdaptor> CvodeSolver; // Check we can create an instance boost::shared_ptr<CvodeSolver> p_solver = CvodeSolver::Instance(); TS_ASSERT(p_solver.get() != NULL); // Check singleton-ness boost::shared_ptr<CvodeSolver> p_solver2 = CvodeSolver::Instance(); TS_ASSERT_EQUALS(p_solver, p_solver2); p_solver->Initialise(); TS_ASSERT_THROWS_NOTHING(p_solver->CheckForStoppingEvents()); TS_ASSERT_THROWS_NOTHING(p_solver->SetMaxSteps(1000)); TS_ASSERT_THROWS_NOTHING(p_solver->SetTolerances(1e-5, 1e-5)); #else std::cout << "CVODE is not enabled. " << std::endl; std::cout << "If required please install and alter your hostconfig settings to switch on chaste support." << std::endl; #endif //CHASTE_CVODE }
void TestGetCellUsingLocationIndexWithHaloCell() throw (Exception) { boost::shared_ptr<Node<3> > p_node(new Node<3>(10, false, 0.0, 0.0, 0.0)); // Create a cell. MAKE_PTR(WildTypeCellMutationState, p_state); MAKE_PTR(TransitCellProliferativeType, p_type); FixedDurationGenerationBasedCellCycleModel* p_model = new FixedDurationGenerationBasedCellCycleModel(); CellPtr p_cell(new Cell(p_state, p_model)); mpNodeBasedCellPopulation->AddHaloCell(p_cell, p_node); TS_ASSERT_THROWS_NOTHING(mpNodeBasedCellPopulation->GetCellUsingLocationIndex(10)); TS_ASSERT_EQUALS(mpNodeBasedCellPopulation->GetCellUsingLocationIndex(10), p_cell); }
void TestDivideZeroByZero() throw(Exception) { double zero = 0.0; double ans; #ifdef TEST_FOR_FPE // If we are testing for divide-by-zero, then this will throw an exception //TS_ASSERT_THROWS_ANYTHING(ans = zero / zero); ans = zero;//otherwise compiler would complain TS_ASSERT_EQUALS(ans, zero); ans=ans*zero;//otherwise compiler would complain #else // If we aren't testing for it, then there will be no exception TS_ASSERT_THROWS_NOTHING(ans = zero / zero); TS_ASSERT(std::isnan(ans)); #endif }
void test_OutputPrimitives() { std::ofstream ofs("archive.bin"); TS_ASSERT(ofs.is_open()); // @todo Simulate single Serialize routine // that performs both loading and saving // serializePrimitive(ofs) s11n::BinaryOutArchive ar(ofs); bool some_flag = false; TS_ASSERT_THROWS_NOTHING(ar & TAG(some_flag)); bool some_other_flag = true; TS_ASSERT_THROWS_NOTHING(ar & TAG(some_other_flag)); // serialize integers of different sizes TS_ASSERT_EQUALS(sizeof(long long), 8); for (std::size_t i = 0; integers[i] > 0; ++i) { TS_ASSERT_THROWS_NOTHING(ar & TAG( integers[i])); TS_ASSERT_THROWS_NOTHING(ar & TAG(-integers[i])); } unsigned long long longlong1 = 18446744073709551615; TS_ASSERT_THROWS_NOTHING(ar & TAG(longlong1)); double float1 = 101.1; TS_ASSERT_THROWS_NOTHING(ar & TAG(float1)); // single character, NOT a string char char1 = 'j'; TS_ASSERT_THROWS_NOTHING(ar & TAG(char1)); // this is a string, NOT an array char const* cstr1 = "test string"; TS_ASSERT_THROWS_NOTHING(ar & TAG(cstr1)); // this IS an array int some_nums[] = {2, 4, 8}; TS_ASSERT_THROWS_NOTHING(ar & TAG(some_nums)); }
void TestUpdateWithLoadBalanceDoesntThrow() throw (Exception) { #if BOOST_VERSION < 103700 TS_ASSERT_THROWS_THIS(mpNodeBasedCellPopulation->SendCellsToNeighbourProcesses(), "Parallel cell-based Chaste requires Boost >= 1.37"); #else SimulationTime* p_simulation_time = SimulationTime::Instance(); p_simulation_time->SetEndTimeAndNumberOfTimeSteps(10.0, 1); mpNodeBasedCellPopulation->SetLoadBalanceMesh(true); mpNodeBasedCellPopulation->SetLoadBalanceFrequency(50); TS_ASSERT_EQUALS(mpNodeBasedCellPopulation->mLoadBalanceFrequency, 50u); TS_ASSERT_THROWS_NOTHING(mpNodeBasedCellPopulation->Update()); #endif }
void TestDivideOneByZero() throw(Exception) { double one = 1.0; double zero = 0.0; double ans; #ifdef TEST_FOR_FPE // If we are testing for divide-by-zero, then this will throw an exception //TS_ASSERT_THROWS_ANYTHING(ans = one / zero); ans = zero*one;//otherwise compiler would complain TS_ASSERT_EQUALS(ans, zero); ans=ans*zero;//otherwise compiler would complain #else // If we aren't testing for it, then there will be no exception TS_ASSERT_THROWS_NOTHING(ans = one / zero); double negative_infinity=std::numeric_limits<double>::infinity(); TS_ASSERT_EQUALS(ans, negative_infinity); #endif }
/** * Check that the elements are read correctly. Checks that the output vector * for a given input file is the correct length and that if the input file * is corrupted (missing elements) then an exception is thrown. */ void TestElementsDataRead() throw(Exception) { VertexMeshReader<2,2> mesh_reader("mesh/test/data/TestVertexMeshWriter/vertex_mesh_2d"); TS_ASSERT_EQUALS(mesh_reader.GetNumElements(), 2u); // Read element 0 from file ElementData data1 = mesh_reader.GetNextElementData(); TS_ASSERT_EQUALS(data1.NodeIndices.size(), 5u); TS_ASSERT_EQUALS(data1.NodeIndices[0], 0u); TS_ASSERT_EQUALS(data1.NodeIndices[1], 1u); TS_ASSERT_EQUALS(data1.NodeIndices[2], 2u); TS_ASSERT_EQUALS(data1.NodeIndices[3], 3u); TS_ASSERT_EQUALS(data1.NodeIndices[4], 4u); // Read element 1 from file ElementData data2 = mesh_reader.GetNextElementData(); TS_ASSERT_EQUALS(data2.NodeIndices.size(), 3u); TS_ASSERT_EQUALS(data2.NodeIndices[0], 2u); TS_ASSERT_EQUALS(data2.NodeIndices[1], 5u); TS_ASSERT_EQUALS(data2.NodeIndices[2], 6u); TS_ASSERT_EQUALS(mesh_reader.GetNumElementAttributes(), 1u); mesh_reader.Reset(); for (unsigned i=1; i<mesh_reader.GetNumElements(); i++) { ElementData data = mesh_reader.GetNextElementData(); TS_ASSERT_EQUALS(data.AttributeValue, 0u); } VertexMeshReader<2,2> mesh_reader2("mesh/test/data/baddata/vertex_mesh_bad_elements"); // Reads element 0 from file TS_ASSERT_THROWS_NOTHING(mesh_reader2.GetNextElementData()); // Reads element 2 from file when expecting number 1 TS_ASSERT_THROWS_THIS(mesh_reader2.GetNextElementData(), "Data for element 1 missing"); }
void TestKspExceptionsForCoverage() { TS_ASSERT_THROWS_NOTHING( KSPEXCEPT(2)); /* * These next few lines are designed to force the coverage test to pass. * Some are hard to throw in normal circumstances -- * "Unknown KSP error code" ought never to be thrown. */ TS_ASSERT_THROWS_CONTAINS( KSPEXCEPT(KSP_DIVERGED_ITS), "DIVERGED_ITS in function \'User provided function\' on line"); // The next one is deliberately fragile because it contains the line number in this test suite (to check that the line number is output correctly). TS_ASSERT_THROWS_THIS( KSPEXCEPT(KSP_DIVERGED_DTOL), "DIVERGED_DTOL in function \'User provided function\' on line 102 of file ./global/test/TestPetscSetup.hpp"); TS_ASSERT_THROWS( KSPEXCEPT(KSP_DIVERGED_BREAKDOWN), Exception ); TS_ASSERT_THROWS( KSPEXCEPT(KSP_DIVERGED_BREAKDOWN_BICG), Exception ); TS_ASSERT_THROWS( KSPEXCEPT(KSP_DIVERGED_NONSYMMETRIC), Exception ); TS_ASSERT_THROWS( KSPEXCEPT(KSP_DIVERGED_INDEFINITE_PC), Exception ); TS_ASSERT_THROWS( KSPEXCEPT(-735827), Exception ); KSPWARNIFFAILED(KSP_DIVERGED_ITS); TS_ASSERT_EQUALS(Warnings::Instance()->GetNumWarnings(), 1u); Warnings::QuietDestroy(); }
/** * Check that GetNextNode() returns the coordinates of the correct node. * Compares the coordinates of the first two nodes with their known * values, checks that no errors are thrown for the remaining nodes and * that an error is thrown if we try to call the function too many times. */ void TestGetNextNode() throw(Exception) { VertexMeshReader<2,2> mesh_reader("mesh/test/data/TestVertexMeshWriter/vertex_mesh_2d"); std::vector<double> first_node; first_node = mesh_reader.GetNextNode(); TS_ASSERT_DELTA(first_node[0], 0.0, 1e-6); TS_ASSERT_DELTA(first_node[1], 0.0, 1e-6) std::vector<double> next_node; next_node = mesh_reader.GetNextNode(); TS_ASSERT_DELTA(next_node[0], 1.0, 1e-6); TS_ASSERT_DELTA(next_node[1], 0.0, 1e-6); for (unsigned i=0; i<5; i++) { TS_ASSERT_THROWS_NOTHING(next_node = mesh_reader.GetNextNode()); } TS_ASSERT_THROWS_THIS(next_node = mesh_reader.GetNextNode(), "Cannot get the next line from node or element file due to incomplete data"); }
void TestTessellationConstructor() throw (Exception) { // Create a simple Cylindrical2dMesh, the Delaunay triangulation unsigned cells_across = 3; unsigned cells_up = 3; unsigned thickness_of_ghost_layer = 0; CylindricalHoneycombMeshGenerator generator(cells_across, cells_up, thickness_of_ghost_layer); Cylindrical2dMesh* p_delaunay_mesh = generator.GetCylindricalMesh(); TrianglesMeshWriter<2,2> mesh_writer("TestVertexMeshWriters", "DelaunayMesh", false); TS_ASSERT_THROWS_NOTHING(mesh_writer.WriteFilesUsingMesh(*p_delaunay_mesh)); TS_ASSERT_EQUALS(p_delaunay_mesh->GetWidth(0), 3u); TS_ASSERT_EQUALS(p_delaunay_mesh->CheckIsVoronoi(), true); TS_ASSERT_EQUALS(p_delaunay_mesh->GetNumElements(), 12u); TS_ASSERT_EQUALS(p_delaunay_mesh->GetNumNodes(), 9u); // Create a vertex mesh, the Voronoi tessellation, using the tetrahedral mesh Cylindrical2dVertexMesh voronoi_mesh(*p_delaunay_mesh); VertexMeshWriter<2,2> vertexmesh_writer("TestVertexMeshWriters", "VertexMesh", false); TS_ASSERT_THROWS_NOTHING(vertexmesh_writer.WriteFilesUsingMesh(voronoi_mesh)); // Test the Voronoi tessellation has the correct number of nodes and elements TS_ASSERT_EQUALS(voronoi_mesh.GetWidth(0), 3u); TS_ASSERT_EQUALS(voronoi_mesh.GetNumElements(), 9u); TS_ASSERT_EQUALS(voronoi_mesh.GetNumNodes(), 12u); // // Test the location of the Voronoi nodes /* These are ordered from right to left from bottom to top as * 10 1 0 5 4 6 9 2 3 11 7 8 * Due to the numbering of the elements in the generator. */ TS_ASSERT_DELTA(voronoi_mesh.GetNode(10)->rGetLocation()[0], 3.0, 1e-6); TS_ASSERT_DELTA(voronoi_mesh.GetNode(10)->rGetLocation()[1], sqrt(3.0)/3.0, 1e-6); TS_ASSERT_DELTA(voronoi_mesh.GetNode(1)->rGetLocation()[0], 0.5, 1e-6); TS_ASSERT_DELTA(voronoi_mesh.GetNode(1)->rGetLocation()[1], sqrt(3.0)/6.0, 1e-6); TS_ASSERT_DELTA(voronoi_mesh.GetNode(0)->rGetLocation()[0], 1.0, 1e-6); TS_ASSERT_DELTA(voronoi_mesh.GetNode(0)->rGetLocation()[1], sqrt(3.0)/3.0, 1e-6); TS_ASSERT_DELTA(voronoi_mesh.GetNode(5)->rGetLocation()[0], 1.5, 1e-6); TS_ASSERT_DELTA(voronoi_mesh.GetNode(5)->rGetLocation()[1], sqrt(3.0)/6.0, 1e-6); TS_ASSERT_DELTA(voronoi_mesh.GetNode(4)->rGetLocation()[0], 2.0, 1e-6); TS_ASSERT_DELTA(voronoi_mesh.GetNode(4)->rGetLocation()[1], sqrt(3.0)/3.0, 1e-6); TS_ASSERT_DELTA(voronoi_mesh.GetNode(6)->rGetLocation()[0], 2.5, 1e-6); TS_ASSERT_DELTA(voronoi_mesh.GetNode(6)->rGetLocation()[1], sqrt(3.0)/6.0, 1e-6); TS_ASSERT_DELTA(voronoi_mesh.GetNode(9)->rGetLocation()[0], 0.0, 1e-6); TS_ASSERT_DELTA(voronoi_mesh.GetNode(9)->rGetLocation()[1], 2.0*sqrt(3.0)/3.0, 1e-6); TS_ASSERT_DELTA(voronoi_mesh.GetNode(2)->rGetLocation()[0], 0.5, 1e-6); TS_ASSERT_DELTA(voronoi_mesh.GetNode(2)->rGetLocation()[1], 5.0*sqrt(3.0)/6.0, 1e-6); TS_ASSERT_DELTA(voronoi_mesh.GetNode(3)->rGetLocation()[0], 1.0, 1e-6); TS_ASSERT_DELTA(voronoi_mesh.GetNode(3)->rGetLocation()[1], 2.0*sqrt(3.0)/3.0, 1e-6); TS_ASSERT_DELTA(voronoi_mesh.GetNode(11)->rGetLocation()[0], 1.5, 1e-6); TS_ASSERT_DELTA(voronoi_mesh.GetNode(11)->rGetLocation()[1], 5.0*sqrt(3.0)/6.0, 1e-6); TS_ASSERT_DELTA(voronoi_mesh.GetNode(7)->rGetLocation()[0], 2.0, 1e-6); TS_ASSERT_DELTA(voronoi_mesh.GetNode(7)->rGetLocation()[1], 2.0*sqrt(3.0)/3.0, 1e-6); TS_ASSERT_DELTA(voronoi_mesh.GetNode(8)->rGetLocation()[0], 2.5, 1e-6); TS_ASSERT_DELTA(voronoi_mesh.GetNode(8)->rGetLocation()[1], 5.0*sqrt(3.0)/6.0, 1e-6); // Test the number of nodes owned by each Voronoi element TS_ASSERT_EQUALS(voronoi_mesh.GetElement(0)->GetNumNodes(), 3u); TS_ASSERT_EQUALS(voronoi_mesh.GetElement(1)->GetNumNodes(), 3u); TS_ASSERT_EQUALS(voronoi_mesh.GetElement(2)->GetNumNodes(), 3u); TS_ASSERT_EQUALS(voronoi_mesh.GetElement(3)->GetNumNodes(), 6u); TS_ASSERT_EQUALS(voronoi_mesh.GetElement(4)->GetNumNodes(), 6u); TS_ASSERT_EQUALS(voronoi_mesh.GetElement(5)->GetNumNodes(), 6u); TS_ASSERT_EQUALS(voronoi_mesh.GetElement(6)->GetNumNodes(), 3u); TS_ASSERT_EQUALS(voronoi_mesh.GetElement(7)->GetNumNodes(), 3u); TS_ASSERT_EQUALS(voronoi_mesh.GetElement(8)->GetNumNodes(), 3u); // Test element areas TS_ASSERT_DELTA(voronoi_mesh.GetVolumeOfElement(0), sqrt(3.0)/12.0, 1e-6); TS_ASSERT_DELTA(voronoi_mesh.GetVolumeOfElement(1), sqrt(3.0)/12.0, 1e-6); TS_ASSERT_DELTA(voronoi_mesh.GetVolumeOfElement(2), sqrt(3.0)/12.0, 1e-6); TS_ASSERT_DELTA(voronoi_mesh.GetVolumeOfElement(3), sqrt(3.0)/2.0, 1e-6); TS_ASSERT_DELTA(voronoi_mesh.GetVolumeOfElement(4), sqrt(3.0)/2.0, 1e-6); TS_ASSERT_DELTA(voronoi_mesh.GetVolumeOfElement(5), sqrt(3.0)/2.0, 1e-6); TS_ASSERT_DELTA(voronoi_mesh.GetVolumeOfElement(6), sqrt(3.0)/12.0, 1e-6); TS_ASSERT_DELTA(voronoi_mesh.GetVolumeOfElement(7), sqrt(3.0)/12.0, 1e-6); TS_ASSERT_DELTA(voronoi_mesh.GetVolumeOfElement(8), sqrt(3.0)/12.0, 1e-6); }
void TestWritingToFile() throw(Exception) { EXIT_IF_PARALLEL; std::string output_directory = "TestCellBasedPdeHandlerWritingToFile"; // Create a cell population HoneycombMeshGenerator generator(4, 4, 0); MutableMesh<2,2>* p_generating_mesh = generator.GetMesh(); NodesOnlyMesh<2> mesh; mesh.ConstructNodesWithoutMesh(*p_generating_mesh, 1.5); std::vector<CellPtr> cells; CellsGenerator<FixedDurationGenerationBasedCellCycleModel, 2> cells_generator; cells_generator.GenerateBasic(cells, mesh.GetNumNodes()); TS_ASSERT_EQUALS(cells.size(), mesh.GetNumNodes()); NodeBasedCellPopulation<2> cell_population(mesh, cells); cell_population.SetDataOnAllCells("variable", 1.0); // Create a PDE handler object using this cell population CellBasedPdeHandler<2> pde_handler(&cell_population); TS_ASSERT_THROWS_THIS(pde_handler.OpenResultsFiles(output_directory), "Trying to solve a PDE on a cell population that doesn't have a mesh. Try calling UseCoarsePdeMesh()."); // Use a coarse PDE mesh since we are using a node-based cell population AveragedSourcePde<2> pde(cell_population, -0.1); ConstBoundaryCondition<2> bc(1.0); PdeAndBoundaryConditions<2> pde_and_bc(&pde, &bc, false); pde_and_bc.SetDependentVariableName("variable"); pde_handler.AddPdeAndBc(&pde_and_bc); ChastePoint<2> lower(0.0, 0.0); ChastePoint<2> upper(9.0, 9.0); ChasteCuboid<2> cuboid(lower, upper); pde_handler.UseCoarsePdeMesh(3.0, cuboid, true); // For coverage, call SetWriteAverageRadialPdeSolution() prior to output pde_handler.SetWriteAverageRadialPdeSolution("variable", 5, true); // Test that output files are opened correctly pde_handler.OpenResultsFiles(output_directory); FileFinder file_finder(output_directory + "/results.vizcoarsepdesolution", RelativeTo::ChasteTestOutput); TS_ASSERT(file_finder.Exists()); TS_ASSERT(file_finder.IsFile()); FileFinder file_finder2(output_directory + "/radial_dist.dat", RelativeTo::ChasteTestOutput); TS_ASSERT(file_finder2.Exists()); TS_ASSERT(file_finder2.IsFile()); TS_ASSERT_THROWS_NOTHING(pde_handler.CloseResultsFiles()); // For coverage, also test that output files are opened correctly when not using a coarse PDE mesh HoneycombMeshGenerator generator2(5, 5, 0); MutableMesh<2,2>* p_mesh2 = generator2.GetMesh(); std::vector<CellPtr> cells2; CellsGenerator<FixedDurationGenerationBasedCellCycleModel, 2> cells_generator2; cells_generator2.GenerateBasic(cells2, p_mesh2->GetNumNodes()); MeshBasedCellPopulation<2> cell_population2(*p_mesh2, cells2); cell_population2.SetDataOnAllCells("another variable", 1.0); CellBasedPdeHandler<2> pde_handler2(&cell_population2); pde_handler2.OpenResultsFiles(output_directory); FileFinder file_finder3(output_directory + "/results.vizpdesolution", RelativeTo::ChasteTestOutput); TS_ASSERT(file_finder3.Exists()); TS_ASSERT(file_finder3.IsFile()); pde_handler2.CloseResultsFiles(); }
/* * == Testing the SRN model == * * We begin by testing that our new cell-cycle model is implemented correctly. */ void TestMySrnModel() throw(Exception) { /* Test that we can construct a {{{MySrnModel}}} object: */ TS_ASSERT_THROWS_NOTHING(MySrnModel srn_model); /* Now we construct and initialise a cell with a {{{MySrnModel}}}.*/ MAKE_PTR(WildTypeCellMutationState, p_state); MAKE_PTR(DifferentiatedCellProliferativeType, p_diff_type); StochasticDurationCellCycleModel* p_cell_cycle_model = new StochasticDurationCellCycleModel(); MySrnModel* p_srn_model = new MySrnModel; CellPtr p_cell(new Cell(p_state, p_cell_cycle_model, p_srn_model)); p_cell->SetCellProliferativeType(p_diff_type); p_cell->InitialiseCellCycleModel(); p_cell->InitialiseSrnModel(); /* Now increment time and check the ODE in {{{MySrnModel}}} is solved correctly. */ double end_time = 10; unsigned num_steps = 1000; SimulationTime::Instance()->SetEndTimeAndNumberOfTimeSteps(end_time, num_steps); for (unsigned i=0; i<num_steps; i++) { SimulationTime::Instance()->IncrementTimeOneStep(); double current_time = SimulationTime::Instance()->GetTime(); /* Check that the ODE system is solved correctly */ p_srn_model->SimulateToCurrentTime(); // Test converged to steady state TS_ASSERT_DELTA(p_cell->GetCellData()->GetItem("x"), cos(0.5*current_time), 1e-4); } /* Lastly, we briefly test that archiving of {{{MySrnModel}}} has * been implemented correctly. Create an {{{OutputFileHandler}}} and use * this to define a filename for the archive. */ OutputFileHandler handler("archive", false); std::string archive_filename = handler.GetOutputDirectoryFullPath() + "my_srn_model.arch"; /* Create an output archive. */ { /* Destroy the current instance of {{{SimulationTime}}} and create another instance. * Set the start time, end time and number of time steps. */ SimulationTime::Destroy(); SimulationTime::Instance()->SetStartTime(0.0); SimulationTime* p_simulation_time = SimulationTime::Instance(); p_simulation_time->SetEndTimeAndNumberOfTimeSteps(3.0, 4); /* Create a cell with associated srn and cell-cycle model. */ StochasticDurationCellCycleModel* p_cell_cycle_model = new StochasticDurationCellCycleModel(); AbstractSrnModel* p_srn_model = new MySrnModel; CellPtr p_cell(new Cell(p_state, p_cell_cycle_model, p_srn_model)); p_cell->SetCellProliferativeType(p_diff_type); p_cell->InitialiseCellCycleModel(); p_cell->InitialiseSrnModel(); /* Move forward two time steps. */ p_simulation_time->IncrementTimeOneStep(); p_simulation_time->IncrementTimeOneStep(); /* Solve the SRN. */ p_srn_model->SimulateToCurrentTime(); double current_time = 1.5; TS_ASSERT_DELTA(p_cell->GetCellData()->GetItem("x"), cos(0.5*current_time), 1e-4); /* Now archive the cell-cycle model through its cell. */ CellPtr const p_const_cell = p_cell; std::ofstream ofs(archive_filename.c_str()); boost::archive::text_oarchive output_arch(ofs); output_arch << p_const_cell; } /* Now create an input archive. Begin by again destroying the current * instance of {{{SimulationTime}}} and creating another instance. Set * the start time, end time and number of time steps. note that this is * overwritten when you load the archive. */ { SimulationTime::Destroy(); SimulationTime* p_simulation_time = SimulationTime::Instance(); p_simulation_time->SetStartTime(0.0); p_simulation_time->SetEndTimeAndNumberOfTimeSteps(1.0, 1); TS_ASSERT_DELTA(p_simulation_time->GetTime(), 0.0, 1e-4); /* Create a pointer to a cell. */ CellPtr p_cell; /* Create an input archive and restore the cell from the archive. */ std::ifstream ifs(archive_filename.c_str(), std::ios::binary); boost::archive::text_iarchive input_arch(ifs); input_arch >> p_cell; /* Test that the state of the ODES has been restored correctly. */ double current_time = 1.5; TS_ASSERT_DELTA(p_simulation_time->GetTime(), current_time, 1e-4); TS_ASSERT_DELTA(p_cell->GetCellData()->GetItem("x"), cos(0.5*current_time), 1e-4); /* Move forward two more time steps. */ p_simulation_time->IncrementTimeOneStep(); p_simulation_time->IncrementTimeOneStep(); /* Solve the SRN. */ p_cell->GetSrnModel()->SimulateToCurrentTime(); /* Check it's moved on OK */ current_time = 3.0; TS_ASSERT_DELTA(p_simulation_time->GetTime(), current_time, 1e-4); TS_ASSERT_DELTA(p_cell->GetCellData()->GetItem("x"), cos(0.5*current_time), 1e-4); } }
/* HOW_TO_TAG Cardiac/Electro-mechanics * Run electro-mechanical simulations using bidomain instead of monodomain * * This test is the same as above but with bidomain instead of monodomain. * Extracellular conductivities are set very high so the results should be the same. */ void TestWithHomogeneousEverythingCompressibleBidomain() throw(Exception) { EntirelyStimulatedTissueCellFactory cell_factory; TetrahedralMesh<2,2> electrics_mesh; electrics_mesh.ConstructRegularSlabMesh(0.01, 0.05, 0.05); QuadraticMesh<2> mechanics_mesh; mechanics_mesh.ConstructRegularSlabMesh(0.025, 0.05, 0.05); std::vector<unsigned> fixed_nodes; std::vector<c_vector<double,2> > fixed_node_locations; // fix the node at the origin so that the solution is well-defined (ie unique) fixed_nodes.push_back(0); fixed_node_locations.push_back(zero_vector<double>(2)); // for the rest of the nodes, if they lie on X=0, fix x=0 but leave y free. for(unsigned i=1 /*not 0*/; i<mechanics_mesh.GetNumNodes(); i++) { if(fabs(mechanics_mesh.GetNode(i)->rGetLocation()[0])<1e-6) { c_vector<double,2> new_position; new_position(0) = 0.0; new_position(1) = SolidMechanicsProblemDefinition<2>::FREE; fixed_nodes.push_back(i); fixed_node_locations.push_back(new_position); } } ElectroMechanicsProblemDefinition<2> problem_defn(mechanics_mesh); problem_defn.SetContractionModel(KERCHOFFS2003,1.0); problem_defn.SetUseDefaultCardiacMaterialLaw(COMPRESSIBLE); problem_defn.SetFixedNodes(fixed_nodes, fixed_node_locations); problem_defn.SetMechanicsSolveTimestep(1.0); // the following is just for coverage - applying a zero pressure so has no effect on deformation std::vector<BoundaryElement<1,2>*> boundary_elems; boundary_elems.push_back(* (mechanics_mesh.GetBoundaryElementIteratorBegin())); problem_defn.SetApplyNormalPressureOnDeformedSurface(boundary_elems, 0.0); HeartConfig::Instance()->SetSimulationDuration(10.0); HeartConfig::Instance()->SetExtracellularConductivities(Create_c_vector(1500,1500,1500)); //creates the EM problem with ELEC_PROB_DIM=2 CardiacElectroMechanicsProblem<2,2> problem(COMPRESSIBLE, BIDOMAIN, &electrics_mesh, &mechanics_mesh, &cell_factory, &problem_defn, "TestCardiacEmHomogeneousEverythingCompressibleBidomain"); problem.Solve(); std::vector<c_vector<double,2> >& r_deformed_position = problem.rGetDeformedPosition(); // not sure how easy is would be determine what the deformation should be // exactly, but it certainly should be constant squash in X direction, constant // stretch in Y. // first, check node 8 starts is the far corner assert(fabs(mechanics_mesh.GetNode(8)->rGetLocation()[0] - 0.05)<1e-8); assert(fabs(mechanics_mesh.GetNode(8)->rGetLocation()[1] - 0.05)<1e-8); double X_scale_factor = r_deformed_position[8](0)/0.05; double Y_scale_factor = r_deformed_position[8](1)/0.05; std::cout << "Scale_factors = " << X_scale_factor << " " << Y_scale_factor << ", product = " << X_scale_factor*Y_scale_factor<<"\n"; for(unsigned i=0; i<mechanics_mesh.GetNumNodes(); i++) { double X = mechanics_mesh.GetNode(i)->rGetLocation()[0]; double Y = mechanics_mesh.GetNode(i)->rGetLocation()[1]; TS_ASSERT_DELTA( r_deformed_position[i](0), X * X_scale_factor, 1e-6); TS_ASSERT_DELTA( r_deformed_position[i](1), Y * Y_scale_factor, 1e-6); } //check interpolated voltages and calcium unsigned quad_points = problem.mpCardiacMechSolver->GetTotalNumQuadPoints(); TS_ASSERT_EQUALS(problem.mInterpolatedVoltages.size(), quad_points); TS_ASSERT_EQUALS(problem.mInterpolatedCalciumConcs.size(), quad_points); //two hardcoded values TS_ASSERT_DELTA(problem.mInterpolatedVoltages[0],9.267,1e-3); TS_ASSERT_DELTA(problem.mInterpolatedCalciumConcs[0],0.001464,1e-6); //for the rest, we check that, at the end of this simulation, all quad nodes have V and Ca above a certain threshold for(unsigned i = 0; i < quad_points; i++) { TS_ASSERT_LESS_THAN(9.2,problem.mInterpolatedVoltages[i]); TS_ASSERT_LESS_THAN(0.0014,problem.mInterpolatedCalciumConcs[i]); } //check default value of whether there is a bath or not TS_ASSERT_EQUALS(problem.mpElectricsProblem->GetHasBath(), false); //test the functionality of having phi_e on the mechanics mesh (values are tested somewhere else) Hdf5DataReader data_reader("TestCardiacEmHomogeneousEverythingCompressibleBidomain/electrics","voltage_mechanics_mesh"); TS_ASSERT_THROWS_NOTHING(data_reader.GetVariableOverTime("Phi_e",0u)); }