00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037 #ifndef ABSTRACTCARDIACPROBLEM_HPP_
00038 #define ABSTRACTCARDIACPROBLEM_HPP_
00039
00040
00041
00042 #include <string>
00043 #include <vector>
00044 #include <cassert>
00045 #include <climits>
00046 #include <boost/shared_ptr.hpp>
00047
00048 #include "ChasteSerialization.hpp"
00049 #include <boost/serialization/vector.hpp>
00050 #include <boost/serialization/string.hpp>
00051 #include <boost/serialization/split_member.hpp>
00052 #include <boost/serialization/shared_ptr.hpp>
00053 #include "ClassIsAbstract.hpp"
00054 #include "ChasteSerializationVersion.hpp"
00055
00056 #include "AbstractTetrahedralMesh.hpp"
00057 #include "AbstractCardiacCell.hpp"
00058 #include "AbstractCardiacCellFactory.hpp"
00059 #include "AbstractCardiacTissue.hpp"
00060 #include "AbstractDynamicLinearPdeSolver.hpp"
00061 #include "BoundaryConditionsContainer.hpp"
00062 #include "DistributedVectorFactory.hpp"
00063 #include "Hdf5DataReader.hpp"
00064 #include "Hdf5DataWriter.hpp"
00065 #include "Warnings.hpp"
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084 #include "DistributedTetrahedralMesh.hpp"
00085 #include "TetrahedralMesh.hpp"
00086 #include "MonodomainTissue.hpp"
00087 #include "BidomainTissue.hpp"
00088
00092 class AbstractUntemplatedCardiacProblem : private boost::noncopyable
00093 {
00094 public:
00096 virtual ~AbstractUntemplatedCardiacProblem()
00097 {}
00098 };
00099
00114 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
00115 class AbstractCardiacProblem : public AbstractUntemplatedCardiacProblem
00116 {
00117 friend class TestBidomainWithBath;
00118 friend class TestCardiacSimulationArchiver;
00119
00121 typedef typename boost::shared_ptr<BoundaryConditionsContainer<ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM> >
00122 BccType;
00123
00124 private:
00126 friend class boost::serialization::access;
00127
00134 template<class Archive>
00135 void save(Archive & archive, const unsigned int version) const
00136 {
00137 if (version >= 1)
00138 {
00139 const unsigned element_dim=ELEMENT_DIM;
00140 archive & element_dim;
00141 const unsigned space_dim=SPACE_DIM;
00142 archive & space_dim;
00143 const unsigned problem_dim=PROBLEM_DIM;
00144 archive & problem_dim;
00145 }
00146 archive & mMeshFilename;
00147 archive & mpMesh;
00148
00149
00150
00151 assert(version >= 2);
00152
00153
00154
00155
00156
00157 archive & mWriteInfo;
00158 archive & mPrintOutput;
00159 archive & mNodesToOutput;
00160
00161
00162
00163
00164
00165 archive & mpCardiacTissue;
00166
00167 bool has_solution = (mSolution != NULL);
00168 archive & has_solution;
00169 if (has_solution)
00170 {
00172 Hdf5DataWriter writer(*mpMesh->GetDistributedVectorFactory(), ArchiveLocationInfo::GetArchiveRelativePath(), "AbstractCardiacProblem_mSolution", false);
00173 writer.DefineFixedDimension(mpMesh->GetDistributedVectorFactory()->GetProblemSize());
00174 writer.DefineUnlimitedDimension("Time", "msec", 1);
00175
00176 int vm_col = writer.DefineVariable("Vm","mV");
00177
00178 if (PROBLEM_DIM==1)
00179 {
00180 writer.EndDefineMode();
00181 writer.PutUnlimitedVariable(0.0);
00182 writer.PutVector(vm_col, mSolution);
00183 }
00184
00185 if (PROBLEM_DIM==2)
00186 {
00187 int phie_col = writer.DefineVariable("Phie","mV");
00188 std::vector<int> variable_ids;
00189 variable_ids.push_back(vm_col);
00190 variable_ids.push_back(phie_col);
00191 writer.EndDefineMode();
00192 writer.PutUnlimitedVariable(0.0);
00193 writer.PutStripedVector(variable_ids, mSolution);
00194 }
00195
00196 writer.Close();
00197
00198 }
00199 archive & mCurrentTime;
00200
00201
00202 SaveBoundaryConditions(archive, mpMesh, mpBoundaryConditionsContainer);
00203 SaveBoundaryConditions(archive, mpMesh, mpDefaultBoundaryConditionsContainer);
00204 }
00205
00212 template<class Archive>
00213 void load(Archive & archive, const unsigned int version)
00214 {
00215 if (version >= 1)
00216 {
00217 unsigned element_dim;
00218 unsigned space_dim;
00219 unsigned problem_dim;
00220 archive & element_dim;
00221 archive & space_dim;
00222 archive & problem_dim;
00223 if ( (element_dim != ELEMENT_DIM) ||(space_dim != SPACE_DIM) ||(problem_dim != PROBLEM_DIM) )
00224 {
00225
00226
00227
00228
00229
00230
00231 EXCEPTION("Failed to load from checkpoint because the dimensions of the archive do not match the object it's being read into.");
00232 }
00233 }
00234 archive & mMeshFilename;
00235 archive & mpMesh;
00236 assert(mpMesh != NULL);
00237
00238
00239 if (version < 2)
00240 {
00241 bool use_matrix_based_assembly;
00242 archive & use_matrix_based_assembly;
00243 }
00244
00245 archive & mWriteInfo;
00246 archive & mPrintOutput;
00247 archive & mNodesToOutput;
00248
00249
00250
00251
00252
00253 archive & mpCardiacTissue;
00254
00255 bool has_solution;
00256 archive & has_solution;
00257 if ((has_solution) && PROBLEM_DIM < 3)
00258 {
00261 mSolution = mpMesh->GetDistributedVectorFactory()->CreateVec(PROBLEM_DIM);
00262 DistributedVector mSolution_distri = mpMesh->GetDistributedVectorFactory()->CreateDistributedVector(mSolution);
00263
00264 Vec vm = mpMesh->GetDistributedVectorFactory()->CreateVec();
00265 Vec phie = mpMesh->GetDistributedVectorFactory()->CreateVec();
00266
00267 std::string archive_dir = ArchiveLocationInfo::GetArchiveRelativePath();
00268 Hdf5DataReader reader(archive_dir, "AbstractCardiacProblem_mSolution", !FileFinder::IsAbsolutePath(archive_dir));
00269 reader.GetVariableOverNodes(vm, "Vm", 0);
00270
00271 if (PROBLEM_DIM==1)
00272 {
00273
00274
00275 DistributedVector vm_distri = mpMesh->GetDistributedVectorFactory()->CreateDistributedVector(vm);
00276
00277 DistributedVector::Stripe mSolution_vm(mSolution_distri,0);
00278
00279 for (DistributedVector::Iterator index = mSolution_distri.Begin();
00280 index != mSolution_distri.End();
00281 ++index)
00282 {
00283 mSolution_vm[index] = vm_distri[index];
00284 }
00285 }
00286
00287 if (PROBLEM_DIM==2)
00288 {
00289 reader.GetVariableOverNodes(phie, "Phie", 0);
00290
00291
00292 DistributedVector vm_distri = mpMesh->GetDistributedVectorFactory()->CreateDistributedVector(vm);
00293 DistributedVector phie_distri = mpMesh->GetDistributedVectorFactory()->CreateDistributedVector(phie);
00294
00295 DistributedVector::Stripe mSolution_vm(mSolution_distri,0);
00296 DistributedVector::Stripe mSolution_phie(mSolution_distri,1);
00297
00298 for (DistributedVector::Iterator index = mSolution_distri.Begin();
00299 index != mSolution_distri.End();
00300 ++index)
00301 {
00302 mSolution_vm[index] = vm_distri[index];
00303 mSolution_phie[index] = phie_distri[index];
00304 }
00305 }
00306
00307 mSolution_distri.Restore();
00308
00309 PetscTools::Destroy(vm);
00310 PetscTools::Destroy(phie);
00311
00312 }
00313 archive & mCurrentTime;
00314
00315
00316 mpBoundaryConditionsContainer = LoadBoundaryConditions(archive, mpMesh);
00317 mpDefaultBoundaryConditionsContainer = LoadBoundaryConditions(archive, mpMesh);
00318 }
00319
00320 BOOST_SERIALIZATION_SPLIT_MEMBER()
00321
00322
00329 template<class Archive>
00330 void SaveBoundaryConditions(Archive & archive,
00331 AbstractTetrahedralMesh<ELEMENT_DIM,SPACE_DIM>* pMesh,
00332 BccType pBcc) const
00333 {
00334 (*ProcessSpecificArchive<Archive>::Get()) & pBcc;
00335 }
00336
00344 template<class Archive>
00345 BccType LoadBoundaryConditions(
00346 Archive & archive,
00347 AbstractTetrahedralMesh<ELEMENT_DIM,SPACE_DIM>* pMesh)
00348 {
00349
00350 BccType p_bcc;
00351 (*ProcessSpecificArchive<Archive>::Get()) & p_bcc;
00352
00353
00354 if (p_bcc)
00355 {
00356 p_bcc->LoadFromArchive(*ProcessSpecificArchive<Archive>::Get(), pMesh);
00357 }
00358
00359 return p_bcc;
00360 }
00361
00362 protected:
00365 std::string mMeshFilename;
00366
00368 bool mAllocatedMemoryForMesh;
00370 bool mWriteInfo;
00372 bool mPrintOutput;
00373
00375 std::vector<unsigned> mNodesToOutput;
00376
00378 unsigned mVoltageColumnId;
00380 std::vector<unsigned> mExtraVariablesId;
00382 unsigned mTimeColumnId;
00384 unsigned mNodeColumnId;
00385
00387 AbstractCardiacTissue<ELEMENT_DIM,SPACE_DIM>* mpCardiacTissue;
00388
00390 BccType mpBoundaryConditionsContainer;
00392 BccType mpDefaultBoundaryConditionsContainer;
00394 AbstractDynamicLinearPdeSolver<ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM>* mpSolver;
00396 AbstractCardiacCellFactory<ELEMENT_DIM,SPACE_DIM>* mpCellFactory;
00398 AbstractTetrahedralMesh<ELEMENT_DIM,SPACE_DIM>* mpMesh;
00399
00402 Vec mSolution;
00403
00411 double mCurrentTime;
00412
00414 AbstractTimeAdaptivityController* mpTimeAdaptivityController;
00415
00416
00417
00424 virtual AbstractCardiacTissue<ELEMENT_DIM,SPACE_DIM>* CreateCardiacTissue() =0;
00425
00432 virtual AbstractDynamicLinearPdeSolver<ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM>* CreateSolver() =0;
00433
00441 virtual void CreateMeshFromHeartConfig();
00442
00446 template<unsigned DIM, unsigned ELEC_PROB_DIM>
00447 friend class CardiacElectroMechanicsProblem;
00448
00452 Hdf5DataWriter* mpWriter;
00453
00454 public:
00460 AbstractCardiacProblem(AbstractCardiacCellFactory<ELEMENT_DIM,SPACE_DIM>* pCellFactory);
00461
00465 AbstractCardiacProblem();
00466
00470 virtual ~AbstractCardiacProblem();
00471
00479 void Initialise();
00480
00486 void SetNodesPerProcessorFilename(const std::string& rFilename);
00487
00492 void SetBoundaryConditionsContainer(BccType pBcc);
00493
00501 virtual void PreSolveChecks();
00502
00516 virtual Vec CreateInitialCondition();
00517
00523 void SetMesh(AbstractTetrahedralMesh<ELEMENT_DIM,SPACE_DIM>* pMesh);
00524
00530 void PrintOutput(bool rPrintOutput);
00531
00537 void SetWriteInfo(bool writeInfo = true);
00538
00549 Vec GetSolution();
00550
00556 DistributedVector GetSolutionDistributedVector();
00557
00561 double GetCurrentTime();
00562
00566 AbstractTetrahedralMesh<ELEMENT_DIM,SPACE_DIM> & rGetMesh();
00567
00571 AbstractCardiacTissue<ELEMENT_DIM,SPACE_DIM>* GetTissue();
00572
00582 void Solve();
00583
00591 void CloseFilesAndPostProcess();
00592
00600 virtual void WriteInfo(double time)=0;
00601
00606 virtual void DefineWriterColumns(bool extending);
00607
00612 void DefineExtraVariablesWriterColumns(bool extending);
00613
00620 virtual void WriteOneStep(double time, Vec voltageVec) = 0;
00621
00625 void WriteExtraVariablesOneStep();
00626
00637 bool InitialiseWriter();
00638
00648 void SetOutputNodes(std::vector<unsigned> & rNodesToOutput);
00649
00653 Hdf5DataReader GetDataReader();
00654
00662 virtual void AtBeginningOfTimestep(double time)
00663 {}
00664
00672 virtual void OnEndOfTimestep(double time)
00673 {}
00674
00682 virtual void SetUpAdditionalStoppingTimes(std::vector<double>& rAdditionalStoppingTimes)
00683 {}
00684
00685
00686
00688
00689
00695 void SetUseTimeAdaptivityController(bool useAdaptivity,
00696 AbstractTimeAdaptivityController* pController = NULL);
00697
00718 template<class Archive>
00719 void LoadExtraArchive(Archive & archive, unsigned version);
00720
00724 virtual bool GetHasBath();
00725
00730 virtual void SetElectrodes();
00731 };
00732
00733 TEMPLATED_CLASS_IS_ABSTRACT_3_UNSIGNED(AbstractCardiacProblem)
00734
00735
00736 template<unsigned DIM>
00737 class BidomainProblem;
00738
00739 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
00740 template<class Archive>
00741 void AbstractCardiacProblem<ELEMENT_DIM,SPACE_DIM,PROBLEM_DIM>::LoadExtraArchive(Archive & archive, unsigned version)
00742 {
00743
00744 DistributedVectorFactory* p_mesh_factory;
00745 archive >> p_mesh_factory;
00746
00747
00748 DistributedVectorFactory* p_original_factory = p_mesh_factory->GetOriginalFactory();
00749 unsigned orig_num_procs = 1;
00750 if (p_original_factory)
00751 {
00752 orig_num_procs = p_original_factory->GetNumProcs();
00753 }
00754
00755
00756 mpCardiacTissue->LoadCardiacCells(archive, version);
00757
00758 {
00759 DistributedVectorFactory* p_pde_factory;
00760 archive >> p_pde_factory;
00761 assert(p_pde_factory == p_mesh_factory);
00762 }
00763
00764 delete p_mesh_factory;
00765
00766
00767 BccType p_bcc;
00768 archive >> p_bcc;
00769 if (p_bcc)
00770 {
00771 if (!mpBoundaryConditionsContainer)
00772 {
00773 mpBoundaryConditionsContainer = p_bcc;
00774 mpBoundaryConditionsContainer->LoadFromArchive(archive, mpMesh);
00775 }
00776 else
00777 {
00778
00779
00780 #define COVERAGE_IGNORE
00781 if(!dynamic_cast<DistributedTetrahedralMesh<ELEMENT_DIM,SPACE_DIM>*>(mpMesh) && orig_num_procs > 1)
00782 {
00783
00784
00785 WARNING("Loading from a parallel archive which used a non-distributed mesh. This scenario should work but is not fully tested.");
00786 }
00787 #undef COVERAGE_IGNORE
00788 mpBoundaryConditionsContainer->MergeFromArchive(archive, mpMesh);
00789 }
00790 }
00791 BccType p_default_bcc;
00792 archive >> p_default_bcc;
00793 if (p_default_bcc)
00794 {
00795
00796 assert(p_bcc == p_default_bcc);
00797 }
00798
00799
00800 BidomainProblem<ELEMENT_DIM>* p_bidomain_problem = dynamic_cast<BidomainProblem<ELEMENT_DIM>*>(this);
00801 if (p_bidomain_problem)
00802 {
00803 assert(ELEMENT_DIM == SPACE_DIM);
00804 p_bidomain_problem->LoadExtraArchiveForBidomain(archive, version);
00805 }
00806 }
00807
00808 namespace boost {
00809 namespace serialization {
00816 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
00817 struct version<AbstractCardiacProblem<ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM> >
00818 {
00820 CHASTE_VERSION_CONTENT(2);
00821 };
00822 }
00823 }
00824 #endif