AbstractCardiacPde.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 ABSTRACTCARDIACPDE_HPP_
00029 #define ABSTRACTCARDIACPDE_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 
00041 #include <boost/numeric/ublas/matrix.hpp>
00042 
00043 #include "AbstractCardiacCell.hpp"
00044 #include "AbstractCardiacCellFactory.hpp"
00045 #include "AbstractConductivityTensors.hpp"
00046 
00047 #include "ReplicatableVector.hpp"
00048 #include "HeartConfig.hpp"
00049 #include "ArchiveLocationInfo.hpp"
00050 #include "AbstractDynamicallyLoadableEntity.hpp"
00051 #include "DynamicModelLoaderRegistry.hpp"
00052 
00054 // IMPORTANT NOTE: the inheritance of AbstractPde has to be 'virtual'
00055 // ie "class AbstractCardiacPde : public virtual AbstractPde"
00056 // because AbstractPde will be the top class in a 'dreaded diamond':
00057 //      A
00058 //     / \     A = AbstractPde, B = AbstractCardiac, C = AbstractLinearParabolic (etc)
00059 //    B   C    D = MonodomainPde
00060 //     \ /
00061 //      D
00062 //
00063 // B and C must use virtual inheritence of A in order for D to only contain 1 instance
00064 // of the member variables in A
00065 
00075 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM = ELEMENT_DIM>
00076 class AbstractCardiacPde
00077 {
00078 private:
00079 
00081     friend class boost::serialization::access;
00088     template<class Archive>
00089     void serialize(Archive & archive, const unsigned int version)
00090     {
00091         // archive & mpMesh; Archived in save/load_constructs at the bottom of mono/bidomainPde.hpp
00092         // archive & mpIntracellularConductivityTensors; Loaded from HeartConfig every time constructor is called
00093         // archive & mCellsDistributed; Archived in save/load_constructs at the bottom of mono/bidomainPde.hpp
00094         // archive & mIionicCacheReplicated; // will be regenerated
00095         // archive & mIntracellularStimulusCacheReplicated; // will be regenerated
00096         // archive & mStride; // archiving constructor sets this.
00097         archive & mDoCacheReplication;
00098         archive & mDoOneCacheReplication;
00099         (*ProcessSpecificArchive<Archive>::Get()) & mpDistributedVectorFactory;
00100 
00101         // Paranoia: check we agree with the mesh on who owns what
00102         assert(mpDistributedVectorFactory->GetLow()==mpMesh->GetDistributedVectorFactory()->GetLow());
00103         assert(mpDistributedVectorFactory->GetLocalOwnership()==mpMesh->GetDistributedVectorFactory()->GetLocalOwnership());
00104         // archive & mMeshUnarchived; Not archived since set to true when archiving constructor is called.
00105     }
00106 
00110     void CreateIntracellularConductivityTensor();
00111 
00112 protected:
00113 
00115     AbstractTetrahedralMesh<ELEMENT_DIM,SPACE_DIM>* mpMesh;
00116 
00118     AbstractConductivityTensors<SPACE_DIM> *mpIntracellularConductivityTensors;
00119 
00121     std::vector< AbstractCardiacCell* > mCellsDistributed;
00122 
00127     ReplicatableVector mIionicCacheReplicated;
00128 
00133     ReplicatableVector mIntracellularStimulusCacheReplicated;
00134 
00141     const unsigned mStride;
00142 
00144     HeartConfig* mpConfig;
00145 
00155     bool mDoCacheReplication;
00156 
00162     bool mDoOneCacheReplication;
00163 
00172     DistributedVectorFactory* mpDistributedVectorFactory;
00173 
00177     bool mMeshUnarchived;
00178 
00183     void DeleteCells(bool deleteFakeCells);
00184 
00185 public:
00193     AbstractCardiacPde(AbstractCardiacCellFactory<ELEMENT_DIM,SPACE_DIM>* pCellFactory,
00194                        const unsigned stride=1);
00195 
00203     AbstractCardiacPde(std::vector<AbstractCardiacCell*>& rCellsDistributed,
00204                        AbstractTetrahedralMesh<ELEMENT_DIM,SPACE_DIM>* pMesh,
00205                        const unsigned stride);
00206 
00208     virtual ~AbstractCardiacPde();
00209 
00220     void MergeCells(const std::vector<AbstractCardiacCell*>& rOtherCells);
00221 
00228     void SetCacheReplication(bool doCacheReplication);
00229 
00235     bool GetDoCacheReplication();
00236 
00240     const c_matrix<double, SPACE_DIM, SPACE_DIM>& rGetIntracellularConductivityTensor(unsigned elementIndex);
00241 
00250     AbstractCardiacCell* GetCardiacCell( unsigned globalIndex );
00251 
00266     virtual void SolveCellSystems(Vec existingSolution, double time, double nextTime);
00267 
00269     ReplicatableVector& rGetIionicCacheReplicated();
00270 
00272     ReplicatableVector& rGetIntracellularStimulusCacheReplicated();
00273 
00274 
00282     void UpdateCaches(unsigned globalIndex, unsigned localIndex, double nextTime);
00283 
00287     void ReplicateCaches();
00288 
00292     const std::vector<AbstractCardiacCell*>& rGetCellsDistributed() const;
00293 
00299     const AbstractTetrahedralMesh<ELEMENT_DIM,SPACE_DIM>* pGetMesh() const;
00300 
00312     template<class Archive>
00313     void SaveCardiacCells(Archive & archive, const unsigned int version) const
00314     {
00315         Archive& r_archive = *ProcessSpecificArchive<Archive>::Get();
00316         const std::vector<AbstractCardiacCell*> & r_cells_distributed = rGetCellsDistributed();
00317         r_archive & mpDistributedVectorFactory; // Needed when loading
00318         const unsigned num_cells = r_cells_distributed.size();
00319         r_archive & num_cells;
00320         for (unsigned i=0; i<num_cells; i++)
00321         {
00322             AbstractDynamicallyLoadableEntity* p_entity = dynamic_cast<AbstractDynamicallyLoadableEntity*>(r_cells_distributed[i]);
00323             bool is_dynamic = (p_entity != NULL);
00324             r_archive & is_dynamic;
00325             if (is_dynamic)
00326             {
00327 #ifdef CHASTE_CAN_CHECKPOINT_DLLS
00328                 r_archive & p_entity->GetLoader()->GetLoadableModulePath();
00329 #else
00330                 // We should have thrown an exception before this point
00331                 NEVER_REACHED;
00332 #endif // CHASTE_CAN_CHECKPOINT_DLLS
00333             }
00334             r_archive & r_cells_distributed[i];
00335         }
00336     }
00337 
00349     template<class Archive>
00350     static void LoadCardiacCells(Archive & archive, const unsigned int version,
00351                                  std::vector<AbstractCardiacCell*>& rCells,
00352                                  AbstractTetrahedralMesh<ELEMENT_DIM,SPACE_DIM>* pMesh)
00353     {
00354         DistributedVectorFactory* p_factory;
00355         archive & p_factory;
00356         unsigned num_cells;
00357         archive & num_cells;
00358         rCells.resize(p_factory->GetLocalOwnership());
00359 #ifndef NDEBUG
00360         // Paranoia
00361         for (unsigned i=0; i<rCells.size(); i++)
00362         {
00363             assert(rCells[i] == NULL);
00364         }
00365 #endif
00366 
00367         // We don't store a cell index in the archive, so need to work out what global
00368         // index this collection of cells starts up.  If we're migrating (so have an
00369         // original factory) we use the original low index; otherwise we use the current
00370         // low index.
00371         unsigned index_low = p_factory->GetOriginalFactory() ? p_factory->GetOriginalFactory()->GetLow() : p_factory->GetLow();
00372 
00373         // Track fake bath cells to make sure we only delete non-local ones
00374         std::set<FakeBathCell*> fake_bath_cells_non_local, fake_bath_cells_local;
00375 
00376         for (unsigned local_index=0; local_index<num_cells; local_index++)
00377         {
00378             // If we're permuting, figure out where this cell goes
00379             unsigned original_global_index = index_low + local_index;
00380             const std::vector<unsigned>& r_permutation = pMesh->rGetNodePermutation();
00381             unsigned new_global_index;
00382             if (r_permutation.empty())
00383             {
00384                 new_global_index = original_global_index;
00385             }
00386             else
00387             {
00389 //                new_global_index = r_permutation[original_global_index];
00390                 NEVER_REACHED;
00391             }
00392             unsigned new_local_index = new_global_index - p_factory->GetLow();
00393             bool local = p_factory->IsGlobalIndexLocal(new_global_index);
00394 
00395             bool is_dynamic;
00396             archive & is_dynamic;
00397             if (is_dynamic)
00398             {
00399 #ifdef CHASTE_CAN_CHECKPOINT_DLLS
00400                 // Ensure the shared object file for this cell model is loaded.
00401                 // We need to do this here, rather than in the class' serialization code,
00402                 // because that code won't be available until this is done...
00403                 std::string shared_object_path;
00404                 archive & shared_object_path;
00405                 DynamicModelLoaderRegistry::Instance()->GetLoader(shared_object_path);
00406 #else
00407                 // Since checkpoints with dynamically loadable cells can only be
00408                 // created on Boost>=1.37, trying to load such a checkpoint on an
00409                 // earlier Boost would give an error when first opening the archive.
00410                 NEVER_REACHED;
00411 #endif // CHASTE_CAN_CHECKPOINT_DLLS
00412             }
00413             AbstractCardiacCell* p_cell;
00414             archive & p_cell;
00415             // Check if it's a fake cell
00416             FakeBathCell* p_fake = dynamic_cast<FakeBathCell*>(p_cell);
00417             if (local)
00418             {
00419                 rCells[new_local_index] = p_cell; // Add to local cells collection
00420                 if (p_fake)
00421                 {
00422                     fake_bath_cells_local.insert(p_fake);
00423                 }
00424             }
00425             else
00426             {
00427                 if (p_fake)
00428                 {
00429                     fake_bath_cells_non_local.insert(p_fake);
00430                 }
00431                 else
00432                 {
00433                     // Non-local real cell, so free the memory.
00434                     delete p_cell;
00435                 }
00436             }
00437         }
00438 
00439         // Delete any unused fake cells
00440         if (!fake_bath_cells_non_local.empty())
00441         {
00442             for (std::set<FakeBathCell*>::iterator it = fake_bath_cells_non_local.begin();
00443                  it != fake_bath_cells_non_local.end();
00444                  ++it)
00445             {
00446                 if (fake_bath_cells_local.find(*it) == fake_bath_cells_local.end())
00447                 {
00448                     delete (*it);
00449                 }
00450             }
00451         }
00452     }
00453 };
00454 
00455 TEMPLATED_CLASS_IS_ABSTRACT_2_UNSIGNED(AbstractCardiacPde);
00456 
00457 #endif /*ABSTRACTCARDIACPDE_HPP_*/
00458 

Generated by  doxygen 1.6.2