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