void TestAssigningModifiersToACellModel() throw(Exception) { boost::shared_ptr<ZeroStimulus> p_stimulus(new ZeroStimulus()); boost::shared_ptr<EulerIvpOdeSolver> p_solver(new EulerIvpOdeSolver); CellShannon2004FromCellML* p_shannon = new CellShannon2004FromCellML(p_solver, p_stimulus); TS_ASSERT_EQUALS(p_shannon->HasModifier("Alan"), false); TS_ASSERT_THROWS_THIS(p_shannon->GetModifier("Alan"), "There is no modifier called Alan in this model."); // Default modifier shouldn't do anything to the value inputted to calc() TS_ASSERT_EQUALS(p_shannon->HasModifier("membrane_rapid_delayed_rectifier_potassium_current_conductance"), true); TS_ASSERT_DELTA(p_shannon->GetModifier("membrane_rapid_delayed_rectifier_potassium_current_conductance")->Calc(123,0),123,1e-9); // Make a new modifier boost::shared_ptr<AbstractModifier> p_new_modifier(new FixedModifier(-90.0)); TS_ASSERT_THROWS_THIS(p_shannon->SetModifier("Alan",p_new_modifier), "There is no modifier called Alan in this model."); // Assign it to the Shannon model p_shannon->SetModifier("membrane_rapid_delayed_rectifier_potassium_current_conductance",p_new_modifier); // We should now get a new answer to this. TS_ASSERT_DELTA(p_shannon->GetModifier("membrane_rapid_delayed_rectifier_potassium_current_conductance")->Calc(0,0),-90,1e-9); delete p_shannon; }
void TestProcessSpecificArchive() throw(Exception) { TS_ASSERT_THROWS_THIS(ProcessSpecificArchive<boost::archive::text_oarchive>::Get(), "A ProcessSpecificArchive has not been set up."); TS_ASSERT_THROWS_THIS(ProcessSpecificArchive<boost::archive::text_iarchive>::Get(), "A ProcessSpecificArchive has not been set up."); // Set up an output archive pointer OutputFileHandler handler("archive", false); handler.SetArchiveDirectory(); std::string arch_path = ArchiveLocationInfo::GetProcessUniqueFilePath("test.arch"); std::ofstream ofs(arch_path.c_str()); boost::archive::text_oarchive* p_arch = new boost::archive::text_oarchive(ofs); // Test the ProcessSpecificArchive Get and Set methods with this ProcessSpecificArchive<boost::archive::text_oarchive>::Set(p_arch); TS_ASSERT(ProcessSpecificArchive<boost::archive::text_oarchive>::Get()==p_arch); delete p_arch; // Set up an input archive pointer std::ifstream ifs(arch_path.c_str()); boost::archive::text_iarchive* p_arch2 = new boost::archive::text_iarchive(ifs); // Test the ProcessSpecificArchive Get and Set methods with this ProcessSpecificArchive<boost::archive::text_iarchive>::Set(p_arch2); TS_ASSERT(ProcessSpecificArchive<boost::archive::text_iarchive>::Get()==p_arch2); delete p_arch2; // Clean up ProcessSpecificArchive<boost::archive::text_iarchive>::Set(NULL); ProcessSpecificArchive<boost::archive::text_oarchive>::Set(NULL); }
void TestReadingNclInformation() throw(Exception) { TrianglesMeshReader<3,3> mesh_reader_3d("mesh/test/data/simple_cube_binary"); TS_ASSERT(mesh_reader_3d.HasNclFile()); std::vector<unsigned> containing_element_indices = mesh_reader_3d.GetContainingElementIndices(0); TS_ASSERT_EQUALS(containing_element_indices.size(), 5u) TS_ASSERT_EQUALS(containing_element_indices[0], 0u); TS_ASSERT_EQUALS(containing_element_indices[1], 4u); TS_ASSERT_EQUALS(containing_element_indices[2], 8u); TS_ASSERT_EQUALS(containing_element_indices[3], 10u); TS_ASSERT_EQUALS(containing_element_indices[4], 11u); containing_element_indices = mesh_reader_3d.GetContainingElementIndices(7); TS_ASSERT_EQUALS(containing_element_indices.size(), 5u) TS_ASSERT_EQUALS(containing_element_indices[0], 3u); TS_ASSERT_EQUALS(containing_element_indices[1], 4u); TS_ASSERT_EQUALS(containing_element_indices[2], 5u); TS_ASSERT_EQUALS(containing_element_indices[3], 9u); TS_ASSERT_EQUALS(containing_element_indices[4], 10u); // Out of range TS_ASSERT_THROWS_THIS(containing_element_indices = mesh_reader_3d.GetContainingElementIndices(9), "Connectivity list does not exist - not enough nodes."); // Test exception if NCL file has wrong number of nodes TS_ASSERT_THROWS_THIS( READER_3D bad_mesh_reader("mesh/test/data/simple_cube_binary_ncl_corrupted"), "NCL file does not contain the correct number of nodes for mesh"); }
void TestEnforceConstantTimeStep() throw(Exception) { TimeStepper stepper(0.0, 1.0, 0.3); // timestep does not divide, but no checking TS_ASSERT_THROWS_THIS( TimeStepper bad_const_dt_stepper(0.0, 1.0, 0.3, true), "TimeStepper estimates non-constant timesteps will need to be used: " "check timestep divides (end_time-start_time) (or divides printing timestep). " "[End time=1; start=0; dt=0.3; error=0.1]"); #ifdef _MSC_VER _set_output_format(_TWO_DIGIT_EXPONENT); #endif TS_ASSERT_THROWS_THIS( TimeStepper bad_const_dt_stepper2(0.0, 1.0, 0.99999999, true), "TimeStepper estimates non-constant timesteps will need to be used: " "check timestep divides (end_time-start_time) (or divides printing timestep). " "[End time=1; start=0; dt=1; error=1e-08]"); TimeStepper const_dt_stepper(0.0, 1.0, 0.1, true); unsigned counter = 0; while (!const_dt_stepper.IsTimeAtEnd()) { counter++; TS_ASSERT_DELTA(const_dt_stepper.GetNextTimeStep(), 0.1, 1e-15); TS_ASSERT_EQUALS(const_dt_stepper.GetIdealTimeStep(), 0.1); const_dt_stepper.AdvanceOneTimeStep(); if (const_dt_stepper.IsTimeAtEnd()) { TS_ASSERT_EQUALS(const_dt_stepper.GetNextTimeStep(), 0.0); } else { TS_ASSERT_DELTA(const_dt_stepper.GetNextTimeStep(), 0.1, 1e-15); } } TS_ASSERT_EQUALS(counter,10u); }
// For #1199 void TestFactorySetFromFactory() { unsigned num_procs = PetscTools::GetNumProcs(); unsigned total_elements = (num_procs+1)*num_procs/2; unsigned my_rank = PetscTools::GetMyRank(); DistributedVectorFactory uneven_factory(total_elements, my_rank+1); DistributedVectorFactory even_factory(total_elements); DistributedVectorFactory* p_even_orig = even_factory.GetOriginalFactory(); TS_ASSERT_EQUALS(uneven_factory.GetNumProcs(), even_factory.GetNumProcs()); TS_ASSERT_EQUALS(uneven_factory.GetProblemSize(), even_factory.GetProblemSize()); bool any_differ = PetscTools::ReplicateBool(uneven_factory.GetLow() != even_factory.GetLow()); TS_ASSERT(PetscTools::IsSequential() || any_differ); // Now make them equal even_factory.SetFromFactory(&uneven_factory); TS_ASSERT_EQUALS(uneven_factory.GetNumProcs(), even_factory.GetNumProcs()); TS_ASSERT_EQUALS(uneven_factory.GetProblemSize(), even_factory.GetProblemSize()); TS_ASSERT_EQUALS(uneven_factory.GetLow(), even_factory.GetLow()); TS_ASSERT_EQUALS(uneven_factory.GetHigh(), even_factory.GetHigh()); TS_ASSERT(even_factory.GetOriginalFactory() == p_even_orig); // Exceptions DistributedVectorFactory diff_procs(1, 2, total_elements, num_procs+1); TS_ASSERT_THROWS_THIS(even_factory.SetFromFactory(&diff_procs), "Cannot set from a factory for a different number of processes."); DistributedVectorFactory diff_total(1, 2, total_elements+1, num_procs); TS_ASSERT_THROWS_THIS(even_factory.SetFromFactory(&diff_total), "Cannot set from a factory for a different problem size."); }
void TestOtherExceptions() throw(Exception) { TS_ASSERT_THROWS_THIS(READER_2D mesh_reader("mesh/test/data/nonexistent_file"), "Could not open data file: mesh/test/data/nonexistent_file.node"); TS_ASSERT_THROWS_THIS(READER_2D mesh_reader("mesh/test/data/baddata/vertex_mesh_without_element_file"), "Could not open data file: mesh/test/data/baddata/vertex_mesh_without_element_file.cell"); }
void TestDerivedQuantities() throw (Exception) { ParameterisedOde ode; boost::shared_ptr<const AbstractOdeSystemInformation> p_info = ode.GetSystemInformation(); TS_ASSERT_EQUALS(ode.GetNumberOfDerivedQuantities(), 1u); TS_ASSERT_EQUALS(ode.HasDerivedQuantity("2a_plus_y"), true); TS_ASSERT_EQUALS(ode.HasDerivedQuantity("Not_there"), false); TS_ASSERT_EQUALS(ode.GetDerivedQuantityIndex("2a_plus_y"), 0u); TS_ASSERT_EQUALS(ode.GetDerivedQuantityUnits(0u), "dimensionless"); TS_ASSERT_EQUALS(ode.rGetDerivedQuantityNames().size(), 1u); TS_ASSERT_EQUALS(ode.rGetDerivedQuantityUnits().size(), 1u); TS_ASSERT_EQUALS(ode.rGetDerivedQuantityNames()[0], "2a_plus_y"); TS_ASSERT_EQUALS(ode.rGetDerivedQuantityUnits()[0], "dimensionless"); TS_ASSERT_EQUALS(p_info->HasDerivedQuantity("2a_plus_y"), true); TS_ASSERT_EQUALS(p_info->HasDerivedQuantity("Not_there"), false); TS_ASSERT_EQUALS(p_info->GetDerivedQuantityIndex("2a_plus_y"), 0u); TS_ASSERT_EQUALS(p_info->GetDerivedQuantityUnits(0u), "dimensionless"); TS_ASSERT_EQUALS(p_info->rGetDerivedQuantityNames().size(), 1u); TS_ASSERT_EQUALS(p_info->rGetDerivedQuantityUnits().size(), 1u); TS_ASSERT_EQUALS(p_info->rGetDerivedQuantityNames()[0], "2a_plus_y"); TS_ASSERT_EQUALS(p_info->rGetDerivedQuantityUnits()[0], "dimensionless"); TS_ASSERT_EQUALS(ode.HasAnyVariable("2a_plus_y"), true); TS_ASSERT_EQUALS(ode.HasAnyVariable("Not_there"), false); TS_ASSERT_EQUALS(ode.GetAnyVariableIndex("2a_plus_y"), 2u); TS_ASSERT_EQUALS(ode.GetAnyVariableUnits(2u), "dimensionless"); TS_ASSERT_EQUALS(p_info->GetAnyVariableIndex("2a_plus_y"), 2u); TS_ASSERT_EQUALS(p_info->GetAnyVariableUnits(2u), "dimensionless"); std::vector<double> derived = ode.ComputeDerivedQuantitiesFromCurrentState(0.0); double a = ode.GetParameter(0); TS_ASSERT_EQUALS(a, 0.0); TS_ASSERT_DELTA(derived[0], 2*a, 1e-4); TS_ASSERT_DELTA(ode.GetAnyVariable(2u, 0.0), 2*a, 1e-4); TS_ASSERT_DELTA(ode.GetAnyVariable(2u, 0.0, &derived), 2*a, 1e-4); a = 1.0; ode.SetParameter(0, a); derived = ode.ComputeDerivedQuantities(0.0, ode.GetInitialConditions()); TS_ASSERT_DELTA(derived[0], 2*a, 1e-4); double y = 10.0; ode.SetStateVariable(0, y); derived = ode.ComputeDerivedQuantitiesFromCurrentState(0.0); TS_ASSERT_DELTA(derived[0], 2*a+y, 1e-4); TS_ASSERT_DELTA(ode.GetAnyVariable(2u, 1.0/* ignored for this ODE */), 2*a+y, 1e-4); // Exceptions TS_ASSERT_THROWS_THIS(ode.GetDerivedQuantityIndex("Missing"), "No derived quantity named 'Missing'."); TS_ASSERT_THROWS_THIS(ode.GetDerivedQuantityUnits(1u), "The index passed in must be less than the number of derived quantities."); TwoDimOdeSystem ode2; TS_ASSERT_THROWS_THIS(ode2.ComputeDerivedQuantitiesFromCurrentState(0.0), "This ODE system does not define derived quantities."); std::vector<double> doesnt_matter; TS_ASSERT_THROWS_THIS(ode2.ComputeDerivedQuantities(0.0, doesnt_matter), "This ODE system does not define derived quantities."); }
void TestVolumeConstraintPottsUpdateRuleIn2d() throw (Exception) { // Create a simple 2D PottsMesh with 2 elements PottsMeshGenerator<2> generator(4, 1, 2, 4, 2, 2, 1, 1, 1, true); // last bool makes elements start in bottom left 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); // Create an update law system VolumeConstraintPottsUpdateRule<2> volume_constraint; // Test get/set methods TS_ASSERT_DELTA(volume_constraint.GetDeformationEnergyParameter(), 0.5, 1e-12); TS_ASSERT_DELTA(volume_constraint.GetMatureCellTargetVolume(), 16.0, 1e-12); volume_constraint.SetDeformationEnergyParameter(1.0); volume_constraint.SetMatureCellTargetVolume(0.6); TS_ASSERT_DELTA(volume_constraint.GetDeformationEnergyParameter(), 1.0, 1e-12); TS_ASSERT_DELTA(volume_constraint.GetMatureCellTargetVolume(), 0.6, 1e-12); volume_constraint.SetDeformationEnergyParameter(0.5); volume_constraint.SetMatureCellTargetVolume(4.0); // Test EvaluateHamiltonianContribution() double alpha = volume_constraint.GetDeformationEnergyParameter(); // Both points lie within cell 0 TS_ASSERT_THROWS_THIS(volume_constraint.EvaluateHamiltonianContribution(0, 1, cell_population), "The current node and target node must not be in the same element."); // Both points lie within cell 1 TS_ASSERT_THROWS_THIS(volume_constraint.EvaluateHamiltonianContribution(8, 9, cell_population), "The current node and target node must not be in the same element."); // Both points lie within cell medium TS_ASSERT_THROWS_THIS(volume_constraint.EvaluateHamiltonianContribution(2, 3, cell_population), "At least one of the current node or target node must be in an element."); // Current site in cell 0; target site in cell medium double contribution = volume_constraint.EvaluateHamiltonianContribution(5, 6, cell_population); TS_ASSERT_DELTA(contribution, alpha, 1e-6); // Current site in cell medium; target site in cell 0 contribution = volume_constraint.EvaluateHamiltonianContribution(6, 5, cell_population); TS_ASSERT_DELTA(contribution, alpha, 1e-6); // Current site in cell 0; target site in cell 1 contribution = volume_constraint.EvaluateHamiltonianContribution(5, 9, cell_population); TS_ASSERT_DELTA(contribution, 2.0*alpha, 1e-6); }
void TestAdhesionPottsUpdateRuleIn3d() throw (Exception) { // Create a simple 2D PottsMesh with 2 elements PottsMeshGenerator<3> generator(4, 2, 2, 2, 1, 2, 4, 1, 2, true); PottsMesh<3>* p_mesh = generator.GetMesh(); TS_ASSERT_EQUALS(p_mesh->GetNumElements(), 2u); TS_ASSERT_EQUALS(p_mesh->GetNumNodes(), 32u); // Create cells std::vector<CellPtr> cells; CellsGenerator<FixedDurationGenerationBasedCellCycleModel, 3> cells_generator; cells_generator.GenerateBasic(cells, p_mesh->GetNumElements()); // Label cells 0 and 1 MAKE_PTR(CellLabel, p_label); cells[0]->AddCellProperty(p_label); cells[1]->AddCellProperty(p_label); // Create cell population PottsBasedCellPopulation<3> cell_population(*p_mesh, cells); // Create an update law system AdhesionPottsUpdateRule<3> adhesion_update; // Set the parameters to facilitate calculations below. adhesion_update.SetCellCellAdhesionEnergyParameter(0.1); adhesion_update.SetCellBoundaryAdhesionEnergyParameter(0.2); // Test EvaluateHamiltonianContribution(). Note that the boundary of the domain is a void not medium. double gamma_cell_cell = adhesion_update.GetCellCellAdhesionEnergyParameter(); double gamma_cell_boundary = adhesion_update.GetCellBoundaryAdhesionEnergyParameter(); // Both points lie within cell 0 TS_ASSERT_THROWS_THIS(adhesion_update.EvaluateHamiltonianContribution(0, 1, cell_population), "The current node and target node must not be in the same element."); // Both points lie within cell 1 TS_ASSERT_THROWS_THIS(adhesion_update.EvaluateHamiltonianContribution(2, 3, cell_population), "The current node and target node must not be in the same element."); // Both points lie within cell medium TS_ASSERT_THROWS_THIS(adhesion_update.EvaluateHamiltonianContribution(16, 17, cell_population), "At least one of the current node or target node must be in an element."); // Current site in cell 0; target site in cell medium double contribution = adhesion_update.EvaluateHamiltonianContribution(9, 17, cell_population); TS_ASSERT_DELTA(contribution, 3.0*gamma_cell_boundary, 1e-6); // Current site in cell medium; target site in cell 0 contribution = adhesion_update.EvaluateHamiltonianContribution(17, 9, cell_population); TS_ASSERT_DELTA(contribution, 3.0*gamma_cell_boundary - gamma_cell_cell, 1e-6); // Current site in cell 0; target site in cell 1 contribution = adhesion_update.EvaluateHamiltonianContribution(9, 10, cell_population); TS_ASSERT_DELTA(contribution, 2.0*gamma_cell_cell, 1e-6); }
void TestSurfaceAreaConstraintPottsUpdateRuleIn3d() throw (Exception) { // Create a simple 3D PottsMesh with 2 elements PottsMeshGenerator<3> generator(4, 2, 2, 4, 1, 2, 4, 1, 2, true); PottsMesh<3>* p_mesh = generator.GetMesh(); TS_ASSERT_EQUALS(p_mesh->GetNumElements(), 2u); TS_ASSERT_EQUALS(p_mesh->GetNumNodes(), 64u); // Create cells std::vector<CellPtr> cells; CellsGenerator<FixedDurationGenerationBasedCellCycleModel, 3> cells_generator; cells_generator.GenerateBasic(cells, p_mesh->GetNumElements()); // Create cell population PottsBasedCellPopulation<3> cell_population(*p_mesh, cells); // Create an update law system SurfaceAreaConstraintPottsUpdateRule<3> surface_area_constraint; surface_area_constraint.SetDeformationEnergyParameter(0.5); surface_area_constraint.SetMatureCellTargetSurfaceArea(24.0); // Test EvaluateHamiltonianContribution() double gamma = surface_area_constraint.GetDeformationEnergyParameter(); // Both points lie within cell 0 TS_ASSERT_THROWS_THIS(surface_area_constraint.EvaluateHamiltonianContribution(0, 1, cell_population), "The current node and target node must not be in the same element."); // Both points lie within cell 1 TS_ASSERT_THROWS_THIS(surface_area_constraint.EvaluateHamiltonianContribution(2, 3, cell_population), "The current node and target node must not be in the same element."); // Both points lie within cell medium TS_ASSERT_THROWS_THIS(surface_area_constraint.EvaluateHamiltonianContribution(8, 9, cell_population), "At least one of the current node or target node must be in an element."); // Current site in cell 0; target site in cell medium Cell on edge of domain double contribution = surface_area_constraint.EvaluateHamiltonianContribution(4, 8, cell_population); TS_ASSERT_DELTA(contribution, 4.0*4.0*gamma, 1e-6); // Current site in cell medium; target site in cell 1 contribution = surface_area_constraint.EvaluateHamiltonianContribution(10, 6, cell_population); TS_ASSERT_DELTA(contribution, 0.0, 1e-6); // Current site in cell 0; target site in cell 1 contribution = surface_area_constraint.EvaluateHamiltonianContribution(17, 18, cell_population); TS_ASSERT_DELTA(contribution, 4.0*4.0*gamma, 1e-6); // Current site in cell 0; target site in cell 1 (diagonal switch) contribution = surface_area_constraint.EvaluateHamiltonianContribution(1, 18, cell_population); TS_ASSERT_DELTA(contribution, 4.0*4.0*gamma, 1e-6); // Current site in cell 0; target site in medium contribution = surface_area_constraint.EvaluateHamiltonianContribution(5, 9, cell_population); TS_ASSERT_DELTA(contribution, 4.0*4.0*gamma, 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 TestNodeAndMeshMethods() throw(Exception) { // Create a Potts-based cell population PottsMeshGenerator<2> generator(4, 2, 2, 4, 2, 2); PottsMesh<2>* p_mesh = generator.GetMesh(); std::vector<CellPtr> cells; CellsGenerator<FixedDurationGenerationBasedCellCycleModel, 2> cells_generator; cells_generator.GenerateBasic(cells, p_mesh->GetNumElements()); PottsBasedCellPopulation<2> cell_population(*p_mesh, cells); // Test GetNumNodes() TS_ASSERT_EQUALS(cell_population.GetNumNodes(), 16u); // Test GetNode() for (unsigned index=0; index<cell_population.GetNumNodes(); index++) { Node<2>* p_node = cell_population.GetNode(index); TS_ASSERT_EQUALS(p_node->GetIndex(), index); c_vector<double, 2> node_location = p_node->rGetLocation(); c_vector<double, 2> expected; expected(0) = (double)(index%4); expected(1) = (double)(index>3) + (double)(index>7) + (double)(index>11); double drift = norm_2(node_location-expected); TS_ASSERT_LESS_THAN(drift, 1e-6); } // Test GetElement() for (unsigned index=0; index<cell_population.GetNumElements(); index++) { PottsElement<2>* p_element = cell_population.GetElement(index); TS_ASSERT_EQUALS(p_element->GetIndex(), index); TS_ASSERT_EQUALS(p_element->GetNumNodes(), 4u); } // Test SetNode() ChastePoint<2> unused_point; TS_ASSERT_THROWS_THIS(cell_population.SetNode(0, unused_point), "SetNode() cannot be called on a subclass of AbstractOnLatticeCellPopulation."); // Test GetWidth() method double width_x = cell_population.GetWidth(0); TS_ASSERT_DELTA(width_x, 3.0, 1e-4); double width_y = cell_population.GetWidth(1); TS_ASSERT_DELTA(width_y, 3.0, 1e-4); // Test GetNeighbouringNodeIndices() method TS_ASSERT_THROWS_THIS(cell_population.GetNeighbouringNodeIndices(10), "Cannot call GetNeighbouringNodeIndices() on a subclass of AbstractOnLatticeCellPopulation, need to go through the PottsMesh instead"); }
void TestExceptions() throw(Exception) { TS_ASSERT_THROWS_THIS(MatrixVentilationProblem bad_problem("mesh/test/data/y_branch_3d_mesh", 1u), "Outlet node is not a boundary node"); MatrixVentilationProblem problem("lung/test/data/three_bifurcations"); TS_ASSERT_THROWS_THIS(problem.SolveProblemFromFile("DoesNotExist.txt", "out", "out"), "Could not open file DoesNotExist.txt"); TS_ASSERT_THROWS_THIS(problem.SetPressureAtBoundaryNode(3u, 0.0), "Boundary conditions cannot be set at internal nodes"); TS_ASSERT_THROWS_THIS(problem.SetFluxAtBoundaryNode(3u, 0.0), "Boundary conditions cannot be set at internal nodes"); }
/* * 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"); }
void TestArchiveOpenerReadAndWrite() throw(Exception) { // Should this test fail with an exception involving // apps/texttest/chaste/resume_bidomain/save_bidomain // then look at TestCardiacSimulationArchiver mArchiveDir = "archiving_helpers"; FileFinder archive_dir(mArchiveDir, RelativeTo::ChasteTestOutput); std::string archive_file = "archive_opener.arch"; const unsigned test_int = 123; // Write { OutputArchiveOpener archive_opener_out(archive_dir, archive_file); boost::archive::text_oarchive* p_arch = archive_opener_out.GetCommonArchive(); boost::archive::text_oarchive* p_process_arch = ProcessSpecificArchive<boost::archive::text_oarchive>::Get(); (*p_arch) & test_int; // All can write to the common archive - non-masters will write to /dev/null. (*p_process_arch) & test_int; // archive_opener_out will do a PetscTools::Barrier when it is destructed } // Read { TS_ASSERT_THROWS_THIS(ProcessSpecificArchive<boost::archive::text_oarchive>::Get(), "A ProcessSpecificArchive has not been set up."); TS_ASSERT_THROWS_THIS(ProcessSpecificArchive<boost::archive::text_iarchive>::Get(), "A ProcessSpecificArchive has not been set up."); InputArchiveOpener archive_opener_in(archive_dir, archive_file); boost::archive::text_iarchive* p_arch = archive_opener_in.GetCommonArchive(); boost::archive::text_iarchive* p_process_arch = ProcessSpecificArchive<boost::archive::text_iarchive>::Get(); unsigned test_int1, test_int2; (*p_arch) & test_int1; (*p_process_arch) & test_int2; TS_ASSERT_EQUALS(test_int1, test_int); TS_ASSERT_EQUALS(test_int2, test_int); } // Cover the case of an archive in the chaste folder (i.e. a path relative to the working directory) if (PetscTools::IsSequential()) { // Read FileFinder save_bidomain_dir("apps/texttest/chaste/resume_bidomain/save_bidomain", RelativeTo::ChasteSourceRoot); InputArchiveOpener archive_opener_relative(save_bidomain_dir, "archive.arch"); } PetscTools::Barrier(); // Make sure all processes have finished this test before proceeding }
void TestVolumeConstraintPottsUpdateRuleIn3d() throw (Exception) { // Create a simple 2D PottsMesh with 2 elements PottsMeshGenerator<3> generator(4, 2, 2, 2, 1, 2, 4, 1, 2, true); PottsMesh<3>* p_mesh = generator.GetMesh(); TS_ASSERT_EQUALS(p_mesh->GetNumElements(), 2u); TS_ASSERT_EQUALS(p_mesh->GetNumNodes(), 32u); // Create cells std::vector<CellPtr> cells; CellsGenerator<FixedDurationGenerationBasedCellCycleModel, 3> cells_generator; cells_generator.GenerateBasic(cells, p_mesh->GetNumElements()); // Create cell population PottsBasedCellPopulation<3> cell_population(*p_mesh, cells); // Create an update law system VolumeConstraintPottsUpdateRule<3> volume_constraint; // Test EvaluateHamiltonianContribution() volume_constraint.SetDeformationEnergyParameter(0.5); volume_constraint.SetMatureCellTargetVolume(8.0); double alpha = volume_constraint.GetDeformationEnergyParameter(); // Both points lie within cell 0 TS_ASSERT_THROWS_THIS(volume_constraint.EvaluateHamiltonianContribution(0, 1, cell_population), "The current node and target node must not be in the same element."); // Both points lie within cell 1 TS_ASSERT_THROWS_THIS(volume_constraint.EvaluateHamiltonianContribution(2, 3, cell_population), "The current node and target node must not be in the same element."); // Both points lie within cell medium TS_ASSERT_THROWS_THIS(volume_constraint.EvaluateHamiltonianContribution(16, 17, cell_population), "At least one of the current node or target node must be in an element."); // Current site in cell 0; target site in cell medium double contribution = volume_constraint.EvaluateHamiltonianContribution(9, 17, cell_population); TS_ASSERT_DELTA(contribution, alpha, 1e-6); // Current site in cell medium; target site in cell 0 contribution = volume_constraint.EvaluateHamiltonianContribution(17, 9, cell_population); TS_ASSERT_DELTA(contribution, alpha, 1e-6); // Current site in cell 0; target site in cell 1 contribution = volume_constraint.EvaluateHamiltonianContribution(9, 10, cell_population); TS_ASSERT_DELTA(contribution, 2.0*alpha, 1e-6); }
void TestExceptions() { Ode1 ode; TS_ASSERT_EQUALS(ode.GetNumberOfStateVariables(), 1u); std::vector<double> v(2); v[0] = -1.0; v[1] = -2.0; TS_ASSERT_THROWS_THIS(ode.SetDefaultInitialConditions(v), "The number of initial conditions must be that of the number of state variables."); TS_ASSERT_THROWS_THIS(ode.SetDefaultInitialCondition(2, -3.0), "Index is greater than the number of state variables."); TS_ASSERT_THROWS_THIS(ode.SetStateVariables(v), "The size of the passed in vector must be that of the number of state variables."); }
void TestEventExceptions() throw(Exception) { // Should not be able to end and event that has not yet begun TS_ASSERT_THROWS_THIS(HeartEventHandler::EndEvent(HeartEventHandler::EVERYTHING), "Error: The event associated with the counter for \'Total\' had not begun when EndEvent was called."); HeartEventHandler::BeginEvent(HeartEventHandler::EVERYTHING); // Beginning an event already begun should print an error message and disable the handler HeartEventHandler::BeginEvent(HeartEventHandler::EVERYTHING); TS_ASSERT(!HeartEventHandler::IsEnabled()); // Report should then throw TS_ASSERT_THROWS_THIS(HeartEventHandler::Report(), "Asked to report on a disabled event handler. Check for contributory errors above."); }
/** * 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 TestCellProliferativeTypeMethods() throw(Exception) { MAKE_PTR(StemCellProliferativeType, p_type); TS_ASSERT_EQUALS(p_type->GetCellCount(), 0u); p_type->IncrementCellCount(); TS_ASSERT_EQUALS(p_type->GetCellCount(), 1u); p_type->DecrementCellCount(); TS_ASSERT_EQUALS(p_type->GetCellCount(), 0u); TS_ASSERT_THROWS_THIS(p_type->DecrementCellCount(), "Cannot decrement cell count: no cells have this cell property"); TS_ASSERT_EQUALS(p_type->GetColour(), 0u); TS_ASSERT_EQUALS(p_type->IsType<StemCellProliferativeType>(), true); TS_ASSERT_EQUALS(p_type->IsType<TransitCellProliferativeType>(), false); MAKE_PTR(StemCellProliferativeType, p_stem_type); MAKE_PTR(TransitCellProliferativeType, p_transit_type); TS_ASSERT(p_stem_type->IsSame(p_type.get())); TS_ASSERT(p_type->IsSame(p_stem_type)); TS_ASSERT_EQUALS(p_stem_type->IsSame(p_transit_type.get()), false); TS_ASSERT_EQUALS(p_transit_type->IsSame(p_stem_type), false); // Check that const-ness doesn't matter TS_ASSERT(p_stem_type->IsType<const StemCellProliferativeType>()); const StemCellProliferativeType const_stem_type; TS_ASSERT(p_stem_type->IsSame(&const_stem_type)); TS_ASSERT(const_stem_type.IsSame(p_stem_type)); TS_ASSERT(const_stem_type.IsSame(p_stem_type.get())); }
void TestConstruct1dParallelPopulation() throw (Exception) { NodesOnlyMesh<1> mesh; mesh.SetMaximumInteractionDistance(0.5); std::vector<CellPtr> cells; ParallelCellsGenerator<FixedDurationGenerationBasedCellCycleModel, 1> generator; c_vector<double, 2> bounding_box = generator.GetArchiveBoundingBox("cell_based/test/data/TestParallelConstruction/Population1d.dat"); TS_ASSERT_DELTA(bounding_box[0], 0.0, 1e-4); TS_ASSERT_DELTA(bounding_box[1], 1.0, 1e-4); // Check an assertion which tests whether the space dimensions of the mesh and archive file are consistent. TS_ASSERT_THROWS_THIS(generator.GetArchiveBoundingBox("cell_based/test/data/TestParallelConstruction/Population2d.dat"), "Space dimension of ParallelCellsGenerator and archive file do not match"); generator.GenerateParallelCells("cell_based/test/data/TestParallelConstruction/Population1d.dat", cells, mesh, CellPropertyRegistry::Instance()->Get<DifferentiatedCellProliferativeType>()); unsigned num_nodes = mesh.GetNumNodes(); unsigned total_nodes; MPI_Allreduce(&num_nodes, &total_nodes, 1, MPI_UNSIGNED, MPI_SUM, PetscTools::GetWorld()); TS_ASSERT_EQUALS(total_nodes, 2u); unsigned num_cells = cells.size(); unsigned total_cells; MPI_Allreduce(&num_cells, &total_cells, 1, MPI_UNSIGNED, MPI_SUM, PetscTools::GetWorld()); TS_ASSERT_EQUALS(total_cells, 2u); for (unsigned i=0; i<cells.size(); i++) { TS_ASSERT(cells[i]->GetCellProliferativeType()->IsType<DifferentiatedCellProliferativeType>()); } }
/** * 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 TestAttributes() throw (Exception) { ParameterisedOde ode; TS_ASSERT_EQUALS(ode.GetNumberOfAttributes(), 1u); TS_ASSERT(ode.HasAttribute("attr")); TS_ASSERT_DELTA(ode.GetAttribute("attr"), 1.1, 1e-12); TS_ASSERT(!ode.HasAttribute("missing")); TS_ASSERT_THROWS_THIS(ode.GetAttribute("missing"), "No attribute 'missing' found."); boost::shared_ptr<const AbstractOdeSystemInformation> p_info = ode.GetSystemInformation(); TS_ASSERT_EQUALS(p_info->GetNumberOfAttributes(), 1u); TS_ASSERT(p_info->HasAttribute("attr")); TS_ASSERT_DELTA(p_info->GetAttribute("attr"), 1.1, 1e-12); TS_ASSERT(!p_info->HasAttribute("missing")); TS_ASSERT_THROWS_THIS(p_info->GetAttribute("missing"), "No attribute 'missing' found."); }
void TestRefreshHaloCells() throw (Exception) { #if BOOST_VERSION < 103700 TS_ASSERT_THROWS_THIS(mpNodeBasedCellPopulation->SendCellsToNeighbourProcesses(), "Parallel cell-based Chaste requires Boost >= 1.37"); #else // Set up the halo boxes and nodes. mpNodeBasedCellPopulation->Update(); // Send and receive halo nodes. mpNodeBasedCellPopulation->RefreshHaloCells(); mpNodeBasedCellPopulation->AddReceivedHaloCells(); if (!PetscTools::AmMaster() && !PetscTools::AmTopMost()) { TS_ASSERT_EQUALS(mpNodeBasedCellPopulation->mHaloCells.size(), 2u); TS_ASSERT_EQUALS(mpNodeBasedCellPopulation->mHaloCellLocationMap[mpNodeBasedCellPopulation->mHaloCells[0]], PetscTools::GetMyRank() - 1); TS_ASSERT_EQUALS(mpNodeBasedCellPopulation->mHaloCellLocationMap[mpNodeBasedCellPopulation->mHaloCells[1]], PetscTools::GetMyRank() + 1); } else if (!PetscTools::AmMaster() || !PetscTools::AmTopMost()) { TS_ASSERT_EQUALS(mpNodeBasedCellPopulation->mHaloCells.size(), 1u); } #endif }
void TestSendAndRecieveCellsNonBlocking() throw (Exception) { unsigned index_of_node_to_send = mpNodesOnlyMesh->GetNodeIteratorBegin()->GetIndex();; mpNodeBasedCellPopulation->AddNodeAndCellToSendRight(index_of_node_to_send); mpNodeBasedCellPopulation->AddNodeAndCellToSendLeft(index_of_node_to_send); TS_ASSERT_EQUALS(mpNodeBasedCellPopulation->mCellCommunicationTag, 123u); TS_ASSERT(!(mpNodeBasedCellPopulation->mpCellsRecvRight)); TS_ASSERT(!(mpNodeBasedCellPopulation->mpCellsRecvLeft)); #if BOOST_VERSION < 103700 TS_ASSERT_THROWS_THIS(mpNodeBasedCellPopulation->SendCellsToNeighbourProcesses(), "Parallel cell-based Chaste requires Boost >= 1.37"); #else mpNodeBasedCellPopulation->NonBlockingSendCellsToNeighbourProcesses(); mpNodeBasedCellPopulation->GetReceivedCells(); if (!PetscTools::AmTopMost()) { TS_ASSERT_EQUALS(mpNodeBasedCellPopulation->mpCellsRecvRight->size(), 1u); unsigned index = (*mpNodeBasedCellPopulation->mpCellsRecvRight->begin()).second->GetIndex(); TS_ASSERT_EQUALS(index, PetscTools::GetMyRank() + 1); } if (!PetscTools::AmMaster()) { TS_ASSERT_EQUALS(mpNodeBasedCellPopulation->mpCellsRecvLeft->size(), 1u); unsigned index = (*mpNodeBasedCellPopulation->mpCellsRecvLeft->begin()).second->GetIndex(); TS_ASSERT_EQUALS(index, PetscTools::GetMyRank() - 1); } #endif }
void TestAddInitialApex() 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(); AirwayGenerator generator(sphere); double origin[3] = {0.0, 1.0, 0.0}; double direction[3] = {0.0, 1.0, 0.0}; double parent_direction[3] = {1.0, 0.0, 0.0}; generator.AddInitialApex(origin, direction, parent_direction, 10.0, 0); generator.AddInitialApex(origin, direction, parent_direction, 10.0, 1); generator.AddInitialApex(origin, direction, parent_direction, 10.0, 1); generator.AddInitialApex(origin, direction, parent_direction, 10.0, 3); TS_ASSERT_EQUALS(generator.GetGenerations().size(), 30u); TS_ASSERT_EQUALS(generator.GetGenerations()[0].GetApices().size(), 1u); TS_ASSERT_EQUALS(generator.GetGenerations()[1].GetApices().size(), 2u); TS_ASSERT_EQUALS(generator.GetGenerations()[2].GetApices().size(), 0u); TS_ASSERT_EQUALS(generator.GetGenerations()[3].GetApices().size(), 1u); TS_ASSERT_EQUALS(generator.GetAirwayTree()->GetNumberOfPoints(), 4); //The generator only supports generations up to 30 TS_ASSERT_THROWS_THIS(generator.AddInitialApex(origin, direction, parent_direction, 10.0, 35), "Error: Airway generation can only generate up to 30 generations."); #endif }
void TestCellMutationStateMethods() throw(Exception) { MAKE_PTR(WildTypeCellMutationState, p_state); TS_ASSERT_EQUALS(p_state->GetCellCount(), 0u); p_state->IncrementCellCount(); TS_ASSERT_EQUALS(p_state->GetCellCount(), 1u); p_state->DecrementCellCount(); TS_ASSERT_EQUALS(p_state->GetCellCount(), 0u); TS_ASSERT_THROWS_THIS(p_state->DecrementCellCount(), "Cannot decrement cell count: no cells have this cell property"); TS_ASSERT_EQUALS(p_state->GetColour(), 0u); TS_ASSERT_EQUALS(p_state->IsType<WildTypeCellMutationState>(), true); TS_ASSERT_EQUALS(p_state->IsType<ApcOneHitCellMutationState>(), false); MAKE_PTR(WildTypeCellMutationState, p_wt_state); MAKE_PTR(ApcTwoHitCellMutationState, p_apc2_state); TS_ASSERT(p_wt_state->IsSame(p_state.get())); TS_ASSERT(p_state->IsSame(p_wt_state)); TS_ASSERT_EQUALS(p_wt_state->IsSame(p_apc2_state.get()), false); TS_ASSERT_EQUALS(p_apc2_state->IsSame(p_wt_state), false); // Check that const-ness doesn't matter TS_ASSERT(p_wt_state->IsType<const WildTypeCellMutationState>()); const WildTypeCellMutationState const_wt_state; TS_ASSERT(p_wt_state->IsSame(&const_wt_state)); TS_ASSERT(const_wt_state.IsSame(p_wt_state)); TS_ASSERT(const_wt_state.IsSame(p_wt_state.get())); }
void TestExceptions() throw (Exception) { // Only TrianglesMeshReader supports cables MemfemMeshReader<3,3> memfem_reader("mesh/test/data/Memfem_slab"); TS_ASSERT_EQUALS(memfem_reader.GetNumCableElements(), 0u); TS_ASSERT_EQUALS(memfem_reader.GetNumCableElementAttributes(), 0u); TS_ASSERT_THROWS_THIS(memfem_reader.GetNextCableElementData(), "Cable elements are not supported by this mesh format."); }
void TestReading3dMeshWithPermutation() throw (Exception) { const unsigned ELEMENT_DIM = 3; const unsigned SPACE_DIM = 3; TrianglesMeshReader<ELEMENT_DIM,SPACE_DIM> mesh_reader_3d_ascii("mesh/test/data/simple_cube"); TrianglesMeshReader<ELEMENT_DIM,SPACE_DIM> mesh_reader_3d("mesh/test/data/simple_cube_binary"); TrianglesMeshReader<ELEMENT_DIM,SPACE_DIM> mesh_reader_3d_permuted("mesh/test/data/simple_cube_binary"); unsigned num_nodes = mesh_reader_3d.GetNumNodes(); std::vector<unsigned> permutation(num_nodes); for (unsigned node_index=0; node_index < num_nodes; node_index++) { permutation[node_index] = num_nodes-node_index-1; } TS_ASSERT_THROWS_THIS(mesh_reader_3d_ascii.SetNodePermutation(permutation), "Permuted read can only be used with binary files since it requires random access to the node file."); TS_ASSERT_EQUALS(mesh_reader_3d_permuted.HasNodePermutation(), false); TS_ASSERT_EQUALS(mesh_reader_3d_permuted.rGetNodePermutation().size(), 0u); mesh_reader_3d_permuted.SetNodePermutation(permutation); TS_ASSERT_EQUALS(mesh_reader_3d_permuted.HasNodePermutation(), true); TS_ASSERT_EQUALS(mesh_reader_3d_permuted.rGetNodePermutation().size(), 9u); TS_ASSERT_EQUALS(mesh_reader_3d_permuted.rGetNodePermutation()[8], 0u); TS_ASSERT_EQUALS(mesh_reader_3d_permuted.rGetNodePermutation()[0], 8u); for (unsigned node_index=0; node_index < num_nodes; node_index++) { for (unsigned dimension=0; dimension<SPACE_DIM; dimension++) { TS_ASSERT_EQUALS( mesh_reader_3d.GetNode(permutation[node_index])[dimension], mesh_reader_3d_permuted.GetNode(node_index)[dimension]); } } for (unsigned element_index=0; element_index < mesh_reader_3d.GetNumElements(); element_index++) { for (unsigned local_node_index = 0; local_node_index < ELEMENT_DIM+1; local_node_index++) { unsigned original_mesh_global_index = mesh_reader_3d.GetElementData(element_index).NodeIndices[local_node_index]; unsigned permuted_mesh_global_index = mesh_reader_3d_permuted.GetElementData(element_index).NodeIndices[local_node_index]; TS_ASSERT_EQUALS(permutation[original_mesh_global_index], permuted_mesh_global_index); } } for (unsigned boundary_ele_index=0; boundary_ele_index < mesh_reader_3d.GetNumElements(); boundary_ele_index++) { for (unsigned local_node_index = 0; local_node_index < ELEMENT_DIM; local_node_index++) { unsigned original_mesh_global_index = mesh_reader_3d.GetFaceData(boundary_ele_index).NodeIndices[local_node_index]; unsigned permuted_mesh_global_index = mesh_reader_3d_permuted.GetFaceData(boundary_ele_index).NodeIndices[local_node_index]; TS_ASSERT_EQUALS(permutation[original_mesh_global_index], permuted_mesh_global_index); } } }
void TestSpecifyingSecondaryArchive() throw (Exception) { FileFinder archive_dir("archive", RelativeTo::ChasteTestOutput); std::string archive_file = "specific_secondary.arch"; const unsigned test_int = 321; const unsigned proc_id = PetscTools::GetMyRank(); // Writing when specifying the secondary archive doesn't make sense { TS_ASSERT_THROWS_THIS(OutputArchiveOpener archive_opener_out(archive_dir, archive_file, UINT_MAX), "Specifying the secondary archive file ID doesn't make sense when writing."); } // Write normally so we can test reading { OutputArchiveOpener archive_opener_out(archive_dir, archive_file); boost::archive::text_oarchive* p_arch = archive_opener_out.GetCommonArchive(); boost::archive::text_oarchive* p_process_arch = ProcessSpecificArchive<boost::archive::text_oarchive>::Get(); (*p_arch) & test_int; // All can write to the common archive - non-masters will write to /dev/null. (*p_process_arch) & proc_id; // archive_opener_out will do a PetscTools::Barrier when it is destructed } // Read { TS_ASSERT_THROWS_THIS(ProcessSpecificArchive<boost::archive::text_oarchive>::Get(), "A ProcessSpecificArchive has not been set up."); TS_ASSERT_THROWS_THIS(ProcessSpecificArchive<boost::archive::text_iarchive>::Get(), "A ProcessSpecificArchive has not been set up."); InputArchiveOpener archive_opener_in(archive_dir, archive_file, 0); boost::archive::text_iarchive* p_arch = archive_opener_in.GetCommonArchive(); boost::archive::text_iarchive* p_process_arch = ProcessSpecificArchive<boost::archive::text_iarchive>::Get(); unsigned test_int1, test_int2; (*p_arch) & test_int1; (*p_process_arch) & test_int2; TS_ASSERT_EQUALS(test_int1, test_int); TS_ASSERT_EQUALS(test_int2, 0u); } }