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 "AbstractCardiacPde.hpp"
00030
00031 #include "DistributedVector.hpp"
00032 #include "AxisymmetricConductivityTensors.hpp"
00033 #include "OrthotropicConductivityTensors.hpp"
00034 #include "ChastePoint.hpp"
00035 #include "ChasteCuboid.hpp"
00036 #include "HeartEventHandler.hpp"
00037 #include "PetscTools.hpp"
00038 #include "FakeBathCell.hpp"
00039
00040
00041 template <unsigned ELEMENT_DIM,unsigned SPACE_DIM>
00042 AbstractCardiacPde<ELEMENT_DIM,SPACE_DIM>::AbstractCardiacPde(
00043 AbstractCardiacCellFactory<ELEMENT_DIM,SPACE_DIM>* pCellFactory,
00044 const unsigned stride)
00045 : mpMesh(pCellFactory->GetMesh()),
00046 mStride(stride),
00047 mDoCacheReplication(true),
00048 mDoOneCacheReplication(true),
00049 mpDistributedVectorFactory(mpMesh->GetDistributedVectorFactory()),
00050 mMeshUnarchived(false)
00051 {
00052
00053 assert(pCellFactory != NULL);
00054 assert(pCellFactory->GetMesh() != NULL);
00055
00056 unsigned num_local_nodes = mpDistributedVectorFactory->GetLocalOwnership();
00057 unsigned ownership_range_low = mpDistributedVectorFactory->GetLow();
00058 mCellsDistributed.resize(num_local_nodes);
00059
00060 for (unsigned local_index = 0; local_index < num_local_nodes; local_index++)
00061 {
00062 unsigned global_index = ownership_range_low + local_index;
00063 mCellsDistributed[local_index] = pCellFactory->CreateCardiacCellForNode(global_index);
00064 }
00065
00066 pCellFactory->FinaliseCellCreation(&mCellsDistributed,
00067 mpDistributedVectorFactory->GetLow(),
00068 mpDistributedVectorFactory->GetHigh());
00069
00070 HeartEventHandler::BeginEvent(HeartEventHandler::COMMUNICATION);
00071 mIionicCacheReplicated.Resize( pCellFactory->GetNumberOfCells() );
00072 mIntracellularStimulusCacheReplicated.Resize( pCellFactory->GetNumberOfCells() );
00073 HeartEventHandler::EndEvent(HeartEventHandler::COMMUNICATION);
00074
00075 CreateIntracellularConductivityTensor();
00076 }
00077
00078
00079 template <unsigned ELEMENT_DIM,unsigned SPACE_DIM>
00080 AbstractCardiacPde<ELEMENT_DIM,SPACE_DIM>::AbstractCardiacPde(std::vector<AbstractCardiacCell*> & rCellsDistributed,
00081 AbstractTetrahedralMesh<ELEMENT_DIM,SPACE_DIM>* pMesh,
00082 const unsigned stride)
00083 : mpMesh(pMesh),
00084 mCellsDistributed(rCellsDistributed),
00085 mStride(stride),
00086 mDoCacheReplication(true),
00087 mDoOneCacheReplication(true),
00088 mpDistributedVectorFactory(mpMesh->GetDistributedVectorFactory()),
00089 mMeshUnarchived(true)
00090 {
00091 mIionicCacheReplicated.Resize(mpDistributedVectorFactory->GetProblemSize());
00092 mIntracellularStimulusCacheReplicated.Resize(mpDistributedVectorFactory->GetProblemSize());
00093
00094 CreateIntracellularConductivityTensor();
00095 }
00096
00097 template <unsigned ELEMENT_DIM,unsigned SPACE_DIM>
00098 void AbstractCardiacPde<ELEMENT_DIM,SPACE_DIM>::DeleteCells(bool deleteFakeCells)
00099 {
00100 std::set<FakeBathCell*> fake_cells;
00101 for (std::vector<AbstractCardiacCell*>::iterator cell_iterator = mCellsDistributed.begin();
00102 cell_iterator != mCellsDistributed.end();
00103 ++cell_iterator)
00104 {
00105
00106 FakeBathCell* p_fake = dynamic_cast<FakeBathCell*>(*cell_iterator);
00107 if (p_fake == NULL)
00108 {
00109 delete (*cell_iterator);
00110 }
00111 else
00112 {
00113 fake_cells.insert(p_fake);
00114 }
00115 }
00116
00117 if (deleteFakeCells)
00118 {
00119
00120 for (std::set<FakeBathCell*>::iterator it = fake_cells.begin();
00121 it != fake_cells.end();
00122 ++it)
00123 {
00124 delete (*it);
00125 }
00126 }
00127 }
00128
00129 template <unsigned ELEMENT_DIM,unsigned SPACE_DIM>
00130 AbstractCardiacPde<ELEMENT_DIM,SPACE_DIM>::~AbstractCardiacPde()
00131 {
00132 DeleteCells(mMeshUnarchived);
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 AbstractCardiacPde<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 AbstractCardiacPde<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 switch (mpConfig->GetConductivityMedia())
00166 {
00167 case cp::media_type::Orthotropic:
00168 mpIntracellularConductivityTensors = new OrthotropicConductivityTensors<SPACE_DIM>;
00169 mpIntracellularConductivityTensors->SetFibreOrientationFile(mpConfig->GetMeshName() + ".ortho");
00170 break;
00171
00172 case cp::media_type::Axisymmetric:
00173 mpIntracellularConductivityTensors = new AxisymmetricConductivityTensors<SPACE_DIM>;
00174 mpIntracellularConductivityTensors->SetFibreOrientationFile(mpConfig->GetMeshName() + ".axi");
00175 break;
00176
00177 case cp::media_type::NoFibreOrientation:
00179 mpIntracellularConductivityTensors = new OrthotropicConductivityTensors<SPACE_DIM>;
00180 break;
00181
00182 default :
00183 NEVER_REACHED;
00184 }
00185 }
00186 else
00187 {
00189 mpIntracellularConductivityTensors = new OrthotropicConductivityTensors<SPACE_DIM>;
00190 }
00191
00192 c_vector<double, SPACE_DIM> intra_conductivities;
00193 mpConfig->GetIntracellularConductivities(intra_conductivities);
00194
00195
00196
00197 unsigned num_elements = mpMesh->GetNumElements();
00198 std::vector<c_vector<double, SPACE_DIM> > hetero_intra_conductivities;
00199
00200 if (mpConfig->GetConductivityHeterogeneitiesProvided())
00201 {
00202 try
00203 {
00204 hetero_intra_conductivities.resize(num_elements);
00205 }
00206 catch(std::bad_alloc &badAlloc)
00207 {
00208 #define COVERAGE_IGNORE
00209 std::cout << "Failed to allocate std::vector of size " << num_elements << std::endl;
00210 PetscTools::ReplicateException(true);
00211 throw badAlloc;
00212 #undef COVERAGE_IGNORE
00213 }
00214 PetscTools::ReplicateException(false);
00215
00216 std::vector<ChasteCuboid<SPACE_DIM> > conductivities_heterogeneity_areas;
00217 std::vector< c_vector<double,3> > intra_h_conductivities;
00218 std::vector< c_vector<double,3> > extra_h_conductivities;
00219 HeartConfig::Instance()->GetConductivityHeterogeneities(conductivities_heterogeneity_areas,
00220 intra_h_conductivities,
00221 extra_h_conductivities);
00222
00223 for (unsigned element_index=0; element_index<num_elements; element_index++)
00224 {
00225 for (unsigned region_index=0; region_index< conductivities_heterogeneity_areas.size(); region_index++)
00226 {
00227
00228 ChastePoint<SPACE_DIM> element_centroid(mpMesh->GetElement(element_index)->CalculateCentroid());
00229 if ( conductivities_heterogeneity_areas[region_index].DoesContain(element_centroid) )
00230 {
00231 hetero_intra_conductivities[element_index] = intra_h_conductivities[region_index];
00232 }
00233 else
00234 {
00235 hetero_intra_conductivities[element_index] = intra_conductivities;
00236 }
00237 }
00238 }
00239
00240 mpIntracellularConductivityTensors->SetNonConstantConductivities(&hetero_intra_conductivities);
00241 }
00242 else
00243 {
00244 mpIntracellularConductivityTensors->SetConstantConductivities(intra_conductivities);
00245 }
00246
00247 mpIntracellularConductivityTensors->Init();
00248 HeartEventHandler::EndEvent(HeartEventHandler::READ_MESH);
00249 }
00250
00251
00252 template <unsigned ELEMENT_DIM,unsigned SPACE_DIM>
00253 void AbstractCardiacPde<ELEMENT_DIM,SPACE_DIM>::SetCacheReplication(bool doCacheReplication)
00254 {
00255 mDoCacheReplication = doCacheReplication;
00256 mDoOneCacheReplication = true;
00257 }
00258
00259 template <unsigned ELEMENT_DIM,unsigned SPACE_DIM>
00260 bool AbstractCardiacPde<ELEMENT_DIM,SPACE_DIM>::GetDoCacheReplication()
00261 {
00262 return mDoCacheReplication;
00263 }
00264
00265 template <unsigned ELEMENT_DIM,unsigned SPACE_DIM>
00266 const c_matrix<double, SPACE_DIM, SPACE_DIM>& AbstractCardiacPde<ELEMENT_DIM,SPACE_DIM>::rGetIntracellularConductivityTensor(unsigned elementIndex)
00267 {
00268 assert( mpIntracellularConductivityTensors);
00269 return (*mpIntracellularConductivityTensors)[elementIndex];
00270 }
00271
00272 template <unsigned ELEMENT_DIM,unsigned SPACE_DIM>
00273 AbstractCardiacCell* AbstractCardiacPde<ELEMENT_DIM,SPACE_DIM>::GetCardiacCell( unsigned globalIndex )
00274 {
00275 assert(mpDistributedVectorFactory->GetLow() <= globalIndex &&
00276 globalIndex < mpDistributedVectorFactory->GetHigh());
00277 return mCellsDistributed[globalIndex - mpDistributedVectorFactory->GetLow()];
00278 }
00279
00280
00281 template <unsigned ELEMENT_DIM,unsigned SPACE_DIM>
00282 void AbstractCardiacPde<ELEMENT_DIM,SPACE_DIM>::SolveCellSystems(Vec existingSolution, double time, double nextTime)
00283 {
00284 HeartEventHandler::BeginEvent(HeartEventHandler::SOLVE_ODES);
00285
00286 DistributedVector dist_solution = mpDistributedVectorFactory->CreateDistributedVector(existingSolution);
00287 DistributedVector::Stripe voltage(dist_solution, 0);
00288 for (DistributedVector::Iterator index = dist_solution.Begin();
00289 index != dist_solution.End();
00290 ++index)
00291 {
00292
00293 mCellsDistributed[index.Local]->SetVoltage( voltage[index] );
00294 try
00295 {
00296
00297
00298
00299 mCellsDistributed[index.Local]->ComputeExceptVoltage(time, nextTime);
00300 }
00301 catch (Exception &e)
00302 {
00303 PetscTools::ReplicateException(true);
00304 throw e;
00305 }
00306
00307
00308 UpdateCaches(index.Global, index.Local, nextTime);
00309 }
00310 PetscTools::ReplicateException(false);
00311 HeartEventHandler::EndEvent(HeartEventHandler::SOLVE_ODES);
00312
00313 HeartEventHandler::BeginEvent(HeartEventHandler::COMMUNICATION);
00314 if ( mDoCacheReplication || mDoOneCacheReplication )
00315 {
00316 ReplicateCaches();
00317 mDoOneCacheReplication=false;
00318 }
00319 HeartEventHandler::EndEvent(HeartEventHandler::COMMUNICATION);
00320 }
00321
00322 template <unsigned ELEMENT_DIM,unsigned SPACE_DIM>
00323 ReplicatableVector& AbstractCardiacPde<ELEMENT_DIM,SPACE_DIM>::rGetIionicCacheReplicated()
00324 {
00325 return mIionicCacheReplicated;
00326 }
00327
00328 template <unsigned ELEMENT_DIM,unsigned SPACE_DIM>
00329 ReplicatableVector& AbstractCardiacPde<ELEMENT_DIM,SPACE_DIM>::rGetIntracellularStimulusCacheReplicated()
00330 {
00331 return mIntracellularStimulusCacheReplicated;
00332 }
00333
00334 template <unsigned ELEMENT_DIM,unsigned SPACE_DIM>
00335 void AbstractCardiacPde<ELEMENT_DIM,SPACE_DIM>::UpdateCaches(unsigned globalIndex, unsigned localIndex, double nextTime)
00336 {
00337 mIionicCacheReplicated[globalIndex] = mCellsDistributed[localIndex]->GetIIonic();
00338 mIntracellularStimulusCacheReplicated[globalIndex] = mCellsDistributed[localIndex]->GetIntracellularStimulus(nextTime);
00339 }
00340
00341 template <unsigned ELEMENT_DIM,unsigned SPACE_DIM>
00342 void AbstractCardiacPde<ELEMENT_DIM,SPACE_DIM>::ReplicateCaches()
00343 {
00344 mIionicCacheReplicated.Replicate(mpDistributedVectorFactory->GetLow(), mpDistributedVectorFactory->GetHigh());
00345 mIntracellularStimulusCacheReplicated.Replicate(mpDistributedVectorFactory->GetLow(), mpDistributedVectorFactory->GetHigh());
00346 }
00347
00348 template <unsigned ELEMENT_DIM,unsigned SPACE_DIM>
00349 const std::vector<AbstractCardiacCell*>& AbstractCardiacPde<ELEMENT_DIM,SPACE_DIM>::rGetCellsDistributed() const
00350 {
00351 return mCellsDistributed;
00352 }
00353
00354 template <unsigned ELEMENT_DIM,unsigned SPACE_DIM>
00355 const AbstractTetrahedralMesh<ELEMENT_DIM,SPACE_DIM>* AbstractCardiacPde<ELEMENT_DIM,SPACE_DIM>::pGetMesh() const
00356 {
00357 return mpMesh;
00358 }
00359
00360
00362
00364
00365 template class AbstractCardiacPde<1,1>;
00366 template class AbstractCardiacPde<1,2>;
00367 template class AbstractCardiacPde<1,3>;
00368 template class AbstractCardiacPde<2,2>;
00369 template class AbstractCardiacPde<3,3>;