Chaste Release::3.1
ExtendedBidomainTissue.cpp
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 #include "ExtendedBidomainTissue.hpp"
00037 
00038 #include "DistributedVector.hpp"
00039 #include "OrthotropicConductivityTensors.hpp"
00040 #include "AbstractStimulusFunction.hpp"
00041 #include "ChastePoint.hpp"
00042 #include "AbstractChasteRegion.hpp"
00043 #include "HeartEventHandler.hpp"
00044 
00045 template <unsigned SPACE_DIM>
00046 ExtendedBidomainTissue<SPACE_DIM>::ExtendedBidomainTissue(AbstractCardiacCellFactory<SPACE_DIM>* pCellFactory,
00047                                                           AbstractCardiacCellFactory<SPACE_DIM>* pCellFactorySecondCell,
00048                                                           AbstractStimulusFactory<SPACE_DIM>* pExtracellularStimulusFactory)
00049     : AbstractCardiacTissue<SPACE_DIM>(pCellFactory),
00050       mpIntracellularConductivityTensorsSecondCell(NULL),
00051       mUserSuppliedExtracellularStimulus(false)
00052 {
00053     //First, do the same that the abstract constructor does, but applied to the second cell
00054 
00055     assert(pCellFactorySecondCell != NULL);
00056     assert(pCellFactorySecondCell->GetMesh() != NULL);
00057     assert(pCellFactorySecondCell->GetNumberOfCells() == pCellFactory->GetNumberOfCells() );
00058     assert(pExtracellularStimulusFactory != NULL);
00059     assert(pExtracellularStimulusFactory->GetMesh() != NULL);
00060     assert(pExtracellularStimulusFactory->GetNumberOfCells() == pCellFactorySecondCell->GetNumberOfCells() );
00061 
00062     unsigned num_local_nodes = this->mpDistributedVectorFactory->GetLocalOwnership();
00063     unsigned ownership_range_low = this->mpDistributedVectorFactory->GetLow();
00064     mCellsDistributedSecondCell.resize(num_local_nodes);
00065     mGgapDistributed.resize(num_local_nodes);
00066     mExtracellularStimuliDistributed.resize(num_local_nodes);
00067 
00068     try
00069     {
00070         for (unsigned local_index = 0; local_index < num_local_nodes; local_index++)
00071         {
00072             unsigned global_index = ownership_range_low + local_index;
00073             mCellsDistributedSecondCell[local_index] = pCellFactorySecondCell->CreateCardiacCellForNode(global_index);
00074             mCellsDistributedSecondCell[local_index]->SetUsedInTissueSimulation();
00075             mGgapDistributed[local_index] = 0.0;//default. It will be changed by specific method later when user input will be obtained
00076             mExtracellularStimuliDistributed[local_index] = pExtracellularStimulusFactory->CreateStimulusForNode(global_index);
00077         }
00078 
00079         pCellFactorySecondCell->FinaliseCellCreation(&mCellsDistributedSecondCell,
00080                                            this->mpDistributedVectorFactory->GetLow(),
00081                                            this->mpDistributedVectorFactory->GetHigh());
00082     }
00083     catch (const Exception& e)
00084     {
00085 #define COVERAGE_IGNORE //don't really know how to cover this...
00086         // Errors thrown creating cells will often be process-specific
00087         PetscTools::ReplicateException(true);
00088         // Should really do this for other processes too, but this is all we need
00089         // to get memory testing to pass, and leaking when we're about to die isn't
00090         // that bad! Delete second cells
00091         for (std::vector<AbstractCardiacCellInterface*>::iterator cell_iterator = mCellsDistributedSecondCell.begin();
00092              cell_iterator != mCellsDistributedSecondCell.end();
00093              ++cell_iterator)
00094         {
00095             delete (*cell_iterator);
00096         }
00097         throw e;
00098 #undef COVERAGE_IGNORE
00099     }
00100     PetscTools::ReplicateException(false);
00101 
00102     HeartEventHandler::BeginEvent(HeartEventHandler::COMMUNICATION);
00103     mIionicCacheReplicatedSecondCell.Resize( pCellFactory->GetNumberOfCells() );
00104     mIntracellularStimulusCacheReplicatedSecondCell.Resize( pCellFactorySecondCell->GetNumberOfCells() );
00105     mGgapCacheReplicated.Resize(pCellFactorySecondCell->GetNumberOfCells());//this is a bit of a hack...
00106     mExtracellularStimulusCacheReplicated.Resize(pExtracellularStimulusFactory->GetNumberOfCells());
00107     HeartEventHandler::EndEvent(HeartEventHandler::COMMUNICATION);
00108 
00109     //Creat the extracellular conductivity tensor
00110     CreateExtracellularConductivityTensors();
00111 }
00112 
00113 //archiving constructor
00114 template <unsigned SPACE_DIM>
00115 ExtendedBidomainTissue<SPACE_DIM>::ExtendedBidomainTissue(std::vector<AbstractCardiacCellInterface*> & rCellsDistributed,
00116                                                           std::vector<AbstractCardiacCellInterface*> & rSecondCellsDistributed,
00117                                                           std::vector<boost::shared_ptr<AbstractStimulusFunction> > & rExtraStimuliDistributed,
00118                                                           std::vector<double> & rGgapsDistributed,
00119                                                           AbstractTetrahedralMesh<SPACE_DIM,SPACE_DIM>* pMesh,
00120                                                           c_vector<double, SPACE_DIM>  intracellularConductivitiesSecondCell)
00121         :   AbstractCardiacTissue<SPACE_DIM>(pMesh),
00122             mpIntracellularConductivityTensorsSecondCell(NULL),
00123             mIntracellularConductivitiesSecondCell(intracellularConductivitiesSecondCell),
00124             mCellsDistributedSecondCell(rSecondCellsDistributed),
00125             mExtracellularStimuliDistributed(rExtraStimuliDistributed),
00126             mGgapDistributed(rGgapsDistributed),
00127             mUserSuppliedExtracellularStimulus(false)
00128 {
00129     //segfault guards in case we failed to load anything from the archive
00130     assert(mCellsDistributedSecondCell.size() > 0);
00131     assert(mExtracellularStimuliDistributed.size() > 0);
00132     assert(mGgapDistributed.size() > 0);
00133     //allocate memory for the caches
00134     mIionicCacheReplicatedSecondCell.Resize( this->mpDistributedVectorFactory->GetProblemSize());
00135     mIntracellularStimulusCacheReplicatedSecondCell.Resize( this->mpDistributedVectorFactory->GetProblemSize() );
00136     mGgapCacheReplicated.Resize(this->mpDistributedVectorFactory->GetProblemSize());
00137     mExtracellularStimulusCacheReplicated.Resize(this->mpDistributedVectorFactory->GetProblemSize());
00138 
00139     CreateIntracellularConductivityTensorSecondCell();
00140     CreateExtracellularConductivityTensors();
00141 }
00142 
00143 
00144 template <unsigned SPACE_DIM>
00145 void ExtendedBidomainTissue<SPACE_DIM>::SetGgapHeterogeneities(std::vector<boost::shared_ptr<AbstractChasteRegion<SPACE_DIM> > >& rGgapHeterogeneityRegions,
00146                                                                std::vector<double> rGgapValues)
00147 {
00148     assert( rGgapHeterogeneityRegions.size() == rGgapValues.size() );//problem class (which calls this method should have thrown otherwise)
00149     mGgapHeterogeneityRegions = rGgapHeterogeneityRegions;
00150     mGgapValues =rGgapValues;
00151 }
00152 
00153 template <unsigned SPACE_DIM>
00154 void ExtendedBidomainTissue<SPACE_DIM>::CreateGGapConductivities()
00155 {
00156     assert(mGgapHeterogeneityRegions.size() == mGgapValues.size());
00157     assert(this->mpMesh != NULL);
00158 
00159     unsigned num_local_nodes = this->mpDistributedVectorFactory->GetLocalOwnership();
00160     unsigned ownership_range_low = this->mpDistributedVectorFactory->GetLow();
00161     assert(mGgapDistributed.size() == num_local_nodes);//the constructor should have allocated memory.
00162     try
00163     {
00164         for (unsigned local_index = 0; local_index < num_local_nodes; local_index++)
00165         {
00166             mGgapDistributed[local_index] = mGGap;//assign default uniform value everywhere first
00167 
00168             //then change where and if necessary
00169             unsigned global_index = ownership_range_low + local_index;
00170             for (unsigned het_index = 0; het_index < mGgapHeterogeneityRegions.size(); het_index++)
00171             {
00172                 if ( mGgapHeterogeneityRegions[het_index]->DoesContain ( this->mpMesh->GetNode(global_index)->GetPoint() ) )
00173                 {
00174                     mGgapDistributed[local_index] = mGgapValues[het_index];
00175                 }
00176             }
00177         }
00178     }
00179     catch (const Exception& e)
00180     {
00181 #define COVERAGE_IGNORE
00182         PetscTools::ReplicateException(true);
00183         throw e;
00184 #undef COVERAGE_IGNORE
00185     }
00186     PetscTools::ReplicateException(false);
00187 }
00188 
00189 template <unsigned SPACE_DIM>
00190 void ExtendedBidomainTissue<SPACE_DIM>::CreateIntracellularConductivityTensorSecondCell()
00191 {
00192     HeartEventHandler::BeginEvent(HeartEventHandler::READ_MESH);
00193     this->mpConfig = HeartConfig::Instance();
00194     mpIntracellularConductivityTensorsSecondCell = new OrthotropicConductivityTensors<SPACE_DIM,SPACE_DIM>;
00195 
00196     // this definition must be here (and not inside the if statement) because SetNonConstantConductivities() will keep
00197     // a pointer to it and we don't want it to go out of scope before Init() is called
00198     unsigned num_elements = this->mpMesh->GetNumElements();
00199     std::vector<c_vector<double, SPACE_DIM> > hetero_intra_conductivities;
00200 
00201     c_vector<double, SPACE_DIM> intra_conductivities;
00202     this->mpConfig->GetIntracellularConductivities(intra_conductivities);//this one is used just for resizing
00203 
00204     if (this->mpConfig->GetConductivityHeterogeneitiesProvided())
00205     {
00206         try
00207         {
00208             assert(hetero_intra_conductivities.size()==0);
00209             hetero_intra_conductivities.resize(num_elements, intra_conductivities);
00210         }
00211         catch(std::bad_alloc &badAlloc)
00212         {
00213 #define COVERAGE_IGNORE
00214             std::cout << "Failed to allocate std::vector of size " << num_elements << std::endl;
00215             PetscTools::ReplicateException(true);
00216             throw badAlloc;
00217 #undef COVERAGE_IGNORE
00218         }
00219         PetscTools::ReplicateException(false);
00220 
00221         std::vector<boost::shared_ptr<AbstractChasteRegion<SPACE_DIM> > > conductivities_heterogeneity_areas;
00222         std::vector< c_vector<double,3> > intra_h_conductivities;
00223         std::vector< c_vector<double,3> > extra_h_conductivities;
00224         HeartConfig::Instance()->GetConductivityHeterogeneities(conductivities_heterogeneity_areas,
00225                                                                 intra_h_conductivities,
00226                                                                 extra_h_conductivities);
00227         unsigned local_element_index = 0;
00228         for (typename AbstractTetrahedralMesh<SPACE_DIM,SPACE_DIM>::ElementIterator it = this->mpMesh->GetElementIteratorBegin();
00229              it != this->mpMesh->GetElementIteratorEnd();
00230              ++it)
00231         {
00232             //unsigned element_index = it->GetIndex();
00233             // if element centroid is contained in the region
00234             ChastePoint<SPACE_DIM> element_centroid(it->CalculateCentroid());
00235             for (unsigned region_index=0; region_index< conductivities_heterogeneity_areas.size(); region_index++)
00236             {
00237                 if ( conductivities_heterogeneity_areas[region_index]->DoesContain(element_centroid) )
00238                 {
00239                     //We don't use ublas vector assignment here, because we might be getting a subvector of a 3-vector
00240                     for (unsigned i=0; i<SPACE_DIM; i++)
00241                     {
00242                         hetero_intra_conductivities[local_element_index][i] = intra_h_conductivities[region_index][i];
00243                     }
00244                 }
00245             }
00246             local_element_index++;
00247         }
00248 
00249         mpIntracellularConductivityTensorsSecondCell->SetNonConstantConductivities(&hetero_intra_conductivities);
00250     }
00251     else
00252     {
00253         mpIntracellularConductivityTensorsSecondCell->SetConstantConductivities(mIntracellularConductivitiesSecondCell);
00254     }
00255 
00256     mpIntracellularConductivityTensorsSecondCell->Init(this->mpMesh);
00257     HeartEventHandler::EndEvent(HeartEventHandler::READ_MESH);
00258 }
00259 
00260 template <unsigned SPACE_DIM>
00261 bool ExtendedBidomainTissue<SPACE_DIM>::HasTheUserSuppliedExtracellularStimulus()
00262 {
00263     return mUserSuppliedExtracellularStimulus;
00264 }
00265 
00266 template <unsigned SPACE_DIM>
00267 void ExtendedBidomainTissue<SPACE_DIM>::SetUserSuppliedExtracellularStimulus(bool flag)
00268 {
00269     mUserSuppliedExtracellularStimulus = flag;
00270 }
00271 
00272 template <unsigned SPACE_DIM>
00273 const std::vector<AbstractCardiacCellInterface*>& ExtendedBidomainTissue<SPACE_DIM>::rGetSecondCellsDistributed() const
00274 {
00275     return mCellsDistributedSecondCell;
00276 }
00277 
00278 template <unsigned SPACE_DIM>
00279 const std::vector<double>& ExtendedBidomainTissue<SPACE_DIM>::rGetGapsDistributed() const
00280 {
00281     return mGgapDistributed;
00282 }
00283 
00284 template <unsigned SPACE_DIM>
00285 const std::vector<boost::shared_ptr<AbstractStimulusFunction> >& ExtendedBidomainTissue<SPACE_DIM>::rGetExtracellularStimulusDistributed() const
00286 {
00287     return mExtracellularStimuliDistributed;
00288 }
00289 
00290 
00291 template <unsigned SPACE_DIM>
00292 void ExtendedBidomainTissue<SPACE_DIM>::CreateExtracellularConductivityTensors()
00293 {
00294 
00295     mpExtracellularConductivityTensors =  new OrthotropicConductivityTensors<SPACE_DIM,SPACE_DIM>;
00296     c_vector<double, SPACE_DIM> extra_conductivities;
00297     this->mpConfig->GetExtracellularConductivities(extra_conductivities);
00298 
00299     // this definition must be here (and not inside the if statement) because SetNonConstantConductivities() will keep
00300     // a pointer to it and we don't want it to go out of scope before Init() is called
00301     unsigned num_elements = this->mpMesh->GetNumElements();
00302     std::vector<c_vector<double, SPACE_DIM> > hetero_extra_conductivities;
00303 
00304     if (this->mpConfig->GetConductivityHeterogeneitiesProvided())
00305     {
00306         try
00307         {
00308             assert(hetero_extra_conductivities.size()==0);
00309             //initialise with the values of teh default conductivity tensor
00310             hetero_extra_conductivities.resize(num_elements, extra_conductivities);
00311         }
00312         catch(std::bad_alloc &badAlloc)
00313         {
00314 #define COVERAGE_IGNORE
00315             std::cout << "Failed to allocate std::vector of size " << num_elements << std::endl;
00316             PetscTools::ReplicateException(true);
00317             throw badAlloc;
00318 #undef COVERAGE_IGNORE
00319         }
00320         PetscTools::ReplicateException(false);
00321 
00322         std::vector<boost::shared_ptr<AbstractChasteRegion<SPACE_DIM> > > conductivities_heterogeneity_areas;
00323         std::vector< c_vector<double,3> > intra_h_conductivities;
00324         std::vector< c_vector<double,3> > extra_h_conductivities;
00325         HeartConfig::Instance()->GetConductivityHeterogeneities(conductivities_heterogeneity_areas,
00326                                                                 intra_h_conductivities,
00327                                                                 extra_h_conductivities);
00328         unsigned local_element_index = 0;
00329         for (typename AbstractTetrahedralMesh<SPACE_DIM,SPACE_DIM>::ElementIterator iter = (this->mpMesh)->GetElementIteratorBegin();
00330              iter != (this->mpMesh)->GetElementIteratorEnd();
00331              ++iter)
00332         {
00333             //unsigned element_index = iter->GetIndex();
00334             // if element centroid is contained in the region
00335             ChastePoint<SPACE_DIM> element_centroid(iter->CalculateCentroid());
00336             for (unsigned region_index=0; region_index< conductivities_heterogeneity_areas.size(); region_index++)
00337             {
00338                 // if element centroid is contained in the region
00339                 if ( conductivities_heterogeneity_areas[region_index]->DoesContain( element_centroid ) )
00340                 {
00341                     //We don't use ublas vector assignment here, because we might be getting a subvector of a 3-vector
00342                     for (unsigned i=0; i<SPACE_DIM; i++)
00343                     {
00344                         hetero_extra_conductivities[local_element_index][i] = extra_h_conductivities[region_index][i];
00345                     }
00346                 }
00347             }
00348             local_element_index++;
00349         }
00350 
00351         mpExtracellularConductivityTensors->SetNonConstantConductivities(&hetero_extra_conductivities);
00352     }
00353     else
00354     {
00355         mpExtracellularConductivityTensors->SetConstantConductivities(extra_conductivities);
00356     }
00357     mpExtracellularConductivityTensors->Init(this->mpMesh);
00358 }
00359 
00360 template <unsigned SPACE_DIM>
00361 ExtendedBidomainTissue<SPACE_DIM>::~ExtendedBidomainTissue()
00362 {
00363     // Delete (second) cells
00364     for (std::vector<AbstractCardiacCellInterface*>::iterator cell_iterator = mCellsDistributedSecondCell.begin();
00365          cell_iterator != mCellsDistributedSecondCell.end();
00366          ++cell_iterator)
00367     {
00368         delete (*cell_iterator);
00369     }
00370 
00371     if (mpExtracellularConductivityTensors)
00372     {
00373         delete mpExtracellularConductivityTensors;
00374     }
00375 
00376     if (mpIntracellularConductivityTensorsSecondCell)
00377     {
00378         delete mpIntracellularConductivityTensorsSecondCell;
00379     }
00380 }
00381 
00382 template <unsigned SPACE_DIM>
00383 void ExtendedBidomainTissue<SPACE_DIM>::SetIntracellularConductivitiesSecondCell(c_vector<double, SPACE_DIM> conductivities)
00384 {
00385     for (unsigned i = 0; i < SPACE_DIM; i++)
00386     {
00387         mIntracellularConductivitiesSecondCell[i] = conductivities[i];
00388     }
00389 }
00390 
00391 template <unsigned SPACE_DIM>
00392 c_vector<double, SPACE_DIM>  ExtendedBidomainTissue<SPACE_DIM>::GetIntracellularConductivitiesSecondCell() const
00393 {
00394     return mIntracellularConductivitiesSecondCell;
00395 }
00396 
00397 template <unsigned SPACE_DIM>
00398 const c_matrix<double, SPACE_DIM, SPACE_DIM>& ExtendedBidomainTissue<SPACE_DIM>::rGetExtracellularConductivityTensor(unsigned elementIndex)
00399 {
00400     assert(mpExtracellularConductivityTensors);
00401     return (*mpExtracellularConductivityTensors)[elementIndex];
00402 }
00403 
00404 template <unsigned SPACE_DIM>
00405 const c_matrix<double, SPACE_DIM, SPACE_DIM>& ExtendedBidomainTissue<SPACE_DIM>::rGetIntracellularConductivityTensorSecondCell(unsigned elementIndex)
00406 {
00407     assert(mpIntracellularConductivityTensorsSecondCell);
00408     return (*mpIntracellularConductivityTensorsSecondCell)[elementIndex];
00409 }
00410 
00411 template <unsigned SPACE_DIM>
00412 AbstractCardiacCellInterface* ExtendedBidomainTissue<SPACE_DIM>::GetCardiacSecondCell( unsigned globalIndex )
00413 {
00414     return mCellsDistributedSecondCell[globalIndex - this->mpDistributedVectorFactory->GetLow()];
00415 }
00416 
00417 template <unsigned SPACE_DIM>
00418 boost::shared_ptr<AbstractStimulusFunction> ExtendedBidomainTissue<SPACE_DIM>::GetExtracellularStimulus( unsigned globalIndex )
00419 {
00420     return mExtracellularStimuliDistributed[globalIndex - this->mpDistributedVectorFactory->GetLow()];
00421 }
00422 
00423 template <unsigned SPACE_DIM>
00424 void ExtendedBidomainTissue<SPACE_DIM>::SolveCellSystems(Vec existingSolution, double time, double nextTime, bool updateVoltage)
00425 {
00426     HeartEventHandler::BeginEvent(HeartEventHandler::SOLVE_ODES);
00427 
00428     DistributedVector dist_solution = this->mpDistributedVectorFactory->CreateDistributedVector(existingSolution);
00429     DistributedVector::Stripe phi_i_first_cell(dist_solution, 0);
00430     DistributedVector::Stripe phi_i_second_cell(dist_solution, 1);
00431     DistributedVector::Stripe phi_e(dist_solution, 2);
00432 
00433     for (DistributedVector::Iterator index = dist_solution.Begin();
00434          index != dist_solution.End();
00435          ++index)
00436     {
00437         double voltage_first_cell = phi_i_first_cell[index] - phi_e[index];
00438         double voltage_second_cell = phi_i_second_cell[index] - phi_e[index];
00439 
00440         // overwrite the voltage with the input value
00441         this->mCellsDistributed[index.Local]->SetVoltage( voltage_first_cell );
00442         mCellsDistributedSecondCell[index.Local]->SetVoltage( voltage_second_cell );
00443         try
00444         {
00445             // solve
00446             // Note: Voltage should not be updated. GetIIonic will be called later
00447             // and needs the old voltage. The voltage will be updated from the pde.
00448             this->mCellsDistributed[index.Local]->ComputeExceptVoltage(time, nextTime);
00449             mCellsDistributedSecondCell[index.Local]->ComputeExceptVoltage(time, nextTime);
00450         }
00451         catch (Exception &e)
00452         {
00453 #define COVERAGE_IGNORE
00454             PetscTools::ReplicateException(true);
00455             throw e;
00456 #undef COVERAGE_IGNORE
00457         }
00458 
00459         // update the Iionic and stimulus caches
00460         this->UpdateCaches(index.Global, index.Local, nextTime);//in parent class
00461         UpdateAdditionalCaches(index.Global, index.Local, nextTime);//extended bidomain specific caches
00462     }
00463     PetscTools::ReplicateException(false);
00464     HeartEventHandler::EndEvent(HeartEventHandler::SOLVE_ODES);
00465 
00466     HeartEventHandler::BeginEvent(HeartEventHandler::COMMUNICATION);
00467     if ( this->mDoCacheReplication )
00468     {
00469         this->ReplicateCaches();
00470         ReplicateAdditionalCaches();//extended bidomain specific caches
00471     }
00472     HeartEventHandler::EndEvent(HeartEventHandler::COMMUNICATION);
00473 }
00474 
00475 template <unsigned SPACE_DIM>
00476 void ExtendedBidomainTissue<SPACE_DIM>::UpdateAdditionalCaches(unsigned globalIndex, unsigned localIndex, double nextTime)
00477 {
00478     mIionicCacheReplicatedSecondCell[globalIndex] = mCellsDistributedSecondCell[localIndex]->GetIIonic();
00479     mIntracellularStimulusCacheReplicatedSecondCell[globalIndex] = mCellsDistributedSecondCell[localIndex]->GetIntracellularStimulus(nextTime);
00480     mExtracellularStimulusCacheReplicated[globalIndex] = mExtracellularStimuliDistributed[localIndex]->GetStimulus(nextTime);
00481     mGgapCacheReplicated[globalIndex] = mGgapDistributed[localIndex];
00482 }
00483 
00484 template <unsigned SPACE_DIM>
00485 void ExtendedBidomainTissue<SPACE_DIM>::ReplicateAdditionalCaches()
00486 {
00487     mIionicCacheReplicatedSecondCell.Replicate(this->mpDistributedVectorFactory->GetLow(), this->mpDistributedVectorFactory->GetHigh());
00488     mIntracellularStimulusCacheReplicatedSecondCell.Replicate(this->mpDistributedVectorFactory->GetLow(), this->mpDistributedVectorFactory->GetHigh());
00489     mExtracellularStimulusCacheReplicated.Replicate(this->mpDistributedVectorFactory->GetLow(), this->mpDistributedVectorFactory->GetHigh());
00490     mGgapCacheReplicated.Replicate(this->mpDistributedVectorFactory->GetLow(), this->mpDistributedVectorFactory->GetHigh());
00491 }
00492 
00493 template <unsigned SPACE_DIM>
00494 ReplicatableVector& ExtendedBidomainTissue<SPACE_DIM>::rGetIionicCacheReplicatedSecondCell()
00495 {
00496     return mIionicCacheReplicatedSecondCell;
00497 }
00498 
00499 template <unsigned SPACE_DIM>
00500 ReplicatableVector& ExtendedBidomainTissue<SPACE_DIM>::rGetIntracellularStimulusCacheReplicatedSecondCell()
00501 {
00502     return mIntracellularStimulusCacheReplicatedSecondCell;
00503 }
00504 
00505 template <unsigned SPACE_DIM>
00506 ReplicatableVector& ExtendedBidomainTissue<SPACE_DIM>::rGetExtracellularStimulusCacheReplicated()
00507 {
00508     return mExtracellularStimulusCacheReplicated;
00509 }
00510 
00511 template <unsigned SPACE_DIM>
00512 ReplicatableVector& ExtendedBidomainTissue<SPACE_DIM>::rGetGgapCacheReplicated()
00513 {
00514     return mGgapCacheReplicated;
00515 }
00516 
00517 template <unsigned SPACE_DIM>
00518 double ExtendedBidomainTissue<SPACE_DIM>::GetAmFirstCell()
00519 {
00520     return mAmFirstCell;
00521 }
00522 
00523 template <unsigned SPACE_DIM>
00524 double ExtendedBidomainTissue<SPACE_DIM>::GetAmSecondCell()
00525 {
00526     return mAmSecondCell;
00527 }
00528 
00529 template <unsigned SPACE_DIM>
00530 double ExtendedBidomainTissue<SPACE_DIM>::GetAmGap()
00531 {
00532     return mAmGap;
00533 }
00534 
00535 template <unsigned SPACE_DIM>
00536 double ExtendedBidomainTissue<SPACE_DIM>::GetCmFirstCell()
00537 {
00538     return mCmFirstCell;
00539 }
00540 
00541 template <unsigned SPACE_DIM>
00542 double ExtendedBidomainTissue<SPACE_DIM>::GetCmSecondCell()
00543 {
00544     return mCmSecondCell;
00545 }
00546 
00547 template <unsigned SPACE_DIM>
00548 double ExtendedBidomainTissue<SPACE_DIM>::GetGGap()
00549 {
00550     return mGGap;
00551 }
00552 
00553 template <unsigned SPACE_DIM>
00554 void ExtendedBidomainTissue<SPACE_DIM>::SetAmFirstCell(double value)
00555 {
00556     mAmFirstCell = value;
00557 }
00558 
00559 template <unsigned SPACE_DIM>
00560 void ExtendedBidomainTissue<SPACE_DIM>::SetAmSecondCell(double value)
00561 {
00562     mAmSecondCell = value;
00563 }
00564 
00565 template <unsigned SPACE_DIM>
00566 void ExtendedBidomainTissue<SPACE_DIM>::SetAmGap(double value)
00567 {
00568     mAmGap = value;
00569 }
00570 
00571 template <unsigned SPACE_DIM>
00572 void ExtendedBidomainTissue<SPACE_DIM>::SetGGap(double value)
00573 {
00574     mGGap = value;
00575 }
00576 
00577 template <unsigned SPACE_DIM>
00578 void ExtendedBidomainTissue<SPACE_DIM>::SetCmFirstCell(double value)
00579 {
00580     mCmFirstCell = value;
00581 }
00582 
00583 template <unsigned SPACE_DIM>
00584 void ExtendedBidomainTissue<SPACE_DIM>::SetCmSecondCell(double value)
00585 {
00586     mCmSecondCell = value;
00587 }
00588 
00590 // Explicit instantiation
00592 
00593 template class ExtendedBidomainTissue<1>;
00594 template class ExtendedBidomainTissue<2>;
00595 template class ExtendedBidomainTissue<3>;
00596 
00597 // Serialization for Boost >= 1.36
00598 #include "SerializationExportWrapperForCpp.hpp"
00599 EXPORT_TEMPLATE_CLASS_SAME_DIMS(ExtendedBidomainTissue)