Exemplo n.º 1
0
    void TestCellKillersOutputParameters()
   {
       std::string output_directory = "TestSloughingCellKillersOutputParameters";
       OutputFileHandler output_file_handler(output_directory, false);

       // Test with SloughingCellKiller
       SloughingCellKiller<2> sloughing_cell_killer(NULL, 20.0, true, 10.0);
       TS_ASSERT_EQUALS(sloughing_cell_killer.GetIdentifier(), "SloughingCellKiller-2");

       out_stream sloughing_cell_killer_parameter_file = output_file_handler.OpenOutputFile("sloughing_results.parameters");
       sloughing_cell_killer.OutputCellKillerParameters(sloughing_cell_killer_parameter_file);
       sloughing_cell_killer_parameter_file->close();

       std::string sloughing_cell_killer_results_dir = output_file_handler.GetOutputDirectoryFullPath();
       FileComparison( sloughing_cell_killer_results_dir + "sloughing_results.parameters", "crypt/test/data/TestSloughingCellKillers/sloughing_results.parameters").CompareFiles();

       // Test with RadialSloughingCellKiller
       c_vector<double,2> centre(2);
       centre[0] = 0.1;
       centre[1] = 0.2;
       double radius = 0.4;
       RadialSloughingCellKiller radial_cell_killer(NULL, centre, radius);
       TS_ASSERT_EQUALS(radial_cell_killer.GetIdentifier(), "RadialSloughingCellKiller");

       out_stream radial_cell_killer_parameter_file = output_file_handler.OpenOutputFile("radial_results.parameters");
       radial_cell_killer.OutputCellKillerParameters(radial_cell_killer_parameter_file);
       radial_cell_killer_parameter_file->close();

       std::string radial_cell_killer_results_dir = output_file_handler.GetOutputDirectoryFullPath();
       FileComparison( radial_cell_killer_results_dir + "radial_results.parameters", "crypt/test/data/TestSloughingCellKillers/radial_results.parameters").CompareFiles();
   }
    /*
     * Cellular birth has been tested in TestCaSingleCellWithBirth for one cell per lattice site.
     * This test adds to the above by further testing cellular birth considering multiple cells per lattice site.
     * A  two-lattice mesh was created and only one lattice had free space to add one daughter cell.
     */
    void TestMultipleCellsPerLatticeSiteWithBirth() throw (Exception)
    {
        EXIT_IF_PARALLEL;

        // Create a simple 2D PottsMesh
        PottsMeshGenerator<2> generator(2, 0, 0, 1, 0, 0);
        PottsMesh<2>* p_mesh = generator.GetMesh();

        // Create cells
        std::vector<CellPtr> cells;
        MAKE_PTR(StemCellProliferativeType, p_stem_type);
        CellsGenerator<FixedDurationGenerationBasedCellCycleModel, 2> cells_generator;
        cells_generator.GenerateBasicRandom(cells, 3, p_stem_type);

        // Specify where cells lie
        std::vector<unsigned> location_indices;
        location_indices.push_back(0);
        location_indices.push_back(0);
        location_indices.push_back(1);

        // Create cell population
        CaBasedCellPopulation<2> cell_population(*p_mesh, cells, location_indices, 2);

        // Set up cell-based simulation
        OnLatticeSimulation<2> simulator(cell_population);
        std::string output_directory = "TestMultipleCellsPerLatticeSiteWithBirth";
        simulator.SetOutputDirectory(output_directory);
        simulator.SetDt(0.1);
        simulator.SetEndTime(40);

        // Add update rule
        MAKE_PTR(DiffusionCaUpdateRule<2u>, p_diffusion_update_rule);
        p_diffusion_update_rule->SetDiffusionParameter(0.5);
        simulator.AddCaUpdateRule(p_diffusion_update_rule);

        // Run simulation
        simulator.Solve();

        // Check the number of cells
        TS_ASSERT_EQUALS(simulator.rGetCellPopulation().GetNumRealCells(), 4u);

        // Test no deaths and some births
        TS_ASSERT_EQUALS(simulator.GetNumBirths(), 1u);
        TS_ASSERT_EQUALS(simulator.GetNumDeaths(), 0u);

#ifdef CHASTE_VTK
        // Test that VTK writer has produced a file
        OutputFileHandler output_file_handler(output_directory, false);
        std::string results_dir = output_file_handler.GetOutputDirectoryFullPath();

        // Initial condition file
        FileFinder vtk_file(results_dir + "results_from_time_0/results_0.vtu", RelativeTo::Absolute);
        TS_ASSERT(vtk_file.Exists());

        // Final file
        FileFinder vtk_file2(results_dir + "results_from_time_0/results_400.vtu", RelativeTo::Absolute);
        TS_ASSERT(vtk_file2.Exists());
#endif //CHASTE_VTK
    }
    void TestWriter() throw (Exception)
    {
        EXIT_IF_PARALLEL;

        // Set up a small MeshBasedCellPopulationWithGhostNodes using an appropriate cell-cycle model class
        CylindricalHoneycombMeshGenerator generator(5, 4, 1);
        Cylindrical2dMesh* p_mesh = generator.GetCylindricalMesh();
        double domain_length_for_wnt = 4.0*(sqrt(3.0)/2);
        std::vector<unsigned> location_indices = generator.GetCellLocationIndices();

        std::vector<CellPtr> cells;
        CryptCellsGenerator<VanLeeuwen2009WntSwatCellCycleModelHypothesisOne> cells_generator;
        cells_generator.Generate(cells, p_mesh, location_indices, false);

        MeshBasedCellPopulationWithGhostNodes<2> cell_population(*p_mesh, cells, location_indices);

        // Create an instance of a Wnt concentration
        WntConcentration<2>::Instance()->SetType(LINEAR);
        WntConcentration<2>::Instance()->SetCellPopulation(cell_population);
        WntConcentration<2>::Instance()->SetCryptLength(domain_length_for_wnt);

        // Initialise the cell population to set up the ODE system associated with each cell-cycle model object
        cell_population.InitialiseCells();

        // Create an output directory for the writer
        std::string output_directory = "TestCellBetaCateninWriter";
        OutputFileHandler output_file_handler(output_directory, false);
        std::string results_dir = output_file_handler.GetOutputDirectoryFullPath();

        // Create a CellBetaCateninWriter and test that the correct output is generated
        CellBetaCateninWriter<2,2> cell_writer;
        cell_writer.OpenOutputFile(output_file_handler);
        cell_writer.WriteTimeStamp();
        for (AbstractCellPopulation<2,2>::Iterator cell_iter = cell_population.Begin();
             cell_iter != cell_population.End();
             ++cell_iter)
        {
            cell_writer.VisitCell(*cell_iter, &cell_population);
        }
        cell_writer.CloseFile();

        /*
         * To verify this test, we can eyeball the results file to check that the correct default
         * initial conditions are output (see VanLeeuwen2009WntSwatCellCycleOdeSystem.hpp).
         */
        FileComparison(results_dir + "results.vizbetacatenin", "crypt/test/data/TestCellBetaCateninWriter/results.vizbetacatenin").CompareFiles();

        // Test the correct data are returned for VTK output for the first cell
        double vtk_data = cell_writer.GetCellDataForVtkOutput(*(cell_population.Begin()), &cell_population);
        TS_ASSERT_DELTA(vtk_data, 14.6088, 1e-4);

        // Avoid memory leak
        WntConcentration<2>::Destroy();
    }
Exemplo n.º 4
0
void CellBasedPdeHandler<DIM>::OpenResultsFiles(std::string outputDirectory)
{
    // If appropriate, make a coarse mesh which exactly overlays the lattice sites of a PottsMesh (used for all OnLattice simulations)
    if ((dynamic_cast<MultipleCaBasedCellPopulation<DIM>*>(mpCellPopulation) != NULL) && mpCoarsePdeMesh==NULL)
    {
        assert(DIM ==2);
        ChasteCuboid<DIM> cuboid = mpCellPopulation->rGetMesh().CalculateBoundingBox();

        // Currently only works with square meshes
        assert(cuboid.GetWidth(0) == cuboid.GetWidth(1));

        UseCoarsePdeMesh(1, cuboid, false);
    }

    // If using a NodeBasedCellPopulation a VertexBasedCellPopulation, a MultipleCABasedCellPopulation or a PottsBasedCellPopulation, mpCoarsePdeMesh must be set up
    if (PdeSolveNeedsCoarseMesh() && mpCoarsePdeMesh==NULL)
    {
        EXCEPTION("Trying to solve a PDE on a cell population that doesn't have a mesh. Try calling UseCoarsePdeMesh().");
    }

    if (mpCoarsePdeMesh != NULL)
    {
        InitialiseCellPdeElementMap();

        // Write mesh to file
        TrianglesMeshWriter<DIM,DIM> mesh_writer(outputDirectory+"/coarse_mesh_output", "coarse_mesh",false);
        mesh_writer.WriteFilesUsingMesh(*mpCoarsePdeMesh);
    }

    if (PetscTools::AmMaster())
    {
        OutputFileHandler output_file_handler(outputDirectory+"/", false);

        if (mpCoarsePdeMesh != NULL)
        {
            mpVizPdeSolutionResultsFile = output_file_handler.OpenOutputFile("results.vizcoarsepdesolution");
        }
        else
        {
            mpVizPdeSolutionResultsFile = output_file_handler.OpenOutputFile("results.vizpdesolution");
        }

        if (mWriteAverageRadialPdeSolution)
        {
            mpAverageRadialPdeSolutionResultsFile = output_file_handler.OpenOutputFile("radial_dist.dat");
        }
    }

    mDirPath = outputDirectory; // caching the path to the output directory for VTK
    //double current_time = SimulationTime::Instance()->GetTime();
    //WritePdeSolution(current_time);
}
    void TestUseInPopulationWriteResultsToFile()
    {
        EXIT_IF_PARALLEL;

        // Set up SimulationTime (needed if VTK is used)
        SimulationTime::Instance()->SetEndTimeAndNumberOfTimeSteps(1.0, 1);

        // Create a simple mesh-based cell population, comprising various cell types in various cell cycle phases
        TrianglesMeshReader<2,2> mesh_reader("mesh/test/data/square_4_elements");
        MutableMesh<2,2> mesh;
        mesh.ConstructFromMeshReader(mesh_reader);

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

        MeshBasedCellPopulation<2> cell_population(mesh, cells);

        // Create an instance of a Wnt concentration
        WntConcentration<2>::Instance()->SetType(LINEAR);
        WntConcentration<2>::Instance()->SetCellPopulation(cell_population);
        WntConcentration<2>::Instance()->SetCryptLength(1.0);

        cell_population.InitialiseCells();

        // This is where we add the writer
        cell_population.AddCellWriter<CellBetaCateninWriter>();

        // This method is usually called by Update()
        cell_population.CreateVoronoiTessellation();

        std::string output_directory = "TestUseInPopulationWriteResultsToFile";
        OutputFileHandler output_file_handler(output_directory, false);

        cell_population.OpenWritersFiles(output_file_handler);
        cell_population.WriteResultsToFiles(output_directory);

        SimulationTime::Instance()->IncrementTimeOneStep();
        cell_population.Update();

        cell_population.WriteResultsToFiles(output_directory);
        cell_population.CloseWritersFiles();

        // Compare output with saved file of what they should look like
        std::string results_dir = output_file_handler.GetOutputDirectoryFullPath();

        FileComparison comparer(results_dir + "results.vizbetacatenin","crypt/test/data/TestCellBetaCateninWriter/results2.vizbetacatenin");
        TS_ASSERT(comparer.CompareFiles());
    }
    void TestForceOutputParameters()
    {
        std::string output_directory = "TestForcesOutputParameters";
        OutputFileHandler output_file_handler(output_directory, false);

        // Test with VertexCryptBoundaryForce
        VertexCryptBoundaryForce<2> boundary_force;
        TS_ASSERT_EQUALS(boundary_force.GetIdentifier(), "VertexCryptBoundaryForce-2");

        out_stream boundary_force_parameter_file = output_file_handler.OpenOutputFile("boundary_results.parameters");
        boundary_force.OutputForceParameters(boundary_force_parameter_file);
        boundary_force_parameter_file->close();

        std::string boundary_force_results_dir = output_file_handler.GetOutputDirectoryFullPath();
        FileComparison( boundary_force_results_dir + "boundary_results.parameters", "crypt/test/data/TestForcesForCrypt/boundary_results.parameters").CompareFiles();
    }
    void TestCellProliferativeTypesCountWriters() throw (Exception)
    {
        EXIT_IF_PARALLEL;

        // Create a simple 3D MeshBasedCellPopulation
        std::vector<Node<3>*> nodes;
        nodes.push_back(new Node<3>(0, true,  0.0, 0.0, 0.0));
        nodes.push_back(new Node<3>(1, true,  1.0, 1.0, 0.0));
        nodes.push_back(new Node<3>(2, true,  1.0, 0.0, 1.0));
        nodes.push_back(new Node<3>(3, true,  0.0, 1.0, 1.0));
        nodes.push_back(new Node<3>(4, false, 0.5, 0.5, 0.5));
        MutableMesh<3,3> mesh(nodes);
        std::vector<CellPtr> cells;
        CellsGenerator<FixedDurationGenerationBasedCellCycleModel, 3> cells_generator;
        cells_generator.GenerateBasic(cells, mesh.GetNumNodes());
        MeshBasedCellPopulation<3> cell_population(mesh, cells);

        cell_population.AddCellPopulationCountWriter<CellProliferativeTypesCountWriter>();

        // An ordering must be specified for cell mutation states and cell proliferative types
        cell_population.SetDefaultCellMutationStateAndProliferativeTypeOrdering();

        // Create an output directory for the writer
        std::string output_directory = "TestCellProliferativeTypesCountWriter";
        OutputFileHandler output_file_handler(output_directory, false);
        std::string results_dir = output_file_handler.GetOutputDirectoryFullPath();

        // Create a CellProliferativeTypesCountWriter and test that the correct output is generated
        CellProliferativeTypesCountWriter<3,3> types_count_writer;
        types_count_writer.OpenOutputFile(output_file_handler);
        types_count_writer.WriteTimeStamp();
        types_count_writer.Visit(&cell_population);
        types_count_writer.WriteNewline();
        types_count_writer.CloseFile();

        FileComparison(results_dir + "celltypes.dat", "cell_based/test/data/TestCellPopulationCountWriters/celltypes.dat").CompareFiles();

        // Test that we can append to files
        types_count_writer.OpenOutputFileForAppend(output_file_handler);
        types_count_writer.WriteTimeStamp();
        types_count_writer.Visit(&cell_population);
        types_count_writer.WriteNewline();
        types_count_writer.CloseFile();

        FileComparison(results_dir + "celltypes.dat", "cell_based/test/data/TestCellPopulationCountWriters/celltypes_twice.dat").CompareFiles();
    }
    void TestCellMutationStatesCountWriter() throw (Exception)
    {
        EXIT_IF_PARALLEL;

        // Create a simple 2D CaBasedCellPopulation
        PottsMeshGenerator<2> generator(5, 0, 0, 5, 0, 0);
        PottsMesh<2>* p_mesh = generator.GetMesh();
        std::vector<CellPtr> cells;
        CellsGenerator<FixedDurationGenerationBasedCellCycleModel, 2> cells_generator;
        cells_generator.GenerateBasic(cells, 5u);
        std::vector<unsigned> location_indices;
        location_indices.push_back(7);
        location_indices.push_back(11);
        location_indices.push_back(12);
        location_indices.push_back(13);
        location_indices.push_back(17);
        CaBasedCellPopulation<2> cell_population(*p_mesh, cells, location_indices);

        cell_population.AddCellPopulationCountWriter<CellMutationStatesCountWriter>();

        // Create an output directory for the writer
        std::string output_directory = "TestCellMutationStatesCountWriter";
        OutputFileHandler output_file_handler(output_directory, false);
        std::string results_dir = output_file_handler.GetOutputDirectoryFullPath();

        // Create a CellMutationStatesCountWriter and test that the correct output is generated
        CellMutationStatesCountWriter<2,2> mutation_states_writer;
        mutation_states_writer.OpenOutputFile(output_file_handler);
        mutation_states_writer.WriteHeader(&cell_population);
        mutation_states_writer.WriteTimeStamp();
        mutation_states_writer.Visit(&cell_population);
        mutation_states_writer.WriteNewline();
        mutation_states_writer.CloseFile();

        FileComparison(results_dir + "cellmutationstates.dat", "cell_based/test/data/TestCellPopulationCountWriters/cellmutationstates.dat").CompareFiles();

        // Test that we can append to files
        mutation_states_writer.OpenOutputFileForAppend(output_file_handler);
        mutation_states_writer.WriteTimeStamp();
        mutation_states_writer.Visit(&cell_population);
        mutation_states_writer.WriteNewline();
        mutation_states_writer.CloseFile();

        FileComparison(results_dir + "cellmutationstates.dat", "cell_based/test/data/TestCellPopulationCountWriters/cellmutationstates_twice.dat").CompareFiles();
    }
