示例#1
0
    void TestGenerateBasicRandomWithFixedDurationGenerationBasedCellCycleModel() throw(Exception)
    {
        // Create mesh
        TrianglesMeshReader<2,2> mesh_reader("mesh/test/data/square_2_elements");
        TetrahedralMesh<2,2> mesh;
        mesh.ConstructFromMeshReader(mesh_reader);

        // Create cells
        MAKE_PTR(TransitCellProliferativeType, p_transit_type);
        std::vector<CellPtr> cells;
        CellsGenerator<FixedDurationGenerationBasedCellCycleModel, 2> cells_generator;
        cells_generator.GenerateBasicRandom(cells, mesh.GetNumNodes(), p_transit_type);

        // Test that cells were generated correctly
        TS_ASSERT_EQUALS(cells.size(), mesh.GetNumNodes());

        for (unsigned i=0; i<cells.size(); i++)
        {
            // Should lie between -24 and 0
            TS_ASSERT_LESS_THAN_EQUALS(cells[i]->GetBirthTime(), 0.0);
            TS_ASSERT_LESS_THAN_EQUALS(-24.0, cells[i]->GetBirthTime());
            TS_ASSERT_EQUALS(cells[i]->GetCellCycleModel()->GetDimension(), 2u);
            TS_ASSERT_EQUALS(cells[i]->GetCellProliferativeType(), p_transit_type);
        }

        // Test exact random numbers as test re-seeds random number generator.
        TS_ASSERT_DELTA(cells[0]->GetBirthTime(), -7.1141, 1e-4);
        TS_ASSERT_DELTA(cells[1]->GetBirthTime(), -10.1311, 1e-4);
        TS_ASSERT_DELTA(cells[2]->GetBirthTime(), -10.2953, 1e-4);
    }
示例#2
0
    void TestGenerateBasicRandomWithFixedDurationGenerationBasedCellCycleModelandVertexCells() throw(Exception)
    {
        EXIT_IF_PARALLEL;
        // Create mesh
        HoneycombVertexMeshGenerator mesh_generator(2, 2);
        VertexMesh<2,2>* p_mesh = mesh_generator.GetMesh();

        // Create cells
        std::vector<CellPtr> cells;
        MAKE_PTR(TransitCellProliferativeType, p_transit_type);
        CellsGenerator<FixedDurationGenerationBasedCellCycleModel, 2> cells_generator;
        cells_generator.GenerateBasicRandom(cells, p_mesh->GetNumElements(), p_transit_type);

        // Test that cells were generated correctly
        TS_ASSERT_EQUALS(cells.size(), p_mesh->GetNumElements());

        for (unsigned i=0; i<cells.size(); i++)
        {
            // Shold lie between -24 and 0
            TS_ASSERT_LESS_THAN_EQUALS(cells[i]->GetBirthTime(), 0.0);
            TS_ASSERT_LESS_THAN_EQUALS(-24.0, cells[i]->GetBirthTime());
            TS_ASSERT_EQUALS(cells[i]->GetCellCycleModel()->GetDimension(), 2u);
            TS_ASSERT_EQUALS(cells[i]->GetCellProliferativeType(), p_transit_type);
        }

        // Test exact random numbers as test re-seeds random number generator.
        TS_ASSERT_DELTA(cells[0]->GetBirthTime(), -7.1141, 1e-4);
        TS_ASSERT_DELTA(cells[1]->GetBirthTime(), -10.1311, 1e-4);
        TS_ASSERT_DELTA(cells[2]->GetBirthTime(), -10.2953, 1e-4);
    }
示例#3
0
void CheckMonoLr91Vars(MonodomainProblem<ELEMENT_DIM, SPACE_DIM>& problem)
{

    DistributedVector voltage = problem.rGetMesh().GetDistributedVectorFactory()->CreateDistributedVector(problem.GetSolution());
    for (DistributedVector::Iterator index = voltage.Begin();
         index != voltage.End();
         ++index)
    {
        // assuming LR model has Ena = 54.4 and Ek = -77
        double Ena   =  54.4;
        double Ek    = -77.0;

        TS_ASSERT_LESS_THAN_EQUALS( voltage[index] , Ena +  30);
        TS_ASSERT_LESS_THAN_EQUALS(-voltage[index] + (Ek-30), 0);

        std::vector<double> ode_vars = problem.GetMonodomainTissue()->GetCardiacCell(index.Global)->GetStdVecStateVariables();
        for (int j=0; j<8; j++)
        {
            // if not voltage or calcium ion conc, test whether between 0 and 1
            if ((j!=0) && (j!=7))
            {
                TS_ASSERT_LESS_THAN_EQUALS(  ode_vars[j], 1.0);
                TS_ASSERT_LESS_THAN_EQUALS( -ode_vars[j], 0.0);
            }
        }
    }
}
    void TestSloughingCellKillerTopAndSides() throw(Exception)
    {
        // Create mesh
        TrianglesMeshReader<2,2> mesh_reader("mesh/test/data/square_128_elements");
        MutableMesh<2,2> mesh;
        mesh.ConstructFromMeshReader(mesh_reader);
        mesh.Translate(-0.25,-0.25);

        // Create cells
        std::vector<CellPtr> cells;
        CellsGenerator<FixedDurationGenerationBasedCellCycleModel, 2> cells_generator;
        cells_generator.GenerateBasic(cells, mesh.GetNumNodes());

        // Create cell population
        MeshBasedCellPopulation<2> cell_population(mesh, cells);

        // Create cell killer and kill cells
        SloughingCellKiller<2> sloughing_cell_killer(&cell_population, 0.5, true, 0.5);

        sloughing_cell_killer.CheckAndLabelCellsForApoptosisOrDeath();

        TS_ASSERT_EQUALS(sloughing_cell_killer.GetIdentifier(), "SloughingCellKiller-2");

        // Check that cells were labelled for death correctly
        for (AbstractCellPopulation<2>::Iterator cell_iter = cell_population.Begin();
             cell_iter != cell_population.End();
             ++cell_iter)
        {
            double x = cell_population.GetLocationOfCellCentre(*cell_iter)[0];
            double y = cell_population.GetLocationOfCellCentre(*cell_iter)[1];

            if ((x<0) || (x>0.5) || (y>0.5))
            {
                TS_ASSERT_EQUALS(cell_iter->IsDead(), true);
            }
            else
            {
                TS_ASSERT_EQUALS(cell_iter->IsDead(), false);
            }
        }

        cell_population.RemoveDeadCells();

        for (AbstractCellPopulation<2>::Iterator cell_iter = cell_population.Begin();
             cell_iter != cell_population.End();
             ++cell_iter)
        {
            double x = cell_population.GetLocationOfCellCentre(*cell_iter)[0];
            double y = cell_population.GetLocationOfCellCentre(*cell_iter)[1];

            TS_ASSERT_LESS_THAN_EQUALS(x, 0.5);
            TS_ASSERT_LESS_THAN_EQUALS(y, 0.5);
        }
    }
