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 ELEM_DIM,unsigned SPACE_DIM>
00042 AbstractCardiacPde<ELEM_DIM,SPACE_DIM>::AbstractCardiacPde(
00043 AbstractCardiacCellFactory<ELEM_DIM,SPACE_DIM>* pCellFactory,
00044 const unsigned stride)
00045 : mStride(stride),
00046 mDoCacheReplication(true),
00047 mDoOneCacheReplication(true),
00048 mpDistributedVectorFactory(pCellFactory->GetMesh()->GetDistributedVectorFactory()),
00049 mpFactoryWasUnarchived(false)
00050 {
00051
00052 assert(pCellFactory!=NULL);
00053 assert(pCellFactory->GetMesh()!=NULL);
00054
00055 unsigned num_local_nodes = mpDistributedVectorFactory->GetLocalOwnership();
00056 unsigned ownership_range_low = mpDistributedVectorFactory->GetLow();
00057 mCellsDistributed.resize(num_local_nodes);
00058
00059 for (unsigned local_index = 0; local_index < num_local_nodes; local_index++)
00060 {
00061 unsigned global_index = ownership_range_low + local_index;
00062 mCellsDistributed[local_index] = pCellFactory->CreateCardiacCellForNode(global_index);
00063 }
00064
00065
00066 pCellFactory->FinaliseCellCreation(&mCellsDistributed,
00067 pCellFactory->GetMesh()->GetDistributedVectorFactory()->GetLow(),
00068 pCellFactory->GetMesh()->GetDistributedVectorFactory()->GetHigh());
00069
00070
00071 mIionicCacheReplicated.resize( pCellFactory->GetNumberOfCells() );
00072 mIntracellularStimulusCacheReplicated.resize( pCellFactory->GetNumberOfCells() );
00073
00074 mpConfig = HeartConfig::Instance();
00075
00076 if (mpConfig->IsMeshProvided() && mpConfig->GetLoadMesh())
00077 {
00078 switch (mpConfig->GetConductivityMedia())
00079 {
00080 case media_type::Orthotropic:
00081 mpIntracellularConductivityTensors = new OrthotropicConductivityTensors<SPACE_DIM>;
00082 mpIntracellularConductivityTensors->SetFibreOrientationFile(mpConfig->GetMeshName() + ".ortho");
00083 break;
00084
00085 case media_type::Axisymmetric:
00086 mpIntracellularConductivityTensors = new AxisymmetricConductivityTensors<SPACE_DIM>;
00087 mpIntracellularConductivityTensors->SetFibreOrientationFile(mpConfig->GetMeshName() + ".axi");
00088 break;
00089
00090 case media_type::NoFibreOrientation:
00092 mpIntracellularConductivityTensors = new OrthotropicConductivityTensors<SPACE_DIM>;
00093 break;
00094
00095 default :
00096 NEVER_REACHED;
00097 }
00098 }
00099 else
00100 {
00102 mpIntracellularConductivityTensors = new OrthotropicConductivityTensors<SPACE_DIM>;
00103 }
00104
00105 c_vector<double, SPACE_DIM> intra_conductivities;
00106 mpConfig->GetIntracellularConductivities(intra_conductivities);
00107
00108
00109
00110 unsigned num_elements = pCellFactory->GetMesh()->GetNumElements();
00111 std::vector<c_vector<double, SPACE_DIM> > hetero_intra_conductivities(num_elements);
00112
00113 if (mpConfig->GetConductivityHeterogeneitiesProvided())
00114 {
00115 std::vector<ChasteCuboid> conductivities_heterogeneity_areas;
00116 std::vector< c_vector<double,3> > intra_h_conductivities;
00117 std::vector< c_vector<double,3> > extra_h_conductivities;
00118 HeartConfig::Instance()->GetConductivityHeterogeneities(conductivities_heterogeneity_areas,
00119 intra_h_conductivities,
00120 extra_h_conductivities);
00121
00122 for (unsigned element_index=0; element_index<num_elements; element_index++)
00123 {
00124 for (unsigned region_index=0; region_index< conductivities_heterogeneity_areas.size(); region_index++)
00125 {
00126
00127 ChastePoint<SPACE_DIM> element_centroid(pCellFactory->GetMesh()->GetElement(element_index)->CalculateCentroid());
00128 if ( conductivities_heterogeneity_areas[region_index].DoesContain(element_centroid) )
00129 {
00130 hetero_intra_conductivities[element_index] = intra_h_conductivities[region_index];
00131 }
00132 else
00133 {
00134 hetero_intra_conductivities[element_index] = intra_conductivities;
00135 }
00136 }
00137 }
00138
00139 mpIntracellularConductivityTensors->SetNonConstantConductivities(&hetero_intra_conductivities);
00140 }
00141 else
00142 {
00143 mpIntracellularConductivityTensors->SetConstantConductivities(intra_conductivities);
00144 }
00145
00146 mpIntracellularConductivityTensors->Init();
00147 }
00148
00149 template <unsigned ELEM_DIM,unsigned SPACE_DIM>
00150 AbstractCardiacPde<ELEM_DIM,SPACE_DIM>::AbstractCardiacPde(std::vector<AbstractCardiacCell*> & rCellsDistributed,
00151 const unsigned stride)
00152 : mCellsDistributed(rCellsDistributed),
00153 mStride(stride),
00154 mDoCacheReplication(true),
00155 mDoOneCacheReplication(true),
00156 mpDistributedVectorFactory(NULL),
00157 mpFactoryWasUnarchived(true)
00158 {
00160 mpIntracellularConductivityTensors = NULL;
00161 }
00162
00163 template <unsigned ELEM_DIM,unsigned SPACE_DIM>
00164 AbstractCardiacPde<ELEM_DIM,SPACE_DIM>::~AbstractCardiacPde()
00165 {
00166 for (std::vector<AbstractCardiacCell*>::iterator cell_iterator = mCellsDistributed.begin();
00167 cell_iterator != mCellsDistributed.end();
00168 ++cell_iterator)
00169 {
00170
00171 FakeBathCell* p_fake = dynamic_cast<FakeBathCell*>(*cell_iterator);
00172 if (p_fake == NULL)
00173 {
00174 delete (*cell_iterator);
00175 }
00176 }
00177
00179 if (mpIntracellularConductivityTensors)
00180 {
00181 delete mpIntracellularConductivityTensors;
00182 }
00183
00184
00185 if (mpFactoryWasUnarchived)
00186 {
00187 delete mpDistributedVectorFactory;
00188 }
00189 }
00190
00191 template <unsigned ELEM_DIM,unsigned SPACE_DIM>
00192 void AbstractCardiacPde<ELEM_DIM,SPACE_DIM>::SetCacheReplication(bool doCacheReplication)
00193 {
00194 mDoCacheReplication = doCacheReplication;
00195 }
00196
00197 template <unsigned ELEM_DIM,unsigned SPACE_DIM>
00198 const c_matrix<double, SPACE_DIM, SPACE_DIM>& AbstractCardiacPde<ELEM_DIM,SPACE_DIM>::rGetIntracellularConductivityTensor(unsigned elementIndex)
00199 {
00200 assert( mpIntracellularConductivityTensors);
00201 return (*mpIntracellularConductivityTensors)[elementIndex];
00202 }
00203
00204 template <unsigned ELEM_DIM,unsigned SPACE_DIM>
00205 AbstractCardiacCell* AbstractCardiacPde<ELEM_DIM,SPACE_DIM>::GetCardiacCell( unsigned globalIndex )
00206 {
00207 assert(mpDistributedVectorFactory->GetLow() <= globalIndex &&
00208 globalIndex < mpDistributedVectorFactory->GetHigh());
00209 return mCellsDistributed[globalIndex - mpDistributedVectorFactory->GetLow()];
00210 }
00211
00212
00213 template <unsigned ELEM_DIM,unsigned SPACE_DIM>
00214 void AbstractCardiacPde<ELEM_DIM,SPACE_DIM>::SolveCellSystems(Vec existingSolution, double time, double nextTime)
00215 {
00216 HeartEventHandler::BeginEvent(HeartEventHandler::SOLVE_ODES);
00217
00218 DistributedVector dist_solution = mpDistributedVectorFactory->CreateDistributedVector(existingSolution);
00219 DistributedVector::Stripe voltage(dist_solution, 0);
00220 for (DistributedVector::Iterator index = dist_solution.Begin();
00221 index != dist_solution.End();
00222 ++index)
00223 {
00224
00225 mCellsDistributed[index.Local]->SetVoltage( voltage[index] );
00226 try
00227 {
00228
00229
00230
00231 mCellsDistributed[index.Local]->ComputeExceptVoltage(time, nextTime);
00232 }
00233 catch (Exception &e)
00234 {
00235 PetscTools::ReplicateException(true);
00236 throw e;
00237 }
00238
00239
00240 UpdateCaches(index.Global, index.Local, nextTime);
00241 }
00242 HeartEventHandler::EndEvent(HeartEventHandler::SOLVE_ODES);
00243
00244 PetscTools::ReplicateException(false);
00245
00246 HeartEventHandler::BeginEvent(HeartEventHandler::COMMUNICATION);
00247 if ((mDoCacheReplication)||mDoOneCacheReplication)
00248 {
00249 ReplicateCaches();
00250 mDoOneCacheReplication=false;
00251 }
00252 HeartEventHandler::EndEvent(HeartEventHandler::COMMUNICATION);
00253 }
00254
00255 template <unsigned ELEM_DIM,unsigned SPACE_DIM>
00256 ReplicatableVector& AbstractCardiacPde<ELEM_DIM,SPACE_DIM>::rGetIionicCacheReplicated()
00257 {
00258 return mIionicCacheReplicated;
00259 }
00260
00261 template <unsigned ELEM_DIM,unsigned SPACE_DIM>
00262 ReplicatableVector& AbstractCardiacPde<ELEM_DIM,SPACE_DIM>::rGetIntracellularStimulusCacheReplicated()
00263 {
00264 return mIntracellularStimulusCacheReplicated;
00265 }
00266
00267 template <unsigned ELEM_DIM,unsigned SPACE_DIM>
00268 void AbstractCardiacPde<ELEM_DIM,SPACE_DIM>::UpdateCaches(unsigned globalIndex, unsigned localIndex, double nextTime)
00269 {
00270 mIionicCacheReplicated[globalIndex] = mCellsDistributed[localIndex]->GetIIonic();
00271 mIntracellularStimulusCacheReplicated[globalIndex] = mCellsDistributed[localIndex]->GetIntracellularStimulus(nextTime);
00272 }
00273
00274 template <unsigned ELEM_DIM,unsigned SPACE_DIM>
00275 void AbstractCardiacPde<ELEM_DIM,SPACE_DIM>::ReplicateCaches()
00276 {
00277 mIionicCacheReplicated.Replicate(mpDistributedVectorFactory->GetLow(), mpDistributedVectorFactory->GetHigh());
00278 mIntracellularStimulusCacheReplicated.Replicate(mpDistributedVectorFactory->GetLow(), mpDistributedVectorFactory->GetHigh());
00279 }
00280
00281 template <unsigned ELEM_DIM,unsigned SPACE_DIM>
00282 const std::vector<AbstractCardiacCell*>& AbstractCardiacPde<ELEM_DIM,SPACE_DIM>::GetCellsDistributed() const
00283 {
00284 return mCellsDistributed;
00285 }
00286
00288
00290
00291 template class AbstractCardiacPde<1,1>;
00292 template class AbstractCardiacPde<1,2>;
00293 template class AbstractCardiacPde<1,3>;
00294 template class AbstractCardiacPde<2,2>;
00295 template class AbstractCardiacPde<3,3>;