Exemplo n.º 9
0
    void TestWriteAverageRadialPdeSolution() throw(Exception)
    {
        EXIT_IF_PARALLEL;

        // Create a cell population using a circular mesh
        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);

        // Put random data on the cells
        for (AbstractCellPopulation<2>::Iterator cell_iter = cell_population.Begin();
             cell_iter != cell_population.End();
             ++cell_iter)
        {
            cell_iter->GetCellData()->SetItem("averaged quantity", RandomNumberGenerator::Instance()->ranf());
        }

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

        pde_handler.SetWriteAverageRadialPdeSolution("averaged quantity", 2);

        // Open result file ourselves
        OutputFileHandler output_file_handler("TestWriteAverageRadialPdeSolution", false);
        pde_handler.mpAverageRadialPdeSolutionResultsFile = output_file_handler.OpenOutputFile("radial_dist.dat");

        // Write average radial PDE solution to file
        pde_handler.WriteAverageRadialPdeSolution(SimulationTime::Instance()->GetTime());

        // Test that this is correct by comparing with an existing results file
        std::string results_dir = output_file_handler.GetOutputDirectoryFullPath();

        NumericFileComparison comparison(results_dir + "/radial_dist.dat", "cell_based/test/data/TestCellBasedPdeHandler/radial_dist.dat");
        TS_ASSERT(comparison.CompareFiles());

        // Close result file ourselves
        pde_handler.mpAverageRadialPdeSolutionResultsFile->close();
    }
Exemplo n.º 10
0
    void TestUpdateRuleOutputUpdateRuleInfo()
    {
        std::string output_directory = "TestCaUpdateRulesOutputParameters";
        OutputFileHandler output_file_handler(output_directory, false);

        // Test with VolumeConstraintPottsUpdateRule
        DiffusionCaUpdateRule<2> diffusion_update_rule;
        diffusion_update_rule.SetDiffusionParameter(1.0);

        TS_ASSERT_EQUALS(diffusion_update_rule.GetIdentifier(), "DiffusionCaUpdateRule-2");

        out_stream diffusion_update_rule_parameter_file = output_file_handler.OpenOutputFile("diffusion_update_rule_results.parameters");
        diffusion_update_rule.OutputUpdateRuleInfo(diffusion_update_rule_parameter_file);
        diffusion_update_rule_parameter_file->close();

        // Compare the generated file in test output with a reference copy in the source code.
        FileFinder generated = output_file_handler.FindFile("diffusion_update_rule_results.parameters");
        FileFinder reference("cell_based/test/data/TestCaUpdateRules/diffusion_update_rule_results.parameters",
                RelativeTo::ChasteSourceRoot);
        FileComparison comparer(generated, reference);
        TS_ASSERT(comparer.CompareFiles());
    }
Exemplo n.º 11
0
    void TestSwitchingUpdateRuleOutputUpdateRuleInfo()
    {
        std::string output_directory = "TestCaSwitchingUpdateRulesOutputParameters";
        OutputFileHandler output_file_handler(output_directory, false);

        // Test with RandomCaSwitchingUpdateRule
        RandomCaSwitchingUpdateRule<2> random_switching_update_rule;
        random_switching_update_rule.SetSwitchingParameter(1.0);

        TS_ASSERT_EQUALS(random_switching_update_rule.GetIdentifier(), "RandomCaSwitchingUpdateRule-2");

        out_stream random_switching_update_rule_parameter_file = output_file_handler.OpenOutputFile("random_switching_update_rule_results.parameters");
        random_switching_update_rule.OutputUpdateRuleInfo(random_switching_update_rule_parameter_file);
        random_switching_update_rule_parameter_file->close();

        // Compare the generated file in test output with a reference copy in the source code.
        FileFinder generated = output_file_handler.FindFile("random_switching_update_rule_results.parameters");
        FileFinder reference("cell_based/test/data/TestCaUpdateRules/random_switching_update_rule_results.parameters",
                RelativeTo::ChasteSourceRoot);
        FileComparison comparer(generated, reference);
        TS_ASSERT(comparer.CompareFiles());
    }
    void TestOutputParameters2d() throw(Exception)
    {
        std::string output_directory = "TestOutputParameters2d";
        OutputFileHandler output_file_handler(output_directory, false);

        CryptSimulationBoundaryCondition<2> boundary_condition(NULL);
        TS_ASSERT_EQUALS(boundary_condition.GetIdentifier(), "CryptSimulationBoundaryCondition-2");

        out_stream boundary_condition_parameter_file = output_file_handler.OpenOutputFile("results2d.parameters");
        boundary_condition.OutputCellPopulationBoundaryConditionParameters(boundary_condition_parameter_file);
        boundary_condition_parameter_file->close();

        std::string boundary_condition_results_dir = output_file_handler.GetOutputDirectoryFullPath();
        FileComparison( boundary_condition_results_dir + "results2d.parameters", "crypt/test/data/TestCryptSimulationBoundaryCondition/results2d.parameters").CompareFiles();

        // Test OutputCellPopulationBoundaryConditionInfo() method
        out_stream boundary_condition_info_file = output_file_handler.OpenOutputFile("results2d.info");
        boundary_condition.OutputCellPopulationBoundaryConditionInfo(boundary_condition_info_file);
        boundary_condition_info_file->close();

        FileComparison( boundary_condition_results_dir + "results2d.info", "crypt/test/data/TestCryptSimulationBoundaryCondition/results2d.info").CompareFiles();
    }
    void TestSimpleTargetAreaModifierOutputParameters()
    {
        EXIT_IF_PARALLEL;
        std::string output_directory = "TestSimpleTargetAreaModifierOutputParameters";
        OutputFileHandler output_file_handler(output_directory, false);

        MAKE_PTR(SimpleTargetAreaModifier<2>, p_modifier);
        TS_ASSERT_EQUALS(p_modifier->GetIdentifier(), "SimpleTargetAreaModifier-2");

        out_stream modifier_parameter_file = output_file_handler.OpenOutputFile("SimpleTargetAreaModifier.parameters");
        p_modifier->OutputSimulationModifierParameters(modifier_parameter_file);
        modifier_parameter_file->close();

        {
            // Compare the generated file in test output with a reference copy in the source code
            FileFinder generated = output_file_handler.FindFile("SimpleTargetAreaModifier.parameters");
            FileFinder reference("cell_based/test/data/TestSimulationModifierOutputParameters/SimpleTargetAreaModifier.parameters",
                    RelativeTo::ChasteSourceRoot);
            FileComparison comparer(generated, reference);
            TS_ASSERT(comparer.CompareFiles());
        }
    }
Exemplo n.º 14
0
    void TestCellBasedPdeHandlerOutputParameters() throw(Exception)
    {
        EXIT_IF_PARALLEL;

        std::string output_directory = "TestCellBasedPdeHandlerOutputParameters";
        OutputFileHandler output_file_handler(output_directory, false);

        // Create a cell population
        HoneycombMeshGenerator generator(2, 2, 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());

        NodeBasedCellPopulation<2> cell_population(mesh, cells);

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

        // Test output methods
        TS_ASSERT_EQUALS(pde_handler.GetIdentifier(), "CellBasedPdeHandler-2");

        out_stream pde_handler_parameter_file = output_file_handler.OpenOutputFile("CellBasedPdeHandler.parameters");
        pde_handler.OutputParameters(pde_handler_parameter_file);
        pde_handler_parameter_file->close();

        {
            // Compare the generated file in test output with a reference copy in the source code.
            FileFinder generated = output_file_handler.FindFile("CellBasedPdeHandler.parameters");
            FileFinder reference("cell_based/test/data/TestCellBasedPdeHandler/CellBasedPdeHandler.parameters",
                    RelativeTo::ChasteSourceRoot);
            FileComparison comparer(generated, reference);
            TS_ASSERT(comparer.CompareFiles());
        }
    }
