HeartConfigRelatedCellFactory.cpp
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 "HeartConfigRelatedCellFactory.hpp"
00030 #include "HeartGeometryInformation.hpp"
00031 #include "ChasteNodesList.hpp"
00032 #include "FileFinder.hpp"
00033 #include "CellMLToSharedLibraryConverter.hpp"
00034
00035
00036 template<unsigned SPACE_DIM>
00037 HeartConfigRelatedCellFactory<SPACE_DIM>::HeartConfigRelatedCellFactory()
00038 : AbstractCardiacCellFactory<SPACE_DIM>(),
00039 mDefaultIonicModel(HeartConfig::Instance()->GetDefaultIonicModel())
00040 {
00041
00042 HeartConfig::Instance()->GetIonicModelRegions(mIonicModelRegions,
00043 mIonicModelsDefined);
00044
00045
00046 try
00047 {
00048 HeartConfig::Instance()->GetStimuli(mStimuliApplied, mStimulatedAreas);
00049 }
00050 catch (Exception& e)
00051 {
00052
00053 NEVER_REACHED;
00054 }
00055
00056
00057 try
00058 {
00059 HeartConfig::Instance()->GetCellHeterogeneities(mCellHeterogeneityAreas,
00060 mScaleFactorGks,
00061 mScaleFactorIto,
00062 mScaleFactorGkr);
00063 }
00064 catch (Exception& e)
00065 {
00066
00067 }
00068
00069
00070 PreconvertCellmlFiles();
00071 }
00072
00073 template<unsigned SPACE_DIM>
00074 void HeartConfigRelatedCellFactory<SPACE_DIM>::PreconvertCellmlFiles()
00075 {
00076 if (mDefaultIonicModel.Dynamic().present())
00077 {
00078 LoadDynamicModel(mDefaultIonicModel, true);
00079 }
00080 for (unsigned i=0; i<mIonicModelsDefined.size(); i++)
00081 {
00082 if (mIonicModelsDefined[i].Dynamic().present())
00083 {
00084 LoadDynamicModel(mIonicModelsDefined[i], true);
00085 }
00086 }
00087 }
00088
00089 template<unsigned SPACE_DIM>
00090 DynamicCellModelLoader* HeartConfigRelatedCellFactory<SPACE_DIM>::LoadDynamicModel(
00091 const cp::ionic_model_selection_type& rModel,
00092 bool isCollective)
00093 {
00094 assert(rModel.Dynamic().present());
00095 FileFinder file_finder(rModel.Dynamic()->Path());
00096 CellMLToSharedLibraryConverter converter;
00097 return converter.Convert(file_finder, isCollective);
00098 }
00099
00100 template<unsigned SPACE_DIM>
00101 HeartConfigRelatedCellFactory<SPACE_DIM>::~HeartConfigRelatedCellFactory()
00102 {
00103 for (unsigned i = 0; i<mCellHeterogeneityAreas.size();i++)
00104 {
00105 delete mCellHeterogeneityAreas[i];
00106 }
00107 }
00108
00109 template<unsigned SPACE_DIM>
00110 AbstractCardiacCell* HeartConfigRelatedCellFactory<SPACE_DIM>::CreateCellWithIntracellularStimulus(
00111 boost::shared_ptr<AbstractStimulusFunction> intracellularStimulus,
00112 unsigned nodeIndex)
00113 {
00114 cp::ionic_model_selection_type ionic_model = mDefaultIonicModel;
00115
00116 for (unsigned ionic_model_region_index = 0;
00117 ionic_model_region_index < mIonicModelRegions.size();
00118 ++ionic_model_region_index)
00119 {
00120 if ( mIonicModelRegions[ionic_model_region_index].DoesContain(this->GetMesh()->GetNode(nodeIndex)->GetPoint()) )
00121 {
00122 ionic_model = mIonicModelsDefined[ionic_model_region_index];
00123 break;
00124 }
00125 }
00126
00127 if (ionic_model.Dynamic().present())
00128 {
00129 #ifndef CHASTE_CAN_CHECKPOINT_DLLS
00130 if (HeartConfig::Instance()->GetCheckpointSimulation())
00131 {
00132 EXCEPTION("Checkpointing is not compatible with dynamically loaded cell models on Boost<1.37.");
00133 }
00134 #endif // CHASTE_CAN_CHECKPOINT_DLLS
00135
00136 DynamicCellModelLoader* p_loader = LoadDynamicModel(ionic_model, false);
00137 return p_loader->CreateCell(this->mpSolver, intracellularStimulus);
00138 }
00139 else
00140 {
00141 assert(ionic_model.Hardcoded().present());
00142 switch(ionic_model.Hardcoded().get())
00143 {
00144 case(cp::ionic_models_available_type::LuoRudyI):
00145 {
00146 return new LuoRudyIModel1991OdeSystem(this->mpSolver, intracellularStimulus);
00147 break;
00148 }
00149
00150 case(cp::ionic_models_available_type::LuoRudyIBackwardEuler):
00151 {
00152 return new BackwardEulerLuoRudyIModel1991(intracellularStimulus);
00153 break;
00154 }
00155
00156 case(cp::ionic_models_available_type::Fox2002BackwardEuler):
00157 {
00158 return new BackwardEulerFoxModel2002Modified(intracellularStimulus);
00159 break;
00160 }
00161
00162 case(cp::ionic_models_available_type::DifrancescoNoble):
00163 {
00164 return new DiFrancescoNoble1985OdeSystem(this->mpSolver, intracellularStimulus);
00165 break;
00166 }
00167
00168 case(cp::ionic_models_available_type::MahajanShiferaw):
00169 {
00170 return new Mahajan2008OdeSystem(this->mpSolver, intracellularStimulus);
00171 break;
00172 }
00173
00174 case(cp::ionic_models_available_type::tenTusscher2006):
00175 {
00176 TenTusscher2006OdeSystem* p_tt06_instance = new TenTusscher2006OdeSystem(this->mpSolver, intracellularStimulus);
00177
00178 for (unsigned ht_index = 0;
00179 ht_index < mCellHeterogeneityAreas.size();
00180 ++ht_index)
00181 {
00182 if ( mCellHeterogeneityAreas[ht_index]->DoesContain(this->GetMesh()->GetNode(nodeIndex)->GetPoint()) )
00183 {
00184 p_tt06_instance->SetScaleFactorGks(mScaleFactorGks[ht_index]);
00185 p_tt06_instance->SetScaleFactorIto(mScaleFactorIto[ht_index]);
00186 p_tt06_instance->SetScaleFactorGkr(mScaleFactorGkr[ht_index]);
00187 }
00188 }
00189
00190 return p_tt06_instance;
00191 break;
00192 }
00193
00194 case(cp::ionic_models_available_type::Maleckar):
00195 {
00196 Maleckar2009OdeSystem* p_maleckar_instance = new Maleckar2009OdeSystem(this->mpSolver, intracellularStimulus);
00197
00198 for (unsigned ht_index = 0;
00199 ht_index < mCellHeterogeneityAreas.size();
00200 ++ht_index)
00201 {
00202 if ( mCellHeterogeneityAreas[ht_index]->DoesContain(this->GetMesh()->GetNode(nodeIndex)->GetPoint()) )
00203 {
00204 p_maleckar_instance->SetScaleFactorGks(mScaleFactorGks[ht_index]);
00205 p_maleckar_instance->SetScaleFactorIto(mScaleFactorIto[ht_index]);
00206 p_maleckar_instance->SetScaleFactorGkr(mScaleFactorGkr[ht_index]);
00207 }
00208 }
00209
00210 return p_maleckar_instance;
00211 break;
00212 }
00213
00214 case(cp::ionic_models_available_type::HodgkinHuxley):
00215 {
00216 return new HodgkinHuxleySquidAxon1952OriginalOdeSystem(this->mpSolver, intracellularStimulus);
00217 break;
00218 }
00219
00220 case(cp::ionic_models_available_type::FaberRudy2000):
00221 {
00222 FaberRudy2000Version3* p_faber_rudy_instance = new FaberRudy2000Version3(this->mpSolver, intracellularStimulus);
00223 for (unsigned ht_index = 0;
00224 ht_index < mCellHeterogeneityAreas.size();
00225 ++ht_index)
00226 {
00227 if ( mCellHeterogeneityAreas[ht_index]->DoesContain(this->GetMesh()->GetNode(nodeIndex)->GetPoint()) )
00228 {
00229 p_faber_rudy_instance->SetScaleFactorGks(mScaleFactorGks[ht_index]);
00230 p_faber_rudy_instance->SetScaleFactorIto(mScaleFactorIto[ht_index]);
00231 p_faber_rudy_instance->SetScaleFactorGkr(mScaleFactorGkr[ht_index]);
00232 }
00233 }
00234
00235 return p_faber_rudy_instance;
00236 break;
00237 }
00238
00239 case(cp::ionic_models_available_type::FaberRudy2000Optimised):
00240 {
00241 return new FaberRudy2000Version3Optimised(this->mpSolver, intracellularStimulus);
00242 break;
00243 }
00244
00245 default:
00246 {
00247
00248 NEVER_REACHED;
00249 }
00250 }
00251 }
00252 NEVER_REACHED;
00253
00254 return NULL;
00255 }
00256
00257
00258 template<unsigned SPACE_DIM>
00259 AbstractCardiacCell* HeartConfigRelatedCellFactory<SPACE_DIM>::CreateCardiacCellForTissueNode(unsigned nodeIndex)
00260 {
00261 boost::shared_ptr<MultiStimulus> node_specific_stimulus(new MultiStimulus());
00262
00263
00264 for (unsigned stimulus_index = 0;
00265 stimulus_index < mStimuliApplied.size();
00266 ++stimulus_index)
00267 {
00268 if ( mStimulatedAreas[stimulus_index].DoesContain(this->GetMesh()->GetNode(nodeIndex)->GetPoint()) )
00269 {
00270 node_specific_stimulus->AddStimulus(mStimuliApplied[stimulus_index]);
00271 }
00272 }
00273
00274 return CreateCellWithIntracellularStimulus(node_specific_stimulus, nodeIndex);
00275 }
00276
00277 template<unsigned SPACE_DIM>
00278 void HeartConfigRelatedCellFactory<SPACE_DIM>::FillInCellularTransmuralAreas()
00279 {
00280 NEVER_REACHED;
00281 }
00282
00283 template<>
00284 void HeartConfigRelatedCellFactory<3u>::FillInCellularTransmuralAreas()
00285 {
00286 std::string mesh_file_name = HeartConfig::Instance()->GetMeshName();
00287
00288 std::string epi_surface = mesh_file_name + ".epi";
00289 std::string lv_surface = mesh_file_name + ".lv";
00290 std::string rv_surface = mesh_file_name + ".rv";
00291
00292
00293
00294
00295 HeartGeometryInformation<3u> info(*(this->GetMesh()), epi_surface, lv_surface, rv_surface, true);
00296
00297
00298 double epi_fraction = HeartConfig::Instance()->GetEpiLayerFraction();
00299 double endo_fraction = HeartConfig::Instance()->GetEndoLayerFraction();
00300
00301
00302 info.DetermineLayerForEachNode(epi_fraction,endo_fraction);
00303
00304 std::vector<unsigned> heterogeneity_node_list;
00305 for (unsigned index=0; index<this->GetMesh()->GetNumNodes(); index++)
00306 {
00307 heterogeneity_node_list.push_back(info.rGetLayerForEachNode()[index]);
00308 }
00309
00310 std::vector<Node<3u>*> epi_nodes;
00311 std::vector<Node<3u>*> mid_nodes;
00312 std::vector<Node<3u>*> endo_nodes;
00313
00314
00315 for (unsigned node_index = 0; node_index < this->GetMesh()->GetNumNodes(); node_index++)
00316 {
00317 if (this->GetMesh()->GetDistributedVectorFactory()->IsGlobalIndexLocal(node_index) )
00318 {
00319 switch (heterogeneity_node_list[node_index])
00320 {
00321
00322 case 2u:
00323 {
00324 epi_nodes.push_back(this->GetMesh()->GetNode(node_index));
00325 break;
00326 }
00327
00328 case 1u:
00329 {
00330 mid_nodes.push_back(this->GetMesh()->GetNode(node_index));
00331 break;
00332 }
00333
00334 case 0u:
00335 {
00336 endo_nodes.push_back(this->GetMesh()->GetNode(node_index));
00337 break;
00338 }
00339 default:
00340 NEVER_REACHED;
00341 }
00342 }
00343 }
00344
00345
00346
00347
00348
00349
00350
00351 unsigned user_supplied_epi_index = HeartConfig::Instance()->GetEpiLayerIndex();
00352 unsigned user_supplied_mid_index = HeartConfig::Instance()->GetMidLayerIndex();
00353 unsigned user_supplied_endo_index = HeartConfig::Instance()->GetEndoLayerIndex();
00354
00355
00356 assert(user_supplied_epi_index<3);
00357 assert(user_supplied_mid_index<3);
00358 assert(user_supplied_endo_index<3);
00359
00360
00361 std::vector<unsigned> user_supplied_indices;
00362 user_supplied_indices.push_back(user_supplied_epi_index);
00363 user_supplied_indices.push_back(user_supplied_mid_index);
00364 user_supplied_indices.push_back(user_supplied_endo_index);
00365
00366
00367
00368
00369 for (unsigned layer_index=0; layer_index<3; layer_index++)
00370 {
00371 unsigned counter = 0;
00372
00373 for (unsigned supplied_index = 0; supplied_index<user_supplied_indices.size(); supplied_index++)
00374 {
00375 if (user_supplied_indices[supplied_index] == layer_index)
00376 {
00377 break;
00378 }
00379 counter++;
00380 }
00381
00382
00383 if (counter==0)
00384 {
00385 mCellHeterogeneityAreas.push_back(new ChasteNodesList<3u>(epi_nodes));
00386 }
00387 if (counter==1)
00388 {
00389 mCellHeterogeneityAreas.push_back(new ChasteNodesList<3u>(mid_nodes));
00390 }
00391 if (counter==2)
00392 {
00393 mCellHeterogeneityAreas.push_back(new ChasteNodesList<3u>(endo_nodes));
00394 }
00395 assert(counter<3);
00396 }
00397 assert(mCellHeterogeneityAreas.size()==3);
00398 }
00399
00400
00401 template class HeartConfigRelatedCellFactory<1u>;
00402 template class HeartConfigRelatedCellFactory<2u>;
00403 template class HeartConfigRelatedCellFactory<3u>;