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
00030
00031
00032
00033
00034
00035
00036
00037 #include "CheckpointArchiveTypesIfNeeded.hpp"
00038
00039 #include "UblasCustomFunctions.hpp"
00040
00041 #include "HeartConfig.hpp"
00042 #include "OutputFileHandler.hpp"
00043 #include "Exception.hpp"
00044 #include "ChastePoint.hpp"
00045 #include "Version.hpp"
00046 #include "AbstractChasteRegion.hpp"
00047 #include "HeartFileFinder.hpp"
00048 #include "Warnings.hpp"
00049
00050 #include "HeartRegionCodes.hpp"
00051
00052 #include "SimpleStimulus.hpp"
00053 #include "RegularStimulus.hpp"
00054
00055 #include <string>
00056 #include <istream>
00057 #include <fstream>
00058 #include <cassert>
00059 #include <map>
00060
00061 #include "XmlTools.hpp"
00062 #include <xsd/cxx/tree/exceptions.hxx>
00063 using namespace xsd::cxx::tree;
00064
00065
00066 #if (XSD_INT_VERSION >= 3000000L)
00067 #define XSD_SEQUENCE_TYPE(base) base##_sequence
00068 #define XSD_ITERATOR_TYPE(base) base##_iterator
00069 #define XSD_NESTED_TYPE(t) t##_type
00070 #define XSD_ANON_TYPE(t1, t2) \
00071 t1::t2##_type
00072 #else
00073 #define XSD_SEQUENCE_TYPE(base) base::container
00074 #define XSD_ITERATOR_TYPE(base) base::iterator
00075 #define XSD_NESTED_TYPE(t) t::type
00076 #define XSD_ANON_TYPE(t1, t2) \
00077 t1::t2::_xsd_##t2##_::t2
00078 #endif
00079
00080
00081 #define XSD_ANON_SEQUENCE_TYPE(t1, t2, t3) \
00082 XSD_SEQUENCE_TYPE(XSD_ANON_TYPE(t1, t2)::t3)
00083 #define XSD_ANON_ITERATOR_TYPE(t1, t2, t3) \
00084 XSD_ITERATOR_TYPE(XSD_ANON_TYPE(t1, t2)::t3)
00085
00086
00087 #if (XSD_INT_VERSION >= 3020000L)
00088 #define XSD_CREATE_WITH_FIXED_ATTR(type, name, attr) \
00089 type name
00090 #define XSD_CREATE_WITH_FIXED_ATTR1(type, name, arg1, attr) \
00091 type name(arg1)
00092 #define XSD_CREATE_WITH_FIXED_ATTR2(type, name, arg1, arg2, attr) \
00093 type name(arg1, arg2)
00094 #define XSD_CREATE_WITH_FIXED_ATTR3(type, name, arg1, arg2, arg3, attr) \
00095 type name(arg1, arg2, arg3)
00096 #else
00097 #define XSD_CREATE_WITH_FIXED_ATTR(type, name, attr) \
00098 type name(attr)
00099 #define XSD_CREATE_WITH_FIXED_ATTR1(type, name, arg1, attr) \
00100 type name(arg1, attr)
00101 #define XSD_CREATE_WITH_FIXED_ATTR2(type, name, arg1, arg2, attr) \
00102 type name(arg1, arg2, attr)
00103 #define XSD_CREATE_WITH_FIXED_ATTR3(type, name, arg1, arg2, arg3, attr) \
00104 type name(arg1, arg2, arg3, attr)
00105 #endif
00106
00110 #define ENSURE_SECTION_PRESENT(location, type) \
00111 if (!location.present()) \
00112 { \
00113 type empty_item; \
00114 location.set(empty_item); \
00115 }
00116
00117 #include <boost/current_function.hpp>
00125 #define CHECK_EXISTS(test, path) \
00126 do { \
00127 if (!test) { \
00128 EXCEPTION("No XML element " << path << " found in parameters when calling '" \
00129 << BOOST_CURRENT_FUNCTION << "'"); \
00130 }} while (false)
00131
00132
00137 class XmlTransforms
00138 {
00139 public:
00147 static void TransformIonicModelDefinitions(xercesc::DOMDocument* pDocument,
00148 xercesc::DOMElement* pRootElement);
00149
00158 static void TransformArchiveDirectory(xercesc::DOMDocument* pDocument,
00159 xercesc::DOMElement* pRootElement);
00160
00168 static void CheckForIluPreconditioner(xercesc::DOMDocument* pDocument,
00169 xercesc::DOMElement* pRootElement);
00170
00178 static void MoveConductivityHeterogeneities(xercesc::DOMDocument* pDocument,
00179 xercesc::DOMElement* pRootElement);
00180 };
00181
00182
00183
00184
00185 #include "HeartConfigDefaults.hpp"
00186
00187
00188
00189
00190 std::auto_ptr<HeartConfig> HeartConfig::mpInstance;
00191
00192
00193
00194
00195
00196 HeartConfig* HeartConfig::Instance()
00197 {
00198 if (mpInstance.get() == NULL)
00199 {
00200 mpInstance.reset(new HeartConfig);
00201 }
00202 return mpInstance.get();
00203 }
00204
00205 HeartConfig::HeartConfig()
00206 : mUseMassLumping(false),
00207 mUseMassLumpingForPrecond(false),
00208 mUseFixedNumberIterations(false),
00209 mEvaluateNumItsEveryNSolves(UINT_MAX)
00210 {
00211 assert(mpInstance.get() == NULL);
00212 mUseFixedSchemaLocation = true;
00213 SetDefaultSchemaLocations();
00214
00215 mpParameters = CreateDefaultParameters();
00216
00217
00218
00219 mEpiFraction = -1.0;
00220 mEndoFraction = -1.0;
00221 mMidFraction = -1.0;
00222 mUserAskedForCellularTransmuralHeterogeneities = false;
00223
00224
00225
00226 mIndexMid = UINT_MAX-3u;
00227 mIndexEpi = UINT_MAX-3u;
00228 mIndexEndo = UINT_MAX-3u;
00229
00230 mUseReactionDiffusionOperatorSplitting = false;
00231
00233 mTissueIdentifiers.insert(0);
00234 mBathIdentifiers.insert(1);
00235 }
00236
00237 HeartConfig::~HeartConfig()
00238 {
00239 }
00240
00241
00242 void HeartConfig::Write(bool useArchiveLocationInfo, std::string subfolderName)
00243 {
00244
00245 std::string output_dirname;
00246 if (useArchiveLocationInfo)
00247 {
00248 output_dirname = ArchiveLocationInfo::GetArchiveDirectory();
00249 }
00250 else
00251 {
00252 OutputFileHandler handler(GetOutputDirectory() + "/" + subfolderName, false);
00253 output_dirname = handler.GetOutputDirectoryFullPath();
00254 }
00255
00256
00257
00258
00259
00260 if (!PetscTools::AmMaster())
00261 {
00262 return;
00263 }
00264
00265 out_stream p_parameters_file( new std::ofstream( (output_dirname+"ChasteParameters.xml").c_str() ) );
00266
00267 if (!p_parameters_file->is_open())
00268 {
00269 EXCEPTION("Could not open XML file in HeartConfig");
00270 }
00271
00272
00273
00274 ::xml_schema::namespace_infomap map;
00275
00276 map[""].schema = "ChasteParameters_1_1.xsd";
00277
00278 map["cp20"].name = "https://chaste.comlab.ox.ac.uk/nss/parameters/2_0";
00279 map["cp20"].schema = "ChasteParameters_2_0.xsd";
00280 map["cp21"].name = "https://chaste.comlab.ox.ac.uk/nss/parameters/2_1";
00281 map["cp21"].schema = "ChasteParameters_2_1.xsd";
00282 map["cp22"].name = "https://chaste.comlab.ox.ac.uk/nss/parameters/2_2";
00283 map["cp22"].schema = "ChasteParameters_2_2.xsd";
00284 map["cp23"].name = "https://chaste.comlab.ox.ac.uk/nss/parameters/2_3";
00285 map["cp23"].schema = "ChasteParameters_2_3.xsd";
00286 map["cp30"].name = "https://chaste.comlab.ox.ac.uk/nss/parameters/3_0";
00287 map["cp30"].schema = "ChasteParameters_3_0.xsd";
00288
00289
00290 map["cp"].name = "https://chaste.comlab.ox.ac.uk/nss/parameters/3_1";
00291 map["cp"].schema = "ChasteParameters_3_1.xsd";
00292
00293 cp::ChasteParameters(*p_parameters_file, *mpParameters, map);
00294
00295
00296 if (useArchiveLocationInfo)
00297 {
00298 CopySchema(output_dirname);
00299 }
00300
00301 }
00302
00303 void HeartConfig::LoadFromCheckpoint()
00304 {
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314 assert(mpParameters.use_count() > 0);
00315 boost::shared_ptr<cp::chaste_parameters_type> p_new_parameters = mpParameters;
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325 std::string parameters_filename_xml = ArchiveLocationInfo::GetArchiveDirectory() + "ChasteParameters.xml";
00326 mpParameters = ReadFile(parameters_filename_xml);
00327 mParametersFilePath.SetPath(parameters_filename_xml, RelativeTo::AbsoluteOrCwd);
00328
00329
00330 std::string defaults_filename_xml = ArchiveLocationInfo::GetArchiveDirectory() + "ChasteDefaults.xml";
00331 if (FileFinder(defaults_filename_xml).Exists())
00332 {
00333 boost::shared_ptr<cp::chaste_parameters_type> p_defaults = ReadFile(defaults_filename_xml);
00334 MergeDefaults(mpParameters, p_defaults);
00335 }
00336
00337 HeartConfig::Instance()->SetCheckpointSimulation(false);
00338
00339
00340 if (p_new_parameters->ResumeSimulation().present())
00341 {
00342 UpdateParametersFromResumeSimulation(p_new_parameters);
00343 }
00344
00345 CheckTimeSteps();
00346 }
00347
00348 void HeartConfig::CopySchema(const std::string& rToDirectory)
00349 {
00350
00351
00352
00353
00354 std::string schema_name("ChasteParameters_3_1.xsd");
00355 FileFinder schema_location("heart/src/io/" + schema_name, RelativeTo::ChasteSourceRoot);
00356 if (!schema_location.Exists())
00357 {
00358
00359 schema_location.SetPath(schema_name, RelativeTo::CWD);
00360 if (!schema_location.Exists())
00361 {
00362
00363 std::string message("Unable to locate schema file " + schema_name +
00364 ". You will need to ensure it is available when resuming from the checkpoint.");
00365 WARN_ONCE_ONLY(message);
00366 }
00367 }
00368 if (schema_location.Exists())
00369 {
00370 FileFinder output_directory(rToDirectory, RelativeTo::Absolute);
00371 schema_location.CopyTo(output_directory);
00372 }
00373 }
00374
00375 void HeartConfig::SetDefaultSchemaLocations()
00376 {
00377 mSchemaLocations.clear();
00378
00379 std::string root_dir = std::string(ChasteBuildInfo::GetRootDir()) + "/heart/src/io/";
00380
00381 mSchemaLocations[""] = root_dir + "ChasteParameters_1_1.xsd";
00382
00383 mSchemaLocations["https://chaste.comlab.ox.ac.uk/nss/parameters/2_0"] = root_dir + "ChasteParameters_2_0.xsd";
00384 mSchemaLocations["https://chaste.comlab.ox.ac.uk/nss/parameters/2_1"] = root_dir + "ChasteParameters_2_1.xsd";
00385 mSchemaLocations["https://chaste.comlab.ox.ac.uk/nss/parameters/2_2"] = root_dir + "ChasteParameters_2_2.xsd";
00386 mSchemaLocations["https://chaste.comlab.ox.ac.uk/nss/parameters/2_3"] = root_dir + "ChasteParameters_2_3.xsd";
00387 mSchemaLocations["https://chaste.comlab.ox.ac.uk/nss/parameters/3_0"] = root_dir + "ChasteParameters_3_0.xsd";
00388 mSchemaLocations["https://chaste.comlab.ox.ac.uk/nss/parameters/3_1"] = root_dir + "ChasteParameters_3_1.xsd";
00389 }
00390
00391 unsigned HeartConfig::GetVersionFromNamespace(const std::string& rNamespaceUri)
00392 {
00393 unsigned version_major = 0;
00394 unsigned version_minor = 0;
00395 if (rNamespaceUri == "")
00396 {
00397 version_major = 1;
00398 version_minor = 1;
00399 }
00400 else
00401 {
00402 std::string uri_base("https://chaste.comlab.ox.ac.uk/nss/parameters/");
00403 if (rNamespaceUri.substr(0, uri_base.length()) == uri_base)
00404 {
00405 std::istringstream version_string(rNamespaceUri.substr(uri_base.length()));
00406 version_string >> version_major;
00407 version_string.ignore(1);
00408 version_string >> version_minor;
00409 if (version_string.fail())
00410 {
00411 version_major = 0;
00412 version_minor = 0;
00413 }
00414 }
00415 }
00416
00417 unsigned version = version_major * 1000 + version_minor;
00418 if (version == 0)
00419 {
00420 EXCEPTION(rNamespaceUri + " is not a recognised Chaste parameters namespace.");
00421 }
00422 return version;
00423 }
00424
00425 void HeartConfig::SetFixedSchemaLocations(const SchemaLocationsMap& rSchemaLocations)
00426 {
00427 mSchemaLocations = rSchemaLocations;
00428 SetUseFixedSchemaLocation(true);
00429 }
00430
00431 void HeartConfig::SetUseFixedSchemaLocation(bool useFixedSchemaLocation)
00432 {
00433 mUseFixedSchemaLocation = useFixedSchemaLocation;
00434 }
00435
00436 boost::shared_ptr<cp::chaste_parameters_type> HeartConfig::ReadFile(const std::string& rFileName)
00437 {
00438
00439 ::xml_schema::properties props;
00440 if (mUseFixedSchemaLocation)
00441 {
00442 for (SchemaLocationsMap::iterator it = mSchemaLocations.begin();
00443 it != mSchemaLocations.end();
00444 ++it)
00445 {
00446 if (it->first == "")
00447 {
00448 props.no_namespace_schema_location(XmlTools::EscapeSpaces(it->second));
00449 }
00450 else
00451 {
00452 props.schema_location(it->first, XmlTools::EscapeSpaces(it->second));
00453 }
00454 }
00455 }
00456
00457
00458
00459 try
00460 {
00461
00462 XmlTools::Finalizer finalizer(false);
00463
00464 xsd::cxx::xml::dom::auto_ptr<xercesc::DOMDocument> p_doc = XmlTools::ReadXmlFile(rFileName, props);
00465
00466 xercesc::DOMElement* p_root_elt = p_doc->getDocumentElement();
00467 std::string namespace_uri(X2C(p_root_elt->getNamespaceURI()));
00468 const unsigned version = GetVersionFromNamespace(namespace_uri);
00469 if (version < 2000)
00470 {
00471 XmlTransforms::TransformIonicModelDefinitions(p_doc.get(), p_root_elt);
00472 }
00473 if (version < 2001)
00474 {
00475 XmlTransforms::TransformArchiveDirectory(p_doc.get(), p_root_elt);
00476 XmlTransforms::CheckForIluPreconditioner(p_doc.get(), p_root_elt);
00477 }
00478 if (version < 3001)
00479 {
00480 XmlTransforms::MoveConductivityHeterogeneities(p_doc.get(), p_root_elt);
00481 }
00482 if (version < 3001)
00483 {
00484 XmlTools::SetNamespace(p_doc.get(), p_root_elt, "https://chaste.comlab.ox.ac.uk/nss/parameters/3_1");
00485 }
00486
00487 std::auto_ptr<cp::chaste_parameters_type> p_params(cp::ChasteParameters(*p_doc, ::xml_schema::flags::dont_initialize, props));
00488
00489 p_doc.reset();
00490
00491 return boost::shared_ptr<cp::chaste_parameters_type>(p_params);
00492 }
00493 catch (const xml_schema::exception& e)
00494 {
00495 std::cerr << e << std::endl;
00496
00497 mpParameters.reset();
00498 EXCEPTION("XML parsing error in configuration file: " + rFileName);
00499 }
00500 catch (...)
00501 {
00502
00503 mpParameters.reset();
00504 throw;
00505 }
00506 }
00507
00508 void HeartConfig::SetParametersFile(const std::string& rFileName)
00509 {
00510 mpParameters = ReadFile(rFileName);
00511 MergeDefaults(mpParameters, CreateDefaultParameters());
00512 mParametersFilePath.SetPath(rFileName, RelativeTo::AbsoluteOrCwd);
00513
00514 if (IsSimulationDefined())
00515 {
00516 CheckTimeSteps();
00517 }
00518 }
00519
00520 FileFinder HeartConfig::GetParametersFilePath()
00521 {
00522 return mParametersFilePath;
00523 }
00524
00525 void HeartConfig::UpdateParametersFromResumeSimulation(boost::shared_ptr<cp::chaste_parameters_type> pResumeParameters)
00526 {
00527
00528 if ( (pResumeParameters->ResumeSimulation()->SpaceDimension() != HeartConfig::Instance()->GetSpaceDimension())
00529 ||(pResumeParameters->ResumeSimulation()->Domain() != HeartConfig::Instance()->GetDomain()))
00530 {
00531 EXCEPTION("Problem type and space dimension should match when restarting a simulation.");
00532 }
00533
00534
00535 HeartConfig::Instance()->SetSimulationDuration(pResumeParameters->ResumeSimulation()->SimulationDuration());
00536
00537
00538 if (pResumeParameters->ResumeSimulation()->Stimuli().present())
00539 {
00540 mpParameters->Simulation()->Stimuli().set(pResumeParameters->ResumeSimulation()->Stimuli().get());
00541 }
00542
00543
00544
00545 if (pResumeParameters->ResumeSimulation()->CellHeterogeneities().present())
00546 {
00547 if (!mpParameters->Simulation()->CellHeterogeneities().present())
00548 {
00549
00550 mpParameters->Simulation()->CellHeterogeneities().set(pResumeParameters->ResumeSimulation()->CellHeterogeneities().get());
00551 }
00552 else
00553 {
00554
00555 XSD_SEQUENCE_TYPE(cp::cell_heterogeneities_type::CellHeterogeneity)&
00556 new_seq = pResumeParameters->ResumeSimulation()->CellHeterogeneities()->CellHeterogeneity();
00557 XSD_SEQUENCE_TYPE(cp::cell_heterogeneities_type::CellHeterogeneity)&
00558 orig_seq = mpParameters->Simulation()->CellHeterogeneities()->CellHeterogeneity();
00559 for (XSD_ITERATOR_TYPE(cp::cell_heterogeneities_type::CellHeterogeneity) i = new_seq.begin();
00560 i != new_seq.end();
00561 ++i)
00562 {
00563 orig_seq.push_back(*i);
00564 }
00565 }
00566 }
00567
00568
00569 if (pResumeParameters->ResumeSimulation()->CheckpointSimulation().present())
00570 {
00571 HeartConfig::Instance()->SetCheckpointSimulation(true,
00572 pResumeParameters->ResumeSimulation()->CheckpointSimulation()->timestep(),
00573 pResumeParameters->ResumeSimulation()->CheckpointSimulation()->max_checkpoints_on_disk());
00574 }
00575
00576
00577 HeartConfig::Instance()->SetVisualizeWithParallelVtk(pResumeParameters->ResumeSimulation()->OutputVisualizer().parallel_vtk() == cp::yesno_type::yes);
00578 HeartConfig::Instance()->SetVisualizeWithVtk(pResumeParameters->ResumeSimulation()->OutputVisualizer().vtk() == cp::yesno_type::yes);
00579 HeartConfig::Instance()->SetVisualizeWithCmgui(pResumeParameters->ResumeSimulation()->OutputVisualizer().cmgui() == cp::yesno_type::yes);
00580 HeartConfig::Instance()->SetVisualizeWithMeshalyzer(pResumeParameters->ResumeSimulation()->OutputVisualizer().meshalyzer() == cp::yesno_type::yes);
00581
00582
00583 {
00584 cp::numerical_type& r_resume = pResumeParameters->Numerical();
00585 cp::numerical_type& r_user = mpParameters->Numerical();
00586 if (r_resume.TimeSteps().present())
00587 {
00588 r_user.TimeSteps().set(r_resume.TimeSteps().get());
00589 }
00590 if (r_resume.KSPTolerances().present())
00591 {
00592 r_user.KSPTolerances().set(r_resume.KSPTolerances().get());
00593 }
00594 if (r_resume.KSPSolver().present())
00595 {
00596 r_user.KSPSolver().set(r_resume.KSPSolver().get());
00597 }
00598 if (r_resume.KSPPreconditioner().present())
00599 {
00600 r_user.KSPPreconditioner().set(r_resume.KSPPreconditioner().get());
00601 }
00602 if (r_resume.AdaptivityParameters().present())
00603 {
00604 r_user.AdaptivityParameters().set(r_resume.AdaptivityParameters().get());
00605 }
00606 }
00607
00608
00609 if (pResumeParameters->PostProcessing().present())
00610 {
00611 EnsurePostProcessingSectionPresent();
00612 cp::postprocessing_type& r_resume = pResumeParameters->PostProcessing().get();
00613 cp::postprocessing_type& r_user = mpParameters->PostProcessing().get();
00614 if (!r_resume.ActionPotentialDurationMap().empty())
00615 {
00616 r_user.ActionPotentialDurationMap() = r_resume.ActionPotentialDurationMap();
00617 }
00618 if (!r_resume.UpstrokeTimeMap().empty())
00619 {
00620 r_user.UpstrokeTimeMap() = r_resume.UpstrokeTimeMap();
00621 }
00622 if (!r_resume.MaxUpstrokeVelocityMap().empty())
00623 {
00624 r_user.MaxUpstrokeVelocityMap() = r_resume.MaxUpstrokeVelocityMap();
00625 }
00626 if (!r_resume.ConductionVelocityMap().empty())
00627 {
00628 r_user.ConductionVelocityMap() = r_resume.ConductionVelocityMap();
00629 }
00630 }
00631 }
00632
00633
00634 void HeartConfig::Reset()
00635 {
00636
00637 mpInstance.reset();
00638
00639 mpInstance.reset(new HeartConfig);
00640 }
00641
00642 bool HeartConfig::IsSimulationDefined() const
00643 {
00644 return mpParameters->Simulation().present();
00645 }
00646
00647 bool HeartConfig::IsSimulationResumed() const
00648 {
00649 return mpParameters->ResumeSimulation().present();
00650 }
00651
00652
00653 void HeartConfig::CheckSimulationIsDefined(std::string callingMethod) const
00654 {
00655 if (IsSimulationResumed())
00656 {
00657 EXCEPTION(callingMethod + " information is not available in a resumed simulation.");
00658 }
00659 }
00660
00661 void HeartConfig::CheckResumeSimulationIsDefined(std::string callingMethod) const
00662 {
00663 if (IsSimulationDefined())
00664 {
00665 EXCEPTION(callingMethod + " information is not available in a standard (non-resumed) simulation.");
00666 }
00667 }
00668
00669 unsigned HeartConfig::GetSpaceDimension() const
00670 {
00671 if (IsSimulationDefined())
00672 {
00673 CHECK_EXISTS(mpParameters->Simulation()->SpaceDimension().present(), "Simulation/SpaceDimension");
00674 return mpParameters->Simulation()->SpaceDimension().get();
00675 }
00676 else
00677 {
00678 return mpParameters->ResumeSimulation()->SpaceDimension();
00679 }
00680 }
00681
00682 double HeartConfig::GetSimulationDuration() const
00683 {
00684 if (IsSimulationDefined())
00685 {
00686 CHECK_EXISTS(mpParameters->Simulation()->SimulationDuration().present(), "Simulation/SimulationDuration");
00687 return mpParameters->Simulation()->SimulationDuration().get();
00688 }
00689 else
00690 {
00691 return mpParameters->ResumeSimulation()->SimulationDuration();
00692 }
00693 }
00694
00695 cp::domain_type HeartConfig::GetDomain() const
00696 {
00697 if (IsSimulationDefined())
00698 {
00699 CHECK_EXISTS(mpParameters->Simulation()->Domain().present(), "Simulation/Domain");
00700 return mpParameters->Simulation()->Domain().get();
00701 }
00702 else
00703 {
00704 return mpParameters->ResumeSimulation()->Domain();
00705 }
00706 }
00707
00708 cp::ionic_model_selection_type HeartConfig::GetDefaultIonicModel() const
00709 {
00710 CheckSimulationIsDefined("DefaultIonicModel");
00711
00712 return mpParameters->Simulation()->IonicModels()->Default();
00713 }
00714
00715 template<unsigned DIM>
00716 void HeartConfig::GetIonicModelRegions(std::vector<boost::shared_ptr<AbstractChasteRegion<DIM> > >& definedRegions,
00717 std::vector<cp::ionic_model_selection_type>& ionicModels) const
00718 {
00719 CheckSimulationIsDefined("IonicModelRegions");
00720 definedRegions.clear();
00721 ionicModels.clear();
00722
00723 XSD_SEQUENCE_TYPE(cp::ionic_models_type::Region)&
00724 regions = mpParameters->Simulation()->IonicModels()->Region();
00725
00726 for (XSD_ITERATOR_TYPE(cp::ionic_models_type::Region) i = regions.begin();
00727 i != regions.end();
00728 ++i)
00729 {
00730 cp::ionic_model_region_type ionic_model_region(*i);
00731
00732 if (ionic_model_region.Location().Cuboid().present() || ionic_model_region.Location().Ellipsoid().present())
00733 {
00734 if (ionic_model_region.Location().Cuboid().present())
00735 {
00736 cp::point_type point_a = ionic_model_region.Location().Cuboid()->LowerCoordinates();
00737 cp::point_type point_b = ionic_model_region.Location().Cuboid()->UpperCoordinates();
00738
00739 switch (DIM)
00740 {
00741 case 1:
00742 {
00743 ChastePoint<DIM> chaste_point_a ( point_a.x() );
00744 ChastePoint<DIM> chaste_point_b ( point_b.x() );
00745 definedRegions.push_back(boost::shared_ptr<AbstractChasteRegion<DIM> >(new ChasteCuboid<DIM>( chaste_point_a, chaste_point_b )));
00746 break;
00747 }
00748 case 2:
00749 {
00750 ChastePoint<DIM> chaste_point_a ( point_a.x(), point_a.y() );
00751 ChastePoint<DIM> chaste_point_b ( point_b.x(), point_b.y() );
00752 definedRegions.push_back(boost::shared_ptr<AbstractChasteRegion<DIM> >(new ChasteCuboid<DIM>( chaste_point_a, chaste_point_b )));
00753 break;
00754 }
00755 case 3:
00756 {
00757 ChastePoint<DIM> chaste_point_a ( point_a.x(), point_a.y(), point_a.z() );
00758 ChastePoint<DIM> chaste_point_b ( point_b.x(), point_b.y(), point_b.z() );
00759 definedRegions.push_back(boost::shared_ptr<AbstractChasteRegion<DIM> >(new ChasteCuboid<DIM>( chaste_point_a, chaste_point_b )) );
00760 break;
00761 }
00762 default:
00763 NEVER_REACHED;
00764 break;
00765 }
00766 }
00767 else if (ionic_model_region.Location().Ellipsoid().present())
00768 {
00769 cp::point_type centre = ionic_model_region.Location().Ellipsoid()->Centre();
00770 cp::point_type radii = ionic_model_region.Location().Ellipsoid()->Radii();
00771 switch (DIM)
00772 {
00773 case 1:
00774 {
00775 ChastePoint<DIM> chaste_point_a ( centre.x() );
00776 ChastePoint<DIM> chaste_point_b ( radii.x() );
00777 definedRegions.push_back(boost::shared_ptr<AbstractChasteRegion<DIM> >(new ChasteEllipsoid<DIM> ( chaste_point_a, chaste_point_b )) );
00778 break;
00779 }
00780 case 2:
00781 {
00782 ChastePoint<DIM> chaste_point_a ( centre.x(), centre.y() );
00783 ChastePoint<DIM> chaste_point_b ( radii.x(), radii.y() );
00784 definedRegions.push_back(boost::shared_ptr<AbstractChasteRegion<DIM> >(new ChasteEllipsoid<DIM> ( chaste_point_a, chaste_point_b )) );
00785 break;
00786 }
00787 case 3:
00788 {
00789 ChastePoint<DIM> chaste_point_a ( centre.x(), centre.y(), centre.z() );
00790 ChastePoint<DIM> chaste_point_b ( radii.x(), radii.y(), radii.z() );
00791 definedRegions.push_back(boost::shared_ptr<AbstractChasteRegion<DIM> >(new ChasteEllipsoid<DIM> ( chaste_point_a, chaste_point_b )) );
00792 break;
00793 }
00794 default:
00795 {
00796 NEVER_REACHED;
00797 break;
00798 }
00799 }
00800 }
00801 else
00802 {
00803 NEVER_REACHED;
00804 }
00805
00806 ionicModels.push_back(ionic_model_region.IonicModel());
00807 }
00808 else if(ionic_model_region.Location().EpiLayer().present() || ionic_model_region.Location().MidLayer().present() || ionic_model_region.Location().EndoLayer().present() )
00809 {
00811 EXCEPTION("Definition of transmural layers is not yet supported for defining different ionic models, please use cuboids instead");
00812 }
00813 else
00814 {
00815 EXCEPTION("Invalid region type for ionic model definition");
00816 }
00817 }
00818 }
00819
00820
00821 bool HeartConfig::IsMeshProvided() const
00822 {
00823 CheckSimulationIsDefined("Mesh");
00824 return mpParameters->Simulation()->Mesh().present();
00825 }
00826
00827 bool HeartConfig::GetCreateMesh() const
00828 {
00829 CheckSimulationIsDefined("Mesh");
00830 CHECK_EXISTS(IsMeshProvided(), "Simulation/Mesh");
00831 cp::mesh_type mesh = mpParameters->Simulation()->Mesh().get();
00832 return (mesh.Slab().present() || mesh.Sheet().present() || mesh.Fibre().present());
00833 }
00834
00835 bool HeartConfig::GetCreateSlab() const
00836 {
00837 CheckSimulationIsDefined("Mesh");
00838 CHECK_EXISTS(IsMeshProvided(), "Simulation/Mesh");
00839 cp::mesh_type mesh = mpParameters->Simulation()->Mesh().get();
00840 return (mesh.Slab().present());
00841 }
00842
00843 bool HeartConfig::GetCreateSheet() const
00844 {
00845 CheckSimulationIsDefined("Mesh");
00846 CHECK_EXISTS(IsMeshProvided(), "Simulation/Mesh");
00847 cp::mesh_type mesh = mpParameters->Simulation()->Mesh().get();
00848 return (mesh.Sheet().present());
00849 }
00850
00851 bool HeartConfig::GetCreateFibre() const
00852 {
00853 CheckSimulationIsDefined("Mesh");
00854 CHECK_EXISTS(IsMeshProvided(), "Simulation/Mesh");
00855 cp::mesh_type mesh = mpParameters->Simulation()->Mesh().get();
00856 return (mesh.Fibre().present());
00857 }
00858
00859
00860 bool HeartConfig::GetLoadMesh() const
00861 {
00862 CheckSimulationIsDefined("Mesh");
00863 CHECK_EXISTS(IsMeshProvided(), "Simulation/Mesh");
00864 return (mpParameters->Simulation()->Mesh()->LoadMesh().present());
00865 }
00866
00867 void HeartConfig::GetSlabDimensions(c_vector<double, 3>& slabDimensions) const
00868 {
00869 CheckSimulationIsDefined("Slab");
00870
00871 if (GetSpaceDimension()!=3 || !GetCreateSlab())
00872 {
00873 EXCEPTION("Tissue slabs can only be defined in 3D");
00874 }
00875
00876 optional<cp::slab_type, false> slab_dimensions = mpParameters->Simulation()->Mesh()->Slab();
00877
00878 slabDimensions[0] = slab_dimensions->x();
00879 slabDimensions[1] = slab_dimensions->y();
00880 slabDimensions[2] = slab_dimensions->z();
00881 }
00882
00883 void HeartConfig::GetSheetDimensions(c_vector<double, 2>& sheetDimensions) const
00884 {
00885 CheckSimulationIsDefined("Sheet");
00886
00887 if (GetSpaceDimension()!=2 || !GetCreateSheet())
00888 {
00889 EXCEPTION("Tissue sheets can only be defined in 2D");
00890 }
00891
00892 optional<cp::sheet_type, false> sheet_dimensions = mpParameters->Simulation()->Mesh()->Sheet();
00893
00894 sheetDimensions[0] = sheet_dimensions->x();
00895 sheetDimensions[1] = sheet_dimensions->y();
00896 }
00897
00898 void HeartConfig::GetFibreLength(c_vector<double, 1>& fibreLength) const
00899 {
00900 CheckSimulationIsDefined("Fibre");
00901
00902 if (GetSpaceDimension()!=1 || !GetCreateFibre())
00903 {
00904 EXCEPTION("Tissue fibres can only be defined in 1D");
00905 }
00906
00907 optional<cp::fibre_type, false> fibre_length = mpParameters->Simulation()->Mesh()->Fibre();
00908
00909 fibreLength[0] = fibre_length->x();
00910 }
00911
00912 double HeartConfig::GetInterNodeSpace() const
00913 {
00914 CheckSimulationIsDefined("InterNodeSpace");
00915
00916 switch (GetSpaceDimension())
00917 {
00918 case 3:
00919 CHECK_EXISTS(GetCreateSlab(), "Simulation/Mesh/Slab");
00920 return mpParameters->Simulation()->Mesh()->Slab()->inter_node_space();
00921 break;
00922 case 2:
00923 CHECK_EXISTS(GetCreateSheet(), "Simulation/Mesh/Sheet");
00924 return mpParameters->Simulation()->Mesh()->Sheet()->inter_node_space();
00925 break;
00926 case 1:
00927 CHECK_EXISTS(GetCreateFibre(), "Simulation/Mesh/Fibre");
00928 return mpParameters->Simulation()->Mesh()->Fibre()->inter_node_space();
00929 break;
00930 default:
00931 NEVER_REACHED;
00932 #define COVERAGE_IGNORE
00933 return 0.0;
00934 #undef COVERAGE_IGNORE
00935 }
00936 }
00937
00938 std::string HeartConfig::GetMeshName() const
00939 {
00940 CheckSimulationIsDefined("LoadMesh");
00941 CHECK_EXISTS(GetLoadMesh(), "Mesh/LoadMesh");
00942
00943 return mpParameters->Simulation()->Mesh()->LoadMesh()->name();
00944 }
00945
00946 cp::media_type HeartConfig::GetConductivityMedia() const
00947 {
00948 CheckSimulationIsDefined("LoadMesh");
00949 CHECK_EXISTS(GetLoadMesh(), "Mesh/LoadMesh");
00950
00951 return mpParameters->Simulation()->Mesh()->LoadMesh()->conductivity_media();
00952 }
00953
00954 template <unsigned DIM>
00955 void HeartConfig::GetStimuli(std::vector<boost::shared_ptr<AbstractStimulusFunction> >& rStimuliApplied,
00956 std::vector<boost::shared_ptr<AbstractChasteRegion<DIM> > >& rStimulatedAreas) const
00957 {
00958 CheckSimulationIsDefined("Stimuli");
00959
00960 if (!mpParameters->Simulation()->Stimuli().present())
00961 {
00962
00963
00964 return;
00965 }
00966
00967 XSD_SEQUENCE_TYPE(cp::stimuli_type::Stimulus) stimuli = mpParameters->Simulation()->Stimuli()->Stimulus();
00968
00969 for (XSD_ITERATOR_TYPE(cp::stimuli_type::Stimulus) i = stimuli.begin();
00970 i != stimuli.end();
00971 ++i)
00972 {
00973 cp::stimulus_type stimulus(*i);
00974 if (stimulus.Location().Cuboid().present() || stimulus.Location().Ellipsoid().present())
00975 {
00976 boost::shared_ptr<AbstractChasteRegion<DIM> > area_ptr;
00977 if (stimulus.Location().Cuboid().present() )
00978 {
00979 cp::point_type point_a = stimulus.Location().Cuboid()->LowerCoordinates();
00980 cp::point_type point_b = stimulus.Location().Cuboid()->UpperCoordinates();
00981 switch (DIM)
00982 {
00983 case 1:
00984 {
00985 ChastePoint<DIM> chaste_point_a ( point_a.x() );
00986 ChastePoint<DIM> chaste_point_b ( point_b.x() );
00987 area_ptr.reset(new ChasteCuboid<DIM>( chaste_point_a, chaste_point_b ) );
00988 break;
00989 }
00990 case 2:
00991 {
00992 ChastePoint<DIM> chaste_point_a ( point_a.x(), point_a.y() );
00993 ChastePoint<DIM> chaste_point_b ( point_b.x(), point_b.y() );
00994 area_ptr.reset(new ChasteCuboid<DIM>( chaste_point_a, chaste_point_b ) );
00995 break;
00996 }
00997 case 3:
00998 {
00999 ChastePoint<DIM> chaste_point_a ( point_a.x(), point_a.y(), point_a.z() );
01000 ChastePoint<DIM> chaste_point_b ( point_b.x(), point_b.y(), point_b.z() );
01001 area_ptr.reset(new ChasteCuboid<DIM>( chaste_point_a, chaste_point_b ) );
01002 break;
01003 }
01004 default:
01005 NEVER_REACHED;
01006 break;
01007 }
01008 }
01009 else if (stimulus.Location().Ellipsoid().present())
01010 {
01011 cp::point_type centre = stimulus.Location().Ellipsoid()->Centre();
01012 cp::point_type radii = stimulus.Location().Ellipsoid()->Radii();
01013 switch (DIM)
01014 {
01015 case 1:
01016 {
01017 ChastePoint<DIM> chaste_point_a ( centre.x() );
01018 ChastePoint<DIM> chaste_point_b ( radii.x() );
01019 area_ptr.reset( new ChasteEllipsoid<DIM> ( chaste_point_a, chaste_point_b ) );
01020 break;
01021 }
01022 case 2:
01023 {
01024 ChastePoint<DIM> chaste_point_a ( centre.x(), centre.y() );
01025 ChastePoint<DIM> chaste_point_b ( radii.x(), radii.y() );
01026 area_ptr.reset( new ChasteEllipsoid<DIM> ( chaste_point_a, chaste_point_b ) );
01027 break;
01028 }
01029 case 3:
01030 {
01031 ChastePoint<DIM> chaste_point_a ( centre.x(), centre.y(), centre.z() );
01032 ChastePoint<DIM> chaste_point_b ( radii.x(), radii.y(), radii.z() );
01033 area_ptr.reset( new ChasteEllipsoid<DIM> ( chaste_point_a, chaste_point_b ) );
01034 break;
01035 }
01036 default:
01037 {
01038 NEVER_REACHED;
01039 break;
01040 }
01041 }
01042 }
01043 rStimulatedAreas.push_back(area_ptr);
01044
01045 boost::shared_ptr<AbstractStimulusFunction> stim;
01046
01047 if (stimulus.Period().present())
01048 {
01049 if (stimulus.StopTime().present())
01050 {
01051 stim.reset(new RegularStimulus(stimulus.Strength(),
01052 stimulus.Duration(),
01053 stimulus.Period().get(),
01054 stimulus.Delay(),
01055 stimulus.StopTime().get()));
01056 }
01057 else
01058 {
01059 stim.reset(new RegularStimulus(stimulus.Strength(),
01060 stimulus.Duration(),
01061 stimulus.Period().get(),
01062 stimulus.Delay()));
01063 }
01064
01065 }
01066 else
01067 {
01068 if (stimulus.StopTime().present())
01069 {
01070 EXCEPTION("Stop time can not be defined for SimpleStimulus. Use Duration instead.");
01071 }
01072
01073 stim.reset(new SimpleStimulus(stimulus.Strength(),
01074 stimulus.Duration(),
01075 stimulus.Delay()));
01076 }
01077 rStimuliApplied.push_back( stim );
01078 }
01079 else if(stimulus.Location().EpiLayer().present() || stimulus.Location().MidLayer().present() || stimulus.Location().EndoLayer().present() )
01080 {
01081 EXCEPTION("Definition of transmural layers is not yet supported for specifying stimulated areas, please use cuboids instead");
01082 }
01083 else
01084 {
01085 EXCEPTION("Invalid region type for stimulus definition");
01086 }
01087 }
01088 }
01089
01090
01091 template<unsigned DIM>
01092 void HeartConfig::GetCellHeterogeneities(std::vector<boost::shared_ptr<AbstractChasteRegion<DIM> > >& rCellHeterogeneityRegions,
01093 std::vector<double>& rScaleFactorGks,
01094 std::vector<double>& rScaleFactorIto,
01095 std::vector<double>& rScaleFactorGkr,
01096 std::vector<std::map<std::string, double> >* pParameterSettings)
01097 {
01098 CheckSimulationIsDefined("CellHeterogeneities");
01099
01100 if (!mpParameters->Simulation()->CellHeterogeneities().present())
01101 {
01102
01103 return;
01104 }
01105 XSD_SEQUENCE_TYPE(cp::cell_heterogeneities_type::CellHeterogeneity) cell_heterogeneity
01106 = mpParameters->Simulation()->CellHeterogeneities()->CellHeterogeneity();
01107
01108 bool user_supplied_negative_value = false;
01109 bool user_asking_for_transmural_layers = false;
01110 bool user_asked_for_cuboids_or_ellipsoids = false;
01111 unsigned counter_of_heterogeneities = 0;
01112
01113 for (XSD_ITERATOR_TYPE(cp::cell_heterogeneities_type::CellHeterogeneity) i = cell_heterogeneity.begin();
01114 i != cell_heterogeneity.end();
01115 ++i)
01116 {
01117 cp::cell_heterogeneity_type ht(*i);
01118
01119 if (ht.Location().Cuboid().present())
01120 {
01121 user_asked_for_cuboids_or_ellipsoids = true;
01122 cp::point_type point_a = ht.Location().Cuboid()->LowerCoordinates();
01123 cp::point_type point_b = ht.Location().Cuboid()->UpperCoordinates();
01124
01125 ChastePoint<DIM> chaste_point_a ( point_a.x(), point_a.y(), point_a.z() );
01126 ChastePoint<DIM> chaste_point_b ( point_b.x(), point_b.y(), point_b.z() );
01127
01128 rCellHeterogeneityRegions.push_back(boost::shared_ptr<AbstractChasteRegion<DIM> >(new ChasteCuboid<DIM> ( chaste_point_a, chaste_point_b )) );
01129 }
01130 else if (ht.Location().Ellipsoid().present())
01131 {
01132 user_asked_for_cuboids_or_ellipsoids = true;
01133 cp::point_type centre = ht.Location().Ellipsoid()->Centre();
01134 cp::point_type radii = ht.Location().Ellipsoid()->Radii();
01135
01136 ChastePoint<DIM> chaste_point_a ( centre.x(), centre.y(), centre.z() );
01137 ChastePoint<DIM> chaste_point_b ( radii.x(), radii.y(), radii.z() );
01138 rCellHeterogeneityRegions.push_back(boost::shared_ptr<AbstractChasteRegion<DIM> >(new ChasteEllipsoid<DIM> ( chaste_point_a, chaste_point_b )) );
01139 }
01140 else if (ht.Location().EpiLayer().present())
01141 {
01142 mEpiFraction = ht.Location().EpiLayer().get();
01143
01144 user_asking_for_transmural_layers = true;
01145 if (mEpiFraction <0)
01146 {
01147 user_supplied_negative_value=true;
01148 }
01149 mIndexEpi = counter_of_heterogeneities;
01150 }
01151 else if (ht.Location().EndoLayer().present())
01152 {
01153 mEndoFraction = ht.Location().EndoLayer().get();
01154
01155 user_asking_for_transmural_layers = true;
01156 if (mEndoFraction <0)
01157 {
01158 user_supplied_negative_value=true;
01159 }
01160 mIndexEndo = counter_of_heterogeneities;
01161 }
01162 else if (ht.Location().MidLayer().present())
01163 {
01164 mMidFraction = ht.Location().MidLayer().get();
01165
01166 user_asking_for_transmural_layers = true;
01167 if (mMidFraction <0)
01168 {
01169 user_supplied_negative_value=true;
01170 }
01171 mIndexMid = counter_of_heterogeneities;
01172 }
01173 else
01174 {
01175 EXCEPTION("Invalid region type for cell heterogeneity definition");
01176 }
01177
01178
01179 rScaleFactorGks.push_back(ht.ScaleFactorGks().present() ? (double)ht.ScaleFactorGks().get() : 1.0);
01180 rScaleFactorIto.push_back(ht.ScaleFactorIto().present() ? (double)ht.ScaleFactorIto().get() : 1.0);
01181 rScaleFactorGkr.push_back(ht.ScaleFactorGkr().present() ? (double)ht.ScaleFactorGkr().get() : 1.0);
01182
01183
01184 if (pParameterSettings)
01185 {
01186 std::map<std::string, double> param_settings;
01187 XSD_SEQUENCE_TYPE(cp::cell_heterogeneity_type::SetParameter)& params = ht.SetParameter();
01188 for (XSD_ITERATOR_TYPE(cp::cell_heterogeneity_type::SetParameter) param_it = params.begin();
01189 param_it != params.end();
01190 ++param_it)
01191 {
01192 cp::set_parameter_type param(*param_it);
01193 param_settings[param.name()] = param.value();
01194 }
01195 pParameterSettings->push_back(param_settings);
01196 }
01197
01198 counter_of_heterogeneities++;
01199 }
01200
01201
01202 mUserAskedForCellularTransmuralHeterogeneities = user_asking_for_transmural_layers;
01203
01204 if ( mUserAskedForCellularTransmuralHeterogeneities )
01205 {
01206
01207 if (user_asked_for_cuboids_or_ellipsoids )
01208 {
01209 EXCEPTION ("Specification of cellular heterogeneities by cuboids/ellipsoids and layers at the same time is not yet supported");
01210 }
01211
01212
01213
01214
01215 if ((mIndexMid+mIndexEndo+mIndexEpi) > 3)
01216 {
01217 EXCEPTION ("Three specifications of layers must be supplied");
01218 }
01219 if (fabs((mEndoFraction+mMidFraction+mEpiFraction)-1)>1e-2)
01220 {
01221 EXCEPTION ("Summation of epicardial, midmyocardial and endocardial fractions should be 1");
01222 }
01223 if (user_supplied_negative_value)
01224 {
01225 EXCEPTION ("Fractions must be positive");
01226 }
01227 }
01228 }
01229
01230 bool HeartConfig::AreCellularTransmuralHeterogeneitiesRequested()
01231 {
01232 return mUserAskedForCellularTransmuralHeterogeneities;
01233 }
01234
01235 double HeartConfig::GetEpiLayerFraction()
01236 {
01237 return mEpiFraction;
01238 }
01239
01240 double HeartConfig::GetEndoLayerFraction()
01241 {
01242 return mEndoFraction;
01243 }
01244
01245 double HeartConfig::GetMidLayerFraction()
01246 {
01247 return mMidFraction;
01248 }
01249
01250 unsigned HeartConfig::GetEpiLayerIndex()
01251 {
01252 return mIndexEpi;
01253 }
01254
01255 unsigned HeartConfig::GetEndoLayerIndex()
01256 {
01257 return mIndexEndo;
01258 }
01259
01260 unsigned HeartConfig::GetMidLayerIndex()
01261 {
01262 return mIndexMid;
01263 }
01264
01265 bool HeartConfig::GetConductivityHeterogeneitiesProvided() const
01266 {
01267 CheckSimulationIsDefined("ConductivityHeterogeneities");
01268 return mpParameters->Physiological().ConductivityHeterogeneities().present();
01269 }
01270
01271 template<unsigned DIM>
01272 void HeartConfig::GetConductivityHeterogeneities(
01273 std::vector<boost::shared_ptr<AbstractChasteRegion<DIM> > >& conductivitiesHeterogeneityAreas,
01274 std::vector< c_vector<double,3> >& intraConductivities,
01275 std::vector< c_vector<double,3> >& extraConductivities) const
01276 {
01277 CheckSimulationIsDefined("ConductivityHeterogeneities");
01278 CHECK_EXISTS(GetConductivityHeterogeneitiesProvided(), "Physiological/ConductivityHeterogeneities");
01279 XSD_ANON_SEQUENCE_TYPE(cp::physiological_type, ConductivityHeterogeneities, ConductivityHeterogeneity)&
01280 conductivity_heterogeneity = mpParameters->Physiological().ConductivityHeterogeneities()->ConductivityHeterogeneity();
01281
01282 for (XSD_ANON_ITERATOR_TYPE(cp::physiological_type, ConductivityHeterogeneities, ConductivityHeterogeneity) i = conductivity_heterogeneity.begin();
01283 i != conductivity_heterogeneity.end();
01284 ++i)
01285 {
01286 cp::conductivity_heterogeneity_type ht(*i);
01287
01288 if (ht.Location().Cuboid().present())
01289 {
01290 cp::point_type point_a = ht.Location().Cuboid()->LowerCoordinates();
01291 cp::point_type point_b = ht.Location().Cuboid()->UpperCoordinates();
01292 ChastePoint<DIM> chaste_point_a ( point_a.x(), point_a.y(), point_a.z() );
01293 ChastePoint<DIM> chaste_point_b ( point_b.x(), point_b.y(), point_b.z() );
01294 conductivitiesHeterogeneityAreas.push_back(boost::shared_ptr<AbstractChasteRegion<DIM> > ( new ChasteCuboid<DIM> ( chaste_point_a, chaste_point_b )) );
01295 }
01296 else if (ht.Location().Ellipsoid().present())
01297 {
01298 cp::point_type centre = ht.Location().Ellipsoid()->Centre();
01299 cp::point_type radii = ht.Location().Ellipsoid()->Radii();
01300 ChastePoint<DIM> chaste_point_a ( centre.x(), centre.y(), centre.z() );
01301 ChastePoint<DIM> chaste_point_b ( radii.x(), radii.y(), radii.z() );
01302 conductivitiesHeterogeneityAreas.push_back(boost::shared_ptr<AbstractChasteRegion<DIM> > ( new ChasteEllipsoid<DIM> ( chaste_point_a, chaste_point_b )) );
01303 }
01304 else if (ht.Location().EpiLayer().present() || ht.Location().MidLayer().present() || ht.Location().EndoLayer().present() )
01305 {
01307 EXCEPTION("Definition of transmural layers is not allowed for conductivities heterogeneities, you may use fibre orientation support instead");
01308 }
01309 else
01310 {
01311 EXCEPTION("Invalid region type for conductivity definition");
01312 }
01313
01314 if (ht.IntracellularConductivities().present())
01315 {
01316 double intra_x = ht.IntracellularConductivities()->longi();
01317 double intra_y = ht.IntracellularConductivities()->trans();
01318 double intra_z = ht.IntracellularConductivities()->normal();
01319
01320 intraConductivities.push_back( Create_c_vector(intra_x, intra_y, intra_z) );
01321 }
01322 else
01323 {
01324 c_vector<double, 3> intra_conductivities;
01325 GetIntracellularConductivities(intra_conductivities);
01326 intraConductivities.push_back(intra_conductivities);
01327 }
01328
01329 if (ht.ExtracellularConductivities().present())
01330 {
01331 double extra_x = ht.ExtracellularConductivities()->longi();
01332 double extra_y = ht.ExtracellularConductivities()->trans();
01333 double extra_z = ht.ExtracellularConductivities()->normal();
01334
01335 extraConductivities.push_back( Create_c_vector(extra_x, extra_y, extra_z) );
01336 }
01337 else
01338 {
01339 c_vector<double, 3> extra_conductivities;
01340 GetExtracellularConductivities(extra_conductivities);
01341 extraConductivities.push_back(extra_conductivities);
01342 }
01343
01344 }
01345 }
01346
01347 std::string HeartConfig::GetOutputDirectory() const
01348 {
01349 CheckSimulationIsDefined("Simulation/OutputDirectory");
01350 CHECK_EXISTS(mpParameters->Simulation()->OutputDirectory().present(), "Simulation/OutputDirectory");
01351 return mpParameters->Simulation()->OutputDirectory().get();
01352 }
01353
01354 std::string HeartConfig::GetOutputFilenamePrefix() const
01355 {
01356 CheckSimulationIsDefined("Simulation/OutputFilenamePrefix");
01357 CHECK_EXISTS(mpParameters->Simulation()->OutputFilenamePrefix().present(), "Simulation/OutputFilenamePrefix");
01358 return mpParameters->Simulation()->OutputFilenamePrefix().get();
01359 }
01360
01361 bool HeartConfig::GetOutputVariablesProvided() const
01362 {
01363 CheckSimulationIsDefined("OutputVariables");
01364 return mpParameters->Simulation()->OutputVariables().present();
01365 }
01366
01367 void HeartConfig::GetOutputVariables(std::vector<std::string>& rOutputVariables) const
01368 {
01369 CHECK_EXISTS(GetOutputVariablesProvided(), "Simulation/OutputVariables");
01370 XSD_SEQUENCE_TYPE(cp::output_variables_type::Var)&
01371 output_variables = mpParameters->Simulation()->OutputVariables()->Var();
01372 rOutputVariables.clear();
01373
01374 for (XSD_ITERATOR_TYPE(cp::output_variables_type::Var) i = output_variables.begin();
01375 i != output_variables.end();
01376 ++i)
01377 {
01378 cp::var_type& r_var(*i);
01379
01380
01381 rOutputVariables.push_back(r_var.name());
01382 }
01383 }
01384
01385 bool HeartConfig::GetOutputUsingOriginalNodeOrdering()
01386 {
01387 CheckSimulationIsDefined("OutputUsingOriginalNodeOrdering");
01388 bool result = false;
01389 if (mpParameters->Simulation()->OutputUsingOriginalNodeOrdering().present())
01390 {
01391 result = (mpParameters->Simulation()->OutputUsingOriginalNodeOrdering().get() == cp::yesno_type::yes);
01392 }
01393 return result;
01394 }
01395
01396 bool HeartConfig::GetCheckpointSimulation() const
01397 {
01398 return IsSimulationDefined() && mpParameters->Simulation()->CheckpointSimulation().present();
01399 }
01400
01401 double HeartConfig::GetCheckpointTimestep() const
01402 {
01403 CHECK_EXISTS(GetCheckpointSimulation(), "Simulation/CheckpointSimulation");
01404 return mpParameters->Simulation()->CheckpointSimulation()->timestep();
01405 }
01406
01407 unsigned HeartConfig::GetMaxCheckpointsOnDisk() const
01408 {
01409 CHECK_EXISTS(GetCheckpointSimulation(), "Simulation/CheckpointSimulation");
01410 return mpParameters->Simulation()->CheckpointSimulation()->max_checkpoints_on_disk();
01411 }
01412
01413
01414 HeartFileFinder HeartConfig::GetArchivedSimulationDir() const
01415 {
01416 CheckResumeSimulationIsDefined("GetArchivedSimulationDir");
01417
01418 return HeartFileFinder(mpParameters->ResumeSimulation()->ArchiveDirectory());
01419 }
01420
01421
01422 void HeartConfig::GetIntracellularConductivities(c_vector<double, 3>& intraConductivities) const
01423 {
01424 CHECK_EXISTS(mpParameters->Physiological().IntracellularConductivities().present(), "Physiological/IntracellularConductivities");
01425 cp::conductivities_type intra_conductivities
01426 = mpParameters->Physiological().IntracellularConductivities().get();
01427 double intra_x_cond = intra_conductivities.longi();
01428 double intra_y_cond = intra_conductivities.trans();
01429 double intra_z_cond = intra_conductivities.normal();;
01430
01431 assert(intra_y_cond != DBL_MAX);
01432 assert(intra_z_cond != DBL_MAX);
01433
01434 intraConductivities[0] = intra_x_cond;
01435 intraConductivities[1] = intra_y_cond;
01436 intraConductivities[2] = intra_z_cond;
01437 }
01438
01439 void HeartConfig::GetIntracellularConductivities(c_vector<double, 2>& intraConductivities) const
01440 {
01441 CHECK_EXISTS(mpParameters->Physiological().IntracellularConductivities().present(), "Physiological/IntracellularConductivities");
01442 cp::conductivities_type intra_conductivities
01443 = mpParameters->Physiological().IntracellularConductivities().get();
01444 double intra_x_cond = intra_conductivities.longi();
01445 double intra_y_cond = intra_conductivities.trans();
01446
01447 assert(intra_y_cond != DBL_MAX);
01448
01449 intraConductivities[0] = intra_x_cond;
01450 intraConductivities[1] = intra_y_cond;
01451 }
01452
01453 void HeartConfig::GetIntracellularConductivities(c_vector<double, 1>& intraConductivities) const
01454 {
01455 CHECK_EXISTS(mpParameters->Physiological().IntracellularConductivities().present(), "Physiological/IntracellularConductivities");
01456 cp::conductivities_type intra_conductivities
01457 = mpParameters->Physiological().IntracellularConductivities().get();
01458 double intra_x_cond = intra_conductivities.longi();
01459
01460 intraConductivities[0] = intra_x_cond;
01461 }
01462
01463 void HeartConfig::GetExtracellularConductivities(c_vector<double, 3>& extraConductivities) const
01464 {
01465 CHECK_EXISTS(mpParameters->Physiological().ExtracellularConductivities().present(), "Physiological/ExtracellularConductivities");
01466 cp::conductivities_type extra_conductivities
01467 = mpParameters->Physiological().ExtracellularConductivities().get();
01468 double extra_x_cond = extra_conductivities.longi();
01469 double extra_y_cond = extra_conductivities.trans();
01470 double extra_z_cond = extra_conductivities.normal();;
01471
01472 assert(extra_y_cond != DBL_MAX);
01473 assert(extra_z_cond != DBL_MAX);
01474
01475 extraConductivities[0] = extra_x_cond;
01476 extraConductivities[1] = extra_y_cond;
01477 extraConductivities[2] = extra_z_cond;
01478 }
01479
01480 void HeartConfig::GetExtracellularConductivities(c_vector<double, 2>& extraConductivities) const
01481 {
01482 CHECK_EXISTS(mpParameters->Physiological().ExtracellularConductivities().present(), "Physiological/ExtracellularConductivities");
01483 cp::conductivities_type extra_conductivities
01484 = mpParameters->Physiological().ExtracellularConductivities().get();
01485 double extra_x_cond = extra_conductivities.longi();
01486 double extra_y_cond = extra_conductivities.trans();
01487
01488 assert(extra_y_cond != DBL_MAX);
01489
01490 extraConductivities[0] = extra_x_cond;
01491 extraConductivities[1] = extra_y_cond;
01492 }
01493
01494 void HeartConfig::GetExtracellularConductivities(c_vector<double, 1>& extraConductivities) const
01495 {
01496 CHECK_EXISTS(mpParameters->Physiological().ExtracellularConductivities().present(), "Physiological/ExtracellularConductivities");
01497 cp::conductivities_type extra_conductivities
01498 = mpParameters->Physiological().ExtracellularConductivities().get();
01499 double extra_x_cond = extra_conductivities.longi();
01500
01501 extraConductivities[0] = extra_x_cond;
01502 }
01503
01504 double HeartConfig::GetBathConductivity(unsigned bathRegion) const
01505 {
01506
01507
01508
01509
01510
01511
01512
01513
01514
01515 if (bathRegion == UINT_MAX)
01516 {
01517
01518 CHECK_EXISTS(mpParameters->Physiological().BathConductivity().present(), "Physiological/BathConductivity");
01519 return mpParameters->Physiological().BathConductivity().get();
01520 }
01521 else
01522 {
01523 assert(HeartRegionCode::IsRegionBath(bathRegion));
01524
01525 std::map<unsigned, double>::const_iterator map_entry = mBathConductivities.find(bathRegion);
01526
01527 if (map_entry != mBathConductivities.end())
01528 {
01529 return map_entry->second;
01530 }
01531 else
01532 {
01533
01534 CHECK_EXISTS(mpParameters->Physiological().BathConductivity().present(), "Physiological/BathConductivity");
01535 return mpParameters->Physiological().BathConductivity().get();
01536 }
01537 }
01538 }
01539 const std::set<unsigned>& HeartConfig::rGetTissueIdentifiers()
01540 {
01541 return mTissueIdentifiers;
01542 }
01543
01544 const std::set<unsigned>& HeartConfig::rGetBathIdentifiers()
01545 {
01546 return mBathIdentifiers;
01547 }
01548
01549 double HeartConfig::GetSurfaceAreaToVolumeRatio() const
01550 {
01551 CHECK_EXISTS(mpParameters->Physiological().SurfaceAreaToVolumeRatio().present(), "Physiological/SurfaceAreaToVolumeRatio");
01552 return mpParameters->Physiological().SurfaceAreaToVolumeRatio().get();
01553 }
01554
01555 double HeartConfig::GetCapacitance() const
01556 {
01557 CHECK_EXISTS(mpParameters->Physiological().Capacitance().present(), "Physiological/Capacitance");
01558 return mpParameters->Physiological().Capacitance().get();
01559 }
01560
01561 double HeartConfig::GetOdeTimeStep() const
01562 {
01563 CHECK_EXISTS(mpParameters->Numerical().TimeSteps().present(), "Numerical/TimeSteps");
01564 return mpParameters->Numerical().TimeSteps()->ode();
01565 }
01566
01567 double HeartConfig::GetPdeTimeStep() const
01568 {
01569 CHECK_EXISTS(mpParameters->Numerical().TimeSteps().present(), "Numerical/TimeSteps");
01570 return mpParameters->Numerical().TimeSteps()->pde();
01571 }
01572
01573 double HeartConfig::GetPrintingTimeStep() const
01574 {
01575 CHECK_EXISTS(mpParameters->Numerical().TimeSteps().present(), "Numerical/TimeSteps");
01576 return mpParameters->Numerical().TimeSteps()->printing();
01577 }
01578
01579 bool HeartConfig::GetUseAbsoluteTolerance() const
01580 {
01581 CHECK_EXISTS(mpParameters->Numerical().KSPTolerances().present(), "Numerical/KSPTolerances");
01582 return mpParameters->Numerical().KSPTolerances()->KSPAbsolute().present();
01583 }
01584
01585 double HeartConfig::GetAbsoluteTolerance() const
01586 {
01587 CHECK_EXISTS(mpParameters->Numerical().KSPTolerances().present(), "Numerical/KSPTolerances");
01588 if (!GetUseAbsoluteTolerance())
01589 {
01590 EXCEPTION("Absolute tolerance is not set in Chaste parameters");
01591 }
01592 return mpParameters->Numerical().KSPTolerances()->KSPAbsolute().get();
01593 }
01594
01595 bool HeartConfig::GetUseRelativeTolerance() const
01596 {
01597 CHECK_EXISTS(mpParameters->Numerical().KSPTolerances().present(), "Numerical/KSPTolerances");
01598 return mpParameters->Numerical().KSPTolerances()->KSPRelative().present();
01599 }
01600
01601 double HeartConfig::GetRelativeTolerance() const
01602 {
01603 CHECK_EXISTS(mpParameters->Numerical().KSPTolerances().present(), "Numerical/KSPTolerances");
01604 if (!GetUseRelativeTolerance())
01605 {
01606 EXCEPTION("Relative tolerance is not set in Chaste parameters");
01607 }
01608 return mpParameters->Numerical().KSPTolerances()->KSPRelative().get();
01609 }
01610
01611 const char* HeartConfig::GetKSPSolver() const
01612 {
01613 CHECK_EXISTS(mpParameters->Numerical().KSPSolver().present(), "Numerical/KSPSolver");
01614 switch (mpParameters->Numerical().KSPSolver().get())
01615 {
01616 case cp::ksp_solver_type::gmres :
01617 return "gmres";
01618 case cp::ksp_solver_type::cg :
01619 return "cg";
01620 case cp::ksp_solver_type::symmlq :
01621 return "symmlq";
01622 case cp::ksp_solver_type::chebychev :
01623 return "chebychev";
01624 }
01625 #define COVERAGE_IGNORE
01626 EXCEPTION("Unknown ksp solver");
01627 #undef COVERAGE_IGNORE
01628 }
01629
01630 const char* HeartConfig::GetKSPPreconditioner() const
01631 {
01632 CHECK_EXISTS(mpParameters->Numerical().KSPPreconditioner().present(), "Numerical/KSPPreconditioner");
01633 switch ( mpParameters->Numerical().KSPPreconditioner().get() )
01634 {
01635 case cp::ksp_preconditioner_type::jacobi :
01636 return "jacobi";
01637 case cp::ksp_preconditioner_type::bjacobi :
01638 return "bjacobi";
01639 case cp::ksp_preconditioner_type::hypre :
01640 return "hypre";
01641 case cp::ksp_preconditioner_type::ml :
01642 return "ml";
01643 case cp::ksp_preconditioner_type::spai :
01644 return "spai";
01645 case cp::ksp_preconditioner_type::blockdiagonal :
01646 return "blockdiagonal";
01647 case cp::ksp_preconditioner_type::ldufactorisation :
01648 return "ldufactorisation";
01649 case cp::ksp_preconditioner_type::twolevelsblockdiagonal :
01650 return "twolevelsblockdiagonal";
01651 case cp::ksp_preconditioner_type::none :
01652 return "none";
01653
01654 }
01655 #define COVERAGE_IGNORE
01656 EXCEPTION("Unknown ksp preconditioner");
01657 #undef COVERAGE_IGNORE
01658 }
01659
01660 DistributedTetrahedralMeshPartitionType::type HeartConfig::GetMeshPartitioning() const
01661 {
01662 CHECK_EXISTS(mpParameters->Numerical().MeshPartitioning().present(), "Numerical/MeshPartitioning");
01663 switch ( mpParameters->Numerical().MeshPartitioning().get() )
01664 {
01665 case cp::mesh_partitioning_type::dumb :
01666 return DistributedTetrahedralMeshPartitionType::DUMB;
01667 case cp::mesh_partitioning_type::metis :
01668 return DistributedTetrahedralMeshPartitionType::METIS_LIBRARY;
01669 case cp::mesh_partitioning_type::parmetis :
01670 return DistributedTetrahedralMeshPartitionType::PARMETIS_LIBRARY;
01671 case cp::mesh_partitioning_type::petsc :
01672 return DistributedTetrahedralMeshPartitionType::PETSC_MAT_PARTITION;
01673 }
01674 #define COVERAGE_IGNORE
01675 EXCEPTION("Unknown mesh partitioning type");
01676 #undef COVERAGE_IGNORE
01677 }
01678
01679 bool HeartConfig::IsAdaptivityParametersPresent() const
01680 {
01681 bool IsAdaptivityParametersPresent = mpParameters->Numerical().AdaptivityParameters().present();
01682 if (IsAdaptivityParametersPresent)
01683 {
01684 WARNING("Use of the Adaptivity library is deprecated");
01685 }
01686 return IsAdaptivityParametersPresent;
01687 }
01688
01689
01690
01691
01692
01693 bool HeartConfig::IsPostProcessingSectionPresent() const
01694 {
01695 return mpParameters->PostProcessing().present();
01696 }
01697
01698 void HeartConfig::EnsurePostProcessingSectionPresent()
01699 {
01700 ENSURE_SECTION_PRESENT(mpParameters->PostProcessing(), cp::postprocessing_type);
01701 }
01702
01703 bool HeartConfig::IsPostProcessingRequested() const
01704 {
01705 if (IsPostProcessingSectionPresent() == false)
01706 {
01707 return false;
01708 }
01709 else
01710 {
01711 return(IsApdMapsRequested() ||
01712 IsUpstrokeTimeMapsRequested() ||
01713 IsMaxUpstrokeVelocityMapRequested() ||
01714 IsConductionVelocityMapsRequested() ||
01715 IsAnyNodalTimeTraceRequested()||
01716 IsPseudoEcgCalculationRequested());
01717 }
01718 }
01719 bool HeartConfig::IsApdMapsRequested() const
01720 {
01721 bool result = false;
01722 if (IsPostProcessingSectionPresent())
01723 {
01724 XSD_SEQUENCE_TYPE(cp::postprocessing_type::ActionPotentialDurationMap)&
01725 apd_maps = mpParameters->PostProcessing()->ActionPotentialDurationMap();
01726 result = (apd_maps.begin() != apd_maps.end());
01727 }
01728 return result;
01729 }
01730
01731 void HeartConfig::GetApdMaps(std::vector<std::pair<double,double> >& apd_maps) const
01732 {
01733 CHECK_EXISTS(IsApdMapsRequested(), "PostProcessing/ActionPotentialDurationMap");
01734 apd_maps.clear();
01735
01736 XSD_SEQUENCE_TYPE(cp::postprocessing_type::ActionPotentialDurationMap)&
01737 apd_maps_sequence = mpParameters->PostProcessing()->ActionPotentialDurationMap();
01738
01739 for (XSD_ITERATOR_TYPE(cp::postprocessing_type::ActionPotentialDurationMap) i = apd_maps_sequence.begin();
01740 i != apd_maps_sequence.end();
01741 ++i)
01742 {
01743 std::pair<double,double> map(i->repolarisation_percentage(),i->threshold());
01744
01745 apd_maps.push_back(map);
01746 }
01747 }
01748
01749 bool HeartConfig::IsUpstrokeTimeMapsRequested() const
01750 {
01751 bool result = false;
01752 if (IsPostProcessingSectionPresent())
01753 {
01754 XSD_SEQUENCE_TYPE(cp::postprocessing_type::UpstrokeTimeMap)&
01755 upstroke_map = mpParameters->PostProcessing()->UpstrokeTimeMap();
01756 result = (upstroke_map.begin() != upstroke_map.end());
01757 }
01758 return result;
01759 }
01760 void HeartConfig::GetUpstrokeTimeMaps (std::vector<double>& upstroke_time_maps) const
01761 {
01762 CHECK_EXISTS(IsUpstrokeTimeMapsRequested(), "PostProcessing/UpstrokeTimeMap");
01763 assert(upstroke_time_maps.size() == 0);
01764
01765 XSD_SEQUENCE_TYPE(cp::postprocessing_type::UpstrokeTimeMap)&
01766 upstroke_maps_sequence = mpParameters->PostProcessing()->UpstrokeTimeMap();
01767
01768 for (XSD_ITERATOR_TYPE(cp::postprocessing_type::UpstrokeTimeMap) i = upstroke_maps_sequence.begin();
01769 i != upstroke_maps_sequence.end();
01770 ++i)
01771 {
01772 upstroke_time_maps.push_back(i->threshold());
01773 }
01774 }
01775
01776 bool HeartConfig::IsMaxUpstrokeVelocityMapRequested() const
01777 {
01778 bool result = false;
01779 if (IsPostProcessingSectionPresent())
01780 {
01781 XSD_SEQUENCE_TYPE(cp::postprocessing_type::MaxUpstrokeVelocityMap)&
01782 max_upstroke_velocity_map = mpParameters->PostProcessing()->MaxUpstrokeVelocityMap();
01783 result = (max_upstroke_velocity_map.begin() != max_upstroke_velocity_map.end());
01784 }
01785 return result;
01786 }
01787
01788 void HeartConfig::GetMaxUpstrokeVelocityMaps(std::vector<double>& upstroke_velocity_maps) const
01789 {
01790 CHECK_EXISTS(IsMaxUpstrokeVelocityMapRequested(), "PostProcessing/MaxUpstrokeVelocityMap");
01791 assert(upstroke_velocity_maps.size() == 0);
01792
01793 XSD_SEQUENCE_TYPE(cp::postprocessing_type::MaxUpstrokeVelocityMap)&
01794 max_upstroke_velocity_maps_sequence = mpParameters->PostProcessing()->MaxUpstrokeVelocityMap();
01795
01796 for (XSD_ITERATOR_TYPE(cp::postprocessing_type::MaxUpstrokeVelocityMap) i = max_upstroke_velocity_maps_sequence.begin();
01797 i != max_upstroke_velocity_maps_sequence.end();
01798 ++i)
01799 {
01800 upstroke_velocity_maps.push_back(i->threshold());
01801 }
01802 }
01803
01804 bool HeartConfig::IsConductionVelocityMapsRequested() const
01805 {
01806 bool result = false;
01807 if (IsPostProcessingSectionPresent())
01808 {
01809 XSD_SEQUENCE_TYPE(cp::postprocessing_type::ConductionVelocityMap)&
01810 cond_vel_maps = mpParameters->PostProcessing()->ConductionVelocityMap();
01811 result = (cond_vel_maps.begin() != cond_vel_maps.end());
01812 }
01813 return result;
01814 }
01815
01816 void HeartConfig::GetConductionVelocityMaps(std::vector<unsigned>& conduction_velocity_maps) const
01817 {
01818 CHECK_EXISTS(IsConductionVelocityMapsRequested(), "PostProcessing/ConductionVelocityMap");
01819 assert(conduction_velocity_maps.size() == 0);
01820
01821 XSD_SEQUENCE_TYPE(cp::postprocessing_type::ConductionVelocityMap)&
01822 cond_vel_maps_sequence = mpParameters->PostProcessing()->ConductionVelocityMap();
01823
01824 for (XSD_ITERATOR_TYPE(cp::postprocessing_type::ConductionVelocityMap) i = cond_vel_maps_sequence.begin();
01825 i != cond_vel_maps_sequence.end();
01826 ++i)
01827 {
01828 conduction_velocity_maps.push_back(i->origin_node());
01829 }
01830 }
01831
01832 bool HeartConfig::IsAnyNodalTimeTraceRequested() const
01833 {
01834 bool result = false;
01835 if (IsPostProcessingSectionPresent())
01836 {
01837 XSD_SEQUENCE_TYPE(cp::postprocessing_type::TimeTraceAtNode)&
01838 requested_nodes = mpParameters->PostProcessing()->TimeTraceAtNode();
01839 result = (requested_nodes.begin() != requested_nodes.end());
01840 }
01841 return result;
01842 }
01843
01844 void HeartConfig::GetNodalTimeTraceRequested(std::vector<unsigned>& rRequestedNodes) const
01845 {
01846 CHECK_EXISTS(IsAnyNodalTimeTraceRequested(), "PostProcessing/TimeTraceAtNode");
01847 assert(rRequestedNodes.size() == 0);
01848
01849 XSD_SEQUENCE_TYPE(cp::postprocessing_type::TimeTraceAtNode)&
01850 req_nodes = mpParameters->PostProcessing()->TimeTraceAtNode();
01851
01852 for (XSD_ITERATOR_TYPE(cp::postprocessing_type::TimeTraceAtNode) i = req_nodes.begin();
01853 i != req_nodes.end();
01854 ++i)
01855 {
01856 rRequestedNodes.push_back(i->node_number());
01857 }
01858 }
01859
01860
01861 bool HeartConfig::IsPseudoEcgCalculationRequested() const
01862 {
01863 bool result = false;
01864 if (IsPostProcessingSectionPresent())
01865 {
01866 XSD_SEQUENCE_TYPE(cp::postprocessing_type::PseudoEcgElectrodePosition)&
01867 electrodes = mpParameters->PostProcessing()->PseudoEcgElectrodePosition();
01868 result = (electrodes.begin() != electrodes.end());
01869 }
01870 return result;
01871 }
01872
01873 template<unsigned SPACE_DIM>
01874 void HeartConfig::GetPseudoEcgElectrodePositions(std::vector<ChastePoint<SPACE_DIM> >& rPseudoEcgElectrodePositions) const
01875 {
01876 rPseudoEcgElectrodePositions.clear();
01877 XSD_SEQUENCE_TYPE(cp::postprocessing_type::PseudoEcgElectrodePosition)&
01878 electrodes = mpParameters->PostProcessing()->PseudoEcgElectrodePosition();
01879 for (XSD_ITERATOR_TYPE(cp::postprocessing_type::PseudoEcgElectrodePosition) i = electrodes.begin();
01880 i != electrodes.end();
01881 ++i)
01882 {
01883 rPseudoEcgElectrodePositions.push_back(ChastePoint<SPACE_DIM>(i->x(), i->y(), i->z()));
01884 }
01885 }
01886
01887
01888
01889
01890
01891
01892 bool HeartConfig::IsOutputVisualizerPresent() const
01893 {
01894 CheckSimulationIsDefined("OutputVisualizer");
01895
01896 return mpParameters->Simulation()->OutputVisualizer().present();
01897 }
01898
01899 bool HeartConfig::GetVisualizeWithMeshalyzer() const
01900 {
01901 if (!IsOutputVisualizerPresent())
01902 {
01903 return true;
01904 }
01905 else
01906 {
01907 return mpParameters->Simulation()->OutputVisualizer()->meshalyzer() == cp::yesno_type::yes;
01908 }
01909 }
01910
01911 bool HeartConfig::GetVisualizeWithCmgui() const
01912 {
01913 if (!IsOutputVisualizerPresent())
01914 {
01915 return false;
01916 }
01917 else
01918 {
01919 return mpParameters->Simulation()->OutputVisualizer()->cmgui() == cp::yesno_type::yes;
01920 }
01921 }
01922
01923 bool HeartConfig::GetVisualizeWithParallelVtk() const
01924 {
01925 if (!IsOutputVisualizerPresent())
01926 {
01927 return false;
01928 }
01929 else
01930 {
01931 return mpParameters->Simulation()->OutputVisualizer()->parallel_vtk() == cp::yesno_type::yes;
01932 }
01933 }
01934
01935 bool HeartConfig::GetVisualizeWithVtk() const
01936 {
01937 if (!IsOutputVisualizerPresent())
01938 {
01939 return false;
01940 }
01941 else
01942 {
01943 return mpParameters->Simulation()->OutputVisualizer()->vtk() == cp::yesno_type::yes;
01944 }
01945 }
01946
01947 unsigned HeartConfig::GetVisualizerOutputPrecision()
01948 {
01949 if (!IsOutputVisualizerPresent())
01950 {
01951 return 0u;
01952 }
01953 else
01954 {
01955 return mpParameters->Simulation()->OutputVisualizer()->precision();
01956 }
01957 }
01958
01959
01960 bool HeartConfig::IsElectrodesPresent() const
01961 {
01962 return mpParameters->Simulation()->Electrodes().present();
01963 }
01964
01965
01966
01967
01968 void HeartConfig::SetSpaceDimension(unsigned spaceDimension)
01969 {
01970 mpParameters->Simulation()->SpaceDimension().set(spaceDimension);
01971 }
01972
01973 void HeartConfig::SetSimulationDuration(double simulationDuration)
01974 {
01975 XSD_CREATE_WITH_FIXED_ATTR1(cp::time_type, time, simulationDuration, "ms");
01976 mpParameters->Simulation()->SimulationDuration().set(time);
01977 }
01978
01979 void HeartConfig::SetDomain(const cp::domain_type& rDomain)
01980 {
01981 mpParameters->Simulation()->Domain().set(rDomain);
01982 }
01983
01984 void HeartConfig::SetDefaultIonicModel(const cp::ionic_models_available_type& rIonicModel)
01985 {
01986 cp::ionic_model_selection_type ionic_model;
01987 ionic_model.Hardcoded(rIonicModel);
01988 cp::ionic_models_type container(ionic_model);
01989 mpParameters->Simulation()->IonicModels().set(container);
01990 }
01991
01992 void HeartConfig::SetSlabDimensions(double x, double y, double z, double inter_node_space)
01993 {
01994 if ( ! mpParameters->Simulation()->Mesh().present())
01995 {
01996 XSD_CREATE_WITH_FIXED_ATTR(cp::mesh_type, mesh_to_load, "cm");
01997 mpParameters->Simulation()->Mesh().set(mesh_to_load);
01998 }
01999
02000 cp::slab_type slab_definition(x, y, z, inter_node_space);
02001 mpParameters->Simulation()->Mesh()->Slab().set(slab_definition);
02002 }
02003
02004 void HeartConfig::SetSheetDimensions(double x, double y, double inter_node_space)
02005 {
02006 if ( ! mpParameters->Simulation()->Mesh().present())
02007 {
02008 XSD_CREATE_WITH_FIXED_ATTR(cp::mesh_type, mesh_to_load, "cm");
02009 mpParameters->Simulation()->Mesh().set(mesh_to_load);
02010 }
02011
02012 cp::sheet_type sheet_definition(x, y, inter_node_space);
02013 mpParameters->Simulation()->Mesh()->Sheet().set(sheet_definition);
02014 }
02015
02016 void HeartConfig::SetFibreLength(double x, double inter_node_space)
02017 {
02018 if ( ! mpParameters->Simulation()->Mesh().present())
02019 {
02020 XSD_CREATE_WITH_FIXED_ATTR(cp::mesh_type, mesh_to_load, "cm");
02021 mpParameters->Simulation()->Mesh().set(mesh_to_load);
02022 }
02023
02024 cp::fibre_type fibre_definition(x, inter_node_space);
02025 mpParameters->Simulation()->Mesh()->Fibre().set(fibre_definition);
02026 }
02027
02028 void HeartConfig::SetMeshFileName(std::string meshPrefix, cp::media_type fibreDefinition)
02029 {
02030 if ( ! mpParameters->Simulation()->Mesh().present())
02031 {
02032 XSD_CREATE_WITH_FIXED_ATTR(cp::mesh_type, mesh_to_load, "cm");
02033 mpParameters->Simulation()->Mesh().set(mesh_to_load);
02034 }
02035
02036 XSD_NESTED_TYPE(cp::mesh_type::LoadMesh) mesh_prefix(meshPrefix, fibreDefinition);
02037 mpParameters->Simulation()->Mesh()->LoadMesh().set(mesh_prefix);
02038 }
02039
02040 void HeartConfig::SetIonicModelRegions(std::vector<ChasteCuboid<3> >& rDefinedRegions,
02041 std::vector<cp::ionic_model_selection_type>& rIonicModels) const
02042 {
02043 assert(rDefinedRegions.size() == rIonicModels.size());
02044
02045 assert(mpParameters->Simulation()->IonicModels().present());
02046 XSD_SEQUENCE_TYPE(cp::ionic_models_type::Region)&
02047 regions = mpParameters->Simulation()->IonicModels()->Region();
02048 regions.clear();
02049 for (unsigned region_index=0; region_index<rDefinedRegions.size(); region_index++)
02050 {
02051 cp::point_type point_a(rDefinedRegions[region_index].rGetLowerCorner()[0],
02052 rDefinedRegions[region_index].rGetLowerCorner()[1],
02053 rDefinedRegions[region_index].rGetLowerCorner()[2]);
02054
02055 cp::point_type point_b(rDefinedRegions[region_index].rGetUpperCorner()[0],
02056 rDefinedRegions[region_index].rGetUpperCorner()[1],
02057 rDefinedRegions[region_index].rGetUpperCorner()[2]);
02058
02059 XSD_CREATE_WITH_FIXED_ATTR(cp::location_type, locn, "cm");
02060 locn.Cuboid().set(cp::box_type(point_a, point_b));
02061
02062 cp::ionic_model_region_type region(rIonicModels[region_index], locn);
02063 regions.push_back(region);
02064 }
02065 }
02066
02067 void HeartConfig::SetConductivityHeterogeneities(std::vector<ChasteCuboid<3> >& conductivityAreas,
02068 std::vector< c_vector<double,3> >& intraConductivities,
02069 std::vector< c_vector<double,3> >& extraConductivities)
02070 {
02071 assert ( conductivityAreas.size() == intraConductivities.size() );
02072 assert ( intraConductivities.size() == extraConductivities.size());
02073
02074 XSD_ANON_SEQUENCE_TYPE(cp::physiological_type, ConductivityHeterogeneities, ConductivityHeterogeneity) heterogeneities_container;
02075
02076 for (unsigned region_index=0; region_index<conductivityAreas.size(); region_index++)
02077 {
02078 cp::point_type point_a(conductivityAreas[region_index].rGetLowerCorner()[0],
02079 conductivityAreas[region_index].rGetLowerCorner()[1],
02080 conductivityAreas[region_index].rGetLowerCorner()[2]);
02081
02082 cp::point_type point_b(conductivityAreas[region_index].rGetUpperCorner()[0],
02083 conductivityAreas[region_index].rGetUpperCorner()[1],
02084 conductivityAreas[region_index].rGetUpperCorner()[2]);
02085
02086 XSD_CREATE_WITH_FIXED_ATTR(cp::location_type, locn, "cm");
02087 locn.Cuboid().set(cp::box_type(point_a, point_b));
02088 cp::conductivity_heterogeneity_type ht(locn);
02089
02090 XSD_CREATE_WITH_FIXED_ATTR3(cp::conductivities_type, intra,
02091 intraConductivities[region_index][0],
02092 intraConductivities[region_index][1],
02093 intraConductivities[region_index][2],
02094 "mS/cm");
02095
02096 ht.IntracellularConductivities(intra);
02097
02098 XSD_CREATE_WITH_FIXED_ATTR3(cp::conductivities_type, extra,
02099 extraConductivities[region_index][0],
02100 extraConductivities[region_index][1],
02101 extraConductivities[region_index][2],
02102 "mS/cm");
02103
02104 ht.ExtracellularConductivities(extra);
02105
02106 heterogeneities_container.push_back(ht);
02107 }
02108
02109 XSD_ANON_TYPE(cp::physiological_type, ConductivityHeterogeneities) heterogeneities_object;
02110 heterogeneities_object.ConductivityHeterogeneity(heterogeneities_container);
02111
02112 mpParameters->Physiological().ConductivityHeterogeneities().set(heterogeneities_object);
02113 }
02114
02115 void HeartConfig::SetConductivityHeterogeneitiesEllipsoid(std::vector<ChasteEllipsoid<3> >& conductivityAreas,
02116 std::vector< c_vector<double,3> >& intraConductivities,
02117 std::vector< c_vector<double,3> >& extraConductivities)
02118 {
02119 assert ( conductivityAreas.size() == intraConductivities.size() );
02120 assert ( intraConductivities.size() == extraConductivities.size());
02121
02122 XSD_ANON_SEQUENCE_TYPE(cp::physiological_type, ConductivityHeterogeneities, ConductivityHeterogeneity) heterogeneities_container;
02123
02124 for (unsigned region_index=0; region_index<conductivityAreas.size(); region_index++)
02125 {
02126 cp::point_type centre(conductivityAreas[region_index].rGetCentre()[0],
02127 conductivityAreas[region_index].rGetCentre()[1],
02128 conductivityAreas[region_index].rGetCentre()[2]);
02129
02130 cp::point_type radii(conductivityAreas[region_index].rGetRadii()[0],
02131 conductivityAreas[region_index].rGetRadii()[1],
02132 conductivityAreas[region_index].rGetRadii()[2]);
02133
02134 XSD_CREATE_WITH_FIXED_ATTR(cp::location_type, locn, "cm");
02135 locn.Ellipsoid().set(cp::ellipsoid_type(centre, radii));
02136 cp::conductivity_heterogeneity_type ht(locn);
02137
02138 XSD_CREATE_WITH_FIXED_ATTR3(cp::conductivities_type, intra,
02139 intraConductivities[region_index][0],
02140 intraConductivities[region_index][1],
02141 intraConductivities[region_index][2],
02142 "mS/cm");
02143
02144 ht.IntracellularConductivities(intra);
02145
02146 XSD_CREATE_WITH_FIXED_ATTR3(cp::conductivities_type, extra,
02147 extraConductivities[region_index][0],
02148 extraConductivities[region_index][1],
02149 extraConductivities[region_index][2],
02150 "mS/cm");
02151
02152 ht.ExtracellularConductivities(extra);
02153
02154 heterogeneities_container.push_back(ht);
02155 }
02156
02157 XSD_ANON_TYPE(cp::physiological_type, ConductivityHeterogeneities) heterogeneities_object;
02158 heterogeneities_object.ConductivityHeterogeneity(heterogeneities_container);
02159
02160 mpParameters->Physiological().ConductivityHeterogeneities().set(heterogeneities_object);
02161 }
02162
02163 void HeartConfig::SetOutputDirectory(const std::string& rOutputDirectory)
02164 {
02165 mpParameters->Simulation()->OutputDirectory().set(rOutputDirectory);
02166 }
02167
02168 void HeartConfig::SetOutputFilenamePrefix(const std::string& rOutputFilenamePrefix)
02169 {
02170 mpParameters->Simulation()->OutputFilenamePrefix().set(rOutputFilenamePrefix);
02171 }
02172
02173 void HeartConfig::SetOutputVariables(const std::vector<std::string>& rOutputVariables)
02174 {
02175 if ( ! mpParameters->Simulation()->OutputVariables().present())
02176 {
02177 cp::output_variables_type variables_requested;
02178 mpParameters->Simulation()->OutputVariables().set(variables_requested);
02179 }
02180
02181 XSD_SEQUENCE_TYPE(cp::output_variables_type::Var)&
02182 var_type_sequence = mpParameters->Simulation()->OutputVariables()->Var();
02183
02184 var_type_sequence.clear();
02185
02186 for (unsigned i=0; i<rOutputVariables.size(); i++)
02187 {
02188 cp::var_type temp(rOutputVariables[i]);
02189 var_type_sequence.push_back(temp);
02190 }
02191 }
02192
02193 void HeartConfig::SetOutputUsingOriginalNodeOrdering(bool useOriginal)
02194 {
02195
02196 mpParameters->Simulation()->OutputUsingOriginalNodeOrdering().set(useOriginal? cp::yesno_type::yes : cp::yesno_type::no);
02197 }
02198
02199 void HeartConfig::SetCheckpointSimulation(bool saveSimulation, double checkpointTimestep, unsigned maxCheckpointsOnDisk)
02200 {
02201 if (saveSimulation)
02202 {
02203
02204 assert(checkpointTimestep!=-1.0 && maxCheckpointsOnDisk!=UINT_MAX);
02205
02206 XSD_CREATE_WITH_FIXED_ATTR2(cp::simulation_type::XSD_NESTED_TYPE(CheckpointSimulation),
02207 cs,
02208 checkpointTimestep,
02209 maxCheckpointsOnDisk,
02210 "ms");
02211 mpParameters->Simulation()->CheckpointSimulation().set(cs);
02212 }
02213 else
02214 {
02215 mpParameters->Simulation()->CheckpointSimulation().reset();
02216 }
02217
02218 CheckTimeSteps();
02219 }
02220
02221
02222
02223 void HeartConfig::SetIntracellularConductivities(const c_vector<double, 3>& intraConductivities)
02224 {
02225 XSD_CREATE_WITH_FIXED_ATTR3(cp::conductivities_type, intra,
02226 intraConductivities[0],
02227 intraConductivities[1],
02228 intraConductivities[2],
02229 "mS/cm");
02230
02231 mpParameters->Physiological().IntracellularConductivities().set(intra);
02232 }
02233
02234 void HeartConfig::SetIntracellularConductivities(const c_vector<double, 2>& intraConductivities)
02235 {
02236 XSD_CREATE_WITH_FIXED_ATTR3(cp::conductivities_type, intra,
02237 intraConductivities[0],
02238 intraConductivities[1],
02239 0.0, "mS/cm");
02240
02241 mpParameters->Physiological().IntracellularConductivities().set(intra);
02242 }
02243
02244 void HeartConfig::SetIntracellularConductivities(const c_vector<double, 1>& intraConductivities)
02245 {
02246 XSD_CREATE_WITH_FIXED_ATTR3(cp::conductivities_type, intra,
02247 intraConductivities[0],
02248 0.0, 0.0, "mS/cm");
02249
02250 mpParameters->Physiological().IntracellularConductivities().set(intra);
02251 }
02252
02253 void HeartConfig::SetExtracellularConductivities(const c_vector<double, 3>& extraConductivities)
02254 {
02255 XSD_CREATE_WITH_FIXED_ATTR3(cp::conductivities_type, extra,
02256 extraConductivities[0],
02257 extraConductivities[1],
02258 extraConductivities[2],
02259 "mS/cm");
02260
02261 mpParameters->Physiological().ExtracellularConductivities().set(extra);
02262 }
02263
02264 void HeartConfig::SetExtracellularConductivities(const c_vector<double, 2>& extraConductivities)
02265 {
02266 XSD_CREATE_WITH_FIXED_ATTR3(cp::conductivities_type, extra,
02267 extraConductivities[0],
02268 extraConductivities[1],
02269 0.0, "mS/cm");
02270
02271 mpParameters->Physiological().ExtracellularConductivities().set(extra);
02272 }
02273
02274 void HeartConfig::SetExtracellularConductivities(const c_vector<double, 1>& extraConductivities)
02275 {
02276 XSD_CREATE_WITH_FIXED_ATTR3(cp::conductivities_type, extra,
02277 extraConductivities[0],
02278 0.0, 0.0, "mS/cm");
02279
02280 mpParameters->Physiological().ExtracellularConductivities().set(extra);
02281 }
02282
02283 void HeartConfig::SetBathConductivity(double bathConductivity)
02284 {
02285 XSD_CREATE_WITH_FIXED_ATTR1(cp::conductivity_type, cond, bathConductivity, "mS/cm");
02286 mpParameters->Physiological().BathConductivity().set(cond);
02287 }
02288
02289 void HeartConfig::SetBathMultipleConductivities(std::map<unsigned, double> bathConductivities)
02290 {
02292 mBathConductivities = bathConductivities;
02293 }
02294
02295
02296
02297
02298
02299
02300
02301 void HeartConfig::SetTissueAndBathIdentifiers(const std::set<unsigned>& tissueIds, const std::set<unsigned>& bathIds)
02302 {
02303 if (tissueIds.empty() || bathIds.empty() )
02304 {
02305 EXCEPTION("Identifying set must be non-empty");
02306 }
02307 std::set<unsigned> shared_identifiers;
02308 std::set_intersection(tissueIds.begin(),
02309 tissueIds.end(),
02310 bathIds.begin(),
02311 bathIds.end(),
02312 std::inserter(shared_identifiers, shared_identifiers.begin()));
02313
02314 if (!shared_identifiers.empty())
02315 {
02316 EXCEPTION("Tissue identifiers and bath identifiers overlap");
02317 }
02318 mTissueIdentifiers=tissueIds;
02319 mBathIdentifiers=bathIds;
02320 }
02321
02322 void HeartConfig::SetSurfaceAreaToVolumeRatio(double ratio)
02323 {
02324 XSD_CREATE_WITH_FIXED_ATTR1(cp::inverse_length_type, ratio_object, ratio, "1/cm");
02325 mpParameters->Physiological().SurfaceAreaToVolumeRatio().set(ratio_object);
02326 }
02327
02328 void HeartConfig::SetCapacitance(double capacitance)
02329 {
02330 XSD_CREATE_WITH_FIXED_ATTR1(cp::capacitance_type, capacitance_object, capacitance, "uF/cm^2");
02331 mpParameters->Physiological().Capacitance().set(capacitance_object);
02332 }
02333
02334
02335
02336 void HeartConfig::SetOdePdeAndPrintingTimeSteps(double odeTimeStep, double pdeTimeStep, double printingTimeStep)
02337 {
02338 XSD_CREATE_WITH_FIXED_ATTR3(cp::time_steps_type, time_steps,
02339 odeTimeStep, pdeTimeStep, printingTimeStep, "ms");
02340 mpParameters->Numerical().TimeSteps().set(time_steps);
02341 CheckTimeSteps();
02342 }
02343
02344 void HeartConfig::SetOdeTimeStep(double odeTimeStep)
02345 {
02346 SetOdePdeAndPrintingTimeSteps(odeTimeStep, GetPdeTimeStep(), GetPrintingTimeStep());
02347 }
02348
02349 void HeartConfig::SetPdeTimeStep(double pdeTimeStep)
02350 {
02351 SetOdePdeAndPrintingTimeSteps(GetOdeTimeStep(), pdeTimeStep, GetPrintingTimeStep());
02352 }
02353
02354 void HeartConfig::SetPrintingTimeStep(double printingTimeStep)
02355 {
02356 SetOdePdeAndPrintingTimeSteps(GetOdeTimeStep(), GetPdeTimeStep(), printingTimeStep);
02357 }
02358
02359 void HeartConfig::CheckTimeSteps() const
02360 {
02361 if (GetOdeTimeStep() <= 0)
02362 {
02363 EXCEPTION("Ode time-step should be positive");
02364 }
02365 if (GetPdeTimeStep() <= 0)
02366 {
02367 EXCEPTION("Pde time-step should be positive");
02368 }
02369 if (GetPrintingTimeStep() <= 0.0)
02370 {
02371 EXCEPTION("Printing time-step should be positive");
02372 }
02373
02374 if (GetPdeTimeStep()>GetPrintingTimeStep())
02375 {
02376 EXCEPTION("Printing time-step should not be smaller than PDE time-step");
02377 }
02378
02379 if ( !Divides(GetPdeTimeStep(), GetPrintingTimeStep()) )
02380 {
02381 EXCEPTION("Printing time-step should be a multiple of PDE time step");
02382 }
02383
02384 if ( GetOdeTimeStep() > GetPdeTimeStep() )
02385 {
02386 EXCEPTION("Ode time-step should not be greater than PDE time-step");
02387 }
02388
02389 if (GetCheckpointSimulation())
02390 {
02391 if (GetCheckpointTimestep() <= 0.0)
02392 {
02393 EXCEPTION("Checkpoint time-step should be positive");
02394 }
02395
02396 if ( !Divides(GetPrintingTimeStep(), GetCheckpointTimestep()) )
02397 {
02398 EXCEPTION("Checkpoint time-step should be a multiple of printing time-step");
02399 }
02400 }
02401 }
02402
02403
02404 void HeartConfig::SetUseRelativeTolerance(double relativeTolerance)
02405 {
02406 ENSURE_SECTION_PRESENT(mpParameters->Numerical().KSPTolerances(), cp::ksp_tolerances_type);
02407
02408 mpParameters->Numerical().KSPTolerances()->KSPAbsolute().reset();
02409 mpParameters->Numerical().KSPTolerances()->KSPRelative().set(relativeTolerance);
02410 }
02411
02412 void HeartConfig::SetUseAbsoluteTolerance(double absoluteTolerance)
02413 {
02414 ENSURE_SECTION_PRESENT(mpParameters->Numerical().KSPTolerances(), cp::ksp_tolerances_type);
02415
02416 mpParameters->Numerical().KSPTolerances()->KSPRelative().reset();
02417 mpParameters->Numerical().KSPTolerances()->KSPAbsolute().set(absoluteTolerance);
02418 }
02419
02420 void HeartConfig::SetKSPSolver(const char* kspSolver, bool warnOfChange)
02421 {
02422 if (warnOfChange && strcmp(GetKSPSolver(), kspSolver) != 0)
02423 {
02424
02425 WARNING("Code has changed the KSP solver type from "<<GetKSPSolver()<<" to "<< kspSolver);
02426 }
02427
02428
02429 if ( strcmp(kspSolver, "gmres") == 0)
02430 {
02431 mpParameters->Numerical().KSPSolver().set(cp::ksp_solver_type::gmres);
02432 return;
02433 }
02434 if ( strcmp(kspSolver, "cg") == 0)
02435 {
02436 mpParameters->Numerical().KSPSolver().set(cp::ksp_solver_type::cg);
02437 return;
02438 }
02439 if ( strcmp(kspSolver, "symmlq") == 0)
02440 {
02441 mpParameters->Numerical().KSPSolver().set(cp::ksp_solver_type::symmlq);
02442 return;
02443 }
02444 if ( strcmp(kspSolver, "chebychev") == 0)
02445 {
02446 mpParameters->Numerical().KSPSolver().set(cp::ksp_solver_type::chebychev);
02447 return;
02448 }
02449
02450 EXCEPTION("Unknown solver type provided");
02451 }
02452
02453 void HeartConfig::SetKSPPreconditioner(const char* kspPreconditioner)
02454 {
02455
02456 if ( strcmp(kspPreconditioner, "jacobi") == 0)
02457 {
02458 mpParameters->Numerical().KSPPreconditioner().set(cp::ksp_preconditioner_type::jacobi);
02459 return;
02460 }
02461 if ( strcmp(kspPreconditioner, "bjacobi") == 0)
02462 {
02463 mpParameters->Numerical().KSPPreconditioner().set(cp::ksp_preconditioner_type::bjacobi);
02464 return;
02465 }
02466 if ( strcmp(kspPreconditioner, "hypre") == 0)
02467 {
02468 mpParameters->Numerical().KSPPreconditioner().set(cp::ksp_preconditioner_type::hypre);
02469 return;
02470 }
02471 if ( strcmp(kspPreconditioner, "ml") == 0)
02472 {
02473 mpParameters->Numerical().KSPPreconditioner().set(cp::ksp_preconditioner_type::ml);
02474 return;
02475 }
02476 if ( strcmp(kspPreconditioner, "spai") == 0)
02477 {
02478 mpParameters->Numerical().KSPPreconditioner().set(cp::ksp_preconditioner_type::spai);
02479 return;
02480 }
02481 if ( strcmp(kspPreconditioner, "twolevelsblockdiagonal") == 0)
02482 {
02483 mpParameters->Numerical().KSPPreconditioner().set(cp::ksp_preconditioner_type::twolevelsblockdiagonal);
02484 return;
02485 }
02486 if ( strcmp(kspPreconditioner, "blockdiagonal") == 0)
02487 {
02488 mpParameters->Numerical().KSPPreconditioner().set(cp::ksp_preconditioner_type::blockdiagonal);
02489 return;
02490 }
02491 if ( strcmp(kspPreconditioner, "ldufactorisation") == 0)
02492 {
02493 mpParameters->Numerical().KSPPreconditioner().set(cp::ksp_preconditioner_type::ldufactorisation);
02494 return;
02495 }
02496 if ( strcmp(kspPreconditioner, "none") == 0)
02497 {
02498 mpParameters->Numerical().KSPPreconditioner().set(cp::ksp_preconditioner_type::none);
02499 return;
02500 }
02501
02502 EXCEPTION("Unknown preconditioner type provided");
02503 }
02504
02505 void HeartConfig::SetMeshPartitioning(const char* meshPartioningMethod)
02506 {
02507
02508 if ( strcmp(meshPartioningMethod, "dumb") == 0)
02509 {
02510 mpParameters->Numerical().MeshPartitioning().set(cp::mesh_partitioning_type::dumb);
02511 return;
02512 }
02513 if ( strcmp(meshPartioningMethod, "metis") == 0)
02514 {
02515 mpParameters->Numerical().MeshPartitioning().set(cp::mesh_partitioning_type::metis);
02516 return;
02517 }
02518 if ( strcmp(meshPartioningMethod, "parmetis") == 0)
02519 {
02520 mpParameters->Numerical().MeshPartitioning().set(cp::mesh_partitioning_type::parmetis);
02521 return;
02522 }
02523 if ( strcmp(meshPartioningMethod, "petsc") == 0)
02524 {
02525 mpParameters->Numerical().MeshPartitioning().set(cp::mesh_partitioning_type::petsc);
02526 return;
02527 }
02528
02529 EXCEPTION("Unknown mesh partitioning method provided");
02530 }
02531
02532
02533 void HeartConfig::SetApdMaps(const std::vector<std::pair<double,double> >& apdMaps)
02534 {
02535 EnsurePostProcessingSectionPresent();
02536 XSD_SEQUENCE_TYPE(cp::postprocessing_type::ActionPotentialDurationMap)& apd_maps_sequence
02537 = mpParameters->PostProcessing()->ActionPotentialDurationMap();
02538
02539 apd_maps_sequence.clear();
02540
02541 for (unsigned i=0; i<apdMaps.size(); i++)
02542 {
02543 XSD_CREATE_WITH_FIXED_ATTR2(cp::apd_map_type, temp,
02544 apdMaps[i].first, apdMaps[i].second,
02545 "mV");
02546 apd_maps_sequence.push_back( temp);
02547 }
02548 }
02549
02550
02551 void HeartConfig::SetUpstrokeTimeMaps (std::vector<double>& upstrokeTimeMaps)
02552 {
02553 EnsurePostProcessingSectionPresent();
02554 XSD_SEQUENCE_TYPE(cp::postprocessing_type::UpstrokeTimeMap)& var_type_sequence
02555 = mpParameters->PostProcessing()->UpstrokeTimeMap();
02556
02557
02558 var_type_sequence.clear();
02559
02560 for (unsigned i=0; i<upstrokeTimeMaps.size(); i++)
02561 {
02562 XSD_CREATE_WITH_FIXED_ATTR1(cp::upstrokes_map_type, temp,
02563 upstrokeTimeMaps[i],
02564 "mV");
02565 var_type_sequence.push_back(temp);
02566 }
02567 }
02568
02569 void HeartConfig::SetMaxUpstrokeVelocityMaps (std::vector<double>& maxUpstrokeVelocityMaps)
02570 {
02571 EnsurePostProcessingSectionPresent();
02572 XSD_SEQUENCE_TYPE(cp::postprocessing_type::MaxUpstrokeVelocityMap)& max_upstroke_velocity_maps_sequence
02573 = mpParameters->PostProcessing()->MaxUpstrokeVelocityMap();
02574
02575
02576 max_upstroke_velocity_maps_sequence.clear();
02577
02578 for (unsigned i=0; i<maxUpstrokeVelocityMaps.size(); i++)
02579 {
02580 XSD_CREATE_WITH_FIXED_ATTR1(cp::max_upstrokes_velocity_map_type, temp,
02581 maxUpstrokeVelocityMaps[i],
02582 "mV");
02583
02584
02585 max_upstroke_velocity_maps_sequence.push_back(temp);
02586 }
02587
02588 }
02589
02590 void HeartConfig::SetConductionVelocityMaps (std::vector<unsigned>& conductionVelocityMaps)
02591 {
02592 EnsurePostProcessingSectionPresent();
02593 XSD_SEQUENCE_TYPE(cp::postprocessing_type::ConductionVelocityMap)& conduction_velocity_maps_sequence
02594 = mpParameters->PostProcessing()->ConductionVelocityMap();
02595
02596
02597 conduction_velocity_maps_sequence.clear();
02598
02599 for (unsigned i=0; i<conductionVelocityMaps.size(); i++)
02600 {
02601 cp::conduction_velocity_map_type temp(conductionVelocityMaps[i]);
02602 conduction_velocity_maps_sequence.push_back(temp);
02603 }
02604 }
02605
02606 void HeartConfig::SetRequestedNodalTimeTraces (std::vector<unsigned>& requestedNodes)
02607 {
02608 EnsurePostProcessingSectionPresent();
02609 XSD_SEQUENCE_TYPE(cp::postprocessing_type::TimeTraceAtNode)& requested_nodes_sequence
02610 = mpParameters->PostProcessing()->TimeTraceAtNode();
02611
02612
02613 requested_nodes_sequence.clear();
02614
02615 for (unsigned i=0; i<requestedNodes.size(); i++)
02616 {
02617 cp::node_number_type temp(requestedNodes[i]);
02618 requested_nodes_sequence.push_back(temp);
02619 }
02620 }
02621
02622 template<unsigned SPACE_DIM>
02623 void HeartConfig::SetPseudoEcgElectrodePositions(const std::vector<ChastePoint<SPACE_DIM> >& rPseudoEcgElectrodePositions)
02624 {
02625 EnsurePostProcessingSectionPresent();
02626 XSD_SEQUENCE_TYPE(cp::postprocessing_type::PseudoEcgElectrodePosition)& electrodes_sequence
02627 = mpParameters->PostProcessing()->PseudoEcgElectrodePosition();
02628
02629
02630 electrodes_sequence.clear();
02631
02632 for (unsigned i=0; i<rPseudoEcgElectrodePositions.size(); i++)
02633 {
02634 cp::point_type temp(rPseudoEcgElectrodePositions[i].GetWithDefault(0),
02635 rPseudoEcgElectrodePositions[i].GetWithDefault(1),
02636 rPseudoEcgElectrodePositions[i].GetWithDefault(2));
02637 electrodes_sequence.push_back(temp);
02638 }
02639 }
02640
02641
02642
02643
02644
02645
02646 void HeartConfig::EnsureOutputVisualizerExists()
02647 {
02648 ENSURE_SECTION_PRESENT(mpParameters->Simulation()->OutputVisualizer(), cp::output_visualizer_type);
02649 }
02650
02651 void HeartConfig::SetVisualizeWithMeshalyzer(bool useMeshalyzer)
02652 {
02653 EnsureOutputVisualizerExists();
02654
02655 mpParameters->Simulation()->OutputVisualizer()->meshalyzer(
02656 useMeshalyzer ? cp::yesno_type::yes : cp::yesno_type::no);
02657 }
02658
02659 void HeartConfig::SetVisualizeWithCmgui(bool useCmgui)
02660 {
02661 EnsureOutputVisualizerExists();
02662
02663 mpParameters->Simulation()->OutputVisualizer()->cmgui(
02664 useCmgui ? cp::yesno_type::yes : cp::yesno_type::no);
02665 }
02666
02667 void HeartConfig::SetVisualizeWithVtk(bool useVtk)
02668 {
02669 EnsureOutputVisualizerExists();
02670
02671 mpParameters->Simulation()->OutputVisualizer()->vtk(
02672 useVtk ? cp::yesno_type::yes : cp::yesno_type::no);
02673 }
02674
02675 void HeartConfig::SetVisualizeWithParallelVtk(bool useParallelVtk)
02676 {
02677 EnsureOutputVisualizerExists();
02678
02679 mpParameters->Simulation()->OutputVisualizer()->parallel_vtk(
02680 useParallelVtk ? cp::yesno_type::yes : cp::yesno_type::no);
02681 }
02682
02683 void HeartConfig::SetVisualizerOutputPrecision(unsigned numberOfDigits)
02684 {
02685 EnsureOutputVisualizerExists();
02686
02687 mpParameters->Simulation()->OutputVisualizer()->precision(numberOfDigits);
02688 }
02689
02690
02691 void HeartConfig::SetElectrodeParameters(bool groundSecondElectrode,
02692 unsigned index, double magnitude,
02693 double startTime, double duration )
02694 {
02695 assert(index < 3);
02696
02697 cp::axis_type axis = cp::axis_type::x;
02698 if (index==1)
02699 {
02700 axis = cp::axis_type::y;
02701 }
02702 else if (index==2)
02703 {
02704 axis = cp::axis_type::z;
02705 }
02706
02707 XSD_CREATE_WITH_FIXED_ATTR1(cp::surface_stimulus_strength_type, strength, magnitude, "uA/cm^2");
02708 XSD_CREATE_WITH_FIXED_ATTR1(cp::time_type, start_time, startTime, "ms");
02709 XSD_CREATE_WITH_FIXED_ATTR1(cp::time_type, duration_time, duration, "ms");
02710
02711 if (!IsElectrodesPresent())
02712 {
02713 cp::electrodes_type element( groundSecondElectrode ? cp::yesno_type::yes : cp::yesno_type::no,
02714 axis,
02715 strength,
02716 start_time,
02717 duration_time );
02718 mpParameters->Simulation()->Electrodes().set(element);
02719 }
02720 else
02721 {
02722 mpParameters->Simulation()->Electrodes()->GroundSecondElectrode(groundSecondElectrode ? cp::yesno_type::yes : cp::yesno_type::no);
02723 mpParameters->Simulation()->Electrodes()->PerpendicularToAxis(axis);
02724 mpParameters->Simulation()->Electrodes()->Strength(strength);
02725 mpParameters->Simulation()->Electrodes()->StartTime(start_time);
02726 mpParameters->Simulation()->Electrodes()->Duration(duration_time);
02727 }
02728 }
02729
02730 void HeartConfig::GetElectrodeParameters(bool& rGroundSecondElectrode,
02731 unsigned& rIndex, double& rMagnitude,
02732 double& rStartTime, double& rDuration )
02733 {
02734 if (!IsElectrodesPresent())
02735 {
02736 EXCEPTION("Attempted to get electrodes that have not been defined.");
02737 }
02738 else
02739 {
02740 rGroundSecondElectrode = (mpParameters->Simulation()->Electrodes()->GroundSecondElectrode()==cp::yesno_type::yes);
02741
02742 cp::axis_type axis = mpParameters->Simulation()->Electrodes()->PerpendicularToAxis();
02743 if (axis==cp::axis_type::x)
02744 {
02745 rIndex = 0;
02746 }
02747 else if (axis==cp::axis_type::y)
02748 {
02749 rIndex = 1;
02750 }
02751 else
02752 {
02753 rIndex = 2;
02754 }
02755
02756 rMagnitude = mpParameters->Simulation()->Electrodes()->Strength();
02757 rStartTime = mpParameters->Simulation()->Electrodes()->StartTime();
02758 rDuration = mpParameters->Simulation()->Electrodes()->Duration();
02759 }
02760
02761 }
02762
02763 bool HeartConfig::GetUseStateVariableInterpolation() const
02764 {
02765
02766 bool result = false;
02767 if (mpParameters->Numerical().UseStateVariableInterpolation().present())
02768 {
02769 result = mpParameters->Numerical().UseStateVariableInterpolation().get() == cp::yesno_type::yes;
02770 }
02771 return result;
02772 }
02773
02774 void HeartConfig::SetUseStateVariableInterpolation(bool useStateVariableInterpolation)
02775 {
02776 if (useStateVariableInterpolation)
02777 {
02778 mpParameters->Numerical().UseStateVariableInterpolation().set(cp::yesno_type::yes);
02779 }
02780 else
02781 {
02782 mpParameters->Numerical().UseStateVariableInterpolation().set(cp::yesno_type::no);
02783 }
02784 }
02785
02786
02787
02788 bool HeartConfig::HasDrugDose() const
02789 {
02790 return mpParameters->Physiological().ApplyDrug().present();
02791 }
02792
02793 double HeartConfig::GetDrugDose() const
02794 {
02795 CHECK_EXISTS(HasDrugDose(), "Physiological/ApplyDrug");
02796 return mpParameters->Physiological().ApplyDrug()->concentration();
02797 }
02798
02799 void HeartConfig::SetDrugDose(double drugDose)
02800 {
02801 if (!mpParameters->Physiological().ApplyDrug().present())
02802 {
02803 cp::apply_drug_type drug(drugDose);
02804 mpParameters->Physiological().ApplyDrug().set(drug);
02805 }
02806 else
02807 {
02808 mpParameters->Physiological().ApplyDrug()->concentration(drugDose);
02809 }
02810 }
02811
02812 std::map<std::string, std::pair<double, double> > HeartConfig::GetIc50Values()
02813 {
02814 CHECK_EXISTS(HasDrugDose(), "Physiological/ApplyDrug");
02815 std::map<std::string, std::pair<double, double> > ic50s;
02816
02817 XSD_SEQUENCE_TYPE(cp::apply_drug_type::IC50)&
02818 ic50_seq = mpParameters->Physiological().ApplyDrug()->IC50();
02819
02820 for (XSD_ITERATOR_TYPE(cp::apply_drug_type::IC50) i = ic50_seq.begin();
02821 i != ic50_seq.end();
02822 ++i)
02823 {
02824 std::pair<double, double> ic50_hill(*i, i->hill());
02825 std::string current = i->current();
02826 ic50s[current] = ic50_hill;
02827 }
02828
02829 return ic50s;
02830 }
02831
02832 void HeartConfig::SetIc50Value(const std::string& rCurrentName, double ic50, double hill)
02833 {
02834 if (!mpParameters->Physiological().ApplyDrug().present())
02835 {
02836 SetDrugDose(0.0);
02837 }
02838 XSD_SEQUENCE_TYPE(cp::apply_drug_type::IC50)& ic50_seq = mpParameters->Physiological().ApplyDrug()->IC50();
02839 if (ic50_seq.empty())
02840 {
02841
02842 ic50_seq.clear();
02843 }
02844 bool entry_exists = false;
02845 cp::ic50_type ic50_elt(ic50, rCurrentName);
02846 ic50_elt.hill(hill);
02847 for (XSD_ITERATOR_TYPE(cp::apply_drug_type::IC50) i = ic50_seq.begin();
02848 i != ic50_seq.end();
02849 ++i)
02850 {
02851 if (i->current() == rCurrentName)
02852 {
02853 entry_exists = true;
02854 *i = ic50_elt;
02855 break;
02856 }
02857 }
02858 if (!entry_exists)
02859 {
02860 ic50_seq.push_back(ic50_elt);
02861 }
02862 }
02863
02864
02865
02866 void HeartConfig::SetUseMassLumping(bool useMassLumping)
02867 {
02868 mUseMassLumping = useMassLumping;
02869 }
02870
02871 bool HeartConfig::GetUseMassLumping()
02872 {
02873 return mUseMassLumping;
02874 }
02875
02876 void HeartConfig::SetUseMassLumpingForPrecond(bool useMassLumping)
02877 {
02878 mUseMassLumpingForPrecond = useMassLumping;
02879 }
02880
02881 bool HeartConfig::GetUseMassLumpingForPrecond()
02882 {
02883 return mUseMassLumpingForPrecond;
02884 }
02885
02886 void HeartConfig::SetUseReactionDiffusionOperatorSplitting(bool useOperatorSplitting)
02887 {
02888 mUseReactionDiffusionOperatorSplitting = useOperatorSplitting;
02889 }
02890
02891 bool HeartConfig::GetUseReactionDiffusionOperatorSplitting()
02892 {
02893 return mUseReactionDiffusionOperatorSplitting;
02894 }
02895
02896 void HeartConfig::SetUseFixedNumberIterationsLinearSolver(bool useFixedNumberIterations, unsigned evaluateNumItsEveryNSolves)
02897 {
02898 mUseFixedNumberIterations = useFixedNumberIterations;
02899 mEvaluateNumItsEveryNSolves = evaluateNumItsEveryNSolves;
02900 }
02901
02902 bool HeartConfig::GetUseFixedNumberIterationsLinearSolver()
02903 {
02904 return mUseFixedNumberIterations;
02905 }
02906
02907 unsigned HeartConfig::GetEvaluateNumItsEveryNSolves()
02908 {
02909 return mEvaluateNumItsEveryNSolves;
02910 }
02911
02912
02913
02914
02915
02916 bool HeartConfig::HasPurkinje()
02917 {
02918 CheckSimulationIsDefined("Purkinje");
02919 return mpParameters->Simulation()->Purkinje().present();
02920 }
02921
02922 double HeartConfig::GetPurkinjeCapacitance()
02923 {
02924 CHECK_EXISTS(mpParameters->Physiological().Purkinje().present(), "Physiological/Purkinje");
02925 CHECK_EXISTS(mpParameters->Physiological().Purkinje()->Capacitance().present(),
02926 "Physiological/Purkinje/Capacitance");
02927 return mpParameters->Physiological().Purkinje()->Capacitance().get();
02928 }
02929
02930 void HeartConfig::SetPurkinjeCapacitance(double capacitance)
02931 {
02932 ENSURE_SECTION_PRESENT(mpParameters->Physiological().Purkinje(), cp::purkinje_physiological_type);
02933 XSD_CREATE_WITH_FIXED_ATTR1(cp::capacitance_type, purk_Cm, capacitance, "uF/cm^2");
02934 mpParameters->Physiological().Purkinje()->Capacitance().set(purk_Cm);
02935 }
02936
02937
02938 double HeartConfig::GetPurkinjeSurfaceAreaToVolumeRatio()
02939 {
02940 CHECK_EXISTS(mpParameters->Physiological().Purkinje().present(), "Physiological/Purkinje");
02941 CHECK_EXISTS(mpParameters->Physiological().Purkinje()->SurfaceAreaToVolumeRatio().present(),
02942 "Physiological/Purkinje/SurfaceAreaToVolumeRatio");
02943 return mpParameters->Physiological().Purkinje()->SurfaceAreaToVolumeRatio().get();
02944 }
02945
02946 void HeartConfig::SetPurkinjeSurfaceAreaToVolumeRatio(double ratio)
02947 {
02948 ENSURE_SECTION_PRESENT(mpParameters->Physiological().Purkinje(), cp::purkinje_physiological_type);
02949 XSD_CREATE_WITH_FIXED_ATTR1(cp::inverse_length_type, purk_Am, ratio, "1/cm");
02950 mpParameters->Physiological().Purkinje()->SurfaceAreaToVolumeRatio().set(purk_Am);
02951 }
02952
02953 double HeartConfig::GetPurkinjeConductivity()
02954 {
02955 CHECK_EXISTS(mpParameters->Physiological().Purkinje().present(), "Physiological/Purkinje");
02956 CHECK_EXISTS(mpParameters->Physiological().Purkinje()->Conductivity().present(),
02957 "Physiological/Purkinje/Conductivity");
02958 return mpParameters->Physiological().Purkinje()->Conductivity().get();
02959 }
02960
02961 void HeartConfig::SetPurkinjeConductivity(double conductivity)
02962 {
02963 ENSURE_SECTION_PRESENT(mpParameters->Physiological().Purkinje(), cp::purkinje_physiological_type);
02964 XSD_CREATE_WITH_FIXED_ATTR1(cp::conductivity_type, purkinje_conductivity, conductivity, "mS/cm");
02965 mpParameters->Physiological().Purkinje()->Conductivity().set(purkinje_conductivity);
02966 }
02967
02968
02969
02970
02971
02972
02973
02974
02975
02976
02977 void XmlTransforms::TransformArchiveDirectory(xercesc::DOMDocument* pDocument,
02978 xercesc::DOMElement* pRootElement)
02979 {
02980 using namespace xercesc;
02981 std::vector<xercesc::DOMElement*> elts = XmlTools::FindElements(
02982 pRootElement,
02983 "ResumeSimulation/ArchiveDirectory");
02984 if (elts.size() > 0)
02985 {
02986
02987 DOMElement* p_dir_elt = elts[0];
02988 p_dir_elt->setAttribute(X("relative_to"), X("chaste_test_output"));
02989 }
02990 }
02991
02992 void XmlTransforms::TransformIonicModelDefinitions(xercesc::DOMDocument* pDocument,
02993 xercesc::DOMElement* pRootElement)
02994 {
02995
02996 std::vector<xercesc::DOMElement*> p_elt_list = XmlTools::FindElements(
02997 pRootElement,
02998 "Simulation/IonicModels/Default");
02999 if (p_elt_list.size() > 0)
03000 {
03001 assert(p_elt_list.size() == 1);
03002 XmlTools::WrapContentInElement(pDocument, p_elt_list[0], X("Hardcoded"));
03003
03004 p_elt_list = XmlTools::FindElements(pRootElement, "Simulation/IonicModels/Region/IonicModel");
03005 for (unsigned i=0; i<p_elt_list.size(); i++)
03006 {
03007 XmlTools::WrapContentInElement(pDocument, p_elt_list[i], X("Hardcoded"));
03008 }
03009 }
03010 }
03011
03012 void XmlTransforms::CheckForIluPreconditioner(xercesc::DOMDocument* pDocument,
03013 xercesc::DOMElement* pRootElement)
03014 {
03015 std::vector<xercesc::DOMElement*> p_elt_list = XmlTools::FindElements(
03016 pRootElement,
03017 "Numerical/KSPPreconditioner");
03018 if (p_elt_list.size() > 0)
03019 {
03020 assert(p_elt_list.size() == 1);
03021 std::string text_value = X2C(p_elt_list[0]->getTextContent());
03022 if (text_value == "ilu")
03023 {
03024 EXCEPTION("PETSc does not have a parallel implementation of ilu, so we no longer allow it as an option. Use bjacobi instead.");
03025 }
03026 }
03027 }
03028
03029 void XmlTransforms::MoveConductivityHeterogeneities(xercesc::DOMDocument* pDocument,
03030 xercesc::DOMElement* pRootElement)
03031 {
03032 std::vector<xercesc::DOMElement*> p_elt_list = XmlTools::FindElements(
03033 pRootElement,
03034 "Simulation/ConductivityHeterogeneities");
03035 if (p_elt_list.size() > 0)
03036 {
03037 assert(p_elt_list.size() == 1);
03038 xercesc::DOMNode* p_parent = p_elt_list[0]->getParentNode();
03039 xercesc::DOMNode* p_child = p_parent->removeChild(p_elt_list[0]);
03040 std::vector<xercesc::DOMElement*> p_phys_list = XmlTools::FindElements(pRootElement, "Physiological");
03041 assert(p_phys_list.size() == 1);
03042 p_phys_list[0]->appendChild(p_child);
03043 }
03044 }
03045
03047
03049 #define COVERAGE_IGNORE //These methods are covered above with DIM=1,2,3 but the instantiations may fail spuriously
03050
03054 template void HeartConfig::GetIonicModelRegions<3u>(std::vector<boost::shared_ptr<AbstractChasteRegion<3u> > >& , std::vector<cp::ionic_model_selection_type>&) const;
03055 template void HeartConfig::GetStimuli<3u>(std::vector<boost::shared_ptr<AbstractStimulusFunction> >& , std::vector<boost::shared_ptr<AbstractChasteRegion<3u> > >& ) const;
03056 template void HeartConfig::GetCellHeterogeneities<3u>(std::vector<boost::shared_ptr<AbstractChasteRegion<3u> > >& ,std::vector<double>& ,std::vector<double>& ,std::vector<double>& ,std::vector<std::map<std::string, double> >*) ;
03057 template void HeartConfig::GetConductivityHeterogeneities<3u>(std::vector<boost::shared_ptr<AbstractChasteRegion<3u> > >& ,std::vector< c_vector<double,3> >& ,std::vector< c_vector<double,3> >& ) const;
03058
03059 template void HeartConfig::GetIonicModelRegions<2u>(std::vector<boost::shared_ptr<AbstractChasteRegion<2u> > >& , std::vector<cp::ionic_model_selection_type>&) const;
03060 template void HeartConfig::GetStimuli<2u>(std::vector<boost::shared_ptr<AbstractStimulusFunction> >& , std::vector<boost::shared_ptr<AbstractChasteRegion<2u> > >& ) const;
03061 template void HeartConfig::GetCellHeterogeneities<2u>(std::vector<boost::shared_ptr<AbstractChasteRegion<2u> > >& ,std::vector<double>& ,std::vector<double>& ,std::vector<double>& ,std::vector<std::map<std::string, double> >*) ;
03062 template void HeartConfig::GetConductivityHeterogeneities<2u>(std::vector<boost::shared_ptr<AbstractChasteRegion<2u> > >& ,std::vector< c_vector<double,3> >& ,std::vector< c_vector<double,3> >& ) const;
03063
03064 template void HeartConfig::GetIonicModelRegions<1u>(std::vector<boost::shared_ptr<AbstractChasteRegion<1u> > >& , std::vector<cp::ionic_model_selection_type>&) const;
03065 template void HeartConfig::GetStimuli<1u>(std::vector<boost::shared_ptr<AbstractStimulusFunction> >& , std::vector<boost::shared_ptr<AbstractChasteRegion<1u> > >& ) const;
03066 template void HeartConfig::GetCellHeterogeneities<1u>(std::vector<boost::shared_ptr<AbstractChasteRegion<1u> > >& ,std::vector<double>& ,std::vector<double>& ,std::vector<double>& ,std::vector<std::map<std::string, double> >*);
03067 template void HeartConfig::GetConductivityHeterogeneities<1u>(std::vector<boost::shared_ptr<AbstractChasteRegion<1u> > >& ,std::vector< c_vector<double,3> >& ,std::vector< c_vector<double,3> >& ) const;
03068
03069 template void HeartConfig::GetPseudoEcgElectrodePositions(std::vector<ChastePoint<1u> >& rPseudoEcgElectrodePositions) const;
03070 template void HeartConfig::GetPseudoEcgElectrodePositions(std::vector<ChastePoint<2u> >& rPseudoEcgElectrodePositions) const;
03071 template void HeartConfig::GetPseudoEcgElectrodePositions(std::vector<ChastePoint<3u> >& rPseudoEcgElectrodePositions) const;
03072
03073 template void HeartConfig::SetPseudoEcgElectrodePositions(const std::vector<ChastePoint<1u> >& rPseudoEcgElectrodePositions);
03074 template void HeartConfig::SetPseudoEcgElectrodePositions(const std::vector<ChastePoint<2u> >& rPseudoEcgElectrodePositions);
03075 template void HeartConfig::SetPseudoEcgElectrodePositions(const std::vector<ChastePoint<3u> >& rPseudoEcgElectrodePositions);
03080 #undef COVERAGE_IGNORE //These methods are covered above with DIM=1,2,3 but the instantiations may fail spuriously
03081
03082
03083
03084 #include "SerializationExportWrapperForCpp.hpp"
03085 CHASTE_CLASS_EXPORT(HeartConfig)