void PostProcessingWriter<ELEMENT_DIM, SPACE_DIM>::WriteGenericFileToMeshalyzer(std::vector<std::vector<double> >& rDataPayload, const std::string& rFolder, const std::string& rFileName)
{
    OutputFileHandler output_file_handler(HeartConfig::Instance()->GetOutputDirectory() + "/" + rFolder, false);
    PetscTools::BeginRoundRobin();
    {
        out_stream p_file=out_stream(NULL);
        //Open file
        if (PetscTools::AmMaster())
        {
            // Open the file for the first time
            p_file = output_file_handler.OpenOutputFile(rFileName);
        }
        else
        {
            // Append data to the existing file opened by master
            p_file = output_file_handler.OpenOutputFile(rFileName, std::ios::app);
        }
        // Write data
        for (unsigned line_number=0; line_number<rDataPayload.size(); line_number++)
        {
            for (unsigned i = 0; i < rDataPayload[line_number].size(); i++)
            {
                *p_file << rDataPayload[line_number][i] << "\t";
            }
            *p_file << std::endl;
        }

        // Last processor appends comment line
        if (PetscTools::AmTopMost())
        {
            std::string comment = "# " + ChasteBuildInfo::GetProvenanceString();
            *p_file << comment;
        }
        p_file->close();
    }
    //There's a barrier included here: Process i+1 waits for process i to close the file
    PetscTools::EndRoundRobin();
}
    void TestCellCycleModelOutputParameters()
    {
        std::string output_directory = "TestCellCycleModelOutputParameters";
        OutputFileHandler output_file_handler(output_directory, false);

        // Test with Alarcon2004OxygenBasedCellCycleModel
        Alarcon2004OxygenBasedCellCycleModel alarcon_oxygen_based_cell_cycle_model;
        TS_ASSERT_EQUALS(alarcon_oxygen_based_cell_cycle_model.GetIdentifier(), "Alarcon2004OxygenBasedCellCycleModel");

        out_stream alarcon_oxygen_based_parameter_file = output_file_handler.OpenOutputFile("alarcon_oxygen_based_results.parameters");
        alarcon_oxygen_based_cell_cycle_model.OutputCellCycleModelParameters(alarcon_oxygen_based_parameter_file);
        alarcon_oxygen_based_parameter_file->close();

        {
            FileFinder generated_file = output_file_handler.FindFile("alarcon_oxygen_based_results.parameters");
            FileFinder reference_file("cell_based/test/data/TestCellCycleModels/alarcon_oxygen_based_results.parameters",
                                      RelativeTo::ChasteSourceRoot);
            FileComparison comparer(generated_file,reference_file);
            TS_ASSERT(comparer.CompareFiles());
        }

        // Test with TysonNovakCellCycleModel
        TysonNovakCellCycleModel tyson_novak_based_cell_cycle_model;
        TS_ASSERT_EQUALS(tyson_novak_based_cell_cycle_model.GetIdentifier(), "TysonNovakCellCycleModel");

        out_stream tyson_novak_based_parameter_file = output_file_handler.OpenOutputFile("tyson_novak_based_results.parameters");
        tyson_novak_based_cell_cycle_model.OutputCellCycleModelParameters(tyson_novak_based_parameter_file);
        tyson_novak_based_parameter_file->close();

        {
            FileFinder generated_file = output_file_handler.FindFile("tyson_novak_based_results.parameters");
            FileFinder reference_file("cell_based/test/data/TestCellCycleModels/tyson_novak_based_results.parameters",
                                      RelativeTo::ChasteSourceRoot);
            FileComparison comparer(generated_file,reference_file);
            TS_ASSERT(comparer.CompareFiles());
        }
    }