示例#5
0
    /**
     * Initializes a matrix with the specified id.
     *   Global matrices are set to the corresponding values,
     *   local matrices initialized with random values.
     *
     * @param i_id id of the matrix {0, .., 51} -> flux matrix, {52} -> jacobian (flux solver), {53, 54, 55} -> stiffness matrices, {56, 57, 58} -> transposed stiffness matrices, {59} -> jacobian (star matrix)
     * @param i_numberOfRows number of rows.
     * @param i_numberOfColumns number of columns.
     * @param o_matrix matrix, which is initialized.
     **/
    void initializeMatrix( unsigned int i_id,
                           unsigned int i_numberOfRows,
                           unsigned int i_numberOfColumns,
                           real*        o_matrix ) {
      // assert the matrices have been read
      assert( m_matrixIds.size() > 0 );

      // get the position of our matrix
      unsigned int l_position;
      for( l_position = 0; l_position < m_matrixIds.size(); l_position++ ) {
        if( i_id == m_matrixIds[l_position] ) {
          break;
        }
        else {
          // matrix with the given id couldn't be found
          TS_ASSERT_DIFFERS( l_position, m_matrixIds.size() -1 );
        }
      }

      // flux solver -> random values
      if( i_id == 52 ) {
        // assert correct matrix id
        TS_ASSERT_EQUALS( m_matrixIds[l_position], 52 );
        setRandomValues( i_numberOfRows * i_numberOfColumns,
                         o_matrix );
      } 
      // flux matrix, stiffness matrix or star matrix
      else {
        std::fill( o_matrix, o_matrix + i_numberOfRows * i_numberOfColumns, 0 );
        for( unsigned int l_element = 0; l_element < m_matrixRows[l_position].size(); l_element++ ) {
          // assert that we can save the non-zero element
          TS_ASSERT_LESS_THAN_EQUALS( m_matrixRows[l_position][l_element],    i_numberOfRows);
          TS_ASSERT_LESS_THAN_EQUALS( m_matrixColumns[l_position][l_element], i_numberOfColumns);

          unsigned int l_denseIndex = (m_matrixColumns[l_position][l_element]-1) * i_numberOfRows + (m_matrixRows[l_position][l_element]-1);

          // assert this a valid index
          TS_ASSERT_LESS_THAN( l_denseIndex, i_numberOfRows*i_numberOfColumns );

          if( i_id == 59 ) { // star matrix
            o_matrix[ l_denseIndex ] = ((real)rand()/(real)RAND_MAX)*10.0;
          }
          else if( i_id >= 56 && i_id <= 58 ) { // add minus-sign for time kernel
            o_matrix[ l_denseIndex ] = -m_matrixValues[l_position][l_element];
          }
          else{ // flux or stiffness matrix
            o_matrix[ l_denseIndex ] =  m_matrixValues[l_position][l_element];
          }
        }
      }
    }
示例#6
0
    void TestGenerateBasicRandomWithNoSpecifiedProliferativeCellType() throw(Exception)
    {
        // Create mesh
        TrianglesMeshReader<2,2> mesh_reader("mesh/test/data/square_2_elements");
        TetrahedralMesh<2,2> mesh;
        mesh.ConstructFromMeshReader(mesh_reader);

        // Create cells
        std::vector<CellPtr> cells;
        CellsGenerator<FixedDurationGenerationBasedCellCycleModel, 2> cells_generator;
        cells_generator.GenerateBasicRandom(cells, mesh.GetNumNodes());

        // Test that cells were generated correctly
        TS_ASSERT_EQUALS(cells.size(), mesh.GetNumNodes());

        for (unsigned i=0; i<cells.size(); i++)
        {
            TS_ASSERT_EQUALS(cells[i]->GetCellCycleModel()->GetDimension(), 2u);
            TS_ASSERT_EQUALS(cells[i]->GetCellProliferativeType()->IsType<StemCellProliferativeType>(), true);
            // Should lie between -24 and 0
            double birth_time=cells[i]->GetBirthTime();
            ///\todo Breaks Intel 10? TS_ASSERT_LESS_THAN_EQUALS(birth_time, 0.0);
            TS_ASSERT_LESS_THAN_EQUALS(-24.0, birth_time);
        }
    }
