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