Exemplo n.º 17
0
    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);
        }
    }
    /**
     * Run the same test at different levels of refinement until some convergence criterion is met.
     * @param nameOfTest The name of the convergence test (typically the name in the suite) for use in naming files.
     * \todo This is a scarily long method; could do with some parts extracted?
     */
    void Converge(std::string nameOfTest)
    {
        // Create the meshes on which the test will be based
        const std::string mesh_dir = "ConvergenceMesh";
        OutputFileHandler output_file_handler(mesh_dir);
        ReplicatableVector voltage_replicated;

        unsigned file_num=0;

        // Create a file for storing conduction velocity and AP data and write the header
        OutputFileHandler conv_info_handler("ConvergencePlots"+nameOfTest, false);
        out_stream p_conv_info_file;
        if (PetscTools::AmMaster())
        {
            std::cout << "=========================== Beginning Test...==================================\n";
            p_conv_info_file = conv_info_handler.OpenOutputFile(nameOfTest+"_info.csv");
            (*p_conv_info_file) << "#Abcisa\t"
                                << "l2-norm-full\t"
                                << "l2-norm-onset\t"
                                << "Max absolute err\t"
                                << "APD90_1st_quad\t"
                                << "APD90_3rd_quad\t"
                                << "Conduction velocity (relative diffs)" << std::endl;
        }
        SetInitialConvergenceParameters();

        double prev_apd90_first_qn=0.0;
        double prev_apd90_third_qn=0.0;
        double prev_cond_velocity=0.0;
        std::vector<double> prev_voltage;
        std::vector<double> prev_times;
        PopulateStandardResult(prev_voltage, prev_times);

        do
        {
            CuboidMeshConstructor<DIM> constructor;

            //If the printing time step is too fine, then simulations become I/O bound without much improvement in accuracy
            double printing_step = this->PdeTimeStep;
#define COVERAGE_IGNORE
            while (printing_step < 1.0e-4)
            {
                printing_step *= 2.0;
                std::cout<<"Warning: PrintingTimeStep increased\n";
            }
#undef COVERAGE_IGNORE
            HeartConfig::Instance()->SetOdePdeAndPrintingTimeSteps(this->OdeTimeStep, this->PdeTimeStep, printing_step);
#define COVERAGE_IGNORE
            if (SimulateFullActionPotential)
            {
                HeartConfig::Instance()->SetSimulationDuration(400.0);
            }
            else
            {
                HeartConfig::Instance()->SetSimulationDuration(8.0);
            }
#undef COVERAGE_IGNORE
            HeartConfig::Instance()->SetOutputDirectory("Convergence"+nameOfTest);
            HeartConfig::Instance()->SetOutputFilenamePrefix("Results");

            DistributedTetrahedralMesh<DIM, DIM> mesh;
            constructor.Construct(mesh, this->MeshNum, mMeshWidth);

            unsigned num_ele_across = SmallPow(2u, this->MeshNum+2); // number of elements in each dimension

            AbstractCardiacCellFactory<DIM>* p_cell_factory=NULL;

            switch (this->Stimulus)
            {
                case NEUMANN:
                {
                    p_cell_factory = new ZeroStimulusCellFactory<CELL, DIM>();
                    break;
                }
                case PLANE:
                {
                    if (this->UseAbsoluteStimulus)
                    {
                        #define COVERAGE_IGNORE
                        p_cell_factory = new GeneralPlaneStimulusCellFactory<CELL, DIM>(0, this->AbsoluteStimulus, true);
                        #undef COVERAGE_IGNORE
                    }
                    else
                    {
                        p_cell_factory = new GeneralPlaneStimulusCellFactory<CELL, DIM>(num_ele_across, constructor.GetWidth(), false, this->AbsoluteStimulus);
                    }
                    break;
                }
                case QUARTER:
                {
                    ///\todo consider reducing all stimuli to match this one.
                    p_cell_factory = new RampedQuarterStimulusCellFactory<CELL, DIM>(constructor.GetWidth(), num_ele_across, this->AbsoluteStimulus/10.0);
                    break;
                }
                default:
                    NEVER_REACHED;
            }


            CARDIAC_PROBLEM cardiac_problem(p_cell_factory);
            cardiac_problem.SetMesh(&mesh);

            // Calculate positions of nodes 1/4 and 3/4 through the mesh
            unsigned third_quadrant_node;
            unsigned first_quadrant_node;
            switch(DIM)
            {
                case 1:
                {
                    first_quadrant_node = (unsigned) (0.25*constructor.GetNumElements());
                    third_quadrant_node = (unsigned) (0.75*constructor.GetNumElements());
                    break;
                }
                case 2:
                {
                    unsigned n= SmallPow (2u, this->MeshNum+2);
                    first_quadrant_node =   (n+1)*(n/2)+  n/4 ;
                    third_quadrant_node =   (n+1)*(n/2)+3*n/4 ;
                    break;
                }
                case 3:
                {
                    const unsigned first_quadrant_nodes_3d[5]={61, 362, 2452, 17960, 137296};
                    const unsigned third_quadrant_nodes_3d[5]={63, 366, 2460, 17976, 137328};
                    assert(this->PdeTimeStep<5);
                    first_quadrant_node = first_quadrant_nodes_3d[this->MeshNum];
                    third_quadrant_node = third_quadrant_nodes_3d[this->MeshNum];
                    break;
                }

                default:
                    NEVER_REACHED;
            }

            double mesh_width=constructor.GetWidth();

            // We only need the output of these two nodes
            std::vector<unsigned> nodes_to_be_output;
            nodes_to_be_output.push_back(first_quadrant_node);
            nodes_to_be_output.push_back(third_quadrant_node);
            cardiac_problem.SetOutputNodes(nodes_to_be_output);

            // The results of the tests were originally obtained with the following conductivity
            // values. After implementing fibre orientation the defaults changed. Here we set
            // the former ones to be used.
            SetConductivities(cardiac_problem);

            cardiac_problem.Initialise();

            boost::shared_ptr<BoundaryConditionsContainer<DIM,DIM,PROBLEM_DIM> > p_bcc(new BoundaryConditionsContainer<DIM,DIM,PROBLEM_DIM>);
            SimpleStimulus stim(NeumannStimulus, 0.5);
            if (Stimulus==NEUMANN)
            {

                StimulusBoundaryCondition<DIM>* p_bc_stim = new StimulusBoundaryCondition<DIM>(&stim);

                // get mesh
                AbstractTetrahedralMesh<DIM, DIM> &r_mesh = cardiac_problem.rGetMesh();
                // loop over boundary elements
                typename AbstractTetrahedralMesh<DIM, DIM>::BoundaryElementIterator iter;
                iter = r_mesh.GetBoundaryElementIteratorBegin();
                while (iter != r_mesh.GetBoundaryElementIteratorEnd())
                {
                    double x = ((*iter)->CalculateCentroid())[0];
                    ///\todo remove magic number? (#1884)
                    if (x*x<=1e-10)
                    {
                        p_bcc->AddNeumannBoundaryCondition(*iter, p_bc_stim);
                    }
                    iter++;
                }
                // pass the bcc to the problem
                cardiac_problem.SetBoundaryConditionsContainer(p_bcc);
            }

            DisplayRun();
            Timer::Reset();
            //// use this to get some info printed out
            //cardiac_problem.SetWriteInfo();

            try
            {
                cardiac_problem.Solve();
            }
            catch (Exception e)
            {
                WARNING("This run threw an exception.  Check convergence results\n");
                std::cout << e.GetMessage() << std::endl;
            }

            if (PetscTools::AmMaster())
            {
                std::cout << "Time to solve = " << Timer::GetElapsedTime() << " seconds\n";
            }

            OutputFileHandler results_handler("Convergence"+nameOfTest, false);
            Hdf5DataReader results_reader = cardiac_problem.GetDataReader();

            {
                std::vector<double> transmembrane_potential = results_reader.GetVariableOverTime("V", third_quadrant_node);
                std::vector<double> time_series = results_reader.GetUnlimitedDimensionValues();

                OutputFileHandler plot_file_handler("ConvergencePlots"+nameOfTest, false);
                if (PetscTools::AmMaster())
                {
                    // Write out the time series for the node at third quadrant
                    {
                        std::stringstream plot_file_name_stream;
                        plot_file_name_stream<< nameOfTest << "_Third_quadrant_node_run_"<< file_num << ".csv";
                        out_stream p_plot_file = plot_file_handler.OpenOutputFile(plot_file_name_stream.str());
                        for (unsigned data_point = 0; data_point<time_series.size(); data_point++)
                        {
                            (*p_plot_file) << time_series[data_point] << "\t" << transmembrane_potential[data_point] << "\n";
                        }
                        p_plot_file->close();
                    }
                    // Write time series for first quadrant node
                    {
                        std::vector<double> transmembrane_potential_1qd=results_reader.GetVariableOverTime("V", first_quadrant_node);
                        std::vector<double> time_series_1qd = results_reader.GetUnlimitedDimensionValues();
                        std::stringstream plot_file_name_stream;
                        plot_file_name_stream<< nameOfTest << "_First_quadrant_node_run_"<< file_num << ".csv";
                        out_stream p_plot_file = plot_file_handler.OpenOutputFile(plot_file_name_stream.str());
                        for (unsigned data_point = 0; data_point<time_series.size(); data_point++)
                        {
                            (*p_plot_file) << time_series_1qd[data_point] << "\t" << transmembrane_potential_1qd[data_point] << "\n";
                        }
                        p_plot_file->close();
                    }
                }
                // calculate conduction velocity and APD90 error
                PropagationPropertiesCalculator ppc(&results_reader);

                try
                {
                    #define COVERAGE_IGNORE
                    if (SimulateFullActionPotential)
                    {
                        Apd90FirstQn = ppc.CalculateActionPotentialDuration(90.0, first_quadrant_node);
                        Apd90ThirdQn = ppc.CalculateActionPotentialDuration(90.0, third_quadrant_node);
                    }
                    #undef COVERAGE_IGNORE
                    ConductionVelocity  = ppc.CalculateConductionVelocity(first_quadrant_node,third_quadrant_node,0.5*mesh_width);
                }
                catch (Exception e)
                {
                    #define COVERAGE_IGNORE
                    std::cout << "Warning - this run threw an exception in calculating propagation.  Check convergence results\n";
                    std::cout << e.GetMessage() << std::endl;
                    #undef COVERAGE_IGNORE
                }
                double cond_velocity_error = 1e10;
                double apd90_first_qn_error = 1e10;
                double apd90_third_qn_error = 1e10;

                if (this->PopulatedResult)
                {
                    if (prev_cond_velocity != 0.0)
                    {
                        cond_velocity_error = fabs(ConductionVelocity - prev_cond_velocity) / prev_cond_velocity;
                    }
#define COVERAGE_IGNORE
                    if (prev_apd90_first_qn != 0.0)
                    {
                        apd90_first_qn_error = fabs(Apd90FirstQn - prev_apd90_first_qn) / prev_apd90_first_qn;
                    }
                    if (prev_apd90_third_qn != 0.0)
                    {
                        apd90_third_qn_error = fabs(Apd90ThirdQn - prev_apd90_third_qn) / prev_apd90_third_qn;
                    }
                    if (apd90_first_qn_error == 0.0)
                    {
                        apd90_first_qn_error = DBL_EPSILON; //Avoid log zero on plot
                    }
                    if (apd90_third_qn_error == 0.0)
                    {
                        apd90_third_qn_error = DBL_EPSILON; //Avoid log zero on plot
                    }
#undef COVERAGE_IGNORE
                    if (cond_velocity_error == 0.0)
                    {
                        cond_velocity_error = DBL_EPSILON; //Avoid log zero on plot
                    }
                }

                prev_cond_velocity = ConductionVelocity;
                prev_apd90_first_qn = Apd90FirstQn;
                prev_apd90_third_qn = Apd90ThirdQn;

                // calculate l2norm
                double max_abs_error = 0;
                double sum_sq_abs_error =0;
                double sum_sq_prev_voltage = 0;
                double sum_sq_abs_error_full =0;
                double sum_sq_prev_voltage_full = 0;
                if (this->PopulatedResult)
                {
                    //If the PDE step is varying then we'll have twice as much data now as we use to have

                    unsigned time_factor=(time_series.size()-1) / (prev_times.size()-1);
                    assert (time_factor == 1 || time_factor == 2 || time_factor == 8);
                    //Iterate over the shorter time series data
                    for (unsigned data_point = 0; data_point<prev_times.size(); data_point++)
                    {
                        unsigned this_data_point=time_factor*data_point;

                        assert(time_series[this_data_point] == prev_times[data_point]);
                        double abs_error = fabs(transmembrane_potential[this_data_point]-prev_voltage[data_point]);
                        max_abs_error = (abs_error > max_abs_error) ? abs_error : max_abs_error;
                        //Only do resolve the upstroke...
                        sum_sq_abs_error_full += abs_error*abs_error;
                        sum_sq_prev_voltage_full += prev_voltage[data_point] * prev_voltage[data_point];
                        if (time_series[this_data_point] <= 8.0)
                        {
                            //In most regular cases we always do this, since the simulation stops at ms
                            sum_sq_abs_error += abs_error*abs_error;
                            sum_sq_prev_voltage += prev_voltage[data_point] * prev_voltage[data_point];
                        }
                    }

                }
                if (!this->PopulatedResult || !FixedResult)
                {
                    prev_voltage = transmembrane_potential;
                    prev_times = time_series;
                }

                if (this->PopulatedResult)
                {
                    double l2_norm_upstroke = sqrt(sum_sq_abs_error/sum_sq_prev_voltage);
                    double l2_norm_full = sqrt(sum_sq_abs_error_full/sum_sq_prev_voltage_full);

                    if (PetscTools::AmMaster())
                    {
                        (*p_conv_info_file) << std::setprecision(8)
                                            << Abscissa() << "\t"
                                            << l2_norm_full << "\t"
                                            << l2_norm_upstroke << "\t"
                                            << max_abs_error << "\t"
                                            << Apd90FirstQn <<" "<< apd90_first_qn_error <<""<< "\t"
                                            << Apd90ThirdQn <<" "<< apd90_third_qn_error <<""<< "\t"
                                            << ConductionVelocity <<" "<< cond_velocity_error  <<""<< std::endl;
                    }
                    // convergence criterion
                    this->Converged = l2_norm_full < this->RelativeConvergenceCriterion;
                    this->LastDifference = l2_norm_full;
#define COVERAGE_IGNORE
                    assert (time_series.size() != 1u);
                    if (time_series.back() == 0.0)
                    {
                        std::cout << "Failed after successful convergence - give up this convergence test\n";
                        break;
                    }
#undef COVERAGE_IGNORE

                }

                if ( time_series.back() != 0.0)
                {
                    // Simulation ran to completion
                    this->PopulatedResult=true;

                }
            }

            // Get ready for the next test by halving the time step
            if (!this->Converged)
            {
                UpdateConvergenceParameters();
                file_num++;
            }
            delete p_cell_factory;
        }
        while (!GiveUpConvergence() && !this->Converged);


        if (PetscTools::AmMaster())
        {
            p_conv_info_file->close();

            std::cout << "Results: " << std::endl;
            FileFinder info_finder = conv_info_handler.FindFile(nameOfTest + "_info.csv");
            std::ifstream info_file(info_finder.GetAbsolutePath().c_str());
            if (info_file)
            {
                std::cout << info_file.rdbuf();
                info_file.close();
            }
        }

    }
    void TestSolvingEllipticPde() throw(Exception)
    {
        /* First we declare a mesh reader which reads mesh data files of the 'Triangle'
         * format. The path given is relative to the main Chaste directory. As we are in 2d,
         * the reader will look for three datafiles, [name].nodes, [name].ele and [name].edge.
         * Note that the first template argument here is the spatial dimension of the
         * elements in the mesh ({{{ELEMENT_DIM}}}), and the second is the dimension of the nodes,
         * i.e. the dimension of the space the mesh lives in ({{{SPACE_DIM}}}). Usually
         * {{{ELEMENT_DIM}}} and {{{SPACE_DIM}}} will be equal. */
        TrianglesMeshReader<2,2> mesh_reader("mesh/test/data/square_128_elements");
        /* Now declare a tetrahedral mesh with the same dimensions... */
        TetrahedralMesh<2,2> mesh;
        /* ... and construct the mesh using the mesh reader. */
        mesh.ConstructFromMeshReader(mesh_reader);

        /* Next we instantiate an instance of our PDE we wish to solve. */
        MyPde pde;

        /* A set of boundary conditions are stored in a {{{BoundaryConditionsContainer}}}. The
         * three template arguments are ELEMENT_DIM, SPACE_DIM and PROBLEM_DIM, the latter being
         * the number of unknowns we are solving for. We have one unknown (ie u is a scalar, not
         * a vector), so in this case {{{PROBLEM_DIM}}}=1. */
        BoundaryConditionsContainer<2,2,1> bcc;

        /* Defining the boundary conditions is the only particularly fiddly part of solving PDEs,
         * unless they are very simple, such as u=0 on the boundary, which could be done
         * as follows: */
        //bcc.DefineZeroDirichletOnMeshBoundary(&mesh);

        /* We want to specify u=0 on x=0 and y=0.  To do this, we first create the boundary condition
         * object saying what the value of the condition is at any particular point in space.  Here
         * we use the class `ConstBoundaryCondition`, a subclass of `AbstractBoundaryCondition` that
         * yields the same constant value (0.0 here) everywhere it is used.
         *
         * Note that the object is allocated with `new`.  The `BoundaryConditionsContainer` object deals
         * with deleting its associated boundary condition objects.  Note too that we could allocate a
         * separate condition object for each boundary node, but using the same object where possible is
         * more memory efficient.
         */
        ConstBoundaryCondition<2>* p_zero_boundary_condition = new ConstBoundaryCondition<2>(0.0);
        /* We then get a boundary node iterator from the mesh... */
        TetrahedralMesh<2,2>::BoundaryNodeIterator iter = mesh.GetBoundaryNodeIteratorBegin();
        /* ...and loop over the boundary nodes, getting the x and y values. */
        while (iter < mesh.GetBoundaryNodeIteratorEnd())
        {
            double x = (*iter)->GetPoint()[0];
            double y = (*iter)->GetPoint()[1];
            /* If x=0 or y=0... */
            if ((x==0) || (y==0))
            {
                /* ...associate the zero boundary condition created above with this boundary node
                 * ({{{*iter}}} being a pointer to a {{{Node<2>}}}).
                 */
                bcc.AddDirichletBoundaryCondition(*iter, p_zero_boundary_condition);
            }
            iter++;
        }

        /* Now we create Neumann boundary conditions for the ''surface elements'' on x=1 and y=1. Note that
         * Dirichlet boundary conditions are defined on nodes, whereas Neumann boundary conditions are
         * defined on surface elements. Note also that the natural boundary condition statement for this
         * PDE is (D grad u).n = g(x) (where n is the outward-facing surface normal), and g(x) is a prescribed
         * function, ''not'' something like du/dn=g(x). Hence the boundary condition we are specifying is
         * (D grad u).n = 0.
         *
         * '''Important note for 1D:''' This means that if we were solving 2u,,xx,,=f(x) in 1D, and
         * wanted to specify du/dx=1 on the LHS boundary, the Neumann boundary value we have to specify is
         * -2, as n=-1 (outward facing normal) so (D gradu).n = -2 when du/dx=1.
         *
         * To define Neumann bcs, we reuse the zero boundary condition object defined above, but apply it
         * at surface elements.  We loop over these using another iterator provided by the mesh class.
         */
        TetrahedralMesh<2,2>::BoundaryElementIterator surf_iter
            = mesh.GetBoundaryElementIteratorBegin();
        while (surf_iter != mesh.GetBoundaryElementIteratorEnd())
        {
            /* Get the x and y values of any node (here, the 0th) in the element. */
            unsigned node_index = (*surf_iter)->GetNodeGlobalIndex(0);
            double x = mesh.GetNode(node_index)->GetPoint()[0];
            double y = mesh.GetNode(node_index)->GetPoint()[1];

            /* If x=1 or y=1... */
            if ( (fabs(x-1.0) < 1e-6) || (fabs(y-1.0) < 1e-6) )
            {
                /* ...associate the boundary condition with the surface element. */
                bcc.AddNeumannBoundaryCondition(*surf_iter, p_zero_boundary_condition);
            }

            /* Finally increment the iterator. */
            surf_iter++;
        }

        /* Next we define the solver of the PDE.
         * To solve an {{{AbstractLinearEllipticPde}}} (which is the type of PDE {{{MyPde}}} is),
         * we use a {{{SimpleLinearEllipticSolver}}}. The solver, again templated over
         * {{{ELEMENT_DIM}}} and {{{SPACE_DIM}}}, needs to be given (pointers to) the mesh,
         * pde and boundary conditions.
         */
        SimpleLinearEllipticSolver<2,2> solver(&mesh, &pde, &bcc);

        /* To solve, just call {{{Solve()}}}. A PETSc vector is returned. */
        Vec result = solver.Solve();

        /* It is a pain to access the individual components of a PETSc vector, even when running only on
         * one process. A helper class called {{{ReplicatableVector}}} has been created. Create
         * an instance of one of these, using the PETSc {{{Vec}}} as the data. The ''i''th
         * component of {{{result}}} can now be obtained by simply doing {{{result_repl[i]}}}.
         */
        ReplicatableVector result_repl(result);

        /* Let us write out the solution to a file. To do this, create an
         * {{{OutputFileHandler}}}, passing in the directory we want files written to.
         * This is relative to the directory defined by the CHASTE_TEST_OUTPUT environment
         * variable - usually `/tmp/$USER/testoutput`. Note by default the output directory
         * passed in is emptied by this command. To avoid this, {{{false}}} can be passed in as a second
         * parameter.
         */
        OutputFileHandler output_file_handler("TestSolvingLinearPdeTutorial");

        /* Create an {{{out_stream}}}, which is a stream to a particular file. An {{{out_stream}}}
         * is a smart pointer to a `std::ofstream`. */
        out_stream p_file = output_file_handler.OpenOutputFile("linear_solution.txt");

        /* Loop over the entries of the solution. */
        for (unsigned i=0; i<result_repl.GetSize(); i++)
        {
            /* Get the x and y-values of the node corresponding to this entry. The method
             * {{{GetNode}}} on the mesh class returns a pointer to a {{{Node}}}. */
            double x = mesh.GetNode(i)->rGetLocation()[0];
            double y = mesh.GetNode(i)->rGetLocation()[1];

            /* Get the computed solution at this node from the {{{ReplicatableVector}}}. */
            double u = result_repl[i];

            /* Finally, write x, y and u to the output file. The solution could then be
             * visualised in (eg) matlab, using the commands:
             * {{{sol=load('linear_solution.txt'); plot3(sol(:,1),sol(:,2),sol(:,3),'.');}}}*/
            (*p_file) << x << " " << y << " " << u << "\n";
        }

        /* All PETSc {{{Vec}}}s should be destroyed when they are no longer needed, or you will have a memory leak. */
        PetscTools::Destroy(result);
    }
