CardiacSimulation.hpp

00001 /*
00002 
00003 Copyright (C) University of Oxford, 2005-2010
00004 
00005 University of Oxford means the Chancellor, Masters and Scholars of the
00006 University of Oxford, having an administrative office at Wellington
00007 Square, Oxford OX1 2JD, UK.
00008 
00009 This file is part of Chaste.
00010 
00011 Chaste is free software: you can redistribute it and/or modify it
00012 under the terms of the GNU Lesser General Public License as published
00013 by the Free Software Foundation, either version 2.1 of the License, or
00014 (at your option) any later version.
00015 
00016 Chaste is distributed in the hope that it will be useful, but WITHOUT
00017 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00018 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
00019 License for more details. The offer of Chaste under the terms of the
00020 License is subject to the License being interpreted in accordance with
00021 English Law and subject to any action against the University of Oxford
00022 being under the jurisdiction of the English Courts.
00023 
00024 You should have received a copy of the GNU Lesser General Public License
00025 along with Chaste. If not, see <http://www.gnu.org/licenses/>.
00026 
00027 */
00028 
00029 #ifndef CARDIACSIMULATION_HPP_
00030 #define CARDIACSIMULATION_HPP_
00031 
00032 // Must go first
00033 #include "CardiacSimulationArchiver.hpp"
00034 // Note that since we include this header, we can't (easily) create a .cpp file for this class.
00035 // Doing so would break the build with chaste_libs=0 on linking, since it would mean that no test
00036 // (or executable) could include CardiacSimulation.hpp, since Boost archiving GUIDs would then be
00037 // defined in two object files (CardiacSimulation.o and the test runner .o).  You get errors such
00038 // as: multiple definition of `boost::archive::detail::guid_initializer<HeartConfig>::instance'.
00039 
00040 #include <vector>
00041 #include <ctime>
00042 #include <memory>
00043 
00044 #include "UblasIncludes.hpp"
00045 
00046 #include "MonodomainProblem.hpp"
00047 #include "BidomainProblem.hpp"
00048 #include "PetscTools.hpp"
00049 #include "TimeStepper.hpp"
00050 #include "Exception.hpp"
00051 
00052 #include "HeartConfig.hpp"
00053 #include "HeartConfigRelatedCellFactory.hpp"
00054 
00055 #include "TetrahedralMesh.hpp"
00056 #include "NonCachedTetrahedralMesh.hpp"
00057 #include "ChastePoint.hpp"
00058 #include "ChasteCuboid.hpp"
00059 #include "MeshalyzerMeshWriter.hpp"
00060 #include "TrianglesMeshWriter.hpp"
00061 
00062 #include "OrthotropicConductivityTensors.hpp"
00063 
00064 #include "Hdf5ToMeshalyzerConverter.hpp"
00065 #include "PostProcessingWriter.hpp"
00066 
00067 #include "OutputDirectoryFifoQueue.hpp"
00068 
00079 class CardiacSimulation
00080 {
00081 private:
00087     void ReadParametersFromFile(std::string parameterFileName);
00088 
00093     template<class Problem, unsigned SPACE_DIM>
00094     void CreateAndRun()
00095     {
00096         std::auto_ptr<Problem> p_problem;
00097 
00098         if (HeartConfig::Instance()->IsSimulationDefined())
00099         {
00100             HeartConfigRelatedCellFactory<SPACE_DIM> cell_factory;
00101             p_problem.reset(new Problem(&cell_factory));
00102 
00103             p_problem->Initialise();
00104         }
00105         else // (HeartConfig::Instance()->IsSimulationResumed())
00106         {
00107             p_problem.reset(CardiacSimulationArchiver<Problem>::Load(HeartConfig::Instance()->GetArchivedSimulationDir()));
00108         }
00109 
00110         if (HeartConfig::Instance()->GetCheckpointSimulation())
00111         {
00112             // Create the checkpoints directory and set up a fifo queue of subdirectory names
00113             OutputDirectoryFifoQueue directory_queue(HeartConfig::Instance()->GetOutputDirectory() + "_checkpoints/",
00114                                                      HeartConfig::Instance()->GetMaxCheckpointsOnDisk());
00115 
00116             TimeStepper checkpoint_stepper(p_problem->GetCurrentTime(), HeartConfig::Instance()->GetSimulationDuration(), HeartConfig::Instance()->GetCheckpointTimestep());
00117             while ( !checkpoint_stepper.IsTimeAtEnd() )
00118             {
00119                 // Solve checkpoint timestep
00120                 HeartConfig::Instance()->SetSimulationDuration(checkpoint_stepper.GetNextTime());
00121                 p_problem->Solve();
00122 
00123                 // Create directory that will contain archive and partial results for this checkpoint timestep.
00124                 std::stringstream checkpoint_id;
00125                 checkpoint_id << HeartConfig::Instance()->GetSimulationDuration() << "ms/";
00126                 std::string checkpoint_dir_basename = directory_queue.CreateNextDir(checkpoint_id.str());
00127 
00128                 // Archive simulation (in a subdirectory of checkpoint_dir_basename).
00129                 std::stringstream archive_foldername;
00130                 archive_foldername << HeartConfig::Instance()->GetOutputDirectory() << "_" << HeartConfig::Instance()->GetSimulationDuration() << "ms";
00131                 CardiacSimulationArchiver<Problem>::Save(*(p_problem.get()), checkpoint_dir_basename + archive_foldername.str(), false);
00132 
00133                 // Put a copy of the partial results aside (in a subdirectory of checkpoint_dir_basename).
00134                 OutputFileHandler checkpoint_dir_basename_handler(checkpoint_dir_basename, false);
00135                 OutputFileHandler partial_output_dir_handler(HeartConfig::Instance()->GetOutputDirectory(), false);
00136                 if (PetscTools::AmMaster())
00137                 {
00138                     EXPECT0(system, "cp -r " + partial_output_dir_handler.GetOutputDirectoryFullPath() + " " + checkpoint_dir_basename_handler.GetOutputDirectoryFullPath());
00139                 }
00140                 
00141                 // Create an XML file to help in resuming
00142                 CreateResumeXmlFile(checkpoint_dir_basename, archive_foldername.str());
00143 
00144                 // Advance time stepper
00145                 checkpoint_stepper.AdvanceOneTimeStep();
00146             }
00147         }
00148         else
00149         {
00150             p_problem->Solve();
00151         }
00152     }
00153 
00159     void Run();
00160     
00170     void CreateResumeXmlFile(const std::string& rOutputDirectory, const std::string& rArchiveDirectory);
00171 
00176     std::string BoolToString(bool yesNo);
00177 public:
00185     CardiacSimulation(std::string parameterFileName);
00186 };
00187 
00188 //
00189 // Implementation must remain in this file (see comment by #include "CardiacSimulationArchiver.hpp").
00190 //
00191 
00192 std::string CardiacSimulation::BoolToString(bool yesNo)
00193 {
00194     std::string result;
00195     if (yesNo)
00196     {
00197         result = "yes";
00198     }
00199     else
00200     {
00201         result = "no";
00202     }
00203     return result;
00204 }
00205 
00206 void CardiacSimulation::CreateResumeXmlFile(const std::string& rOutputDirectory, const std::string& rArchiveDirectory)
00207 {
00208     OutputFileHandler handler(rOutputDirectory, false);
00209     out_stream p_file = handler.OpenOutputFile("ResumeParameters.xml");
00210     (*p_file) << "<?xml version='1.0' encoding='UTF-8'?>" << std::endl;
00211     (*p_file) << "<ChasteParameters xmlns='https://chaste.comlab.ox.ac.uk/nss/parameters/2_0'>" << std::endl;
00212     (*p_file) << std::endl;
00213     (*p_file) << "    <ResumeSimulation>" << std::endl;
00214     (*p_file) << "        <ArchiveDirectory>" << rArchiveDirectory << "</ArchiveDirectory>" << std::endl;
00215     (*p_file) << "        <SpaceDimension>" << HeartConfig::Instance()->GetSpaceDimension() << "</SpaceDimension>" << std::endl;
00216     (*p_file) << "        <SimulationDuration unit='ms'>0.0</SimulationDuration>" << std::endl;
00217     (*p_file) << "        <Domain>" << HeartConfig::Instance()->GetDomain() << "</Domain>" << std::endl;
00218     (*p_file) << "        <CheckpointSimulation timestep='" << HeartConfig::Instance()->GetCheckpointTimestep()
00219               << "' unit='ms' max_checkpoints_on_disk='" << HeartConfig::Instance()->GetMaxCheckpointsOnDisk()
00220               << "'/> <!-- This is optional; if not given, the loaded simulation will NOT itself be checkpointed -->" << std::endl;
00221     (*p_file) << "        <OutputVisualizer meshalyzer='" << BoolToString(HeartConfig::Instance()->GetVisualizeWithMeshalyzer())
00222               << "' vtk='" << BoolToString(HeartConfig::Instance()->GetVisualizeWithVtk())
00223               << "' cmgui='" << BoolToString(HeartConfig::Instance()->GetVisualizeWithCmgui()) << "'/>" << std::endl;
00224     (*p_file) << "    </ResumeSimulation>" << std::endl;
00225     (*p_file) << std::endl; 
00226     (*p_file) << "    <!-- These elements must exist, but their contents are ignored -->" << std::endl;
00227     (*p_file) << "    <Physiological/>" << std::endl;
00228     (*p_file) << "    <Numerical/>" << std::endl;
00229     (*p_file) << "</ChasteParameters>" << std::endl;
00230     p_file->close();
00231 }
00232 
00233 CardiacSimulation::CardiacSimulation(std::string parameterFileName)
00234 {
00235     // If we have been passed an XML file then parse the XML file, otherwise throw
00236     if (parameterFileName == "")
00237     {
00238         EXCEPTION("No XML file name given");
00239     }
00240     ReadParametersFromFile(parameterFileName);
00241     Run();
00242     HeartEventHandler::Headings();
00243     HeartEventHandler::Report();
00244 }
00245 
00246 
00247 void CardiacSimulation::ReadParametersFromFile(std::string parameterFileName)
00248 {
00249     // Ensure the singleton is in a clean state
00250     HeartConfig::Reset();
00251     try
00252     {
00253         // Try the hardcoded schema location first
00254         HeartConfig::Instance()->SetUseFixedSchemaLocation(true);
00255         HeartConfig::Instance()->SetParametersFile(parameterFileName);
00256     }
00257     catch (Exception& e)
00258     {
00259         if (e.CheckShortMessageContains("Missing file parsing configuration") == "")
00260         {
00261             // Try using the schema location given in the XML
00262             HeartConfig::Reset();
00263             HeartConfig::Instance()->SetUseFixedSchemaLocation(false);
00264             HeartConfig::Instance()->SetParametersFile(parameterFileName);
00265         }
00266         else
00267         {
00268             throw e;
00269         }
00270     }
00271 }
00272 
00273 
00274 void CardiacSimulation::Run()
00275 {
00276     switch (HeartConfig::Instance()->GetDomain())
00277     {
00278         case cp::domain_type::Mono :
00279         {
00280             switch (HeartConfig::Instance()->GetSpaceDimension())
00281             {
00282                 case 3:
00283                 {
00284                     CreateAndRun<MonodomainProblem<3>,3>();
00285                     break;
00286                 }
00287 
00288                 case 2:
00289                 {
00290                     CreateAndRun<MonodomainProblem<2>,2>();
00291                     break;
00292                 }
00293 
00294                 case 1:
00295                 {
00296                     CreateAndRun<MonodomainProblem<1>,1>();
00297                     break;
00298                 }
00299                 default :
00300                     EXCEPTION("Monodomain space dimension not supported: should be 1, 2 or 3");
00301             }
00302             break;
00303         }
00304 
00305         case cp::domain_type::Bi :
00306         {
00307             switch (HeartConfig::Instance()->GetSpaceDimension())
00308             {
00309                 case 3:
00310                 {
00311                     CreateAndRun<BidomainProblem<3>,3>();
00312                     break;
00313                 }
00314                 case 2:
00315                 {
00316                     CreateAndRun<BidomainProblem<2>,2>();
00317                     break;
00318                 }
00319                 case 1:
00320                 {
00321                     CreateAndRun<BidomainProblem<1>,1>();
00322                     break;
00323                 }
00324                 default :
00325                 {
00326                     EXCEPTION("Bidomain space dimension not supported: should be 1, 2 or 3");
00327                 }
00328             }
00329             break;
00330         }
00331         default :
00332         {
00333             // If the domain is not set correctly then the XML parser will have picked it up before now!
00334             NEVER_REACHED;
00335         }
00336     }
00337 }
00338 
00339 
00340 
00341 #endif /*CARDIACSIMULATION_HPP_*/

Generated by  doxygen 1.6.2