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 #ifndef ABSTRACTCARDIACTISSUE_HPP_
00029 #define ABSTRACTCARDIACTISSUE_HPP_
00030
00031 #include <set>
00032 #include <vector>
00033 #include <boost/shared_ptr.hpp>
00034
00035 #include "UblasMatrixInclude.hpp"
00036
00037 #include "ChasteSerialization.hpp"
00038 #include "ClassIsAbstract.hpp"
00039 #include "ChasteSerializationVersion.hpp"
00040 #include <boost/serialization/base_object.hpp>
00041 #include <boost/serialization/shared_ptr.hpp>
00042 #include <boost/serialization/vector.hpp>
00043 #include <boost/serialization/string.hpp>
00044 #include <boost/serialization/split_member.hpp>
00045
00046 #include "AbstractCardiacCell.hpp"
00047 #include "FakeBathCell.hpp"
00048 #include "AbstractCardiacCellFactory.hpp"
00049 #include "AbstractConductivityTensors.hpp"
00050 #include "AbstractPurkinjeCellFactory.hpp"
00051 #include "ReplicatableVector.hpp"
00052 #include "HeartConfig.hpp"
00053 #include "ArchiveLocationInfo.hpp"
00054 #include "AbstractDynamicallyLoadableEntity.hpp"
00055 #include "DynamicModelLoaderRegistry.hpp"
00056 #include "AbstractConductivityModifier.hpp"
00057
00070 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM = ELEMENT_DIM>
00071 class AbstractCardiacTissue : boost::noncopyable
00072 {
00073 private:
00074
00076 friend class boost::serialization::access;
00077 friend class TestMonodomainTissue;
00078
00085 template<class Archive>
00086 void save(Archive & archive, const unsigned int version) const
00087 {
00088 if (version >= 3)
00089 {
00090 archive & mHasPurkinje;
00091 }
00092 if (version >= 2)
00093 {
00094 archive & mExchangeHalos;
00095 }
00096
00097
00098 SaveCardiacCells(*ProcessSpecificArchive<Archive>::Get(), version);
00099
00100
00101
00102 if (HeartConfig::Instance()->IsMeshProvided() && HeartConfig::Instance()->GetLoadMesh())
00103 {
00104 switch (HeartConfig::Instance()->GetConductivityMedia())
00105 {
00106 case cp::media_type::Orthotropic:
00107 {
00108 FileFinder source_file(mFibreFilePathNoExtension + ".ortho", RelativeTo::AbsoluteOrCwd);
00109 assert(source_file.Exists());
00110 FileFinder dest_file(ArchiveLocationInfo::GetArchiveRelativePath() + ArchiveLocationInfo::GetMeshFilename() + ".ortho", RelativeTo::ChasteTestOutput);
00111
00112 if (PetscTools::AmMaster())
00113 {
00114 ABORT_IF_NON0(system,"cp " + source_file.GetAbsolutePath() + " " + dest_file.GetAbsolutePath());
00115 }
00116 PetscTools::Barrier();
00117 break;
00118 }
00119
00120 case cp::media_type::Axisymmetric:
00121 {
00122 FileFinder source_file(mFibreFilePathNoExtension + ".axi", RelativeTo::AbsoluteOrCwd);
00123 assert(source_file.Exists());
00124 FileFinder dest_file(ArchiveLocationInfo::GetArchiveRelativePath() + ArchiveLocationInfo::GetMeshFilename() + ".axi", RelativeTo::ChasteTestOutput);
00125
00126 if (PetscTools::AmMaster())
00127 {
00128 ABORT_IF_NON0(system,"cp " + source_file.GetAbsolutePath() + " " + dest_file.GetAbsolutePath());
00129 }
00130 PetscTools::Barrier();
00131
00132 break;
00133 }
00134
00135 case cp::media_type::NoFibreOrientation:
00136 break;
00137
00138 default :
00139 NEVER_REACHED;
00140 }
00141 }
00142
00143
00144
00145 archive & mDoCacheReplication;
00146
00147
00148 (*ProcessSpecificArchive<Archive>::Get()) & mpDistributedVectorFactory;
00149
00150
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->GetLow()==mpMesh->GetDistributedVectorFactory()->GetLow());
00211 assert(mpDistributedVectorFactory->GetLocalOwnership()==mpMesh->GetDistributedVectorFactory()->GetLocalOwnership());
00212
00213
00214
00215
00216 mpConductivityModifier = NULL;
00217 }
00218 BOOST_SERIALIZATION_SPLIT_MEMBER()
00219
00220
00223 void CreateIntracellularConductivityTensor();
00224
00225 protected:
00226
00228 AbstractTetrahedralMesh<ELEMENT_DIM,SPACE_DIM>* mpMesh;
00229
00232 AbstractConductivityTensors<ELEMENT_DIM,SPACE_DIM>* mpIntracellularConductivityTensors;
00233
00235 std::vector< AbstractCardiacCell* > mCellsDistributed;
00236
00238 std::vector< AbstractCardiacCell* > mPurkinjeCellsDistributed;
00239
00244 ReplicatableVector mIionicCacheReplicated;
00245
00250 ReplicatableVector mPurkinjeIionicCacheReplicated;
00251
00256 ReplicatableVector mIntracellularStimulusCacheReplicated;
00257
00259 HeartConfig* mpConfig;
00260
00269 DistributedVectorFactory* mpDistributedVectorFactory;
00270
00274 std::string mFibreFilePathNoExtension;
00275
00281 AbstractConductivityModifier<ELEMENT_DIM,SPACE_DIM>* mpConductivityModifier;
00282
00284 bool mHasPurkinje;
00285
00295 bool mDoCacheReplication;
00296
00300 bool mMeshUnarchived;
00301
00306 bool mExchangeHalos;
00307
00309 std::vector<unsigned> mHaloNodes;
00310
00312 std::vector< AbstractCardiacCell* > mHaloCellsDistributed;
00313
00315 std::map<unsigned, unsigned> mHaloGlobalToLocalIndexMap;
00316
00322 std::vector<std::vector<unsigned> > mNodesToSendPerProcess;
00323
00328 std::vector<std::vector<unsigned> > mNodesToReceivePerProcess;
00329
00335 void CalculateHaloNodesFromNodeExchange();
00336
00343 void SetUpHaloCells(AbstractCardiacCellFactory<ELEMENT_DIM,SPACE_DIM>* pCellFactory);
00344
00345 public:
00356 AbstractCardiacTissue(AbstractCardiacCellFactory<ELEMENT_DIM,SPACE_DIM>* pCellFactory, bool exchangeHalos=false);
00357
00363 AbstractCardiacTissue(AbstractTetrahedralMesh<ELEMENT_DIM,SPACE_DIM>* pMesh);
00364
00366 virtual ~AbstractCardiacTissue();
00367
00369 bool HasPurkinje();
00370
00377 void SetCacheReplication(bool doCacheReplication);
00378
00384 bool GetDoCacheReplication();
00385
00389 const c_matrix<double, SPACE_DIM, SPACE_DIM>& rGetIntracellularConductivityTensor(unsigned elementIndex);
00390
00398 virtual const c_matrix<double, SPACE_DIM, SPACE_DIM>& rGetExtracellularConductivityTensor(unsigned elementIndex);
00399
00408 AbstractCardiacCell* GetCardiacCell( unsigned globalIndex );
00409
00418 AbstractCardiacCell* GetPurkinjeCell( unsigned globalIndex );
00419
00428 AbstractCardiacCell* GetCardiacCellOrHaloCell( unsigned globalIndex );
00429
00439 virtual void SolveCellSystems(Vec existingSolution, double time, double nextTime, bool updateVoltage=false);
00440
00442 ReplicatableVector& rGetIionicCacheReplicated();
00443
00445 ReplicatableVector& rGetIntracellularStimulusCacheReplicated();
00446
00448 ReplicatableVector& rGetPurkinjeIionicCacheReplicated();
00449
00450
00458 void UpdateCaches(unsigned globalIndex, unsigned localIndex, double nextTime);
00459
00463 void ReplicateCaches();
00464
00468 const std::vector<AbstractCardiacCell*>& rGetCellsDistributed() const;
00469
00473 const std::vector<AbstractCardiacCell*>& rGetPurkinjeCellsDistributed() const;
00474
00480 const AbstractTetrahedralMesh<ELEMENT_DIM,SPACE_DIM>* pGetMesh() const;
00481
00487 void SetConductivityModifier(AbstractConductivityModifier<ELEMENT_DIM,SPACE_DIM>* pModifier);
00488
00500 template<class Archive>
00501 void SaveCardiacCells(Archive & archive, const unsigned int version) const
00502 {
00503 const std::vector<AbstractCardiacCell*> & r_cells_distributed = rGetCellsDistributed();
00504 archive & mpDistributedVectorFactory;
00505 const unsigned num_cells = r_cells_distributed.size();
00506 archive & num_cells;
00507 for (unsigned i=0; i<num_cells; i++)
00508 {
00509 AbstractDynamicallyLoadableEntity* p_entity = dynamic_cast<AbstractDynamicallyLoadableEntity*>(r_cells_distributed[i]);
00510 bool is_dynamic = (p_entity != NULL);
00511 archive & is_dynamic;
00512 if (is_dynamic)
00513 {
00514 #ifdef CHASTE_CAN_CHECKPOINT_DLLS
00515 archive & p_entity->GetLoader()->GetLoadableModulePath();
00516 #else
00517
00518 NEVER_REACHED;
00519 #endif // CHASTE_CAN_CHECKPOINT_DLLS
00520 }
00521 archive & r_cells_distributed[i];
00522 if (mHasPurkinje)
00523 {
00524 archive & rGetPurkinjeCellsDistributed()[i];
00525 }
00526 }
00527 }
00528
00541 template<class Archive>
00542 void LoadCardiacCells(Archive & archive, const unsigned int version)
00543 {
00544 DistributedVectorFactory* p_factory;
00545 DistributedVectorFactory* p_mesh_factory = this->mpMesh->GetDistributedVectorFactory();
00546 archive & p_factory;
00547 unsigned num_cells;
00548 archive & num_cells;
00549 if (mCellsDistributed.empty())
00550 {
00551 mCellsDistributed.resize(p_factory->GetLocalOwnership());
00552 #ifndef NDEBUG
00553
00554 for (unsigned i=0; i<mCellsDistributed.size(); i++)
00555 {
00556 assert(mCellsDistributed[i] == NULL);
00557 }
00558 #endif
00559 }
00560 else
00561 {
00562 assert(mCellsDistributed.size() == p_mesh_factory->GetLocalOwnership());
00563 }
00564 if (mHasPurkinje)
00565 {
00566 if (mPurkinjeCellsDistributed.empty())
00567 {
00568 mPurkinjeCellsDistributed.resize(p_factory->GetLocalOwnership());
00569 }
00570 else
00571 {
00572 assert(mPurkinjeCellsDistributed.size() == p_mesh_factory->GetLocalOwnership());
00573 }
00574 }
00575
00576
00577
00578 unsigned index_low = p_factory->GetOriginalFactory() ? p_factory->GetOriginalFactory()->GetLow() : p_mesh_factory->GetLow();
00579
00580
00581 std::set<FakeBathCell*> fake_cells_non_local, fake_cells_local;
00582
00583 const std::vector<unsigned>& r_permutation = this->mpMesh->rGetNodePermutation();
00584 for (unsigned local_index=0; local_index<num_cells; local_index++)
00585 {
00586
00587 unsigned original_global_index = index_low + local_index;
00588 unsigned new_global_index;
00589 if (r_permutation.empty())
00590 {
00591 new_global_index = original_global_index;
00592 }
00593 else
00594 {
00596
00597 NEVER_REACHED;
00598 }
00599 unsigned new_local_index = new_global_index - p_mesh_factory->GetLow();
00600 bool local = p_mesh_factory->IsGlobalIndexLocal(new_global_index);
00601
00602
00603 std::map<unsigned, unsigned>::const_iterator halo_position;
00604 bool halo = ((halo_position=mHaloGlobalToLocalIndexMap.find(new_global_index)) != mHaloGlobalToLocalIndexMap.end());
00605
00606
00607 bool is_dynamic;
00608 archive & is_dynamic;
00609 if (is_dynamic)
00610 {
00611 #ifdef CHASTE_CAN_CHECKPOINT_DLLS
00612
00613
00614
00615 std::string shared_object_path;
00616 archive & shared_object_path;
00617 DynamicModelLoaderRegistry::Instance()->GetLoader(shared_object_path);
00618 #else
00619
00620
00621
00622 NEVER_REACHED;
00623 #endif // CHASTE_CAN_CHECKPOINT_DLLS
00624 }
00625 AbstractCardiacCell* p_cell;
00626 archive & p_cell;
00627 AbstractCardiacCell* p_purkinje_cell = NULL;
00628 if (mHasPurkinje)
00629 {
00630 archive & p_purkinje_cell;
00631 }
00632
00633 FakeBathCell* p_fake = dynamic_cast<FakeBathCell*>(p_cell);
00634 if (p_fake)
00635 {
00636 if (halo || local)
00637 {
00638 fake_cells_local.insert(p_fake);
00639 }
00640 else
00641 {
00642 fake_cells_non_local.insert(p_fake);
00643 }
00644 }
00645 FakeBathCell* p_fake_purkinje = dynamic_cast<FakeBathCell*>(p_purkinje_cell);
00646 if (p_fake_purkinje)
00647 {
00648 if (halo || local)
00649 {
00650 fake_cells_local.insert(p_fake_purkinje);
00651 }
00652 else
00653 {
00654 fake_cells_non_local.insert(p_fake_purkinje);
00655 }
00656 }
00657
00658 if (local)
00659 {
00660 assert(mCellsDistributed[new_local_index] == NULL);
00661 mCellsDistributed[new_local_index] = p_cell;
00662 if (mHasPurkinje)
00663 {
00664 assert(mPurkinjeCellsDistributed[new_local_index] == NULL);
00665 mPurkinjeCellsDistributed[new_local_index] = p_purkinje_cell;
00666 }
00667 }
00668 else if (halo)
00669 {
00670 assert(mHaloCellsDistributed[halo_position->second] == NULL);
00671 mHaloCellsDistributed[halo_position->second] = p_cell;
00672 if (mHasPurkinje)
00673 {
00675 NEVER_REACHED;
00676 }
00677 }
00678 else
00679 {
00680 if (!p_fake)
00681 {
00682
00683 delete p_cell;
00684 }
00685 if (!p_fake_purkinje)
00686 {
00687
00688 delete p_purkinje_cell;
00689 }
00690 }
00691 }
00692
00693
00694 for (std::set<FakeBathCell*>::iterator it = fake_cells_non_local.begin();
00695 it != fake_cells_non_local.end();
00696 ++it)
00697 {
00698 if (fake_cells_local.find(*it) == fake_cells_local.end())
00699 {
00700 delete (*it);
00701 }
00702 }
00703 }
00704 };
00705
00706 TEMPLATED_CLASS_IS_ABSTRACT_2_UNSIGNED(AbstractCardiacTissue)
00707
00708 namespace boost {
00709 namespace serialization {
00716 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00717 struct version<AbstractCardiacTissue<ELEMENT_DIM, SPACE_DIM> >
00718 {
00720 CHASTE_VERSION_CONTENT(3);
00721 };
00722 }
00723 }
00724
00725 #endif
00726