CylindricalHoneycombMeshGenerator::CylindricalHoneycombMeshGenerator(unsigned numNodesAlongWidth, unsigned numNodesAlongLength, unsigned ghosts, double scaleFactor)
{
    mpMesh = NULL;
    mDomainWidth = numNodesAlongWidth*scaleFactor;
    mNumCellWidth = numNodesAlongWidth; //*1 because cells are considered to be size one
    mNumCellLength = numNodesAlongLength;
    mMeshFilename = "mesh";
    mGhostNodeIndices.clear();
    // The code below won't work in parallel
    assert(PetscTools::IsSequential());

    // An older version of the constructor might allow the wrong argument through to the scale factor
    assert(scaleFactor > 0.0);

    // Get a unique mesh filename
    std::stringstream pid;
    pid << getpid();

    OutputFileHandler output_file_handler("2D_temporary_honeycomb_mesh_"+ pid.str());

    unsigned num_nodes_along_width = mNumCellWidth;
    unsigned num_nodes_along_length = mNumCellLength;
    double horizontal_spacing = mDomainWidth / (double)num_nodes_along_width;
    double vertical_spacing = (sqrt(3.0)/2)*horizontal_spacing;

    // This line is needed to define ghost nodes later
    mDomainDepth = (double)(num_nodes_along_length) * vertical_spacing;

    // Take account of ghost nodes
    num_nodes_along_length += 2*ghosts;

    unsigned num_nodes            = num_nodes_along_width*num_nodes_along_length;
    unsigned num_elem_along_width = num_nodes_along_width-1;
    unsigned num_elem_along_length = num_nodes_along_length-1;
    unsigned num_elem             = 2*num_elem_along_width*num_elem_along_length;
    unsigned num_edges            = 3*num_elem_along_width*num_elem_along_length + num_elem_along_width + num_elem_along_length;

    double x0 = 0;
    double y0 = -vertical_spacing*ghosts;

    mBottom = -vertical_spacing*ghosts;
    mTop = mBottom + vertical_spacing*(num_nodes_along_length-1);

    // Write node file
    out_stream p_node_file = output_file_handler.OpenOutputFile(mMeshFilename+".node");
    (*p_node_file) << std::scientific;
    //(*p_node_file) << std::setprecision(20);
    (*p_node_file) << num_nodes << "\t2\t0\t1" << std::endl;

    unsigned node = 0;
    for (unsigned i=0; i<num_nodes_along_length; i++)
    {
        for (unsigned j=0; j<num_nodes_along_width; j++)
        {
            if (i<ghosts || i>=(ghosts+mNumCellLength))
            {
                mGhostNodeIndices.insert(node);
            }
            unsigned boundary = 0;
            if ((i==0) || (i==num_nodes_along_length-1))
            {
                boundary = 1;
            }

            double x = x0 + horizontal_spacing*((double)j + 0.25*(1.0+ SmallPow(-1.0,i+1)));
            double y = y0 + vertical_spacing*(double)i;

            // Avoid floating point errors which upset OffLatticeSimulation
            if ( (y<0.0) && (y>-1e-12) )
            {
                // Difficult to cover - just corrects floating point errors that have occurred from time to time!
                #define COVERAGE_IGNORE
                y = 0.0;
                #undef COVERAGE_IGNORE
            }

            (*p_node_file) << node++ << "\t" << x << "\t" << y << "\t" << boundary << std::endl;
        }
    }
    p_node_file->close();

    // Write element file and edge file
    out_stream p_elem_file = output_file_handler.OpenOutputFile(mMeshFilename+".ele");
    (*p_elem_file) << std::scientific;

    out_stream p_edge_file = output_file_handler.OpenOutputFile(mMeshFilename+".edge");
    (*p_node_file) << std::scientific;

    (*p_elem_file) << num_elem << "\t3\t0" << std::endl;
    (*p_edge_file) << num_edges << "\t1" << std::endl;

    unsigned elem = 0;
    unsigned edge = 0;
    for (unsigned i=0; i<num_elem_along_length; i++)
    {
        for (unsigned j=0; j < num_elem_along_width; j++)
        {
            unsigned node0 =     i*num_nodes_along_width + j;
            unsigned node1 =     i*num_nodes_along_width + j+1;
            unsigned node2 = (i+1)*num_nodes_along_width + j;

            if (i%2 != 0)
            {
                node2 = node2 + 1;
            }

            (*p_elem_file) << elem++ << "\t" << node0 << "\t" << node1 << "\t" << node2 << std::endl;

            unsigned horizontal_edge_is_boundary_edge = 0;
            unsigned vertical_edge_is_boundary_edge = 0;
            if (i==0)
            {
                horizontal_edge_is_boundary_edge = 1;
            }

            (*p_edge_file) << edge++ << "\t" << node0 << "\t" << node1 << "\t" << horizontal_edge_is_boundary_edge << std::endl;
            (*p_edge_file) << edge++ << "\t" << node1 << "\t" << node2 << "\t" << 0 << std::endl;
            (*p_edge_file) << edge++ << "\t" << node2 << "\t" << node0 << "\t" << vertical_edge_is_boundary_edge << std::endl;

            node0 = i*num_nodes_along_width + j + 1;

            if (i%2 != 0)
            {
                node0 = node0 - 1;
            }
            node1 = (i+1)*num_nodes_along_width + j+1;
            node2 = (i+1)*num_nodes_along_width + j;

            (*p_elem_file) << elem++ << "\t" << node0 << "\t" << node1 << "\t" << node2 << std::endl;
        }
    }

    for (unsigned i=0; i<num_elem_along_length; i++)
    {
        unsigned node0, node1;

        if (i%2==0)
        {
             node0 = (i+1)*num_nodes_along_width - 1;
             node1 = (i+2)*num_nodes_along_width - 1;
        }
        else
        {
            node0 = (i+1)*num_nodes_along_width;
            node1 = (i)*num_nodes_along_width;
        }
        (*p_edge_file) << edge++ << "\t" << node0 << "\t" << node1 << "\t" << 1 << std::endl;
    }

    for (unsigned j=0; j<num_elem_along_width; j++)
    {
        unsigned node0 = num_nodes_along_width*(num_nodes_along_length-1) + j;
        unsigned node1 = num_nodes_along_width*(num_nodes_along_length-1) + j+1;
        (*p_edge_file) << edge++ << "\t" << node1 << "\t" << node0 << "\t" << 1 << std::endl;
    }

    p_elem_file->close();
    p_edge_file->close();

    // Having written the mesh to file, now construct it using TrianglesMeshReader.
    // Nested scope so the reader closes files before we delete them below.
    {
        TrianglesMeshReader<2,2> mesh_reader(output_file_handler.GetOutputDirectoryFullPath() + mMeshFilename);
        mpMesh = new Cylindrical2dMesh(mDomainWidth);
        mpMesh->ConstructFromMeshReader(mesh_reader);
    }

    // Make the mesh cylindrical (we use Triangle library mode inside this ReMesh call)
    mpMesh->ReMesh();

    // Delete the temporary files
    output_file_handler.FindFile("").Remove();

    // The original files have been deleted, it is better if the mesh object forgets about them
    mpMesh->SetMeshHasChangedSinceLoading();
}
    void TestWriteResultsToFileAndOutputCellPopulationParameters()
    {
        EXIT_IF_PARALLEL;    // Copying in parallel uses parallel NodesOnlyMesh and will therefore cause unexpected errors.

        // Resetting the maximum cell ID to zero (to account for previous tests)
        CellId::ResetMaxCellId();

        std::string output_directory = "TestPottsBasedCellPopulationWriters";
        OutputFileHandler output_file_handler(output_directory, false);

        // 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;
        CellsGenerator<FixedDurationGenerationBasedCellCycleModel, 2> cells_generator;
        cells_generator.GenerateBasic(cells, p_mesh->GetNumElements());

        // Create cell population
        PottsBasedCellPopulation<2> cell_population(*p_mesh, cells);

        // For coverage, label one cell
        boost::shared_ptr<AbstractCellProperty> p_label(cell_population.GetCellPropertyRegistry()->Get<CellLabel>());
        cell_population.GetCellUsingLocationIndex(0)->AddCellProperty(p_label);

        TS_ASSERT_EQUALS(cell_population.GetIdentifier(), "PottsBasedCellPopulation-2");

        cell_population.SetCellAncestorsToLocationIndices();
        cell_population.AddCellPopulationCountWriter<CellMutationStatesCountWriter>();
        cell_population.AddCellPopulationCountWriter<CellProliferativeTypesCountWriter>();
        cell_population.AddCellPopulationCountWriter<CellProliferativePhasesCountWriter>();
        cell_population.AddCellWriter<CellProliferativePhasesWriter>();
        cell_population.AddCellWriter<CellAncestorWriter>();
        cell_population.AddCellWriter<CellAgesWriter>();
        cell_population.AddCellWriter<CellVolumesWriter>();
        cell_population.SetNumSweepsPerTimestep(5);

        TS_ASSERT_EQUALS(cell_population.GetNumSweepsPerTimestep(), 5u);

        // VTK writing needs a simulation time
        SimulationTime::Instance()->SetEndTimeAndNumberOfTimeSteps(1.0, 1);

        cell_population.OpenWritersFiles(output_file_handler);
        cell_population.WriteResultsToFiles(output_directory);
        cell_population.CloseWritersFiles();

        // Compare output with saved files of what they should look like
        std::string results_dir = output_file_handler.GetOutputDirectoryFullPath();

        FileComparison(results_dir + "results.viznodes", "cell_based/test/data/TestPottsBasedCellPopulationWriters/results.viznodes").CompareFiles();
        FileComparison(results_dir + "results.vizcelltypes", "cell_based/test/data/TestPottsBasedCellPopulationWriters/results.vizcelltypes").CompareFiles();
        FileComparison(results_dir + "results.vizancestors", "cell_based/test/data/TestPottsBasedCellPopulationWriters/results.vizancestors").CompareFiles();
        FileComparison(results_dir + "cellmutationstates.dat", "cell_based/test/data/TestPottsBasedCellPopulationWriters/cellmutationstates.dat").CompareFiles();
        FileComparison(results_dir + "cellages.dat", "cell_based/test/data/TestPottsBasedCellPopulationWriters/cellages.dat").CompareFiles();
        FileComparison(results_dir + "cellareas.dat", "cell_based/test/data/TestPottsBasedCellPopulationWriters/cellareas.dat").CompareFiles();

        // Test that the cell population parameters are output correctly
        out_stream parameter_file = output_file_handler.OpenOutputFile("results.parameters");

        // Write cell population parameters to file
        cell_population.OutputCellPopulationParameters(parameter_file);
        parameter_file->close();

        // Compare output with saved files of what they should look like
        FileComparison( results_dir + "results.parameters", "cell_based/test/data/TestPottsBasedCellPopulationWriters/results.parameters").CompareFiles();
    }