示例#7
0
文件: vector.cpp 项目: onitake/glam
	void testSize() {
		TS_TRACE(std::string("sizeof(float) is ") + std::to_string(sizeof(float)));
		TS_TRACE(std::string("sizeof(vec2) is ") + std::to_string(sizeof(glam::vec2)));
		TS_TRACE(std::string("sizeof(vec4) is ") + std::to_string(sizeof(glam::vec4)));
		TS_TRACE(std::string("sizeof(bool) is ") + std::to_string(sizeof(bool)));
		TS_TRACE(std::string("sizeof(bvec4) is ") + std::to_string(sizeof(glam::bvec4)));
		TS_TRACE(std::string("sizeof(int) is ") + std::to_string(sizeof(int)));
		TS_TRACE(std::string("sizeof(ivec2) is ") + std::to_string(sizeof(glam::ivec2)));
		TS_TRACE(std::string("sizeof(double) is ") + std::to_string(sizeof(double)));
		TS_TRACE(std::string("sizeof(dvec3) is ") + std::to_string(sizeof(glam::dvec3)));
		// A vectorized implementation may pad to up to 4 vector elements to improve SIMD performance, but not more
		TS_ASSERT_LESS_THAN_EQUALS(sizeof(glam::Vector<float, 4>), sizeof(float) * 4);
		TS_ASSERT_LESS_THAN_EQUALS(sizeof(glam::Vector<double, 2>), sizeof(double) * 4);
		TS_ASSERT_LESS_THAN_EQUALS(sizeof(glam::Vector<bool, 4>), sizeof(bool) * 4);
		TS_ASSERT_LESS_THAN_EQUALS(sizeof(glam::Vector<int, 256>), sizeof(int) * 256);
	}
示例#8
0
    /*
     * Check that the submatrix of A with size B matches B.
     *
     * @param i_A values of matrix A.
     * @param i_aNumberOfRows number of rows of A.
     * @param i_aNumberOfColumns number of columns of A.
     * @param o_B values of matrix B, which will be set.
     * @param i_bNumberOfRows number of rows of matrix B.
     * @param i_bNumberOfColumns number of columns of matrix B
     */
    void checkSubMatrix( const real* i_A,
                         const unsigned int i_aNumberOfRows,
                         const unsigned int i_aNumberOfColumns,
                         const real* i_B,
                         const unsigned int i_bNumberOfRows,
                         const unsigned int i_bNumberOfColumns ) {
      // assert that B is a submatrix of A
      TS_ASSERT_LESS_THAN_EQUALS( i_bNumberOfRows,    i_aNumberOfRows    );
      TS_ASSERT_LESS_THAN_EQUALS( i_bNumberOfColumns, i_aNumberOfColumns );

      for( unsigned int l_column = 0; l_column < i_bNumberOfColumns; l_column++ ) {
        unsigned int l_aStart = l_column*i_aNumberOfRows;
        unsigned int l_bStart = l_column*i_bNumberOfRows;

        // check result column wise
        checkResult( i_bNumberOfRows, &i_A[l_aStart], &i_B[l_bStart] );
      }
    }
