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 #include "AbstractOutputModifier.hpp"
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 TestMonodomainProblem;
00119 friend class TestCardiacSimulationArchiver;
00120
00122 typedef typename boost::shared_ptr<BoundaryConditionsContainer<ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM> >
00123 BccType;
00124
00125 private:
00127 friend class boost::serialization::access;
00128
00135 template<class Archive>
00136 void save(Archive & archive, const unsigned int version) const
00137 {
00138 if (version >= 1)
00139 {
00140 const unsigned element_dim=ELEMENT_DIM;
00141 archive & element_dim;
00142 const unsigned space_dim=SPACE_DIM;
00143 archive & space_dim;
00144 const unsigned problem_dim=PROBLEM_DIM;
00145 archive & problem_dim;
00146 }
00147 archive & mMeshFilename;
00148 archive & mpMesh;
00149
00150
00151
00152 assert(version >= 2);
00153
00154
00155
00156
00157
00158 archive & mWriteInfo;
00159 archive & mPrintOutput;
00160 archive & mNodesToOutput;
00161
00162
00163
00164
00165
00166 archive & mpCardiacTissue;
00167
00168 bool has_solution = (mSolution != NULL);
00169 archive & has_solution;
00170 if (has_solution)
00171 {
00174 Hdf5DataWriter writer(*mpMesh->GetDistributedVectorFactory(), ArchiveLocationInfo::GetArchiveRelativePath(), "AbstractCardiacProblem_mSolution", false);
00175 writer.DefineFixedDimension(mpMesh->GetDistributedVectorFactory()->GetProblemSize());
00176 writer.DefineUnlimitedDimension("Time", "msec", 1);
00177
00178 int vm_col = writer.DefineVariable("Vm","mV");
00179
00180 if (PROBLEM_DIM==1)
00181 {
00182 writer.EndDefineMode();
00183 writer.PutUnlimitedVariable(0.0);
00184 writer.PutVector(vm_col, mSolution);
00185 }
00186
00187 if (PROBLEM_DIM==2)
00188 {
00189 int phie_col = writer.DefineVariable("Phie","mV");
00190 std::vector<int> variable_ids;
00191 variable_ids.push_back(vm_col);
00192 variable_ids.push_back(phie_col);
00193 writer.EndDefineMode();
00194 writer.PutUnlimitedVariable(0.0);
00195 writer.PutStripedVector(variable_ids, mSolution);
00196 }
00197
00198 writer.Close();
00199
00200 }
00201 archive & mCurrentTime;
00202
00203
00204 SaveBoundaryConditions(archive, mpMesh, mpBoundaryConditionsContainer);
00205 SaveBoundaryConditions(archive, mpMesh, mpDefaultBoundaryConditionsContainer);
00206
00207 if (version>= 3)
00208 {
00209 archive & mOutputModifiers;
00210 }
00211 }
00212
00219 template<class Archive>
00220 void load(Archive & archive, const unsigned int version)
00221 {
00222 if (version >= 1)
00223 {
00224 unsigned element_dim;
00225 unsigned space_dim;
00226 unsigned problem_dim;
00227 archive & element_dim;
00228 archive & space_dim;
00229 archive & problem_dim;
00230 if ( (element_dim != ELEMENT_DIM) ||(space_dim != SPACE_DIM) ||(problem_dim != PROBLEM_DIM) )
00231 {
00232
00233
00234
00235
00236
00237
00238 EXCEPTION("Failed to load from checkpoint because the dimensions of the archive do not match the object it's being read into.");
00239 }
00240 }
00241 archive & mMeshFilename;
00242 archive & mpMesh;
00243 assert(mpMesh != NULL);
00244
00245
00246 if (version < 2)
00247 {
00248 bool use_matrix_based_assembly;
00249 archive & use_matrix_based_assembly;
00250 }
00251
00252 archive & mWriteInfo;
00253 archive & mPrintOutput;
00254 archive & mNodesToOutput;
00255
00256
00257
00258
00259
00260 archive & mpCardiacTissue;
00261
00262 bool has_solution;
00263 archive & has_solution;
00264 if ((has_solution) && PROBLEM_DIM < 3)
00265 {
00268 mSolution = mpMesh->GetDistributedVectorFactory()->CreateVec(PROBLEM_DIM);
00269 DistributedVector mSolution_distri = mpMesh->GetDistributedVectorFactory()->CreateDistributedVector(mSolution);
00270
00271 Vec vm = mpMesh->GetDistributedVectorFactory()->CreateVec();
00272 Vec phie = mpMesh->GetDistributedVectorFactory()->CreateVec();
00273
00274 std::string archive_dir = ArchiveLocationInfo::GetArchiveRelativePath();
00275 Hdf5DataReader reader(archive_dir, "AbstractCardiacProblem_mSolution", !FileFinder::IsAbsolutePath(archive_dir));
00276 reader.GetVariableOverNodes(vm, "Vm", 0);
00277
00278 if (PROBLEM_DIM==1)
00279 {
00280
00281
00282 DistributedVector vm_distri = mpMesh->GetDistributedVectorFactory()->CreateDistributedVector(vm);
00283
00284 DistributedVector::Stripe mSolution_vm(mSolution_distri,0);
00285
00286 for (DistributedVector::Iterator index = mSolution_distri.Begin();
00287 index != mSolution_distri.End();
00288 ++index)
00289 {
00290 mSolution_vm[index] = vm_distri[index];
00291 }
00292 }
00293
00294 if (PROBLEM_DIM==2)
00295 {
00296 reader.GetVariableOverNodes(phie, "Phie", 0);
00297
00298
00299 DistributedVector vm_distri = mpMesh->GetDistributedVectorFactory()->CreateDistributedVector(vm);
00300 DistributedVector phie_distri = mpMesh->GetDistributedVectorFactory()->CreateDistributedVector(phie);
00301
00302 DistributedVector::Stripe mSolution_vm(mSolution_distri,0);
00303 DistributedVector::Stripe mSolution_phie(mSolution_distri,1);
00304
00305 for (DistributedVector::Iterator index = mSolution_distri.Begin();
00306 index != mSolution_distri.End();
00307 ++index)
00308 {
00309 mSolution_vm[index] = vm_distri[index];
00310 mSolution_phie[index] = phie_distri[index];
00311 }
00312 }
00313
00314 mSolution_distri.Restore();
00315
00316 PetscTools::Destroy(vm);
00317 PetscTools::Destroy(phie);
00318
00319 }
00320 archive & mCurrentTime;
00321
00322
00323 mpBoundaryConditionsContainer = LoadBoundaryConditions(archive, mpMesh);
00324 mpDefaultBoundaryConditionsContainer = LoadBoundaryConditions(archive, mpMesh);
00325
00326 if (version>= 3)
00327 {
00328 archive & mOutputModifiers;
00329 }
00330 }
00331
00332 BOOST_SERIALIZATION_SPLIT_MEMBER()
00333
00334
00341 template<class Archive>
00342 void SaveBoundaryConditions(Archive & archive,
00343 AbstractTetrahedralMesh<ELEMENT_DIM,SPACE_DIM>* pMesh,
00344 BccType pBcc) const
00345 {
00346 (*ProcessSpecificArchive<Archive>::Get()) & pBcc;
00347 }
00348
00356 template<class Archive>
00357 BccType LoadBoundaryConditions(
00358 Archive & archive,
00359 AbstractTetrahedralMesh<ELEMENT_DIM,SPACE_DIM>* pMesh)
00360 {
00361
00362 BccType p_bcc;
00363 (*ProcessSpecificArchive<Archive>::Get()) & p_bcc;
00364
00365
00366 if (p_bcc)
00367 {
00368 p_bcc->LoadFromArchive(*ProcessSpecificArchive<Archive>::Get(), pMesh);
00369 }
00370
00371 return p_bcc;
00372 }
00373
00374 protected:
00377 std::string mMeshFilename;
00378
00380 bool mAllocatedMemoryForMesh;
00382 bool mWriteInfo;
00384 bool mPrintOutput;
00385
00387 std::vector<unsigned> mNodesToOutput;
00388
00390 unsigned mVoltageColumnId;
00392 std::vector<unsigned> mExtraVariablesId;
00394 unsigned mTimeColumnId;
00396 unsigned mNodeColumnId;
00397
00399 AbstractCardiacTissue<ELEMENT_DIM,SPACE_DIM>* mpCardiacTissue;
00400
00402 BccType mpBoundaryConditionsContainer;
00404 BccType mpDefaultBoundaryConditionsContainer;
00406 AbstractDynamicLinearPdeSolver<ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM>* mpSolver;
00408 AbstractCardiacCellFactory<ELEMENT_DIM,SPACE_DIM>* mpCellFactory;
00410 AbstractTetrahedralMesh<ELEMENT_DIM,SPACE_DIM>* mpMesh;
00411
00414 Vec mSolution;
00415
00423 double mCurrentTime;
00424
00426 AbstractTimeAdaptivityController* mpTimeAdaptivityController;
00427
00428
00429
00436 virtual AbstractCardiacTissue<ELEMENT_DIM,SPACE_DIM>* CreateCardiacTissue() =0;
00437
00444 virtual AbstractDynamicLinearPdeSolver<ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM>* CreateSolver() =0;
00445
00453 virtual void CreateMeshFromHeartConfig();
00454
00458 template<unsigned DIM, unsigned ELEC_PROB_DIM>
00459 friend class CardiacElectroMechanicsProblem;
00460
00464 Hdf5DataWriter* mpWriter;
00465
00469 std::vector<boost::shared_ptr<AbstractOutputModifier> > mOutputModifiers;
00470
00471 public:
00477 AbstractCardiacProblem(AbstractCardiacCellFactory<ELEMENT_DIM,SPACE_DIM>* pCellFactory);
00478
00482 AbstractCardiacProblem();
00483
00487 virtual ~AbstractCardiacProblem();
00488
00496 void Initialise();
00497
00503 void SetNodesPerProcessorFilename(const std::string& rFilename);
00504
00509 void SetBoundaryConditionsContainer(BccType pBcc);
00510
00518 virtual void PreSolveChecks();
00519
00533 virtual Vec CreateInitialCondition();
00534
00540 void SetMesh(AbstractTetrahedralMesh<ELEMENT_DIM,SPACE_DIM>* pMesh);
00541
00547 void PrintOutput(bool rPrintOutput);
00548
00554 void SetWriteInfo(bool writeInfo = true);
00555
00566 Vec GetSolution();
00567
00573 DistributedVector GetSolutionDistributedVector();
00574
00578 double GetCurrentTime();
00579
00583 AbstractTetrahedralMesh<ELEMENT_DIM,SPACE_DIM> & rGetMesh();
00584
00588 AbstractCardiacTissue<ELEMENT_DIM,SPACE_DIM>* GetTissue();
00589
00599 void Solve();
00600
00608 void CloseFilesAndPostProcess();
00609
00617 virtual void WriteInfo(double time)=0;
00618
00623 virtual void DefineWriterColumns(bool extending);
00624
00629 void DefineExtraVariablesWriterColumns(bool extending);
00630
00637 virtual void WriteOneStep(double time, Vec voltageVec) = 0;
00638
00642 void WriteExtraVariablesOneStep();
00643
00654 bool InitialiseWriter();
00655
00665 void SetOutputNodes(std::vector<unsigned> & rNodesToOutput);
00666
00670 Hdf5DataReader GetDataReader();
00671
00679 virtual void AtBeginningOfTimestep(double time)
00680 {}
00681
00689 virtual void OnEndOfTimestep(double time)
00690 {}
00691
00699 virtual void SetUpAdditionalStoppingTimes(std::vector<double>& rAdditionalStoppingTimes)
00700 {}
00701
00702
00703
00705
00706
00712 void SetUseTimeAdaptivityController(bool useAdaptivity,
00713 AbstractTimeAdaptivityController* pController = NULL);
00714
00735 template<class Archive>
00736 void LoadExtraArchive(Archive & archive, unsigned version);
00737
00741 virtual bool GetHasBath();
00742
00747 virtual void SetElectrodes();
00748
00754 void AddOutputModifier( boost::shared_ptr<AbstractOutputModifier> pOutputModifier)
00755 {
00756 mOutputModifiers.push_back(pOutputModifier);
00757 }
00758 };
00759
00760 TEMPLATED_CLASS_IS_ABSTRACT_3_UNSIGNED(AbstractCardiacProblem)
00761
00762
00763 template<unsigned DIM>
00764 class BidomainProblem;
00765
00766 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
00767 template<class Archive>
00768 void AbstractCardiacProblem<ELEMENT_DIM,SPACE_DIM,PROBLEM_DIM>::LoadExtraArchive(Archive & archive, unsigned version)
00769 {
00770
00771 DistributedVectorFactory* p_mesh_factory;
00772 archive >> p_mesh_factory;
00773
00774
00775 DistributedVectorFactory* p_original_factory = p_mesh_factory->GetOriginalFactory();
00776 unsigned orig_num_procs = 1;
00777 if (p_original_factory)
00778 {
00779 orig_num_procs = p_original_factory->GetNumProcs();
00780 }
00781
00782
00783 mpCardiacTissue->LoadCardiacCells(archive, version);
00784
00785 {
00786 DistributedVectorFactory* p_pde_factory;
00787 archive >> p_pde_factory;
00788 assert(p_pde_factory == p_mesh_factory);
00789 }
00790
00791 delete p_mesh_factory;
00792
00793
00794 BccType p_bcc;
00795 archive >> p_bcc;
00796 if (p_bcc)
00797 {
00798 if (!mpBoundaryConditionsContainer)
00799 {
00800 mpBoundaryConditionsContainer = p_bcc;
00801 mpBoundaryConditionsContainer->LoadFromArchive(archive, mpMesh);
00802 }
00803 else
00804 {
00805
00806
00807 #define COVERAGE_IGNORE
00808 if(!dynamic_cast<DistributedTetrahedralMesh<ELEMENT_DIM,SPACE_DIM>*>(mpMesh) && orig_num_procs > 1)
00809 {
00810
00811
00812 WARNING("Loading from a parallel archive which used a non-distributed mesh. This scenario should work but is not fully tested.");
00813 }
00814 #undef COVERAGE_IGNORE
00815 mpBoundaryConditionsContainer->MergeFromArchive(archive, mpMesh);
00816 }
00817 }
00818 BccType p_default_bcc;
00819 archive >> p_default_bcc;
00820 if (p_default_bcc)
00821 {
00822
00823 assert(p_bcc == p_default_bcc);
00824 }
00825
00826
00827 BidomainProblem<ELEMENT_DIM>* p_bidomain_problem = dynamic_cast<BidomainProblem<ELEMENT_DIM>*>(this);
00828 if (p_bidomain_problem)
00829 {
00830 assert(ELEMENT_DIM == SPACE_DIM);
00831 p_bidomain_problem->LoadExtraArchiveForBidomain(archive, version);
00832 }
00833 }
00834
00835 namespace boost {
00836 namespace serialization {
00843 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
00844 struct version<AbstractCardiacProblem<ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM> >
00845 {
00847 CHASTE_VERSION_CONTENT(3);
00848 };
00849 }
00850 }
00851 #endif