void AbstractCellBasedSimulation<ELEMENT_DIM,SPACE_DIM>::Solve()
{
    CellBasedEventHandler::BeginEvent(CellBasedEventHandler::EVERYTHING);
    CellBasedEventHandler::BeginEvent(CellBasedEventHandler::SETUP);

    // Set up the simulation time
    SimulationTime* p_simulation_time = SimulationTime::Instance();
    double current_time = p_simulation_time->GetTime();

    assert(mDt != DOUBLE_UNSET);  //Subclass constructors take care of this

    if (mEndTime == DOUBLE_UNSET)
    {
        EXCEPTION("SetEndTime has not yet been called.");
    }

    /*
     * Note that mDt is used here for "ideal time step". If this step doesn't divide the time remaining
     * then a *different* time step will be taken by the time-stepper. The real time-step (used in the
     * SimulationTime singleton) is currently not available to this class.
     *
     * \todo Should we over-write the value of mDt, or change this behaviour? (see #2159)
     */
    unsigned num_time_steps = (unsigned) ((mEndTime-current_time)/mDt+0.5);
    if (current_time > 0) // use the reset function if necessary
    {
        p_simulation_time->ResetEndTimeAndNumberOfTimeSteps(mEndTime, num_time_steps);
    }
    else
    {
        if (p_simulation_time->IsEndTimeAndNumberOfTimeStepsSetUp())
        {
            EXCEPTION("End time and number of timesteps already setup. You should not use SimulationTime::SetEndTimeAndNumberOfTimeSteps in cell-based tests.");
        }
        else
        {
            p_simulation_time->SetEndTimeAndNumberOfTimeSteps(mEndTime, num_time_steps);
        }
    }

    if (mOutputDirectory == "")
    {
        EXCEPTION("OutputDirectory not set");
    }

    double time_now = p_simulation_time->GetTime();
    std::ostringstream time_string;
    time_string << time_now;

    std::string results_directory = mOutputDirectory +"/results_from_time_" + time_string.str();
    mSimulationOutputDirectory = results_directory;

    // Set up simulation

    // Create output files for the visualizer
    OutputFileHandler output_file_handler(results_directory+"/", true);

    mrCellPopulation.OpenWritersFiles(results_directory+"/");

    if (mOutputDivisionLocations)
    {
        mpDivisionLocationFile = output_file_handler.OpenOutputFile("divisions.dat");
    }

    if (PetscTools::AmMaster())
    {
        mpVizSetupFile = output_file_handler.OpenOutputFile("results.vizsetup");
    }

    // If any PDEs have been defined, set up results files to store their solution
    if (mpCellBasedPdeHandler != NULL)
    {
        mpCellBasedPdeHandler->OpenResultsFiles(this->mSimulationOutputDirectory);
        if (PetscTools::AmMaster())
        {
            *this->mpVizSetupFile << "PDE \n";
        }

        /*
         * If any PDEs have been defined, solve them here before updating cells and store
         * their solution in results files. This also initializes the relevant CellData.
         * NOTE that this works as the PDEs are elliptic.
         */
        CellBasedEventHandler::BeginEvent(CellBasedEventHandler::PDE);
        mpCellBasedPdeHandler->SolvePdeAndWriteResultsToFile(this->mSamplingTimestepMultiple);
        CellBasedEventHandler::EndEvent(CellBasedEventHandler::PDE);
    }

    SetupSolve();

    // Call SetupSolve() on each modifier
    for (typename std::vector<boost::shared_ptr<AbstractCellBasedSimulationModifier<ELEMENT_DIM, SPACE_DIM> > >::iterator iter = mSimulationModifiers.begin();
         iter != mSimulationModifiers.end();
         ++iter)
    {
        (*iter)->SetupSolve(this->mrCellPopulation,this->mSimulationOutputDirectory);
    }

    /*
     * Age the cells to the correct time. Note that cells are created with
     * negative birth times so that some are initially almost ready to divide.
     */
    LOG(1, "Setting up cells...");
    for (typename AbstractCellPopulation<ELEMENT_DIM,SPACE_DIM>::Iterator cell_iter = mrCellPopulation.Begin();
         cell_iter != mrCellPopulation.End();
         ++cell_iter)
    {
        /*
         * We don't use the result; this call is just to force the cells to age
         * to the current time running their cell-cycle models to get there.
         */
        cell_iter->ReadyToDivide();
    }
    LOG(1, "\tdone\n");

    // Write initial conditions to file for the visualizer
    WriteVisualizerSetupFile();

    if (PetscTools::AmMaster())
    {
        *mpVizSetupFile << std::flush;
    }

    mrCellPopulation.WriteResultsToFiles(results_directory+"/");

    OutputSimulationSetup();
    CellBasedEventHandler::EndEvent(CellBasedEventHandler::SETUP);

    // Enter main time loop
    while (!( p_simulation_time->IsFinished() || StoppingEventHasOccurred() ) )
    {
        LOG(1, "--TIME = " << p_simulation_time->GetTime() << "\n");

        // This function calls DoCellRemoval(), DoCellBirth() and CellPopulation::Update()
        UpdateCellPopulation();

        // Update cell locations and topology
        UpdateCellLocationsAndTopology();

        // Update the assignment of cells to processes.
        mrCellPopulation.UpdateCellProcessLocation();

        // Increment simulation time here, so results files look sensible
        p_simulation_time->IncrementTimeOneStep();

        // If any PDEs have been defined, solve them and store their solution in results files
        if (mpCellBasedPdeHandler != NULL)
        {
            CellBasedEventHandler::BeginEvent(CellBasedEventHandler::PDE);
            mpCellBasedPdeHandler->SolvePdeAndWriteResultsToFile(this->mSamplingTimestepMultiple);
            CellBasedEventHandler::EndEvent(CellBasedEventHandler::PDE);
        }

        // Call UpdateAtEndOfTimeStep(), which may be implemented by child classes
        CellBasedEventHandler::BeginEvent(CellBasedEventHandler::UPDATESIMULATION);
        UpdateAtEndOfTimeStep();

        // Call UpdateAtEndOfTimeStep() on each modifier
        for (typename std::vector<boost::shared_ptr<AbstractCellBasedSimulationModifier<ELEMENT_DIM, SPACE_DIM> > >::iterator iter = mSimulationModifiers.begin();
             iter != mSimulationModifiers.end();
             ++iter)
        {
            (*iter)->UpdateAtEndOfTimeStep(this->mrCellPopulation);
        }
        CellBasedEventHandler::EndEvent(CellBasedEventHandler::UPDATESIMULATION);

        // Output current results to file
        CellBasedEventHandler::BeginEvent(CellBasedEventHandler::OUTPUT);
        if (p_simulation_time->GetTimeStepsElapsed()%mSamplingTimestepMultiple == 0)
        {
            mrCellPopulation.WriteResultsToFiles(results_directory+"/");

            // Call UpdateAtEndOfOutputTimeStep() on each modifier
            for (typename std::vector<boost::shared_ptr<AbstractCellBasedSimulationModifier<ELEMENT_DIM, SPACE_DIM> > >::iterator iter = mSimulationModifiers.begin();
                 iter != mSimulationModifiers.end();
                 ++iter)
            {
                (*iter)->UpdateAtEndOfOutputTimeStep(this->mrCellPopulation);
            }
        }
        CellBasedEventHandler::EndEvent(CellBasedEventHandler::OUTPUT);
    }

    LOG(1, "--END TIME = " << p_simulation_time->GetTime() << "\n");

    /*
     * Carry out a final update so that cell population is coherent with new cell positions.
     * Note that cell birth and death still need to be checked because they may be spatially
     * dependent.
     */
    UpdateCellPopulation();

    // If any PDEs have been defined, close the results files storing their solution
    if (mpCellBasedPdeHandler != NULL)
    {
        mpCellBasedPdeHandler->CloseResultsFiles();
    }

    CellBasedEventHandler::BeginEvent(CellBasedEventHandler::UPDATESIMULATION);
    UpdateAtEndOfSolve();

    // Call UpdateAtEndOfSolve(), on each modifier
    for (typename std::vector<boost::shared_ptr<AbstractCellBasedSimulationModifier<ELEMENT_DIM, SPACE_DIM> > >::iterator iter = mSimulationModifiers.begin();
         iter != mSimulationModifiers.end();
         ++iter)
    {
        (*iter)->UpdateAtEndOfSolve(this->mrCellPopulation);
    }
    CellBasedEventHandler::EndEvent(CellBasedEventHandler::UPDATESIMULATION);

    CellBasedEventHandler::BeginEvent(CellBasedEventHandler::OUTPUT);

    mrCellPopulation.CloseOutputFiles();

    if (mOutputDivisionLocations)
    {
        mpDivisionLocationFile->close();
    }

    if (PetscTools::AmMaster())
    {
        *mpVizSetupFile << "Complete\n";
        mpVizSetupFile->close();
    }

    CellBasedEventHandler::EndEvent(CellBasedEventHandler::OUTPUT);
    CellBasedEventHandler::EndEvent(CellBasedEventHandler::EVERYTHING);
}
Exemplo n.º 23
0
    void TestSolvePdeAndWriteResultsToFileWithoutCoarsePdeMeshNeumann() throw(Exception)
    {
        EXIT_IF_PARALLEL;

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

        // Set up mesh
        MutableMesh<2,2> mesh;
        TrianglesMeshReader<2,2> mesh_reader("mesh/test/data/disk_522_elements");
        mesh.ConstructFromMeshReader(mesh_reader);

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

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

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

        // Create a single PDE and pass to the handler
        // Note SimplePdeForTesting wouldnt work as theres no solution with Neuman conditions.
        // Also note that when using Neuman conditions the only solution that works is u=0
        CellwiseSourcePde<2> pde(cell_population, 0.0);
        ConstBoundaryCondition<2> bc(0.0);
        PdeAndBoundaryConditions<2> pde_and_bc(&pde, &bc, true);
        pde_and_bc.SetDependentVariableName("variable");

        // For coverage, provide an initial guess for the solution
        std::vector<double> data(mesh.GetNumNodes()+1);
        for (unsigned i=0; i<mesh.GetNumNodes(); i++)
        {
            data[i] = 1.0;
        }

        Vec vector = PetscTools::CreateVec(data);
        pde_and_bc.SetSolution(vector);

        pde_handler.AddPdeAndBc(&pde_and_bc);

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

        // Solve PDE (set sampling timestep multiple to be large doesn't do anything as always output on 1st timestep)
        pde_handler.SolvePdeAndWriteResultsToFile(10);

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

        // Check the correct solution was obtained
        for (AbstractCellPopulation<2>::Iterator cell_iter = cell_population.Begin();
             cell_iter != cell_population.End();
             ++cell_iter)
        {
            // Test that PDE solver is working correctly
            TS_ASSERT_DELTA(cell_iter->GetCellData()->GetItem("variable"), 0.0, 0.02);
        }
    }
    void TestNodeBasedSimulationWithContactInhibition()
    {
        EXIT_IF_PARALLEL;    // HoneycombMeshGenerator does not work in parallel

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

        MAKE_PTR(WildTypeCellMutationState, p_state);
        MAKE_PTR(TransitCellProliferativeType, p_transit_type);
        std::vector<CellPtr> cells;
        for (unsigned i=0; i<mesh.GetNumNodes(); i++)
        {
            ContactInhibitionCellCycleModel* p_cycle_model = new ContactInhibitionCellCycleModel();
            p_cycle_model->SetDimension(2);
            p_cycle_model->SetBirthTime(-10.0);
            p_cycle_model->SetQuiescentVolumeFraction(0.9);
            p_cycle_model->SetEquilibriumVolume(0.7854); //pi *(0.5)^2
            p_cycle_model->SetStemCellG1Duration(0.1);
            p_cycle_model->SetTransitCellG1Duration(0.1);

            CellPtr p_cell(new Cell(p_state, p_cycle_model));
            p_cell->SetCellProliferativeType(p_transit_type);
            cells.push_back(p_cell);
        }

        NodeBasedCellPopulation<2> cell_population(mesh, cells);
        cell_population.AddPopulationWriter<CellMutationStatesCountWriter>();
        cell_population.AddCellWriter<CellVolumesWriter>();
        cell_population.AddPopulationWriter<NodeVelocityWriter>();

        // Create a simulation
        OffLatticeSimulation<2> simulator(cell_population);
        simulator.SetOutputDirectory("TestNodeBasedSimulationWithVolumeTracked");

        TS_ASSERT_EQUALS(simulator.GetDt(), 1.0/120.0); // Default value for off-lattice simulations
        simulator.SetEndTime(simulator.GetDt()/2.0);

        // Create a volume-tracking modifier and pass it to the simulation
        MAKE_PTR(VolumeTrackingModifier<2>, p_modifier);
        simulator.AddSimulationModifier(p_modifier);

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

        // Run simulation
        simulator.Solve();

        // Test that the node velocities file exists
        OutputFileHandler output_file_handler("TestNodeBasedSimulationWithVolumeTracked", false);
        FileFinder generated = output_file_handler.FindFile("results_from_time_0/nodevelocities.dat");
        TS_ASSERT(generated.Exists());

        // Test that the volumes of the cells are correct in CellData at the first timestep
        for (AbstractCellPopulation<2>::Iterator cell_iter = cell_population.Begin();
             cell_iter != cell_population.End();
             ++cell_iter)
        {
            TS_ASSERT_DELTA(cell_population.GetVolumeOfCell(*cell_iter), cell_iter->GetCellData()->GetItem("volume"), 1e-4);
        }

        simulator.SetEndTime(2.0);

        // Run simulation
        simulator.Solve();

        // Test that the volumes of the cells are correct in CellData at the end time
        for (AbstractCellPopulation<2>::Iterator cell_iter = cell_population.Begin();
             cell_iter != cell_population.End();
             ++cell_iter)
        {
            TS_ASSERT_DELTA(cell_population.GetVolumeOfCell(*cell_iter), cell_iter->GetCellData()->GetItem("volume"), 1e-4);
        }

        // Check that the correct number of cells are labelled (i.e. experiencing contact inhibition)
        TS_ASSERT_EQUALS(cell_population.GetCellPropertyRegistry()->Get<CellLabel>()->GetCellCount(), 2u);
    }
