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 #include "CheckpointArchiveTypesIfNeeded.hpp"
00031
00032 #include "UblasCustomFunctions.hpp"
00033
00034 #include "HeartConfig.hpp"
00035 #include "OutputFileHandler.hpp"
00036 #include "Exception.hpp"
00037 #include "ChastePoint.hpp"
00038 #include "Version.hpp"
00039 #include "AbstractChasteRegion.hpp"
00040 #include "HeartFileFinder.hpp"
00041 #include "Warnings.hpp"
00042
00043 #include "HeartRegionCodes.hpp"
00044
00045 #include "SimpleStimulus.hpp"
00046 #include "RegularStimulus.hpp"
00047
00048 #include <string>
00049 #include <istream>
00050 #include <fstream>
00051 #include <cassert>
00052
00053 #include <xercesc/util/PlatformUtils.hpp>
00054 #include <xercesc/util/QName.hpp>
00055 #include <xercesc/util/XMLUniDefs.hpp>
00056 #include <xercesc/framework/Wrapper4InputSource.hpp>
00057 #include <xercesc/validators/common/Grammar.hpp>
00058 #include <xercesc/dom/DOMNamedNodeMap.hpp>
00059 #include <xercesc/dom/DOMXPathEvaluator.hpp>
00060 #include <xercesc/dom/DOMXPathResult.hpp>
00061
00062 #include <xsd/cxx/xml/string.hxx>
00063 #include <xsd/cxx/xml/dom/auto-ptr.hxx>
00064 #include <xsd/cxx/xml/sax/std-input-source.hxx>
00065 #include <xsd/cxx/xml/dom/bits/error-handler-proxy.hxx>
00066 #include <xsd/cxx/tree/exceptions.hxx>
00067 #include <xsd/cxx/tree/error-handler.hxx>
00068
00069
00070 using namespace xsd::cxx::tree;
00071
00072
00073
00074 #if (XSD_INT_VERSION >= 3000000L)
00075 #define XSD_SEQUENCE_TYPE(base) base##_sequence
00076 #define XSD_ITERATOR_TYPE(base) base##_iterator
00077 #define XSD_NESTED_TYPE(t) t##_type
00078 #define XSD_ANON_TYPE(t1, t2) \
00079 t1::t2##_type
00080 #else
00081 #define XSD_SEQUENCE_TYPE(base) base::container
00082 #define XSD_ITERATOR_TYPE(base) base::iterator
00083 #define XSD_NESTED_TYPE(t) t::type
00084 #define XSD_ANON_TYPE(t1, t2) \
00085 t1::t2::_xsd_##t2##_::t2
00086 #endif
00087
00088
00089 #define XSD_ANON_SEQUENCE_TYPE(t1, t2, t3) \
00090 XSD_SEQUENCE_TYPE(XSD_ANON_TYPE(t1, t2)::t3)
00091 #define XSD_ANON_ITERATOR_TYPE(t1, t2, t3) \
00092 XSD_ITERATOR_TYPE(XSD_ANON_TYPE(t1, t2)::t3)
00093
00094
00095 #if (XSD_INT_VERSION >= 3020000L)
00096 #define XSD_CREATE_WITH_FIXED_ATTR(type, name, attr) \
00097 type name
00098 #define XSD_CREATE_WITH_FIXED_ATTR1(type, name, arg1, attr) \
00099 type name(arg1)
00100 #define XSD_CREATE_WITH_FIXED_ATTR2(type, name, arg1, arg2, attr) \
00101 type name(arg1, arg2)
00102 #define XSD_CREATE_WITH_FIXED_ATTR3(type, name, arg1, arg2, arg3, attr) \
00103 type name(arg1, arg2, arg3)
00104 #else
00105 #define XSD_CREATE_WITH_FIXED_ATTR(type, name, attr) \
00106 type name(attr)
00107 #define XSD_CREATE_WITH_FIXED_ATTR1(type, name, arg1, attr) \
00108 type name(arg1, attr)
00109 #define XSD_CREATE_WITH_FIXED_ATTR2(type, name, arg1, arg2, attr) \
00110 type name(arg1, arg2, attr)
00111 #define XSD_CREATE_WITH_FIXED_ATTR3(type, name, arg1, arg2, arg3, attr) \
00112 type name(arg1, arg2, arg3, attr)
00113 #endif
00114
00119 #define X(str) xsd::cxx::xml::string(str).c_str()
00120
00124 #define ENSURE_SECTION_PRESENT(location, type) \
00125 if (!location.present()) \
00126 { \
00127 type empty_item; \
00128 location.set(empty_item); \
00129 }
00130
00131
00135 class XmlTools
00136 {
00137 public:
00151 static xsd::cxx::xml::dom::auto_ptr<xercesc::DOMDocument> ReadFileToDomDocument(
00152 const std::string& rFileName,
00153 ::xml_schema::error_handler& rErrorHandler,
00154 const ::xml_schema::properties& rProps);
00155
00163 static void PrintNode(const std::string& rMsg, xercesc::DOMNode* pNode, bool showChildren=false);
00164
00175 static xercesc::DOMElement* SetNamespace(xercesc::DOMDocument* pDocument,
00176 xercesc::DOMElement* pElement,
00177 const std::string& rNamespace);
00178
00189 static xercesc::DOMElement* SetNamespace(xercesc::DOMDocument* pDocument,
00190 xercesc::DOMElement* pElement,
00191 const XMLCh* pNamespace);
00192
00204 static void WrapContentInElement(xercesc::DOMDocument* pDocument,
00205 xercesc::DOMElement* pElement,
00206 const XMLCh* pNewElementLocalName);
00207
00214 static std::vector<xercesc::DOMElement*> FindElements(xercesc::DOMElement* pContextElement,
00215 const std::string& rPath);
00216
00226 static void FindElements(xercesc::DOMElement* pContextElement,
00227 const std::vector<std::string>& rNames,
00228 std::vector<xercesc::DOMElement*>& rResults,
00229 unsigned depth=0);
00230 };
00231
00236 class XmlTransforms
00237 {
00238 public:
00246 static void TransformIonicModelDefinitions(xercesc::DOMDocument* pDocument,
00247 xercesc::DOMElement* pRootElement);
00248
00257 static void TransformArchiveDirectory(xercesc::DOMDocument* pDocument,
00258 xercesc::DOMElement* pRootElement);
00259
00267 static void CheckForIluPreconditioner(xercesc::DOMDocument* pDocument,
00268 xercesc::DOMElement* pRootElement);
00269 };
00270
00271
00272
00273
00274 #include "HeartConfigDefaults.hpp"
00275
00276
00277
00278
00279 std::auto_ptr<HeartConfig> HeartConfig::mpInstance;
00280
00281
00282
00283
00284
00285 HeartConfig* HeartConfig::Instance()
00286 {
00287 if (mpInstance.get() == NULL)
00288 {
00289 mpInstance.reset(new HeartConfig);
00290 }
00291 return mpInstance.get();
00292 }
00293
00294 HeartConfig::HeartConfig()
00295 : mUseMassLumping(false),
00296 mUseMassLumpingForPrecond(false),
00297 mUseFixedNumberIterations(false),
00298 mEvaluateNumItsEveryNSolves(UINT_MAX)
00299 {
00300 assert(mpInstance.get() == NULL);
00301 mUseFixedSchemaLocation = true;
00302 SetDefaultSchemaLocations();
00303
00304 mpDefaultParameters = CreateDefaultParameters();
00305 mpUserParameters = mpDefaultParameters;
00306
00307
00308
00309 mEpiFraction = -1.0;
00310 mEndoFraction = -1.0;
00311 mMidFraction = -1.0;
00312 mUserAskedForCellularTransmuralHeterogeneities=false;
00313
00314
00315
00316 mIndexMid = UINT_MAX-3u;
00317 mIndexEpi = UINT_MAX-3u;
00318 mIndexEndo = UINT_MAX-3u;
00319
00320 mUseReactionDiffusionOperatorSplitting = false;
00321
00323 mTissueIdentifiers.insert(0);
00324 mBathIdentifiers.insert(1);
00325 }
00326
00327 HeartConfig::~HeartConfig()
00328 {
00329 }
00330
00331 void HeartConfig::SetDefaultsFile(const std::string& rFileName)
00332 {
00333 bool same_target = (mpUserParameters == mpDefaultParameters);
00334
00335 mpDefaultParameters = ReadFile(rFileName);
00336
00337 if (same_target)
00338 {
00339 mpUserParameters = mpDefaultParameters;
00340 }
00341 CheckTimeSteps();
00342 }
00343
00344 void HeartConfig::Write(bool useArchiveLocationInfo, std::string subfolderName)
00345 {
00346
00347 std::string output_dirname;
00348 if (useArchiveLocationInfo)
00349 {
00350 output_dirname = ArchiveLocationInfo::GetArchiveDirectory();
00351 }
00352 else
00353 {
00354 OutputFileHandler handler(GetOutputDirectory() + "/" + subfolderName, false);
00355 output_dirname = handler.GetOutputDirectoryFullPath();
00356 }
00357 if (!PetscTools::AmMaster())
00358 {
00359
00360 return;
00361 }
00362 out_stream p_defaults_file( new std::ofstream( (output_dirname+"ChasteDefaults.xml").c_str() ) );
00363 out_stream p_parameters_file( new std::ofstream( (output_dirname+"ChasteParameters.xml").c_str() ) );
00364
00365 if (!p_defaults_file->is_open() || !p_parameters_file->is_open())
00366 {
00367 EXCEPTION("Could not open XML file in HeartConfig");
00368 }
00369
00370
00371
00372 ::xml_schema::namespace_infomap map;
00373
00374 map[""].schema = "ChasteParameters_1_1.xsd";
00375
00376 map["cp20"].name = "https://chaste.comlab.ox.ac.uk/nss/parameters/2_0";
00377 map["cp20"].schema = "ChasteParameters_2_0.xsd";
00378 map["cp21"].name = "https://chaste.comlab.ox.ac.uk/nss/parameters/2_1";
00379 map["cp21"].schema = "ChasteParameters_2_1.xsd";
00380
00381
00382 map["cp"].name = "https://chaste.comlab.ox.ac.uk/nss/parameters/2_2";
00383 map["cp"].schema = "ChasteParameters_2_2.xsd";
00384
00385 cp::ChasteParameters(*p_parameters_file, *mpUserParameters, map);
00386 cp::ChasteParameters(*p_defaults_file, *mpDefaultParameters, map);
00387
00388
00389 if (useArchiveLocationInfo)
00390 {
00391 CopySchema(output_dirname);
00392 }
00393 }
00394
00395 void HeartConfig::CopySchema(const std::string& rToDirectory)
00396 {
00397 if (PetscTools::AmMaster())
00398 {
00399 std::string schema_name("ChasteParameters_2_2.xsd");
00400 FileFinder schema_location("heart/src/io/" + schema_name, RelativeTo::ChasteSourceRoot);
00401 if (!schema_location.Exists())
00402 {
00403
00404 schema_location.SetPath(schema_name, RelativeTo::CWD);
00405 if (!schema_location.Exists())
00406 {
00407
00408 std::string message("Unable to locate schema file " + schema_name +
00409 ". You will need to ensure it is available when resuming from the checkpoint.");
00410 WARN_ONCE_ONLY(message);
00411 }
00412 }
00413 if (schema_location.Exists())
00414 {
00415
00416 MPIABORTIFNON0(system,("cp " + schema_location.GetAbsolutePath() + " " + rToDirectory).c_str());
00417 }
00418 }
00419 }
00420
00421 void HeartConfig::SetDefaultSchemaLocations()
00422 {
00423 mSchemaLocations.clear();
00424
00425 std::string root_dir = std::string(ChasteBuildInfo::GetRootDir()) + "/heart/src/io/";
00426
00427 mSchemaLocations[""] = root_dir + "ChasteParameters_1_1.xsd";
00428
00429 mSchemaLocations["https://chaste.comlab.ox.ac.uk/nss/parameters/2_0"] = root_dir + "ChasteParameters_2_0.xsd";
00430 mSchemaLocations["https://chaste.comlab.ox.ac.uk/nss/parameters/2_1"] = root_dir + "ChasteParameters_2_1.xsd";
00431 mSchemaLocations["https://chaste.comlab.ox.ac.uk/nss/parameters/2_2"] = root_dir + "ChasteParameters_2_2.xsd";
00432 }
00433
00434 unsigned HeartConfig::GetVersionFromNamespace(const std::string& rNamespaceUri)
00435 {
00436 unsigned version_major = 0;
00437 unsigned version_minor = 0;
00438 if (rNamespaceUri == "")
00439 {
00440 version_major = 1;
00441 version_minor = 1;
00442 }
00443 else
00444 {
00445 std::string uri_base("https://chaste.comlab.ox.ac.uk/nss/parameters/");
00446 if (rNamespaceUri.substr(0, uri_base.length()) == uri_base)
00447 {
00448 std::istringstream version_string(rNamespaceUri.substr(uri_base.length()));
00449 version_string >> version_major;
00450 version_string.ignore(1);
00451 version_string >> version_minor;
00452 if (version_string.fail())
00453 {
00454 version_major = 0;
00455 version_minor = 0;
00456 }
00457 }
00458 }
00459
00460 unsigned version = version_major * 1000 + version_minor;
00461 if (version == 0)
00462 {
00463 EXCEPTION(rNamespaceUri + " is not a recognised Chaste parameters namespace.");
00464 }
00465 return version;
00466 }
00467
00468 void HeartConfig::SetFixedSchemaLocations(const SchemaLocationsMap& rSchemaLocations)
00469 {
00470 mSchemaLocations = rSchemaLocations;
00471 SetUseFixedSchemaLocation(true);
00472 }
00473
00474 void HeartConfig::SetUseFixedSchemaLocation(bool useFixedSchemaLocation)
00475 {
00476 mUseFixedSchemaLocation = useFixedSchemaLocation;
00477 }
00478
00479 std::string HeartConfig::EscapeSpaces(const std::string& rPath)
00480 {
00481 std::string escaped_path;
00482 for (std::string::const_iterator it = rPath.begin(); it != rPath.end(); ++it)
00483 {
00484 if (*it == ' ')
00485 {
00486 escaped_path += "%20";
00487 }
00488 else
00489 {
00490 escaped_path += *it;
00491 }
00492 }
00493 return escaped_path;
00494 }
00495
00496 boost::shared_ptr<cp::chaste_parameters_type> HeartConfig::ReadFile(const std::string& rFileName)
00497 {
00498
00499 ::xml_schema::properties props;
00500 if (mUseFixedSchemaLocation)
00501 {
00502 for (SchemaLocationsMap::iterator it = mSchemaLocations.begin();
00503 it != mSchemaLocations.end();
00504 ++it)
00505 {
00506 if (it->first == "")
00507 {
00508 props.no_namespace_schema_location(EscapeSpaces(it->second));
00509 }
00510 else
00511 {
00512 props.schema_location(it->first, EscapeSpaces(it->second));
00513 }
00514 }
00515 }
00516
00517
00518
00519 try
00520 {
00521
00522 ::xsd::cxx::xml::auto_initializer init_fini(true, true);
00523
00524 ::xsd::cxx::tree::error_handler<char> error_handler;
00525
00526 xsd::cxx::xml::dom::auto_ptr<xercesc::DOMDocument> p_doc = XmlTools::ReadFileToDomDocument(rFileName, error_handler, props);
00527
00528 error_handler.throw_if_failed< ::xsd::cxx::tree::parsing< char > >();
00529
00530 xercesc::DOMElement* p_root_elt = p_doc->getDocumentElement();
00531 std::string namespace_uri(xsd::cxx::xml::transcode<char>(p_root_elt->getNamespaceURI()));
00532 switch (GetVersionFromNamespace(namespace_uri))
00533 {
00534 case 1001:
00535 XmlTransforms::TransformIonicModelDefinitions(p_doc.get(), p_root_elt);
00536 case 2000:
00537 XmlTransforms::TransformArchiveDirectory(p_doc.get(), p_root_elt);
00538 XmlTransforms::CheckForIluPreconditioner(p_doc.get(), p_root_elt);
00539 case 2001:
00540 XmlTools::SetNamespace(p_doc.get(), p_root_elt, "https://chaste.comlab.ox.ac.uk/nss/parameters/2_2");
00541 default:
00542 break;
00543 }
00544
00545 std::auto_ptr<cp::chaste_parameters_type> p_params(cp::ChasteParameters(*p_doc, ::xml_schema::flags::dont_initialize, props));
00546
00547 p_doc.reset();
00548
00549 return boost::shared_ptr<cp::chaste_parameters_type>(p_params);
00550 }
00551 catch (const xml_schema::parsing& e)
00552 {
00553
00554 mpUserParameters.reset();
00555 mpDefaultParameters.reset();
00556
00557 #if (XSD_INT_VERSION >= 3000000L)
00558 const xml_schema::diagnostics& diags = e.diagnostics();
00559 const xml_schema::error& first_error = diags[0];
00560 #else
00561 const xml_schema::errors& errors = e.errors();
00562 const xml_schema::error& first_error = errors[0];
00563 #endif
00564 if (first_error.line() == 0u)
00565 {
00566 std::cerr << first_error << std::endl;
00567 EXCEPTION("Missing file parsing configuration file: " + rFileName);
00568 }
00569 else
00570 {
00571 std::cerr << e << std::endl;
00572 EXCEPTION("XML parsing error in configuration file: " + rFileName);
00573 }
00574 }
00575 catch (const xml_schema::exception& e)
00576 {
00577 std::cerr << e << std::endl;
00578
00579 mpUserParameters.reset();
00580 mpDefaultParameters.reset();
00581 EXCEPTION("XML parsing error in configuration file: " + rFileName);
00582 }
00583 }
00584
00585 void HeartConfig::SetParametersFile(const std::string& rFileName)
00586 {
00587 mpUserParameters = ReadFile(rFileName);
00588
00589 CheckTimeSteps();
00590 }
00591
00592
00593 void HeartConfig::UpdateParametersFromResumeSimulation(boost::shared_ptr<cp::chaste_parameters_type> pResumeParameters)
00594 {
00595
00596 if ( (pResumeParameters->ResumeSimulation()->SpaceDimension() != HeartConfig::Instance()->GetSpaceDimension())
00597 ||(pResumeParameters->ResumeSimulation()->Domain() != HeartConfig::Instance()->GetDomain()))
00598 {
00599 EXCEPTION("Problem type and space dimension should match when restarting a simulation.");
00600 }
00601
00602
00603 HeartConfig::Instance()->SetSimulationDuration(pResumeParameters->ResumeSimulation()->SimulationDuration());
00604
00605
00606 if (pResumeParameters->ResumeSimulation()->Stimuli().present())
00607 {
00608 mpUserParameters->Simulation()->Stimuli().set(pResumeParameters->ResumeSimulation()->Stimuli().get());
00609 }
00610
00611
00612
00613 if (pResumeParameters->ResumeSimulation()->CellHeterogeneities().present())
00614 {
00615 if (!mpUserParameters->Simulation()->CellHeterogeneities().present())
00616 {
00617
00618 mpUserParameters->Simulation()->CellHeterogeneities().set(pResumeParameters->ResumeSimulation()->CellHeterogeneities().get());
00619 }
00620 else
00621 {
00622
00623 XSD_SEQUENCE_TYPE(cp::cell_heterogeneities_type::CellHeterogeneity)&
00624 new_seq = pResumeParameters->ResumeSimulation()->CellHeterogeneities()->CellHeterogeneity();
00625 XSD_SEQUENCE_TYPE(cp::cell_heterogeneities_type::CellHeterogeneity)&
00626 orig_seq = mpUserParameters->Simulation()->CellHeterogeneities()->CellHeterogeneity();
00627 for (XSD_ITERATOR_TYPE(cp::cell_heterogeneities_type::CellHeterogeneity) i = new_seq.begin();
00628 i != new_seq.end();
00629 ++i)
00630 {
00631 orig_seq.push_back(*i);
00632 }
00633 }
00634 }
00635
00636
00637 if (pResumeParameters->ResumeSimulation()->CheckpointSimulation().present())
00638 {
00639 HeartConfig::Instance()->SetCheckpointSimulation(true,
00640 pResumeParameters->ResumeSimulation()->CheckpointSimulation()->timestep(),
00641 pResumeParameters->ResumeSimulation()->CheckpointSimulation()->max_checkpoints_on_disk());
00642 }
00643
00644
00645 HeartConfig::Instance()->SetVisualizeWithParallelVtk(pResumeParameters->ResumeSimulation()->OutputVisualizer().parallel_vtk() == cp::yesno_type::yes);
00646 HeartConfig::Instance()->SetVisualizeWithVtk(pResumeParameters->ResumeSimulation()->OutputVisualizer().vtk() == cp::yesno_type::yes);
00647 HeartConfig::Instance()->SetVisualizeWithCmgui(pResumeParameters->ResumeSimulation()->OutputVisualizer().cmgui() == cp::yesno_type::yes);
00648 HeartConfig::Instance()->SetVisualizeWithMeshalyzer(pResumeParameters->ResumeSimulation()->OutputVisualizer().meshalyzer() == cp::yesno_type::yes);
00649
00650
00651 {
00652 cp::numerical_type& r_resume = pResumeParameters->Numerical();
00653 cp::numerical_type& r_user = mpUserParameters->Numerical();
00654 if (r_resume.TimeSteps().present())
00655 {
00656 r_user.TimeSteps().set(r_resume.TimeSteps().get());
00657 }
00658 if (r_resume.KSPTolerances().present())
00659 {
00660 r_user.KSPTolerances().set(r_resume.KSPTolerances().get());
00661 }
00662 if (r_resume.KSPSolver().present())
00663 {
00664 r_user.KSPSolver().set(r_resume.KSPSolver().get());
00665 }
00666 if (r_resume.KSPPreconditioner().present())
00667 {
00668 r_user.KSPPreconditioner().set(r_resume.KSPPreconditioner().get());
00669 }
00670 if (r_resume.AdaptivityParameters().present())
00671 {
00672 r_user.AdaptivityParameters().set(r_resume.AdaptivityParameters().get());
00673 }
00674 }
00675
00676
00677 if (pResumeParameters->PostProcessing().present())
00678 {
00679 EnsurePostProcessingSectionPresent();
00680 cp::postprocessing_type& r_resume = pResumeParameters->PostProcessing().get();
00681 cp::postprocessing_type& r_user = mpUserParameters->PostProcessing().get();
00682 if (!r_resume.ActionPotentialDurationMap().empty())
00683 {
00684 r_user.ActionPotentialDurationMap() = r_resume.ActionPotentialDurationMap();
00685 }
00686 if (!r_resume.UpstrokeTimeMap().empty())
00687 {
00688 r_user.UpstrokeTimeMap() = r_resume.UpstrokeTimeMap();
00689 }
00690 if (!r_resume.MaxUpstrokeVelocityMap().empty())
00691 {
00692 r_user.MaxUpstrokeVelocityMap() = r_resume.MaxUpstrokeVelocityMap();
00693 }
00694 if (!r_resume.ConductionVelocityMap().empty())
00695 {
00696 r_user.ConductionVelocityMap() = r_resume.ConductionVelocityMap();
00697 }
00698 }
00699 }
00700
00701
00702 void HeartConfig::Reset()
00703 {
00704
00705 mpInstance.reset();
00706
00707 mpInstance.reset(new HeartConfig);
00708 }
00709
00710 bool HeartConfig::IsSimulationDefined() const
00711 {
00712 return mpUserParameters->Simulation().present();
00713 }
00714
00715 bool HeartConfig::IsSimulationResumed() const
00716 {
00717 return mpUserParameters->ResumeSimulation().present();
00718 }
00719
00720
00721 template<class TYPE>
00722 TYPE* HeartConfig::DecideLocation(TYPE* ptr1, TYPE* ptr2, const std::string& nameParameter) const
00723 {
00724 if (ptr1->present())
00725 {
00726 return ptr1;
00727 }
00728 if (ptr2->present())
00729 {
00730 return ptr2;
00731 }
00732
00733 EXCEPTION("No " + nameParameter + " provided (neither default nor user defined)");
00734 }
00735
00736 void HeartConfig::CheckSimulationIsDefined(std::string callingMethod) const
00737 {
00738 if (IsSimulationResumed())
00739 {
00740 EXCEPTION(callingMethod + " information is not available in a resumed simulation.");
00741 }
00742 }
00743
00744 void HeartConfig::CheckResumeSimulationIsDefined(std::string callingMethod) const
00745 {
00746 if (IsSimulationDefined())
00747 {
00748 EXCEPTION(callingMethod + " information is not available in a standard (non-resumed) simulation.");
00749 }
00750 }
00751
00752 unsigned HeartConfig::GetSpaceDimension() const
00753 {
00754 if (IsSimulationDefined())
00755 {
00756 return DecideLocation( & mpUserParameters->Simulation().get().SpaceDimension(),
00757 & mpDefaultParameters->Simulation().get().SpaceDimension(),
00758 "SpaceDimension")->get();
00759 }
00760 else
00761 {
00762 return mpUserParameters->ResumeSimulation().get().SpaceDimension();
00763 }
00764 }
00765
00766 double HeartConfig::GetSimulationDuration() const
00767 {
00768 if (IsSimulationDefined())
00769 {
00770 return DecideLocation( & mpUserParameters->Simulation().get().SimulationDuration(),
00771 & mpDefaultParameters->Simulation().get().SimulationDuration(),
00772 "Simulation/SimulationDuration")->get();
00773 }
00774 else
00775 {
00776 return mpUserParameters->ResumeSimulation().get().SimulationDuration();
00777 }
00778 }
00779
00780 cp::domain_type HeartConfig::GetDomain() const
00781 {
00782 if (IsSimulationDefined())
00783 {
00784 return DecideLocation( & mpUserParameters->Simulation().get().Domain(),
00785 & mpDefaultParameters->Simulation().get().Domain(),
00786 "Domain")->get();
00787 }
00788 else
00789 {
00790 return mpUserParameters->ResumeSimulation().get().Domain();
00791 }
00792 }
00793
00794 cp::ionic_model_selection_type HeartConfig::GetDefaultIonicModel() const
00795 {
00796 CheckSimulationIsDefined("DefaultIonicModel");
00797
00798 return DecideLocation( & mpUserParameters->Simulation().get().IonicModels(),
00799 & mpDefaultParameters->Simulation().get().IonicModels(),
00800 "IonicModel")->get().Default();
00801 }
00802
00803 template<unsigned DIM>
00804 void HeartConfig::GetIonicModelRegions(std::vector<boost::shared_ptr<AbstractChasteRegion<DIM> > >& definedRegions,
00805 std::vector<cp::ionic_model_selection_type>& ionicModels) const
00806 {
00807 CheckSimulationIsDefined("IonicModelRegions");
00808 definedRegions.clear();
00809 ionicModels.clear();
00810
00811 XSD_SEQUENCE_TYPE(cp::ionic_models_type::Region)&
00812 regions = DecideLocation( & mpUserParameters->Simulation().get().IonicModels(),
00813 & mpDefaultParameters->Simulation().get().IonicModels(),
00814 "IonicModel")->get().Region();
00815
00816 for (XSD_ITERATOR_TYPE(cp::ionic_models_type::Region) i = regions.begin();
00817 i != regions.end();
00818 ++i)
00819 {
00820 cp::ionic_model_region_type ionic_model_region(*i);
00821
00822 if (ionic_model_region.Location().Cuboid().present() || ionic_model_region.Location().Ellipsoid().present())
00823 {
00824 if (ionic_model_region.Location().Cuboid().present())
00825 {
00826 cp::point_type point_a = ionic_model_region.Location().Cuboid()->LowerCoordinates();
00827 cp::point_type point_b = ionic_model_region.Location().Cuboid()->UpperCoordinates();
00828
00829 switch (DIM)
00830 {
00831 case 1:
00832 {
00833 ChastePoint<DIM> chaste_point_a ( point_a.x() );
00834 ChastePoint<DIM> chaste_point_b ( point_b.x() );
00835 definedRegions.push_back(boost::shared_ptr<AbstractChasteRegion<DIM> >(new ChasteCuboid<DIM>( chaste_point_a, chaste_point_b )));
00836 break;
00837 }
00838 case 2:
00839 {
00840 ChastePoint<DIM> chaste_point_a ( point_a.x(), point_a.y() );
00841 ChastePoint<DIM> chaste_point_b ( point_b.x(), point_b.y() );
00842 definedRegions.push_back(boost::shared_ptr<AbstractChasteRegion<DIM> >(new ChasteCuboid<DIM>( chaste_point_a, chaste_point_b )));
00843 break;
00844 }
00845 case 3:
00846 {
00847 ChastePoint<DIM> chaste_point_a ( point_a.x(), point_a.y(), point_a.z() );
00848 ChastePoint<DIM> chaste_point_b ( point_b.x(), point_b.y(), point_b.z() );
00849 definedRegions.push_back(boost::shared_ptr<AbstractChasteRegion<DIM> >(new ChasteCuboid<DIM>( chaste_point_a, chaste_point_b )) );
00850 break;
00851 }
00852 default:
00853 NEVER_REACHED;
00854 break;
00855 }
00856 }
00857 else if (ionic_model_region.Location().Ellipsoid().present())
00858 {
00859 cp::point_type centre = ionic_model_region.Location().Ellipsoid()->Centre();
00860 cp::point_type radii = ionic_model_region.Location().Ellipsoid()->Radii();
00861 switch (DIM)
00862 {
00863 case 1:
00864 {
00865 ChastePoint<DIM> chaste_point_a ( centre.x() );
00866 ChastePoint<DIM> chaste_point_b ( radii.x() );
00867 definedRegions.push_back(boost::shared_ptr<AbstractChasteRegion<DIM> >(new ChasteEllipsoid<DIM> ( chaste_point_a, chaste_point_b )) );
00868 break;
00869 }
00870 case 2:
00871 {
00872 ChastePoint<DIM> chaste_point_a ( centre.x(), centre.y() );
00873 ChastePoint<DIM> chaste_point_b ( radii.x(), radii.y() );
00874 definedRegions.push_back(boost::shared_ptr<AbstractChasteRegion<DIM> >(new ChasteEllipsoid<DIM> ( chaste_point_a, chaste_point_b )) );
00875 break;
00876 }
00877 case 3:
00878 {
00879 ChastePoint<DIM> chaste_point_a ( centre.x(), centre.y(), centre.z() );
00880 ChastePoint<DIM> chaste_point_b ( radii.x(), radii.y(), radii.z() );
00881 definedRegions.push_back(boost::shared_ptr<AbstractChasteRegion<DIM> >(new ChasteEllipsoid<DIM> ( chaste_point_a, chaste_point_b )) );
00882 break;
00883 }
00884 default:
00885 {
00886 NEVER_REACHED;
00887 break;
00888 }
00889 }
00890 }
00891 else
00892 {
00893 NEVER_REACHED;
00894 }
00895
00896 ionicModels.push_back(ionic_model_region.IonicModel());
00897 }
00898 else if(ionic_model_region.Location().EpiLayer().present() || ionic_model_region.Location().MidLayer().present() || ionic_model_region.Location().EndoLayer().present() )
00899 {
00901 EXCEPTION("Definition of transmural layers is not yet supported for defining different ionic models, please use cuboids instead");
00902 }
00903 else
00904 {
00905 EXCEPTION("Invalid region type for ionic model definition");
00906 }
00907 }
00908 }
00909
00910
00911 bool HeartConfig::IsMeshProvided() const
00912 {
00913 CheckSimulationIsDefined("Mesh");
00914
00915 try
00916 {
00917 DecideLocation( & mpUserParameters->Simulation().get().Mesh(),
00918 & mpDefaultParameters->Simulation().get().Mesh(),
00919 "Mesh");
00920 return true;
00921 }
00922 catch (Exception& e)
00923 {
00924 return false;
00925 }
00926 }
00927
00928 bool HeartConfig::GetCreateMesh() const
00929 {
00930 CheckSimulationIsDefined("Mesh");
00931
00932 cp::mesh_type mesh = DecideLocation( & mpUserParameters->Simulation().get().Mesh(),
00933 & mpDefaultParameters->Simulation().get().Mesh(),
00934 "Mesh")->get();
00935
00936 return (mesh.Slab().present() || mesh.Sheet().present() || mesh.Fibre().present());
00937 }
00938
00939 bool HeartConfig::GetCreateSlab() const
00940 {
00941 CheckSimulationIsDefined("Mesh");
00942
00943 cp::mesh_type mesh = DecideLocation( & mpUserParameters->Simulation().get().Mesh(),
00944 & mpDefaultParameters->Simulation().get().Mesh(),
00945 "Mesh")->get();
00946
00947 return (mesh.Slab().present());
00948 }
00949
00950 bool HeartConfig::GetCreateSheet() const
00951 {
00952 CheckSimulationIsDefined("Mesh");
00953
00954 cp::mesh_type mesh = DecideLocation( & mpUserParameters->Simulation().get().Mesh(),
00955 & mpDefaultParameters->Simulation().get().Mesh(),
00956 "Mesh")->get();
00957
00958 return (mesh.Sheet().present());
00959 }
00960
00961 bool HeartConfig::GetCreateFibre() const
00962 {
00963 CheckSimulationIsDefined("Mesh");
00964
00965 cp::mesh_type mesh = DecideLocation( & mpUserParameters->Simulation().get().Mesh(),
00966 & mpDefaultParameters->Simulation().get().Mesh(),
00967 "Mesh")->get();
00968
00969 return (mesh.Fibre().present());
00970 }
00971
00972
00973 bool HeartConfig::GetLoadMesh() const
00974 {
00975 CheckSimulationIsDefined("Mesh");
00976
00977 return (DecideLocation( & mpUserParameters->Simulation().get().Mesh(),
00978 & mpDefaultParameters->Simulation().get().Mesh(),
00979 "Mesh")->get().LoadMesh().present());
00980 }
00981
00982 void HeartConfig::GetSlabDimensions(c_vector<double, 3>& slabDimensions) const
00983 {
00984 CheckSimulationIsDefined("Slab");
00985
00986 if (GetSpaceDimension()!=3 || !GetCreateSlab())
00987 {
00988 EXCEPTION("Tissue slabs can only be defined in 3D");
00989 }
00990
00991 optional<cp::slab_type, false> slab_dimensions = DecideLocation( & mpUserParameters->Simulation().get().Mesh(),
00992 & mpDefaultParameters->Simulation().get().Mesh(),
00993 "Slab")->get().Slab();
00994
00995 slabDimensions[0] = slab_dimensions->x();
00996 slabDimensions[1] = slab_dimensions->y();
00997 slabDimensions[2] = slab_dimensions->z();
00998 }
00999
01000 void HeartConfig::GetSheetDimensions(c_vector<double, 2>& sheetDimensions) const
01001 {
01002 CheckSimulationIsDefined("Sheet");
01003
01004 if (GetSpaceDimension()!=2 || !GetCreateSheet())
01005 {
01006 EXCEPTION("Tissue sheets can only be defined in 2D");
01007 }
01008
01009 optional<cp::sheet_type, false> sheet_dimensions = DecideLocation( & mpUserParameters->Simulation().get().Mesh(),
01010 & mpDefaultParameters->Simulation().get().Mesh(),
01011 "Sheet")->get().Sheet();
01012
01013 sheetDimensions[0] = sheet_dimensions->x();
01014 sheetDimensions[1] = sheet_dimensions->y();
01015 }
01016
01017 void HeartConfig::GetFibreLength(c_vector<double, 1>& fibreLength) const
01018 {
01019 CheckSimulationIsDefined("Fibre");
01020
01021 if (GetSpaceDimension()!=1 || !GetCreateFibre())
01022 {
01023 EXCEPTION("Tissue fibres can only be defined in 1D");
01024 }
01025
01026 optional<cp::fibre_type, false> fibre_length = DecideLocation( & mpUserParameters->Simulation().get().Mesh(),
01027 & mpDefaultParameters->Simulation().get().Mesh(),
01028 "Fibre")->get().Fibre();
01029
01030 fibreLength[0] = fibre_length->x();
01031 }
01032
01033
01034 double HeartConfig::GetInterNodeSpace() const
01035 {
01036 CheckSimulationIsDefined("InterNodeSpace");
01037 assert(GetCreateMesh());
01038
01039 switch(GetSpaceDimension())
01040 {
01041 case 3:
01042 return DecideLocation( & mpUserParameters->Simulation().get().Mesh(),
01043 & mpDefaultParameters->Simulation().get().Mesh(),
01044 "Slab")->get().Slab()->inter_node_space();
01045 break;
01046 case 2:
01047 return DecideLocation( & mpUserParameters->Simulation().get().Mesh(),
01048 & mpDefaultParameters->Simulation().get().Mesh(),
01049 "Sheet")->get().Sheet()->inter_node_space();
01050 break;
01051 case 1:
01052 return DecideLocation( & mpUserParameters->Simulation().get().Mesh(),
01053 & mpDefaultParameters->Simulation().get().Mesh(),
01054 "Fibre")->get().Fibre()->inter_node_space();
01055 break;
01056 default:
01057 NEVER_REACHED;
01058 #define COVERAGE_IGNORE
01059 return 0.0;
01060 #undef COVERAGE_IGNORE
01061 }
01062 }
01063
01064 std::string HeartConfig::GetMeshName() const
01065 {
01066 CheckSimulationIsDefined("LoadMesh");
01067 assert(GetLoadMesh());
01068
01069 return DecideLocation( & mpUserParameters->Simulation().get().Mesh(),
01070 & mpDefaultParameters->Simulation().get().Mesh(),
01071 "LoadMesh")->get().LoadMesh()->name();
01072 }
01073
01074 cp::media_type HeartConfig::GetConductivityMedia() const
01075 {
01076 CheckSimulationIsDefined("LoadMesh");
01077 assert(GetLoadMesh());
01078
01079 return DecideLocation( & mpUserParameters->Simulation().get().Mesh(),
01080 & mpDefaultParameters->Simulation().get().Mesh(),
01081 "LoadMesh")->get().LoadMesh()->conductivity_media();
01082 }
01083
01084 template <unsigned DIM>
01085 void HeartConfig::GetStimuli(std::vector<boost::shared_ptr<AbstractStimulusFunction> >& rStimuliApplied,
01086 std::vector<boost::shared_ptr<AbstractChasteRegion<DIM> > >& rStimulatedAreas) const
01087 {
01088 CheckSimulationIsDefined("Stimuli");
01089 XSD_SEQUENCE_TYPE(cp::stimuli_type::Stimulus) stimuli;
01090
01091
01092 try
01093 {
01094 stimuli = DecideLocation( & mpUserParameters->Simulation().get().Stimuli(),
01095 & mpDefaultParameters->Simulation().get().Stimuli(),
01096 "Stimuli")->get().Stimulus();
01097 }
01098 catch(Exception& e)
01099 {
01100
01101
01102 return;
01103 }
01104
01105 for (XSD_ITERATOR_TYPE(cp::stimuli_type::Stimulus) i = stimuli.begin();
01106 i != stimuli.end();
01107 ++i)
01108 {
01109 cp::stimulus_type stimulus(*i);
01110 if (stimulus.Location().Cuboid().present() || stimulus.Location().Ellipsoid().present())
01111 {
01112 boost::shared_ptr<AbstractChasteRegion<DIM> > area_ptr;
01113 if (stimulus.Location().Cuboid().present() )
01114 {
01115 cp::point_type point_a = stimulus.Location().Cuboid()->LowerCoordinates();
01116 cp::point_type point_b = stimulus.Location().Cuboid()->UpperCoordinates();
01117 switch (DIM)
01118 {
01119 case 1:
01120 {
01121 ChastePoint<DIM> chaste_point_a ( point_a.x() );
01122 ChastePoint<DIM> chaste_point_b ( point_b.x() );
01123 area_ptr.reset(new ChasteCuboid<DIM>( chaste_point_a, chaste_point_b ) );
01124 break;
01125 }
01126 case 2:
01127 {
01128 ChastePoint<DIM> chaste_point_a ( point_a.x(), point_a.y() );
01129 ChastePoint<DIM> chaste_point_b ( point_b.x(), point_b.y() );
01130 area_ptr.reset(new ChasteCuboid<DIM>( chaste_point_a, chaste_point_b ) );
01131 break;
01132 }
01133 case 3:
01134 {
01135 ChastePoint<DIM> chaste_point_a ( point_a.x(), point_a.y(), point_a.z() );
01136 ChastePoint<DIM> chaste_point_b ( point_b.x(), point_b.y(), point_b.z() );
01137 area_ptr.reset(new ChasteCuboid<DIM>( chaste_point_a, chaste_point_b ) );
01138 break;
01139 }
01140 default:
01141 NEVER_REACHED;
01142 break;
01143 }
01144 }
01145 else if (stimulus.Location().Ellipsoid().present())
01146 {
01147 cp::point_type centre = stimulus.Location().Ellipsoid()->Centre();
01148 cp::point_type radii = stimulus.Location().Ellipsoid()->Radii();
01149 switch (DIM)
01150 {
01151 case 1:
01152 {
01153 ChastePoint<DIM> chaste_point_a ( centre.x() );
01154 ChastePoint<DIM> chaste_point_b ( radii.x() );
01155 area_ptr.reset( new ChasteEllipsoid<DIM> ( chaste_point_a, chaste_point_b ) );
01156 break;
01157 }
01158 case 2:
01159 {
01160 ChastePoint<DIM> chaste_point_a ( centre.x(), centre.y() );
01161 ChastePoint<DIM> chaste_point_b ( radii.x(), radii.y() );
01162 area_ptr.reset( new ChasteEllipsoid<DIM> ( chaste_point_a, chaste_point_b ) );
01163 break;
01164 }
01165 case 3:
01166 {
01167 ChastePoint<DIM> chaste_point_a ( centre.x(), centre.y(), centre.z() );
01168 ChastePoint<DIM> chaste_point_b ( radii.x(), radii.y(), radii.z() );
01169 area_ptr.reset( new ChasteEllipsoid<DIM> ( chaste_point_a, chaste_point_b ) );
01170 break;
01171 }
01172 default:
01173 {
01174 NEVER_REACHED;
01175 break;
01176 }
01177 }
01178 }
01179 rStimulatedAreas.push_back(area_ptr);
01180
01181 boost::shared_ptr<AbstractStimulusFunction> stim;
01182
01183 if (stimulus.Period().present())
01184 {
01185 if (stimulus.StopTime().present())
01186 {
01187 stim.reset(new RegularStimulus(stimulus.Strength(),
01188 stimulus.Duration(),
01189 stimulus.Period().get(),
01190 stimulus.Delay(),
01191 stimulus.StopTime().get()));
01192 }
01193 else
01194 {
01195 stim.reset(new RegularStimulus(stimulus.Strength(),
01196 stimulus.Duration(),
01197 stimulus.Period().get(),
01198 stimulus.Delay()));
01199 }
01200
01201 }
01202 else
01203 {
01204 if (stimulus.StopTime().present())
01205 {
01206 EXCEPTION("Stop time can not be defined for SimpleStimulus. Use Duration instead.");
01207 }
01208
01209 stim.reset(new SimpleStimulus(stimulus.Strength(),
01210 stimulus.Duration(),
01211 stimulus.Delay()));
01212 }
01213 rStimuliApplied.push_back( stim );
01214 }
01215 else if(stimulus.Location().EpiLayer().present() || stimulus.Location().MidLayer().present() || stimulus.Location().EndoLayer().present() )
01216 {
01217 EXCEPTION("Definition of transmural layers is not yet supported for specifying stimulated areas, please use cuboids instead");
01218 }
01219 else
01220 {
01221 EXCEPTION("Invalid region type for stimulus definition");
01222 }
01223 }
01224 }
01225
01226
01227 template<unsigned DIM>
01228 void HeartConfig::GetCellHeterogeneities(std::vector<boost::shared_ptr<AbstractChasteRegion<DIM> > >& rCellHeterogeneityRegions,
01229 std::vector<double>& rScaleFactorGks,
01230 std::vector<double>& rScaleFactorIto,
01231 std::vector<double>& rScaleFactorGkr,
01232 std::vector<std::map<std::string, double> >* pParameterSettings)
01233 {
01234 CheckSimulationIsDefined("CellHeterogeneities");
01235 XSD_SEQUENCE_TYPE(cp::cell_heterogeneities_type::CellHeterogeneity) cell_heterogeneity;
01236
01237 try
01238 {
01239 cell_heterogeneity = DecideLocation( & mpUserParameters->Simulation().get().CellHeterogeneities(),
01240 & mpDefaultParameters->Simulation().get().CellHeterogeneities(),
01241 "CellHeterogeneities")->get().CellHeterogeneity();
01242 }
01243 catch(Exception& e)
01244 {
01245
01246 return;
01247 }
01248
01249 bool user_supplied_negative_value = false;
01250 bool user_asking_for_transmural_layers = false;
01251 bool user_asked_for_cuboids_or_ellipsoids = false;
01252 unsigned counter_of_heterogeneities = 0;
01253
01254 for (XSD_ITERATOR_TYPE(cp::cell_heterogeneities_type::CellHeterogeneity) i = cell_heterogeneity.begin();
01255 i != cell_heterogeneity.end();
01256 ++i)
01257 {
01258 cp::cell_heterogeneity_type ht(*i);
01259
01260
01261 if (ht.Location().Cuboid().present())
01262 {
01263 user_asked_for_cuboids_or_ellipsoids = true;
01264 cp::point_type point_a = ht.Location().Cuboid()->LowerCoordinates();
01265 cp::point_type point_b = ht.Location().Cuboid()->UpperCoordinates();
01266
01267 ChastePoint<DIM> chaste_point_a ( point_a.x(), point_a.y(), point_a.z() );
01268 ChastePoint<DIM> chaste_point_b ( point_b.x(), point_b.y(), point_b.z() );
01269
01270 rCellHeterogeneityRegions.push_back(boost::shared_ptr<AbstractChasteRegion<DIM> >(new ChasteCuboid<DIM> ( chaste_point_a, chaste_point_b )) );
01271 }
01272 else if (ht.Location().Ellipsoid().present())
01273 {
01274 user_asked_for_cuboids_or_ellipsoids = true;
01275 cp::point_type centre = ht.Location().Ellipsoid()->Centre();
01276 cp::point_type radii = ht.Location().Ellipsoid()->Radii();
01277
01278 ChastePoint<DIM> chaste_point_a ( centre.x(), centre.y(), centre.z() );
01279 ChastePoint<DIM> chaste_point_b ( radii.x(), radii.y(), radii.z() );
01280 rCellHeterogeneityRegions.push_back(boost::shared_ptr<AbstractChasteRegion<DIM> >(new ChasteEllipsoid<DIM> ( chaste_point_a, chaste_point_b )) );
01281 }
01282 else if (ht.Location().EpiLayer().present())
01283 {
01284 mEpiFraction = ht.Location().EpiLayer().get();
01285
01286 user_asking_for_transmural_layers = true;
01287 if (mEpiFraction <0)
01288 {
01289 user_supplied_negative_value=true;
01290 }
01291 mIndexEpi = counter_of_heterogeneities;
01292 }
01293 else if (ht.Location().EndoLayer().present())
01294 {
01295 mEndoFraction = ht.Location().EndoLayer().get();
01296
01297 user_asking_for_transmural_layers = true;
01298 if (mEndoFraction <0)
01299 {
01300 user_supplied_negative_value=true;
01301 }
01302 mIndexEndo = counter_of_heterogeneities;
01303 }
01304 else if (ht.Location().MidLayer().present())
01305 {
01306 mMidFraction = ht.Location().MidLayer().get();
01307
01308 user_asking_for_transmural_layers = true;
01309 if (mMidFraction <0)
01310 {
01311 user_supplied_negative_value=true;
01312 }
01313 mIndexMid = counter_of_heterogeneities;
01314 }
01315 else
01316 {
01317 EXCEPTION("Invalid region type for cell heterogeneity definition");
01318 }
01319
01320
01321 rScaleFactorGks.push_back(ht.ScaleFactorGks().present() ? (double)ht.ScaleFactorGks().get() : 1.0);
01322 rScaleFactorIto.push_back(ht.ScaleFactorIto().present() ? (double)ht.ScaleFactorIto().get() : 1.0);
01323 rScaleFactorGkr.push_back(ht.ScaleFactorGkr().present() ? (double)ht.ScaleFactorGkr().get() : 1.0);
01324
01325
01326 if (pParameterSettings)
01327 {
01328 std::map<std::string, double> param_settings;
01329 XSD_SEQUENCE_TYPE(cp::cell_heterogeneity_type::SetParameter)& params = ht.SetParameter();
01330 for (XSD_ITERATOR_TYPE(cp::cell_heterogeneity_type::SetParameter) param_it = params.begin();
01331 param_it != params.end();
01332 ++param_it)
01333 {
01334 cp::set_parameter_type param(*param_it);
01335 param_settings[param.name()] = param.value();
01336 }
01337 pParameterSettings->push_back(param_settings);
01338 }
01339
01340 counter_of_heterogeneities++;
01341 }
01342
01343
01344 mUserAskedForCellularTransmuralHeterogeneities = user_asking_for_transmural_layers;
01345
01346 if ( mUserAskedForCellularTransmuralHeterogeneities )
01347 {
01348
01349 if (user_asked_for_cuboids_or_ellipsoids )
01350 {
01351 EXCEPTION ("Specification of cellular heterogeneities by cuboids/ellipsoids and layers at the same time is not yet supported");
01352 }
01353
01354
01355
01356
01357 if ((mIndexMid+mIndexEndo+mIndexEpi) > 3)
01358 {
01359 EXCEPTION ("Three specifications of layers must be supplied");
01360 }
01361 if (fabs((mEndoFraction+mMidFraction+mEpiFraction)-1)>1e-2)
01362 {
01363 EXCEPTION ("Summation of epicardial, midmyocardial and endocardial fractions should be 1");
01364 }
01365 if (user_supplied_negative_value)
01366 {
01367 EXCEPTION ("Fractions must be positive");
01368 }
01369 }
01370 }
01371
01372 bool HeartConfig::AreCellularTransmuralHeterogeneitiesRequested()
01373 {
01374 return mUserAskedForCellularTransmuralHeterogeneities;
01375 }
01376
01377 double HeartConfig::GetEpiLayerFraction()
01378 {
01379 return mEpiFraction;
01380 }
01381
01382 double HeartConfig::GetEndoLayerFraction()
01383 {
01384 return mEndoFraction;
01385 }
01386
01387 double HeartConfig::GetMidLayerFraction()
01388 {
01389 return mMidFraction;
01390 }
01391
01392 unsigned HeartConfig::GetEpiLayerIndex()
01393 {
01394 return mIndexEpi;
01395 }
01396
01397 unsigned HeartConfig::GetEndoLayerIndex()
01398 {
01399 return mIndexEndo;
01400 }
01401
01402 unsigned HeartConfig::GetMidLayerIndex()
01403 {
01404 return mIndexMid;
01405 }
01406
01407 bool HeartConfig::GetConductivityHeterogeneitiesProvided() const
01408 {
01409 CheckSimulationIsDefined("ConductivityHeterogeneities");
01410 try
01411 {
01412 DecideLocation( & mpUserParameters->Simulation().get().ConductivityHeterogeneities(),
01413 & mpDefaultParameters->Simulation().get().ConductivityHeterogeneities(),
01414 "ConductivityHeterogeneities");
01415 return true;
01416 }
01417 catch (Exception& e)
01418 {
01419 return false;
01420 }
01421 }
01422
01423 template<unsigned DIM>
01424 void HeartConfig::GetConductivityHeterogeneities(
01425 std::vector<boost::shared_ptr<AbstractChasteRegion<DIM> > >& conductivitiesHeterogeneityAreas,
01426 std::vector< c_vector<double,3> >& intraConductivities,
01427 std::vector< c_vector<double,3> >& extraConductivities) const
01428 {
01429 CheckSimulationIsDefined("ConductivityHeterogeneities");
01430 XSD_ANON_SEQUENCE_TYPE(cp::simulation_type, ConductivityHeterogeneities, ConductivityHeterogeneity)&
01431 conductivity_heterogeneity = DecideLocation( & mpUserParameters->Simulation().get().ConductivityHeterogeneities(),
01432 & mpDefaultParameters->Simulation().get().ConductivityHeterogeneities(),
01433 "ConductivityHeterogeneities")->get().ConductivityHeterogeneity();
01434
01435 for (XSD_ANON_ITERATOR_TYPE(cp::simulation_type, ConductivityHeterogeneities, ConductivityHeterogeneity) i = conductivity_heterogeneity.begin();
01436 i != conductivity_heterogeneity.end();
01437 ++i)
01438 {
01439 cp::conductivity_heterogeneity_type ht(*i);
01440
01441 if (ht.Location().Cuboid().present())
01442 {
01443 cp::point_type point_a = ht.Location().Cuboid()->LowerCoordinates();
01444 cp::point_type point_b = ht.Location().Cuboid()->UpperCoordinates();
01445 ChastePoint<DIM> chaste_point_a ( point_a.x(), point_a.y(), point_a.z() );
01446 ChastePoint<DIM> chaste_point_b ( point_b.x(), point_b.y(), point_b.z() );
01447 conductivitiesHeterogeneityAreas.push_back(boost::shared_ptr<AbstractChasteRegion<DIM> > ( new ChasteCuboid<DIM> ( chaste_point_a, chaste_point_b )) );
01448 }
01449 else if (ht.Location().Ellipsoid().present())
01450 {
01451 cp::point_type centre = ht.Location().Ellipsoid()->Centre();
01452 cp::point_type radii = ht.Location().Ellipsoid()->Radii();
01453 ChastePoint<DIM> chaste_point_a ( centre.x(), centre.y(), centre.z() );
01454 ChastePoint<DIM> chaste_point_b ( radii.x(), radii.y(), radii.z() );
01455 conductivitiesHeterogeneityAreas.push_back(boost::shared_ptr<AbstractChasteRegion<DIM> > ( new ChasteEllipsoid<DIM> ( chaste_point_a, chaste_point_b )) );
01456 }
01457 else if(ht.Location().EpiLayer().present() || ht.Location().MidLayer().present() || ht.Location().EndoLayer().present() )
01458 {
01460 EXCEPTION("Definition of transmural layers is not allowed for conductivities heterogeneities, you may use fibre orientation support instead");
01461 }
01462 else
01463 {
01464 EXCEPTION("Invalid region type for conductivity definition");
01465 }
01466
01467 if (ht.IntracellularConductivities().present())
01468 {
01469 double intra_x = ht.IntracellularConductivities().get().longi();
01470 double intra_y = ht.IntracellularConductivities().get().trans();
01471 double intra_z = ht.IntracellularConductivities().get().normal();
01472
01473 intraConductivities.push_back( Create_c_vector(intra_x, intra_y, intra_z) );
01474 }
01475 else
01476 {
01477 c_vector<double, 3> intra_conductivities;
01478 GetIntracellularConductivities(intra_conductivities);
01479 intraConductivities.push_back(intra_conductivities);
01480 }
01481
01482 if (ht.ExtracellularConductivities().present())
01483 {
01484 double extra_x = ht.ExtracellularConductivities().get().longi();
01485 double extra_y = ht.ExtracellularConductivities().get().trans();
01486 double extra_z = ht.ExtracellularConductivities().get().normal();
01487
01488 extraConductivities.push_back( Create_c_vector(extra_x, extra_y, extra_z) );
01489 }
01490 else
01491 {
01492 c_vector<double, 3> extra_conductivities;
01493 GetExtracellularConductivities(extra_conductivities);
01494 extraConductivities.push_back(extra_conductivities);
01495 }
01496
01497 }
01498 }
01499
01500 std::string HeartConfig::GetOutputDirectory() const
01501 {
01502 CheckSimulationIsDefined("Simulation/OutputDirectory");
01503 return DecideLocation( & mpUserParameters->Simulation().get().OutputDirectory(),
01504 & mpDefaultParameters->Simulation().get().OutputDirectory(),
01505 "Simulation/OutputDirectory")->get();
01506 }
01507
01508 std::string HeartConfig::GetOutputFilenamePrefix() const
01509 {
01510 CheckSimulationIsDefined("Simulation/OutputFilenamePrefix");
01511 return DecideLocation( & mpUserParameters->Simulation().get().OutputFilenamePrefix(),
01512 & mpDefaultParameters->Simulation().get().OutputFilenamePrefix(),
01513 "Simulation/OutputFilenamePrefix")->get();
01514 }
01515
01516 bool HeartConfig::GetOutputVariablesProvided() const
01517 {
01518 CheckSimulationIsDefined("OutputVariables");
01519
01520 try
01521 {
01522 DecideLocation( & mpUserParameters->Simulation().get().OutputVariables(),
01523 & mpDefaultParameters->Simulation().get().OutputVariables(),
01524 "OutputVariables");
01525 return true;
01526 }
01527 catch (Exception& e)
01528 {
01529 return false;
01530 }
01531 }
01532
01533 void HeartConfig::GetOutputVariables(std::vector<std::string>& rOutputVariables) const
01534 {
01535 CheckSimulationIsDefined("OutputVariables");
01536 XSD_SEQUENCE_TYPE(cp::output_variables_type::Var)&
01537 output_variables = DecideLocation( & mpUserParameters->Simulation().get().OutputVariables(),
01538 & mpDefaultParameters->Simulation().get().OutputVariables(),
01539 "OutputVariables")->get().Var();
01540 rOutputVariables.clear();
01541
01542 for (XSD_ITERATOR_TYPE(cp::output_variables_type::Var) i = output_variables.begin();
01543 i != output_variables.end();
01544 ++i)
01545 {
01546 cp::var_type& r_var(*i);
01547
01548
01549 rOutputVariables.push_back(r_var.name());
01550 }
01551 }
01552 bool HeartConfig::GetOutputUsingOriginalNodeOrdering()
01553 {
01554 try
01555 {
01556 return (DecideLocation(& mpUserParameters->Simulation().get().OutputUsingOriginalNodeOrdering(),
01557 & mpDefaultParameters->Simulation().get().OutputUsingOriginalNodeOrdering(),
01558 "OutputUsingOriginalNodeOrdering")->get() == cp::yesno_type::yes);
01559 }
01560 catch (Exception &e)
01561 {
01562
01563 return false;
01564 }
01565 }
01566
01567 bool HeartConfig::GetCheckpointSimulation() const
01568 {
01569 try
01570 {
01571 if (IsSimulationDefined())
01572 {
01573 CheckSimulationIsDefined("GetSaveSimulation");
01574 DecideLocation( & mpUserParameters->Simulation().get().CheckpointSimulation(),
01575 & mpDefaultParameters->Simulation().get().CheckpointSimulation(),
01576 "Simulation/SaveSimulation");
01577 }
01578 else
01579 {
01580 CheckResumeSimulationIsDefined("GetSaveSimulation");
01581 DecideLocation( & mpUserParameters->ResumeSimulation().get().CheckpointSimulation(),
01582 & mpDefaultParameters->Simulation().get().CheckpointSimulation(),
01583 "ResumeSimulation/SaveSimulation");
01584 }
01585 return true;
01586 }
01587 catch (Exception& e)
01588 {
01589 return false;
01590 }
01591 }
01592
01593 double HeartConfig::GetCheckpointTimestep() const
01594 {
01595 if (IsSimulationDefined())
01596 {
01597 CheckSimulationIsDefined("GetSaveSimulation");
01598 return DecideLocation( & mpUserParameters->Simulation().get().CheckpointSimulation(),
01599 & mpDefaultParameters->Simulation().get().CheckpointSimulation(),
01600 "Simulation/SaveSimulation")->get().timestep();
01601 }
01602 else
01603 {
01604 CheckResumeSimulationIsDefined("GetSaveSimulation");
01605 return DecideLocation( & mpUserParameters->ResumeSimulation().get().CheckpointSimulation(),
01606 & mpDefaultParameters->Simulation().get().CheckpointSimulation(),
01607 "ResumeSimulation/SaveSimulation")->get().timestep();
01608 }
01609 }
01610
01611 unsigned HeartConfig::GetMaxCheckpointsOnDisk() const
01612 {
01613 if (IsSimulationDefined())
01614 {
01615 CheckSimulationIsDefined("GetSaveSimulation");
01616 return DecideLocation( & mpUserParameters->Simulation().get().CheckpointSimulation(),
01617 & mpDefaultParameters->Simulation().get().CheckpointSimulation(),
01618 "Simulation/SaveSimulation")->get().max_checkpoints_on_disk();
01619 }
01620 else
01621 {
01622 CheckResumeSimulationIsDefined("GetSaveSimulation");
01623 return DecideLocation( & mpUserParameters->ResumeSimulation().get().CheckpointSimulation(),
01624 & mpDefaultParameters->Simulation().get().CheckpointSimulation(),
01625 "ResumeSimulation/SaveSimulation")->get().max_checkpoints_on_disk();
01626 }
01627 }
01628
01629
01630 HeartFileFinder HeartConfig::GetArchivedSimulationDir() const
01631 {
01632 CheckResumeSimulationIsDefined("GetArchivedSimulationDir");
01633
01634 return HeartFileFinder(mpUserParameters->ResumeSimulation().get().ArchiveDirectory());
01635 }
01636
01637
01638 void HeartConfig::GetIntracellularConductivities(c_vector<double, 3>& intraConductivities) const
01639 {
01640 optional<cp::conductivities_type, false>* intra_conductivities
01641 = DecideLocation( & mpUserParameters->Physiological().IntracellularConductivities(),
01642 & mpDefaultParameters->Physiological().IntracellularConductivities(),
01643 "IntracellularConductivities");
01644 double intra_x_cond = intra_conductivities->get().longi();
01645 double intra_y_cond = intra_conductivities->get().trans();
01646 double intra_z_cond = intra_conductivities->get().normal();;
01647
01648 assert(intra_y_cond != DBL_MAX);
01649 assert(intra_z_cond != DBL_MAX);
01650
01651 intraConductivities[0] = intra_x_cond;
01652 intraConductivities[1] = intra_y_cond;
01653 intraConductivities[2] = intra_z_cond;
01654 }
01655
01656 void HeartConfig::GetIntracellularConductivities(c_vector<double, 2>& intraConductivities) const
01657 {
01658 optional<cp::conductivities_type, false>* intra_conductivities
01659 = DecideLocation( & mpUserParameters->Physiological().IntracellularConductivities(),
01660 & mpDefaultParameters->Physiological().IntracellularConductivities(),
01661 "IntracellularConductivities");
01662 double intra_x_cond = intra_conductivities->get().longi();
01663 double intra_y_cond = intra_conductivities->get().trans();
01664
01665 assert(intra_y_cond != DBL_MAX);
01666
01667 intraConductivities[0] = intra_x_cond;
01668 intraConductivities[1] = intra_y_cond;
01669 }
01670
01671 void HeartConfig::GetIntracellularConductivities(c_vector<double, 1>& intraConductivities) const
01672 {
01673 optional<cp::conductivities_type, false>* intra_conductivities
01674 = DecideLocation( & mpUserParameters->Physiological().IntracellularConductivities(),
01675 & mpDefaultParameters->Physiological().IntracellularConductivities(),
01676 "IntracellularConductivities");
01677 double intra_x_cond = intra_conductivities->get().longi();
01678
01679 intraConductivities[0] = intra_x_cond;
01680 }
01681
01682 void HeartConfig::GetExtracellularConductivities(c_vector<double, 3>& extraConductivities) const
01683 {
01684 optional<cp::conductivities_type, false>* extra_conductivities
01685 = DecideLocation( & mpUserParameters->Physiological().ExtracellularConductivities(),
01686 & mpDefaultParameters->Physiological().ExtracellularConductivities(),
01687 "ExtracellularConductivities");
01688 double extra_x_cond = extra_conductivities->get().longi();
01689 double extra_y_cond = extra_conductivities->get().trans();
01690 double extra_z_cond = extra_conductivities->get().normal();;
01691
01692 assert(extra_y_cond != DBL_MAX);
01693 assert(extra_z_cond != DBL_MAX);
01694
01695 extraConductivities[0] = extra_x_cond;
01696 extraConductivities[1] = extra_y_cond;
01697 extraConductivities[2] = extra_z_cond;
01698 }
01699
01700 void HeartConfig::GetExtracellularConductivities(c_vector<double, 2>& extraConductivities) const
01701 {
01702 optional<cp::conductivities_type, false>* extra_conductivities
01703 = DecideLocation( & mpUserParameters->Physiological().ExtracellularConductivities(),
01704 & mpDefaultParameters->Physiological().ExtracellularConductivities(),
01705 "ExtracellularConductivities");
01706 double extra_x_cond = extra_conductivities->get().longi();
01707 double extra_y_cond = extra_conductivities->get().trans();
01708
01709 assert(extra_y_cond != DBL_MAX);
01710
01711 extraConductivities[0] = extra_x_cond;
01712 extraConductivities[1] = extra_y_cond;
01713 }
01714
01715 void HeartConfig::GetExtracellularConductivities(c_vector<double, 1>& extraConductivities) const
01716 {
01717 optional<cp::conductivities_type, false>* extra_conductivities
01718 = DecideLocation( & mpUserParameters->Physiological().ExtracellularConductivities(),
01719 & mpDefaultParameters->Physiological().ExtracellularConductivities(),
01720 "ExtracellularConductivities");
01721 double extra_x_cond = extra_conductivities->get().longi();
01722
01723 extraConductivities[0] = extra_x_cond;
01724 }
01725
01726 double HeartConfig::GetBathConductivity(unsigned bathRegion) const
01727 {
01728
01729
01730
01731
01732
01733
01734
01735
01736
01737 if (bathRegion == UINT_MAX)
01738 {
01739
01740 return DecideLocation( & mpUserParameters->Physiological().BathConductivity(),
01741 & mpDefaultParameters->Physiological().BathConductivity(),
01742 "BathConductivity")->get();
01743 }
01744 else
01745 {
01746 assert(HeartRegionCode::IsRegionBath(bathRegion));
01747
01748 std::map<unsigned, double>::const_iterator map_entry = mBathConductivities.find(bathRegion);
01749
01750 if (map_entry != mBathConductivities.end())
01751 {
01752 return map_entry->second;
01753 }
01754 else
01755 {
01756
01757 return DecideLocation( & mpUserParameters->Physiological().BathConductivity(),
01758 & mpDefaultParameters->Physiological().BathConductivity(),
01759 "BathConductivity")->get();
01760 }
01761 }
01762 }
01763 const std::set<unsigned>& HeartConfig::rGetTissueIdentifiers()
01764 {
01765 return mTissueIdentifiers;
01766 }
01767
01768 const std::set<unsigned>& HeartConfig::rGetBathIdentifiers()
01769 {
01770 return mBathIdentifiers;
01771 }
01772
01773 double HeartConfig::GetSurfaceAreaToVolumeRatio() const
01774 {
01775
01776 return DecideLocation( & mpUserParameters->Physiological().SurfaceAreaToVolumeRatio(),
01777 & mpDefaultParameters->Physiological().SurfaceAreaToVolumeRatio(),
01778 "SurfaceAreaToVolumeRatio")->get();
01779 }
01780
01781 double HeartConfig::GetCapacitance() const
01782 {
01783
01784 return DecideLocation( & mpUserParameters->Physiological().Capacitance(),
01785 & mpDefaultParameters->Physiological().Capacitance(),
01786 "Capacitance")->get();
01787 }
01788
01789 double HeartConfig::GetOdeTimeStep() const
01790 {
01791 return DecideLocation( & mpUserParameters->Numerical().TimeSteps(),
01792 & mpDefaultParameters->Numerical().TimeSteps(),
01793 "ode TimeStep")->get().ode();
01794 }
01795
01796 double HeartConfig::GetPdeTimeStep() const
01797 {
01798 return DecideLocation( & mpUserParameters->Numerical().TimeSteps(),
01799 & mpDefaultParameters->Numerical().TimeSteps(),
01800 "pde TimeStep")->get().pde();
01801 }
01802
01803 double HeartConfig::GetPrintingTimeStep() const
01804 {
01805 return DecideLocation( & mpUserParameters->Numerical().TimeSteps(),
01806 & mpDefaultParameters->Numerical().TimeSteps(),
01807 "printing TimeStep")->get().printing();
01808 }
01809
01810 bool HeartConfig::GetUseAbsoluteTolerance() const
01811 {
01812 return DecideLocation( & mpUserParameters->Numerical().KSPTolerances(),
01813 & mpDefaultParameters->Numerical().KSPTolerances(),
01814 "KSPTolerances")->get().KSPAbsolute().present();
01815 }
01816
01817 double HeartConfig::GetAbsoluteTolerance() const
01818 {
01819 if (!GetUseAbsoluteTolerance())
01820 {
01821 EXCEPTION("Absolute tolerance is not set in Chaste parameters");
01822 }
01823 return DecideLocation( & mpUserParameters->Numerical().KSPTolerances(),
01824 & mpDefaultParameters->Numerical().KSPTolerances(),
01825 "KSPTolerances")->get().KSPAbsolute().get();
01826 }
01827
01828 bool HeartConfig::GetUseRelativeTolerance() const
01829 {
01830 return DecideLocation( & mpUserParameters->Numerical().KSPTolerances(),
01831 & mpDefaultParameters->Numerical().KSPTolerances(),
01832 "KSPTolerances")->get().KSPRelative().present();
01833 }
01834
01835 double HeartConfig::GetRelativeTolerance() const
01836 {
01837 if (!GetUseRelativeTolerance())
01838 {
01839 EXCEPTION("Relative tolerance is not set in Chaste parameters");
01840 }
01841 return DecideLocation( & mpUserParameters->Numerical().KSPTolerances(),
01842 & mpDefaultParameters->Numerical().KSPTolerances(),
01843 "KSPTolerances")->get().KSPRelative().get();
01844 }
01845
01846 const char* HeartConfig::GetKSPSolver() const
01847 {
01848 switch ( DecideLocation( & mpUserParameters->Numerical().KSPSolver(),
01849 & mpDefaultParameters->Numerical().KSPSolver(),
01850 "KSPSolver")->get() )
01851 {
01852 case cp::ksp_solver_type::gmres :
01853 return "gmres";
01854 case cp::ksp_solver_type::cg :
01855 return "cg";
01856 case cp::ksp_solver_type::symmlq :
01857 return "symmlq";
01858 case cp::ksp_solver_type::chebychev :
01859 return "chebychev";
01860 }
01861 #define COVERAGE_IGNORE
01862 EXCEPTION("Unknown ksp solver");
01863 #undef COVERAGE_IGNORE
01864 }
01865
01866 const char* HeartConfig::GetKSPPreconditioner() const
01867 {
01868 switch ( DecideLocation( & mpUserParameters->Numerical().KSPPreconditioner(),
01869 & mpDefaultParameters->Numerical().KSPPreconditioner(),
01870 "KSPPreconditioner")->get() )
01871 {
01872 case cp::ksp_preconditioner_type::jacobi :
01873 return "jacobi";
01874 case cp::ksp_preconditioner_type::bjacobi :
01875 return "bjacobi";
01876 case cp::ksp_preconditioner_type::hypre :
01877 return "hypre";
01878 case cp::ksp_preconditioner_type::ml :
01879 return "ml";
01880 case cp::ksp_preconditioner_type::spai :
01881 return "spai";
01882 case cp::ksp_preconditioner_type::blockdiagonal :
01883 return "blockdiagonal";
01884 case cp::ksp_preconditioner_type::ldufactorisation :
01885 return "ldufactorisation";
01886 case cp::ksp_preconditioner_type::twolevelsblockdiagonal :
01887 return "twolevelsblockdiagonal";
01888 case cp::ksp_preconditioner_type::none :
01889 return "none";
01890
01891 }
01892 #define COVERAGE_IGNORE
01893 EXCEPTION("Unknown ksp preconditioner");
01894 #undef COVERAGE_IGNORE
01895 }
01896
01897 DistributedTetrahedralMeshPartitionType::type HeartConfig::GetMeshPartitioning() const
01898 {
01899 switch ( DecideLocation( & mpUserParameters->Numerical().MeshPartitioning(),
01900 & mpDefaultParameters->Numerical().MeshPartitioning(),
01901 "MeshPartitioning")->get() )
01902 {
01903 case cp::mesh_partitioning_type::dumb :
01904 return DistributedTetrahedralMeshPartitionType::DUMB;
01905 case cp::mesh_partitioning_type::metis :
01906 return DistributedTetrahedralMeshPartitionType::METIS_LIBRARY;
01907 case cp::mesh_partitioning_type::parmetis :
01908 return DistributedTetrahedralMeshPartitionType::PARMETIS_LIBRARY;
01909 case cp::mesh_partitioning_type::petsc :
01910 return DistributedTetrahedralMeshPartitionType::PETSC_MAT_PARTITION;
01911 }
01912 #define COVERAGE_IGNORE
01913 EXCEPTION("Unknown mesh partitioning type");
01914 #undef COVERAGE_IGNORE
01915 }
01916
01917 bool HeartConfig::IsAdaptivityParametersPresent() const
01918 {
01919 try
01920 {
01921 DecideLocation( & mpUserParameters->Numerical().AdaptivityParameters(),
01922 & mpDefaultParameters->Numerical().AdaptivityParameters(),
01923 "AdaptivityParameters")->present();
01924
01925 return true;
01926 }
01927 catch (Exception &e)
01928 {
01929
01930 return false;
01931 }
01932 }
01933
01934 double HeartConfig::GetTargetErrorForAdaptivity() const
01935 {
01936 if ( IsAdaptivityParametersPresent() )
01937 {
01938 return DecideLocation( & mpUserParameters->Numerical().AdaptivityParameters(),
01939 & mpDefaultParameters->Numerical().AdaptivityParameters(),
01940 "TargetError")->get().target_error();
01941 }
01942 else
01943 {
01944 EXCEPTION("Adaptivity parameters have not been set");
01945 }
01946 }
01947
01948 double HeartConfig::GetSigmaForAdaptivity() const
01949 {
01950 if ( IsAdaptivityParametersPresent() )
01951 {
01952 return DecideLocation( & mpUserParameters->Numerical().AdaptivityParameters(),
01953 & mpDefaultParameters->Numerical().AdaptivityParameters(),
01954 "TargetError")->get().sigma();
01955 }
01956 else
01957 {
01958 EXCEPTION("Adaptivity parameters have not been set");
01959 }
01960 }
01961
01962 double HeartConfig::GetMaxEdgeLengthForAdaptivity() const
01963 {
01964 if ( IsAdaptivityParametersPresent() )
01965 {
01966 return DecideLocation( & mpUserParameters->Numerical().AdaptivityParameters(),
01967 & mpDefaultParameters->Numerical().AdaptivityParameters(),
01968 "TargetError")->get().max_edge_length();
01969 }
01970 else
01971 {
01972 EXCEPTION("Adaptivity parameters have not been set");
01973 }
01974 }
01975
01976 double HeartConfig::GetMinEdgeLengthForAdaptivity() const
01977 {
01978 if ( IsAdaptivityParametersPresent() )
01979 {
01980 return DecideLocation( & mpUserParameters->Numerical().AdaptivityParameters(),
01981 & mpDefaultParameters->Numerical().AdaptivityParameters(),
01982 "TargetError")->get().min_edge_length();
01983 }
01984 else
01985 {
01986 EXCEPTION("Adaptivity parameters have not been set");
01987 }
01988 }
01989
01990 double HeartConfig::GetGradationForAdaptivity() const
01991 {
01992 if ( IsAdaptivityParametersPresent() )
01993 {
01994 return DecideLocation( & mpUserParameters->Numerical().AdaptivityParameters(),
01995 & mpDefaultParameters->Numerical().AdaptivityParameters(),
01996 "TargetError")->get().gradation();
01997 }
01998 else
01999 {
02000 EXCEPTION("Adaptivity parameters have not been set");
02001 }
02002 }
02003
02004 unsigned HeartConfig::GetMaxNodesForAdaptivity() const
02005 {
02006 if ( IsAdaptivityParametersPresent() )
02007 {
02008 return DecideLocation( & mpUserParameters->Numerical().AdaptivityParameters(),
02009 & mpDefaultParameters->Numerical().AdaptivityParameters(),
02010 "TargetError")->get().max_nodes();
02011 }
02012 else
02013 {
02014 EXCEPTION("Adaptivity parameters have not been set");
02015 }
02016 }
02017
02018 unsigned HeartConfig::GetNumberOfAdaptiveSweeps() const
02019 {
02020 if ( IsAdaptivityParametersPresent() )
02021 {
02022 return DecideLocation( & mpUserParameters->Numerical().AdaptivityParameters(),
02023 & mpDefaultParameters->Numerical().AdaptivityParameters(),
02024 "TargetError")->get().num_sweeps();
02025 }
02026 else
02027 {
02028 EXCEPTION("Adaptivity parameters have not been set");
02029 }
02030 }
02031
02032
02033
02034
02035
02036 bool HeartConfig::IsPostProcessingSectionPresent() const
02037 {
02038 try
02039 {
02040 DecideLocation( & mpUserParameters->PostProcessing(),
02041 & mpDefaultParameters->PostProcessing(),
02042 "PostProcessing")->present();
02043
02044 return true;
02045 }
02046 catch (Exception &e)
02047 {
02048
02049 return false;
02050 }
02051 }
02052
02053 void HeartConfig::EnsurePostProcessingSectionPresent()
02054 {
02055 ENSURE_SECTION_PRESENT(mpUserParameters->PostProcessing(), cp::postprocessing_type);
02056 }
02057
02058 bool HeartConfig::IsPostProcessingRequested() const
02059 {
02060 if (IsPostProcessingSectionPresent() == false)
02061 {
02062 return false;
02063 }
02064 else
02065 {
02066 return(IsApdMapsRequested() ||
02067 IsUpstrokeTimeMapsRequested() ||
02068 IsMaxUpstrokeVelocityMapRequested() ||
02069 IsConductionVelocityMapsRequested() ||
02070 IsAnyNodalTimeTraceRequested()||
02071 IsPseudoEcgCalculationRequested());
02072 }
02073 }
02074 bool HeartConfig::IsApdMapsRequested() const
02075 {
02076 assert(IsPostProcessingSectionPresent());
02077
02078 XSD_SEQUENCE_TYPE(cp::postprocessing_type::ActionPotentialDurationMap)&
02079 apd_maps = DecideLocation( & mpUserParameters->PostProcessing(),
02080 & mpDefaultParameters->PostProcessing(),
02081 "ActionPotentialDurationMap")->get().ActionPotentialDurationMap();
02082 return (apd_maps.begin() != apd_maps.end());
02083 }
02084
02085 void HeartConfig::GetApdMaps(std::vector<std::pair<double,double> >& apd_maps) const
02086 {
02087 assert(IsApdMapsRequested());
02088 apd_maps.clear();
02089
02090 XSD_SEQUENCE_TYPE(cp::postprocessing_type::ActionPotentialDurationMap)&
02091 apd_maps_sequence = DecideLocation( & mpUserParameters->PostProcessing(),
02092 & mpDefaultParameters->PostProcessing(),
02093 "ActionPotentialDurationMap")->get().ActionPotentialDurationMap();
02094
02095 for (XSD_ITERATOR_TYPE(cp::postprocessing_type::ActionPotentialDurationMap) i = apd_maps_sequence.begin();
02096 i != apd_maps_sequence.end();
02097 ++i)
02098 {
02099 std::pair<double,double> map(i->repolarisation_percentage(),i->threshold());
02100
02101 apd_maps.push_back(map);
02102 }
02103 }
02104
02105 bool HeartConfig::IsUpstrokeTimeMapsRequested() const
02106 {
02107 assert(IsPostProcessingSectionPresent());
02108
02109 XSD_SEQUENCE_TYPE(cp::postprocessing_type::UpstrokeTimeMap)&
02110 upstroke_map = DecideLocation( & mpUserParameters->PostProcessing(),
02111 & mpDefaultParameters->PostProcessing(),
02112 "UpstrokeTimeMap")->get().UpstrokeTimeMap();
02113 return (upstroke_map.begin() != upstroke_map.end());
02114 }
02115 void HeartConfig::GetUpstrokeTimeMaps (std::vector<double>& upstroke_time_maps) const
02116 {
02117 assert(IsUpstrokeTimeMapsRequested());
02118 assert(upstroke_time_maps.size() == 0);
02119
02120 XSD_SEQUENCE_TYPE(cp::postprocessing_type::UpstrokeTimeMap)&
02121 upstroke_maps_sequence = DecideLocation( & mpUserParameters->PostProcessing(),
02122 & mpDefaultParameters->PostProcessing(),
02123 "UpstrokeTimeMap")->get().UpstrokeTimeMap();
02124
02125 for (XSD_ITERATOR_TYPE(cp::postprocessing_type::UpstrokeTimeMap) i = upstroke_maps_sequence.begin();
02126 i != upstroke_maps_sequence.end();
02127 ++i)
02128 {
02129 upstroke_time_maps.push_back(i->threshold());
02130 }
02131 }
02132
02133 bool HeartConfig::IsMaxUpstrokeVelocityMapRequested() const
02134 {
02135 assert(IsPostProcessingSectionPresent());
02136
02137 XSD_SEQUENCE_TYPE(cp::postprocessing_type::MaxUpstrokeVelocityMap)&
02138 max_upstroke_velocity_map = DecideLocation( & mpUserParameters->PostProcessing(),
02139 & mpDefaultParameters->PostProcessing(),
02140 "MaxUpstrokeVelocityMap")->get().MaxUpstrokeVelocityMap();
02141
02142 return (max_upstroke_velocity_map.begin() != max_upstroke_velocity_map.end());
02143 }
02144
02145 void HeartConfig::GetMaxUpstrokeVelocityMaps(std::vector<double>& upstroke_velocity_maps) const
02146 {
02147 assert(IsMaxUpstrokeVelocityMapRequested());
02148 assert(upstroke_velocity_maps.size() == 0);
02149
02150 XSD_SEQUENCE_TYPE(cp::postprocessing_type::MaxUpstrokeVelocityMap)&
02151 max_upstroke_velocity_maps_sequence = DecideLocation( & mpUserParameters->PostProcessing(),
02152 & mpDefaultParameters->PostProcessing(),
02153 "MaxUpstrokeVelocityMap")->get().MaxUpstrokeVelocityMap();
02154
02155 for (XSD_ITERATOR_TYPE(cp::postprocessing_type::MaxUpstrokeVelocityMap) i = max_upstroke_velocity_maps_sequence.begin();
02156 i != max_upstroke_velocity_maps_sequence.end();
02157 ++i)
02158 {
02159 upstroke_velocity_maps.push_back(i->threshold());
02160 }
02161 }
02162
02163 bool HeartConfig::IsConductionVelocityMapsRequested() const
02164 {
02165 assert(IsPostProcessingSectionPresent());
02166
02167 XSD_SEQUENCE_TYPE(cp::postprocessing_type::ConductionVelocityMap)&
02168 cond_vel_maps = DecideLocation( & mpUserParameters->PostProcessing(),
02169 & mpDefaultParameters->PostProcessing(),
02170 "ConductionVelocityMap")->get().ConductionVelocityMap();
02171 return (cond_vel_maps.begin() != cond_vel_maps.end());
02172 }
02173
02174 void HeartConfig::GetConductionVelocityMaps(std::vector<unsigned>& conduction_velocity_maps) const
02175 {
02176 assert(IsConductionVelocityMapsRequested());
02177 assert(conduction_velocity_maps.size() == 0);
02178
02179 XSD_SEQUENCE_TYPE(cp::postprocessing_type::ConductionVelocityMap)&
02180 cond_vel_maps_sequence = DecideLocation( & mpUserParameters->PostProcessing(),
02181 & mpDefaultParameters->PostProcessing(),
02182 "ConductionVelocityMap")->get().ConductionVelocityMap();
02183
02184 for (XSD_ITERATOR_TYPE(cp::postprocessing_type::ConductionVelocityMap) i = cond_vel_maps_sequence.begin();
02185 i != cond_vel_maps_sequence.end();
02186 ++i)
02187 {
02188 conduction_velocity_maps.push_back(i->origin_node());
02189 }
02190 }
02191
02192 bool HeartConfig::IsAnyNodalTimeTraceRequested() const
02193 {
02194 assert(IsPostProcessingSectionPresent());
02195
02196 XSD_SEQUENCE_TYPE(cp::postprocessing_type::TimeTraceAtNode)&
02197 requested_nodes = DecideLocation( & mpUserParameters->PostProcessing(),
02198 & mpDefaultParameters->PostProcessing(),
02199 "TimeTraceAtNode")->get().TimeTraceAtNode();
02200 return (requested_nodes.begin() != requested_nodes.end());
02201 }
02202
02203 void HeartConfig::GetNodalTimeTraceRequested(std::vector<unsigned>& rRequestedNodes) const
02204 {
02205 assert(IsAnyNodalTimeTraceRequested());
02206 assert(rRequestedNodes.size() == 0);
02207
02208 XSD_SEQUENCE_TYPE(cp::postprocessing_type::TimeTraceAtNode)&
02209 req_nodes = DecideLocation( & mpUserParameters->PostProcessing(),
02210 & mpDefaultParameters->PostProcessing(),
02211 "TimeTraceAtNode")->get().TimeTraceAtNode();
02212
02213 for (XSD_ITERATOR_TYPE(cp::postprocessing_type::TimeTraceAtNode) i = req_nodes.begin();
02214 i != req_nodes.end();
02215 ++i)
02216 {
02217 rRequestedNodes.push_back(i->node_number());
02218 }
02219 }
02220
02221
02222 bool HeartConfig::IsPseudoEcgCalculationRequested() const
02223 {
02224 assert(IsPostProcessingSectionPresent());
02225
02226 XSD_SEQUENCE_TYPE(cp::postprocessing_type::PseudoEcgElectrodePosition)&
02227 electrodes = DecideLocation( & mpUserParameters->PostProcessing(),
02228 & mpDefaultParameters->PostProcessing(),
02229 "PseudoEcgElectrodePosition")->get().PseudoEcgElectrodePosition();
02230 return (electrodes.begin() != electrodes.end());
02231 }
02232
02233 template<unsigned SPACE_DIM>
02234 void HeartConfig::GetPseudoEcgElectrodePositions(std::vector<ChastePoint<SPACE_DIM> >& rPseudoEcgElectrodePositions) const
02235 {
02236 rPseudoEcgElectrodePositions.clear();
02237 XSD_SEQUENCE_TYPE(cp::postprocessing_type::PseudoEcgElectrodePosition)&
02238 electrodes = DecideLocation( & mpUserParameters->PostProcessing(),
02239 & mpDefaultParameters->PostProcessing(),
02240 "PseudoEcgElectrodePosition")->get().PseudoEcgElectrodePosition();
02241 for (XSD_ITERATOR_TYPE(cp::postprocessing_type::PseudoEcgElectrodePosition) i = electrodes.begin();
02242 i != electrodes.end();
02243 ++i)
02244 {
02245 rPseudoEcgElectrodePositions.push_back(ChastePoint<SPACE_DIM>(i->x(), i->y(), i->z()));
02246 }
02247 }
02248
02249
02250
02251
02252
02253
02254 bool HeartConfig::IsOutputVisualizerPresent() const
02255 {
02256 CheckSimulationIsDefined("OutputVisualizer");
02257
02258 try
02259 {
02260 DecideLocation( & mpUserParameters->Simulation().get().OutputVisualizer(),
02261 & mpDefaultParameters->Simulation().get().OutputVisualizer(),
02262 "OutputVisualizer")->present();
02263
02264 return true;
02265 }
02266 catch (Exception &e)
02267 {
02268
02269 return false;
02270 }
02271 }
02272
02273 bool HeartConfig::GetVisualizeWithMeshalyzer() const
02274 {
02275 if (!IsOutputVisualizerPresent())
02276 {
02277 return true;
02278 }
02279 else
02280 {
02281 return DecideLocation( & mpUserParameters->Simulation().get().OutputVisualizer(),
02282 & mpDefaultParameters->Simulation().get().OutputVisualizer(),
02283 "OutputVisualizer")->get().meshalyzer() == cp::yesno_type::yes;
02284 }
02285 }
02286
02287 bool HeartConfig::GetVisualizeWithCmgui() const
02288 {
02289 if (!IsOutputVisualizerPresent())
02290 {
02291 return false;
02292 }
02293 else
02294 {
02295 return DecideLocation( & mpUserParameters->Simulation().get().OutputVisualizer(),
02296 & mpDefaultParameters->Simulation().get().OutputVisualizer(),
02297 "OutputVisualizer")->get().cmgui() == cp::yesno_type::yes;
02298 }
02299 }
02300
02301 bool HeartConfig::GetVisualizeWithParallelVtk() const
02302 {
02303 if (!IsOutputVisualizerPresent())
02304 {
02305 return false;
02306 }
02307 else
02308 {
02309 return DecideLocation( & mpUserParameters->Simulation().get().OutputVisualizer(),
02310 & mpDefaultParameters->Simulation().get().OutputVisualizer(),
02311 "OutputVisualizer")->get().parallel_vtk() == cp::yesno_type::yes;
02312 }
02313 }
02314
02315 bool HeartConfig::GetVisualizeWithVtk() const
02316 {
02317 if (!IsOutputVisualizerPresent())
02318 {
02319 return false;
02320 }
02321 else
02322 {
02323 return DecideLocation( & mpUserParameters->Simulation().get().OutputVisualizer(),
02324 & mpDefaultParameters->Simulation().get().OutputVisualizer(),
02325 "OutputVisualizer")->get().vtk() == cp::yesno_type::yes;
02326 }
02327 }
02328
02329 bool HeartConfig::IsElectrodesPresent() const
02330 {
02331 try
02332 {
02333 DecideLocation( & mpUserParameters->Simulation().get().Electrodes(),
02334 & mpDefaultParameters->Simulation().get().Electrodes(),
02335 "Electrodes")->present();
02336
02337 return true;
02338 }
02339 catch (Exception &e)
02340 {
02341
02342 return false;
02343 }
02344 }
02345
02346
02347
02348
02349 void HeartConfig::SetSpaceDimension(unsigned spaceDimension)
02350 {
02351 mpUserParameters->Simulation().get().SpaceDimension().set(spaceDimension);
02352 }
02353
02354 void HeartConfig::SetSimulationDuration(double simulationDuration)
02355 {
02356 XSD_CREATE_WITH_FIXED_ATTR1(cp::time_type, time, simulationDuration, "ms");
02357 mpUserParameters->Simulation().get().SimulationDuration().set(time);
02358 }
02359
02360 void HeartConfig::SetDomain(const cp::domain_type& rDomain)
02361 {
02362 mpUserParameters->Simulation().get().Domain().set(rDomain);
02363 }
02364
02365 void HeartConfig::SetDefaultIonicModel(const cp::ionic_models_available_type& rIonicModel)
02366 {
02367 cp::ionic_model_selection_type ionic_model;
02368 ionic_model.Hardcoded(rIonicModel);
02369 cp::ionic_models_type container(ionic_model);
02370 mpUserParameters->Simulation().get().IonicModels().set(container);
02371 }
02372
02373 void HeartConfig::SetSlabDimensions(double x, double y, double z, double inter_node_space)
02374 {
02375 if ( ! mpUserParameters->Simulation().get().Mesh().present())
02376 {
02377 XSD_CREATE_WITH_FIXED_ATTR(cp::mesh_type, mesh_to_load, "cm");
02378 mpUserParameters->Simulation().get().Mesh().set(mesh_to_load);
02379 }
02380
02381 cp::slab_type slab_definition(x, y, z, inter_node_space);
02382 mpUserParameters->Simulation().get().Mesh().get().Slab().set(slab_definition);
02383 }
02384
02385 void HeartConfig::SetSheetDimensions(double x, double y, double inter_node_space)
02386 {
02387 if ( ! mpUserParameters->Simulation().get().Mesh().present())
02388 {
02389 XSD_CREATE_WITH_FIXED_ATTR(cp::mesh_type, mesh_to_load, "cm");
02390 mpUserParameters->Simulation().get().Mesh().set(mesh_to_load);
02391 }
02392
02393 cp::sheet_type sheet_definition(x, y, inter_node_space);
02394 mpUserParameters->Simulation().get().Mesh().get().Sheet().set(sheet_definition);
02395 }
02396
02397 void HeartConfig::SetFibreLength(double x, double inter_node_space)
02398 {
02399 if ( ! mpUserParameters->Simulation().get().Mesh().present())
02400 {
02401 XSD_CREATE_WITH_FIXED_ATTR(cp::mesh_type, mesh_to_load, "cm");
02402 mpUserParameters->Simulation().get().Mesh().set(mesh_to_load);
02403 }
02404
02405 cp::fibre_type fibre_definition(x, inter_node_space);
02406 mpUserParameters->Simulation().get().Mesh().get().Fibre().set(fibre_definition);
02407 }
02408
02409 void HeartConfig::SetMeshFileName(std::string meshPrefix, cp::media_type fibreDefinition)
02410 {
02411 if ( ! mpUserParameters->Simulation()->Mesh().present())
02412 {
02413 XSD_CREATE_WITH_FIXED_ATTR(cp::mesh_type, mesh_to_load, "cm");
02414 mpUserParameters->Simulation()->Mesh().set(mesh_to_load);
02415 }
02416
02417 XSD_NESTED_TYPE(cp::mesh_type::LoadMesh) mesh_prefix(meshPrefix, fibreDefinition);
02418 mpUserParameters->Simulation()->Mesh()->LoadMesh().set(mesh_prefix);
02419 }
02420
02421 void HeartConfig::SetIonicModelRegions(std::vector<ChasteCuboid<3> >& rDefinedRegions,
02422 std::vector<cp::ionic_model_selection_type>& rIonicModels) const
02423 {
02424 assert(rDefinedRegions.size() == rIonicModels.size());
02425
02426 assert(mpUserParameters->Simulation()->IonicModels().present());
02427 XSD_SEQUENCE_TYPE(cp::ionic_models_type::Region)&
02428 regions = mpUserParameters->Simulation()->IonicModels()->Region();
02429 regions.clear();
02430 for (unsigned region_index=0; region_index<rDefinedRegions.size(); region_index++)
02431 {
02432 cp::point_type point_a(rDefinedRegions[region_index].rGetLowerCorner()[0],
02433 rDefinedRegions[region_index].rGetLowerCorner()[1],
02434 rDefinedRegions[region_index].rGetLowerCorner()[2]);
02435
02436 cp::point_type point_b(rDefinedRegions[region_index].rGetUpperCorner()[0],
02437 rDefinedRegions[region_index].rGetUpperCorner()[1],
02438 rDefinedRegions[region_index].rGetUpperCorner()[2]);
02439
02440 XSD_CREATE_WITH_FIXED_ATTR(cp::location_type, locn, "cm");
02441 locn.Cuboid().set(cp::box_type(point_a, point_b));
02442
02443 cp::ionic_model_region_type region(rIonicModels[region_index], locn);
02444 regions.push_back(region);
02445 }
02446 }
02447
02448 void HeartConfig::SetConductivityHeterogeneities(std::vector<ChasteCuboid<3> >& conductivityAreas,
02449 std::vector< c_vector<double,3> >& intraConductivities,
02450 std::vector< c_vector<double,3> >& extraConductivities)
02451 {
02452 assert ( conductivityAreas.size() == intraConductivities.size() );
02453 assert ( intraConductivities.size() == extraConductivities.size());
02454
02455 XSD_ANON_SEQUENCE_TYPE(cp::simulation_type, ConductivityHeterogeneities, ConductivityHeterogeneity) heterogeneities_container;
02456
02457 for (unsigned region_index=0; region_index<conductivityAreas.size(); region_index++)
02458 {
02459 cp::point_type point_a(conductivityAreas[region_index].rGetLowerCorner()[0],
02460 conductivityAreas[region_index].rGetLowerCorner()[1],
02461 conductivityAreas[region_index].rGetLowerCorner()[2]);
02462
02463 cp::point_type point_b(conductivityAreas[region_index].rGetUpperCorner()[0],
02464 conductivityAreas[region_index].rGetUpperCorner()[1],
02465 conductivityAreas[region_index].rGetUpperCorner()[2]);
02466
02467 XSD_CREATE_WITH_FIXED_ATTR(cp::location_type, locn, "cm");
02468 locn.Cuboid().set(cp::box_type(point_a, point_b));
02469 cp::conductivity_heterogeneity_type ht(locn);
02470
02471 XSD_CREATE_WITH_FIXED_ATTR3(cp::conductivities_type, intra,
02472 intraConductivities[region_index][0],
02473 intraConductivities[region_index][1],
02474 intraConductivities[region_index][2],
02475 "mS/cm");
02476
02477 ht.IntracellularConductivities(intra);
02478
02479 XSD_CREATE_WITH_FIXED_ATTR3(cp::conductivities_type, extra,
02480 extraConductivities[region_index][0],
02481 extraConductivities[region_index][1],
02482 extraConductivities[region_index][2],
02483 "mS/cm");
02484
02485 ht.ExtracellularConductivities(extra);
02486
02487 heterogeneities_container.push_back(ht);
02488 }
02489
02490 XSD_ANON_TYPE(cp::simulation_type, ConductivityHeterogeneities) heterogeneities_object;
02491 heterogeneities_object.ConductivityHeterogeneity(heterogeneities_container);
02492
02493 mpUserParameters->Simulation().get().ConductivityHeterogeneities().set(heterogeneities_object);
02494 }
02495
02496 void HeartConfig::SetConductivityHeterogeneitiesEllipsoid(std::vector<ChasteEllipsoid<3> >& conductivityAreas,
02497 std::vector< c_vector<double,3> >& intraConductivities,
02498 std::vector< c_vector<double,3> >& extraConductivities)
02499 {
02500 assert ( conductivityAreas.size() == intraConductivities.size() );
02501 assert ( intraConductivities.size() == extraConductivities.size());
02502
02503 XSD_ANON_SEQUENCE_TYPE(cp::simulation_type, ConductivityHeterogeneities, ConductivityHeterogeneity) heterogeneities_container;
02504
02505 for (unsigned region_index=0; region_index<conductivityAreas.size(); region_index++)
02506 {
02507 cp::point_type centre(conductivityAreas[region_index].rGetCentre()[0],
02508 conductivityAreas[region_index].rGetCentre()[1],
02509 conductivityAreas[region_index].rGetCentre()[2]);
02510
02511 cp::point_type radii(conductivityAreas[region_index].rGetRadii()[0],
02512 conductivityAreas[region_index].rGetRadii()[1],
02513 conductivityAreas[region_index].rGetRadii()[2]);
02514
02515 XSD_CREATE_WITH_FIXED_ATTR(cp::location_type, locn, "cm");
02516 locn.Ellipsoid().set(cp::ellipsoid_type(centre, radii));
02517 cp::conductivity_heterogeneity_type ht(locn);
02518
02519 XSD_CREATE_WITH_FIXED_ATTR3(cp::conductivities_type, intra,
02520 intraConductivities[region_index][0],
02521 intraConductivities[region_index][1],
02522 intraConductivities[region_index][2],
02523 "mS/cm");
02524
02525 ht.IntracellularConductivities(intra);
02526
02527 XSD_CREATE_WITH_FIXED_ATTR3(cp::conductivities_type, extra,
02528 extraConductivities[region_index][0],
02529 extraConductivities[region_index][1],
02530 extraConductivities[region_index][2],
02531 "mS/cm");
02532
02533 ht.ExtracellularConductivities(extra);
02534
02535 heterogeneities_container.push_back(ht);
02536 }
02537
02538 XSD_ANON_TYPE(cp::simulation_type, ConductivityHeterogeneities) heterogeneities_object;
02539 heterogeneities_object.ConductivityHeterogeneity(heterogeneities_container);
02540
02541 mpUserParameters->Simulation().get().ConductivityHeterogeneities().set(heterogeneities_object);
02542 }
02543
02544 void HeartConfig::SetOutputDirectory(const std::string& rOutputDirectory)
02545 {
02546 mpUserParameters->Simulation().get().OutputDirectory().set(rOutputDirectory);
02547 }
02548
02549 void HeartConfig::SetOutputFilenamePrefix(const std::string& rOutputFilenamePrefix)
02550 {
02551 mpUserParameters->Simulation().get().OutputFilenamePrefix().set(rOutputFilenamePrefix);
02552 }
02553
02554 void HeartConfig::SetOutputVariables(const std::vector<std::string>& rOutputVariables)
02555 {
02556 if ( ! mpUserParameters->Simulation()->OutputVariables().present())
02557 {
02558 cp::output_variables_type variables_requested;
02559 mpUserParameters->Simulation()->OutputVariables().set(variables_requested);
02560 }
02561
02562 XSD_SEQUENCE_TYPE(cp::output_variables_type::Var)&
02563 var_type_sequence = mpUserParameters->Simulation()->OutputVariables()->Var();
02564
02565 var_type_sequence.clear();
02566
02567 for (unsigned i=0; i<rOutputVariables.size(); i++)
02568 {
02569 cp::var_type temp(rOutputVariables[i]);
02570 var_type_sequence.push_back(temp);
02571 }
02572
02573
02574
02575
02576
02577
02578
02579
02580
02581
02582 }
02583
02584 void HeartConfig::SetOutputUsingOriginalNodeOrdering(bool useOriginal)
02585 {
02586
02587 mpUserParameters->Simulation().get().OutputUsingOriginalNodeOrdering().set(useOriginal? cp::yesno_type::yes : cp::yesno_type::no);
02588 }
02589
02590 void HeartConfig::SetCheckpointSimulation(bool saveSimulation, double checkpointTimestep, unsigned maxCheckpointsOnDisk)
02591 {
02592 if (saveSimulation)
02593 {
02594
02595 assert(checkpointTimestep!=-1.0 && maxCheckpointsOnDisk!=UINT_MAX);
02596
02597 XSD_CREATE_WITH_FIXED_ATTR2(cp::simulation_type::XSD_NESTED_TYPE(CheckpointSimulation),
02598 cs,
02599 checkpointTimestep,
02600 maxCheckpointsOnDisk,
02601 "ms");
02602 mpUserParameters->Simulation().get().CheckpointSimulation().set(cs);
02603 }
02604 else
02605 {
02606 mpUserParameters->Simulation().get().CheckpointSimulation().reset();
02607 }
02608
02609 CheckTimeSteps();
02610 }
02611
02612
02613 void HeartConfig::SetIntracellularConductivities(const c_vector<double, 3>& intraConductivities)
02614 {
02615 XSD_CREATE_WITH_FIXED_ATTR3(cp::conductivities_type, intra,
02616 intraConductivities[0],
02617 intraConductivities[1],
02618 intraConductivities[2],
02619 "mS/cm");
02620
02621 mpUserParameters->Physiological().IntracellularConductivities().set(intra);
02622 }
02623
02624 void HeartConfig::SetIntracellularConductivities(const c_vector<double, 2>& intraConductivities)
02625 {
02626 XSD_CREATE_WITH_FIXED_ATTR3(cp::conductivities_type, intra,
02627 intraConductivities[0],
02628 intraConductivities[1],
02629 0.0, "mS/cm");
02630
02631 mpUserParameters->Physiological().IntracellularConductivities().set(intra);
02632 }
02633
02634 void HeartConfig::SetIntracellularConductivities(const c_vector<double, 1>& intraConductivities)
02635 {
02636 XSD_CREATE_WITH_FIXED_ATTR3(cp::conductivities_type, intra,
02637 intraConductivities[0],
02638 0.0, 0.0, "mS/cm");
02639
02640 mpUserParameters->Physiological().IntracellularConductivities().set(intra);
02641 }
02642
02643 void HeartConfig::SetExtracellularConductivities(const c_vector<double, 3>& extraConductivities)
02644 {
02645 XSD_CREATE_WITH_FIXED_ATTR3(cp::conductivities_type, extra,
02646 extraConductivities[0],
02647 extraConductivities[1],
02648 extraConductivities[2],
02649 "mS/cm");
02650
02651 mpUserParameters->Physiological().ExtracellularConductivities().set(extra);
02652 }
02653
02654 void HeartConfig::SetExtracellularConductivities(const c_vector<double, 2>& extraConductivities)
02655 {
02656 XSD_CREATE_WITH_FIXED_ATTR3(cp::conductivities_type, extra,
02657 extraConductivities[0],
02658 extraConductivities[1],
02659 0.0, "mS/cm");
02660
02661 mpUserParameters->Physiological().ExtracellularConductivities().set(extra);
02662 }
02663
02664 void HeartConfig::SetExtracellularConductivities(const c_vector<double, 1>& extraConductivities)
02665 {
02666 XSD_CREATE_WITH_FIXED_ATTR3(cp::conductivities_type, extra,
02667 extraConductivities[0],
02668 0.0, 0.0, "mS/cm");
02669
02670 mpUserParameters->Physiological().ExtracellularConductivities().set(extra);
02671 }
02672
02673 void HeartConfig::SetBathConductivity(double bathConductivity)
02674 {
02675 XSD_CREATE_WITH_FIXED_ATTR1(cp::conductivity_type, cond, bathConductivity, "mS/cm");
02676 mpUserParameters->Physiological().BathConductivity().set(cond);
02677 }
02678
02679 void HeartConfig::SetBathMultipleConductivities(std::map<unsigned, double> bathConductivities)
02680 {
02682 mBathConductivities = bathConductivities;
02683 }
02684
02685
02686
02687
02688
02689
02690
02691 void HeartConfig::SetTissueAndBathIdentifiers(const std::set<unsigned>& tissueIds, const std::set<unsigned>& bathIds)
02692 {
02693 if (tissueIds.empty() || bathIds.empty() )
02694 {
02695 EXCEPTION("Identifying set must be non-empty");
02696 }
02697 std::set<unsigned> shared_identifiers;
02698 std::set_intersection(tissueIds.begin(),
02699 tissueIds.end(),
02700 bathIds.begin(),
02701 bathIds.end(),
02702 std::inserter(shared_identifiers, shared_identifiers.begin()));
02703
02704 if (!shared_identifiers.empty())
02705 {
02706 EXCEPTION("Tissue identifiers and bath identifiers overlap");
02707 }
02708 mTissueIdentifiers=tissueIds;
02709 mBathIdentifiers=bathIds;
02710 }
02711
02712 void HeartConfig::SetSurfaceAreaToVolumeRatio(double ratio)
02713 {
02714 XSD_CREATE_WITH_FIXED_ATTR1(cp::inverse_length_type, ratio_object, ratio, "1/cm");
02715 mpUserParameters->Physiological().SurfaceAreaToVolumeRatio().set(ratio_object);
02716 }
02717
02718 void HeartConfig::SetCapacitance(double capacitance)
02719 {
02720 XSD_CREATE_WITH_FIXED_ATTR1(cp::capacitance_type, capacitance_object, capacitance, "uF/cm^2");
02721 mpUserParameters->Physiological().Capacitance().set(capacitance_object);
02722 }
02723
02724
02725
02726 void HeartConfig::SetOdePdeAndPrintingTimeSteps(double odeTimeStep, double pdeTimeStep, double printingTimeStep)
02727 {
02728 XSD_CREATE_WITH_FIXED_ATTR3(cp::time_steps_type, time_steps,
02729 odeTimeStep, pdeTimeStep, printingTimeStep, "ms");
02730 mpUserParameters->Numerical().TimeSteps().set(time_steps);
02731 CheckTimeSteps();
02732 }
02733
02734 void HeartConfig::SetOdeTimeStep(double odeTimeStep)
02735 {
02736 SetOdePdeAndPrintingTimeSteps(odeTimeStep, GetPdeTimeStep(), GetPrintingTimeStep());
02737 }
02738
02739 void HeartConfig::SetPdeTimeStep(double pdeTimeStep)
02740 {
02741 SetOdePdeAndPrintingTimeSteps(GetOdeTimeStep(), pdeTimeStep, GetPrintingTimeStep());
02742 }
02743
02744 void HeartConfig::SetPrintingTimeStep(double printingTimeStep)
02745 {
02746 SetOdePdeAndPrintingTimeSteps(GetOdeTimeStep(), GetPdeTimeStep(), printingTimeStep);
02747 }
02748
02749 void HeartConfig::CheckTimeSteps() const
02750 {
02751 if (GetOdeTimeStep() <= 0)
02752 {
02753 EXCEPTION("Ode time-step should be positive");
02754 }
02755 if (GetPdeTimeStep() <= 0)
02756 {
02757 EXCEPTION("Pde time-step should be positive");
02758 }
02759 if (GetPrintingTimeStep() <= 0.0)
02760 {
02761 EXCEPTION("Printing time-step should be positive");
02762 }
02763
02764 if (GetPdeTimeStep()>GetPrintingTimeStep())
02765 {
02766 EXCEPTION("Printing time-step should not be smaller than PDE time-step");
02767 }
02768
02769 if ( !Divides(GetPdeTimeStep(), GetPrintingTimeStep()) )
02770 {
02771 EXCEPTION("Printing time-step should be a multiple of PDE time step");
02772 }
02773
02774 if ( GetOdeTimeStep() > GetPdeTimeStep() )
02775 {
02776 EXCEPTION("Ode time-step should not be greater than PDE time-step");
02777 }
02778
02779 if (GetCheckpointSimulation())
02780 {
02781 if (GetCheckpointTimestep() <= 0.0)
02782 {
02783 EXCEPTION("Checkpoint time-step should be positive");
02784 }
02785
02786 if ( !Divides(GetPrintingTimeStep(), GetCheckpointTimestep()) )
02787 {
02788 EXCEPTION("Checkpoint time-step should be a multiple of printing time-step");
02789 }
02790 }
02791 }
02792
02793
02794 void HeartConfig::SetUseRelativeTolerance(double relativeTolerance)
02795 {
02796 ENSURE_SECTION_PRESENT(mpUserParameters->Numerical().KSPTolerances(), cp::ksp_tolerances_type);
02797
02798 mpUserParameters->Numerical().KSPTolerances()->KSPAbsolute().reset();
02799 mpUserParameters->Numerical().KSPTolerances()->KSPRelative().set(relativeTolerance);
02800 }
02801
02802 void HeartConfig::SetUseAbsoluteTolerance(double absoluteTolerance)
02803 {
02804 ENSURE_SECTION_PRESENT(mpUserParameters->Numerical().KSPTolerances(), cp::ksp_tolerances_type);
02805
02806 mpUserParameters->Numerical().KSPTolerances()->KSPRelative().reset();
02807 mpUserParameters->Numerical().KSPTolerances()->KSPAbsolute().set(absoluteTolerance);
02808 }
02809
02810 void HeartConfig::SetKSPSolver(const char* kspSolver)
02811 {
02812
02813 if ( strcmp(kspSolver, "gmres") == 0)
02814 {
02815 mpUserParameters->Numerical().KSPSolver().set(cp::ksp_solver_type::gmres);
02816 return;
02817 }
02818 if ( strcmp(kspSolver, "cg") == 0)
02819 {
02820 mpUserParameters->Numerical().KSPSolver().set(cp::ksp_solver_type::cg);
02821 return;
02822 }
02823 if ( strcmp(kspSolver, "symmlq") == 0)
02824 {
02825 mpUserParameters->Numerical().KSPSolver().set(cp::ksp_solver_type::symmlq);
02826 return;
02827 }
02828 if ( strcmp(kspSolver, "chebychev") == 0)
02829 {
02830 mpUserParameters->Numerical().KSPSolver().set(cp::ksp_solver_type::chebychev);
02831 return;
02832 }
02833
02834 EXCEPTION("Unknown solver type provided");
02835 }
02836
02837 void HeartConfig::SetKSPPreconditioner(const char* kspPreconditioner)
02838 {
02839
02840 if ( strcmp(kspPreconditioner, "jacobi") == 0)
02841 {
02842 mpUserParameters->Numerical().KSPPreconditioner().set(cp::ksp_preconditioner_type::jacobi);
02843 return;
02844 }
02845 if ( strcmp(kspPreconditioner, "bjacobi") == 0)
02846 {
02847 mpUserParameters->Numerical().KSPPreconditioner().set(cp::ksp_preconditioner_type::bjacobi);
02848 return;
02849 }
02850 if ( strcmp(kspPreconditioner, "hypre") == 0)
02851 {
02852 mpUserParameters->Numerical().KSPPreconditioner().set(cp::ksp_preconditioner_type::hypre);
02853 return;
02854 }
02855 if ( strcmp(kspPreconditioner, "ml") == 0)
02856 {
02857 mpUserParameters->Numerical().KSPPreconditioner().set(cp::ksp_preconditioner_type::ml);
02858 return;
02859 }
02860 if ( strcmp(kspPreconditioner, "spai") == 0)
02861 {
02862 mpUserParameters->Numerical().KSPPreconditioner().set(cp::ksp_preconditioner_type::spai);
02863 return;
02864 }
02865 if ( strcmp(kspPreconditioner, "twolevelsblockdiagonal") == 0)
02866 {
02867 mpUserParameters->Numerical().KSPPreconditioner().set(cp::ksp_preconditioner_type::twolevelsblockdiagonal);
02868 return;
02869 }
02870 if ( strcmp(kspPreconditioner, "blockdiagonal") == 0)
02871 {
02872 mpUserParameters->Numerical().KSPPreconditioner().set(cp::ksp_preconditioner_type::blockdiagonal);
02873 return;
02874 }
02875 if ( strcmp(kspPreconditioner, "ldufactorisation") == 0)
02876 {
02877 mpUserParameters->Numerical().KSPPreconditioner().set(cp::ksp_preconditioner_type::ldufactorisation);
02878 return;
02879 }
02880 if ( strcmp(kspPreconditioner, "none") == 0)
02881 {
02882 mpUserParameters->Numerical().KSPPreconditioner().set(cp::ksp_preconditioner_type::none);
02883 return;
02884 }
02885
02886 EXCEPTION("Unknown preconditioner type provided");
02887 }
02888
02889 void HeartConfig::SetMeshPartitioning(const char* meshPartioningMethod)
02890 {
02891
02892 if ( strcmp(meshPartioningMethod, "dumb") == 0)
02893 {
02894 mpUserParameters->Numerical().MeshPartitioning().set(cp::mesh_partitioning_type::dumb);
02895 return;
02896 }
02897 if ( strcmp(meshPartioningMethod, "metis") == 0)
02898 {
02899 mpUserParameters->Numerical().MeshPartitioning().set(cp::mesh_partitioning_type::metis);
02900 return;
02901 }
02902 if ( strcmp(meshPartioningMethod, "parmetis") == 0)
02903 {
02904 mpUserParameters->Numerical().MeshPartitioning().set(cp::mesh_partitioning_type::parmetis);
02905 return;
02906 }
02907 if ( strcmp(meshPartioningMethod, "petsc") == 0)
02908 {
02909 mpUserParameters->Numerical().MeshPartitioning().set(cp::mesh_partitioning_type::petsc);
02910 return;
02911 }
02912
02913 EXCEPTION("Unknown mesh partitioning method provided");
02914 }
02915
02916 void HeartConfig::SetAdaptivityParameters(double targetError,
02917 double sigma,
02918 double maxEdgeLength,
02919 double minEdgeLength,
02920 double gradation,
02921 unsigned maxNodes,
02922 unsigned numSweeps )
02923 {
02924 if ( maxEdgeLength < minEdgeLength )
02925 {
02926 EXCEPTION("AdaptivityParameters: maxEdgeLength must be greater than minEdgeLength.");
02927 }
02928
02929 cp::adaptivity_parameters_type element(targetError,
02930 sigma,
02931 maxEdgeLength,
02932 minEdgeLength,
02933 gradation,
02934 maxNodes,
02935 numSweeps );
02936 mpUserParameters->Numerical().AdaptivityParameters().set(element);
02937
02938 if (IsAdaptivityParametersPresent())
02939 {
02940 mpUserParameters->Numerical().AdaptivityParameters().get().target_error(targetError);
02941 mpUserParameters->Numerical().AdaptivityParameters().get().sigma(sigma);
02942 mpUserParameters->Numerical().AdaptivityParameters().get().max_edge_length(maxEdgeLength);
02943 mpUserParameters->Numerical().AdaptivityParameters().get().min_edge_length(minEdgeLength);
02944 mpUserParameters->Numerical().AdaptivityParameters().get().gradation(gradation);
02945 mpUserParameters->Numerical().AdaptivityParameters().get().max_nodes(maxNodes);
02946 mpUserParameters->Numerical().AdaptivityParameters().get().num_sweeps(numSweeps);
02947 }
02948 }
02949
02950 void HeartConfig::SetTargetErrorForAdaptivity(double targetError)
02951 {
02952 SetAdaptivityParameters( targetError,
02953 GetSigmaForAdaptivity(),
02954 GetMaxEdgeLengthForAdaptivity(),
02955 GetMinEdgeLengthForAdaptivity(),
02956 GetGradationForAdaptivity(),
02957 GetMaxNodesForAdaptivity(),
02958 GetNumberOfAdaptiveSweeps() );
02959 }
02960
02961 void HeartConfig::SetSigmaForAdaptivity(double sigma)
02962 {
02963 SetAdaptivityParameters( GetTargetErrorForAdaptivity(),
02964 sigma,
02965 GetMaxEdgeLengthForAdaptivity(),
02966 GetMinEdgeLengthForAdaptivity(),
02967 GetGradationForAdaptivity(),
02968 GetMaxNodesForAdaptivity(),
02969 GetNumberOfAdaptiveSweeps() );
02970 }
02971
02972 void HeartConfig::SetMaxEdgeLengthForAdaptivity(double maxEdgeLength)
02973 {
02974 SetAdaptivityParameters( GetTargetErrorForAdaptivity(),
02975 GetSigmaForAdaptivity(),
02976 maxEdgeLength,
02977 GetMinEdgeLengthForAdaptivity(),
02978 GetGradationForAdaptivity(),
02979 GetMaxNodesForAdaptivity(),
02980 GetNumberOfAdaptiveSweeps() );
02981 }
02982
02983 void HeartConfig::SetMinEdgeLengthForAdaptivity(double minEdgeLength)
02984 {
02985 SetAdaptivityParameters( GetTargetErrorForAdaptivity(),
02986 GetSigmaForAdaptivity(),
02987 GetMaxEdgeLengthForAdaptivity(),
02988 minEdgeLength,
02989 GetGradationForAdaptivity(),
02990 GetMaxNodesForAdaptivity(),
02991 GetNumberOfAdaptiveSweeps() );
02992 }
02993
02994 void HeartConfig::SetGradationForAdaptivity(double gradation)
02995 {
02996 SetAdaptivityParameters( GetTargetErrorForAdaptivity(),
02997 GetSigmaForAdaptivity(),
02998 GetMaxEdgeLengthForAdaptivity(),
02999 GetMinEdgeLengthForAdaptivity(),
03000 gradation,
03001 GetMaxNodesForAdaptivity(),
03002 GetNumberOfAdaptiveSweeps() );
03003 }
03004
03005 void HeartConfig::SetMaxNodesForAdaptivity(unsigned maxNodes)
03006 {
03007 SetAdaptivityParameters( GetTargetErrorForAdaptivity(),
03008 GetSigmaForAdaptivity(),
03009 GetMaxEdgeLengthForAdaptivity(),
03010 GetMinEdgeLengthForAdaptivity(),
03011 GetGradationForAdaptivity(),
03012 maxNodes,
03013 GetNumberOfAdaptiveSweeps() );
03014 }
03015
03016 void HeartConfig::SetNumberOfAdaptiveSweeps(unsigned numSweeps)
03017 {
03018 SetAdaptivityParameters( GetTargetErrorForAdaptivity(),
03019 GetSigmaForAdaptivity(),
03020 GetMaxEdgeLengthForAdaptivity(),
03021 GetMinEdgeLengthForAdaptivity(),
03022 GetGradationForAdaptivity(),
03023 GetMaxNodesForAdaptivity(),
03024 numSweeps );
03025 }
03026
03027 void HeartConfig::SetApdMaps(const std::vector<std::pair<double,double> >& apdMaps)
03028 {
03029 EnsurePostProcessingSectionPresent();
03030 XSD_SEQUENCE_TYPE(cp::postprocessing_type::ActionPotentialDurationMap)& apd_maps_sequence
03031 = mpUserParameters->PostProcessing()->ActionPotentialDurationMap();
03032
03033 apd_maps_sequence.clear();
03034
03035 for (unsigned i=0; i<apdMaps.size(); i++)
03036 {
03037 XSD_CREATE_WITH_FIXED_ATTR2(cp::apd_map_type, temp,
03038 apdMaps[i].first, apdMaps[i].second,
03039 "mV");
03040 apd_maps_sequence.push_back( temp);
03041 }
03042 }
03043
03044
03045 void HeartConfig::SetUpstrokeTimeMaps (std::vector<double>& upstrokeTimeMaps)
03046 {
03047 EnsurePostProcessingSectionPresent();
03048 XSD_SEQUENCE_TYPE(cp::postprocessing_type::UpstrokeTimeMap)& var_type_sequence
03049 = mpUserParameters->PostProcessing()->UpstrokeTimeMap();
03050
03051
03052 var_type_sequence.clear();
03053
03054 for (unsigned i=0; i<upstrokeTimeMaps.size(); i++)
03055 {
03056 XSD_CREATE_WITH_FIXED_ATTR1(cp::upstrokes_map_type, temp,
03057 upstrokeTimeMaps[i],
03058 "mV");
03059 var_type_sequence.push_back(temp);
03060 }
03061 }
03062
03063 void HeartConfig::SetMaxUpstrokeVelocityMaps (std::vector<double>& maxUpstrokeVelocityMaps)
03064 {
03065 EnsurePostProcessingSectionPresent();
03066 XSD_SEQUENCE_TYPE(cp::postprocessing_type::MaxUpstrokeVelocityMap)& max_upstroke_velocity_maps_sequence
03067 = mpUserParameters->PostProcessing()->MaxUpstrokeVelocityMap();
03068
03069
03070 max_upstroke_velocity_maps_sequence.clear();
03071
03072 for (unsigned i=0; i<maxUpstrokeVelocityMaps.size(); i++)
03073 {
03074 XSD_CREATE_WITH_FIXED_ATTR1(cp::max_upstrokes_velocity_map_type, temp,
03075 maxUpstrokeVelocityMaps[i],
03076 "mV");
03077
03078
03079 max_upstroke_velocity_maps_sequence.push_back(temp);
03080 }
03081
03082 }
03083
03084 void HeartConfig::SetConductionVelocityMaps (std::vector<unsigned>& conductionVelocityMaps)
03085 {
03086 EnsurePostProcessingSectionPresent();
03087 XSD_SEQUENCE_TYPE(cp::postprocessing_type::ConductionVelocityMap)& conduction_velocity_maps_sequence
03088 = mpUserParameters->PostProcessing()->ConductionVelocityMap();
03089
03090
03091 conduction_velocity_maps_sequence.clear();
03092
03093 for (unsigned i=0; i<conductionVelocityMaps.size(); i++)
03094 {
03095 cp::conduction_velocity_map_type temp(conductionVelocityMaps[i]);
03096 conduction_velocity_maps_sequence.push_back(temp);
03097 }
03098 }
03099
03100 void HeartConfig::SetRequestedNodalTimeTraces (std::vector<unsigned>& requestedNodes)
03101 {
03102 EnsurePostProcessingSectionPresent();
03103 XSD_SEQUENCE_TYPE(cp::postprocessing_type::TimeTraceAtNode)& requested_nodes_sequence
03104 = mpUserParameters->PostProcessing()->TimeTraceAtNode();
03105
03106
03107 requested_nodes_sequence.clear();
03108
03109 for (unsigned i=0; i<requestedNodes.size(); i++)
03110 {
03111 cp::node_number_type temp(requestedNodes[i]);
03112 requested_nodes_sequence.push_back(temp);
03113 }
03114 }
03115
03116 template<unsigned SPACE_DIM>
03117 void HeartConfig::SetPseudoEcgElectrodePositions(const std::vector<ChastePoint<SPACE_DIM> >& rPseudoEcgElectrodePositions)
03118 {
03119 EnsurePostProcessingSectionPresent();
03120 XSD_SEQUENCE_TYPE(cp::postprocessing_type::PseudoEcgElectrodePosition)& electrodes_sequence
03121 = mpUserParameters->PostProcessing()->PseudoEcgElectrodePosition();
03122
03123
03124 electrodes_sequence.clear();
03125
03126 for (unsigned i=0; i<rPseudoEcgElectrodePositions.size(); i++)
03127 {
03128 cp::point_type temp(rPseudoEcgElectrodePositions[i].GetWithDefault(0),
03129 rPseudoEcgElectrodePositions[i].GetWithDefault(1),
03130 rPseudoEcgElectrodePositions[i].GetWithDefault(2));
03131 electrodes_sequence.push_back(temp);
03132 }
03133 }
03134
03135
03136
03137
03138
03139
03140 void HeartConfig::EnsureOutputVisualizerExists()
03141 {
03142 ENSURE_SECTION_PRESENT(mpUserParameters->Simulation()->OutputVisualizer(), cp::output_visualizer_type);
03143 }
03144
03145 void HeartConfig::SetVisualizeWithMeshalyzer(bool useMeshalyzer)
03146 {
03147 EnsureOutputVisualizerExists();
03148
03149 mpUserParameters->Simulation().get().OutputVisualizer().get().meshalyzer(
03150 useMeshalyzer ? cp::yesno_type::yes : cp::yesno_type::no);
03151 }
03152
03153 void HeartConfig::SetVisualizeWithCmgui(bool useCmgui)
03154 {
03155 EnsureOutputVisualizerExists();
03156
03157 mpUserParameters->Simulation().get().OutputVisualizer().get().cmgui(
03158 useCmgui ? cp::yesno_type::yes : cp::yesno_type::no);
03159 }
03160
03161 void HeartConfig::SetVisualizeWithVtk(bool useVtk)
03162 {
03163 EnsureOutputVisualizerExists();
03164
03165 mpUserParameters->Simulation().get().OutputVisualizer().get().vtk(
03166 useVtk ? cp::yesno_type::yes : cp::yesno_type::no);
03167 }
03168
03169 void HeartConfig::SetVisualizeWithParallelVtk(bool useParallelVtk)
03170 {
03171 EnsureOutputVisualizerExists();
03172
03173 mpUserParameters->Simulation().get().OutputVisualizer().get().parallel_vtk(
03174 useParallelVtk ? cp::yesno_type::yes : cp::yesno_type::no);
03175 }
03176
03177 void HeartConfig::SetElectrodeParameters(bool groundSecondElectrode,
03178 unsigned index, double magnitude,
03179 double startTime, double duration )
03180 {
03181 assert(index < 3);
03182
03183 cp::axis_type axis = cp::axis_type::x;
03184 if (index==1)
03185 {
03186 axis = cp::axis_type::y;
03187 }
03188 else if (index==2)
03189 {
03190 axis = cp::axis_type::z;
03191 }
03192
03193 XSD_CREATE_WITH_FIXED_ATTR1(cp::surface_stimulus_strength_type, strength, magnitude, "uA/cm^2");
03194 XSD_CREATE_WITH_FIXED_ATTR1(cp::time_type, start_time, startTime, "ms");
03195 XSD_CREATE_WITH_FIXED_ATTR1(cp::time_type, duration_time, duration, "ms");
03196
03197 if (!IsElectrodesPresent())
03198 {
03199 cp::electrodes_type element( groundSecondElectrode ? cp::yesno_type::yes : cp::yesno_type::no,
03200 axis,
03201 strength,
03202 start_time,
03203 duration_time );
03204 mpUserParameters->Simulation().get().Electrodes().set(element);
03205 }
03206 else
03207 {
03208 mpUserParameters->Simulation().get().Electrodes().get().GroundSecondElectrode(groundSecondElectrode ? cp::yesno_type::yes : cp::yesno_type::no);
03209 mpUserParameters->Simulation().get().Electrodes().get().PerpendicularToAxis(axis);
03210 mpUserParameters->Simulation().get().Electrodes().get().Strength(strength);
03211 mpUserParameters->Simulation().get().Electrodes().get().StartTime(start_time);
03212 mpUserParameters->Simulation().get().Electrodes().get().Duration(duration_time);
03213 }
03214 }
03215
03216 void HeartConfig::GetElectrodeParameters(bool& rGroundSecondElectrode,
03217 unsigned& rIndex, double& rMagnitude,
03218 double& rStartTime, double& rDuration )
03219 {
03220 if (!IsElectrodesPresent())
03221 {
03222 EXCEPTION("Attempted to get electrodes that have not been defined.");
03223 }
03224 else
03225 {
03226 rGroundSecondElectrode = (mpUserParameters->Simulation().get().Electrodes().get().GroundSecondElectrode()==cp::yesno_type::yes);
03227
03228 cp::axis_type axis = mpUserParameters->Simulation().get().Electrodes().get().PerpendicularToAxis();
03229 if (axis==cp::axis_type::x)
03230 {
03231 rIndex = 0;
03232 }
03233 else if (axis==cp::axis_type::y)
03234 {
03235 rIndex = 1;
03236 }
03237 else
03238 {
03239 rIndex = 2;
03240 }
03241
03242 rMagnitude = mpUserParameters->Simulation().get().Electrodes().get().Strength();
03243 rStartTime = mpUserParameters->Simulation().get().Electrodes().get().StartTime();
03244 rDuration = mpUserParameters->Simulation().get().Electrodes().get().Duration();
03245 }
03246
03247 }
03248
03249 bool HeartConfig::GetUseStateVariableInterpolation() const
03250 {
03251 try
03252 {
03253 return DecideLocation( & mpUserParameters->Numerical().UseStateVariableInterpolation(),
03254 & mpDefaultParameters->Numerical().UseStateVariableInterpolation(),
03255 "UseStateVariableInterpolation")->get() == cp::yesno_type::yes;
03256 }
03257 catch (const Exception& e)
03258 {
03259
03260 return false;
03261 }
03262 }
03263
03264 void HeartConfig::SetUseStateVariableInterpolation(bool useStateVariableInterpolation)
03265 {
03266 if (useStateVariableInterpolation)
03267 {
03268 mpUserParameters->Numerical().UseStateVariableInterpolation().set(cp::yesno_type::yes);
03269 }
03270 else
03271 {
03272 mpUserParameters->Numerical().UseStateVariableInterpolation().set(cp::yesno_type::no);
03273 }
03274 }
03275
03276 void HeartConfig::SetUseMassLumping(bool useMassLumping)
03277 {
03278 mUseMassLumping = useMassLumping;
03279 }
03280
03281 bool HeartConfig::GetUseMassLumping()
03282 {
03283 return mUseMassLumping;
03284 }
03285
03286 void HeartConfig::SetUseMassLumpingForPrecond(bool useMassLumping)
03287 {
03288 mUseMassLumpingForPrecond = useMassLumping;
03289 }
03290
03291 bool HeartConfig::GetUseMassLumpingForPrecond()
03292 {
03293 return mUseMassLumpingForPrecond;
03294 }
03295
03296 void HeartConfig::SetUseReactionDiffusionOperatorSplitting(bool useOperatorSplitting)
03297 {
03298 mUseReactionDiffusionOperatorSplitting = useOperatorSplitting;
03299 }
03300
03301 bool HeartConfig::GetUseReactionDiffusionOperatorSplitting()
03302 {
03303 return mUseReactionDiffusionOperatorSplitting;
03304 }
03305
03306 void HeartConfig::SetUseFixedNumberIterationsLinearSolver(bool useFixedNumberIterations, unsigned evaluateNumItsEveryNSolves)
03307 {
03308 mUseFixedNumberIterations = useFixedNumberIterations;
03309 mEvaluateNumItsEveryNSolves = evaluateNumItsEveryNSolves;
03310 }
03311
03312 bool HeartConfig::GetUseFixedNumberIterationsLinearSolver()
03313 {
03314 return mUseFixedNumberIterations;
03315 }
03316
03317 unsigned HeartConfig::GetEvaluateNumItsEveryNSolves()
03318 {
03319 return mEvaluateNumItsEveryNSolves;
03320 }
03321
03322
03323
03324
03325
03326
03327
03328
03329
03330 xsd::cxx::xml::dom::auto_ptr<xercesc::DOMDocument> XmlTools::ReadFileToDomDocument(
03331 const std::string& rFileName,
03332 ::xml_schema::error_handler& rErrorHandler,
03333 const ::xml_schema::properties& rProps)
03334 {
03335 using namespace xercesc;
03336 namespace xml = xsd::cxx::xml;
03337 namespace tree = xsd::cxx::tree;
03338
03339
03340 const XMLCh ls_id [] = {chLatin_L, chLatin_S, chNull};
03341 DOMImplementation* p_impl(DOMImplementationRegistry::getDOMImplementation(ls_id));
03342
03343 #if _XERCES_VERSION >= 30000
03344
03345 xml::dom::auto_ptr<DOMLSParser> p_parser(p_impl->createLSParser(DOMImplementationLS::MODE_SYNCHRONOUS, 0));
03346 DOMConfiguration* p_conf(p_parser->getDomConfig());
03347
03348
03349 p_conf->setParameter(XMLUni::fgDOMComments, false);
03350
03351
03352 p_conf->setParameter(XMLUni::fgDOMDatatypeNormalization, true);
03353
03354
03355
03356
03357
03358 p_conf->setParameter(XMLUni::fgDOMEntities, false);
03359
03360
03361 p_conf->setParameter(XMLUni::fgDOMNamespaces, true);
03362
03363
03364 p_conf->setParameter(XMLUni::fgDOMElementContentWhitespace, false);
03365
03366
03367 p_conf->setParameter(XMLUni::fgDOMValidate, true);
03368 p_conf->setParameter(XMLUni::fgXercesSchema, true);
03369 p_conf->setParameter(XMLUni::fgXercesSchemaFullChecking, false);
03370
03371 if (!rProps.schema_location().empty())
03372 {
03373 xml::string locn(rProps.schema_location());
03374 const void* p_locn(locn.c_str());
03375 p_conf->setParameter(XMLUni::fgXercesSchemaExternalSchemaLocation,
03376 const_cast<void*>(p_locn));
03377 }
03378 if (!rProps.no_namespace_schema_location().empty())
03379 {
03380 xml::string locn(rProps.no_namespace_schema_location());
03381 const void* p_locn(locn.c_str());
03382
03383 p_conf->setParameter(XMLUni::fgXercesSchemaExternalNoNameSpaceSchemaLocation,
03384 const_cast<void*>(p_locn));
03385 }
03386
03387
03388 p_conf->setParameter(XMLUni::fgXercesUserAdoptsDOMDocument, true);
03389
03390
03391 xml::dom::bits::error_handler_proxy<char> ehp(rErrorHandler);
03392 p_conf->setParameter(XMLUni::fgDOMErrorHandler, &ehp);
03393
03394 #else // _XERCES_VERSION >= 30000
03395
03396 xml::dom::auto_ptr<DOMBuilder> p_parser(p_impl->createDOMBuilder(DOMImplementationLS::MODE_SYNCHRONOUS, 0));
03397
03398 p_parser->setFeature(XMLUni::fgDOMComments, false);
03399 p_parser->setFeature(XMLUni::fgDOMDatatypeNormalization, true);
03400 p_parser->setFeature(XMLUni::fgDOMEntities, false);
03401 p_parser->setFeature(XMLUni::fgDOMNamespaces, true);
03402 p_parser->setFeature(XMLUni::fgDOMWhitespaceInElementContent, false);
03403 p_parser->setFeature(XMLUni::fgDOMValidation, true);
03404 p_parser->setFeature(XMLUni::fgXercesSchema, true);
03405 p_parser->setFeature(XMLUni::fgXercesSchemaFullChecking, false);
03406 p_parser->setFeature(XMLUni::fgXercesUserAdoptsDOMDocument, true);
03407
03408
03409 if (!rProps.schema_location().empty())
03410 {
03411 xml::string locn(rProps.schema_location());
03412 const void* p_locn(locn.c_str());
03413 p_parser->setProperty(XMLUni::fgXercesSchemaExternalSchemaLocation,
03414 const_cast<void*>(p_locn));
03415 }
03416
03417 if (!rProps.no_namespace_schema_location().empty())
03418 {
03419 xml::string locn(rProps.no_namespace_schema_location());
03420 const void* p_locn(locn.c_str());
03421
03422 p_parser->setProperty(XMLUni::fgXercesSchemaExternalNoNameSpaceSchemaLocation,
03423 const_cast<void*>(p_locn));
03424 }
03425
03426 xml::dom::bits::error_handler_proxy<char> ehp(rErrorHandler);
03427 p_parser->setErrorHandler(&ehp);
03428
03429 #endif // _XERCES_VERSION >= 30000
03430
03431
03432 xml::dom::auto_ptr<DOMDocument> p_doc(p_parser->parseURI(rFileName.c_str()));
03433
03434 if (ehp.failed())
03435 {
03436 p_doc.reset();
03437 }
03438
03439 return p_doc;
03440 }
03441
03442 #define COVERAGE_IGNORE
03443 void XmlTools::PrintNode(const std::string& rMsg, xercesc::DOMNode* pNode, bool showChildren)
03444 {
03445 std::string prefix = xsd::cxx::xml::transcode<char>(pNode->getPrefix());
03446 std::string name = xsd::cxx::xml::transcode<char>(pNode->getLocalName());
03447 std::string nsuri = xsd::cxx::xml::transcode<char>(pNode->getNamespaceURI());
03448 std::cout << rMsg << " " << pNode << " " << prefix << ":" << name << " in " << nsuri << std::endl;
03449 if (showChildren)
03450 {
03451 for (xercesc::DOMNode* p_node = pNode->getFirstChild();
03452 p_node != NULL;
03453 p_node = p_node->getNextSibling())
03454 {
03455 std::cout << " child type " << p_node->getNodeType();
03456 PrintNode("", p_node, false);
03457 }
03458 xercesc::DOMNamedNodeMap* p_attrs = pNode->getAttributes();
03459 if (p_attrs)
03460 {
03461 for (XMLSize_t i=0; i<p_attrs->getLength(); i++)
03462 {
03463 xercesc::DOMNode* p_attr = p_attrs->item(i);
03464 std::string value = xsd::cxx::xml::transcode<char>(p_attr->getNodeValue());
03465 PrintNode(" attr (" + value + ")", p_attr, false);
03466 }
03467 }
03468 }
03469 }
03470 #undef COVERAGE_IGNORE
03471
03472 xercesc::DOMElement* XmlTools::SetNamespace(xercesc::DOMDocument* pDocument,
03473 xercesc::DOMElement* pElement,
03474 const XMLCh* pNamespace)
03475 {
03476 using namespace xercesc;
03477
03478
03479 DOMNamedNodeMap* p_orig_attrs = pElement->getAttributes();
03480 std::vector<std::string> attr_values;
03481 if (p_orig_attrs)
03482 {
03483 for (XMLSize_t i=0; i<p_orig_attrs->getLength(); i++)
03484 {
03485 DOMNode* p_attr = p_orig_attrs->item(i);
03486 attr_values.push_back(xsd::cxx::xml::transcode<char>(p_attr->getNodeValue()));
03487 }
03488 }
03489 DOMElement* p_new_elt = static_cast<DOMElement*>(
03490 pDocument->renameNode(pElement, pNamespace, pElement->getLocalName()));
03491
03492
03493 if (p_orig_attrs)
03494 {
03495 DOMNamedNodeMap* p_new_attrs = p_new_elt->getAttributes();
03496 assert(p_new_attrs);
03497 assert(p_new_attrs == p_orig_attrs);
03498 assert(p_new_attrs->getLength() == attr_values.size());
03499 for (XMLSize_t i=0; i<p_new_attrs->getLength(); i++)
03500 {
03501 DOMNode* p_attr = p_new_attrs->item(i);
03502 p_attr->setNodeValue(X(attr_values[i]));
03503 }
03504 }
03505
03506
03507 for (DOMNode* p_node = p_new_elt->getFirstChild();
03508 p_node != NULL;
03509 p_node = p_node->getNextSibling())
03510 {
03511 if (p_node->getNodeType() == DOMNode::ELEMENT_NODE)
03512 {
03513 p_node = SetNamespace(pDocument, static_cast<DOMElement*>(p_node), pNamespace);
03514 }
03515 }
03516
03517 return p_new_elt;
03518 }
03519
03520 xercesc::DOMElement* XmlTools::SetNamespace(xercesc::DOMDocument* pDocument,
03521 xercesc::DOMElement* pElement,
03522 const std::string& rNamespace)
03523 {
03524 return SetNamespace(pDocument, pElement, X(rNamespace));
03525 }
03526
03527 void XmlTools::FindElements(xercesc::DOMElement* pContextElement,
03528 const std::vector<std::string>& rNames,
03529 std::vector<xercesc::DOMElement*>& rResults,
03530 unsigned depth)
03531 {
03532 xercesc::DOMNodeList* p_child_elts = pContextElement->getElementsByTagName(X(rNames[depth]));
03533 unsigned num_children = p_child_elts->getLength();
03534 for (unsigned i=0; i<num_children; i++)
03535 {
03536 xercesc::DOMElement* p_child_elt = static_cast<xercesc::DOMElement*>(p_child_elts->item(i));
03537 if (depth == rNames.size() - 1)
03538 {
03539 rResults.push_back(p_child_elt);
03540 }
03541 else
03542 {
03543 FindElements(p_child_elt, rNames, rResults, depth+1);
03544 }
03545 }
03546 }
03547
03548 std::vector<xercesc::DOMElement*> XmlTools::FindElements(xercesc::DOMElement* pContextElement,
03549 const std::string& rPath)
03550 {
03551 std::vector<xercesc::DOMElement*> results;
03552 std::vector<std::string> path;
03553 size_t start_pos = 0;
03554 size_t slash_pos = 0;
03555 while (slash_pos != std::string::npos)
03556 {
03557 slash_pos = rPath.find('/', start_pos);
03558 if (slash_pos == std::string::npos)
03559 {
03560 path.push_back(rPath.substr(start_pos));
03561 }
03562 else
03563 {
03564 path.push_back(rPath.substr(start_pos, slash_pos-start_pos));
03565 }
03566 start_pos = slash_pos + 1;
03567 }
03568 FindElements(pContextElement, path, results);
03569 return results;
03570 }
03571
03572 void XmlTools::WrapContentInElement(xercesc::DOMDocument* pDocument,
03573 xercesc::DOMElement* pElement,
03574 const XMLCh* pNewElementLocalName)
03575 {
03576 const XMLCh* p_namespace_uri = pElement->getNamespaceURI();
03577 const XMLCh* p_prefix = pElement->getPrefix();
03578 const XMLCh* p_qualified_name;
03579 if (p_prefix)
03580 {
03581 #define COVERAGE_IGNORE
03582
03583
03584 xercesc::QName qname(p_prefix, pNewElementLocalName, 0);
03585 p_qualified_name = qname.getRawName();
03586 #undef COVERAGE_IGNORE
03587 }
03588 else
03589 {
03590 p_qualified_name = pNewElementLocalName;
03591 }
03592 xercesc::DOMElement* p_wrapper_elt = pDocument->createElementNS(p_namespace_uri, p_qualified_name);
03593
03594 xercesc::DOMNodeList* p_children = pElement->getChildNodes();
03595 for (unsigned i=0; i<p_children->getLength(); i++)
03596 {
03597 xercesc::DOMNode* p_child = pElement->removeChild(p_children->item(i));
03598 p_wrapper_elt->appendChild(p_child);
03599 }
03600
03601 pElement->appendChild(p_wrapper_elt);
03602 }
03603
03604
03605 void XmlTransforms::TransformArchiveDirectory(xercesc::DOMDocument* pDocument,
03606 xercesc::DOMElement* pRootElement)
03607 {
03608 using namespace xercesc;
03609 std::vector<xercesc::DOMElement*> elts = XmlTools::FindElements(
03610 pRootElement,
03611 "ResumeSimulation/ArchiveDirectory");
03612 if (elts.size() > 0)
03613 {
03614
03615 DOMElement* p_dir_elt = elts[0];
03616
03617 p_dir_elt->setAttribute(X("relative_to"), X("chaste_test_output"));
03618
03619 }
03620 }
03621
03622 void XmlTransforms::TransformIonicModelDefinitions(xercesc::DOMDocument* pDocument,
03623 xercesc::DOMElement* pRootElement)
03624 {
03625
03626 std::vector<xercesc::DOMElement*> p_elt_list = XmlTools::FindElements(
03627 pRootElement,
03628 "Simulation/IonicModels/Default");
03629 if (p_elt_list.size() > 0)
03630 {
03631 assert(p_elt_list.size() == 1);
03632 XmlTools::WrapContentInElement(pDocument, p_elt_list[0], X("Hardcoded"));
03633
03634 p_elt_list = XmlTools::FindElements(pRootElement, "Simulation/IonicModels/Region/IonicModel");
03635 for (unsigned i=0; i<p_elt_list.size(); i++)
03636 {
03637 XmlTools::WrapContentInElement(pDocument, p_elt_list[i], X("Hardcoded"));
03638 }
03639 }
03640 }
03641
03642 void XmlTransforms::CheckForIluPreconditioner(xercesc::DOMDocument* pDocument,
03643 xercesc::DOMElement* pRootElement)
03644 {
03645 std::vector<xercesc::DOMElement*> p_elt_list = XmlTools::FindElements(
03646 pRootElement,
03647 "Numerical/KSPPreconditioner");
03648 if (p_elt_list.size() > 0)
03649 {
03650 assert(p_elt_list.size() == 1);
03651 std::string text_value = xsd::cxx::xml::transcode<char>(p_elt_list[0]->getTextContent());
03652 if (text_value == "ilu")
03653 {
03654 EXCEPTION("PETSc does not have a parallel implementation of ilu, so we no longer allow it as an option. Use bjacobi instead.");
03655 }
03656 }
03657 }
03658
03660
03662 #define COVERAGE_IGNORE //These methods are covered above with DIM=1,2,3 but the instantiations may fail spuriously
03663
03667 template void HeartConfig::GetIonicModelRegions<3u>(std::vector<boost::shared_ptr<AbstractChasteRegion<3u> > >& , std::vector<cp::ionic_model_selection_type>&) const;
03668 template void HeartConfig::GetStimuli<3u>(std::vector<boost::shared_ptr<AbstractStimulusFunction> >& , std::vector<boost::shared_ptr<AbstractChasteRegion<3u> > >& ) const;
03669 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> >*) ;
03670 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;
03671
03672 template void HeartConfig::GetIonicModelRegions<2u>(std::vector<boost::shared_ptr<AbstractChasteRegion<2u> > >& , std::vector<cp::ionic_model_selection_type>&) const;
03673 template void HeartConfig::GetStimuli<2u>(std::vector<boost::shared_ptr<AbstractStimulusFunction> >& , std::vector<boost::shared_ptr<AbstractChasteRegion<2u> > >& ) const;
03674 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> >*) ;
03675 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;
03676
03677 template void HeartConfig::GetIonicModelRegions<1u>(std::vector<boost::shared_ptr<AbstractChasteRegion<1u> > >& , std::vector<cp::ionic_model_selection_type>&) const;
03678 template void HeartConfig::GetStimuli<1u>(std::vector<boost::shared_ptr<AbstractStimulusFunction> >& , std::vector<boost::shared_ptr<AbstractChasteRegion<1u> > >& ) const;
03679 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> >*);
03680 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;
03681
03682 template void HeartConfig::GetPseudoEcgElectrodePositions(std::vector<ChastePoint<1u> >& rPseudoEcgElectrodePositions) const;
03683 template void HeartConfig::GetPseudoEcgElectrodePositions(std::vector<ChastePoint<2u> >& rPseudoEcgElectrodePositions) const;
03684 template void HeartConfig::GetPseudoEcgElectrodePositions(std::vector<ChastePoint<3u> >& rPseudoEcgElectrodePositions) const;
03685
03686 template void HeartConfig::SetPseudoEcgElectrodePositions(const std::vector<ChastePoint<1u> >& rPseudoEcgElectrodePositions);
03687 template void HeartConfig::SetPseudoEcgElectrodePositions(const std::vector<ChastePoint<2u> >& rPseudoEcgElectrodePositions);
03688 template void HeartConfig::SetPseudoEcgElectrodePositions(const std::vector<ChastePoint<3u> >& rPseudoEcgElectrodePositions);
03693 #undef COVERAGE_IGNORE //These methods are covered above with DIM=1,2,3 but the instantiations may fail spuriously
03694
03695
03696
03697 #include "SerializationExportWrapperForCpp.hpp"
03698 CHASTE_CLASS_EXPORT(HeartConfig)