ExtendedBidomainTissue.hpp

00001 /*
00002 
00003 Copyright (C) University of Oxford, 2005-2011
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 
00029 
00030 #ifndef EXTENDEDBIDOMAINTISSUE_HPP_
00031 #define EXTENDEDBIDOMAINTISSUE_HPP_
00032 
00033 #include "ChasteSerialization.hpp"
00034 #include <boost/serialization/base_object.hpp>
00035 
00036 #include <vector>
00037 #include <boost/numeric/ublas/matrix.hpp>
00038 
00039 #include "AbstractStimulusFunction.hpp"
00040 #include "AbstractStimulusFactory.hpp"
00041 #include "AbstractConductivityTensors.hpp"
00042 
00043 #include "AbstractCardiacTissue.hpp"
00044 
00069 template <unsigned SPACE_DIM>
00070 class ExtendedBidomainTissue : public virtual AbstractCardiacTissue<SPACE_DIM>
00071 {
00072 private:
00073     friend class TestExtendedBidomainTissue; // for testing.
00074 
00076     friend class boost::serialization::access;
00083     template<class Archive>
00084     void serialize(Archive & archive, const unsigned int version)
00085     {
00086         archive & boost::serialization::base_object<AbstractCardiacTissue<SPACE_DIM> >(*this);
00087         // Conductivity tensors are dealt with by HeartConfig, and the caches get regenerated.
00088 
00089         archive & mAmFirstCell;
00090         archive & mAmSecondCell;
00091         archive & mAmGap;
00092         archive & mCmFirstCell;
00093         archive & mCmSecondCell;
00094         archive & mGGap;
00095         archive & mUserSuppliedExtracellularStimulus;
00096     }
00097 
00099     AbstractConductivityTensors<SPACE_DIM, SPACE_DIM> *mpIntracellularConductivityTensorsSecondCell;
00100 
00105     c_vector<double, SPACE_DIM>  mIntracellularConductivitiesSecondCell;
00106 
00107 
00109     AbstractConductivityTensors<SPACE_DIM, SPACE_DIM> *mpExtracellularConductivityTensors;
00110 
00115     ReplicatableVector mExtracellularStimulusCacheReplicated;
00116 
00121     ReplicatableVector mGgapCacheReplicated;
00122 
00127     ReplicatableVector mIionicCacheReplicatedSecondCell;
00128 
00133     ReplicatableVector mIntracellularStimulusCacheReplicatedSecondCell;
00134 
00136     std::vector< AbstractCardiacCell* > mCellsDistributedSecondCell;
00137 
00139     std::vector<boost::shared_ptr<AbstractStimulusFunction> > mExtracellularStimuliDistributed;
00140 
00142     std::vector<double> mGgapDistributed;
00143 
00145     double mAmFirstCell;
00147     double mAmSecondCell;
00149     double mAmGap;
00151     double mCmFirstCell;
00153     double mCmSecondCell;
00155     double mGGap;
00156 
00161     bool mUserSuppliedExtracellularStimulus;
00162 
00166     void CreateExtracellularConductivityTensors();
00167 
00182     void UpdateAdditionalCaches(unsigned globalIndex, unsigned localIndex, double nextTime);
00183 
00194     void ReplicateAdditionalCaches();
00195 
00197     std::vector<boost::shared_ptr<AbstractChasteRegion<SPACE_DIM> > > mGgapHeterogeneityRegions;
00199     std::vector<double> mGgapValues;
00200 
00201 public:
00202 
00209     ExtendedBidomainTissue(AbstractCardiacCellFactory<SPACE_DIM>* pCellFactory, AbstractCardiacCellFactory<SPACE_DIM>* pCellFactorySecondCell, AbstractStimulusFactory<SPACE_DIM>* pExtracellularStimulusFactory);
00210 
00220     ExtendedBidomainTissue(std::vector<AbstractCardiacCell*> & rCellsDistributed, std::vector<AbstractCardiacCell*> & rSecondCellsDistributed, std::vector<boost::shared_ptr<AbstractStimulusFunction> > & rExtraStimuliDistributed, std::vector<double>& rGgapsDistributed, AbstractTetrahedralMesh<SPACE_DIM,SPACE_DIM>* pMesh, c_vector<double, SPACE_DIM>  intracellularConductivitiesSecondCell);
00221 
00225     ~ExtendedBidomainTissue();
00226 
00232     void SetIntracellularConductivitiesSecondCell(c_vector<double, SPACE_DIM> conductivities);
00233 
00239     AbstractCardiacCell* GetCardiacSecondCell( unsigned globalIndex );
00240 
00241 
00247     boost::shared_ptr<AbstractStimulusFunction> GetExtracellularStimulus( unsigned globalIndex );
00248 
00252     const std::vector<AbstractCardiacCell*>& rGetSecondCellsDistributed() const;
00253 
00257     const std::vector<double>& rGetGapsDistributed() const;
00258 
00259 
00263     const std::vector<boost::shared_ptr<AbstractStimulusFunction> >& rGetExtracellularStimulusDistributed() const;
00264 
00265 
00269     c_vector<double, SPACE_DIM> GetIntracellularConductivitiesSecondCell() const;
00270 
00280     virtual void SolveCellSystems(Vec existingSolution, double time, double nextTime, bool updateVoltage = false);
00281 
00285     void CreateIntracellularConductivityTensorSecondCell();
00286 
00293     void SetGgapHeterogeneities ( std::vector<boost::shared_ptr<AbstractChasteRegion<SPACE_DIM> > > & rGgapHeterogeneityRegions, std::vector<double> rGgapValues);
00294 
00300     void CreateGGapConductivities();
00301 
00306      const c_matrix<double, SPACE_DIM, SPACE_DIM>& rGetExtracellularConductivityTensor(unsigned elementIndex);
00307 
00312       const c_matrix<double, SPACE_DIM, SPACE_DIM>& rGetIntracellularConductivityTensorSecondCell(unsigned elementIndex);
00313 
00314 
00316      ReplicatableVector& rGetIionicCacheReplicatedSecondCell();
00317 
00319      ReplicatableVector& rGetIntracellularStimulusCacheReplicatedSecondCell();
00320 
00322      ReplicatableVector& rGetExtracellularStimulusCacheReplicated();
00323 
00325      ReplicatableVector& rGetGgapCacheReplicated();
00326 
00330      double GetAmFirstCell();
00331 
00335      double GetAmSecondCell();
00336 
00340      double GetAmGap();
00341 
00345      double GetCmFirstCell();
00346 
00350      double GetCmSecondCell();
00351 
00355      double GetGGap();
00356 
00360      void SetAmFirstCell(double value);
00361 
00365      void SetAmSecondCell(double value);
00366 
00370      void SetAmGap(double value);
00371 
00375      void SetCmFirstCell(double value);
00376 
00380      void SetCmSecondCell(double value);
00381 
00385      void SetGGap(double value);
00386 
00394      bool HasTheUserSuppliedExtracellularStimulus();
00395 
00403      void SetUserSuppliedExtracellularStimulus(bool flag);
00404 
00405 
00412      template<class Archive>
00413      void SaveExtendedBidomainCells(Archive & archive, const unsigned int version) const
00414      {
00415          Archive& r_archive = *ProcessSpecificArchive<Archive>::Get();
00416          const std::vector<AbstractCardiacCell*> & r_cells_distributed = this->rGetCellsDistributed();
00417          const std::vector<AbstractCardiacCell*> & r_cells_distributed_second_cell = rGetSecondCellsDistributed();
00418          const std::vector<double> & r_ggaps_distributed = rGetGapsDistributed();
00419 
00420          r_archive & this->mpDistributedVectorFactory; // Needed when loading
00421          const unsigned num_cells = r_cells_distributed.size();
00422          r_archive & num_cells;
00423          for (unsigned i=0; i<num_cells; i++)
00424          {
00425              AbstractDynamicallyLoadableEntity* p_entity = dynamic_cast<AbstractDynamicallyLoadableEntity*>(r_cells_distributed[i]);
00426              bool is_dynamic = (p_entity != NULL);
00427              r_archive & is_dynamic;
00428              if (is_dynamic)
00429              {
00430  #ifdef CHASTE_CAN_CHECKPOINT_DLLS
00431                  r_archive & p_entity->GetLoader()->GetLoadableModulePath();
00432  #else
00433                  // We should have thrown an exception before this point
00434                  NEVER_REACHED;
00435  #endif // CHASTE_CAN_CHECKPOINT_DLLS
00436              }
00437              r_archive & r_cells_distributed[i];
00438              r_archive & r_cells_distributed_second_cell[i];
00439              r_archive & r_ggaps_distributed[i];
00440          }
00441      }
00442 
00457      template<class Archive>
00458      static void LoadExtendedBidomainCells(Archive & archive, const unsigned int version,
00459                                   std::vector<AbstractCardiacCell*>& rCells,
00460                                   std::vector<AbstractCardiacCell*>& rSecondCells,
00461                                   std::vector<double>& rGgaps,
00462                                   AbstractTetrahedralMesh<SPACE_DIM,SPACE_DIM>* pMesh)
00463      {
00464          assert(pMesh!=NULL);
00465          DistributedVectorFactory* p_factory;
00466          archive & p_factory;
00467          unsigned num_cells;
00468          archive & num_cells;
00469          rCells.resize(p_factory->GetLocalOwnership());
00470          rSecondCells.resize(p_factory->GetLocalOwnership());
00471          rGgaps.resize(p_factory->GetLocalOwnership());
00472  #ifndef NDEBUG
00473          // Paranoia
00474          assert(rCells.size() == rSecondCells.size());
00475          for (unsigned i=0; i<rCells.size(); i++)
00476          {
00477              assert(rCells[i] == NULL);
00478              assert(rSecondCells[i] == NULL);
00479          }
00480  #endif
00481 
00482          // We don't store a cell index in the archive, so need to work out what global
00483          // index this tissue starts up.  If we're migrating (so have an
00484          // original factory) we use the original low index; otherwise we use the current
00485          // low index.
00486          unsigned index_low = p_factory->GetOriginalFactory() ? p_factory->GetOriginalFactory()->GetLow() : p_factory->GetLow();
00487 
00488          for (unsigned local_index=0; local_index<num_cells; local_index++)
00489          {
00490              unsigned global_index = index_low + local_index;
00491              unsigned new_local_index = global_index - p_factory->GetLow();
00492              bool local = p_factory->IsGlobalIndexLocal(global_index);
00493 
00494              bool is_dynamic;
00495              archive & is_dynamic;
00496 
00497              if (is_dynamic)
00498              {
00499  #ifdef CHASTE_CAN_CHECKPOINT_DLLS
00500                  // Ensure the shared object file for this cell model is loaded.
00501                  // We need to do this here, rather than in the class' serialization code,
00502                  // because that code won't be available until this is done...
00503                  std::string shared_object_path;
00504                  archive & shared_object_path;
00505                  DynamicModelLoaderRegistry::Instance()->GetLoader(shared_object_path);
00506  #else
00507                  // Since checkpoints with dynamically loadable cells can only be
00508                  // created on Boost>=1.37, trying to load such a checkpoint on an
00509                  // earlier Boost would give an error when first opening the archive.
00510                  NEVER_REACHED;
00511  #endif // CHASTE_CAN_CHECKPOINT_DLLS
00512              }
00513 
00514              AbstractCardiacCell* p_cell;
00515              AbstractCardiacCell* p_second_cell;
00516              double g_gap;
00517              archive & p_cell;
00518              archive & p_second_cell;
00519              archive & g_gap;
00520              if (local)
00521              {
00522                  rCells[new_local_index] = p_cell; // Add to local cells
00523                  rSecondCells[new_local_index] = p_second_cell;
00524                  rGgaps[new_local_index] = g_gap;
00525              }
00526              else
00527              {
00528                  //not sure how to cover this, we are already looping over local cells...
00529                  NEVER_REACHED;
00530                 // Non-local real cell, so free the memory.
00531                 // delete p_cell;
00532                 // delete p_second_cell;
00533              }
00534          }
00535      }
00536 
00543      template<class Archive>
00544      void SaveExtracellularStimulus(Archive & archive, const unsigned int version) const
00545      {
00546          Archive& r_archive = *ProcessSpecificArchive<Archive>::Get();
00547          const std::vector<boost::shared_ptr<AbstractStimulusFunction> > & r_stimulus_distributed = rGetExtracellularStimulusDistributed();
00548          r_archive & this->mpDistributedVectorFactory; // Needed when loading
00549          const unsigned num_cells = r_stimulus_distributed.size();
00550          r_archive & num_cells;
00551          for (unsigned i=0; i<num_cells; i++)
00552          {
00553              r_archive & r_stimulus_distributed[i];
00554          }
00555      }
00556 
00565      template<class Archive>
00566      void LoadExtracellularStimulus(Archive & archive, const unsigned int version,
00567                                                std::vector<boost::shared_ptr<AbstractStimulusFunction> >& rStimuli,
00568                                                AbstractTetrahedralMesh<SPACE_DIM,SPACE_DIM>* pMesh)
00569      {
00570 
00571         DistributedVectorFactory* p_factory;
00572         archive & p_factory;
00573         unsigned num_cells;
00574         archive & num_cells;
00575         rStimuli.resize(p_factory->GetLocalOwnership());
00576 #ifndef NDEBUG
00577           // Paranoia
00578           for (unsigned i=0; i<rStimuli.size(); i++)
00579           {
00580               assert(rStimuli[i] == NULL);
00581           }
00582 #endif
00583 
00584         // We don't store a cell index in the archive, so need to work out what global
00585         // index this tissue starts up.  If we're migrating (so have an
00586         // original factory) we use the original low index; otherwise we use the current
00587         // low index.
00588         unsigned index_low = p_factory->GetOriginalFactory() ? p_factory->GetOriginalFactory()->GetLow() : p_factory->GetLow();
00589 
00590         assert(pMesh!=NULL);
00591         //unsigned num_cells = pMesh->GetNumNodes();
00592         for (unsigned local_index=0; local_index<num_cells; local_index++)
00593         {
00594           unsigned global_index = index_low + local_index;
00595 
00596           unsigned new_local_index = global_index - p_factory->GetLow();
00597           bool local = p_factory->IsGlobalIndexLocal(global_index);
00598 
00599           boost::shared_ptr<AbstractStimulusFunction> p_stim;
00600           archive & p_stim;//get from archive
00601 
00602           if (local)
00603           {
00604               rStimuli[new_local_index] = p_stim; // Add stimulus to local cells
00605           }
00606           //otherwise we should delete, but I think shared pointers delete themselves?
00607         }
00608     }
00609 };
00610 
00611  // Declare identifier for the serializer
00612  #include "SerializationExportWrapper.hpp"
00613  EXPORT_TEMPLATE_CLASS_SAME_DIMS(ExtendedBidomainTissue)
00614 
00615  namespace boost
00616  {
00617  namespace serialization
00618  {
00619 
00620  template<class Archive, unsigned SPACE_DIM>
00621  inline void save_construct_data(
00622      Archive & ar, const ExtendedBidomainTissue<SPACE_DIM> * t, const unsigned int file_version)
00623  {
00624      //archive the conductivity tensor of the second cell (which may not be dealt with by heartconfig)
00625      c_vector<double, SPACE_DIM>  intracellular_conductivities_second_cell = t->GetIntracellularConductivitiesSecondCell();
00626      //note that simple: ar & intracellular_conductivities_second_cell may not be liked by some boost versions
00627      for (unsigned i = 0; i < SPACE_DIM; i++)
00628      {
00629          ar & intracellular_conductivities_second_cell(i);
00630      }
00631 
00632      const AbstractTetrahedralMesh<SPACE_DIM,SPACE_DIM>* p_mesh = t->pGetMesh();
00633      ar & p_mesh;
00634 
00635      // Don't use the std::vector serialization for cardiac cells, so that we can load them
00636      // more cleverly when migrating checkpoints.
00637      t->SaveExtendedBidomainCells(ar, file_version);
00638      t->SaveExtracellularStimulus(ar, file_version);
00639 
00640      // Creation of conductivity tensors are called by constructor and uses HeartConfig. So make sure that it is
00641      // archived too (needs doing before construction so appears here instead of usual archive location).
00642      HeartConfig* p_config = HeartConfig::Instance();
00643      ar & *p_config;
00644      ar & p_config;
00645  }
00646 
00651  template<class Archive, unsigned SPACE_DIM>
00652  inline void load_construct_data(
00653      Archive & ar, ExtendedBidomainTissue<SPACE_DIM> * t, const unsigned int file_version)
00654  {
00655      //Load conductivities of the conductivity of the second cell.
00656      c_vector<double, SPACE_DIM>  intra_cond_second_cell;
00657      //note that simple: ar & intra_cond_second_cell may not be liked by some boost versions
00658      for (unsigned i = 0; i < SPACE_DIM; i++)
00659      {
00660          double cond;
00661          ar & cond;
00662          intra_cond_second_cell(i) = cond;
00663      }
00664 
00665 
00666      std::vector<AbstractCardiacCell*> cells_distributed;
00667      std::vector<AbstractCardiacCell*> cells_distributed_second_cell;
00668      std::vector<boost::shared_ptr<AbstractStimulusFunction> > extra_stim;
00669      std::vector<double> g_gaps;
00670      AbstractTetrahedralMesh<SPACE_DIM,SPACE_DIM>* p_mesh;
00671      ar & p_mesh;
00672 
00673      // Load only the cells we actually own
00674      t->LoadExtendedBidomainCells(
00675              *ProcessSpecificArchive<Archive>::Get(), file_version, cells_distributed, cells_distributed_second_cell, g_gaps, p_mesh);
00676 
00677      t->LoadExtracellularStimulus(
00678              *ProcessSpecificArchive<Archive>::Get(), file_version, extra_stim, p_mesh);
00679 
00680      // CreateIntracellularConductivityTensor() is called by AbstractCardiacTissue constructor and uses HeartConfig.
00681      // (as does CreateExtracellularConductivityTensor). So make sure that it is
00682      // archived too (needs doing before construction so appears here instead of usual archive location).
00683      HeartConfig* p_config = HeartConfig::Instance();
00684      ar & *p_config;
00685      ar & p_config;
00686 
00687      ::new(t)ExtendedBidomainTissue<SPACE_DIM>(cells_distributed, cells_distributed_second_cell, extra_stim, g_gaps, p_mesh, intra_cond_second_cell);
00688  }
00689  }
00690  } // namespace ...
00691 
00692 
00693 
00694 #endif /*EXTENDEDBIDOMAINTISSUE_HPP_*/
Generated on Thu Dec 22 13:00:07 2011 for Chaste by  doxygen 1.6.3