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 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", 1);
00154
00155
00156 writer.SetFixedChunkSize(1);
00157
00158 int vm_col = writer.DefineVariable("Vm","mV");
00159
00161 assert(HeartConfig::Instance()->GetOutputUsingOriginalNodeOrdering() == false );
00162
00163 if (PROBLEM_DIM==1)
00164 {
00165 writer.EndDefineMode();
00166 writer.PutUnlimitedVariable(0.0);
00167 writer.PutVector(vm_col, mSolution);
00168 }
00169
00170 if (PROBLEM_DIM==2)
00171 {
00172 int phie_col = writer.DefineVariable("Phie","mV");
00173 std::vector<int> variable_ids;
00174 variable_ids.push_back(vm_col);
00175 variable_ids.push_back(phie_col);
00176 writer.EndDefineMode();
00177 writer.PutUnlimitedVariable(0.0);
00178 writer.PutStripedVector(variable_ids, mSolution);
00179 }
00180
00181 writer.Close();
00182
00183 }
00184 archive & mCurrentTime;
00185
00186
00187 SaveBoundaryConditions(archive, mpMesh, mpBoundaryConditionsContainer);
00188 SaveBoundaryConditions(archive, mpMesh, mpDefaultBoundaryConditionsContainer);
00189 }
00190
00197 template<class Archive>
00198 void load(Archive & archive, const unsigned int version)
00199 {
00200 if (version >= 1)
00201 {
00202 unsigned element_dim;
00203 unsigned space_dim;
00204 unsigned problem_dim;
00205 archive & element_dim;
00206 archive & space_dim;
00207 archive & problem_dim;
00208 if ( (element_dim != ELEMENT_DIM) ||(space_dim != SPACE_DIM) ||(problem_dim != PROBLEM_DIM) )
00209 {
00210
00211
00212
00213
00214
00215
00216 EXCEPTION("Failed to load from checkpoint because the dimensions of the archive do not match the object it's being read into.");
00217 }
00218 }
00219 archive & mMeshFilename;
00220 archive & mpMesh;
00221 assert(mpMesh != NULL);
00222
00223 archive & mUseMatrixBasedRhsAssembly;
00224 archive & mWriteInfo;
00225 archive & mPrintOutput;
00226 archive & mNodesToOutput;
00227
00228
00229
00230
00231
00232 archive & mpCardiacTissue;
00233
00234 bool has_solution;
00235 archive & has_solution;
00236 if ((has_solution) && PROBLEM_DIM < 3)
00237 {
00240 std::string filename = ArchiveLocationInfo::GetArchiveDirectory() + "AbstractCardiacProblem_mSolution.vec";
00241
00242 mSolution = mpMesh->GetDistributedVectorFactory()->CreateVec(PROBLEM_DIM);
00243 DistributedVector mSolution_distri = mpMesh->GetDistributedVectorFactory()->CreateDistributedVector(mSolution);
00244
00245 Vec vm = mpMesh->GetDistributedVectorFactory()->CreateVec();
00246 Vec phie = mpMesh->GetDistributedVectorFactory()->CreateVec();
00247
00248 std::string archive_dir = ArchiveLocationInfo::GetArchiveRelativePath();
00249 Hdf5DataReader reader(archive_dir, "AbstractCardiacProblem_mSolution", !FileFinder::IsAbsolutePath(archive_dir));
00250 reader.GetVariableOverNodes(vm, "Vm", 0);
00251
00252 if (PROBLEM_DIM==1)
00253 {
00254
00255
00256 DistributedVector vm_distri = mpMesh->GetDistributedVectorFactory()->CreateDistributedVector(vm);
00257
00258 DistributedVector::Stripe mSolution_vm(mSolution_distri,0);
00259
00260 for (DistributedVector::Iterator index = mSolution_distri.Begin();
00261 index != mSolution_distri.End();
00262 ++index)
00263 {
00264 mSolution_vm[index] = vm_distri[index];
00265 }
00266 }
00267
00268 if (PROBLEM_DIM==2)
00269 {
00270 reader.GetVariableOverNodes(phie, "Phie", 0);
00271
00272
00273 DistributedVector vm_distri = mpMesh->GetDistributedVectorFactory()->CreateDistributedVector(vm);
00274 DistributedVector phie_distri = mpMesh->GetDistributedVectorFactory()->CreateDistributedVector(phie);
00275
00276 DistributedVector::Stripe mSolution_vm(mSolution_distri,0);
00277 DistributedVector::Stripe mSolution_phie(mSolution_distri,1);
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 mSolution_phie[index] = phie_distri[index];
00285 }
00286 }
00287
00288 mSolution_distri.Restore();
00289
00290 VecDestroy(vm);
00291 VecDestroy(phie);
00292
00293 }
00294 archive & mCurrentTime;
00295
00296
00297 mpBoundaryConditionsContainer = LoadBoundaryConditions(archive, mpMesh);
00298 mpDefaultBoundaryConditionsContainer = LoadBoundaryConditions(archive, mpMesh);
00299 }
00300
00301 BOOST_SERIALIZATION_SPLIT_MEMBER()
00302
00303
00310 template<class Archive>
00311 void SaveBoundaryConditions(Archive & archive,
00312 AbstractTetrahedralMesh<ELEMENT_DIM,SPACE_DIM>* pMesh,
00313 BccType pBcc) const
00314 {
00315 (*ProcessSpecificArchive<Archive>::Get()) & pBcc;
00316 }
00317
00325 template<class Archive>
00326 BccType LoadBoundaryConditions(
00327 Archive & archive,
00328 AbstractTetrahedralMesh<ELEMENT_DIM,SPACE_DIM>* pMesh)
00329 {
00330
00331 BccType p_bcc;
00332 (*ProcessSpecificArchive<Archive>::Get()) & p_bcc;
00333
00334
00335 if (p_bcc)
00336 {
00337 p_bcc->LoadFromArchive(*ProcessSpecificArchive<Archive>::Get(), pMesh);
00338 }
00339
00340 return p_bcc;
00341 }
00342
00343 protected:
00346 std::string mMeshFilename;
00347
00352 bool mUseMatrixBasedRhsAssembly;
00354 bool mAllocatedMemoryForMesh;
00356 bool mWriteInfo;
00358 bool mPrintOutput;
00359
00361 std::vector<unsigned> mNodesToOutput;
00362
00364 unsigned mVoltageColumnId;
00366 std::vector<unsigned> mExtraVariablesId;
00368 unsigned mTimeColumnId;
00370 unsigned mNodeColumnId;
00371
00373 AbstractCardiacTissue<ELEMENT_DIM,SPACE_DIM>* mpCardiacTissue;
00374
00376 BccType mpBoundaryConditionsContainer;
00378 BccType mpDefaultBoundaryConditionsContainer;
00380 AbstractDynamicLinearPdeSolver<ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM>* mpSolver;
00382 AbstractCardiacCellFactory<ELEMENT_DIM,SPACE_DIM>* mpCellFactory;
00384 AbstractTetrahedralMesh<ELEMENT_DIM,SPACE_DIM>* mpMesh;
00385
00388 Vec mSolution;
00389
00397 double mCurrentTime;
00398
00400 AbstractTimeAdaptivityController* mpTimeAdaptivityController;
00401
00402
00403
00409 virtual AbstractCardiacTissue<ELEMENT_DIM,SPACE_DIM>* CreateCardiacTissue() =0;
00410
00416 virtual AbstractDynamicLinearPdeSolver<ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM>* CreateSolver() =0;
00417
00418 protected:
00422 template<unsigned DIM>
00423 friend class CardiacElectroMechanicsProblem;
00427 Hdf5DataWriter* mpWriter;
00428
00429 public:
00435 AbstractCardiacProblem(AbstractCardiacCellFactory<ELEMENT_DIM,SPACE_DIM>* pCellFactory);
00436
00440 AbstractCardiacProblem();
00441
00445 virtual ~AbstractCardiacProblem();
00446
00454 void Initialise();
00455
00461 void SetNodesPerProcessorFilename(const std::string& rFilename);
00462
00467 void SetBoundaryConditionsContainer(BccType pBcc);
00468
00476 virtual void PreSolveChecks();
00477
00483 virtual Vec CreateInitialCondition();
00484
00490 void SetMesh(AbstractTetrahedralMesh<ELEMENT_DIM,SPACE_DIM>* pMesh);
00491
00497 void PrintOutput(bool rPrintOutput);
00498
00504 void SetWriteInfo(bool writeInfo = true);
00505
00516 Vec GetSolution();
00517
00523 DistributedVector GetSolutionDistributedVector();
00524
00528 double GetCurrentTime();
00529
00533 AbstractTetrahedralMesh<ELEMENT_DIM,SPACE_DIM> & rGetMesh();
00534
00538 AbstractCardiacTissue<ELEMENT_DIM,SPACE_DIM>* GetTissue();
00539
00549 void Solve();
00550
00558 void CloseFilesAndPostProcess();
00559
00567 virtual void WriteInfo(double time)=0;
00568
00573 virtual void DefineWriterColumns(bool extending);
00574
00579 void DefineExtraVariablesWriterColumns(bool extending);
00580
00587 virtual void WriteOneStep(double time, Vec voltageVec) = 0;
00588
00592 void WriteExtraVariablesOneStep();
00593
00599 void InitialiseWriter();
00600
00608 void SetOutputNodes(std::vector<unsigned> & rNodesToOutput);
00609
00613 Hdf5DataReader GetDataReader();
00614
00620 void UseMatrixBasedRhsAssembly(bool useMatrixBasedRhsAssembly=true);
00621
00629 virtual void AtBeginningOfTimestep(double time)
00630 {}
00631
00639 virtual void OnEndOfTimestep(double time)
00640 {}
00641
00649 virtual void SetUpAdditionalStoppingTimes(std::vector<double>& rAdditionalStoppingTimes)
00650 {}
00651
00652
00653
00655
00656
00662 void SetUseTimeAdaptivityController(bool useAdaptivity,
00663 AbstractTimeAdaptivityController* pController = NULL);
00664
00685 template<class Archive>
00686 void LoadExtraArchive(Archive & archive, unsigned version);
00687
00691 virtual bool GetHasBath();
00692
00697 virtual void SetElectrodes();
00698 };
00699
00700 TEMPLATED_CLASS_IS_ABSTRACT_3_UNSIGNED(AbstractCardiacProblem)
00701
00702
00703 template<unsigned DIM>
00704 class BidomainProblem;
00705
00706 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
00707 template<class Archive>
00708 void AbstractCardiacProblem<ELEMENT_DIM,SPACE_DIM,PROBLEM_DIM>::LoadExtraArchive(Archive & archive, unsigned version)
00709 {
00710
00711 DistributedVectorFactory* p_mesh_factory;
00712 archive >> p_mesh_factory;
00713
00714
00715 mpCardiacTissue->LoadCardiacCells(archive, version);
00716
00717 {
00718 DistributedVectorFactory* p_pde_factory;
00719 archive >> p_pde_factory;
00720 assert(p_pde_factory == p_mesh_factory);
00721 }
00722
00723 delete p_mesh_factory;
00724
00725
00726 BccType p_bcc;
00727 archive >> p_bcc;
00728 if (p_bcc)
00729 {
00730 if (!mpBoundaryConditionsContainer)
00731 {
00732 mpBoundaryConditionsContainer = p_bcc;
00733 mpBoundaryConditionsContainer->LoadFromArchive(archive, mpMesh);
00734 }
00735 else
00736 {
00737
00738 DistributedTetrahedralMesh<ELEMENT_DIM,SPACE_DIM>* p_dist_mesh = dynamic_cast<DistributedTetrahedralMesh<ELEMENT_DIM,SPACE_DIM>*>(mpMesh);
00739 if (p_dist_mesh)
00740 {
00741 mpBoundaryConditionsContainer->MergeFromArchive(archive, mpMesh);
00742 }
00743 else
00744 {
00745
00746 p_bcc->LoadFromArchive(archive, mpMesh);
00748 }
00749 }
00750 }
00751 BccType p_default_bcc;
00752 archive >> p_default_bcc;
00753 if (p_default_bcc)
00754 {
00755
00756 assert(p_bcc == p_default_bcc);
00757 }
00758
00759
00760 if (PROBLEM_DIM == 2)
00761 {
00762 assert(ELEMENT_DIM == SPACE_DIM);
00763 BidomainProblem<ELEMENT_DIM>* p_problem = dynamic_cast<BidomainProblem<ELEMENT_DIM>*>(this);
00764 assert(p_problem);
00765 p_problem->LoadExtraArchiveForBidomain(archive, version);
00766 }
00767 }
00768
00769 namespace boost {
00770 namespace serialization {
00777 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
00778 struct version<AbstractCardiacProblem<ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM> >
00779 {
00781 CHASTE_VERSION_CONTENT(1);
00782 };
00783 }
00784 }
00785 #endif