ExtendedBidomainTissue.hpp

00001 /*
00002 
00003 Copyright (c) 2005-2015, University of Oxford.
00004 All rights reserved.
00005 
00006 University of Oxford means the Chancellor, Masters and Scholars of the
00007 University of Oxford, having an administrative office at Wellington
00008 Square, Oxford OX1 2JD, UK.
00009 
00010 This file is part of Chaste.
00011 
00012 Redistribution and use in source and binary forms, with or without
00013 modification, are permitted provided that the following conditions are met:
00014  * Redistributions of source code must retain the above copyright notice,
00015    this list of conditions and the following disclaimer.
00016  * Redistributions in binary form must reproduce the above copyright notice,
00017    this list of conditions and the following disclaimer in the documentation
00018    and/or other materials provided with the distribution.
00019  * Neither the name of the University of Oxford nor the names of its
00020    contributors may be used to endorse or promote products derived from this
00021    software without specific prior written permission.
00022 
00023 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00024 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00025 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00026 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
00027 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00028 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
00029 GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00030 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00031 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
00032 OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00033 
00034 */
00035 
00036 
00037 #ifndef EXTENDEDBIDOMAINTISSUE_HPP_
00038 #define EXTENDEDBIDOMAINTISSUE_HPP_
00039 
00040 #include "ChasteSerialization.hpp"
00041 #include <boost/serialization/base_object.hpp>
00042 
00043 #include <vector>
00044 #include "UblasMatrixInclude.hpp"
00045 
00046 #include "AbstractStimulusFunction.hpp"
00047 #include "AbstractStimulusFactory.hpp"
00048 #include "AbstractConductivityTensors.hpp"
00049 
00050 #include "AbstractCardiacTissue.hpp"
00051 
00076 template <unsigned SPACE_DIM>
00077 class ExtendedBidomainTissue : public virtual AbstractCardiacTissue<SPACE_DIM>
00078 {
00079 private:
00080     friend class TestExtendedBidomainTissue; // for testing.
00081 
00083     friend class boost::serialization::access;
00090     template<class Archive>
00091     void serialize(Archive & archive, const unsigned int version)
00092     {
00093         archive & boost::serialization::base_object<AbstractCardiacTissue<SPACE_DIM> >(*this);
00094         // Conductivity tensors are dealt with by HeartConfig, and the caches get regenerated.
00095 
00096         archive & mAmFirstCell;
00097         archive & mAmSecondCell;
00098         archive & mAmGap;
00099         archive & mCmFirstCell;
00100         archive & mCmSecondCell;
00101         archive & mGGap;
00102         archive & mUserSuppliedExtracellularStimulus;
00103     }
00104 
00106     AbstractConductivityTensors<SPACE_DIM, SPACE_DIM> *mpIntracellularConductivityTensorsSecondCell;
00107 
00112     c_vector<double, SPACE_DIM>  mIntracellularConductivitiesSecondCell;
00113 
00114 
00116     AbstractConductivityTensors<SPACE_DIM, SPACE_DIM> *mpExtracellularConductivityTensors;
00117 
00122     ReplicatableVector mExtracellularStimulusCacheReplicated;
00123 
00128     ReplicatableVector mGgapCacheReplicated;
00129 
00134     ReplicatableVector mIionicCacheReplicatedSecondCell;
00135 
00140     ReplicatableVector mIntracellularStimulusCacheReplicatedSecondCell;
00141 
00143     std::vector< AbstractCardiacCellInterface* > mCellsDistributedSecondCell;
00144 
00146     std::vector<boost::shared_ptr<AbstractStimulusFunction> > mExtracellularStimuliDistributed;
00147 
00149     std::vector<double> mGgapDistributed;
00150 
00152     double mAmFirstCell;
00154     double mAmSecondCell;
00156     double mAmGap;
00158     double mCmFirstCell;
00160     double mCmSecondCell;
00162     double mGGap;
00163 
00168     bool mUserSuppliedExtracellularStimulus;
00169 
00173     void CreateExtracellularConductivityTensors();
00174 
00189     void UpdateAdditionalCaches(unsigned globalIndex, unsigned localIndex, double nextTime);
00190 
00201     void ReplicateAdditionalCaches();
00202 
00204     std::vector<boost::shared_ptr<AbstractChasteRegion<SPACE_DIM> > > mGgapHeterogeneityRegions;
00206     std::vector<double> mGgapValues;
00207 
00208 public:
00209 
00216     ExtendedBidomainTissue(AbstractCardiacCellFactory<SPACE_DIM>* pCellFactory, AbstractCardiacCellFactory<SPACE_DIM>* pCellFactorySecondCell, AbstractStimulusFactory<SPACE_DIM>* pExtracellularStimulusFactory);
00217 
00227     ExtendedBidomainTissue(std::vector<AbstractCardiacCellInterface*> & rCellsDistributed, std::vector<AbstractCardiacCellInterface*> & rSecondCellsDistributed, std::vector<boost::shared_ptr<AbstractStimulusFunction> > & rExtraStimuliDistributed, std::vector<double>& rGgapsDistributed, AbstractTetrahedralMesh<SPACE_DIM,SPACE_DIM>* pMesh, c_vector<double, SPACE_DIM>  intracellularConductivitiesSecondCell);
00228 
00232     virtual ~ExtendedBidomainTissue();
00233 
00239     void SetIntracellularConductivitiesSecondCell(c_vector<double, SPACE_DIM> conductivities);
00240 
00246     AbstractCardiacCellInterface* GetCardiacSecondCell( unsigned globalIndex );
00247 
00248 
00254     boost::shared_ptr<AbstractStimulusFunction> GetExtracellularStimulus( unsigned globalIndex );
00255 
00259     const std::vector<AbstractCardiacCellInterface*>& rGetSecondCellsDistributed() const;
00260 
00264     const std::vector<double>& rGetGapsDistributed() const;
00265 
00266 
00270     const std::vector<boost::shared_ptr<AbstractStimulusFunction> >& rGetExtracellularStimulusDistributed() const;
00271 
00272 
00276     c_vector<double, SPACE_DIM> GetIntracellularConductivitiesSecondCell() const;
00277 
00287     virtual void SolveCellSystems(Vec existingSolution, double time, double nextTime, bool updateVoltage = false);
00288 
00292     void CreateIntracellularConductivityTensorSecondCell();
00293 
00300     void SetGgapHeterogeneities ( std::vector<boost::shared_ptr<AbstractChasteRegion<SPACE_DIM> > > & rGgapHeterogeneityRegions, std::vector<double> rGgapValues);
00301 
00307     void CreateGGapConductivities();
00308 
00313      const c_matrix<double, SPACE_DIM, SPACE_DIM>& rGetExtracellularConductivityTensor(unsigned elementIndex);
00314 
00319       const c_matrix<double, SPACE_DIM, SPACE_DIM>& rGetIntracellularConductivityTensorSecondCell(unsigned elementIndex);
00320 
00321 
00323      ReplicatableVector& rGetIionicCacheReplicatedSecondCell();
00324 
00326      ReplicatableVector& rGetIntracellularStimulusCacheReplicatedSecondCell();
00327 
00329      ReplicatableVector& rGetExtracellularStimulusCacheReplicated();
00330 
00332      ReplicatableVector& rGetGgapCacheReplicated();
00333 
00337      double GetAmFirstCell();
00338 
00342      double GetAmSecondCell();
00343 
00347      double GetAmGap();
00348 
00352      double GetCmFirstCell();
00353 
00357      double GetCmSecondCell();
00358 
00362      double GetGGap();
00363 
00367      void SetAmFirstCell(double value);
00368 
00372      void SetAmSecondCell(double value);
00373 
00377      void SetAmGap(double value);
00378 
00382      void SetCmFirstCell(double value);
00383 
00387      void SetCmSecondCell(double value);
00388 
00392      void SetGGap(double value);
00393 
00401      bool HasTheUserSuppliedExtracellularStimulus();
00402 
00410      void SetUserSuppliedExtracellularStimulus(bool flag);
00411 
00412 
00419      template<class Archive>
00420      void SaveExtendedBidomainCells(Archive & archive, const unsigned int version) const
00421      {
00422          Archive& r_archive = *ProcessSpecificArchive<Archive>::Get();
00423          const std::vector<AbstractCardiacCellInterface*> & r_cells_distributed = this->rGetCellsDistributed();
00424          const std::vector<AbstractCardiacCellInterface*> & r_cells_distributed_second_cell = rGetSecondCellsDistributed();
00425          const std::vector<double> & r_ggaps_distributed = rGetGapsDistributed();
00426 
00427          r_archive & this->mpDistributedVectorFactory; // Needed when loading
00428          const unsigned num_cells = r_cells_distributed.size();
00429          r_archive & num_cells;
00430          for (unsigned i=0; i<num_cells; i++)
00431          {
00432              AbstractDynamicallyLoadableEntity* p_entity = dynamic_cast<AbstractDynamicallyLoadableEntity*>(r_cells_distributed[i]);
00433              bool is_dynamic = (p_entity != NULL);
00434              r_archive & is_dynamic;
00435              if (is_dynamic)
00436              {
00437  #ifdef CHASTE_CAN_CHECKPOINT_DLLS
00439                  NEVER_REACHED;
00440                  //r_archive & p_entity->GetLoader()->GetLoadableModulePath();
00441  #else
00442                  // We should have thrown an exception before this point
00443                  NEVER_REACHED;
00444  #endif // CHASTE_CAN_CHECKPOINT_DLLS
00445              }
00446              r_archive & r_cells_distributed[i];
00447              r_archive & r_cells_distributed_second_cell[i];
00448              r_archive & r_ggaps_distributed[i];
00449          }
00450      }
00451 
00466      template<class Archive>
00467      static void LoadExtendedBidomainCells(Archive & archive, const unsigned int version,
00468                                   std::vector<AbstractCardiacCellInterface*>& rCells,
00469                                   std::vector<AbstractCardiacCellInterface*>& rSecondCells,
00470                                   std::vector<double>& rGgaps,
00471                                   AbstractTetrahedralMesh<SPACE_DIM,SPACE_DIM>* pMesh)
00472      {
00473          assert(pMesh!=NULL);
00474          DistributedVectorFactory* p_factory;
00475          archive & p_factory;
00476          unsigned num_cells;
00477          archive & num_cells;
00478          rCells.resize(p_factory->GetLocalOwnership());
00479          rSecondCells.resize(p_factory->GetLocalOwnership());
00480          rGgaps.resize(p_factory->GetLocalOwnership());
00481  #ifndef NDEBUG
00482          // Paranoia
00483          assert(rCells.size() == rSecondCells.size());
00484          for (unsigned i=0; i<rCells.size(); i++)
00485          {
00486              assert(rCells[i] == NULL);
00487              assert(rSecondCells[i] == NULL);
00488          }
00489  #endif
00490 
00491          // We don't store a cell index in the archive, so need to work out what global
00492          // index this tissue starts up.  If we're migrating (so have an
00493          // original factory) we use the original low index; otherwise we use the current
00494          // low index.
00495          unsigned index_low = p_factory->GetOriginalFactory() ? p_factory->GetOriginalFactory()->GetLow() : p_factory->GetLow();
00496 
00497          for (unsigned local_index=0; local_index<num_cells; local_index++)
00498          {
00499              unsigned global_index = index_low + local_index;
00500              unsigned new_local_index = global_index - p_factory->GetLow();
00501              bool local = p_factory->IsGlobalIndexLocal(global_index);
00502 
00503              bool is_dynamic;
00504              archive & is_dynamic;
00505 
00506              if (is_dynamic)
00507              {
00508  #ifdef CHASTE_CAN_CHECKPOINT_DLLS
00510                  NEVER_REACHED;
00511                  // Ensure the shared object file for this cell model is loaded.
00512                  // We need to do this here, rather than in the class' serialization code,
00513                  // because that code won't be available until this is done...
00514 //                 std::string shared_object_path;
00515 //                 archive & shared_object_path;
00516 //                 DynamicModelLoaderRegistry::Instance()->GetLoader(shared_object_path);
00517  #else
00518                  // Since checkpoints with dynamically loadable cells can only be
00519                  // created on Boost>=1.37, trying to load such a checkpoint on an
00520                  // earlier Boost would give an error when first opening the archive.
00521                  NEVER_REACHED;
00522  #endif // CHASTE_CAN_CHECKPOINT_DLLS
00523              }
00524 
00525              AbstractCardiacCellInterface* p_cell;
00526              AbstractCardiacCellInterface* p_second_cell;
00527              double g_gap;
00528              archive & p_cell;
00529              archive & p_second_cell;
00530              archive & g_gap;
00531              if (local)
00532              {
00533                  rCells[new_local_index] = p_cell; // Add to local cells
00534                  rSecondCells[new_local_index] = p_second_cell;
00535                  rGgaps[new_local_index] = g_gap;
00536              }
00537              else
00538              {
00539                  //not sure how to cover this, we are already looping over local cells...
00540                  NEVER_REACHED;
00541                 // Non-local real cell, so free the memory.
00542                 // delete p_cell;
00543                 // delete p_second_cell;
00544              }
00545          }
00546      }
00547 
00554      template<class Archive>
00555      void SaveExtracellularStimulus(Archive & archive, const unsigned int version) const
00556      {
00557          Archive& r_archive = *ProcessSpecificArchive<Archive>::Get();
00558          const std::vector<boost::shared_ptr<AbstractStimulusFunction> > & r_stimulus_distributed = rGetExtracellularStimulusDistributed();
00559          r_archive & this->mpDistributedVectorFactory; // Needed when loading
00560          const unsigned num_cells = r_stimulus_distributed.size();
00561          r_archive & num_cells;
00562          for (unsigned i=0; i<num_cells; i++)
00563          {
00564              r_archive & r_stimulus_distributed[i];
00565          }
00566      }
00567 
00576      template<class Archive>
00577      void LoadExtracellularStimulus(Archive & archive, const unsigned int version,
00578                                                std::vector<boost::shared_ptr<AbstractStimulusFunction> >& rStimuli,
00579                                                AbstractTetrahedralMesh<SPACE_DIM,SPACE_DIM>* pMesh)
00580      {
00581 
00582         DistributedVectorFactory* p_factory;
00583         archive & p_factory;
00584         unsigned num_cells;
00585         archive & num_cells;
00586         rStimuli.resize(p_factory->GetLocalOwnership());
00587 #ifndef NDEBUG
00588           // Paranoia
00589           for (unsigned i=0; i<rStimuli.size(); i++)
00590           {
00591               assert(rStimuli[i] == NULL);
00592           }
00593 #endif
00594 
00595         // We don't store a cell index in the archive, so need to work out what global
00596         // index this tissue starts up.  If we're migrating (so have an
00597         // original factory) we use the original low index; otherwise we use the current
00598         // low index.
00599         unsigned index_low = p_factory->GetOriginalFactory() ? p_factory->GetOriginalFactory()->GetLow() : p_factory->GetLow();
00600 
00601         assert(pMesh!=NULL);
00602         //unsigned num_cells = pMesh->GetNumNodes();
00603         for (unsigned local_index=0; local_index<num_cells; local_index++)
00604         {
00605           unsigned global_index = index_low + local_index;
00606 
00607           unsigned new_local_index = global_index - p_factory->GetLow();
00608           bool local = p_factory->IsGlobalIndexLocal(global_index);
00609 
00610           boost::shared_ptr<AbstractStimulusFunction> p_stim;
00611           archive & p_stim;//get from archive
00612 
00613           if (local)
00614           {
00615               rStimuli[new_local_index] = p_stim; // Add stimulus to local cells
00616           }
00617           //otherwise we should delete, but I think shared pointers delete themselves?
00618         }
00619     }
00620 };
00621 
00622  // Declare identifier for the serializer
00623  #include "SerializationExportWrapper.hpp"
00624  EXPORT_TEMPLATE_CLASS_SAME_DIMS(ExtendedBidomainTissue)
00625 
00626  namespace boost
00627  {
00628  namespace serialization
00629  {
00630 
00631  template<class Archive, unsigned SPACE_DIM>
00632  inline void save_construct_data(
00633      Archive & ar, const ExtendedBidomainTissue<SPACE_DIM> * t, const unsigned int file_version)
00634  {
00635      //archive the conductivity tensor of the second cell (which may not be dealt with by heartconfig)
00636      c_vector<double, SPACE_DIM>  intracellular_conductivities_second_cell = t->GetIntracellularConductivitiesSecondCell();
00637      //note that simple: ar & intracellular_conductivities_second_cell may not be liked by some boost versions
00638      for (unsigned i = 0; i < SPACE_DIM; i++)
00639      {
00640          ar & intracellular_conductivities_second_cell(i);
00641      }
00642 
00643      const AbstractTetrahedralMesh<SPACE_DIM,SPACE_DIM>* p_mesh = t->pGetMesh();
00644      ar & p_mesh;
00645 
00646      // Don't use the std::vector serialization for cardiac cells, so that we can load them
00647      // more cleverly when migrating checkpoints.
00648      t->SaveExtendedBidomainCells(ar, file_version);
00649      t->SaveExtracellularStimulus(ar, file_version);
00650 
00651      // Creation of conductivity tensors are called by constructor and uses HeartConfig. So make sure that it is
00652      // archived too (needs doing before construction so appears here instead of usual archive location).
00653      HeartConfig* p_config = HeartConfig::Instance();
00654      ar & *p_config;
00655      ar & p_config;
00656  }
00657 
00662  template<class Archive, unsigned SPACE_DIM>
00663  inline void load_construct_data(
00664      Archive & ar, ExtendedBidomainTissue<SPACE_DIM> * t, const unsigned int file_version)
00665  {
00666      //Load conductivities of the conductivity of the second cell.
00667      c_vector<double, SPACE_DIM>  intra_cond_second_cell;
00668      //note that simple: ar & intra_cond_second_cell may not be liked by some boost versions
00669      for (unsigned i = 0; i < SPACE_DIM; i++)
00670      {
00671          double cond;
00672          ar & cond;
00673          intra_cond_second_cell(i) = cond;
00674      }
00675 
00676 
00677      std::vector<AbstractCardiacCellInterface*> cells_distributed;
00678      std::vector<AbstractCardiacCellInterface*> cells_distributed_second_cell;
00679      std::vector<boost::shared_ptr<AbstractStimulusFunction> > extra_stim;
00680      std::vector<double> g_gaps;
00681      AbstractTetrahedralMesh<SPACE_DIM,SPACE_DIM>* p_mesh;
00682      ar & p_mesh;
00683 
00684      // Load only the cells we actually own
00685      t->LoadExtendedBidomainCells(
00686              *ProcessSpecificArchive<Archive>::Get(), file_version, cells_distributed, cells_distributed_second_cell, g_gaps, p_mesh);
00687 
00688      t->LoadExtracellularStimulus(
00689              *ProcessSpecificArchive<Archive>::Get(), file_version, extra_stim, p_mesh);
00690 
00691      // CreateIntracellularConductivityTensor() is called by AbstractCardiacTissue constructor and uses HeartConfig.
00692      // (as does CreateExtracellularConductivityTensor). So make sure that it is
00693      // archived too (needs doing before construction so appears here instead of usual archive location).
00694      HeartConfig* p_config = HeartConfig::Instance();
00695      ar & *p_config;
00696      ar & p_config;
00697 
00698      ::new(t)ExtendedBidomainTissue<SPACE_DIM>(cells_distributed, cells_distributed_second_cell, extra_stim, g_gaps, p_mesh, intra_cond_second_cell);
00699  }
00700  }
00701  } // namespace ...
00702 
00703 
00704 
00705 #endif /*EXTENDEDBIDOMAINTISSUE_HPP_*/

Generated by  doxygen 1.6.2