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 #include <string>
00034 #include <vector>
00035 #include <cassert>
00036 #include <climits>
00037 #include <boost/serialization/vector.hpp>
00038 #include <boost/serialization/string.hpp>
00039 #include "ChasteSerialization.hpp"
00040 #include <boost/serialization/split_member.hpp>
00041 #include <boost/shared_ptr.hpp>
00042 #include <boost/serialization/shared_ptr.hpp>
00043 #include "ClassIsAbstract.hpp"
00044 #include "AbstractCardiacCell.hpp"
00045 #include "AbstractCardiacCellFactory.hpp"
00046 #include "AbstractCardiacPde.hpp"
00047 #include "AbstractDynamicAssemblerMixin.hpp"
00048 #include "AbstractTetrahedralMesh.hpp"
00049 #include "BoundaryConditionsContainer.hpp"
00050 #include "DistributedVectorFactory.hpp"
00051 #include "Hdf5DataReader.hpp"
00052 #include "Hdf5DataWriter.hpp"
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072 #include "DistributedTetrahedralMesh.hpp"
00073 #include "TetrahedralMesh.hpp"
00074 #include "MonodomainPde.hpp"
00075 #include "BidomainPde.hpp"
00076
00077
00083 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
00084 class AbstractCardiacProblem
00085 {
00086 friend class TestBidomainWithBathAssembler;
00087 friend class TestCardiacSimulationArchiver;
00088
00090 typedef typename boost::shared_ptr<BoundaryConditionsContainer<ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM> >
00091 BccType;
00092
00093 private:
00095 friend class boost::serialization::access;
00096
00103 template<class Archive>
00104 void save(Archive & archive, const unsigned int version) const
00105 {
00106 archive & mMeshFilename;
00107 archive & mpMesh;
00108
00109 archive & mUseMatrixBasedRhsAssembly;
00110 archive & mWriteInfo;
00111 archive & mPrintOutput;
00112 archive & mNodesToOutput;
00113
00114
00115
00116
00117
00118 archive & mpCardiacPde;
00119
00120 bool has_solution = (mSolution != NULL);
00121 archive & has_solution;
00122 if (has_solution)
00123 {
00125 std::string filename = ArchiveLocationInfo::GetArchiveDirectory() + "AbstractCardiacProblem_mSolution.vec";
00126
00127 Hdf5DataWriter writer(*mpMesh->GetDistributedVectorFactory(), ArchiveLocationInfo::GetArchiveRelativePath(), "AbstractCardiacProblem_mSolution", false);
00128 writer.DefineFixedDimension(mpMesh->GetDistributedVectorFactory()->GetProblemSize());
00129
00130 writer.DefineUnlimitedDimension("Time", "msec");
00131 int vm_col = writer.DefineVariable("Vm","mV");
00132
00133 if (PROBLEM_DIM==1)
00134 {
00135 writer.EndDefineMode();
00136 writer.PutUnlimitedVariable(0.0);
00137 writer.PutVector(vm_col, mSolution);
00138 }
00139
00140 if (PROBLEM_DIM==2)
00141 {
00142 int phie_col = writer.DefineVariable("Phie","mV");
00143 writer.EndDefineMode();
00144 writer.PutUnlimitedVariable(0.0);
00145 writer.PutStripedVector(vm_col, phie_col, mSolution);
00146 }
00147
00148 writer.Close();
00149
00150 }
00151 archive & mCurrentTime;
00152
00153
00154 SaveBoundaryConditions(archive, mpMesh, mpBoundaryConditionsContainer);
00155 SaveBoundaryConditions(archive, mpMesh, mpDefaultBoundaryConditionsContainer);
00156 }
00157
00164 template<class Archive>
00165 void load(Archive & archive, const unsigned int version)
00166 {
00167 archive & mMeshFilename;
00168 archive & mpMesh;
00169
00170 archive & mUseMatrixBasedRhsAssembly;
00171 archive & mWriteInfo;
00172 archive & mPrintOutput;
00173 archive & mNodesToOutput;
00174
00175
00176
00177
00178
00179 archive & mpCardiacPde;
00180
00181 bool has_solution;
00182 archive & has_solution;
00183 if (has_solution)
00184 {
00187 std::string filename = ArchiveLocationInfo::GetArchiveDirectory() + "AbstractCardiacProblem_mSolution.vec";
00188
00189 mSolution = mpMesh->GetDistributedVectorFactory()->CreateVec(PROBLEM_DIM);
00190 DistributedVector mSolution_distri = mpMesh->GetDistributedVectorFactory()->CreateDistributedVector(mSolution);
00191
00192 Vec vm = mpMesh->GetDistributedVectorFactory()->CreateVec();
00193 Vec phie = mpMesh->GetDistributedVectorFactory()->CreateVec();
00194
00195 Hdf5DataReader reader(ArchiveLocationInfo::GetArchiveRelativePath(), "AbstractCardiacProblem_mSolution", ArchiveLocationInfo::GetIsDirRelativeToChasteTestOutput());
00196 reader.GetVariableOverNodes(vm, "Vm", 0);
00197
00198 if (PROBLEM_DIM==1)
00199 {
00200
00201
00202 DistributedVector vm_distri = mpMesh->GetDistributedVectorFactory()->CreateDistributedVector(vm);
00203
00204 DistributedVector::Stripe mSolution_vm(mSolution_distri,0);
00205
00206 for (DistributedVector::Iterator index = mSolution_distri.Begin();
00207 index != mSolution_distri.End();
00208 ++index)
00209 {
00210 mSolution_vm[index] = vm_distri[index];
00211 }
00212 }
00213
00214 if (PROBLEM_DIM==2)
00215 {
00216 reader.GetVariableOverNodes(phie, "Phie", 0);
00217
00218
00219 DistributedVector vm_distri = mpMesh->GetDistributedVectorFactory()->CreateDistributedVector(vm);
00220 DistributedVector phie_distri = mpMesh->GetDistributedVectorFactory()->CreateDistributedVector(phie);
00221
00222 DistributedVector::Stripe mSolution_vm(mSolution_distri,0);
00223 DistributedVector::Stripe mSolution_phie(mSolution_distri,1);
00224
00225 for (DistributedVector::Iterator index = mSolution_distri.Begin();
00226 index != mSolution_distri.End();
00227 ++index)
00228 {
00229 mSolution_vm[index] = vm_distri[index];
00230 mSolution_phie[index] = phie_distri[index];
00231 }
00232 }
00233
00234 mSolution_distri.Restore();
00235
00236 VecDestroy(vm);
00237 VecDestroy(phie);
00238
00239 }
00240 archive & mCurrentTime;
00241
00242
00243 mpBoundaryConditionsContainer = LoadBoundaryConditions(archive, mpMesh);
00244 mpDefaultBoundaryConditionsContainer = LoadBoundaryConditions(archive, mpMesh);
00245 }
00246
00247 BOOST_SERIALIZATION_SPLIT_MEMBER()
00248
00249
00256 template<class Archive>
00257 void SaveBoundaryConditions(Archive & archive,
00258 AbstractTetrahedralMesh<ELEMENT_DIM,SPACE_DIM>* pMesh,
00259 BccType pBcc) const
00260 {
00261 (*ProcessSpecificArchive<Archive>::Get()) & pBcc;
00262 }
00263
00271 template<class Archive>
00272 BccType LoadBoundaryConditions(
00273 Archive & archive,
00274 AbstractTetrahedralMesh<ELEMENT_DIM,SPACE_DIM>* pMesh)
00275 {
00276
00277 BccType p_bcc;
00278 (*ProcessSpecificArchive<Archive>::Get()) & p_bcc;
00279
00280
00281 if (p_bcc)
00282 {
00283 p_bcc->LoadFromArchive(*ProcessSpecificArchive<Archive>::Get(), pMesh);
00284 }
00285
00286 return p_bcc;
00287 }
00288
00289 protected:
00292 std::string mMeshFilename;
00293
00298 bool mUseMatrixBasedRhsAssembly;
00300 bool mAllocatedMemoryForMesh;
00302 bool mWriteInfo;
00304 bool mPrintOutput;
00305
00307 std::vector<unsigned> mNodesToOutput;
00308
00310 unsigned mVoltageColumnId;
00312 std::vector<unsigned> mExtraVariablesId;
00314 unsigned mTimeColumnId;
00316 unsigned mNodeColumnId;
00317
00319 AbstractCardiacPde<ELEMENT_DIM,SPACE_DIM>* mpCardiacPde;
00320
00322 BccType mpBoundaryConditionsContainer;
00324 BccType mpDefaultBoundaryConditionsContainer;
00326 AbstractDynamicAssemblerMixin<ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM>* mpAssembler;
00328 AbstractCardiacCellFactory<ELEMENT_DIM,SPACE_DIM>* mpCellFactory;
00330 AbstractTetrahedralMesh<ELEMENT_DIM,SPACE_DIM>* mpMesh;
00331
00334 Vec mSolution;
00335
00343 double mCurrentTime;
00344
00350 virtual AbstractCardiacPde<ELEMENT_DIM,SPACE_DIM>* CreateCardiacPde() =0;
00351
00357 virtual AbstractDynamicAssemblerMixin<ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM>* CreateAssembler() =0;
00358
00359 protected:
00363 template<unsigned DIM>
00364 friend class CardiacElectroMechanicsProblem;
00368 Hdf5DataWriter* mpWriter;
00369
00370 public:
00376 AbstractCardiacProblem(AbstractCardiacCellFactory<ELEMENT_DIM,SPACE_DIM>* pCellFactory);
00377
00381 AbstractCardiacProblem();
00382
00386 virtual ~AbstractCardiacProblem();
00387
00395 void Initialise();
00396
00402 void SetNodesPerProcessorFilename(const std::string& rFilename);
00403
00408 void SetBoundaryConditionsContainer(BccType pBcc);
00409
00417 virtual void PreSolveChecks();
00418
00424 virtual Vec CreateInitialCondition();
00425
00431 void SetMesh(AbstractTetrahedralMesh<ELEMENT_DIM,SPACE_DIM>* pMesh);
00432
00438 void PrintOutput(bool rPrintOutput);
00439
00445 void SetWriteInfo(bool writeInfo = true);
00446
00457 Vec GetSolution();
00458
00464 DistributedVector GetSolutionDistributedVector();
00465
00469 double GetCurrentTime();
00470
00474 AbstractTetrahedralMesh<ELEMENT_DIM,SPACE_DIM> & rGetMesh();
00475
00479 AbstractCardiacPde<ELEMENT_DIM,SPACE_DIM>* GetPde();
00480
00490 void Solve();
00491
00499 void CloseFilesAndPostProcess();
00500
00508 virtual void WriteInfo(double time)=0;
00509
00514 virtual void DefineWriterColumns(bool extending);
00515
00520 void DefineExtraVariablesWriterColumns(bool extending);
00521
00528 virtual void WriteOneStep(double time, Vec voltageVec) = 0;
00529
00533 void WriteExtraVariablesOneStep();
00534
00540 void InitialiseWriter();
00541
00549 void SetOutputNodes(std::vector<unsigned> & rNodesToOutput);
00550
00554 Hdf5DataReader GetDataReader();
00555
00561 void UseMatrixBasedRhsAssembly(bool usematrix=true);
00562
00570 virtual void AtBeginningOfTimestep(double time)
00571 {}
00572
00580 virtual void OnEndOfTimestep(double time)
00581 {}
00582
00590 virtual void SetUpAdditionalStoppingTimes(std::vector<double>& rAdditionalStoppingTimes)
00591 {}
00592
00613 template<class Archive>
00614 void LoadExtraArchive(Archive & archive, unsigned version);
00615 };
00616
00617 TEMPLATED_CLASS_IS_ABSTRACT_3_UNSIGNED(AbstractCardiacProblem);
00618
00619
00620 template<unsigned DIM>
00621 class BidomainProblem;
00622
00623 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
00624 template<class Archive>
00625 void AbstractCardiacProblem<ELEMENT_DIM,SPACE_DIM,PROBLEM_DIM>::LoadExtraArchive(Archive & archive, unsigned version)
00626 {
00627
00628 DistributedVectorFactory* p_mesh_factory;
00629 archive >> p_mesh_factory;
00630
00631
00632 std::vector<AbstractCardiacCell*> cells;
00633
00634 AbstractCardiacPde<ELEMENT_DIM,SPACE_DIM>::LoadCardiacCells(archive, version, cells, this->mpMesh);
00635 mpCardiacPde->MergeCells(cells);
00636
00637 {
00638 DistributedVectorFactory* p_pde_factory;
00639 archive >> p_pde_factory;
00640 assert(p_pde_factory == p_mesh_factory);
00641 }
00642
00643 delete p_mesh_factory;
00644
00645
00646 BccType p_bcc;
00647 archive >> p_bcc;
00648 if (p_bcc)
00649 {
00650 if (!mpBoundaryConditionsContainer)
00651 {
00652 mpBoundaryConditionsContainer = p_bcc;
00653 mpBoundaryConditionsContainer->LoadFromArchive(archive, mpMesh);
00654 }
00655 else
00656 {
00657
00658 DistributedTetrahedralMesh<ELEMENT_DIM,SPACE_DIM>* p_dist_mesh = dynamic_cast<DistributedTetrahedralMesh<ELEMENT_DIM,SPACE_DIM>*>(mpMesh);
00659 if (p_dist_mesh)
00660 {
00661 mpBoundaryConditionsContainer->MergeFromArchive(archive, mpMesh);
00662 }
00663 else
00664 {
00665
00666 p_bcc->LoadFromArchive(archive, mpMesh);
00668 }
00669 }
00670 }
00671 BccType p_default_bcc;
00672 archive >> p_default_bcc;
00673 if (p_default_bcc)
00674 {
00675
00676 assert(p_bcc == p_default_bcc);
00677 }
00678
00679
00680 if (PROBLEM_DIM == 2)
00681 {
00682 assert(ELEMENT_DIM == SPACE_DIM);
00683 BidomainProblem<ELEMENT_DIM>* p_problem = dynamic_cast<BidomainProblem<ELEMENT_DIM>*>(this);
00684 assert(p_problem);
00685 p_problem->LoadExtraArchiveForBidomain(archive, version);
00686 }
00687 }
00688
00689
00690 #endif