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 #ifndef ABSTRACTCARDIACPROBLEM_HPP_
00031 #define ABSTRACTCARDIACPROBLEM_HPP_
00032
00033
00034
00035 #include <string>
00036 #include <vector>
00037 #include <cassert>
00038 #include <climits>
00039 #include <boost/shared_ptr.hpp>
00040
00041 #include "ChasteSerialization.hpp"
00042 #include <boost/serialization/vector.hpp>
00043 #include <boost/serialization/string.hpp>
00044 #include <boost/serialization/split_member.hpp>
00045 #include <boost/serialization/shared_ptr.hpp>
00046 #include "ClassIsAbstract.hpp"
00047 #include "ChasteSerializationVersion.hpp"
00048
00049 #include "AbstractTetrahedralMesh.hpp"
00050 #include "AbstractCardiacCell.hpp"
00051 #include "AbstractCardiacCellFactory.hpp"
00052 #include "AbstractCardiacTissue.hpp"
00053 #include "AbstractDynamicLinearPdeSolver.hpp"
00054 #include "BoundaryConditionsContainer.hpp"
00055 #include "DistributedVectorFactory.hpp"
00056 #include "Hdf5DataReader.hpp"
00057 #include "Hdf5DataWriter.hpp"
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076 #include "DistributedTetrahedralMesh.hpp"
00077 #include "TetrahedralMesh.hpp"
00078 #include "MonodomainTissue.hpp"
00079 #include "BidomainTissue.hpp"
00080
00084 class AbstractUntemplatedCardiacProblem : boost::noncopyable
00085 {
00086 public:
00088 virtual ~AbstractUntemplatedCardiacProblem()
00089 {}
00090 };
00091
00097 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
00098 class AbstractCardiacProblem : public AbstractUntemplatedCardiacProblem
00099 {
00100 friend class TestBidomainWithBath;
00101 friend class TestCardiacSimulationArchiver;
00102
00104 typedef typename boost::shared_ptr<BoundaryConditionsContainer<ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM> >
00105 BccType;
00106
00107 private:
00109 friend class boost::serialization::access;
00110
00117 template<class Archive>
00118 void save(Archive & archive, const unsigned int version) const
00119 {
00120 if (version >= 1)
00121 {
00122 const unsigned element_dim=ELEMENT_DIM;
00123 archive & element_dim;
00124 const unsigned space_dim=SPACE_DIM;
00125 archive & space_dim;
00126 const unsigned problem_dim=PROBLEM_DIM;
00127 archive & problem_dim;
00128 }
00129 archive & mMeshFilename;
00130 archive & mpMesh;
00131
00132
00133
00134 assert(version >= 2);
00135
00136
00137
00138
00139
00140 archive & mWriteInfo;
00141 archive & mPrintOutput;
00142 archive & mNodesToOutput;
00143
00144
00145
00146
00147
00148 archive & mpCardiacTissue;
00149
00150 bool has_solution = (mSolution != NULL);
00151 archive & has_solution;
00152 if (has_solution)
00153 {
00155 std::string filename = ArchiveLocationInfo::GetArchiveDirectory() + "AbstractCardiacProblem_mSolution.vec";
00156
00157 Hdf5DataWriter writer(*mpMesh->GetDistributedVectorFactory(), ArchiveLocationInfo::GetArchiveRelativePath(), "AbstractCardiacProblem_mSolution", false);
00158 writer.DefineFixedDimension(mpMesh->GetDistributedVectorFactory()->GetProblemSize());
00159
00160 writer.DefineUnlimitedDimension("Time", "msec", 1);
00161
00162
00163 writer.SetFixedChunkSize(1);
00164
00165 int vm_col = writer.DefineVariable("Vm","mV");
00166
00168 assert(HeartConfig::Instance()->GetOutputUsingOriginalNodeOrdering() == false );
00169
00170 if (PROBLEM_DIM==1)
00171 {
00172 writer.EndDefineMode();
00173 writer.PutUnlimitedVariable(0.0);
00174 writer.PutVector(vm_col, mSolution);
00175 }
00176
00177 if (PROBLEM_DIM==2)
00178 {
00179 int phie_col = writer.DefineVariable("Phie","mV");
00180 std::vector<int> variable_ids;
00181 variable_ids.push_back(vm_col);
00182 variable_ids.push_back(phie_col);
00183 writer.EndDefineMode();
00184 writer.PutUnlimitedVariable(0.0);
00185 writer.PutStripedVector(variable_ids, mSolution);
00186 }
00187
00188 writer.Close();
00189
00190 }
00191 archive & mCurrentTime;
00192
00193
00194 SaveBoundaryConditions(archive, mpMesh, mpBoundaryConditionsContainer);
00195 SaveBoundaryConditions(archive, mpMesh, mpDefaultBoundaryConditionsContainer);
00196 }
00197
00204 template<class Archive>
00205 void load(Archive & archive, const unsigned int version)
00206 {
00207 if (version >= 1)
00208 {
00209 unsigned element_dim;
00210 unsigned space_dim;
00211 unsigned problem_dim;
00212 archive & element_dim;
00213 archive & space_dim;
00214 archive & problem_dim;
00215 if ( (element_dim != ELEMENT_DIM) ||(space_dim != SPACE_DIM) ||(problem_dim != PROBLEM_DIM) )
00216 {
00217
00218
00219
00220
00221
00222
00223 EXCEPTION("Failed to load from checkpoint because the dimensions of the archive do not match the object it's being read into.");
00224 }
00225 }
00226 archive & mMeshFilename;
00227 archive & mpMesh;
00228 assert(mpMesh != NULL);
00229
00230
00231 if (version < 2)
00232 {
00233 bool use_matrix_based_assembly;
00234 archive & use_matrix_based_assembly;
00235 }
00236
00237 archive & mWriteInfo;
00238 archive & mPrintOutput;
00239 archive & mNodesToOutput;
00240
00241
00242
00243
00244
00245 archive & mpCardiacTissue;
00246
00247 bool has_solution;
00248 archive & has_solution;
00249 if ((has_solution) && PROBLEM_DIM < 3)
00250 {
00253 std::string filename = ArchiveLocationInfo::GetArchiveDirectory() + "AbstractCardiacProblem_mSolution.vec";
00254
00255 mSolution = mpMesh->GetDistributedVectorFactory()->CreateVec(PROBLEM_DIM);
00256 DistributedVector mSolution_distri = mpMesh->GetDistributedVectorFactory()->CreateDistributedVector(mSolution);
00257
00258 Vec vm = mpMesh->GetDistributedVectorFactory()->CreateVec();
00259 Vec phie = mpMesh->GetDistributedVectorFactory()->CreateVec();
00260
00261 std::string archive_dir = ArchiveLocationInfo::GetArchiveRelativePath();
00262 Hdf5DataReader reader(archive_dir, "AbstractCardiacProblem_mSolution", !FileFinder::IsAbsolutePath(archive_dir));
00263 reader.GetVariableOverNodes(vm, "Vm", 0);
00264
00265 if (PROBLEM_DIM==1)
00266 {
00267
00268
00269 DistributedVector vm_distri = mpMesh->GetDistributedVectorFactory()->CreateDistributedVector(vm);
00270
00271 DistributedVector::Stripe mSolution_vm(mSolution_distri,0);
00272
00273 for (DistributedVector::Iterator index = mSolution_distri.Begin();
00274 index != mSolution_distri.End();
00275 ++index)
00276 {
00277 mSolution_vm[index] = vm_distri[index];
00278 }
00279 }
00280
00281 if (PROBLEM_DIM==2)
00282 {
00283 reader.GetVariableOverNodes(phie, "Phie", 0);
00284
00285
00286 DistributedVector vm_distri = mpMesh->GetDistributedVectorFactory()->CreateDistributedVector(vm);
00287 DistributedVector phie_distri = mpMesh->GetDistributedVectorFactory()->CreateDistributedVector(phie);
00288
00289 DistributedVector::Stripe mSolution_vm(mSolution_distri,0);
00290 DistributedVector::Stripe mSolution_phie(mSolution_distri,1);
00291
00292 for (DistributedVector::Iterator index = mSolution_distri.Begin();
00293 index != mSolution_distri.End();
00294 ++index)
00295 {
00296 mSolution_vm[index] = vm_distri[index];
00297 mSolution_phie[index] = phie_distri[index];
00298 }
00299 }
00300
00301 mSolution_distri.Restore();
00302
00303 VecDestroy(vm);
00304 VecDestroy(phie);
00305
00306 }
00307 archive & mCurrentTime;
00308
00309
00310 mpBoundaryConditionsContainer = LoadBoundaryConditions(archive, mpMesh);
00311 mpDefaultBoundaryConditionsContainer = LoadBoundaryConditions(archive, mpMesh);
00312 }
00313
00314 BOOST_SERIALIZATION_SPLIT_MEMBER()
00315
00316
00323 template<class Archive>
00324 void SaveBoundaryConditions(Archive & archive,
00325 AbstractTetrahedralMesh<ELEMENT_DIM,SPACE_DIM>* pMesh,
00326 BccType pBcc) const
00327 {
00328 (*ProcessSpecificArchive<Archive>::Get()) & pBcc;
00329 }
00330
00338 template<class Archive>
00339 BccType LoadBoundaryConditions(
00340 Archive & archive,
00341 AbstractTetrahedralMesh<ELEMENT_DIM,SPACE_DIM>* pMesh)
00342 {
00343
00344 BccType p_bcc;
00345 (*ProcessSpecificArchive<Archive>::Get()) & p_bcc;
00346
00347
00348 if (p_bcc)
00349 {
00350 p_bcc->LoadFromArchive(*ProcessSpecificArchive<Archive>::Get(), pMesh);
00351 }
00352
00353 return p_bcc;
00354 }
00355
00356 protected:
00359 std::string mMeshFilename;
00360
00362 bool mAllocatedMemoryForMesh;
00364 bool mWriteInfo;
00366 bool mPrintOutput;
00367
00369 std::vector<unsigned> mNodesToOutput;
00370
00372 unsigned mVoltageColumnId;
00374 std::vector<unsigned> mExtraVariablesId;
00376 unsigned mTimeColumnId;
00378 unsigned mNodeColumnId;
00379
00381 AbstractCardiacTissue<ELEMENT_DIM,SPACE_DIM>* mpCardiacTissue;
00382
00384 BccType mpBoundaryConditionsContainer;
00386 BccType mpDefaultBoundaryConditionsContainer;
00388 AbstractDynamicLinearPdeSolver<ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM>* mpSolver;
00390 AbstractCardiacCellFactory<ELEMENT_DIM,SPACE_DIM>* mpCellFactory;
00392 AbstractTetrahedralMesh<ELEMENT_DIM,SPACE_DIM>* mpMesh;
00393
00396 Vec mSolution;
00397
00405 double mCurrentTime;
00406
00408 AbstractTimeAdaptivityController* mpTimeAdaptivityController;
00409
00410
00411
00417 virtual AbstractCardiacTissue<ELEMENT_DIM,SPACE_DIM>* CreateCardiacTissue() =0;
00418
00424 virtual AbstractDynamicLinearPdeSolver<ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM>* CreateSolver() =0;
00425
00426 protected:
00430 template<unsigned DIM>
00431 friend class CardiacElectroMechanicsProblem;
00435 Hdf5DataWriter* mpWriter;
00436
00437 public:
00443 AbstractCardiacProblem(AbstractCardiacCellFactory<ELEMENT_DIM,SPACE_DIM>* pCellFactory);
00444
00448 AbstractCardiacProblem();
00449
00453 virtual ~AbstractCardiacProblem();
00454
00462 void Initialise();
00463
00469 void SetNodesPerProcessorFilename(const std::string& rFilename);
00470
00475 void SetBoundaryConditionsContainer(BccType pBcc);
00476
00484 virtual void PreSolveChecks();
00485
00491 virtual Vec CreateInitialCondition();
00492
00498 void SetMesh(AbstractTetrahedralMesh<ELEMENT_DIM,SPACE_DIM>* pMesh);
00499
00505 void PrintOutput(bool rPrintOutput);
00506
00512 void SetWriteInfo(bool writeInfo = true);
00513
00524 Vec GetSolution();
00525
00531 DistributedVector GetSolutionDistributedVector();
00532
00536 double GetCurrentTime();
00537
00541 AbstractTetrahedralMesh<ELEMENT_DIM,SPACE_DIM> & rGetMesh();
00542
00546 AbstractCardiacTissue<ELEMENT_DIM,SPACE_DIM>* GetTissue();
00547
00557 void Solve();
00558
00566 void CloseFilesAndPostProcess();
00567
00575 virtual void WriteInfo(double time)=0;
00576
00581 virtual void DefineWriterColumns(bool extending);
00582
00587 void DefineExtraVariablesWriterColumns(bool extending);
00588
00595 virtual void WriteOneStep(double time, Vec voltageVec) = 0;
00596
00600 void WriteExtraVariablesOneStep();
00601
00607 void InitialiseWriter();
00608
00616 void SetOutputNodes(std::vector<unsigned> & rNodesToOutput);
00617
00621 Hdf5DataReader GetDataReader();
00622
00630 virtual void AtBeginningOfTimestep(double time)
00631 {}
00632
00640 virtual void OnEndOfTimestep(double time)
00641 {}
00642
00650 virtual void SetUpAdditionalStoppingTimes(std::vector<double>& rAdditionalStoppingTimes)
00651 {}
00652
00653
00654
00656
00657
00663 void SetUseTimeAdaptivityController(bool useAdaptivity,
00664 AbstractTimeAdaptivityController* pController = NULL);
00665
00686 template<class Archive>
00687 void LoadExtraArchive(Archive & archive, unsigned version);
00688
00692 virtual bool GetHasBath();
00693
00698 virtual void SetElectrodes();
00699 };
00700
00701 TEMPLATED_CLASS_IS_ABSTRACT_3_UNSIGNED(AbstractCardiacProblem)
00702
00703
00704 template<unsigned DIM>
00705 class BidomainProblem;
00706
00707 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
00708 template<class Archive>
00709 void AbstractCardiacProblem<ELEMENT_DIM,SPACE_DIM,PROBLEM_DIM>::LoadExtraArchive(Archive & archive, unsigned version)
00710 {
00711
00712 DistributedVectorFactory* p_mesh_factory;
00713 archive >> p_mesh_factory;
00714
00715
00716 mpCardiacTissue->LoadCardiacCells(archive, version);
00717
00718 {
00719 DistributedVectorFactory* p_pde_factory;
00720 archive >> p_pde_factory;
00721 assert(p_pde_factory == p_mesh_factory);
00722 }
00723
00724 delete p_mesh_factory;
00725
00726
00727 BccType p_bcc;
00728 archive >> p_bcc;
00729 if (p_bcc)
00730 {
00731 if (!mpBoundaryConditionsContainer)
00732 {
00733 mpBoundaryConditionsContainer = p_bcc;
00734 mpBoundaryConditionsContainer->LoadFromArchive(archive, mpMesh);
00735 }
00736 else
00737 {
00738
00739 DistributedTetrahedralMesh<ELEMENT_DIM,SPACE_DIM>* p_dist_mesh = dynamic_cast<DistributedTetrahedralMesh<ELEMENT_DIM,SPACE_DIM>*>(mpMesh);
00740 if (p_dist_mesh)
00741 {
00742 mpBoundaryConditionsContainer->MergeFromArchive(archive, mpMesh);
00743 }
00744 else
00745 {
00746
00747 p_bcc->LoadFromArchive(archive, mpMesh);
00749 }
00750 }
00751 }
00752 BccType p_default_bcc;
00753 archive >> p_default_bcc;
00754 if (p_default_bcc)
00755 {
00756
00757 assert(p_bcc == p_default_bcc);
00758 }
00759
00760
00761 if (PROBLEM_DIM == 2)
00762 {
00763 assert(ELEMENT_DIM == SPACE_DIM);
00764 BidomainProblem<ELEMENT_DIM>* p_problem = dynamic_cast<BidomainProblem<ELEMENT_DIM>*>(this);
00765 assert(p_problem);
00766 p_problem->LoadExtraArchiveForBidomain(archive, version);
00767 }
00768 }
00769
00770 namespace boost {
00771 namespace serialization {
00778 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
00779 struct version<AbstractCardiacProblem<ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM> >
00780 {
00782 CHASTE_VERSION_CONTENT(2);
00783 };
00784 }
00785 }
00786 #endif