AbstractCardiacTissue.cpp

00001 /*
00002 
00003 Copyright (C) University of Oxford, 2005-2010
00004 
00005 University of Oxford means the Chancellor, Masters and Scholars of the
00006 University of Oxford, having an administrative office at Wellington
00007 Square, Oxford OX1 2JD, UK.
00008 
00009 This file is part of Chaste.
00010 
00011 Chaste is free software: you can redistribute it and/or modify it
00012 under the terms of the GNU Lesser General Public License as published
00013 by the Free Software Foundation, either version 2.1 of the License, or
00014 (at your option) any later version.
00015 
00016 Chaste is distributed in the hope that it will be useful, but WITHOUT
00017 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00018 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
00019 License for more details. The offer of Chaste under the terms of the
00020 License is subject to the License being interpreted in accordance with
00021 English Law and subject to any action against the University of Oxford
00022 being under the jurisdiction of the English Courts.
00023 
00024 You should have received a copy of the GNU Lesser General Public License
00025 along with Chaste. If not, see <http://www.gnu.org/licenses/>.
00026 
00027 */
00028 
00029 #include "AbstractCardiacTissue.hpp"
00030 
00031 #include "DistributedVector.hpp"
00032 #include "AxisymmetricConductivityTensors.hpp"
00033 #include "OrthotropicConductivityTensors.hpp"
00034 #include "ChastePoint.hpp"
00035 #include "AbstractChasteRegion.hpp"
00036 #include "HeartEventHandler.hpp"
00037 #include "PetscTools.hpp"
00038 
00039 
00040 template <unsigned ELEMENT_DIM,unsigned SPACE_DIM>
00041 AbstractCardiacTissue<ELEMENT_DIM,SPACE_DIM>::AbstractCardiacTissue(
00042             AbstractCardiacCellFactory<ELEMENT_DIM,SPACE_DIM>* pCellFactory)
00043     : mpMesh(pCellFactory->GetMesh()),
00044       mDoCacheReplication(true),
00045       mpDistributedVectorFactory(mpMesh->GetDistributedVectorFactory()),
00046       mMeshUnarchived(false)
00047 {
00048     //This constructor is called from the Initialise() method of the CardiacProblem class
00049     assert(pCellFactory != NULL);
00050     assert(pCellFactory->GetMesh() != NULL);
00051 
00052     unsigned num_local_nodes = mpDistributedVectorFactory->GetLocalOwnership();
00053     unsigned ownership_range_low = mpDistributedVectorFactory->GetLow();
00054     mCellsDistributed.resize(num_local_nodes);
00055 
00056     try
00057     {
00058         for (unsigned local_index = 0; local_index < num_local_nodes; local_index++)
00059         {
00060             unsigned global_index = ownership_range_low + local_index;
00061             mCellsDistributed[local_index] = pCellFactory->CreateCardiacCellForNode(global_index);
00062             mCellsDistributed[local_index]->SetUsedInTissueSimulation();
00063         }
00064 
00065         pCellFactory->FinaliseCellCreation(&mCellsDistributed,
00066                                            mpDistributedVectorFactory->GetLow(),
00067                                            mpDistributedVectorFactory->GetHigh());
00068     }
00069     catch (const Exception& e)
00070     {
00071         // Errors thrown creating cells will often be process-specific
00072         PetscTools::ReplicateException(true);
00073 
00074         // Delete cells
00075         // Should really do this for other processes too, but this is all we need
00076         // to get memory testing to pass, and leaking when we're about to die isn't
00077         // that bad!
00078         for (std::vector<AbstractCardiacCell*>::iterator cell_iterator = mCellsDistributed.begin();
00079              cell_iterator != mCellsDistributed.end();
00080              ++cell_iterator)
00081         {
00082             delete (*cell_iterator);
00083         }
00084 
00085         throw e;
00086     }
00087     PetscTools::ReplicateException(false);
00088 
00089     HeartEventHandler::BeginEvent(HeartEventHandler::COMMUNICATION);
00090     mIionicCacheReplicated.Resize( pCellFactory->GetNumberOfCells() );
00091     mIntracellularStimulusCacheReplicated.Resize( pCellFactory->GetNumberOfCells() );
00092     HeartEventHandler::EndEvent(HeartEventHandler::COMMUNICATION);
00093 
00094     if(HeartConfig::Instance()->IsMeshProvided() && HeartConfig::Instance()->GetLoadMesh())
00095     {
00096         mFibreFilePathNoExtension = "./" + HeartConfig::Instance()->GetMeshName();
00097     }
00098     else
00099     {
00100         // As of 10671 fibre orientation can only be defined when loading a mesh from disc.
00101         mFibreFilePathNoExtension = "";
00102     }
00103     CreateIntracellularConductivityTensor();
00104 }
00105 
00106 // Constructor used for archiving
00107 template <unsigned ELEMENT_DIM,unsigned SPACE_DIM>
00108 AbstractCardiacTissue<ELEMENT_DIM,SPACE_DIM>::AbstractCardiacTissue(std::vector<AbstractCardiacCell*> & rCellsDistributed,
00109                                                                     AbstractTetrahedralMesh<ELEMENT_DIM,SPACE_DIM>* pMesh)
00110     : mpMesh(pMesh),
00111       mCellsDistributed(rCellsDistributed),
00112       mDoCacheReplication(true),
00113       mpDistributedVectorFactory(mpMesh->GetDistributedVectorFactory()),
00114       mMeshUnarchived(true)
00115 {
00116     mIionicCacheReplicated.Resize(mpDistributedVectorFactory->GetProblemSize());
00117     mIntracellularStimulusCacheReplicated.Resize(mpDistributedVectorFactory->GetProblemSize());
00118 
00119     mFibreFilePathNoExtension = ArchiveLocationInfo::GetArchiveDirectory() + ArchiveLocationInfo::GetMeshFilename();
00120     CreateIntracellularConductivityTensor();
00121 }
00122 
00123 template <unsigned ELEMENT_DIM,unsigned SPACE_DIM>
00124 AbstractCardiacTissue<ELEMENT_DIM,SPACE_DIM>::~AbstractCardiacTissue()
00125 {
00126     // Delete cells
00127     for (std::vector<AbstractCardiacCell*>::iterator cell_iterator = mCellsDistributed.begin();
00128          cell_iterator != mCellsDistributed.end();
00129          ++cell_iterator)
00130     {
00131         delete (*cell_iterator);
00132     }
00133 
00134     delete mpIntracellularConductivityTensors;
00135 
00136     // If the mesh was unarchived we need to free it explicitly.
00137     if (mMeshUnarchived)
00138     {
00139         delete mpMesh;
00140     }
00141 }
00142 
00143 template <unsigned ELEMENT_DIM,unsigned SPACE_DIM>
00144 void AbstractCardiacTissue<ELEMENT_DIM,SPACE_DIM>::MergeCells(const std::vector<AbstractCardiacCell*>& rOtherCells)
00145 {
00146     assert(rOtherCells.size() == mCellsDistributed.size());
00147     for (unsigned i=0; i<rOtherCells.size(); i++)
00148     {
00149         if (rOtherCells[i] != NULL)
00150         {
00151             assert(mCellsDistributed[i] == NULL);
00152             mCellsDistributed[i] = rOtherCells[i];
00153         }
00154     }
00155 }
00156 
00157 template <unsigned ELEMENT_DIM,unsigned SPACE_DIM>
00158 void AbstractCardiacTissue<ELEMENT_DIM,SPACE_DIM>::CreateIntracellularConductivityTensor()
00159 {
00160     HeartEventHandler::BeginEvent(HeartEventHandler::READ_MESH);
00161     mpConfig = HeartConfig::Instance();
00162 
00163     if (mpConfig->IsMeshProvided() && mpConfig->GetLoadMesh())
00164     {
00165         assert(mFibreFilePathNoExtension != "");
00166         
00167         switch (mpConfig->GetConductivityMedia())
00168         {
00169             case cp::media_type::Orthotropic:
00170             {
00171                 mpIntracellularConductivityTensors = new OrthotropicConductivityTensors<ELEMENT_DIM,SPACE_DIM>;
00172                 FileFinder ortho_file(mFibreFilePathNoExtension + ".ortho", RelativeTo::AbsoluteOrCwd);
00173                 assert(ortho_file.Exists());                
00174                 mpIntracellularConductivityTensors->SetFibreOrientationFile(ortho_file);
00175                 break;
00176             }
00177 
00178             case cp::media_type::Axisymmetric:
00179             {
00180                 mpIntracellularConductivityTensors = new AxisymmetricConductivityTensors<ELEMENT_DIM,SPACE_DIM>;
00181                 FileFinder axi_file(mFibreFilePathNoExtension + ".axi", RelativeTo::AbsoluteOrCwd);
00182                 assert(axi_file.Exists());                
00183                 mpIntracellularConductivityTensors->SetFibreOrientationFile(axi_file);
00184                 break;
00185             }
00186 
00187             case cp::media_type::NoFibreOrientation:
00189                 mpIntracellularConductivityTensors = new OrthotropicConductivityTensors<ELEMENT_DIM,SPACE_DIM>;
00190                 break;
00191 
00192             default :
00193                 NEVER_REACHED;
00194         }
00195     }
00196     else // Slab defined in config file or SetMesh() called; no fibre orientation assumed
00197     {
00199         mpIntracellularConductivityTensors = new OrthotropicConductivityTensors<ELEMENT_DIM,SPACE_DIM>;
00200     }
00201 
00202     c_vector<double, SPACE_DIM> intra_conductivities;
00203     mpConfig->GetIntracellularConductivities(intra_conductivities);
00204 
00205     // this definition must be here (and not inside the if statement) because SetNonConstantConductivities() will keep
00206     // a pointer to it and we don't want it to go out of scope before Init() is called
00207     unsigned num_local_elements = mpMesh->GetNumLocalElements();
00208     std::vector<c_vector<double, SPACE_DIM> > hetero_intra_conductivities;
00209 
00210     if (mpConfig->GetConductivityHeterogeneitiesProvided())
00211     {
00212         try
00213         {
00214             assert(hetero_intra_conductivities.size()==0);
00215             hetero_intra_conductivities.resize(num_local_elements, intra_conductivities);
00216         }
00217         catch(std::bad_alloc &r_bad_alloc)
00218         {
00219 #define COVERAGE_IGNORE
00220             std::cout << "Failed to allocate std::vector of size " << num_local_elements << std::endl;
00221             PetscTools::ReplicateException(true);
00222             throw r_bad_alloc;
00223 #undef COVERAGE_IGNORE
00224         }
00225         PetscTools::ReplicateException(false);
00226 
00227         std::vector<AbstractChasteRegion<SPACE_DIM>* > conductivities_heterogeneity_areas;
00228         std::vector< c_vector<double,3> > intra_h_conductivities;
00229         std::vector< c_vector<double,3> > extra_h_conductivities;
00230         HeartConfig::Instance()->GetConductivityHeterogeneities(conductivities_heterogeneity_areas,
00231                                                                 intra_h_conductivities,
00232                                                                 extra_h_conductivities);
00233 
00234         unsigned local_element_index = 0;
00235         
00236         for (typename AbstractTetrahedralMesh<ELEMENT_DIM,SPACE_DIM>::ElementIterator it = mpMesh->GetElementIteratorBegin();
00237              it != mpMesh->GetElementIteratorEnd();
00238              ++it)
00239         {
00240 //            unsigned element_index = it->GetIndex();
00241             // if element centroid is contained in the region
00242             ChastePoint<SPACE_DIM> element_centroid(it->CalculateCentroid());
00243             for (unsigned region_index=0; region_index< conductivities_heterogeneity_areas.size(); region_index++)
00244             {
00245                 if ( conductivities_heterogeneity_areas[region_index]->DoesContain(element_centroid) )
00246                 {
00247                     hetero_intra_conductivities[local_element_index] = intra_h_conductivities[region_index];
00248                 }
00249             }
00250             local_element_index++;
00251         }
00252 
00253         // freeing memory allocated by HeartConfig::Instance()->GetConductivityHeterogeneities
00254         for (unsigned region_index=0; region_index< conductivities_heterogeneity_areas.size(); region_index++)
00255         {
00256             delete conductivities_heterogeneity_areas[region_index];
00257         }
00258 
00259         mpIntracellularConductivityTensors->SetNonConstantConductivities(&hetero_intra_conductivities);
00260     }
00261     else
00262     {
00263         mpIntracellularConductivityTensors->SetConstantConductivities(intra_conductivities);
00264     }
00265 
00266     mpIntracellularConductivityTensors->Init(this->mpMesh);
00267     HeartEventHandler::EndEvent(HeartEventHandler::READ_MESH);
00268 }
00269 
00270 
00271 template <unsigned ELEMENT_DIM,unsigned SPACE_DIM>
00272 void AbstractCardiacTissue<ELEMENT_DIM,SPACE_DIM>::SetCacheReplication(bool doCacheReplication)
00273 {
00274     mDoCacheReplication = doCacheReplication;
00275 }
00276 
00277 template <unsigned ELEMENT_DIM,unsigned SPACE_DIM>
00278 bool AbstractCardiacTissue<ELEMENT_DIM,SPACE_DIM>::GetDoCacheReplication()
00279 {
00280     return mDoCacheReplication;
00281 }
00282 
00283 template <unsigned ELEMENT_DIM,unsigned SPACE_DIM>
00284 const c_matrix<double, SPACE_DIM, SPACE_DIM>& AbstractCardiacTissue<ELEMENT_DIM,SPACE_DIM>::rGetIntracellularConductivityTensor(unsigned elementIndex)
00285 {
00286     assert( mpIntracellularConductivityTensors);
00287     return (*mpIntracellularConductivityTensors)[elementIndex];
00288 }
00289 
00290 template <unsigned ELEMENT_DIM,unsigned SPACE_DIM>
00291 AbstractCardiacCell* AbstractCardiacTissue<ELEMENT_DIM,SPACE_DIM>::GetCardiacCell( unsigned globalIndex )
00292 {
00293     assert(mpDistributedVectorFactory->GetLow() <= globalIndex &&
00294            globalIndex < mpDistributedVectorFactory->GetHigh());
00295     return mCellsDistributed[globalIndex - mpDistributedVectorFactory->GetLow()];
00296 }
00297 
00298 
00299 template <unsigned ELEMENT_DIM,unsigned SPACE_DIM>
00300 void AbstractCardiacTissue<ELEMENT_DIM,SPACE_DIM>::SolveCellSystems(Vec existingSolution, double time, double nextTime)
00301 {
00302     HeartEventHandler::BeginEvent(HeartEventHandler::SOLVE_ODES);
00303 
00304     DistributedVector dist_solution = mpDistributedVectorFactory->CreateDistributedVector(existingSolution);
00305     DistributedVector::Stripe voltage(dist_solution, 0);
00306     for (DistributedVector::Iterator index = dist_solution.Begin();
00307          index != dist_solution.End();
00308          ++index)
00309     {
00310         // overwrite the voltage with the input value
00311         mCellsDistributed[index.Local]->SetVoltage( voltage[index] );
00312         try
00313         {
00314             // solve
00315             // Note: Voltage should not be updated. GetIIonic will be called later
00316             // and needs the old voltage. The voltage will be updated in the PDE solve.
00317             mCellsDistributed[index.Local]->ComputeExceptVoltage(time, nextTime);
00318         }
00319         catch (Exception &e)
00320         {
00321             PetscTools::ReplicateException(true);
00322             throw e;
00323         }
00324 
00325         // update the Iionic and stimulus caches
00326         UpdateCaches(index.Global, index.Local, nextTime);
00327     }
00328     PetscTools::ReplicateException(false);
00329     HeartEventHandler::EndEvent(HeartEventHandler::SOLVE_ODES);
00330 
00331     HeartEventHandler::BeginEvent(HeartEventHandler::COMMUNICATION);
00332     if ( mDoCacheReplication )
00333     {
00334         ReplicateCaches();
00335     }
00336     HeartEventHandler::EndEvent(HeartEventHandler::COMMUNICATION);
00337 }
00338 
00339 template <unsigned ELEMENT_DIM,unsigned SPACE_DIM>
00340 ReplicatableVector& AbstractCardiacTissue<ELEMENT_DIM,SPACE_DIM>::rGetIionicCacheReplicated()
00341 {
00342     return mIionicCacheReplicated;
00343 }
00344 
00345 template <unsigned ELEMENT_DIM,unsigned SPACE_DIM>
00346 ReplicatableVector& AbstractCardiacTissue<ELEMENT_DIM,SPACE_DIM>::rGetIntracellularStimulusCacheReplicated()
00347 {
00348     return mIntracellularStimulusCacheReplicated;
00349 }
00350 
00351 template <unsigned ELEMENT_DIM,unsigned SPACE_DIM>
00352 void AbstractCardiacTissue<ELEMENT_DIM,SPACE_DIM>::UpdateCaches(unsigned globalIndex, unsigned localIndex, double nextTime)
00353 {
00354     mIionicCacheReplicated[globalIndex] = mCellsDistributed[localIndex]->GetIIonic();
00355     mIntracellularStimulusCacheReplicated[globalIndex] = mCellsDistributed[localIndex]->GetIntracellularStimulus(nextTime);
00356 }
00357 
00358 template <unsigned ELEMENT_DIM,unsigned SPACE_DIM>
00359 void AbstractCardiacTissue<ELEMENT_DIM,SPACE_DIM>::ReplicateCaches()
00360 {
00361     mIionicCacheReplicated.Replicate(mpDistributedVectorFactory->GetLow(), mpDistributedVectorFactory->GetHigh());
00362     mIntracellularStimulusCacheReplicated.Replicate(mpDistributedVectorFactory->GetLow(), mpDistributedVectorFactory->GetHigh());
00363 }
00364 
00365 template <unsigned ELEMENT_DIM,unsigned SPACE_DIM>
00366 const std::vector<AbstractCardiacCell*>& AbstractCardiacTissue<ELEMENT_DIM,SPACE_DIM>::rGetCellsDistributed() const
00367 {
00368     return mCellsDistributed;
00369 }
00370 
00371 template <unsigned ELEMENT_DIM,unsigned SPACE_DIM>
00372 const AbstractTetrahedralMesh<ELEMENT_DIM,SPACE_DIM>* AbstractCardiacTissue<ELEMENT_DIM,SPACE_DIM>::pGetMesh() const
00373 {
00374     return mpMesh;
00375 }
00376 
00377 
00379 // Explicit instantiation
00381 
00382 template class AbstractCardiacTissue<1,1>;
00383 template class AbstractCardiacTissue<1,2>;
00384 template class AbstractCardiacTissue<1,3>;
00385 template class AbstractCardiacTissue<2,2>;
00386 template class AbstractCardiacTissue<3,3>;

Generated on Mon Nov 1 12:35:17 2010 for Chaste by  doxygen 1.5.5