Chaste  Release::3.4
ExtendedBidomainTissue.hpp
1 /*
2 
3 Copyright (c) 2005-2016, University of Oxford.
4 All rights reserved.
5 
6 University of Oxford means the Chancellor, Masters and Scholars of the
7 University of Oxford, having an administrative office at Wellington
8 Square, Oxford OX1 2JD, UK.
9 
10 This file is part of Chaste.
11 
12 Redistribution and use in source and binary forms, with or without
13 modification, are permitted provided that the following conditions are met:
14  * Redistributions of source code must retain the above copyright notice,
15  this list of conditions and the following disclaimer.
16  * Redistributions in binary form must reproduce the above copyright notice,
17  this list of conditions and the following disclaimer in the documentation
18  and/or other materials provided with the distribution.
19  * Neither the name of the University of Oxford nor the names of its
20  contributors may be used to endorse or promote products derived from this
21  software without specific prior written permission.
22 
23 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
27 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
29 GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
32 OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 
34 */
35 
36 
37 #ifndef EXTENDEDBIDOMAINTISSUE_HPP_
38 #define EXTENDEDBIDOMAINTISSUE_HPP_
39 
40 #include "ChasteSerialization.hpp"
41 #include <boost/serialization/base_object.hpp>
42 
43 #include <vector>
44 #include "UblasMatrixInclude.hpp"
45 
46 #include "AbstractStimulusFunction.hpp"
47 #include "AbstractStimulusFactory.hpp"
48 #include "AbstractConductivityTensors.hpp"
49 
50 #include "AbstractCardiacTissue.hpp"
51 
76 template <unsigned SPACE_DIM>
77 class ExtendedBidomainTissue : public virtual AbstractCardiacTissue<SPACE_DIM>
78 {
79 private:
80  friend class TestExtendedBidomainTissue; // for testing.
81 
83  friend class boost::serialization::access;
90  template<class Archive>
91  void serialize(Archive & archive, const unsigned int version)
92  {
93  archive & boost::serialization::base_object<AbstractCardiacTissue<SPACE_DIM> >(*this);
94  // Conductivity tensors are dealt with by HeartConfig, and the caches get regenerated.
95 
96  archive & mAmFirstCell;
97  archive & mAmSecondCell;
98  archive & mAmGap;
99  archive & mCmFirstCell;
100  archive & mCmSecondCell;
101  archive & mGGap;
103  }
104 
107 
112  c_vector<double, SPACE_DIM> mIntracellularConductivitiesSecondCell;
113 
114 
117 
123 
129 
135 
141 
143  std::vector< AbstractCardiacCellInterface* > mCellsDistributedSecondCell;
144 
146  std::vector<boost::shared_ptr<AbstractStimulusFunction> > mExtracellularStimuliDistributed;
147 
149  std::vector<double> mGgapDistributed;
150 
152  double mAmFirstCell;
156  double mAmGap;
158  double mCmFirstCell;
162  double mGGap;
163 
169 
174 
189  void UpdateAdditionalCaches(unsigned globalIndex, unsigned localIndex, double nextTime);
190 
202 
204  std::vector<boost::shared_ptr<AbstractChasteRegion<SPACE_DIM> > > mGgapHeterogeneityRegions;
206  std::vector<double> mGgapValues;
207 
208 public:
209 
217 
227  ExtendedBidomainTissue(std::vector<AbstractCardiacCellInterface*> & rCellsDistributed,
228  std::vector<AbstractCardiacCellInterface*> & rSecondCellsDistributed,
229  std::vector<boost::shared_ptr<AbstractStimulusFunction> > & rExtraStimuliDistributed,
230  std::vector<double>& rGgapsDistributed,
232  c_vector<double, SPACE_DIM> intracellularConductivitiesSecondCell);
233 
237  virtual ~ExtendedBidomainTissue();
238 
244  void SetIntracellularConductivitiesSecondCell(c_vector<double, SPACE_DIM> conductivities);
245 
251  AbstractCardiacCellInterface* GetCardiacSecondCell( unsigned globalIndex );
252 
253 
259  boost::shared_ptr<AbstractStimulusFunction> GetExtracellularStimulus( unsigned globalIndex );
260 
264  const std::vector<AbstractCardiacCellInterface*>& rGetSecondCellsDistributed() const;
265 
269  const std::vector<double>& rGetGapsDistributed() const;
270 
271 
275  const std::vector<boost::shared_ptr<AbstractStimulusFunction> >& rGetExtracellularStimulusDistributed() const;
276 
277 
281  c_vector<double, SPACE_DIM> GetIntracellularConductivitiesSecondCell() const;
282 
292  virtual void SolveCellSystems(Vec existingSolution, double time, double nextTime, bool updateVoltage = false);
293 
298 
305  void SetGgapHeterogeneities ( std::vector<boost::shared_ptr<AbstractChasteRegion<SPACE_DIM> > > & rGgapHeterogeneityRegions, std::vector<double> rGgapValues);
306 
313 
318  const c_matrix<double, SPACE_DIM, SPACE_DIM>& rGetExtracellularConductivityTensor(unsigned elementIndex);
319 
324  const c_matrix<double, SPACE_DIM, SPACE_DIM>& rGetIntracellularConductivityTensorSecondCell(unsigned elementIndex);
325 
326 
329 
332 
335 
338 
342  double GetAmFirstCell();
343 
347  double GetAmSecondCell();
348 
352  double GetAmGap();
353 
357  double GetCmFirstCell();
358 
362  double GetCmSecondCell();
363 
367  double GetGGap();
368 
372  void SetAmFirstCell(double value);
373 
377  void SetAmSecondCell(double value);
378 
382  void SetAmGap(double value);
383 
387  void SetCmFirstCell(double value);
388 
392  void SetCmSecondCell(double value);
393 
397  void SetGGap(double value);
398 
407 
415  void SetUserSuppliedExtracellularStimulus(bool flag);
416 
417 
424  template<class Archive>
425  void SaveExtendedBidomainCells(Archive & archive, const unsigned int version) const
426  {
427  Archive& r_archive = *ProcessSpecificArchive<Archive>::Get();
428  const std::vector<AbstractCardiacCellInterface*> & r_cells_distributed = this->rGetCellsDistributed();
429  const std::vector<AbstractCardiacCellInterface*> & r_cells_distributed_second_cell = rGetSecondCellsDistributed();
430  const std::vector<double> & r_ggaps_distributed = rGetGapsDistributed();
431 
432  r_archive & this->mpDistributedVectorFactory; // Needed when loading
433  const unsigned num_cells = r_cells_distributed.size();
434  r_archive & num_cells;
435  for (unsigned i=0; i<num_cells; i++)
436  {
437  AbstractDynamicallyLoadableEntity* p_entity = dynamic_cast<AbstractDynamicallyLoadableEntity*>(r_cells_distributed[i]);
438  bool is_dynamic = (p_entity != NULL);
439  r_archive & is_dynamic;
440  if (is_dynamic)
441  {
442  #ifdef CHASTE_CAN_CHECKPOINT_DLLS
445  //r_archive & p_entity->GetLoader()->GetLoadableModulePath();
446  #else
447  // We should have thrown an exception before this point
449  #endif // CHASTE_CAN_CHECKPOINT_DLLS
450  }
451  r_archive & r_cells_distributed[i];
452  r_archive & r_cells_distributed_second_cell[i];
453  r_archive & r_ggaps_distributed[i];
454  }
455  }
456 
471  template<class Archive>
472  static void LoadExtendedBidomainCells(Archive & archive, const unsigned int version,
473  std::vector<AbstractCardiacCellInterface*>& rCells,
474  std::vector<AbstractCardiacCellInterface*>& rSecondCells,
475  std::vector<double>& rGgaps,
477  {
478  assert(pMesh!=NULL);
479  DistributedVectorFactory* p_factory;
480  archive & p_factory;
481  unsigned num_cells;
482  archive & num_cells;
483  rCells.resize(p_factory->GetLocalOwnership());
484  rSecondCells.resize(p_factory->GetLocalOwnership());
485  rGgaps.resize(p_factory->GetLocalOwnership());
486  #ifndef NDEBUG
487  // Paranoia
488  assert(rCells.size() == rSecondCells.size());
489  for (unsigned i=0; i<rCells.size(); i++)
490  {
491  assert(rCells[i] == NULL);
492  assert(rSecondCells[i] == NULL);
493  }
494  #endif
495 
496  // We don't store a cell index in the archive, so need to work out what global
497  // index this tissue starts up. If we're migrating (so have an
498  // original factory) we use the original low index; otherwise we use the current
499  // low index.
500  unsigned index_low = p_factory->GetOriginalFactory() ? p_factory->GetOriginalFactory()->GetLow() : p_factory->GetLow();
501 
502  for (unsigned local_index=0; local_index<num_cells; local_index++)
503  {
504  unsigned global_index = index_low + local_index;
505  unsigned new_local_index = global_index - p_factory->GetLow();
506  bool local = p_factory->IsGlobalIndexLocal(global_index);
507 
508  bool is_dynamic;
509  archive & is_dynamic;
510 
511  if (is_dynamic)
512  {
513  #ifdef CHASTE_CAN_CHECKPOINT_DLLS
516  // Ensure the shared object file for this cell model is loaded.
517  // We need to do this here, rather than in the class' serialization code,
518  // because that code won't be available until this is done...
519 // std::string shared_object_path;
520 // archive & shared_object_path;
521 // DynamicModelLoaderRegistry::Instance()->GetLoader(shared_object_path);
522  #else
523  // Since checkpoints with dynamically loadable cells can only be
524  // created on Boost>=1.37, trying to load such a checkpoint on an
525  // earlier Boost would give an error when first opening the archive.
527  #endif // CHASTE_CAN_CHECKPOINT_DLLS
528  }
529 
531  AbstractCardiacCellInterface* p_second_cell;
532  double g_gap;
533  archive & p_cell;
534  archive & p_second_cell;
535  archive & g_gap;
536  if (local)
537  {
538  rCells[new_local_index] = p_cell; // Add to local cells
539  rSecondCells[new_local_index] = p_second_cell;
540  rGgaps[new_local_index] = g_gap;
541  }
542  else
543  {
544  //not sure how to cover this, we are already looping over local cells...
546  // Non-local real cell, so free the memory.
547  // delete p_cell;
548  // delete p_second_cell;
549  }
550  }
551  }
552 
559  template<class Archive>
560  void SaveExtracellularStimulus(Archive & archive, const unsigned int version) const
561  {
562  Archive& r_archive = *ProcessSpecificArchive<Archive>::Get();
563  const std::vector<boost::shared_ptr<AbstractStimulusFunction> > & r_stimulus_distributed = rGetExtracellularStimulusDistributed();
564  r_archive & this->mpDistributedVectorFactory; // Needed when loading
565  const unsigned num_cells = r_stimulus_distributed.size();
566  r_archive & num_cells;
567  for (unsigned i=0; i<num_cells; i++)
568  {
569  r_archive & r_stimulus_distributed[i];
570  }
571  }
572 
581  template<class Archive>
582  void LoadExtracellularStimulus(Archive & archive, const unsigned int version,
583  std::vector<boost::shared_ptr<AbstractStimulusFunction> >& rStimuli,
585  {
586 
587  DistributedVectorFactory* p_factory;
588  archive & p_factory;
589  unsigned num_cells;
590  archive & num_cells;
591  rStimuli.resize(p_factory->GetLocalOwnership());
592 #ifndef NDEBUG
593  // Paranoia
594  for (unsigned i=0; i<rStimuli.size(); i++)
595  {
596  assert(rStimuli[i] == NULL);
597  }
598 #endif
599 
600  // We don't store a cell index in the archive, so need to work out what global
601  // index this tissue starts up. If we're migrating (so have an
602  // original factory) we use the original low index; otherwise we use the current
603  // low index.
604  unsigned index_low = p_factory->GetOriginalFactory() ? p_factory->GetOriginalFactory()->GetLow() : p_factory->GetLow();
605 
606  assert(pMesh!=NULL);
607  //unsigned num_cells = pMesh->GetNumNodes();
608  for (unsigned local_index=0; local_index<num_cells; local_index++)
609  {
610  unsigned global_index = index_low + local_index;
611 
612  unsigned new_local_index = global_index - p_factory->GetLow();
613  bool local = p_factory->IsGlobalIndexLocal(global_index);
614 
615  boost::shared_ptr<AbstractStimulusFunction> p_stim;
616  archive & p_stim;//get from archive
617 
618  if (local)
619  {
620  rStimuli[new_local_index] = p_stim; // Add stimulus to local cells
621  }
622  //otherwise we should delete, but I think shared pointers delete themselves?
623  }
624  }
625 };
626 
627  // Declare identifier for the serializer
630 
631  namespace boost
632  {
633  namespace serialization
634  {
635 
636  template<class Archive, unsigned SPACE_DIM>
637  inline void save_construct_data(
638  Archive & ar, const ExtendedBidomainTissue<SPACE_DIM> * t, const unsigned int file_version)
639  {
640  //archive the conductivity tensor of the second cell (which may not be dealt with by heartconfig)
641  c_vector<double, SPACE_DIM> intracellular_conductivities_second_cell = t->GetIntracellularConductivitiesSecondCell();
642  //note that simple: ar & intracellular_conductivities_second_cell may not be liked by some boost versions
643  for (unsigned i = 0; i < SPACE_DIM; i++)
644  {
645  ar & intracellular_conductivities_second_cell(i);
646  }
647 
649  ar & p_mesh;
650 
651  // Don't use the std::vector serialization for cardiac cells, so that we can load them
652  // more cleverly when migrating checkpoints.
653  t->SaveExtendedBidomainCells(ar, file_version);
654  t->SaveExtracellularStimulus(ar, file_version);
655 
656  // Creation of conductivity tensors are called by constructor and uses HeartConfig. So make sure that it is
657  // archived too (needs doing before construction so appears here instead of usual archive location).
658  HeartConfig* p_config = HeartConfig::Instance();
659  ar & *p_config;
660  ar & p_config;
661  }
662 
667  template<class Archive, unsigned SPACE_DIM>
668  inline void load_construct_data(
669  Archive & ar, ExtendedBidomainTissue<SPACE_DIM> * t, const unsigned int file_version)
670  {
671  //Load conductivities of the conductivity of the second cell.
672  c_vector<double, SPACE_DIM> intra_cond_second_cell;
673  //note that simple: ar & intra_cond_second_cell may not be liked by some boost versions
674  for (unsigned i = 0; i < SPACE_DIM; i++)
675  {
676  double cond;
677  ar & cond;
678  intra_cond_second_cell(i) = cond;
679  }
680 
681 
682  std::vector<AbstractCardiacCellInterface*> cells_distributed;
683  std::vector<AbstractCardiacCellInterface*> cells_distributed_second_cell;
684  std::vector<boost::shared_ptr<AbstractStimulusFunction> > extra_stim;
685  std::vector<double> g_gaps;
687  ar & p_mesh;
688 
689  // Load only the cells we actually own
691  *ProcessSpecificArchive<Archive>::Get(), file_version, cells_distributed, cells_distributed_second_cell, g_gaps, p_mesh);
692 
694  *ProcessSpecificArchive<Archive>::Get(), file_version, extra_stim, p_mesh);
695 
696  // CreateIntracellularConductivityTensor() is called by AbstractCardiacTissue constructor and uses HeartConfig.
697  // (as does CreateExtracellularConductivityTensor). So make sure that it is
698  // archived too (needs doing before construction so appears here instead of usual archive location).
699  HeartConfig* p_config = HeartConfig::Instance();
700  ar & *p_config;
701  ar & p_config;
702 
703  ::new(t)ExtendedBidomainTissue<SPACE_DIM>(cells_distributed, cells_distributed_second_cell, extra_stim, g_gaps, p_mesh, intra_cond_second_cell);
704  }
705  }
706  } // namespace ...
707 
708 
709 
710 #endif /*EXTENDEDBIDOMAINTISSUE_HPP_*/
AbstractConductivityTensors< SPACE_DIM, SPACE_DIM > * mpExtracellularConductivityTensors
ReplicatableVector mIionicCacheReplicatedSecondCell
std::vector< boost::shared_ptr< AbstractChasteRegion< SPACE_DIM > > > mGgapHeterogeneityRegions
ReplicatableVector & rGetExtracellularStimulusCacheReplicated()
DistributedVectorFactory * mpDistributedVectorFactory
ReplicatableVector & rGetIionicCacheReplicatedSecondCell()
virtual void SolveCellSystems(Vec existingSolution, double time, double nextTime, bool updateVoltage=false)
c_vector< double, SPACE_DIM > GetIntracellularConductivitiesSecondCell() const
std::vector< AbstractCardiacCellInterface * > mCellsDistributedSecondCell
ReplicatableVector & rGetGgapCacheReplicated()
void SetGgapHeterogeneities(std::vector< boost::shared_ptr< AbstractChasteRegion< SPACE_DIM > > > &rGgapHeterogeneityRegions, std::vector< double > rGgapValues)
AbstractCardiacCellInterface * GetCardiacSecondCell(unsigned globalIndex)
c_vector< double, SPACE_DIM > mIntracellularConductivitiesSecondCell
const c_matrix< double, SPACE_DIM, SPACE_DIM > & rGetExtracellularConductivityTensor(unsigned elementIndex)
void SetAmSecondCell(double value)
std::vector< double > mGgapDistributed
void SaveExtendedBidomainCells(Archive &archive, const unsigned int version) const
void UpdateAdditionalCaches(unsigned globalIndex, unsigned localIndex, double nextTime)
std::vector< boost::shared_ptr< AbstractStimulusFunction > > mExtracellularStimuliDistributed
#define NEVER_REACHED
Definition: Exception.hpp:206
AbstractConductivityTensors< SPACE_DIM, SPACE_DIM > * mpIntracellularConductivityTensorsSecondCell
boost::shared_ptr< AbstractStimulusFunction > GetExtracellularStimulus(unsigned globalIndex)
static void LoadExtendedBidomainCells(Archive &archive, const unsigned int version, std::vector< AbstractCardiacCellInterface * > &rCells, std::vector< AbstractCardiacCellInterface * > &rSecondCells, std::vector< double > &rGgaps, AbstractTetrahedralMesh< SPACE_DIM, SPACE_DIM > *pMesh)
void SetCmSecondCell(double value)
static Archive * Get(void)
const std::vector< AbstractCardiacCellInterface * > & rGetSecondCellsDistributed() const
ReplicatableVector mExtracellularStimulusCacheReplicated
#define EXPORT_TEMPLATE_CLASS_SAME_DIMS(CLASS)
ReplicatableVector mGgapCacheReplicated
const std::vector< boost::shared_ptr< AbstractStimulusFunction > > & rGetExtracellularStimulusDistributed() const
ReplicatableVector & rGetIntracellularStimulusCacheReplicatedSecondCell()
std::vector< double > mGgapValues
const std::vector< double > & rGetGapsDistributed() const
ReplicatableVector mIntracellularStimulusCacheReplicatedSecondCell
const std::vector< AbstractCardiacCellInterface * > & rGetCellsDistributed() const
void LoadExtracellularStimulus(Archive &archive, const unsigned int version, std::vector< boost::shared_ptr< AbstractStimulusFunction > > &rStimuli, AbstractTetrahedralMesh< SPACE_DIM, SPACE_DIM > *pMesh)
void SetIntracellularConductivitiesSecondCell(c_vector< double, SPACE_DIM > conductivities)
void SetUserSuppliedExtracellularStimulus(bool flag)
void serialize(Archive &archive, const unsigned int version)
const c_matrix< double, SPACE_DIM, SPACE_DIM > & rGetIntracellularConductivityTensorSecondCell(unsigned elementIndex)
static HeartConfig * Instance()
void SaveExtracellularStimulus(Archive &archive, const unsigned int version) const
const AbstractTetrahedralMesh< ELEMENT_DIM, ELEMENT_DIM > * pGetMesh() const
ExtendedBidomainTissue(AbstractCardiacCellFactory< SPACE_DIM > *pCellFactory, AbstractCardiacCellFactory< SPACE_DIM > *pCellFactorySecondCell, AbstractStimulusFactory< SPACE_DIM > *pExtracellularStimulusFactory)