Chaste Commit::1fd4e48e3990e67db148bc1bc4cf6991a0049d0c
ExtendedBidomainTissue.hpp
1/*
2
3Copyright (c) 2005-2024, University of Oxford.
4All rights reserved.
5
6University of Oxford means the Chancellor, Masters and Scholars of the
7University of Oxford, having an administrative office at Wellington
8Square, Oxford OX1 2JD, UK.
9
10This file is part of Chaste.
11
12Redistribution and use in source and binary forms, with or without
13modification, 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
23THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
27LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
29GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
32OF 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
41#include <boost/serialization/base_object.hpp>
42
43#include <vector>
45
46#include "AbstractStimulusFunction.hpp"
47#include "AbstractStimulusFactory.hpp"
48#include "AbstractConductivityTensors.hpp"
49
50#include "AbstractCardiacTissue.hpp"
51
76template <unsigned SPACE_DIM>
77class ExtendedBidomainTissue : public virtual AbstractCardiacTissue<SPACE_DIM>
78{
79private:
80 friend class TestExtendedBidomainTissue; // for testing.
81
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
156 double mAmGap;
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
208public:
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
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
646 const AbstractTetrahedralMesh<SPACE_DIM,SPACE_DIM>* p_mesh = t->pGetMesh();
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).
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
688 t->LoadExtendedBidomainCells(
689 *ProcessSpecificArchive<Archive>::Get(), file_version, cells_distributed, cells_distributed_second_cell, g_gaps, p_mesh);
690
691 t->LoadExtracellularStimulus(
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).
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_*/
#define NEVER_REACHED
gcov doesn't like this file...
#define EXPORT_TEMPLATE_CLASS_SAME_DIMS(CLASS)
const std::vector< AbstractCardiacCellInterface * > & rGetCellsDistributed() const
DistributedVectorFactory * mpDistributedVectorFactory
Forward declaration which is going to be used for friendship.
DistributedVectorFactory * GetOriginalFactory()
bool IsGlobalIndexLocal(unsigned globalIndex)
ReplicatableVector mExtracellularStimulusCacheReplicated
void UpdateAdditionalCaches(unsigned globalIndex, unsigned localIndex, double nextTime)
void serialize(Archive &archive, const unsigned int version)
ReplicatableVector & rGetExtracellularStimulusCacheReplicated()
const std::vector< boost::shared_ptr< AbstractStimulusFunction > > & rGetExtracellularStimulusDistributed() const
virtual void SolveCellSystems(Vec existingSolution, double time, double nextTime, bool updateVoltage=false)
void SetGgapHeterogeneities(std::vector< boost::shared_ptr< AbstractChasteRegion< SPACE_DIM > > > &rGgapHeterogeneityRegions, std::vector< double > rGgapValues)
ReplicatableVector mIionicCacheReplicatedSecondCell
std::vector< boost::shared_ptr< AbstractChasteRegion< SPACE_DIM > > > mGgapHeterogeneityRegions
std::vector< double > mGgapValues
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)
ReplicatableVector & rGetIionicCacheReplicatedSecondCell()
ReplicatableVector & rGetGgapCacheReplicated()
AbstractConductivityTensors< SPACE_DIM, SPACE_DIM > * mpExtracellularConductivityTensors
const std::vector< AbstractCardiacCellInterface * > & rGetSecondCellsDistributed() const
std::vector< AbstractCardiacCellInterface * > mCellsDistributedSecondCell
ReplicatableVector mIntracellularStimulusCacheReplicatedSecondCell
c_vector< double, SPACE_DIM > mIntracellularConductivitiesSecondCell
boost::shared_ptr< AbstractStimulusFunction > GetExtracellularStimulus(unsigned globalIndex)
std::vector< boost::shared_ptr< AbstractStimulusFunction > > mExtracellularStimuliDistributed
ReplicatableVector & rGetIntracellularStimulusCacheReplicatedSecondCell()
AbstractConductivityTensors< SPACE_DIM, SPACE_DIM > * mpIntracellularConductivityTensorsSecondCell
void LoadExtracellularStimulus(Archive &archive, const unsigned int version, std::vector< boost::shared_ptr< AbstractStimulusFunction > > &rStimuli, AbstractTetrahedralMesh< SPACE_DIM, SPACE_DIM > *pMesh)
void SaveExtracellularStimulus(Archive &archive, const unsigned int version) const
c_vector< double, SPACE_DIM > GetIntracellularConductivitiesSecondCell() const
const c_matrix< double, SPACE_DIM, SPACE_DIM > & rGetExtracellularConductivityTensor(unsigned elementIndex)
std::vector< double > mGgapDistributed
friend class boost::serialization::access
AbstractCardiacCellInterface * GetCardiacSecondCell(unsigned globalIndex)
const std::vector< double > & rGetGapsDistributed() const
void SetUserSuppliedExtracellularStimulus(bool flag)
void SaveExtendedBidomainCells(Archive &archive, const unsigned int version) const
void SetIntracellularConductivitiesSecondCell(c_vector< double, SPACE_DIM > conductivities)
const c_matrix< double, SPACE_DIM, SPACE_DIM > & rGetIntracellularConductivityTensorSecondCell(unsigned elementIndex)
ReplicatableVector mGgapCacheReplicated
static HeartConfig * Instance()