Chaste Release::3.1
|
00001 /* 00002 00003 Copyright (c) 2005-2012, 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 <boost/numeric/ublas/matrix.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 ~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 00438 r_archive & p_entity->GetLoader()->GetLoadableModulePath(); 00439 #else 00440 // We should have thrown an exception before this point 00441 NEVER_REACHED; 00442 #endif // CHASTE_CAN_CHECKPOINT_DLLS 00443 } 00444 r_archive & r_cells_distributed[i]; 00445 r_archive & r_cells_distributed_second_cell[i]; 00446 r_archive & r_ggaps_distributed[i]; 00447 } 00448 } 00449 00464 template<class Archive> 00465 static void LoadExtendedBidomainCells(Archive & archive, const unsigned int version, 00466 std::vector<AbstractCardiacCellInterface*>& rCells, 00467 std::vector<AbstractCardiacCellInterface*>& rSecondCells, 00468 std::vector<double>& rGgaps, 00469 AbstractTetrahedralMesh<SPACE_DIM,SPACE_DIM>* pMesh) 00470 { 00471 assert(pMesh!=NULL); 00472 DistributedVectorFactory* p_factory; 00473 archive & p_factory; 00474 unsigned num_cells; 00475 archive & num_cells; 00476 rCells.resize(p_factory->GetLocalOwnership()); 00477 rSecondCells.resize(p_factory->GetLocalOwnership()); 00478 rGgaps.resize(p_factory->GetLocalOwnership()); 00479 #ifndef NDEBUG 00480 // Paranoia 00481 assert(rCells.size() == rSecondCells.size()); 00482 for (unsigned i=0; i<rCells.size(); i++) 00483 { 00484 assert(rCells[i] == NULL); 00485 assert(rSecondCells[i] == NULL); 00486 } 00487 #endif 00488 00489 // We don't store a cell index in the archive, so need to work out what global 00490 // index this tissue starts up. If we're migrating (so have an 00491 // original factory) we use the original low index; otherwise we use the current 00492 // low index. 00493 unsigned index_low = p_factory->GetOriginalFactory() ? p_factory->GetOriginalFactory()->GetLow() : p_factory->GetLow(); 00494 00495 for (unsigned local_index=0; local_index<num_cells; local_index++) 00496 { 00497 unsigned global_index = index_low + local_index; 00498 unsigned new_local_index = global_index - p_factory->GetLow(); 00499 bool local = p_factory->IsGlobalIndexLocal(global_index); 00500 00501 bool is_dynamic; 00502 archive & is_dynamic; 00503 00504 if (is_dynamic) 00505 { 00506 #ifdef CHASTE_CAN_CHECKPOINT_DLLS 00507 // Ensure the shared object file for this cell model is loaded. 00508 // We need to do this here, rather than in the class' serialization code, 00509 // because that code won't be available until this is done... 00510 std::string shared_object_path; 00511 archive & shared_object_path; 00512 DynamicModelLoaderRegistry::Instance()->GetLoader(shared_object_path); 00513 #else 00514 // Since checkpoints with dynamically loadable cells can only be 00515 // created on Boost>=1.37, trying to load such a checkpoint on an 00516 // earlier Boost would give an error when first opening the archive. 00517 NEVER_REACHED; 00518 #endif // CHASTE_CAN_CHECKPOINT_DLLS 00519 } 00520 00521 AbstractCardiacCellInterface* p_cell; 00522 AbstractCardiacCellInterface* p_second_cell; 00523 double g_gap; 00524 archive & p_cell; 00525 archive & p_second_cell; 00526 archive & g_gap; 00527 if (local) 00528 { 00529 rCells[new_local_index] = p_cell; // Add to local cells 00530 rSecondCells[new_local_index] = p_second_cell; 00531 rGgaps[new_local_index] = g_gap; 00532 } 00533 else 00534 { 00535 //not sure how to cover this, we are already looping over local cells... 00536 NEVER_REACHED; 00537 // Non-local real cell, so free the memory. 00538 // delete p_cell; 00539 // delete p_second_cell; 00540 } 00541 } 00542 } 00543 00550 template<class Archive> 00551 void SaveExtracellularStimulus(Archive & archive, const unsigned int version) const 00552 { 00553 Archive& r_archive = *ProcessSpecificArchive<Archive>::Get(); 00554 const std::vector<boost::shared_ptr<AbstractStimulusFunction> > & r_stimulus_distributed = rGetExtracellularStimulusDistributed(); 00555 r_archive & this->mpDistributedVectorFactory; // Needed when loading 00556 const unsigned num_cells = r_stimulus_distributed.size(); 00557 r_archive & num_cells; 00558 for (unsigned i=0; i<num_cells; i++) 00559 { 00560 r_archive & r_stimulus_distributed[i]; 00561 } 00562 } 00563 00572 template<class Archive> 00573 void LoadExtracellularStimulus(Archive & archive, const unsigned int version, 00574 std::vector<boost::shared_ptr<AbstractStimulusFunction> >& rStimuli, 00575 AbstractTetrahedralMesh<SPACE_DIM,SPACE_DIM>* pMesh) 00576 { 00577 00578 DistributedVectorFactory* p_factory; 00579 archive & p_factory; 00580 unsigned num_cells; 00581 archive & num_cells; 00582 rStimuli.resize(p_factory->GetLocalOwnership()); 00583 #ifndef NDEBUG 00584 // Paranoia 00585 for (unsigned i=0; i<rStimuli.size(); i++) 00586 { 00587 assert(rStimuli[i] == NULL); 00588 } 00589 #endif 00590 00591 // We don't store a cell index in the archive, so need to work out what global 00592 // index this tissue starts up. If we're migrating (so have an 00593 // original factory) we use the original low index; otherwise we use the current 00594 // low index. 00595 unsigned index_low = p_factory->GetOriginalFactory() ? p_factory->GetOriginalFactory()->GetLow() : p_factory->GetLow(); 00596 00597 assert(pMesh!=NULL); 00598 //unsigned num_cells = pMesh->GetNumNodes(); 00599 for (unsigned local_index=0; local_index<num_cells; local_index++) 00600 { 00601 unsigned global_index = index_low + local_index; 00602 00603 unsigned new_local_index = global_index - p_factory->GetLow(); 00604 bool local = p_factory->IsGlobalIndexLocal(global_index); 00605 00606 boost::shared_ptr<AbstractStimulusFunction> p_stim; 00607 archive & p_stim;//get from archive 00608 00609 if (local) 00610 { 00611 rStimuli[new_local_index] = p_stim; // Add stimulus to local cells 00612 } 00613 //otherwise we should delete, but I think shared pointers delete themselves? 00614 } 00615 } 00616 }; 00617 00618 // Declare identifier for the serializer 00619 #include "SerializationExportWrapper.hpp" 00620 EXPORT_TEMPLATE_CLASS_SAME_DIMS(ExtendedBidomainTissue) 00621 00622 namespace boost 00623 { 00624 namespace serialization 00625 { 00626 00627 template<class Archive, unsigned SPACE_DIM> 00628 inline void save_construct_data( 00629 Archive & ar, const ExtendedBidomainTissue<SPACE_DIM> * t, const unsigned int file_version) 00630 { 00631 //archive the conductivity tensor of the second cell (which may not be dealt with by heartconfig) 00632 c_vector<double, SPACE_DIM> intracellular_conductivities_second_cell = t->GetIntracellularConductivitiesSecondCell(); 00633 //note that simple: ar & intracellular_conductivities_second_cell may not be liked by some boost versions 00634 for (unsigned i = 0; i < SPACE_DIM; i++) 00635 { 00636 ar & intracellular_conductivities_second_cell(i); 00637 } 00638 00639 const AbstractTetrahedralMesh<SPACE_DIM,SPACE_DIM>* p_mesh = t->pGetMesh(); 00640 ar & p_mesh; 00641 00642 // Don't use the std::vector serialization for cardiac cells, so that we can load them 00643 // more cleverly when migrating checkpoints. 00644 t->SaveExtendedBidomainCells(ar, file_version); 00645 t->SaveExtracellularStimulus(ar, file_version); 00646 00647 // Creation of conductivity tensors are called by constructor and uses HeartConfig. So make sure that it is 00648 // archived too (needs doing before construction so appears here instead of usual archive location). 00649 HeartConfig* p_config = HeartConfig::Instance(); 00650 ar & *p_config; 00651 ar & p_config; 00652 } 00653 00658 template<class Archive, unsigned SPACE_DIM> 00659 inline void load_construct_data( 00660 Archive & ar, ExtendedBidomainTissue<SPACE_DIM> * t, const unsigned int file_version) 00661 { 00662 //Load conductivities of the conductivity of the second cell. 00663 c_vector<double, SPACE_DIM> intra_cond_second_cell; 00664 //note that simple: ar & intra_cond_second_cell may not be liked by some boost versions 00665 for (unsigned i = 0; i < SPACE_DIM; i++) 00666 { 00667 double cond; 00668 ar & cond; 00669 intra_cond_second_cell(i) = cond; 00670 } 00671 00672 00673 std::vector<AbstractCardiacCellInterface*> cells_distributed; 00674 std::vector<AbstractCardiacCellInterface*> cells_distributed_second_cell; 00675 std::vector<boost::shared_ptr<AbstractStimulusFunction> > extra_stim; 00676 std::vector<double> g_gaps; 00677 AbstractTetrahedralMesh<SPACE_DIM,SPACE_DIM>* p_mesh; 00678 ar & p_mesh; 00679 00680 // Load only the cells we actually own 00681 t->LoadExtendedBidomainCells( 00682 *ProcessSpecificArchive<Archive>::Get(), file_version, cells_distributed, cells_distributed_second_cell, g_gaps, p_mesh); 00683 00684 t->LoadExtracellularStimulus( 00685 *ProcessSpecificArchive<Archive>::Get(), file_version, extra_stim, p_mesh); 00686 00687 // CreateIntracellularConductivityTensor() is called by AbstractCardiacTissue constructor and uses HeartConfig. 00688 // (as does CreateExtracellularConductivityTensor). So make sure that it is 00689 // archived too (needs doing before construction so appears here instead of usual archive location). 00690 HeartConfig* p_config = HeartConfig::Instance(); 00691 ar & *p_config; 00692 ar & p_config; 00693 00694 ::new(t)ExtendedBidomainTissue<SPACE_DIM>(cells_distributed, cells_distributed_second_cell, extra_stim, g_gaps, p_mesh, intra_cond_second_cell); 00695 } 00696 } 00697 } // namespace ... 00698 00699 00700 00701 #endif /*EXTENDEDBIDOMAINTISSUE_HPP_*/