示例#9
0
    void TestEndBranchDistanceLimit() throw(Exception)
    {
    #if defined(CHASTE_VTK) && ( (VTK_MAJOR_VERSION >= 5 && VTK_MINOR_VERSION >= 6) || VTK_MAJOR_VERSION >= 6)
        EXIT_IF_PARALLEL;
        vtkSmartPointer<vtkPolyData> sphere = CreateSphere(100, 100.0); //lung sized sphere to test distance limit

        double min_branch_length = 0.1;
        unsigned point_limit = 1;
        double angle_limit = 180.0;
        double branching_fraction = 0.4;
        bool applyPointReassignmentLimit = true;

        AirwayGenerator generator(sphere, min_branch_length, point_limit, angle_limit, branching_fraction, applyPointReassignmentLimit);

        std::deque<AirwayGeneration>& generations = generator.GetGenerations();

        //The bounding box of the sphere is (-100,-100,-100) and (100,100,100), the diagonal of the bounding box is of size
        //sqrt(dx^2 + dy^2 + dz^2) where dx = dy = dz = 200.0
        double lobe_bound_size = sqrt(120000);

        for(unsigned generation_number = 0; generation_number < generations.size(); ++generation_number)
        {
            double scale_distance_limit = lobe_bound_size/30; //30 is the expected total number of generations
            TS_ASSERT_DELTA(generations[generation_number].GetDistributionRadius(), std::max(lobe_bound_size - scale_distance_limit*generation_number, 5.0), 1e-1);

        }

        double origin[3] = {0.0, 1.0, 0.0};
        double direction[3] = {1.0, 0.0, 0.0};
        double parent_direction[3] = {1.0, 0.0, 0.0};

        //Check that all points are distributed to an apex in generation 0
        generator.AddInitialApex(origin, direction, parent_direction, 10.0, 0);

        vtkSmartPointer<vtkPolyData> cloud = generator.CreatePointCloudUsingTargetPoints(1000);
        std::set<unsigned> invalid_ids;
        generations[0].DistributeGrowthPoints(cloud, invalid_ids);
        unsigned assigned_points = generations[0].GetApices()[0].mPointCloud->GetNumberOfPoints();
        unsigned total_points = cloud->GetNumberOfPoints();
        TS_ASSERT_EQUALS(assigned_points, total_points);

        //Check that the number of distributed points becomes less with each generation
        unsigned previous_assigned_points = assigned_points;
        for(unsigned generation_number = 1; generation_number < generations.size(); ++generation_number)
        {
            generator.AddInitialApex(origin, direction, parent_direction, 10.0, generation_number);

            generations[generation_number].DistributeGrowthPoints(cloud, invalid_ids);
            assigned_points = generations[generation_number].GetApices()[0].mPointCloud->GetNumberOfPoints();
            TS_ASSERT_LESS_THAN_EQUALS(assigned_points, previous_assigned_points);
            previous_assigned_points = assigned_points;
        }
    #endif
    }
    void TestSloughingCellKillerIn1d() throw(Exception)
    {
        // Create 1D mesh
        unsigned num_cells = 14;
        MutableMesh<1,1> mesh;
        mesh.ConstructLinearMesh(num_cells-1);

        // Create cells
        std::vector<CellPtr> cells;
        CellsGenerator<FixedDurationGenerationBasedCellCycleModel, 2> cells_generator;
        cells_generator.GenerateBasic(cells, mesh.GetNumNodes());

        // Create cell population
        MeshBasedCellPopulation<1> cell_population(mesh, cells);

        // Set the crypt length so that 2 cells should be sloughed off
        double crypt_length = 12.5;

        // Create cell killer and kill cells
        SloughingCellKiller<1> sloughing_cell_killer(&cell_population, crypt_length);
        sloughing_cell_killer.CheckAndLabelCellsForApoptosisOrDeath();

        // Check that cells were labelled for death correctly
        for (AbstractCellPopulation<1>::Iterator cell_iter = cell_population.Begin();
            cell_iter != cell_population.End();
            ++cell_iter)
        {
            double x = cell_population.GetLocationOfCellCentre(*cell_iter)[0];
            if (x > crypt_length)
            {
                TS_ASSERT_EQUALS(cell_iter->IsDead(), true);
            }
            else
            {
                TS_ASSERT_EQUALS(cell_iter->IsDead(), false);
            }
        }

        // Check that dead cells were correctly removed
        cell_population.RemoveDeadCells();

        for (AbstractCellPopulation<1>::Iterator cell_iter = cell_population.Begin();
             cell_iter != cell_population.End();
             ++cell_iter)
        {
            double x = cell_population.GetLocationOfCellCentre(*cell_iter)[0];
            TS_ASSERT_LESS_THAN_EQUALS(x, crypt_length);
        }
    }
    /**
     * Create a simulation of a NodeBasedCellPopulation with a BuskeInteractionForce system.
     * Test that no exceptions are thrown, and write the results to file.
     */
    void TestSimpleMonolayerWithBuskeAdhesiveForce() throw (Exception)
    {
        EXIT_IF_PARALLEL;    // HoneycombMeshGenerator doesn't work in parallel

        // Create a simple mesh
        HoneycombMeshGenerator generator(5, 5, 0);
        TetrahedralMesh<2,2>* p_generating_mesh = generator.GetMesh();

        // Convert this to a NodesOnlyMesh
        NodesOnlyMesh<2> mesh;
        mesh.ConstructNodesWithoutMesh(*p_generating_mesh, 1.5);

        // Create cells
        std::vector<CellPtr> cells;
        CellsGenerator<FixedDurationGenerationBasedCellCycleModel, 2> cells_generator;
        cells_generator.GenerateBasicRandom(cells, mesh.GetNumNodes());

        // Create a node-based cell population
        NodeBasedCellPopulation<2> node_based_cell_population(mesh, cells);

        // Set up cell-based simulation
        OffLatticeSimulation<2> simulator(node_based_cell_population);
        simulator.SetOutputDirectory("TestOffLatticeSimulationWithBuskeAdhesiveForce");
        simulator.SetEndTime(5.0);

        // Create a force law and pass it to the simulation
        MAKE_PTR(BuskeAdhesiveForce<2>, p_buske_adhesive_force);
        p_buske_adhesive_force->SetAdhesionEnergyParameter(0.002);
        simulator.AddForce(p_buske_adhesive_force);

        simulator.Solve();

        // Check that nothing's gone badly wrong by testing that nodes aren't too close together
        double min_distance_between_cells = 1.0;

        for (unsigned i=0; i<simulator.rGetCellPopulation().GetNumNodes(); i++)
        {
            for (unsigned j=i+1; j<simulator.rGetCellPopulation().GetNumNodes(); j++)
            {
                double distance = norm_2(simulator.rGetCellPopulation().GetNode(i)->rGetLocation()-simulator.rGetCellPopulation().GetNode(j)->rGetLocation());
                if (distance < min_distance_between_cells)
                {
                    min_distance_between_cells = distance;
                }
            }
        }

        TS_ASSERT_LESS_THAN_EQUALS(1e-3, min_distance_between_cells);
    }
    void TestSolvePdeAndWriteResultsToFileWithCoarsePdeMesh() throw(Exception)
    {
        EXIT_IF_PARALLEL;

        // Set up SimulationTime
        SimulationTime::Instance()->SetEndTimeAndNumberOfTimeSteps(0.05, 6);

        // Create a cell population
        HoneycombMeshGenerator generator(5, 5, 0);
        MutableMesh<2,2>* p_mesh = generator.GetMesh();

        std::vector<CellPtr> cells;
        CellsGenerator<FixedDurationGenerationBasedCellCycleModel, 2> cells_generator;
        cells_generator.GenerateBasic(cells, p_mesh->GetNumNodes());

        MeshBasedCellPopulation<2> cell_population(*p_mesh, cells);

        // Create a PDE handler object using this cell population
        CellBasedPdeHandler<2> pde_handler(&cell_population);

        // Set up PDE and pass to handler
        AveragedSourcePde<2> pde(cell_population, -0.1);
        ConstBoundaryCondition<2> bc(1.0);
        PdeAndBoundaryConditions<2> pde_and_bc(&pde, &bc, false);
        pde_and_bc.SetDependentVariableName("quantity 1");
        pde_handler.AddPdeAndBc(&pde_and_bc);

        // Set up second PDE and pass to handler
        AveragedSourcePde<2> pde2(cell_population, -0.5);
        PdeAndBoundaryConditions<2> pde_and_bc2(&pde2, &bc, false);
        TS_ASSERT_THROWS_THIS(pde_handler.AddPdeAndBc(&pde_and_bc2), "When adding more than one PDE to CellBasedPdeHandler set the dependent variable name using SetDependentVariableName(name).");
        pde_and_bc2.SetDependentVariableName("quantity 1");
        TS_ASSERT_THROWS_THIS(pde_handler.AddPdeAndBc(&pde_and_bc2), "The name quantity 1 has already been used in the PDE collection");
        pde_and_bc2.SetDependentVariableName("quantity 2");
        pde_handler.AddPdeAndBc(&pde_and_bc2);

        // Solve PDEs on a coarse mesh
        ChastePoint<2> lower(0.0, 0.0);
        ChastePoint<2> upper(50.0, 50.0);
        ChasteCuboid<2> cuboid(lower, upper);
        pde_handler.UseCoarsePdeMesh(10.0, cuboid, true);
        pde_handler.SetImposeBcsOnCoarseBoundary(false);

        // Open result file ourselves
        OutputFileHandler output_file_handler("TestSolvePdeAndWriteResultsToFileWithCoarsePdeMesh", false);
        pde_handler.mpVizPdeSolutionResultsFile = output_file_handler.OpenOutputFile("results.vizpdesolution");

        // Solve PDEs and (for coverage) write results to file
        pde_handler.SolvePdeAndWriteResultsToFile(1);

        // Close result file ourselves
        pde_handler.mpVizPdeSolutionResultsFile->close();

        TetrahedralMesh<2,2>* p_coarse_mesh = pde_handler.GetCoarsePdeMesh();
        TS_ASSERT(p_coarse_mesh != NULL);

        TS_ASSERT_THROWS_THIS(pde_handler.GetPdeSolution("quantity 3"), "The PDE collection does not contain a PDE named quantity 3");
        ReplicatableVector pde_solution0(pde_handler.GetPdeSolution("quantity 1"));
        ReplicatableVector pde_solution1(pde_handler.GetPdeSolution("quantity 2"));

        TS_ASSERT_EQUALS(pde_solution0.GetSize(), pde_solution1.GetSize());

        // Test that the solution is 1.0 at each coarse mesh node far from the cells
        for (unsigned i=0; i<pde_solution0.GetSize(); i++)
        {
            c_vector<double,2> centre;
            centre(0) = 2.5; // assuming 5x5 honeycomb mesh
            centre(1) = 2.5;

            c_vector<double,2> position = p_coarse_mesh->GetNode(i)->rGetLocation();
            double dist = norm_2(centre - position);
            double u0 = pde_solution0[i];
            double u1 = pde_solution1[i];

            if (dist > 4.0)
            {
                TS_ASSERT_DELTA(u0, 1.0, 1e-5);
                TS_ASSERT_DELTA(u1, 1.0, 1e-5);
            }
        }

        /*
         * Loop over cells, find the coarse mesh element containing it, then
         * check the interpolated PDE solution is between the min and max of
         * the PDE solution on the nodes of that element.
         */
        for (AbstractCellPopulation<2>::Iterator cell_iter = cell_population.Begin();
            cell_iter != cell_population.End();
            ++cell_iter)
        {
            c_vector<double,2> cell_location = cell_population.GetLocationOfCellCentre(*cell_iter);

            unsigned elem_index = p_coarse_mesh->GetContainingElementIndex(cell_location);
            Element<2,2>* p_element = p_coarse_mesh->GetElement(elem_index);

            unsigned node_0_index = p_element->GetNodeGlobalIndex(0);
            unsigned node_1_index = p_element->GetNodeGlobalIndex(1);
            unsigned node_2_index = p_element->GetNodeGlobalIndex(2);

            double max0 = std::max(pde_solution0[node_0_index], pde_solution0[node_1_index]);
            max0 = std::max(max0, pde_solution0[node_2_index]);

            double max1 = std::max(pde_solution1[node_0_index], pde_solution1[node_1_index]);
            max1 = std::max(max1, pde_solution1[node_2_index]);

            double min0 = std::min(pde_solution0[node_0_index], pde_solution0[node_1_index]);
            min0 = std::min(min0, pde_solution0[node_2_index]);

            double min1 = std::min(pde_solution1[node_0_index], pde_solution1[node_1_index]);
            min1 = std::min(min1, pde_solution1[node_2_index]);

            double value0_at_cell = cell_iter->GetCellData()->GetItem("quantity 1");
            double value1_at_cell = cell_iter->GetCellData()->GetItem("quantity 2");

            TS_ASSERT_LESS_THAN_EQUALS(value1_at_cell, value0_at_cell);
            TS_ASSERT_LESS_THAN_EQUALS(min0, value0_at_cell + DBL_EPSILON);
            TS_ASSERT_LESS_THAN_EQUALS(value0_at_cell, max0 + DBL_EPSILON);
            TS_ASSERT_LESS_THAN_EQUALS(min1, value1_at_cell + DBL_EPSILON);
            TS_ASSERT_LESS_THAN_EQUALS(value1_at_cell, max1 + DBL_EPSILON);

            // Now check the GetPdeSolutionAtPoint method matches
            TS_ASSERT_DELTA(pde_handler.GetPdeSolutionAtPoint(cell_location, "quantity 1"), value0_at_cell, 1e-6);
            TS_ASSERT_DELTA(pde_handler.GetPdeSolutionAtPoint(cell_location, "quantity 2"), value1_at_cell, 1e-6);
        }
    }
    void TestRadialSloughingCellKillerMethods() throw(Exception)
    {
        // Create mesh
        TrianglesMeshReader<2,2> mesh_reader("mesh/test/data/square_128_elements");
        MutableMesh<2,2> mesh;
        mesh.ConstructFromMeshReader(mesh_reader);
        mesh.Translate(-0.5,-0.5);

        // Get centre of mesh (we know it's at the origin, really)
        c_vector<double,2> centre(2);
        centre[0] = 0.0;
        centre[1] = 0.0;
        for (unsigned i=0; i<mesh.GetNumNodes(); i++)
        {
            centre += mesh.GetNode(i)->rGetLocation();
        }
        centre = centre/mesh.GetNumNodes();

        // Choose radius of cell killer
        double radius = 0.4;

        // Create cells
        std::vector<CellPtr> cells;
        CellsGenerator<FixedDurationGenerationBasedCellCycleModel, 2> cells_generator;
        cells_generator.GenerateBasic(cells, mesh.GetNumNodes());

        // Create cell population
        MeshBasedCellPopulation<2> cell_population(mesh, cells);

        // Create cell killer and kill cells
        RadialSloughingCellKiller radial_cell_killer(&cell_population, centre, radius);
        radial_cell_killer.CheckAndLabelCellsForApoptosisOrDeath();

        // Check that cells were labelled for death correctly
        for (AbstractCellPopulation<2>::Iterator cell_iter = cell_population.Begin();
             cell_iter != cell_population.End();
             ++cell_iter)
        {
            double r = norm_2(cell_population.GetLocationOfCellCentre(*cell_iter) - centre);

            if (r > radius)
            {
                TS_ASSERT_EQUALS(cell_iter->IsDead(), true);
            }
            else
            {
                TS_ASSERT_EQUALS(cell_iter->IsDead(), false);
            }
        }

        // Now get rid of dead cells
        cell_population.RemoveDeadCells();

        // Check that we are correctly left with cells inside the circle of death
        for (AbstractCellPopulation<2>::Iterator cell_iter = cell_population.Begin();
             cell_iter != cell_population.End();
             ++cell_iter)
        {
            double r = norm_2(cell_population.GetLocationOfCellCentre(*cell_iter) - centre);
            TS_ASSERT_LESS_THAN_EQUALS(r, radius);
        }
    }
    /**
     * Create a simulation of a NodeBasedCellPopulation with a Cylindrical2dNodesOnlyMesh
     * to test periodicity.
     */
    void TestSimplePeriodicMonolayer() throw (Exception)
    {
        EXIT_IF_PARALLEL;    // HoneycombMeshGenereator does not work in parallel.

        // Create a simple periodic mesh
        unsigned num_cells_depth = 3;
        unsigned num_cells_width = 3;
        HoneycombMeshGenerator generator(num_cells_width, num_cells_depth, 0);
        TetrahedralMesh<2,2>* p_generating_mesh = generator.GetMesh();

        // Convert this to a Cylindrical2dNodesOnlyMesh
        double periodic_width = 4.0;
        Cylindrical2dNodesOnlyMesh mesh(periodic_width);
        mesh.ConstructNodesWithoutMesh(*p_generating_mesh, periodic_width);

        // Create cells
        std::vector<CellPtr> cells;
        CellsGenerator<FixedDurationGenerationBasedCellCycleModel, 2> cells_generator;
        cells_generator.GenerateBasicRandom(cells, mesh.GetNumNodes());

        // Create a node-based cell population
        NodeBasedCellPopulation<2> node_based_cell_population(mesh, cells);

        // Set up cell-based simulation
        OffLatticeSimulation<2> simulator(node_based_cell_population);
        simulator.SetOutputDirectory("TestOffLatticeSimulationWithPeriodicNodeBasedCellPopulation");

        // Run for long enough to see the periodic bounday influencing the cells
        simulator.SetEndTime(10.0);

        // Create a force law and pass it to the simulation
        MAKE_PTR(GeneralisedLinearSpringForce<2>, p_linear_force);
        p_linear_force->SetCutOffLength(1.5);
        simulator.AddForce(p_linear_force);

        simulator.Solve();

        // Check that nothing's gone badly wrong by testing that nodes aren't outside the domain
        for (unsigned i=0; i<simulator.rGetCellPopulation().GetNumNodes(); i++)
        {
            TS_ASSERT_LESS_THAN_EQUALS(0,simulator.rGetCellPopulation().GetNode(i)->rGetLocation()[0]);
            TS_ASSERT_LESS_THAN_EQUALS(simulator.rGetCellPopulation().GetNode(i)->rGetLocation()[0],periodic_width);
        }

        // Now run the simulation again with the periodic boundary in a different place and check its the same

        // First reset the singletons
        SimulationTime::Instance()->Destroy();
        SimulationTime::Instance()->SetStartTime(0.0);
        RandomNumberGenerator::Instance()->Reseed(0);

        double x_offset = periodic_width/2.0;
        p_generating_mesh->Translate(x_offset,0.0);

        // Convert this to a Cylindrical2dNodesOnlyMesh
        Cylindrical2dNodesOnlyMesh mesh_2(periodic_width);
        mesh_2.ConstructNodesWithoutMesh(*p_generating_mesh, periodic_width);

        // Create cells
        std::vector<CellPtr> cells_2;
        CellsGenerator<FixedDurationGenerationBasedCellCycleModel, 2> cells_generator_2;
        cells_generator_2.GenerateBasicRandom(cells_2, mesh_2.GetNumNodes());

        // Create a node-based cell population
        NodeBasedCellPopulation<2> node_based_cell_population_2(mesh_2, cells_2);

        // Set up cell-based simulation
        OffLatticeSimulation<2> simulator_2(node_based_cell_population_2);
        simulator_2.SetOutputDirectory("TestOffLatticeSimulationWith2ndPeriodicNodeBasedCellPopulation");

        // Run for long enough to see the periodic boundary influencing the cells
        simulator_2.SetEndTime(10.0);

        // Pass the same force law to the simulation
        simulator_2.AddForce(p_linear_force);

        simulator_2.Solve();

        // Check that nothing's gone badly wrong by testing that nodes aren't outside the domain
        for (unsigned i=0; i<simulator.rGetCellPopulation().GetNumNodes(); i++)
        {
            double x_1 = simulator.rGetCellPopulation().GetNode(i)->rGetLocation()[0];
            double x_2 = simulator_2.rGetCellPopulation().GetNode(i)->rGetLocation()[0];

            if (x_1 < x_offset)
            {
                TS_ASSERT_DELTA(x_1+x_offset, x_2, 1e-6)
            }
            else
            {
                TS_ASSERT_DELTA(x_1-x_offset, x_2, 1e-6)
            }

            TS_ASSERT_DELTA(simulator.rGetCellPopulation().GetNode(i)->rGetLocation()[1],simulator_2.rGetCellPopulation().GetNode(i)->rGetLocation()[1],1e-6);
        }
    }
    void TestDistancesToCorner() throw (Exception)
    {
        TrianglesMeshReader<3,3> mesh_reader("mesh/test/data/cube_21_nodes_side/Cube21"); // 5x5x5mm cube (internode distance = 0.25mm)

        TetrahedralMesh<3,3> mesh;
        mesh.ConstructFromMeshReader(mesh_reader);

        unsigned num_nodes=9261u;
        TS_ASSERT_EQUALS(mesh.GetNumNodes(), num_nodes); // 21x21x21 nodes
        TS_ASSERT_EQUALS(mesh.GetNumElements(), 48000u);
        TS_ASSERT_EQUALS(mesh.GetNumBoundaryElements(), 4800u);

        DistributedTetrahedralMesh<3,3> parallel_mesh(DistributedTetrahedralMeshPartitionType::DUMB); // No reordering;
        parallel_mesh.ConstructFromMeshReader(mesh_reader);
        TS_ASSERT_EQUALS(parallel_mesh.GetNumNodes(), num_nodes); // 21x21x21 nodes
        TS_ASSERT_EQUALS(parallel_mesh.GetNumElements(), 48000u);
        TS_ASSERT_EQUALS(parallel_mesh.GetNumBoundaryElements(), 4800u);

        unsigned far_index=9260u;
        c_vector<double,3> far_corner=mesh.GetNode(far_index)->rGetLocation();
        TS_ASSERT_DELTA( far_corner[0], 0.25, 1e-11);
        TS_ASSERT_DELTA( far_corner[1], 0.25, 1e-11);
        TS_ASSERT_DELTA( far_corner[2], 0.25, 1e-11);
        try
        {
            c_vector<double,3> parallel_far_corner=parallel_mesh.GetNode(far_index)->rGetLocation();
            TS_ASSERT_DELTA( parallel_far_corner[0], 0.25, 1e-11);
            TS_ASSERT_DELTA( parallel_far_corner[1], 0.25, 1e-11);
            TS_ASSERT_DELTA( parallel_far_corner[2], 0.25, 1e-11);
        }
        catch (Exception&)
        {
        }

        std::vector<unsigned> map_far_corner;
        map_far_corner.push_back(far_index);

        DistanceMapCalculator<3,3> distance_calculator(mesh);
        std::vector<double> distances;
        distance_calculator.ComputeDistanceMap(map_far_corner, distances);

        DistanceMapCalculator<3,3> parallel_distance_calculator(parallel_mesh);
        std::vector<double> parallel_distances;
        parallel_distance_calculator.ComputeDistanceMap(map_far_corner, parallel_distances);

        TS_ASSERT_EQUALS(distance_calculator.mRoundCounter, 1u);
        //Nodes in mesh are order such that a dumb partitioning will give a sequential handover from proc0 to proc1...
        TS_ASSERT_EQUALS(parallel_distance_calculator.mRoundCounter, PetscTools::GetNumProcs());
        //Note unsigned division is okay here
        TS_ASSERT_DELTA(parallel_distance_calculator.mPopCounter, num_nodes/PetscTools::GetNumProcs(), 1u);
        TS_ASSERT_DELTA(distance_calculator.mPopCounter, num_nodes, 1u);
        for (unsigned index=0; index<distances.size(); index++)
        {
            c_vector<double, 3> node = mesh.GetNode(index)->rGetLocation();

            //Straightline distance
            double euclidean_distance = norm_2(far_corner - node);
            // x + y + z distance
            double manhattan_distance = norm_1(far_corner - node);
            //If they differ, then allow the in-mesh distance to be in between
            double error_bound = (manhattan_distance - euclidean_distance)/2.0;
            //If they don't differ, then we expect the in-mesh distance to be similar
            if (error_bound < 1e-15)
            {
                error_bound = 1e-15;
            }
            TS_ASSERT_LESS_THAN_EQUALS(distances[index], manhattan_distance+DBL_EPSILON);
            TS_ASSERT_LESS_THAN_EQUALS(euclidean_distance, distances[index]+DBL_EPSILON);
            TS_ASSERT_DELTA(distances[index], euclidean_distance, error_bound);

            TS_ASSERT_DELTA(distances[index], parallel_distances[index], 1e-15);
        }

        // Test some point-to-point distances
        RandomNumberGenerator::Instance()->Reseed(1);
        unsigned trials=25;
        unsigned pops=0;
        unsigned sequential_pops=0;
        for (unsigned i=0; i<trials; i++)
        {
            unsigned index=RandomNumberGenerator::Instance()->randMod(parallel_distances.size());
            TS_ASSERT_DELTA(parallel_distance_calculator.SingleDistance(9260u, index), parallel_distances[index], 1e-15);
            TS_ASSERT_DELTA(distance_calculator.SingleDistance(9260u, index), parallel_distances[index], 1e-15);
            pops += parallel_distance_calculator.mPopCounter;
            sequential_pops += distance_calculator.mPopCounter;
            TS_ASSERT_LESS_THAN_EQUALS(parallel_distance_calculator.mRoundCounter, PetscTools::GetNumProcs()+2);
        }

        // Without A*: TS_ASSERT_DELTA(sequential_pops/(double)trials, num_nodes/2, 300);
        TS_ASSERT_LESS_THAN(sequential_pops/(double)trials, num_nodes/20.0);
        if (PetscTools::IsSequential())
        {
            //Early termination
            TS_ASSERT_EQUALS(pops, sequential_pops);
        }
        else
        {
            //Early termination on remote processes is not yet possible
            //This may lead to multiple updates from remote
            //A* Leads to even more updates on average
            // Without A*: TS_ASSERT_DELTA(pops/(double)trials, num_nodes/PetscTools::GetNumProcs(), 700.0);
            TS_ASSERT_LESS_THAN(pops/(double)trials, num_nodes/10.0 );
         }

        //Reverse - to check that cached information is flushed.
        for (unsigned i=0; i<3; i++)
        {
            unsigned index=RandomNumberGenerator::Instance()->randMod(parallel_distances.size());
            TS_ASSERT_DELTA(parallel_distance_calculator.SingleDistance(index, 9260u), parallel_distances[index], 1e-15);
        }
    }
    void TestBetterThanNoPreconditioning()
    {
        unsigned num_nodes = 1331;
        DistributedVectorFactory factory(num_nodes);
        Vec parallel_layout = factory.CreateVec(2);

        unsigned point_jacobi_its;
        unsigned block_diag_its;

        Timer::Reset();
        {
            Mat system_matrix;
            // Note that this test deadlocks if the file's not on the disk
            PetscTools::ReadPetscObject(system_matrix, "linalg/test/data/matrices/cube_6000elems_half_activated.mat", parallel_layout);

            Vec system_rhs;
            // Note that this test deadlocks if the file's not on the disk
            PetscTools::ReadPetscObject(system_rhs, "linalg/test/data/matrices/cube_6000elems_half_activated.vec", parallel_layout);

            LinearSystem ls = LinearSystem(system_rhs, system_matrix);

            ls.SetAbsoluteTolerance(1e-9);
            ls.SetKspType("cg");
            ls.SetPcType("none");

            Vec solution = ls.Solve();

            point_jacobi_its = ls.GetNumIterations();

            PetscTools::Destroy(system_matrix);
            PetscTools::Destroy(system_rhs);
            PetscTools::Destroy(solution);
        }
        Timer::PrintAndReset("No preconditioning");

        {
            Mat system_matrix;
            // Note that this test deadlocks if the file's not on the disk
            PetscTools::ReadPetscObject(system_matrix, "linalg/test/data/matrices/cube_6000elems_half_activated.mat", parallel_layout);

            Vec system_rhs;
            // Note that this test deadlocks if the file's not on the disk
            PetscTools::ReadPetscObject(system_rhs, "linalg/test/data/matrices/cube_6000elems_half_activated.vec", parallel_layout);

            LinearSystem ls = LinearSystem(system_rhs, system_matrix);

            ls.SetAbsoluteTolerance(1e-9);
            ls.SetKspType("cg");
            ls.SetPcType("blockdiagonal");

            Vec solution = ls.Solve();

            block_diag_its = ls.GetNumIterations();

            // Coverage (setting PC type after using blockdiagonal solve)
            ls.SetPcType("blockdiagonal");

            PetscTools::Destroy(system_matrix);
            PetscTools::Destroy(system_rhs);
            PetscTools::Destroy(solution);
        }
        Timer::Print("Block diagonal preconditioner");

        std::cout << block_diag_its << " " << point_jacobi_its << std::endl;
        TS_ASSERT_LESS_THAN_EQUALS(block_diag_its, point_jacobi_its);

        PetscTools::Destroy(parallel_layout);
    }