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