Exemplo n.º 25
0
    void TestSolvePdeAndWriteResultsToFileAndGetPDESolutionAtPointWithoutCoarsePdeMeshDirichlet() throw(Exception)
    {
        EXIT_IF_PARALLEL;

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

        // Set up mesh
        MutableMesh<2,2> mesh;
        TrianglesMeshReader<2,2> mesh_reader("mesh/test/data/disk_522_elements");
        mesh.ConstructFromMeshReader(mesh_reader);

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

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

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

        // Create a single PDE and pass to the handler
        SimplePdeForTesting pde;
        ConstBoundaryCondition<2> bc(1.0);
        PdeAndBoundaryConditions<2> pde_and_bc(&pde, &bc, false);
        pde_and_bc.SetDependentVariableName("variable");

        // For coverage, provide an initial guess for the solution
        std::vector<double> data(mesh.GetNumNodes());
        for (unsigned i=0; i<mesh.GetNumNodes(); i++)
        {
            data[i] = 1.0;
        }

        Vec vector = PetscTools::CreateVec(data);
        pde_and_bc.SetSolution(vector);

        pde_handler.AddPdeAndBc(&pde_and_bc);

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

        // Solve PDE (set sampling timestep multiple to be large doesn't do anything as always output on 1st timestep)
        pde_handler.SolvePdeAndWriteResultsToFile(10);

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

        // Test that this is correct by comparing with an existing results file
        std::string results_dir = output_file_handler.GetOutputDirectoryFullPath();

        NumericFileComparison comparison(results_dir + "results.vizpdesolution", "cell_based/test/data/TestCellBasedPdeHandler/results.vizpdesolution");
        TS_ASSERT(comparison.CompareFiles());

        // Check the correct solution was obtained
        for (AbstractCellPopulation<2>::Iterator cell_iter = cell_population.Begin();
             cell_iter != cell_population.End();
             ++cell_iter)
        {
            double radius = norm_2(cell_population.GetLocationOfCellCentre(*cell_iter));
            double analytic_solution = 1.0 - 0.25*(1 - pow(radius,2.0));

            // Test that PDE solver is working correctly
            TS_ASSERT_DELTA(cell_iter->GetCellData()->GetItem("variable"), analytic_solution, 0.02);
        }

        // Now check the GetPdeSolutionAtPoint method

        // First loop over nodes and check it works
        // Check the correct solution was obtained
        for (AbstractCellPopulation<2>::Iterator cell_iter = cell_population.Begin();
             cell_iter != cell_population.End();
             ++cell_iter)
        {
            double cell_data_solution(cell_iter->GetCellData()->GetItem("variable"));
            c_vector<double,2> cell_location = cell_population.GetLocationOfCellCentre(*cell_iter);

            TS_ASSERT_DELTA(pde_handler.GetPdeSolutionAtPoint(cell_location,"variable"), cell_data_solution, 1e-6);
        }

        // Now choose some other points

        // Centre
        c_vector<double,2> point;
        point(0) = 0.0;
        point(1) = 0.0;

        TS_ASSERT_DELTA(pde_handler.GetPdeSolutionAtPoint(point,"variable"), 0.75, 0.01);

        // Cover exception
        TS_ASSERT_THROWS_CONTAINS(pde_handler.GetPdeSolutionAtPoint(point, "not_a_var"),
                                  "There is no PDE with that variable.");

        // Random point
        point(0) = 0.5;
        point(1) = 0.5;

        TS_ASSERT_DELTA(pde_handler.GetPdeSolutionAtPoint(point,"variable"), 1.0 - (1.0-2.0*0.5*0.5)/4.0, 0.01);

        // Point on the boundary
        point(0) = 1.0;
        point(1) = 0.0;

        TS_ASSERT_DELTA(pde_handler.GetPdeSolutionAtPoint(point,"variable"), 1.0, 1e-6);
    }
Exemplo n.º 26
0
    void TestUpdateRuleOutputUpdateRuleInfo()
    {
        EXIT_IF_PARALLEL;
        std::string output_directory = "TestPottsUpdateRulesOutputParameters";
        OutputFileHandler output_file_handler(output_directory, false);

        // Test with VolumeConstraintPottsUpdateRule
        VolumeConstraintPottsUpdateRule<2> volume_constraint;
        volume_constraint.SetDeformationEnergyParameter(0.1);
        volume_constraint.SetMatureCellTargetVolume(20);

        TS_ASSERT_EQUALS(volume_constraint.GetIdentifier(), "VolumeConstraintPottsUpdateRule-2");

        out_stream volume_constraint_parameter_file = output_file_handler.OpenOutputFile("volume_constraint_results.parameters");
        volume_constraint.OutputUpdateRuleInfo(volume_constraint_parameter_file);
        volume_constraint_parameter_file->close();

        std::string volume_constraint_results_dir = output_file_handler.GetOutputDirectoryFullPath();
        FileComparison( volume_constraint_results_dir + "volume_constraint_results.parameters", "cell_based/test/data/TestPottsUpdateRules/volume_constraint_results.parameters").CompareFiles();

        // Test with SurfaceAreaConstraintPottsUpdateRule
        SurfaceAreaConstraintPottsUpdateRule<2> surface_area_constraint;
        surface_area_constraint.SetDeformationEnergyParameter(0.1);
        surface_area_constraint.SetMatureCellTargetSurfaceArea(20);

        TS_ASSERT_EQUALS(surface_area_constraint.GetIdentifier(), "SurfaceAreaConstraintPottsUpdateRule-2");

        out_stream surface_area_constraint_parameter_file = output_file_handler.OpenOutputFile("surface_area_constraint_results.parameters");
        surface_area_constraint.OutputUpdateRuleInfo(surface_area_constraint_parameter_file);
        surface_area_constraint_parameter_file->close();

        std::string surface_area_constraint_results_dir = output_file_handler.GetOutputDirectoryFullPath();
        FileComparison( surface_area_constraint_results_dir + "surface_area_constraint_results.parameters", "cell_based/test/data/TestPottsUpdateRules/surface_area_constraint_results.parameters").CompareFiles();

        // Test with AdhesionPottsUpdateRule
        AdhesionPottsUpdateRule<2> adhesion_update;
        adhesion_update.SetCellCellAdhesionEnergyParameter(0.3);
        adhesion_update.SetCellBoundaryAdhesionEnergyParameter(0.4);

        TS_ASSERT_EQUALS(adhesion_update.GetIdentifier(), "AdhesionPottsUpdateRule-2");

        out_stream adhesion_update_parameter_file = output_file_handler.OpenOutputFile("adhesion_update_results.parameters");
        adhesion_update.OutputUpdateRuleInfo(adhesion_update_parameter_file);
        adhesion_update_parameter_file->close();

        std::string adhesion_update_results_dir = output_file_handler.GetOutputDirectoryFullPath();
        FileComparison( adhesion_update_results_dir + "adhesion_update_results.parameters", "cell_based/test/data/TestPottsUpdateRules/adhesion_update_results.parameters").CompareFiles();

        // Test with DifferentialAdhesionPottsUpdateRule
        DifferentialAdhesionPottsUpdateRule<2> differential_adhesion_update;
        differential_adhesion_update.SetLabelledCellLabelledCellAdhesionEnergyParameter(0.3);
        differential_adhesion_update.SetLabelledCellCellAdhesionEnergyParameter(0.4);
        differential_adhesion_update.SetCellCellAdhesionEnergyParameter(0.5);
        differential_adhesion_update.SetLabelledCellBoundaryAdhesionEnergyParameter(0.6);
        differential_adhesion_update.SetCellBoundaryAdhesionEnergyParameter(0.7);

        TS_ASSERT_EQUALS(differential_adhesion_update.GetIdentifier(), "DifferentialAdhesionPottsUpdateRule-2");

        out_stream differential_adhesion_update_parameter_file = output_file_handler.OpenOutputFile("differential_adhesion_update_results.parameters");
        differential_adhesion_update.OutputUpdateRuleInfo(differential_adhesion_update_parameter_file);
        differential_adhesion_update_parameter_file->close();

        std::string differential_adhesion_update_results_dir = output_file_handler.GetOutputDirectoryFullPath();
        FileComparison(differential_adhesion_update_results_dir + "differential_adhesion_update_results.parameters",
                       "cell_based/test/data/TestPottsUpdateRules/differential_adhesion_update_results.parameters").CompareFiles();

        // Test with DifferentialAdhesionPottsUpdateRule
        ChemotaxisPottsUpdateRule<2> chemotaxis_update;

        TS_ASSERT_EQUALS(chemotaxis_update.GetIdentifier(), "ChemotaxisPottsUpdateRule-2");

        out_stream chemotaxis_update_parameter_file = output_file_handler.OpenOutputFile("chemotaxis_update_results.parameters");
        chemotaxis_update.OutputUpdateRuleInfo(chemotaxis_update_parameter_file);
        chemotaxis_update_parameter_file->close();

        std::string chemotaxis_update_results_dir = output_file_handler.GetOutputDirectoryFullPath();
        FileComparison(chemotaxis_update_results_dir + "chemotaxis_update_results.parameters",
                       "cell_based/test/data/TestPottsUpdateRules/chemotaxis_update_results.parameters").CompareFiles();
    }
Exemplo n.º 27
0
    void TestSolvePdeAndWriteResultsToFileCoarsePdeMeshNeumann() throw(Exception)
    {
        EXIT_IF_PARALLEL;

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

        // Create a cigar-shaped mesh
        TrianglesMeshReader<2,2> mesh_reader("mesh/test/data/disk_522_elements");
        MutableMesh<2,2> mesh;
        mesh.ConstructFromMeshReader(mesh_reader);
        mesh.Scale(5.0, 1.0);

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

        MeshBasedCellPopulation<2> cell_population(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.01);
        ConstBoundaryCondition<2> bc(0.0);
        PdeAndBoundaryConditions<2> pde_and_bc(&pde, &bc, true); // Last boolean specifies Neuman conditions
        pde_and_bc.SetDependentVariableName("variable");

        pde_handler.AddPdeAndBc(&pde_and_bc);

        // 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);

        // For coverage, provide an initial guess for the solution
        std::vector<double> data(pde_handler.mpCoarsePdeMesh->GetNumNodes());
        for (unsigned i=0; i<pde_handler.mpCoarsePdeMesh->GetNumNodes(); i++)
        {
            data[i] = 1.0;
        }

        Vec vector = PetscTools::CreateVec(data);
        pde_and_bc.SetSolution(vector);

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

        // Solve PDE (set sampling timestep multiple to be large doesn't do anything as always output on 1st timestep)
        pde_handler.SolvePdeAndWriteResultsToFile(10);

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

        // Test that boundary cells experience the right boundary condition
        for (AbstractCellPopulation<2>::Iterator cell_iter = cell_population.Begin();
             cell_iter != cell_population.End();
             ++cell_iter)
        {
            if (cell_population.GetNodeCorrespondingToCell(*cell_iter)->IsBoundaryNode())
            {
                TS_ASSERT_DELTA(cell_iter->GetCellData()->GetItem("variable"), 0.0, 1e-1);
            }
        }
    }
    void TestCellPopulationWritersIn3dWithParticles() throw(Exception)
    {
        EXIT_IF_PARALLEL;    // This test doesn't work in parallel.

        // Set up SimulationTime (needed if VTK is used)
        SimulationTime::Instance()->SetEndTimeAndNumberOfTimeSteps(1.0, 1);

        // Resetting the Maximum cell Id to zero (to account for previous tests)
        CellId::ResetMaxCellId();

        // Create a simple 3D mesh with some particles
        std::vector<Node<3>*> nodes;
        nodes.push_back(new Node<3>(0,  true,  0.0, 0.0, 0.0));
        nodes.push_back(new Node<3>(1,  true,  1.0, 1.0, 0.0));
        nodes.push_back(new Node<3>(2,  true,  1.0, 0.0, 1.0));
        nodes.push_back(new Node<3>(3,  true,  0.0, 1.0, 1.0));
        nodes.push_back(new Node<3>(4,  false, 0.5, 0.5, 0.5));
        nodes.push_back(new Node<3>(5,  false, -1.0, -1.0, -1.0));
        nodes.push_back(new Node<3>(6,  false,  2.0, -1.0, -1.0));
        nodes.push_back(new Node<3>(7,  false,  2.0,  2.0, -1.0));
        nodes.push_back(new Node<3>(8,  false, -1.0,  2.0, -1.0));
        nodes.push_back(new Node<3>(9,  false, -1.0, -1.0,  2.0));
        nodes.push_back(new Node<3>(10, false,  2.0, -1.0,  2.0));
        nodes.push_back(new Node<3>(11, false,  2.0,  2.0,  2.0));
        nodes.push_back(new Node<3>(12, false, -1.0,  2.0,  2.0));

        // Convert this to a NodesOnlyMesh
        MAKE_PTR(NodesOnlyMesh<3>, p_mesh);
        p_mesh->ConstructNodesWithoutMesh(nodes, 1.5);

        // Specify the node indices corresponding to cells (the others correspond to particles)
        std::vector<unsigned> location_indices;
        for (unsigned index=0; index<5; index++)
        {
            location_indices.push_back(index);
        }

        // Set up cells
        std::vector<CellPtr> cells;
        CellsGenerator<FixedDurationGenerationBasedCellCycleModel, 3> cells_generator;
        cells_generator.GenerateGivenLocationIndices(cells, location_indices);

        cells[4]->AddCellProperty(CellPropertyRegistry::Instance()->Get<ApoptoticCellProperty>()); // coverage

        TS_ASSERT_EQUALS(cells[4]->HasCellProperty<ApoptoticCellProperty>(), true);

        // Create cell population
        NodeBasedCellPopulationWithParticles<3> cell_population(*p_mesh, cells, location_indices);

        // Coverage of writing CellData to VTK
        for (NodeBasedCellPopulationWithParticles<3>::Iterator cell_iter = cell_population.Begin();
                cell_iter != cell_population.End();
                ++cell_iter)
        {
            cell_iter->GetCellData()->SetItem("var0", 1.0);
            cell_iter->GetCellData()->SetItem("var1", 2.0);
        }

        cell_population.Update(); // so cell neighbours are calculated when outputting volume

        TS_ASSERT_EQUALS(cell_population.GetIdentifier(), "NodeBasedCellPopulationWithParticles-3");

        // Test writer methods
        cell_population.AddCellWriter<CellVolumesWriter>();
        cell_population.AddCellPopulationCountWriter<CellMutationStatesCountWriter>();
        cell_population.AddCellPopulationCountWriter<CellProliferativeTypesCountWriter>();
        cell_population.AddCellWriter<CellAgesWriter>();
        cell_population.AddCellPopulationCountWriter<CellProliferativePhasesCountWriter>();
        cell_population.AddCellWriter<CellProliferativePhasesWriter>();

        cell_population.SetCellAncestorsToLocationIndices();

        cell_population.AddCellWriter<CellAncestorWriter>();

        std::string output_directory = "TestCellPopulationWritersIn3dWithParticles";
        OutputFileHandler output_file_handler(output_directory, false);

        cell_population.OpenWritersFiles(output_file_handler);
        cell_population.WriteResultsToFiles(output_directory);
        cell_population.CloseWritersFiles();

        // Compare output with saved files of what they should look like
        std::string results_dir = output_file_handler.GetOutputDirectoryFullPath();

        FileComparison(results_dir + "results.viznodes", "cell_based/test/data/TestCellPopulationWritersIn3dWithParticles/results.viznodes").CompareFiles();
        FileComparison(results_dir + "results.vizcelltypes", "cell_based/test/data/TestCellPopulationWritersIn3dWithParticles/results.vizcelltypes").CompareFiles();
        FileComparison(results_dir + "results.vizancestors", "cell_based/test/data/TestCellPopulationWritersIn3dWithParticles/results.vizancestors").CompareFiles();

        // Test the GetCellMutationStateCount function: there should only be healthy cells
        std::vector<unsigned> cell_mutation_states = cell_population.GetCellMutationStateCount();
        TS_ASSERT_EQUALS(cell_mutation_states.size(), 4u);
        TS_ASSERT_EQUALS(cell_mutation_states[0], 5u);
        TS_ASSERT_EQUALS(cell_mutation_states[1], 0u);
        TS_ASSERT_EQUALS(cell_mutation_states[2], 0u);
        TS_ASSERT_EQUALS(cell_mutation_states[3], 0u);

        // Test the GetCellProliferativeTypeCount function - we should have 4 stem cells and 1 dead cell (for coverage)
        std::vector<unsigned> cell_types = cell_population.GetCellProliferativeTypeCount();
        TS_ASSERT_EQUALS(cell_types.size(), 4u);
        TS_ASSERT_EQUALS(cell_types[0], 5u);
        TS_ASSERT_EQUALS(cell_types[1], 0u);
        TS_ASSERT_EQUALS(cell_types[2], 0u);
        TS_ASSERT_EQUALS(cell_types[3], 0u);

        // Test that the cell population parameters are output correctly
        out_stream parameter_file = output_file_handler.OpenOutputFile("results.parameters");

        // Write cell population parameters to file
        cell_population.OutputCellPopulationParameters(parameter_file);
        parameter_file->close();

        // Compare output with saved files of what they should look like
        FileComparison( results_dir + "results.parameters", "cell_based/test/data/TestCellPopulationWritersIn3dWithParticles/results.parameters").CompareFiles();

        for (unsigned i=0; i<nodes.size(); i++)
        {
            delete nodes[i];
        }
    }
