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
00040 #include "ChasteSerialization.hpp"
00041 #include <boost/serialization/vector.hpp>
00042 #include <boost/serialization/string.hpp>
00043 #include <boost/serialization/split_member.hpp>
00044 #include <boost/shared_ptr.hpp>
00045 #include <boost/serialization/shared_ptr.hpp>
00046 #include "ClassIsAbstract.hpp"
00047
00048 #include "AbstractTetrahedralMesh.hpp"
00049 #include "AbstractCardiacCell.hpp"
00050 #include "AbstractCardiacCellFactory.hpp"
00051 #include "AbstractCardiacTissue.hpp"
00052 #include "AbstractDynamicLinearPdeSolver.hpp"
00053 #include "BoundaryConditionsContainer.hpp"
00054 #include "DistributedVectorFactory.hpp"
00055 #include "Hdf5DataReader.hpp"
00056 #include "Hdf5DataWriter.hpp"
00057
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 archive & mUseMatrixBasedRhsAssembly;
00133 archive & mWriteInfo;
00134 archive & mPrintOutput;
00135 archive & mNodesToOutput;
00136
00137
00138
00139
00140
00141 archive & mpCardiacTissue;
00142
00143 bool has_solution = (mSolution != NULL);
00144 archive & has_solution;
00145 if (has_solution)
00146 {
00148 std::string filename = ArchiveLocationInfo::GetArchiveDirectory() + "AbstractCardiacProblem_mSolution.vec";
00149
00150 Hdf5DataWriter writer(*mpMesh->GetDistributedVectorFactory(), ArchiveLocationInfo::GetArchiveRelativePath(), "AbstractCardiacProblem_mSolution", false);
00151 writer.DefineFixedDimension(mpMesh->GetDistributedVectorFactory()->GetProblemSize());
00152
00153 writer.DefineUnlimitedDimension("Time", "msec");
00154 int vm_col = writer.DefineVariable("Vm","mV");
00155
00157 assert(HeartConfig::Instance()->GetOutputUsingOriginalNodeOrdering() == false );
00158
00159 if (PROBLEM_DIM==1)
00160 {
00161 writer.EndDefineMode();
00162 writer.PutUnlimitedVariable(0.0);
00163 writer.PutVector(vm_col, mSolution);
00164 }
00165
00166 if (PROBLEM_DIM==2)
00167 {
00168 int phie_col = writer.DefineVariable("Phie","mV");
00169 std::vector<int> variable_ids;
00170 variable_ids.push_back(vm_col);
00171 variable_ids.push_back(phie_col);
00172 writer.EndDefineMode();
00173 writer.PutUnlimitedVariable(0.0);
00174 writer.PutStripedVector(variable_ids, mSolution);
00175 }
00176
00177 writer.Close();
00178
00179 }
00180 archive & mCurrentTime;
00181
00182
00183 SaveBoundaryConditions(archive, mpMesh, mpBoundaryConditionsContainer);
00184 SaveBoundaryConditions(archive, mpMesh, mpDefaultBoundaryConditionsContainer);
00185 }
00186
00193 template<class Archive>
00194 void load(Archive & archive, const unsigned int version)
00195 {
00196 if (version == 1)
00197 {
00198 unsigned element_dim;
00199 unsigned space_dim;
00200 unsigned problem_dim;
00201 archive & element_dim;
00202 archive & space_dim;
00203 archive & problem_dim;
00204 if ( (element_dim != ELEMENT_DIM) ||(space_dim != SPACE_DIM) ||(problem_dim != PROBLEM_DIM) )
00205 {
00206
00207
00208
00209
00210
00211
00212 EXCEPTION("Failed to load from checkpoint because the dimensions of the archive do not match the object it's being read into.");
00213 }
00214 }
00215 archive & mMeshFilename;
00216 archive & mpMesh;
00217 assert(mpMesh != NULL);
00218
00219 archive & mUseMatrixBasedRhsAssembly;
00220 archive & mWriteInfo;
00221 archive & mPrintOutput;
00222 archive & mNodesToOutput;
00223
00224
00225
00226
00227
00228 archive & mpCardiacTissue;
00229
00230 bool has_solution;
00231 archive & has_solution;
00232 if (has_solution)
00233 {
00236 std::string filename = ArchiveLocationInfo::GetArchiveDirectory() + "AbstractCardiacProblem_mSolution.vec";
00237
00238 mSolution = mpMesh->GetDistributedVectorFactory()->CreateVec(PROBLEM_DIM);
00239 DistributedVector mSolution_distri = mpMesh->GetDistributedVectorFactory()->CreateDistributedVector(mSolution);
00240
00241 Vec vm = mpMesh->GetDistributedVectorFactory()->CreateVec();
00242 Vec phie = mpMesh->GetDistributedVectorFactory()->CreateVec();
00243
00244 std::string archive_dir = ArchiveLocationInfo::GetArchiveRelativePath();
00245 Hdf5DataReader reader(archive_dir, "AbstractCardiacProblem_mSolution", !FileFinder::IsAbsolutePath(archive_dir));
00246 reader.GetVariableOverNodes(vm, "Vm", 0);
00247
00248 if (PROBLEM_DIM==1)
00249 {
00250
00251
00252 DistributedVector vm_distri = mpMesh->GetDistributedVectorFactory()->CreateDistributedVector(vm);
00253
00254 DistributedVector::Stripe mSolution_vm(mSolution_distri,0);
00255
00256 for (DistributedVector::Iterator index = mSolution_distri.Begin();
00257 index != mSolution_distri.End();
00258 ++index)
00259 {
00260 mSolution_vm[index] = vm_distri[index];
00261 }
00262 }
00263
00264 if (PROBLEM_DIM==2)
00265 {
00266 reader.GetVariableOverNodes(phie, "Phie", 0);
00267
00268
00269 DistributedVector vm_distri = mpMesh->GetDistributedVectorFactory()->CreateDistributedVector(vm);
00270 DistributedVector phie_distri = mpMesh->GetDistributedVectorFactory()->CreateDistributedVector(phie);
00271
00272 DistributedVector::Stripe mSolution_vm(mSolution_distri,0);
00273 DistributedVector::Stripe mSolution_phie(mSolution_distri,1);
00274
00275 for (DistributedVector::Iterator index = mSolution_distri.Begin();
00276 index != mSolution_distri.End();
00277 ++index)
00278 {
00279 mSolution_vm[index] = vm_distri[index];
00280 mSolution_phie[index] = phie_distri[index];
00281 }
00282 }
00283
00284 mSolution_distri.Restore();
00285
00286 VecDestroy(vm);
00287 VecDestroy(phie);
00288
00289 }
00290 archive & mCurrentTime;
00291
00292
00293 mpBoundaryConditionsContainer = LoadBoundaryConditions(archive, mpMesh);
00294 mpDefaultBoundaryConditionsContainer = LoadBoundaryConditions(archive, mpMesh);
00295 }
00296
00297 BOOST_SERIALIZATION_SPLIT_MEMBER()
00298
00299
00306 template<class Archive>
00307 void SaveBoundaryConditions(Archive & archive,
00308 AbstractTetrahedralMesh<ELEMENT_DIM,SPACE_DIM>* pMesh,
00309 BccType pBcc) const
00310 {
00311 (*ProcessSpecificArchive<Archive>::Get()) & pBcc;
00312 }
00313
00321 template<class Archive>
00322 BccType LoadBoundaryConditions(
00323 Archive & archive,
00324 AbstractTetrahedralMesh<ELEMENT_DIM,SPACE_DIM>* pMesh)
00325 {
00326
00327 BccType p_bcc;
00328 (*ProcessSpecificArchive<Archive>::Get()) & p_bcc;
00329
00330
00331 if (p_bcc)
00332 {
00333 p_bcc->LoadFromArchive(*ProcessSpecificArchive<Archive>::Get(), pMesh);
00334 }
00335
00336 return p_bcc;
00337 }
00338
00339 protected:
00342 std::string mMeshFilename;
00343
00348 bool mUseMatrixBasedRhsAssembly;
00350 bool mAllocatedMemoryForMesh;
00352 bool mWriteInfo;
00354 bool mPrintOutput;
00355
00357 std::vector<unsigned> mNodesToOutput;
00358
00360 unsigned mVoltageColumnId;
00362 std::vector<unsigned> mExtraVariablesId;
00364 unsigned mTimeColumnId;
00366 unsigned mNodeColumnId;
00367
00369 AbstractCardiacTissue<ELEMENT_DIM,SPACE_DIM>* mpCardiacTissue;
00370
00372 BccType mpBoundaryConditionsContainer;
00374 BccType mpDefaultBoundaryConditionsContainer;
00376 AbstractDynamicLinearPdeSolver<ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM>* mpSolver;
00378 AbstractCardiacCellFactory<ELEMENT_DIM,SPACE_DIM>* mpCellFactory;
00380 AbstractTetrahedralMesh<ELEMENT_DIM,SPACE_DIM>* mpMesh;
00381
00384 Vec mSolution;
00385
00393 double mCurrentTime;
00394
00400 virtual AbstractCardiacTissue<ELEMENT_DIM,SPACE_DIM>* CreateCardiacTissue() =0;
00401
00407 virtual AbstractDynamicLinearPdeSolver<ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM>* CreateSolver() =0;
00408
00409 protected:
00413 template<unsigned DIM>
00414 friend class CardiacElectroMechanicsProblem;
00418 Hdf5DataWriter* mpWriter;
00425 virtual void SetElectrodes();
00426
00427 public:
00433 AbstractCardiacProblem(AbstractCardiacCellFactory<ELEMENT_DIM,SPACE_DIM>* pCellFactory);
00434
00438 AbstractCardiacProblem();
00439
00443 virtual ~AbstractCardiacProblem();
00444
00452 void Initialise();
00453
00459 void SetNodesPerProcessorFilename(const std::string& rFilename);
00460
00465 void SetBoundaryConditionsContainer(BccType pBcc);
00466
00474 virtual void PreSolveChecks();
00475
00481 virtual Vec CreateInitialCondition();
00482
00488 void SetMesh(AbstractTetrahedralMesh<ELEMENT_DIM,SPACE_DIM>* pMesh);
00489
00495 void PrintOutput(bool rPrintOutput);
00496
00502 void SetWriteInfo(bool writeInfo = true);
00503
00514 Vec GetSolution();
00515
00521 DistributedVector GetSolutionDistributedVector();
00522
00526 double GetCurrentTime();
00527
00531 AbstractTetrahedralMesh<ELEMENT_DIM,SPACE_DIM> & rGetMesh();
00532
00536 AbstractCardiacTissue<ELEMENT_DIM,SPACE_DIM>* GetTissue();
00537
00547 void Solve();
00548
00556 void CloseFilesAndPostProcess();
00557
00565 virtual void WriteInfo(double time)=0;
00566
00571 virtual void DefineWriterColumns(bool extending);
00572
00577 void DefineExtraVariablesWriterColumns(bool extending);
00578
00585 virtual void WriteOneStep(double time, Vec voltageVec) = 0;
00586
00590 void WriteExtraVariablesOneStep();
00591
00597 void InitialiseWriter();
00598
00606 void SetOutputNodes(std::vector<unsigned> & rNodesToOutput);
00607
00611 Hdf5DataReader GetDataReader();
00612
00618 void UseMatrixBasedRhsAssembly(bool usematrix=true);
00619
00627 virtual void AtBeginningOfTimestep(double time)
00628 {}
00629
00637 virtual void OnEndOfTimestep(double time)
00638 {}
00639
00647 virtual void SetUpAdditionalStoppingTimes(std::vector<double>& rAdditionalStoppingTimes)
00648 {}
00649
00670 template<class Archive>
00671 void LoadExtraArchive(Archive & archive, unsigned version);
00672
00676 virtual bool GetHasBath();
00677
00678 };
00679
00680 TEMPLATED_CLASS_IS_ABSTRACT_3_UNSIGNED(AbstractCardiacProblem)
00681
00682
00683 template<unsigned DIM>
00684 class BidomainProblem;
00685
00686 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
00687 template<class Archive>
00688 void AbstractCardiacProblem<ELEMENT_DIM,SPACE_DIM,PROBLEM_DIM>::LoadExtraArchive(Archive & archive, unsigned version)
00689 {
00690
00691 DistributedVectorFactory* p_mesh_factory;
00692 archive >> p_mesh_factory;
00693
00694
00695 std::vector<AbstractCardiacCell*> cells;
00696
00697 AbstractCardiacTissue<ELEMENT_DIM,SPACE_DIM>::LoadCardiacCells(archive, version, cells, this->mpMesh);
00698 mpCardiacTissue->MergeCells(cells);
00699
00700 {
00701 DistributedVectorFactory* p_pde_factory;
00702 archive >> p_pde_factory;
00703 assert(p_pde_factory == p_mesh_factory);
00704 }
00705
00706 delete p_mesh_factory;
00707
00708
00709 BccType p_bcc;
00710 archive >> p_bcc;
00711 if (p_bcc)
00712 {
00713 if (!mpBoundaryConditionsContainer)
00714 {
00715 mpBoundaryConditionsContainer = p_bcc;
00716 mpBoundaryConditionsContainer->LoadFromArchive(archive, mpMesh);
00717 }
00718 else
00719 {
00720
00721 DistributedTetrahedralMesh<ELEMENT_DIM,SPACE_DIM>* p_dist_mesh = dynamic_cast<DistributedTetrahedralMesh<ELEMENT_DIM,SPACE_DIM>*>(mpMesh);
00722 if (p_dist_mesh)
00723 {
00724 mpBoundaryConditionsContainer->MergeFromArchive(archive, mpMesh);
00725 }
00726 else
00727 {
00728
00729 p_bcc->LoadFromArchive(archive, mpMesh);
00731 }
00732 }
00733 }
00734 BccType p_default_bcc;
00735 archive >> p_default_bcc;
00736 if (p_default_bcc)
00737 {
00738
00739 assert(p_bcc == p_default_bcc);
00740 }
00741
00742
00743 if (PROBLEM_DIM == 2)
00744 {
00745 assert(ELEMENT_DIM == SPACE_DIM);
00746 BidomainProblem<ELEMENT_DIM>* p_problem = dynamic_cast<BidomainProblem<ELEMENT_DIM>*>(this);
00747 assert(p_problem);
00748 p_problem->LoadExtraArchiveForBidomain(archive, version);
00749 }
00750 }
00751
00752 namespace boost {
00753 namespace serialization {
00760 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
00761 struct version<AbstractCardiacProblem<ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM> >
00762 {
00764 BOOST_STATIC_CONSTANT(unsigned, value = 1);
00765 };
00766 }
00767 }
00768 #endif