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