Chaste  Release::2017.1
ExtendedBidomainTissue.hpp
1 /*
2 
3 Copyright (c) 2005-2017, 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  // Could only happen on Mac OS X, and will probably be trapped earlier.
525  #endif // CHASTE_CAN_CHECKPOINT_DLLS
526  }
527 
529  AbstractCardiacCellInterface* p_second_cell;
530  double g_gap;
531  archive & p_cell;
532  archive & p_second_cell;
533  archive & g_gap;
534  if (local)
535  {
536  rCells[new_local_index] = p_cell; // Add to local cells
537  rSecondCells[new_local_index] = p_second_cell;
538  rGgaps[new_local_index] = g_gap;
539  }
540  else
541  {
542  //not sure how to cover this, we are already looping over local cells...
544  // Non-local real cell, so free the memory.
545  // delete p_cell;
546  // delete p_second_cell;
547  }
548  }
549  }
550 
557  template<class Archive>
558  void SaveExtracellularStimulus(Archive & archive, const unsigned int version) const
559  {
560  Archive& r_archive = *ProcessSpecificArchive<Archive>::Get();
561  const std::vector<boost::shared_ptr<AbstractStimulusFunction> > & r_stimulus_distributed = rGetExtracellularStimulusDistributed();
562  r_archive & this->mpDistributedVectorFactory; // Needed when loading
563  const unsigned num_cells = r_stimulus_distributed.size();
564  r_archive & num_cells;
565  for (unsigned i=0; i<num_cells; i++)
566  {
567  r_archive & r_stimulus_distributed[i];
568  }
569  }
570 
579  template<class Archive>
580  void LoadExtracellularStimulus(Archive & archive, const unsigned int version,
581  std::vector<boost::shared_ptr<AbstractStimulusFunction> >& rStimuli,
583  {
584 
585  DistributedVectorFactory* p_factory;
586  archive & p_factory;
587  unsigned num_cells;
588  archive & num_cells;
589  rStimuli.resize(p_factory->GetLocalOwnership());
590 #ifndef NDEBUG
591  // Paranoia
592  for (unsigned i=0; i<rStimuli.size(); i++)
593  {
594  assert(rStimuli[i] == NULL);
595  }
596 #endif
597 
598  // We don't store a cell index in the archive, so need to work out what global
599  // index this tissue starts up. If we're migrating (so have an
600  // original factory) we use the original low index; otherwise we use the current
601  // low index.
602  unsigned index_low = p_factory->GetOriginalFactory() ? p_factory->GetOriginalFactory()->GetLow() : p_factory->GetLow();
603 
604  assert(pMesh!=NULL);
605  //unsigned num_cells = pMesh->GetNumNodes();
606  for (unsigned local_index=0; local_index<num_cells; local_index++)
607  {
608  unsigned global_index = index_low + local_index;
609 
610  unsigned new_local_index = global_index - p_factory->GetLow();
611  bool local = p_factory->IsGlobalIndexLocal(global_index);
612 
613  boost::shared_ptr<AbstractStimulusFunction> p_stim;
614  archive & p_stim;//get from archive
615 
616  if (local)
617  {
618  rStimuli[new_local_index] = p_stim; // Add stimulus to local cells
619  }
620  //otherwise we should delete, but I think shared pointers delete themselves?
621  }
622  }
623 };
624 
625  // Declare identifier for the serializer
628 
629  namespace boost
630  {
631  namespace serialization
632  {
633 
634  template<class Archive, unsigned SPACE_DIM>
635  inline void save_construct_data(
636  Archive & ar, const ExtendedBidomainTissue<SPACE_DIM> * t, const unsigned int file_version)
637  {
638  //archive the conductivity tensor of the second cell (which may not be dealt with by heartconfig)
639  c_vector<double, SPACE_DIM> intracellular_conductivities_second_cell = t->GetIntracellularConductivitiesSecondCell();
640  //note that simple: ar & intracellular_conductivities_second_cell may not be liked by some boost versions
641  for (unsigned i = 0; i < SPACE_DIM; i++)
642  {
643  ar & intracellular_conductivities_second_cell(i);
644  }
645 
647  ar & p_mesh;
648 
649  // Don't use the std::vector serialization for cardiac cells, so that we can load them
650  // more cleverly when migrating checkpoints.
651  t->SaveExtendedBidomainCells(ar, file_version);
652  t->SaveExtracellularStimulus(ar, file_version);
653 
654  // Creation of conductivity tensors are called by constructor and uses HeartConfig. So make sure that it is
655  // archived too (needs doing before construction so appears here instead of usual archive location).
656  HeartConfig* p_config = HeartConfig::Instance();
657  ar & *p_config;
658  ar & p_config;
659  }
660 
665  template<class Archive, unsigned SPACE_DIM>
666  inline void load_construct_data(
667  Archive & ar, ExtendedBidomainTissue<SPACE_DIM> * t, const unsigned int file_version)
668  {
669  //Load conductivities of the conductivity of the second cell.
670  c_vector<double, SPACE_DIM> intra_cond_second_cell;
671  //note that simple: ar & intra_cond_second_cell may not be liked by some boost versions
672  for (unsigned i = 0; i < SPACE_DIM; i++)
673  {
674  double cond;
675  ar & cond;
676  intra_cond_second_cell(i) = cond;
677  }
678 
679 
680  std::vector<AbstractCardiacCellInterface*> cells_distributed;
681  std::vector<AbstractCardiacCellInterface*> cells_distributed_second_cell;
682  std::vector<boost::shared_ptr<AbstractStimulusFunction> > extra_stim;
683  std::vector<double> g_gaps;
685  ar & p_mesh;
686 
687  // Load only the cells we actually own
689  *ProcessSpecificArchive<Archive>::Get(), file_version, cells_distributed, cells_distributed_second_cell, g_gaps, p_mesh);
690 
692  *ProcessSpecificArchive<Archive>::Get(), file_version, extra_stim, p_mesh);
693 
694  // CreateIntracellularConductivityTensor() is called by AbstractCardiacTissue constructor and uses HeartConfig.
695  // (as does CreateExtracellularConductivityTensor). So make sure that it is
696  // archived too (needs doing before construction so appears here instead of usual archive location).
697  HeartConfig* p_config = HeartConfig::Instance();
698  ar & *p_config;
699  ar & p_config;
700 
701  ::new(t)ExtendedBidomainTissue<SPACE_DIM>(cells_distributed, cells_distributed_second_cell, extra_stim, g_gaps, p_mesh, intra_cond_second_cell);
702  }
703  }
704  } // namespace ...
705 
706 #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)
gcov doesn&#39;t like this file...
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)