AbstractCardiacTissue.hpp

00001 /*
00002 
00003 Copyright (C) University of Oxford, 2005-2010
00004 
00005 University of Oxford means the Chancellor, Masters and Scholars of the
00006 University of Oxford, having an administrative office at Wellington
00007 Square, Oxford OX1 2JD, UK.
00008 
00009 This file is part of Chaste.
00010 
00011 Chaste is free software: you can redistribute it and/or modify it
00012 under the terms of the GNU Lesser General Public License as published
00013 by the Free Software Foundation, either version 2.1 of the License, or
00014 (at your option) any later version.
00015 
00016 Chaste is distributed in the hope that it will be useful, but WITHOUT
00017 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00018 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
00019 License for more details. The offer of Chaste under the terms of the
00020 License is subject to the License being interpreted in accordance with
00021 English Law and subject to any action against the University of Oxford
00022 being under the jurisdiction of the English Courts.
00023 
00024 You should have received a copy of the GNU Lesser General Public License
00025 along with Chaste. If not, see <http://www.gnu.org/licenses/>.
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         // archive & mpMesh; Archived in save/load_constructs at the bottom of Mono/BidomainTissue.hpp
00084         // archive & mpIntracellularConductivityTensors; Loaded from HeartConfig every time constructor is called
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         // archive & mCellsDistributed; Archived in save/load_constructs at the bottom of Mono/BidomainTissue.hpp
00128         // archive & mIionicCacheReplicated; // will be regenerated
00129         // archive & mIntracellularStimulusCacheReplicated; // will be regenerated
00130         archive & mDoCacheReplication;
00131 
00132         (*ProcessSpecificArchive<Archive>::Get()) & mpDistributedVectorFactory;
00133 
00134         // Paranoia: check we agree with the mesh on who owns what
00135         assert(mpDistributedVectorFactory->GetLow()==mpMesh->GetDistributedVectorFactory()->GetLow());
00136         assert(mpDistributedVectorFactory->GetLocalOwnership()==mpMesh->GetDistributedVectorFactory()->GetLocalOwnership());
00137         // archive & mMeshUnarchived; Not archived since set to true when archiving constructor is called.
00138     }
00139 
00146     template<class Archive>
00147     void load(Archive & archive, const unsigned int version)
00148     {
00149         // archive & mpMesh; Archived in save/load_constructs at the bottom of Mono/BidomainTissue.hpp
00150         // archive & mpIntracellularConductivityTensors; Loaded from HeartConfig every time constructor is called
00151         // archive & mCellsDistributed; Archived in save/load_constructs at the bottom of Mono/BidomainTissue.hpp
00152         // archive & mIionicCacheReplicated; // will be regenerated
00153         // archive & mIntracellularStimulusCacheReplicated; // will be regenerated
00154         archive & mDoCacheReplication;
00155 
00156         // we no longer have a bool mDoOneCacheReplication, but to maintain backwards compatibility
00157         // we archive something if version==0
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         // Paranoia: check we agree with the mesh on who owns what
00167         assert(mpDistributedVectorFactory->GetLow()==mpMesh->GetDistributedVectorFactory()->GetLow());
00168         assert(mpDistributedVectorFactory->GetLocalOwnership()==mpMesh->GetDistributedVectorFactory()->GetLocalOwnership());
00169         // archive & mMeshUnarchived; Not archived since set to true when archiving constructor is called.
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; // Needed when loading
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                 // We should have thrown an exception before this point
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         // Paranoia
00402         for (unsigned i=0; i<rCells.size(); i++)
00403         {
00404             assert(rCells[i] == NULL);
00405         }
00406 #endif
00407 
00408         // We don't store a cell index in the archive, so need to work out what global
00409         // index this tissue starts up.  If we're migrating (so have an
00410         // original factory) we use the original low index; otherwise we use the current
00411         // low index.
00412         unsigned index_low = p_factory->GetOriginalFactory() ? p_factory->GetOriginalFactory()->GetLow() : p_factory->GetLow();
00413 
00414         // Track fake bath cells to make sure we only delete non-local ones
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             // If we're permuting, figure out where this cell goes
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 //                new_global_index = r_permutation[original_global_index];
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                 // Ensure the shared object file for this cell model is loaded.
00442                 // We need to do this here, rather than in the class' serialization code,
00443                 // because that code won't be available until this is done...
00444                 std::string shared_object_path;
00445                 archive & shared_object_path;
00446                 DynamicModelLoaderRegistry::Instance()->GetLoader(shared_object_path);
00447 #else
00448                 // Since checkpoints with dynamically loadable cells can only be
00449                 // created on Boost>=1.37, trying to load such a checkpoint on an
00450                 // earlier Boost would give an error when first opening the archive.
00451                 NEVER_REACHED;
00452 #endif // CHASTE_CAN_CHECKPOINT_DLLS
00453             }
00454             AbstractCardiacCell* p_cell;
00455             archive & p_cell;
00456             // Check if it's a fake cell
00457             FakeBathCell* p_fake = dynamic_cast<FakeBathCell*>(p_cell);
00458             if (local)
00459             {
00460                 rCells[new_local_index] = p_cell; // Add to local cells 
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                     // Non-local real cell, so free the memory.
00475                     delete p_cell;
00476                 }
00477             }
00478         }
00479 
00480         // Delete any unused fake cells
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 } // namespace serialization
00513 } // namespace boost
00514 
00515 #endif /*ABSTRACTCARDIACTISSUE_HPP_*/
00516 

Generated on Mon Nov 1 12:35:17 2010 for Chaste by  doxygen 1.5.5