00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
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
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
00072 PetscTools::ReplicateException(true);
00073
00074
00075
00076
00077
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
00101 mFibreFilePathNoExtension = "";
00102 }
00103 CreateIntracellularConductivityTensor();
00104 }
00105
00106
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
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
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
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
00206
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
00241
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
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
00311 mCellsDistributed[index.Local]->SetVoltage( voltage[index] );
00312 try
00313 {
00314
00315
00316
00317 mCellsDistributed[index.Local]->ComputeExceptVoltage(time, nextTime);
00318 }
00319 catch (Exception &e)
00320 {
00321 PetscTools::ReplicateException(true);
00322 throw e;
00323 }
00324
00325
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
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>;