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