void AbstractCellBasedSimulation<ELEMENT_DIM,SPACE_DIM>::OutputSimulationSetup()
{
    OutputFileHandler output_file_handler(this->mSimulationOutputDirectory + "/", false);

    // Output machine information
    ExecutableSupport::SetOutputDirectory(output_file_handler.GetOutputDirectoryFullPath());
    ExecutableSupport::WriteMachineInfoFile("system_info");

    if (PetscTools::AmMaster())
    {
        // Output Chaste provenance information
        out_stream build_info_file = output_file_handler.OpenOutputFile("build.info");
        std::string build_info;
        ExecutableSupport::GetBuildInfo(build_info);
        *build_info_file << build_info;
        build_info_file->close();

        // Output simulation parameter and setup details
        out_stream parameter_file = output_file_handler.OpenOutputFile("results.parameters");

        // Output simulation details
        std::string simulation_type = GetIdentifier();

        *parameter_file << "<Chaste>\n";
        *parameter_file << "\n\t<" << simulation_type << ">\n";
        OutputSimulationParameters(parameter_file);
        *parameter_file << "\t</" << simulation_type << ">\n";
        *parameter_file << "\n";

        // Output cell population details (includes cell-cycle model details)
        mrCellPopulation.OutputCellPopulationInfo(parameter_file);

        // Loop over cell killers
        *parameter_file << "\n\t<CellKillers>\n";
        for (typename std::vector<boost::shared_ptr<AbstractCellKiller<SPACE_DIM> > >::iterator iter = mCellKillers.begin();
             iter != mCellKillers.end();
             ++iter)
        {
            // Output cell killer details
            (*iter)->OutputCellKillerInfo(parameter_file);
        }
        *parameter_file << "\t</CellKillers>\n";

        // Iterate over simulationmodifiers
        *parameter_file << "\n\t<SimulationModifiers>\n";
        for (typename std::vector<boost::shared_ptr<AbstractCellBasedSimulationModifier<ELEMENT_DIM, SPACE_DIM> > >::iterator iter = mSimulationModifiers.begin();
             iter != mSimulationModifiers.end();
             ++iter)
        {
            // Output simulation modifier details
            (*iter)->OutputSimulationModifierInfo(parameter_file);
        }
        *parameter_file << "\t</SimulationModifiers>\n";

        // This is used to output information about subclasses
        OutputAdditionalSimulationSetup(parameter_file);

        *parameter_file << "\n</Chaste>\n";
        parameter_file->close();
    }
}
Exemplo n.º 30
0
TetrahedralMesh<DIM, DIM>* VertexBasedCellPopulation<DIM>::GetTetrahedralMeshUsingVertexMesh()
{
    // This method only works in 2D sequential
    assert(DIM == 2);
    assert(PetscTools::IsSequential());

    unsigned num_vertex_nodes = mpMutableVertexMesh->GetNumNodes();
    unsigned num_vertex_elements = mpMutableVertexMesh->GetNumElements();

    std::string mesh_file_name = "mesh";

    // Get a unique temporary foldername
    std::stringstream pid;
    pid << getpid();
    OutputFileHandler output_file_handler("2D_temporary_tetrahedral_mesh_" + pid.str());
    std::string output_dir = output_file_handler.GetOutputDirectoryFullPath();

    // Compute the number of nodes in the TetrahedralMesh
    unsigned num_tetrahedral_nodes = num_vertex_nodes + num_vertex_elements;

    // Write node file
    out_stream p_node_file = output_file_handler.OpenOutputFile(mesh_file_name+".node");
    (*p_node_file) << std::scientific;
    (*p_node_file) << std::setprecision(20);
    (*p_node_file) << num_tetrahedral_nodes << "\t2\t0\t1" << std::endl;

    // Begin by writing each node in the VertexMesh
    for (unsigned node_index=0; node_index<num_vertex_nodes; node_index++)
    {
        Node<DIM>* p_node = mpMutableVertexMesh->GetNode(node_index);

        ///\todo will the nodes in mpMutableVertexMesh always have indices 0,1,2,...? (#2221)
        unsigned index = p_node->GetIndex();

        c_vector<double, DIM> location = p_node->rGetLocation();

        unsigned is_boundary_node = p_node->IsBoundaryNode() ? 1 : 0;

        (*p_node_file) << index << "\t" << location[0] << "\t" << location[1] << "\t" << is_boundary_node << std::endl;
    }

    // Now write an additional node at each VertexElement's centroid
    unsigned num_tetrahedral_elements = 0;
    for (unsigned vertex_elem_index=0; vertex_elem_index<num_vertex_elements; vertex_elem_index++)
    {
        unsigned index = num_vertex_nodes + vertex_elem_index;

        c_vector<double, DIM> location = mpMutableVertexMesh->GetCentroidOfElement(vertex_elem_index);

        // Any node located at a VertexElement's centroid will not be a boundary node
        unsigned is_boundary_node = 0;
        (*p_node_file) << index << "\t" << location[0] << "\t" << location[1] << "\t" << is_boundary_node << std::endl;

        // Also keep track of how many tetrahedral elements there will be
        num_tetrahedral_elements += mpMutableVertexMesh->GetElement(vertex_elem_index)->GetNumNodes();
    }
    p_node_file->close();

    // Write element file
    out_stream p_elem_file = output_file_handler.OpenOutputFile(mesh_file_name+".ele");
    (*p_elem_file) << std::scientific;
    (*p_elem_file) << num_tetrahedral_elements << "\t3\t0" << std::endl;

    std::set<std::pair<unsigned, unsigned> > tetrahedral_edges;

    unsigned tetrahedral_elem_index = 0;
    for (unsigned vertex_elem_index=0; vertex_elem_index<num_vertex_elements; vertex_elem_index++)
    {
        VertexElement<DIM, DIM>* p_vertex_element = mpMutableVertexMesh->GetElement(vertex_elem_index);

        // Iterate over nodes owned by this VertexElement
        unsigned num_nodes_in_vertex_element = p_vertex_element->GetNumNodes();
        for (unsigned local_index=0; local_index<num_nodes_in_vertex_element; local_index++)
        {
            unsigned node_0_index = p_vertex_element->GetNodeGlobalIndex(local_index);
            unsigned node_1_index = p_vertex_element->GetNodeGlobalIndex((local_index+1)%num_nodes_in_vertex_element);
            unsigned node_2_index = num_vertex_nodes + vertex_elem_index;

            (*p_elem_file) << tetrahedral_elem_index++ << "\t" << node_0_index << "\t" << node_1_index << "\t" << node_2_index << std::endl;

            // Add edges to the set if they are not already present
            std::pair<unsigned, unsigned> edge_0 = this->CreateOrderedPair(node_0_index, node_1_index);
            std::pair<unsigned, unsigned> edge_1 = this->CreateOrderedPair(node_1_index, node_2_index);
            std::pair<unsigned, unsigned> edge_2 = this->CreateOrderedPair(node_2_index, node_0_index);

            tetrahedral_edges.insert(edge_0);
            tetrahedral_edges.insert(edge_1);
            tetrahedral_edges.insert(edge_2);
        }
    }
    p_elem_file->close();

    // Write edge file
    out_stream p_edge_file = output_file_handler.OpenOutputFile(mesh_file_name+".edge");
    (*p_edge_file) << std::scientific;
    (*p_edge_file) << tetrahedral_edges.size() << "\t1" << std::endl;

    unsigned edge_index = 0;
    for (std::set<std::pair<unsigned, unsigned> >::iterator edge_iter = tetrahedral_edges.begin();
         edge_iter != tetrahedral_edges.end();
         ++edge_iter)
    {
        std::pair<unsigned, unsigned> this_edge = *edge_iter;

        // To be a boundary edge both nodes need to be boundary nodes.
        bool is_boundary_edge = false;
        if (this_edge.first  < mpMutableVertexMesh->GetNumNodes() &&
            this_edge.second  < mpMutableVertexMesh->GetNumNodes())
        {
            is_boundary_edge = (mpMutableVertexMesh->GetNode(this_edge.first)->IsBoundaryNode() &&
                                mpMutableVertexMesh->GetNode(this_edge.second)->IsBoundaryNode() );
        }
        unsigned is_boundary_edge_unsigned = is_boundary_edge ? 1 : 0;

        (*p_edge_file) << edge_index++ << "\t" << this_edge.first << "\t" << this_edge.second << "\t" << is_boundary_edge_unsigned << std::endl;
    }
    p_edge_file->close();

    // Having written the mesh to file, now construct it using TrianglesMeshReader
    TetrahedralMesh<DIM, DIM>* p_mesh = new TetrahedralMesh<DIM, DIM>;
    // Nested scope so reader is destroyed before we remove the temporary files.
    {
        TrianglesMeshReader<DIM, DIM> mesh_reader(output_dir + mesh_file_name);
        p_mesh->ConstructFromMeshReader(mesh_reader);
    }

    // Delete the temporary files
    output_file_handler.FindFile("").Remove();

    // The original files have been deleted, it is better if the mesh object forgets about them
    p_mesh->SetMeshHasChangedSinceLoading();

    return p_mesh;
}