AbstractCardiacTissue.hpp
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 #ifndef ABSTRACTCARDIACTISSUE_HPP_
00036 #define ABSTRACTCARDIACTISSUE_HPP_
00037
00038 #include <set>
00039 #include <vector>
00040 #include <boost/shared_ptr.hpp>
00041
00042 #include "UblasMatrixInclude.hpp"
00043
00044 #include "ChasteSerialization.hpp"
00045 #include "ClassIsAbstract.hpp"
00046 #include "ChasteSerializationVersion.hpp"
00047 #include <boost/serialization/base_object.hpp>
00048 #include <boost/serialization/shared_ptr.hpp>
00049 #include <boost/serialization/vector.hpp>
00050 #include <boost/serialization/string.hpp>
00051 #include <boost/serialization/split_member.hpp>
00052
00053 #include "AbstractCardiacCellInterface.hpp"
00054 #include "FakeBathCell.hpp"
00055 #include "AbstractCardiacCellFactory.hpp"
00056 #include "AbstractConductivityTensors.hpp"
00057 #include "AbstractPurkinjeCellFactory.hpp"
00058 #include "ReplicatableVector.hpp"
00059 #include "HeartConfig.hpp"
00060 #include "ArchiveLocationInfo.hpp"
00061 #include "AbstractDynamicallyLoadableEntity.hpp"
00062 #include "DynamicModelLoaderRegistry.hpp"
00063 #include "AbstractConductivityModifier.hpp"
00064
00077 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM = ELEMENT_DIM>
00078 class AbstractCardiacTissue : private boost::noncopyable
00079 {
00080 private:
00081
00083 friend class boost::serialization::access;
00084 friend class TestMonodomainTissue;
00085
00092 template<class Archive>
00093 void save(Archive & archive, const unsigned int version) const
00094 {
00095 if (version >= 3)
00096 {
00097 archive & mHasPurkinje;
00098 }
00099 if (version >= 2)
00100 {
00101 archive & mExchangeHalos;
00102 }
00103
00104
00105 SaveCardiacCells(*ProcessSpecificArchive<Archive>::Get(), version);
00106
00107
00108
00109 if (HeartConfig::Instance()->IsMeshProvided() && HeartConfig::Instance()->GetLoadMesh())
00110 {
00111 switch (HeartConfig::Instance()->GetConductivityMedia())
00112 {
00113 case cp::media_type::Orthotropic:
00114 {
00115 FileFinder source_file(mFibreFilePathNoExtension + ".ortho", RelativeTo::AbsoluteOrCwd);
00116 assert(source_file.Exists());
00117 FileFinder dest_file(ArchiveLocationInfo::GetArchiveRelativePath() + ArchiveLocationInfo::GetMeshFilename() + ".ortho", RelativeTo::ChasteTestOutput);
00118
00119 TRY_IF_MASTER(source_file.CopyTo(dest_file));
00120 break;
00121 }
00122
00123 case cp::media_type::Axisymmetric:
00124 {
00125 FileFinder source_file(mFibreFilePathNoExtension + ".axi", RelativeTo::AbsoluteOrCwd);
00126 assert(source_file.Exists());
00127 FileFinder dest_file(ArchiveLocationInfo::GetArchiveRelativePath()
00128 + ArchiveLocationInfo::GetMeshFilename() + ".axi", RelativeTo::ChasteTestOutput);
00129
00130 TRY_IF_MASTER(source_file.CopyTo(dest_file));
00131 break;
00132 }
00133
00134 case cp::media_type::NoFibreOrientation:
00135 break;
00136
00137 default :
00138 NEVER_REACHED;
00139 }
00140 }
00141
00142
00143
00144 archive & mDoCacheReplication;
00145
00146
00147 (*ProcessSpecificArchive<Archive>::Get()) & mpDistributedVectorFactory;
00148
00149
00150 assert(mpDistributedVectorFactory == mpMesh->GetDistributedVectorFactory());
00151 assert(mpDistributedVectorFactory->GetLow()==mpMesh->GetDistributedVectorFactory()->GetLow());
00152 assert(mpDistributedVectorFactory->GetLocalOwnership()==mpMesh->GetDistributedVectorFactory()->GetLocalOwnership());
00153 }
00154
00161 template<class Archive>
00162 void load(Archive & archive, const unsigned int version)
00163 {
00164
00165
00166
00167 if (version >= 3)
00168 {
00169 archive & mHasPurkinje;
00170 if (mHasPurkinje)
00171 {
00172 mPurkinjeIionicCacheReplicated.Resize(mpDistributedVectorFactory->GetProblemSize());
00173 }
00174 }
00175 if (version >= 2)
00176 {
00177 archive & mExchangeHalos;
00178 if (mExchangeHalos)
00179 {
00180 mpMesh->CalculateNodeExchange(mNodesToSendPerProcess, mNodesToReceivePerProcess);
00181 CalculateHaloNodesFromNodeExchange();
00182 unsigned num_halo_nodes = mHaloNodes.size();
00183 mHaloCellsDistributed.resize( num_halo_nodes );
00184 for (unsigned local_index = 0; local_index < num_halo_nodes; local_index++)
00185 {
00186 unsigned global_index = mHaloNodes[local_index];
00187 mHaloGlobalToLocalIndexMap[global_index] = local_index;
00188 }
00189 }
00190 }
00191
00192
00193 LoadCardiacCells(*ProcessSpecificArchive<Archive>::Get(), version);
00194
00195
00196
00197 archive & mDoCacheReplication;
00198
00199
00200
00201 if (version==0)
00202 {
00203 bool do_one_cache_replication = true;
00204 archive & do_one_cache_replication;
00205 }
00206
00207 (*ProcessSpecificArchive<Archive>::Get()) & mpDistributedVectorFactory;
00208
00209
00210 assert(mpDistributedVectorFactory == mpMesh->GetDistributedVectorFactory());
00211 assert(mpDistributedVectorFactory->GetLow()==mpMesh->GetDistributedVectorFactory()->GetLow());
00212 assert(mpDistributedVectorFactory->GetLocalOwnership()==mpMesh->GetDistributedVectorFactory()->GetLocalOwnership());
00213
00214
00215
00216
00217 mpConductivityModifier = NULL;
00218 }
00219 BOOST_SERIALIZATION_SPLIT_MEMBER()
00220
00221
00224 void CreateIntracellularConductivityTensor();
00225
00226 protected:
00227
00229 AbstractTetrahedralMesh<ELEMENT_DIM,SPACE_DIM>* mpMesh;
00230
00233 AbstractConductivityTensors<ELEMENT_DIM,SPACE_DIM>* mpIntracellularConductivityTensors;
00234
00236 std::vector< AbstractCardiacCellInterface* > mCellsDistributed;
00237
00239 std::vector< AbstractCardiacCellInterface* > mPurkinjeCellsDistributed;
00240
00245 ReplicatableVector mIionicCacheReplicated;
00246
00251 ReplicatableVector mPurkinjeIionicCacheReplicated;
00252
00257 ReplicatableVector mIntracellularStimulusCacheReplicated;
00258
00263 ReplicatableVector mPurkinjeIntracellularStimulusCacheReplicated;
00264
00266 HeartConfig* mpConfig;
00267
00276 DistributedVectorFactory* mpDistributedVectorFactory;
00277
00281 std::string mFibreFilePathNoExtension;
00282
00288 AbstractConductivityModifier<ELEMENT_DIM,SPACE_DIM>* mpConductivityModifier;
00289
00291 bool mHasPurkinje;
00292
00302 bool mDoCacheReplication;
00303
00307 bool mMeshUnarchived;
00308
00313 bool mExchangeHalos;
00314
00316 std::vector<unsigned> mHaloNodes;
00317
00319 std::vector< AbstractCardiacCellInterface* > mHaloCellsDistributed;
00320
00322 std::map<unsigned, unsigned> mHaloGlobalToLocalIndexMap;
00323
00329 std::vector<std::vector<unsigned> > mNodesToSendPerProcess;
00330
00335 std::vector<std::vector<unsigned> > mNodesToReceivePerProcess;
00336
00342 void CalculateHaloNodesFromNodeExchange();
00343
00350 void SetUpHaloCells(AbstractCardiacCellFactory<ELEMENT_DIM,SPACE_DIM>* pCellFactory);
00351
00352 public:
00363 AbstractCardiacTissue(AbstractCardiacCellFactory<ELEMENT_DIM,SPACE_DIM>* pCellFactory, bool exchangeHalos=false);
00364
00370 AbstractCardiacTissue(AbstractTetrahedralMesh<ELEMENT_DIM,SPACE_DIM>* pMesh);
00371
00373 virtual ~AbstractCardiacTissue();
00374
00376 bool HasPurkinje();
00377
00384 void SetCacheReplication(bool doCacheReplication);
00385
00391 bool GetDoCacheReplication();
00392
00396 const c_matrix<double, SPACE_DIM, SPACE_DIM>& rGetIntracellularConductivityTensor(unsigned elementIndex);
00397
00405 virtual const c_matrix<double, SPACE_DIM, SPACE_DIM>& rGetExtracellularConductivityTensor(unsigned elementIndex);
00406
00415 AbstractCardiacCellInterface* GetCardiacCell( unsigned globalIndex );
00416
00425 AbstractCardiacCellInterface* GetPurkinjeCell( unsigned globalIndex );
00426
00435 AbstractCardiacCellInterface* GetCardiacCellOrHaloCell( unsigned globalIndex );
00436
00446 virtual void SolveCellSystems(Vec existingSolution, double time, double nextTime, bool updateVoltage=false);
00447
00449 ReplicatableVector& rGetIionicCacheReplicated();
00450
00452 ReplicatableVector& rGetIntracellularStimulusCacheReplicated();
00453
00455 ReplicatableVector& rGetPurkinjeIionicCacheReplicated();
00456
00458 ReplicatableVector& rGetPurkinjeIntracellularStimulusCacheReplicated();
00459
00460
00468 void UpdateCaches(unsigned globalIndex, unsigned localIndex, double nextTime);
00469
00477 void UpdatePurkinjeCaches(unsigned globalIndex, unsigned localIndex, double nextTime);
00478
00482 void ReplicateCaches();
00483
00487 const std::vector<AbstractCardiacCellInterface*>& rGetCellsDistributed() const;
00488
00492 const std::vector<AbstractCardiacCellInterface*>& rGetPurkinjeCellsDistributed() const;
00493
00499 const AbstractTetrahedralMesh<ELEMENT_DIM,SPACE_DIM>* pGetMesh() const;
00500
00506 void SetConductivityModifier(AbstractConductivityModifier<ELEMENT_DIM,SPACE_DIM>* pModifier);
00507
00519 template<class Archive>
00520 void SaveCardiacCells(Archive & archive, const unsigned int version) const
00521 {
00522 const std::vector<AbstractCardiacCellInterface*> & r_cells_distributed = rGetCellsDistributed();
00523 assert(mpDistributedVectorFactory == this->mpMesh->GetDistributedVectorFactory());
00524 archive & mpDistributedVectorFactory;
00525 const unsigned num_cells = r_cells_distributed.size();
00526 archive & num_cells;
00527 for (unsigned i=0; i<num_cells; i++)
00528 {
00529 AbstractDynamicallyLoadableEntity* p_entity = dynamic_cast<AbstractDynamicallyLoadableEntity*>(r_cells_distributed[i]);
00530 bool is_dynamic = (p_entity != NULL);
00531 archive & is_dynamic;
00532 if (is_dynamic)
00533 {
00534 #ifdef CHASTE_CAN_CHECKPOINT_DLLS
00535 archive & p_entity->GetLoader()->GetLoadableModulePath();
00536 #else
00537
00538 NEVER_REACHED;
00539 #endif // CHASTE_CAN_CHECKPOINT_DLLS
00540 }
00541 archive & r_cells_distributed[i];
00542 if (mHasPurkinje)
00543 {
00544 archive & rGetPurkinjeCellsDistributed()[i];
00545 }
00546 }
00547 }
00548
00561 template<class Archive>
00562 void LoadCardiacCells(Archive & archive, const unsigned int version)
00563 {
00564
00565
00566
00567
00568
00569 DistributedVectorFactory* p_factory;
00570 DistributedVectorFactory* p_mesh_factory = this->mpMesh->GetDistributedVectorFactory();
00571 archive & p_factory;
00572 unsigned num_cells;
00573 archive & num_cells;
00574 if (mCellsDistributed.empty())
00575 {
00576 mCellsDistributed.resize(p_mesh_factory->GetLocalOwnership());
00577 #ifndef NDEBUG
00578
00579 for (unsigned i=0; i<mCellsDistributed.size(); i++)
00580 {
00581 assert(mCellsDistributed[i] == NULL);
00582 }
00583 #endif
00584 }
00585 else
00586 {
00587 assert(mCellsDistributed.size() == p_mesh_factory->GetLocalOwnership());
00588 }
00589 if (mHasPurkinje)
00590 {
00591 if (mPurkinjeCellsDistributed.empty())
00592 {
00593 mPurkinjeCellsDistributed.resize(p_mesh_factory->GetLocalOwnership());
00594 }
00595 else
00596 {
00597 assert(mPurkinjeCellsDistributed.size() == p_mesh_factory->GetLocalOwnership());
00598 }
00599 }
00600
00601
00602
00603 unsigned index_low = p_factory->GetOriginalFactory() ? p_factory->GetOriginalFactory()->GetLow() : p_mesh_factory->GetLow();
00604
00605
00606 std::set<FakeBathCell*> fake_cells_non_local, fake_cells_local;
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621 for (unsigned local_index=0; local_index<num_cells; local_index++)
00622 {
00623
00624 unsigned global_index = index_low + local_index;
00625 bool local = p_mesh_factory->IsGlobalIndexLocal(global_index);
00626
00627
00628 std::map<unsigned, unsigned>::const_iterator halo_position;
00629 bool halo = ((halo_position=mHaloGlobalToLocalIndexMap.find(global_index)) != mHaloGlobalToLocalIndexMap.end());
00630
00631
00632 bool is_dynamic;
00633 archive & is_dynamic;
00634 if (is_dynamic)
00635 {
00636 #ifdef CHASTE_CAN_CHECKPOINT_DLLS
00637
00638
00639
00640 std::string shared_object_path;
00641 archive & shared_object_path;
00642 DynamicModelLoaderRegistry::Instance()->GetLoader(shared_object_path);
00643 #else
00644
00645
00646
00647 NEVER_REACHED;
00648 #endif // CHASTE_CAN_CHECKPOINT_DLLS
00649 }
00650 AbstractCardiacCellInterface* p_cell;
00651 archive & p_cell;
00652 AbstractCardiacCellInterface* p_purkinje_cell = NULL;
00653 if (mHasPurkinje)
00654 {
00655 archive & p_purkinje_cell;
00656 }
00657
00658 FakeBathCell* p_fake = dynamic_cast<FakeBathCell*>(p_cell);
00659 if (p_fake)
00660 {
00661 if (halo || local)
00662 {
00663 fake_cells_local.insert(p_fake);
00664 }
00665 else
00666 {
00667 fake_cells_non_local.insert(p_fake);
00668 }
00669 }
00670 FakeBathCell* p_fake_purkinje = dynamic_cast<FakeBathCell*>(p_purkinje_cell);
00671 if (p_fake_purkinje)
00672 {
00673 if (halo || local)
00674 {
00675 fake_cells_local.insert(p_fake_purkinje);
00676 }
00677 else
00678 {
00679 fake_cells_non_local.insert(p_fake_purkinje);
00680 }
00681 }
00682
00683 if (local)
00684 {
00685
00686
00687 unsigned new_local_index = global_index - p_mesh_factory->GetLow();
00688 assert(mCellsDistributed[new_local_index] == NULL);
00689 mCellsDistributed[new_local_index] = p_cell;
00690 if (mHasPurkinje)
00691 {
00692 assert(mPurkinjeCellsDistributed[new_local_index] == NULL);
00693 mPurkinjeCellsDistributed[new_local_index] = p_purkinje_cell;
00694 }
00695 }
00696 else if (halo)
00697 {
00698 assert(mHaloCellsDistributed[halo_position->second] == NULL);
00699 mHaloCellsDistributed[halo_position->second] = p_cell;
00700 }
00701 else
00702 {
00703 if (!p_fake)
00704 {
00705
00706 delete p_cell;
00707 }
00708 if (!p_fake_purkinje)
00709 {
00710
00711 delete p_purkinje_cell;
00712 }
00713 }
00714 }
00715
00716
00717 for (std::set<FakeBathCell*>::iterator it = fake_cells_non_local.begin();
00718 it != fake_cells_non_local.end();
00719 ++it)
00720 {
00721 if (fake_cells_local.find(*it) == fake_cells_local.end())
00722 {
00723 delete (*it);
00724 }
00725 }
00726 }
00727 };
00728
00729 TEMPLATED_CLASS_IS_ABSTRACT_2_UNSIGNED(AbstractCardiacTissue)
00730
00731 namespace boost {
00732 namespace serialization {
00739 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00740 struct version<AbstractCardiacTissue<ELEMENT_DIM, SPACE_DIM> >
00741 {
00743 CHASTE_VERSION_CONTENT(3);
00744 };
00745 }
00746 }
00747
00748 #endif
00749