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 "ChasteSerialization.hpp"
00034 #include "ClassIsAbstract.hpp"
00035 #include <boost/serialization/base_object.hpp>
00036 #include <boost/shared_ptr.hpp>
00037 #include <boost/serialization/shared_ptr.hpp>
00038 #include <boost/serialization/vector.hpp>
00039 #include <boost/serialization/string.hpp>
00040 #include <boost/numeric/ublas/matrix.hpp>
00041 #include <boost/serialization/version.hpp>
00042 #include <boost/serialization/split_member.hpp>
00043
00044 #include "AbstractCardiacCell.hpp"
00045 #include "FakeBathCell.hpp"
00046 #include "AbstractCardiacCellFactory.hpp"
00047 #include "AbstractConductivityTensors.hpp"
00048
00049 #include "ReplicatableVector.hpp"
00050 #include "HeartConfig.hpp"
00051 #include "ArchiveLocationInfo.hpp"
00052 #include "AbstractDynamicallyLoadableEntity.hpp"
00053 #include "DynamicModelLoaderRegistry.hpp"
00054
00067 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM = ELEMENT_DIM>
00068 class AbstractCardiacTissue : boost::noncopyable
00069 {
00070 private:
00071
00073 friend class boost::serialization::access;
00080 template<class Archive>
00081 void save(Archive & archive, const unsigned int version) const
00082 {
00083
00084
00085 if (HeartConfig::Instance()->IsMeshProvided() && HeartConfig::Instance()->GetLoadMesh())
00086 {
00087 switch (HeartConfig::Instance()->GetConductivityMedia())
00088 {
00089 case cp::media_type::Orthotropic:
00090 {
00091 FileFinder source_file(mFibreFilePathNoExtension + ".ortho", RelativeTo::AbsoluteOrCwd);
00092 assert(source_file.Exists());
00093 FileFinder dest_file(ArchiveLocationInfo::GetArchiveRelativePath() + ArchiveLocationInfo::GetMeshFilename() + ".ortho", RelativeTo::ChasteTestOutput);
00094
00095 if (PetscTools::AmMaster())
00096 {
00097 MPIABORTIFNON0(system,"cp " + source_file.GetAbsolutePath() + " " + dest_file.GetAbsolutePath());
00098 }
00099 PetscTools::Barrier();
00100 break;
00101 }
00102
00103 case cp::media_type::Axisymmetric:
00104 {
00105 FileFinder source_file(mFibreFilePathNoExtension + ".axi", RelativeTo::AbsoluteOrCwd);
00106 assert(source_file.Exists());
00107 FileFinder dest_file(ArchiveLocationInfo::GetArchiveRelativePath() + ArchiveLocationInfo::GetMeshFilename() + ".axi", RelativeTo::ChasteTestOutput);
00108
00109 if (PetscTools::AmMaster())
00110 {
00111 MPIABORTIFNON0(system,"cp " + source_file.GetAbsolutePath() + " " + dest_file.GetAbsolutePath());
00112 }
00113 PetscTools::Barrier();
00114
00115 break;
00116 }
00117
00118 case cp::media_type::NoFibreOrientation:
00119 break;
00120
00121 default :
00122 NEVER_REACHED;
00123
00124 }
00125 }
00126
00127
00128
00129
00130 archive & mDoCacheReplication;
00131
00132 (*ProcessSpecificArchive<Archive>::Get()) & mpDistributedVectorFactory;
00133
00134
00135 assert(mpDistributedVectorFactory->GetLow()==mpMesh->GetDistributedVectorFactory()->GetLow());
00136 assert(mpDistributedVectorFactory->GetLocalOwnership()==mpMesh->GetDistributedVectorFactory()->GetLocalOwnership());
00137
00138 }
00139
00146 template<class Archive>
00147 void load(Archive & archive, const unsigned int version)
00148 {
00149
00150
00151
00152
00153
00154 archive & mDoCacheReplication;
00155
00156
00157
00158 if(version==0)
00159 {
00160 bool do_one_cache_replication = true;
00161 archive & do_one_cache_replication;
00162 }
00163
00164 (*ProcessSpecificArchive<Archive>::Get()) & mpDistributedVectorFactory;
00165
00166
00167 assert(mpDistributedVectorFactory->GetLow()==mpMesh->GetDistributedVectorFactory()->GetLow());
00168 assert(mpDistributedVectorFactory->GetLocalOwnership()==mpMesh->GetDistributedVectorFactory()->GetLocalOwnership());
00169
00170 }
00171 BOOST_SERIALIZATION_SPLIT_MEMBER()
00172
00173
00176 void CreateIntracellularConductivityTensor();
00177
00178 protected:
00179
00181 AbstractTetrahedralMesh<ELEMENT_DIM,SPACE_DIM>* mpMesh;
00182
00185 AbstractConductivityTensors<ELEMENT_DIM,SPACE_DIM>* mpIntracellularConductivityTensors;
00186
00188 std::vector< AbstractCardiacCell* > mCellsDistributed;
00189
00194 ReplicatableVector mIionicCacheReplicated;
00195
00200 ReplicatableVector mIntracellularStimulusCacheReplicated;
00201
00203 HeartConfig* mpConfig;
00204
00214 bool mDoCacheReplication;
00215
00224 DistributedVectorFactory* mpDistributedVectorFactory;
00225
00229 bool mMeshUnarchived;
00230
00234 std::string mFibreFilePathNoExtension;
00235
00236 public:
00243 AbstractCardiacTissue(AbstractCardiacCellFactory<ELEMENT_DIM,SPACE_DIM>* pCellFactory);
00244
00251 AbstractCardiacTissue(std::vector<AbstractCardiacCell*>& rCellsDistributed,
00252 AbstractTetrahedralMesh<ELEMENT_DIM,SPACE_DIM>* pMesh);
00253
00255 virtual ~AbstractCardiacTissue();
00256
00267 void MergeCells(const std::vector<AbstractCardiacCell*>& rOtherCells);
00268
00275 void SetCacheReplication(bool doCacheReplication);
00276
00282 bool GetDoCacheReplication();
00283
00287 const c_matrix<double, SPACE_DIM, SPACE_DIM>& rGetIntracellularConductivityTensor(unsigned elementIndex);
00288
00297 AbstractCardiacCell* GetCardiacCell( unsigned globalIndex );
00298
00307 virtual void SolveCellSystems(Vec existingSolution, double time, double nextTime);
00308
00310 ReplicatableVector& rGetIionicCacheReplicated();
00311
00313 ReplicatableVector& rGetIntracellularStimulusCacheReplicated();
00314
00315
00323 void UpdateCaches(unsigned globalIndex, unsigned localIndex, double nextTime);
00324
00328 void ReplicateCaches();
00329
00333 const std::vector<AbstractCardiacCell*>& rGetCellsDistributed() const;
00334
00340 const AbstractTetrahedralMesh<ELEMENT_DIM,SPACE_DIM>* pGetMesh() const;
00341
00353 template<class Archive>
00354 void SaveCardiacCells(Archive & archive, const unsigned int version) const
00355 {
00356 Archive& r_archive = *ProcessSpecificArchive<Archive>::Get();
00357 const std::vector<AbstractCardiacCell*> & r_cells_distributed = rGetCellsDistributed();
00358 r_archive & mpDistributedVectorFactory;
00359 const unsigned num_cells = r_cells_distributed.size();
00360 r_archive & num_cells;
00361 for (unsigned i=0; i<num_cells; i++)
00362 {
00363 AbstractDynamicallyLoadableEntity* p_entity = dynamic_cast<AbstractDynamicallyLoadableEntity*>(r_cells_distributed[i]);
00364 bool is_dynamic = (p_entity != NULL);
00365 r_archive & is_dynamic;
00366 if (is_dynamic)
00367 {
00368 #ifdef CHASTE_CAN_CHECKPOINT_DLLS
00369 r_archive & p_entity->GetLoader()->GetLoadableModulePath();
00370 #else
00371
00372 NEVER_REACHED;
00373 #endif // CHASTE_CAN_CHECKPOINT_DLLS
00374 }
00375 r_archive & r_cells_distributed[i];
00376 }
00377 }
00378
00390 template<class Archive>
00391 static void LoadCardiacCells(Archive & archive, const unsigned int version,
00392 std::vector<AbstractCardiacCell*>& rCells,
00393 AbstractTetrahedralMesh<ELEMENT_DIM,SPACE_DIM>* pMesh)
00394 {
00395 DistributedVectorFactory* p_factory;
00396 archive & p_factory;
00397 unsigned num_cells;
00398 archive & num_cells;
00399 rCells.resize(p_factory->GetLocalOwnership());
00400 #ifndef NDEBUG
00401
00402 for (unsigned i=0; i<rCells.size(); i++)
00403 {
00404 assert(rCells[i] == NULL);
00405 }
00406 #endif
00407
00408
00409
00410
00411
00412 unsigned index_low = p_factory->GetOriginalFactory() ? p_factory->GetOriginalFactory()->GetLow() : p_factory->GetLow();
00413
00414
00415 std::set<FakeBathCell*> fake_bath_cells_non_local, fake_bath_cells_local;
00416
00417 for (unsigned local_index=0; local_index<num_cells; local_index++)
00418 {
00419
00420 unsigned original_global_index = index_low + local_index;
00421 const std::vector<unsigned>& r_permutation = pMesh->rGetNodePermutation();
00422 unsigned new_global_index;
00423 if (r_permutation.empty())
00424 {
00425 new_global_index = original_global_index;
00426 }
00427 else
00428 {
00430
00431 NEVER_REACHED;
00432 }
00433 unsigned new_local_index = new_global_index - p_factory->GetLow();
00434 bool local = p_factory->IsGlobalIndexLocal(new_global_index);
00435
00436 bool is_dynamic;
00437 archive & is_dynamic;
00438 if (is_dynamic)
00439 {
00440 #ifdef CHASTE_CAN_CHECKPOINT_DLLS
00441
00442
00443
00444 std::string shared_object_path;
00445 archive & shared_object_path;
00446 DynamicModelLoaderRegistry::Instance()->GetLoader(shared_object_path);
00447 #else
00448
00449
00450
00451 NEVER_REACHED;
00452 #endif // CHASTE_CAN_CHECKPOINT_DLLS
00453 }
00454 AbstractCardiacCell* p_cell;
00455 archive & p_cell;
00456
00457 FakeBathCell* p_fake = dynamic_cast<FakeBathCell*>(p_cell);
00458 if (local)
00459 {
00460 rCells[new_local_index] = p_cell;
00461 if (p_fake)
00462 {
00463 fake_bath_cells_local.insert(p_fake);
00464 }
00465 }
00466 else
00467 {
00468 if (p_fake)
00469 {
00470 fake_bath_cells_non_local.insert(p_fake);
00471 }
00472 else
00473 {
00474
00475 delete p_cell;
00476 }
00477 }
00478 }
00479
00480
00481 if (!fake_bath_cells_non_local.empty())
00482 {
00483 for (std::set<FakeBathCell*>::iterator it = fake_bath_cells_non_local.begin();
00484 it != fake_bath_cells_non_local.end();
00485 ++it)
00486 {
00487 if (fake_bath_cells_local.find(*it) == fake_bath_cells_local.end())
00488 {
00489 delete (*it);
00490 }
00491 }
00492 }
00493 }
00494 };
00495
00496 TEMPLATED_CLASS_IS_ABSTRACT_2_UNSIGNED(AbstractCardiacTissue)
00497
00498 namespace boost {
00499 namespace serialization {
00506 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00507 struct version<AbstractCardiacTissue<ELEMENT_DIM, SPACE_DIM> >
00508 {
00510 BOOST_STATIC_CONSTANT(unsigned, value = 1);
00511 };
00512 }
00513 }
00514
00515 #endif
00516