CardiacSimulationArchiver.cpp

00001 /*
00002 
00003 Copyright (C) University of Oxford, 2005-2011
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 #include <fstream>
00030 
00031 // Must be included before any other serialization headers
00032 #include "CheckpointArchiveTypes.hpp"
00033 #include "CardiacSimulationArchiver.hpp"
00034 
00035 #include "Exception.hpp"
00036 #include "ArchiveOpener.hpp"
00037 #include "OutputFileHandler.hpp"
00038 #include "ArchiveLocationInfo.hpp"
00039 #include "DistributedVectorFactory.hpp"
00040 #include "PetscTools.hpp"
00041 #include "FileFinder.hpp"
00042 
00043 
00044 template<class PROBLEM_CLASS>
00045 void CardiacSimulationArchiver<PROBLEM_CLASS>::Save(PROBLEM_CLASS& rSimulationToArchive,
00046                                                     const std::string& rDirectory,
00047                                                     bool clearDirectory)
00048 {
00049     // Clear directory if requested (and make sure it exists)
00050     OutputFileHandler handler(rDirectory, clearDirectory);
00051 
00052     // Nest the archive writing, so the ArchiveOpener goes out of scope before
00053     // the method ends.
00054     {
00055         // Open the archive files
00056         FileFinder dir(rDirectory, RelativeTo::ChasteTestOutput);
00057         ArchiveOpener<boost::archive::text_oarchive, std::ofstream> archive_opener(dir, "archive.arch");
00058         boost::archive::text_oarchive* p_main_archive = archive_opener.GetCommonArchive();
00059 
00060         // And save
00061         PROBLEM_CLASS* const p_simulation_to_archive = &rSimulationToArchive;
00062         (*p_main_archive) & p_simulation_to_archive;
00063     }
00064 
00065     // Write the info file
00066     if (PetscTools::AmMaster())
00067     {
00068         std::string info_path = handler.GetOutputDirectoryFullPath() + "archive.info";
00069         std::ofstream info_file(info_path.c_str());
00070         if (!info_file.is_open())
00071         {
00072             // Avoid deadlock...
00073             PetscTools::ReplicateBool(true);
00074             EXCEPTION("Unable to open archive information file: " + info_path);
00075         }
00076         PetscTools::ReplicateBool(false);
00077         unsigned archive_version = 0; 
00078         info_file << PetscTools::GetNumProcs() << " " << archive_version;
00079     }
00080     else
00081     {
00082         bool master_threw = PetscTools::ReplicateBool(false);
00083         if (master_threw)
00084         {
00085             EXCEPTION("Unable to open archive information file");
00086         }
00087     }
00088     // Make sure everything is written before any process continues.
00089     PetscTools::Barrier("CardiacSimulationArchiver::Save");
00090 }
00091 
00092 template<class PROBLEM_CLASS>
00093 PROBLEM_CLASS* CardiacSimulationArchiver<PROBLEM_CLASS>::Load(const std::string& rDirectory)
00094 {
00095     FileFinder directory(rDirectory, RelativeTo::ChasteTestOutput);
00096     return CardiacSimulationArchiver<PROBLEM_CLASS>::Migrate(directory);
00097 }
00098 
00099 template<class PROBLEM_CLASS>
00100 PROBLEM_CLASS* CardiacSimulationArchiver<PROBLEM_CLASS>::Load(const FileFinder& rDirectory)
00101 {
00102     return CardiacSimulationArchiver<PROBLEM_CLASS>::Migrate(rDirectory);
00103 }
00104 
00105 
00106 template<class PROBLEM_CLASS>
00107 PROBLEM_CLASS* CardiacSimulationArchiver<PROBLEM_CLASS>::Migrate(const FileFinder& rDirectory)
00108 {
00109     // Check the directory exists
00110     std::string dir_path = rDirectory.GetAbsolutePath();
00111     if (!rDirectory.IsDir() || !rDirectory.Exists())
00112     {
00113         EXCEPTION("Checkpoint directory does not exist: " + dir_path);
00114     }
00115     assert(*(dir_path.end()-1) == '/'); // Paranoia
00116     // Load the info file
00117     std::string info_path = dir_path + "archive.info";
00118     std::ifstream info_file(info_path.c_str());
00119     if (!info_file.is_open())
00120     {
00121         EXCEPTION("Unable to open archive information file: " + info_path);
00122     }
00123     unsigned num_procs, archive_version;
00124     info_file >> num_procs >> archive_version;
00125 
00126     PROBLEM_CLASS *p_unarchived_simulation;
00127 
00128     // Avoid the DistributedVectorFactory throwing a 'wrong number of processes' exception when loading,
00129     // and make it get the original DistributedVectorFactory from the archive so we can compare against
00130     // num_procs.
00131     DistributedVectorFactory::SetCheckNumberOfProcessesOnLoad(false);
00132     // Put what follows in a try-catch to make sure we reset this
00133     try
00134     {
00135         // Figure out which process-specific archive to load first.  If we're loading on the same number of
00136         // processes, we must load our own one, or the mesh gets confused.  Otherwise, start with 0 to make
00137         // sure it exists.
00138         unsigned initial_archive = num_procs == PetscTools::GetNumProcs() ? PetscTools::GetMyRank() : 0u;
00139 
00140         // Load the master and initial process-specific archive files.
00141         // This will also set up ArchiveLocationInfo for us.
00142         ArchiveOpener<boost::archive::text_iarchive, std::ifstream> archive_opener(rDirectory, "archive.arch", initial_archive);
00143         boost::archive::text_iarchive* p_main_archive = archive_opener.GetCommonArchive();
00144         (*p_main_archive) >> p_unarchived_simulation;
00145 
00146         // Work out how many more process-specific files to load
00147         DistributedVectorFactory* p_factory = p_unarchived_simulation->rGetMesh().GetDistributedVectorFactory();
00148         assert(p_factory != NULL);
00149         unsigned original_num_procs = p_factory->GetOriginalFactory()->GetNumProcs();
00150         assert(original_num_procs == num_procs); // Paranoia
00151 
00152         // Merge in the extra data
00153         for (unsigned archive_num=0; archive_num<original_num_procs; archive_num++)
00154         {
00155             if (archive_num != initial_archive)
00156             {
00157                 std::string archive_path = ArchiveLocationInfo::GetProcessUniqueFilePath("archive.arch", archive_num);
00158                 std::ifstream ifs(archive_path.c_str());
00159                 boost::archive::text_iarchive archive(ifs);
00160                 p_unarchived_simulation->LoadExtraArchive(archive, archive_version);
00161             }
00162         }
00163     }
00164     catch (Exception &e)
00165     {
00166         DistributedVectorFactory::SetCheckNumberOfProcessesOnLoad(true);
00167         throw e;
00168     }
00169 
00170     // Done.
00171     DistributedVectorFactory::SetCheckNumberOfProcessesOnLoad(true);
00172     return p_unarchived_simulation;
00173 }
00174 
00175 //
00176 // Explicit instantiation
00177 //
00178 
00179 template class CardiacSimulationArchiver<MonodomainProblem<1> >;
00180 template class CardiacSimulationArchiver<MonodomainProblem<2> >;
00181 template class CardiacSimulationArchiver<MonodomainProblem<3> >;
00182 
00183 template class CardiacSimulationArchiver<BidomainProblem<1> >;
00184 template class CardiacSimulationArchiver<BidomainProblem<2> >;
00185 template class CardiacSimulationArchiver<BidomainProblem<3> >;
00186 
00187 template class CardiacSimulationArchiver<BidomainWithBathProblem<1> >;
00188 template class CardiacSimulationArchiver<BidomainWithBathProblem<2> >;
00189 template class CardiacSimulationArchiver<BidomainWithBathProblem<3> >;

Generated on Tue May 31 14:31:41 2011 for Chaste by  doxygen 1.5.5