/**
     * 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));
    }
Esempio n. 6
0
    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());
    }
Esempio n. 8
0
    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);
    }
Esempio n. 9
0
    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);
        
    }
Esempio n. 10
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));
 }
Esempio n. 11
0
    /**
     * 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");
    }
Esempio n. 14
0
    /**
     * 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");
    }
Esempio n. 15
0
    /**
     * 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);
    }
Esempio n. 17
0
    /**
     * 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);
    }
Esempio n. 20
0
    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
    }
Esempio n. 21
0
    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
    }
Esempio n. 23
0
    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
    }
Esempio n. 24
0
    /**
     * 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");
    }
Esempio n. 25
0
    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();
    }
Esempio n. 26
0
    /**
     * 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);
    }
Esempio n. 28
0
    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));
    }