Chaste Commit::29c3c4ab2bee00ddd311a035a1e522c03cbe928a
HeartConfig.cpp
1/*
2
3Copyright (c) 2005-2026, University of Oxford.
4All rights reserved.
5
6University of Oxford means the Chancellor, Masters and Scholars of the
7University of Oxford, having an administrative office at Wellington
8Square, Oxford OX1 2JD, UK.
9
10This file is part of Chaste.
11
12Redistribution and use in source and binary forms, with or without
13modification, are permitted provided that the following conditions are met:
14 * Redistributions of source code must retain the above copyright notice,
15 this list of conditions and the following disclaimer.
16 * Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19 * Neither the name of the University of Oxford nor the names of its
20 contributors may be used to endorse or promote products derived from this
21 software without specific prior written permission.
22
23THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
27LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
29GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
32OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33
34*/
35
37
39
40#include "AbstractChasteRegion.hpp"
41#include "ArchiveLocationInfo.hpp"
42#include "ChastePoint.hpp"
43#include "Exception.hpp"
44#include "FilesystemPermissions.hpp"
45#include "HeartConfig.hpp"
46#include "HeartFileFinder.hpp"
47#include "OutputFileHandler.hpp"
48#include "Version.hpp"
49#include "Warnings.hpp"
50
51#include "HeartRegionCodes.hpp"
52
53#include "RegularStimulus.hpp"
54#include "SimpleStimulus.hpp"
55
56#include <cassert>
57#include <fstream>
58#include <istream>
59#include <map>
60#include <string>
61
62#include <xsd/cxx/tree/exceptions.hxx>
63#include "XmlTools.hpp"
64using namespace xsd::cxx::tree;
65
66// Names of the types generated by XSD
67#define XSD_SEQUENCE_TYPE(base) base##_sequence
68#define XSD_ITERATOR_TYPE(base) base##_iterator
69#define XSD_NESTED_TYPE(t) t##_type
70#define XSD_ANON_TYPE(t1, t2) \
71 t1::t2##_type
72
73// These are for convenience
74#define XSD_ANON_SEQUENCE_TYPE(t1, t2, t3) \
75 XSD_SEQUENCE_TYPE(XSD_ANON_TYPE(t1, t2)::t3)
76#define XSD_ANON_ITERATOR_TYPE(t1, t2, t3) \
77 XSD_ITERATOR_TYPE(XSD_ANON_TYPE(t1, t2)::t3)
78
79// XSD doesn't allow you to set fixed attributes in the constructor, so the attr argument is ignored
80#define XSD_CREATE_WITH_FIXED_ATTR(type, name, attr) \
81 type name
82#define XSD_CREATE_WITH_FIXED_ATTR1(type, name, arg1, attr) \
83 type name(arg1)
84#define XSD_CREATE_WITH_FIXED_ATTR2(type, name, arg1, arg2, attr) \
85 type name(arg1, arg2)
86#define XSD_CREATE_WITH_FIXED_ATTR3(type, name, arg1, arg2, arg3, attr) \
87 type name(arg1, arg2, arg3)
88
92#define ENSURE_SECTION_PRESENT(location, type) \
93 if (!location.present()) \
94 { \
95 type empty_item; \
96 location.set(empty_item); \
97 }
98
99#include <boost/current_function.hpp>
107#define CHECK_EXISTS(test, path) \
108 do \
109 { \
110 if (!test) \
111 { \
112 EXCEPTION("No XML element " << path << " found in parameters when calling '" \
113 << BOOST_CURRENT_FUNCTION << "'"); \
114 } \
115 } while (false)
116
122{
123public:
131 static void TransformIonicModelDefinitions(xercesc::DOMDocument* pDocument,
132 xercesc::DOMElement* pRootElement);
133
142 static void TransformArchiveDirectory(xercesc::DOMDocument* pDocument,
143 xercesc::DOMElement* pRootElement);
144
152 static void CheckForIluPreconditioner(xercesc::DOMDocument* pDocument,
153 xercesc::DOMElement* pRootElement);
154
162 static void MoveConductivityHeterogeneities(xercesc::DOMDocument* pDocument,
163 xercesc::DOMElement* pRootElement);
164
172 static void SetDefaultVisualizer(xercesc::DOMDocument* pDocument,
173 xercesc::DOMElement* pRootElement);
174};
175
176//
177// Default settings
178//
180
181//
182// Definition of static member variables
183//
184boost::shared_ptr<HeartConfig> HeartConfig::mpInstance;
185
186//
187// Methods
188//
189
191{
192 if (mpInstance.get() == NULL)
193 {
194 mpInstance.reset(new HeartConfig);
195 }
196 return mpInstance.get();
197}
198
200 : mUseMassLumping(false),
201 mUseMassLumpingForPrecond(false),
202 mUseFixedNumberIterations(false),
203 mEvaluateNumItsEveryNSolves(UINT_MAX)
204{
205 assert(mpInstance.get() == NULL);
208
210 //CheckTimeSteps(); // necessity of this line of code is not tested -- remove with caution!
211
212 //initialise the member variable of the layers
213 mEpiFraction = -1.0;
214 mEndoFraction = -1.0;
215 mMidFraction = -1.0;
217 // initialise to senseless values (these should be only 0, 1 and 2)
218 // note: the 'minus 3' is for checking purposes as we need to add 0, 1 or 2 to this initial value
219 // and UINT_MAX+1 seems to be 0
220 mIndexMid = UINT_MAX - 3u;
221 mIndexEpi = UINT_MAX - 3u;
222 mIndexEndo = UINT_MAX - 3u;
223
225
227 mTissueIdentifiers.insert(0);
228 mBathIdentifiers.insert(1);
229}
230
234
235void HeartConfig::Write(bool useArchiveLocationInfo, std::string subfolderName)
236{
237 //Output file
238 std::string output_dirname;
239 if (useArchiveLocationInfo)
240 {
242 }
243 else
244 {
245 OutputFileHandler handler(GetOutputDirectory() + "/" + subfolderName, false);
246 output_dirname = handler.GetOutputDirectoryFullPath();
247 }
248
249 // Sometimes this method is called collectively, sometimes not,
250 // in any case the below file operations only want to be performed by
251 // the master - so exit. Caller takes responsibility for nice
252 // exception handling.
254 {
255 return;
256 }
257
258 out_stream p_parameters_file(new std::ofstream((output_dirname + "ChasteParameters.xml").c_str()));
259
260 if (!p_parameters_file->is_open())
261 {
262 EXCEPTION("Could not open XML file in HeartConfig");
263 }
264 FilesystemPermissions::SetFilePermissions(output_dirname + "ChasteParameters.xml");
265
266 //Schema map
267 //Note - this location is relative to where we are storing the xml
268 ::xml_schema::namespace_infomap map;
269 // Release 1.1 (and earlier) didn't use a namespace
270 map[""].schema = "ChasteParameters_1_1.xsd";
271 // Later releases use namespaces of the form https://chaste.comlab.ox.ac.uk/nss/parameters/N_M
272 map["cp20"].name = "https://chaste.comlab.ox.ac.uk/nss/parameters/2_0";
273 map["cp20"].schema = "ChasteParameters_2_0.xsd";
274 map["cp21"].name = "https://chaste.comlab.ox.ac.uk/nss/parameters/2_1";
275 map["cp21"].schema = "ChasteParameters_2_1.xsd";
276 map["cp22"].name = "https://chaste.comlab.ox.ac.uk/nss/parameters/2_2";
277 map["cp22"].schema = "ChasteParameters_2_2.xsd";
278 map["cp23"].name = "https://chaste.comlab.ox.ac.uk/nss/parameters/2_3";
279 map["cp23"].schema = "ChasteParameters_2_3.xsd";
280 map["cp30"].name = "https://chaste.comlab.ox.ac.uk/nss/parameters/3_0";
281 map["cp30"].schema = "ChasteParameters_3_0.xsd";
282 map["cp31"].name = "https://chaste.comlab.ox.ac.uk/nss/parameters/3_1";
283 map["cp31"].schema = "ChasteParameters_3_1.xsd";
284 map["cp33"].name = "https://chaste.comlab.ox.ac.uk/nss/parameters/3_3";
285 map["cp33"].schema = "ChasteParameters_3_3.xsd";
286 map["cp34"].name = "https://chaste.comlab.ox.ac.uk/nss/parameters/3_4";
287 map["cp34"].schema = "ChasteParameters_3_4.xsd";
288 // We use 'cp' as prefix for the latest version to avoid having to change saved
289 // versions for comparison at every release.
290 map["cp"].name = "https://chaste.comlab.ox.ac.uk/nss/parameters/2017_1";
291 map["cp"].schema = "ChasteParameters_2017_1.xsd";
292
293 cp::ChasteParameters(*p_parameters_file, *mpParameters, map);
294
295 // If we're archiving, try to save a copy of the latest schema too
296 if (useArchiveLocationInfo)
297 {
298 CopySchema(output_dirname);
299 }
300}
301
303{
304 /*
305 * This method implements the logic required by HeartConfig to be able to handle resuming a simulation via the executable.
306 *
307 * When the control reaches the method mpParameters points to the file specified as resuming parameters.
308 * However SetParametersFile() will set this variable to point to the archived parameters.
309 *
310 * We make a temporary copy of mpParameters so we don't lose its content.
311 * At the end of the method we update the new mpParameters with the resuming parameters.
312 */
313 assert(mpParameters.use_count() > 0);
314 boost::shared_ptr<cp::chaste_parameters_type> p_new_parameters = mpParameters;
315
316 /*
317 * When we unarchive a simulation, we load the old parameters file in order to inherit things such
318 * as default cell model, stimuli, heterogeneities, ... This has the side effect of inheriting the
319 * <CheckpointSimulation> element (if defined).
320 *
321 * We disable checkpointing definition coming from the unarchived config file. We will enable it again
322 * if defined in the resume config file.
323 */
324 std::string parameters_filename_xml = ArchiveLocationInfo::GetArchiveDirectory() + "ChasteParameters.xml";
325 mpParameters = ReadFile(parameters_filename_xml);
326 mParametersFilePath.SetPath(parameters_filename_xml, RelativeTo::AbsoluteOrCwd);
327
328 // Release 3.0 and earlier wrote a separate defaults file in the checkpoint
329 std::string defaults_filename_xml = ArchiveLocationInfo::GetArchiveDirectory() + "ChasteDefaults.xml";
330 if (FileFinder(defaults_filename_xml).Exists())
331 {
332 boost::shared_ptr<cp::chaste_parameters_type> p_defaults = ReadFile(defaults_filename_xml);
333 MergeDefaults(mpParameters, p_defaults);
334 }
335
337
338 // If we are resuming a simulation, some parameters can be altered at this point.
339 if (p_new_parameters->ResumeSimulation().present())
340 {
341 UpdateParametersFromResumeSimulation(p_new_parameters);
342 }
343
344 CheckTimeSteps(); // For consistency with SetParametersFile
345}
346
347void HeartConfig::CopySchema(const std::string& rToDirectory)
348{
349 // N.B. This method should only be called by the master process,
350 // in a situation where it can handle EXCEPTION()s nicely, e.g.
351 // TRY_IF_MASTER(CopySchema(...));
352
353 std::string schema_name("ChasteParameters_2017_1.xsd");
354 FileFinder schema_location("heart/src/io/" + schema_name, RelativeTo::ChasteSourceRoot);
355 if (!schema_location.Exists())
356 {
357 // Try a relative path instead
358 schema_location.SetPath(schema_name, RelativeTo::CWD);
359 if (!schema_location.Exists())
360 {
361 // Warn the user
362 std::string message("Unable to locate schema file " + schema_name + ". You will need to ensure it is available when resuming from the checkpoint.");
363 WARN_ONCE_ONLY(message);
364 }
365 }
366 if (schema_location.Exists())
367 {
368 FileFinder output_directory(rToDirectory, RelativeTo::Absolute);
369 schema_location.CopyTo(output_directory);
370 }
371}
372
374{
375 mSchemaLocations.clear();
376 // Location of schemas in the source tree
377 std::string root_dir = std::string(ChasteBuildInfo::GetRootDir()) + "/heart/src/io/";
378 // Release 1.1 (and earlier) didn't use a namespace
379 mSchemaLocations[""] = root_dir + "ChasteParameters_1_1.xsd";
380 // Later releases use namespaces of the form https://chaste.comlab.ox.ac.uk/nss/parameters/N_M
381 mSchemaLocations["https://chaste.comlab.ox.ac.uk/nss/parameters/2_0"] = root_dir + "ChasteParameters_2_0.xsd";
382 mSchemaLocations["https://chaste.comlab.ox.ac.uk/nss/parameters/2_1"] = root_dir + "ChasteParameters_2_1.xsd";
383 mSchemaLocations["https://chaste.comlab.ox.ac.uk/nss/parameters/2_2"] = root_dir + "ChasteParameters_2_2.xsd";
384 mSchemaLocations["https://chaste.comlab.ox.ac.uk/nss/parameters/2_3"] = root_dir + "ChasteParameters_2_3.xsd";
385 mSchemaLocations["https://chaste.comlab.ox.ac.uk/nss/parameters/3_0"] = root_dir + "ChasteParameters_3_0.xsd";
386 mSchemaLocations["https://chaste.comlab.ox.ac.uk/nss/parameters/3_1"] = root_dir + "ChasteParameters_3_1.xsd";
387 mSchemaLocations["https://chaste.comlab.ox.ac.uk/nss/parameters/3_3"] = root_dir + "ChasteParameters_3_3.xsd";
388 mSchemaLocations["https://chaste.comlab.ox.ac.uk/nss/parameters/3_4"] = root_dir + "ChasteParameters_3_4.xsd";
389 mSchemaLocations["https://chaste.comlab.ox.ac.uk/nss/parameters/2017_1"] = root_dir + "ChasteParameters_2017_1.xsd";
390}
391
392unsigned HeartConfig::GetVersionFromNamespace(const std::string& rNamespaceUri)
393{
394 unsigned version_major = 0;
395 unsigned version_minor = 0;
396 if (rNamespaceUri == "")
397 {
398 version_major = 1;
399 version_minor = 1;
400 }
401 else
402 {
403 std::string uri_base("https://chaste.comlab.ox.ac.uk/nss/parameters/");
404 if (rNamespaceUri.substr(0, uri_base.length()) == uri_base)
405 {
406 std::istringstream version_string(rNamespaceUri.substr(uri_base.length()));
407 version_string >> version_major;
408 version_string.ignore(1);
409 version_string >> version_minor;
410 if (version_string.fail())
411 {
412 version_major = 0;
413 version_minor = 0;
414 }
415 }
416 }
417
418 unsigned version = version_major * 1000 + version_minor;
419 if (version == 0)
420 {
421 EXCEPTION(rNamespaceUri + " is not a recognised Chaste parameters namespace.");
422 }
423 return version;
424}
425
427{
428 mSchemaLocations = rSchemaLocations;
430}
431
432void HeartConfig::SetUseFixedSchemaLocation(bool useFixedSchemaLocation)
433{
434 mUseFixedSchemaLocation = useFixedSchemaLocation;
435}
436
437boost::shared_ptr<cp::chaste_parameters_type> HeartConfig::ReadFile(const std::string& rFileName)
438{
439 // Determine whether to use the schema path given in the input XML, or our own schema
440 ::xml_schema::properties props;
442 {
443 for (SchemaLocationsMap::iterator it = mSchemaLocations.begin();
444 it != mSchemaLocations.end();
445 ++it)
446 {
447 if (it->first == "")
448 {
449 props.no_namespace_schema_location(XmlTools::EscapeSpaces(it->second));
450 }
451 else
452 {
453 props.schema_location(it->first, XmlTools::EscapeSpaces(it->second));
454 }
455 }
456 }
457
458 // Get the parameters using the method 'ChasteParameters(rFileName)',
459 // which returns a std::unique_ptr. We convert to a shared_ptr for easier semantics.
460 try
461 {
462 // Make sure Xerces finalization happens
463 XmlTools::Finalizer finalizer(false);
464 // Parse XML to DOM
465 auto p_doc = XmlTools::ReadXmlFile(rFileName, props);
466 // Test the namespace on the root element
467 xercesc::DOMElement* p_root_elt = p_doc->getDocumentElement();
468 std::string namespace_uri(X2C(p_root_elt->getNamespaceURI()));
469 const unsigned version = GetVersionFromNamespace(namespace_uri);
470 if (version < 2000) // Changes made in release 2.0
471 {
472 XmlTransforms::TransformIonicModelDefinitions(p_doc.get(), p_root_elt);
473 }
474 if (version < 2001) // Changes made in release 2.1
475 {
476 XmlTransforms::TransformArchiveDirectory(p_doc.get(), p_root_elt);
477 XmlTransforms::CheckForIluPreconditioner(p_doc.get(), p_root_elt);
478 }
479 if (version < 3001) // Changes made in release 3.1
480 {
481 XmlTransforms::MoveConductivityHeterogeneities(p_doc.get(), p_root_elt);
482 }
483 if (version < 3003) // Changes made in release 3.3
484 {
485 XmlTransforms::SetDefaultVisualizer(p_doc.get(), p_root_elt);
486 }
487 if (version < 3004) // Not the latest in release 3.4
488 {
489 XmlTools::SetNamespace(p_doc.get(), p_root_elt, "https://chaste.comlab.ox.ac.uk/nss/parameters/3_4");
490 }
491 if (version < 2017001) // Not the latest release
492 {
493 XmlTools::SetNamespace(p_doc.get(), p_root_elt, "https://chaste.comlab.ox.ac.uk/nss/parameters/2017_1");
494 }
495 // Parse DOM to object model
496 boost::shared_ptr<cp::chaste_parameters_type> p_params(cp::ChasteParameters(*p_doc, ::xml_schema::flags::dont_initialize, props));
497 // Get rid of the DOM stuff
498 p_doc.reset();
499
500 return boost::shared_ptr<cp::chaste_parameters_type>(p_params);
501 }
502 catch (const xml_schema::exception& e)
503 {
504 std::cerr << e << std::endl;
505 // Make sure we don't store invalid parameters
506 mpParameters.reset();
507 EXCEPTION("XML parsing error in configuration file: " + rFileName);
508 }
509 catch (...)
510 {
511 // Make sure we don't store invalid parameters
512 mpParameters.reset();
513 throw;
514 }
515}
516
517void HeartConfig::SetParametersFile(const std::string& rFileName)
518{
519 mpParameters = ReadFile(rFileName);
522
524 {
525 CheckTimeSteps(); // Resume files might not have time steps defined
526 }
527}
528
533
534void HeartConfig::UpdateParametersFromResumeSimulation(boost::shared_ptr<cp::chaste_parameters_type> pResumeParameters)
535{
536 // Check for user foolishness
537 if ((pResumeParameters->ResumeSimulation()->SpaceDimension() != HeartConfig::Instance()->GetSpaceDimension())
538 || (pResumeParameters->ResumeSimulation()->Domain() != HeartConfig::Instance()->GetDomain()))
539 {
540 EXCEPTION("Problem type and space dimension should match when restarting a simulation.");
541 }
542
543 // New simulation duration
544 HeartConfig::Instance()->SetSimulationDuration(pResumeParameters->ResumeSimulation()->SimulationDuration());
545
546 // Stimulus definition. For these we always replace any previous definitions (at least for now...)
547 if (pResumeParameters->ResumeSimulation()->Stimuli().present())
548 {
549 mpParameters->Simulation()->Stimuli().set(pResumeParameters->ResumeSimulation()->Stimuli().get());
550 }
551
552 // Cell heterogeneities. Note that while we copy the elements here, other code in CardiacSimulation actually updates
553 // the loaded simulation to take account of the new settings.
554 if (pResumeParameters->ResumeSimulation()->CellHeterogeneities().present())
555 {
556 if (!mpParameters->Simulation()->CellHeterogeneities().present())
557 {
558 // Original parameters had no heterogeneities, so just copy the whole element
559 mpParameters->Simulation()->CellHeterogeneities().set(pResumeParameters->ResumeSimulation()->CellHeterogeneities().get());
560 }
561 else
562 {
563 // Need to append the new heterogeneity defitions to the original sequence
564 XSD_SEQUENCE_TYPE(cp::cell_heterogeneities_type::CellHeterogeneity)& new_seq = pResumeParameters->ResumeSimulation()->CellHeterogeneities()->CellHeterogeneity();
565 XSD_SEQUENCE_TYPE(cp::cell_heterogeneities_type::CellHeterogeneity)& orig_seq = mpParameters->Simulation()->CellHeterogeneities()->CellHeterogeneity();
566 for (XSD_ITERATOR_TYPE(cp::cell_heterogeneities_type::CellHeterogeneity) i = new_seq.begin();
567 i != new_seq.end();
568 ++i)
569 {
570 orig_seq.push_back(*i);
571 }
572 }
573 }
574
575 // Whether to checkpoint the resumed simulation
576 if (pResumeParameters->ResumeSimulation()->CheckpointSimulation().present())
577 {
579 pResumeParameters->ResumeSimulation()->CheckpointSimulation()->timestep(),
580 pResumeParameters->ResumeSimulation()->CheckpointSimulation()->max_checkpoints_on_disk());
581 }
582
583 //Visualization parameters are no longer compulsory
584 if (pResumeParameters->ResumeSimulation()->OutputVisualizer().present())
585 {
586 HeartConfig::Instance()->SetVisualizeWithParallelVtk(pResumeParameters->ResumeSimulation()->OutputVisualizer()->parallel_vtk() == cp::yesno_type::yes);
587 HeartConfig::Instance()->SetVisualizeWithVtk(pResumeParameters->ResumeSimulation()->OutputVisualizer()->vtk() == cp::yesno_type::yes);
588 HeartConfig::Instance()->SetVisualizeWithCmgui(pResumeParameters->ResumeSimulation()->OutputVisualizer()->cmgui() == cp::yesno_type::yes);
589 HeartConfig::Instance()->SetVisualizeWithMeshalyzer(pResumeParameters->ResumeSimulation()->OutputVisualizer()->meshalyzer() == cp::yesno_type::yes);
590 }
591
592 // Numerical parameters may be overridden
593 {
594 cp::numerical_type& r_resume = pResumeParameters->Numerical();
595 cp::numerical_type& r_user = mpParameters->Numerical();
596 if (r_resume.TimeSteps().present())
597 {
598 r_user.TimeSteps().set(r_resume.TimeSteps().get());
599 }
600 if (r_resume.KSPTolerances().present())
601 {
602 r_user.KSPTolerances().set(r_resume.KSPTolerances().get());
603 }
604 if (r_resume.KSPSolver().present())
605 {
606 r_user.KSPSolver().set(r_resume.KSPSolver().get());
607 }
608 if (r_resume.KSPPreconditioner().present())
609 {
610 r_user.KSPPreconditioner().set(r_resume.KSPPreconditioner().get());
611 }
612 if (r_resume.AdaptivityParameters().present())
613 {
614 r_user.AdaptivityParameters().set(r_resume.AdaptivityParameters().get());
615 }
616 }
617
618 // Post-processing parameters may be overridden
619 if (pResumeParameters->PostProcessing().present())
620 {
622 cp::postprocessing_type& r_resume = pResumeParameters->PostProcessing().get();
623 cp::postprocessing_type& r_user = mpParameters->PostProcessing().get();
624 if (!r_resume.ActionPotentialDurationMap().empty())
625 {
626 r_user.ActionPotentialDurationMap() = r_resume.ActionPotentialDurationMap();
627 }
628 if (!r_resume.UpstrokeTimeMap().empty())
629 {
630 r_user.UpstrokeTimeMap() = r_resume.UpstrokeTimeMap();
631 }
632 if (!r_resume.MaxUpstrokeVelocityMap().empty())
633 {
634 r_user.MaxUpstrokeVelocityMap() = r_resume.MaxUpstrokeVelocityMap();
635 }
636 if (!r_resume.ConductionVelocityMap().empty())
637 {
638 r_user.ConductionVelocityMap() = r_resume.ConductionVelocityMap();
639 }
640 if (!r_resume.PseudoEcgElectrodePosition().empty())
641 {
642 r_user.PseudoEcgElectrodePosition() = r_resume.PseudoEcgElectrodePosition();
643 }
644 }
645}
646
648{
649 // Throw it away first, so that mpInstance is NULL when we...
650 mpInstance.reset();
651 // ...make a new one
652 mpInstance.reset(new HeartConfig);
653}
654
656{
657 return mpParameters->Simulation().present();
658}
659
661{
662 return mpParameters->ResumeSimulation().present();
663}
664
665void HeartConfig::CheckSimulationIsDefined(std::string callingMethod) const
666{
668 {
669 EXCEPTION(callingMethod + " information is not available in a resumed simulation.");
670 }
671}
672
673void HeartConfig::CheckResumeSimulationIsDefined(std::string callingMethod) const
674{
676 {
677 EXCEPTION(callingMethod + " information is not available in a standard (non-resumed) simulation.");
678 }
679}
680
682{
684 {
685 CHECK_EXISTS(mpParameters->Simulation()->SpaceDimension().present(), "Simulation/SpaceDimension");
686 return mpParameters->Simulation()->SpaceDimension().get();
687 }
688 else
689 {
690 return mpParameters->ResumeSimulation()->SpaceDimension();
691 }
692}
693
695{
697 {
698 CHECK_EXISTS(mpParameters->Simulation()->SimulationDuration().present(), "Simulation/SimulationDuration");
699 return mpParameters->Simulation()->SimulationDuration().get();
700 }
701 else // IsSimulationResumed
702 {
703 return mpParameters->ResumeSimulation()->SimulationDuration();
704 }
705}
706
707cp::domain_type HeartConfig::GetDomain() const
708{
710 {
711 CHECK_EXISTS(mpParameters->Simulation()->Domain().present(), "Simulation/Domain");
712 return mpParameters->Simulation()->Domain().get();
713 }
714 else
715 {
716 return mpParameters->ResumeSimulation()->Domain();
717 }
718}
719
720cp::ionic_model_selection_type HeartConfig::GetDefaultIonicModel() const
721{
722 CheckSimulationIsDefined("DefaultIonicModel");
723
724 return mpParameters->Simulation()->IonicModels()->Default();
725}
726
727template <unsigned DIM>
728void HeartConfig::GetIonicModelRegions(std::vector<boost::shared_ptr<AbstractChasteRegion<DIM> > >& definedRegions,
729 std::vector<cp::ionic_model_selection_type>& ionicModels) const
730{
731 CheckSimulationIsDefined("IonicModelRegions");
732 definedRegions.clear();
733 ionicModels.clear();
734
735 XSD_SEQUENCE_TYPE(cp::ionic_models_type::Region)& regions = mpParameters->Simulation()->IonicModels()->Region();
736
737 for (XSD_ITERATOR_TYPE(cp::ionic_models_type::Region) i = regions.begin();
738 i != regions.end();
739 ++i)
740 {
741 cp::ionic_model_region_type ionic_model_region(*i);
742
743 if (ionic_model_region.Location().Cuboid().present() || ionic_model_region.Location().Ellipsoid().present())
744 {
745 if (ionic_model_region.Location().Cuboid().present())
746 {
747 cp::point_type point_a = ionic_model_region.Location().Cuboid()->LowerCoordinates();
748 cp::point_type point_b = ionic_model_region.Location().Cuboid()->UpperCoordinates();
749
750 switch (DIM)
751 {
752 case 1:
753 {
754 ChastePoint<DIM> chaste_point_a(point_a.x());
755 ChastePoint<DIM> chaste_point_b(point_b.x());
756 definedRegions.push_back(boost::shared_ptr<AbstractChasteRegion<DIM> >(new ChasteCuboid<DIM>(chaste_point_a, chaste_point_b)));
757 break;
758 }
759 case 2:
760 {
761 ChastePoint<DIM> chaste_point_a(point_a.x(), point_a.y());
762 ChastePoint<DIM> chaste_point_b(point_b.x(), point_b.y());
763 definedRegions.push_back(boost::shared_ptr<AbstractChasteRegion<DIM> >(new ChasteCuboid<DIM>(chaste_point_a, chaste_point_b)));
764 break;
765 }
766 case 3:
767 {
768 ChastePoint<DIM> chaste_point_a(point_a.x(), point_a.y(), point_a.z());
769 ChastePoint<DIM> chaste_point_b(point_b.x(), point_b.y(), point_b.z());
770 definedRegions.push_back(boost::shared_ptr<AbstractChasteRegion<DIM> >(new ChasteCuboid<DIM>(chaste_point_a, chaste_point_b)));
771 break;
772 }
773 default:
775 break;
776 }
777 }
778 else if (ionic_model_region.Location().Ellipsoid().present())
779 {
780 cp::point_type centre = ionic_model_region.Location().Ellipsoid()->Centre();
781 cp::point_type radii = ionic_model_region.Location().Ellipsoid()->Radii();
782 switch (DIM)
783 {
784 case 1:
785 {
786 ChastePoint<DIM> chaste_point_a(centre.x());
787 ChastePoint<DIM> chaste_point_b(radii.x());
788 definedRegions.push_back(boost::shared_ptr<AbstractChasteRegion<DIM> >(new ChasteEllipsoid<DIM>(chaste_point_a, chaste_point_b)));
789 break;
790 }
791 case 2:
792 {
793 ChastePoint<DIM> chaste_point_a(centre.x(), centre.y());
794 ChastePoint<DIM> chaste_point_b(radii.x(), radii.y());
795 definedRegions.push_back(boost::shared_ptr<AbstractChasteRegion<DIM> >(new ChasteEllipsoid<DIM>(chaste_point_a, chaste_point_b)));
796 break;
797 }
798 case 3:
799 {
800 ChastePoint<DIM> chaste_point_a(centre.x(), centre.y(), centre.z());
801 ChastePoint<DIM> chaste_point_b(radii.x(), radii.y(), radii.z());
802 definedRegions.push_back(boost::shared_ptr<AbstractChasteRegion<DIM> >(new ChasteEllipsoid<DIM>(chaste_point_a, chaste_point_b)));
803 break;
804 }
805 default:
806 {
808 break;
809 }
810 }
811 }
812 else
813 {
815 }
816
817 ionicModels.push_back(ionic_model_region.IonicModel());
818 }
819 else if (ionic_model_region.Location().EpiLayer().present() || ionic_model_region.Location().MidLayer().present() || ionic_model_region.Location().EndoLayer().present())
820 {
822 EXCEPTION("Definition of transmural layers is not yet supported for defining different ionic models, please use cuboids instead");
823 }
824 else
825 {
826 EXCEPTION("Invalid region type for ionic model definition");
827 }
828 }
829}
830
832{
834 return mpParameters->Simulation()->Mesh().present();
835}
836
838{
840 CHECK_EXISTS(IsMeshProvided(), "Simulation/Mesh");
841 cp::mesh_type mesh = mpParameters->Simulation()->Mesh().get();
842 return (mesh.Slab().present() || mesh.Sheet().present() || mesh.Fibre().present());
843}
844
846{
848 CHECK_EXISTS(IsMeshProvided(), "Simulation/Mesh");
849 cp::mesh_type mesh = mpParameters->Simulation()->Mesh().get();
850 return (mesh.Slab().present());
851}
852
854{
856 CHECK_EXISTS(IsMeshProvided(), "Simulation/Mesh");
857 cp::mesh_type mesh = mpParameters->Simulation()->Mesh().get();
858 return (mesh.Sheet().present());
859}
860
862{
864 CHECK_EXISTS(IsMeshProvided(), "Simulation/Mesh");
865 cp::mesh_type mesh = mpParameters->Simulation()->Mesh().get();
866 return (mesh.Fibre().present());
867}
868
870{
872 CHECK_EXISTS(IsMeshProvided(), "Simulation/Mesh");
873 return (mpParameters->Simulation()->Mesh()->LoadMesh().present());
874}
875
876void HeartConfig::GetSlabDimensions(c_vector<double, 3>& slabDimensions) const
877{
879
880 if (GetSpaceDimension() != 3 || !GetCreateSlab())
881 {
882 EXCEPTION("Tissue slabs can only be defined in 3D");
883 }
884
885 optional<cp::slab_type, false> slab_dimensions = mpParameters->Simulation()->Mesh()->Slab();
886
887 slabDimensions[0] = slab_dimensions->x();
888 slabDimensions[1] = slab_dimensions->y();
889 slabDimensions[2] = slab_dimensions->z();
890}
891
892void HeartConfig::GetSheetDimensions(c_vector<double, 2>& sheetDimensions) const
893{
895
896 if (GetSpaceDimension() != 2 || !GetCreateSheet())
897 {
898 EXCEPTION("Tissue sheets can only be defined in 2D");
899 }
900
901 optional<cp::sheet_type, false> sheet_dimensions = mpParameters->Simulation()->Mesh()->Sheet();
902
903 sheetDimensions[0] = sheet_dimensions->x();
904 sheetDimensions[1] = sheet_dimensions->y();
905}
906
907void HeartConfig::GetFibreLength(c_vector<double, 1>& fibreLength) const
908{
910
911 if (GetSpaceDimension() != 1 || !GetCreateFibre())
912 {
913 EXCEPTION("Tissue fibres can only be defined in 1D");
914 }
915
916 optional<cp::fibre_type, false> fibre_length = mpParameters->Simulation()->Mesh()->Fibre();
917
918 fibreLength[0] = fibre_length->x();
919}
920
922{
923 CheckSimulationIsDefined("InterNodeSpace");
924
925 switch (GetSpaceDimension())
926 {
927 case 3:
928 CHECK_EXISTS(GetCreateSlab(), "Simulation/Mesh/Slab");
929 return mpParameters->Simulation()->Mesh()->Slab()->inter_node_space();
930 break;
931 case 2:
932 CHECK_EXISTS(GetCreateSheet(), "Simulation/Mesh/Sheet");
933 return mpParameters->Simulation()->Mesh()->Sheet()->inter_node_space();
934 break;
935 case 1:
936 CHECK_EXISTS(GetCreateFibre(), "Simulation/Mesh/Fibre");
937 return mpParameters->Simulation()->Mesh()->Fibre()->inter_node_space();
938 break;
939 default:
941 // LCOV_EXCL_START
942 return 0.0; //To fool the compiler
943 // LCOV_EXCL_STOP
944 }
945}
946
947std::string HeartConfig::GetMeshName() const
948{
949 CheckSimulationIsDefined("LoadMesh");
950 CHECK_EXISTS(GetLoadMesh(), "Mesh/LoadMesh");
951
952 return mpParameters->Simulation()->Mesh()->LoadMesh()->name();
953}
954
956{
957 CheckSimulationIsDefined("LoadMesh");
958 CHECK_EXISTS(GetLoadMesh(), "Mesh/LoadMesh");
959
960 return mpParameters->Simulation()->Mesh()->LoadMesh()->conductivity_media();
961}
962
963template <unsigned DIM>
964void HeartConfig::GetStimuli(std::vector<boost::shared_ptr<AbstractStimulusFunction> >& rStimuliApplied,
965 std::vector<boost::shared_ptr<AbstractChasteRegion<DIM> > >& rStimulatedAreas) const
966{
967 CheckSimulationIsDefined("Stimuli");
968
969 if (!mpParameters->Simulation()->Stimuli().present())
970 {
971 // Finding no stimuli defined is allowed (although HeartConfigRelatedFactory does
972 // throw an exception is no stimuli and no electrodes)
973 return;
974 }
975
976 XSD_SEQUENCE_TYPE(cp::stimuli_type::Stimulus)
977 stimuli = mpParameters->Simulation()->Stimuli()->Stimulus();
978
979 for (XSD_ITERATOR_TYPE(cp::stimuli_type::Stimulus) i = stimuli.begin();
980 i != stimuli.end();
981 ++i)
982 {
983 cp::stimulus_type stimulus(*i);
984 if (stimulus.Location().Cuboid().present() || stimulus.Location().Ellipsoid().present())
985 {
986 boost::shared_ptr<AbstractChasteRegion<DIM> > area_ptr;
987 if (stimulus.Location().Cuboid().present())
988 {
989 cp::point_type point_a = stimulus.Location().Cuboid()->LowerCoordinates();
990 cp::point_type point_b = stimulus.Location().Cuboid()->UpperCoordinates();
991 switch (DIM)
992 {
993 case 1:
994 {
995 ChastePoint<DIM> chaste_point_a(point_a.x());
996 ChastePoint<DIM> chaste_point_b(point_b.x());
997 area_ptr.reset(new ChasteCuboid<DIM>(chaste_point_a, chaste_point_b));
998 break;
999 }
1000 case 2:
1001 {
1002 ChastePoint<DIM> chaste_point_a(point_a.x(), point_a.y());
1003 ChastePoint<DIM> chaste_point_b(point_b.x(), point_b.y());
1004 area_ptr.reset(new ChasteCuboid<DIM>(chaste_point_a, chaste_point_b));
1005 break;
1006 }
1007 case 3:
1008 {
1009 ChastePoint<DIM> chaste_point_a(point_a.x(), point_a.y(), point_a.z());
1010 ChastePoint<DIM> chaste_point_b(point_b.x(), point_b.y(), point_b.z());
1011 area_ptr.reset(new ChasteCuboid<DIM>(chaste_point_a, chaste_point_b));
1012 break;
1013 }
1014 default:
1016 break;
1017 }
1018 }
1019 else if (stimulus.Location().Ellipsoid().present())
1020 {
1021 cp::point_type centre = stimulus.Location().Ellipsoid()->Centre();
1022 cp::point_type radii = stimulus.Location().Ellipsoid()->Radii();
1023 switch (DIM)
1024 {
1025 case 1:
1026 {
1027 ChastePoint<DIM> chaste_point_a(centre.x());
1028 ChastePoint<DIM> chaste_point_b(radii.x());
1029 area_ptr.reset(new ChasteEllipsoid<DIM>(chaste_point_a, chaste_point_b));
1030 break;
1031 }
1032 case 2:
1033 {
1034 ChastePoint<DIM> chaste_point_a(centre.x(), centre.y());
1035 ChastePoint<DIM> chaste_point_b(radii.x(), radii.y());
1036 area_ptr.reset(new ChasteEllipsoid<DIM>(chaste_point_a, chaste_point_b));
1037 break;
1038 }
1039 case 3:
1040 {
1041 ChastePoint<DIM> chaste_point_a(centre.x(), centre.y(), centre.z());
1042 ChastePoint<DIM> chaste_point_b(radii.x(), radii.y(), radii.z());
1043 area_ptr.reset(new ChasteEllipsoid<DIM>(chaste_point_a, chaste_point_b));
1044 break;
1045 }
1046 default:
1047 {
1049 break;
1050 }
1051 }
1052 }
1053 rStimulatedAreas.push_back(area_ptr);
1054
1055 boost::shared_ptr<AbstractStimulusFunction> stim;
1056
1057 if (stimulus.Period().present())
1058 {
1059 if (stimulus.StopTime().present())
1060 {
1061 stim.reset(new RegularStimulus(stimulus.Strength(),
1062 stimulus.Duration(),
1063 stimulus.Period().get(),
1064 stimulus.Delay(),
1065 stimulus.StopTime().get()));
1066 }
1067 else
1068 {
1069 stim.reset(new RegularStimulus(stimulus.Strength(),
1070 stimulus.Duration(),
1071 stimulus.Period().get(),
1072 stimulus.Delay()));
1073 }
1074 }
1075 else
1076 {
1077 if (stimulus.StopTime().present())
1078 {
1079 EXCEPTION("Stop time can not be defined for SimpleStimulus. Use Duration instead.");
1080 }
1081
1082 stim.reset(new SimpleStimulus(stimulus.Strength(),
1083 stimulus.Duration(),
1084 stimulus.Delay()));
1085 }
1086 rStimuliApplied.push_back(stim);
1087 }
1088 else if (stimulus.Location().EpiLayer().present() || stimulus.Location().MidLayer().present() || stimulus.Location().EndoLayer().present())
1089 {
1090 EXCEPTION("Definition of transmural layers is not yet supported for specifying stimulated areas, please use cuboids instead");
1091 }
1092 else
1093 {
1094 EXCEPTION("Invalid region type for stimulus definition");
1095 }
1096 }
1097}
1098
1099template <unsigned DIM>
1100void HeartConfig::GetCellHeterogeneities(std::vector<boost::shared_ptr<AbstractChasteRegion<DIM> > >& rCellHeterogeneityRegions,
1101 std::vector<double>& rScaleFactorGks,
1102 std::vector<double>& rScaleFactorIto,
1103 std::vector<double>& rScaleFactorGkr,
1104 std::vector<std::map<std::string, double> >* pParameterSettings)
1105{
1106 CheckSimulationIsDefined("CellHeterogeneities");
1107
1108 if (!mpParameters->Simulation()->CellHeterogeneities().present())
1109 {
1110 // finding no heterogeneities defined is allowed
1111 return;
1112 }
1113 auto cell_heterogeneity = mpParameters->Simulation()->CellHeterogeneities()->CellHeterogeneity();
1114
1115 bool user_supplied_negative_value = false;
1116 mUserAskedForCellularTransmuralHeterogeneities = false; // overwritten with true below if necessary
1117 bool user_asked_for_cuboids_or_ellipsoids = false;
1118 unsigned counter_of_heterogeneities = 0;
1119
1120 for (XSD_ITERATOR_TYPE(cp::cell_heterogeneities_type::CellHeterogeneity) i = cell_heterogeneity.begin();
1121 i != cell_heterogeneity.end();
1122 ++i)
1123 {
1124 cp::cell_heterogeneity_type ht(*i);
1125
1126 if (ht.Location().Cuboid().present())
1127 {
1128 user_asked_for_cuboids_or_ellipsoids = true;
1129 cp::point_type point_a = ht.Location().Cuboid()->LowerCoordinates();
1130 cp::point_type point_b = ht.Location().Cuboid()->UpperCoordinates();
1131
1132 ChastePoint<DIM> chaste_point_a(point_a.x(), point_a.y(), point_a.z());
1133 ChastePoint<DIM> chaste_point_b(point_b.x(), point_b.y(), point_b.z());
1134
1135 rCellHeterogeneityRegions.push_back(boost::shared_ptr<AbstractChasteRegion<DIM> >(new ChasteCuboid<DIM>(chaste_point_a, chaste_point_b)));
1136 }
1137 else if (ht.Location().Ellipsoid().present())
1138 {
1139 user_asked_for_cuboids_or_ellipsoids = true;
1140 cp::point_type centre = ht.Location().Ellipsoid()->Centre();
1141 cp::point_type radii = ht.Location().Ellipsoid()->Radii();
1142
1143 ChastePoint<DIM> chaste_point_a(centre.x(), centre.y(), centre.z());
1144 ChastePoint<DIM> chaste_point_b(radii.x(), radii.y(), radii.z());
1145 rCellHeterogeneityRegions.push_back(boost::shared_ptr<AbstractChasteRegion<DIM> >(new ChasteEllipsoid<DIM>(chaste_point_a, chaste_point_b)));
1146 }
1147 else if (ht.Location().EpiLayer().present())
1148 {
1149 mEpiFraction = ht.Location().EpiLayer().get();
1150
1152 if (mEpiFraction < 0)
1153 {
1154 user_supplied_negative_value = true;
1155 }
1156 mIndexEpi = counter_of_heterogeneities;
1157 }
1158 else if (ht.Location().EndoLayer().present())
1159 {
1160 mEndoFraction = ht.Location().EndoLayer().get();
1161
1163 if (mEndoFraction < 0)
1164 {
1165 user_supplied_negative_value = true;
1166 }
1167 mIndexEndo = counter_of_heterogeneities;
1168 }
1169 else if (ht.Location().MidLayer().present())
1170 {
1171 mMidFraction = ht.Location().MidLayer().get();
1172
1174 if (mMidFraction < 0)
1175 {
1176 user_supplied_negative_value = true;
1177 }
1178 mIndexMid = counter_of_heterogeneities;
1179 }
1180 else
1181 {
1182 EXCEPTION("Invalid region type for cell heterogeneity definition");
1183 }
1184
1185 // Old scale factors
1186 rScaleFactorGks.push_back(ht.ScaleFactorGks().present() ? (double)ht.ScaleFactorGks().get() : 1.0);
1187 rScaleFactorIto.push_back(ht.ScaleFactorIto().present() ? (double)ht.ScaleFactorIto().get() : 1.0);
1188 rScaleFactorGkr.push_back(ht.ScaleFactorGkr().present() ? (double)ht.ScaleFactorGkr().get() : 1.0);
1189
1190 // Named parameters
1191 if (pParameterSettings)
1192 {
1193 std::map<std::string, double> param_settings;
1194 XSD_SEQUENCE_TYPE(cp::cell_heterogeneity_type::SetParameter)& params = ht.SetParameter();
1195 for (XSD_ITERATOR_TYPE(cp::cell_heterogeneity_type::SetParameter) param_it = params.begin();
1196 param_it != params.end();
1197 ++param_it)
1198 {
1199 cp::set_parameter_type param(*param_it);
1200 param_settings[param.name()] = param.value();
1201 }
1202 pParameterSettings->push_back(param_settings);
1203 }
1204
1205 counter_of_heterogeneities++;
1206 }
1207
1209 {
1210 // cuboids/ellipsoids and layers at the same time are not yet supported
1211 if (user_asked_for_cuboids_or_ellipsoids)
1212 {
1213 EXCEPTION("Specification of cellular heterogeneities by cuboids/ellipsoids and layers at the same time is not yet supported");
1214 }
1215
1216 //check that the user supplied all three layers, the indexes should be 0, 1 and 2.
1217 // As they are initialised to a higher value, if their summation is higher than 3,
1218 // one (or more) is missing
1219 if ((mIndexMid + mIndexEndo + mIndexEpi) > 3)
1220 {
1221 EXCEPTION("Three specifications of layers must be supplied");
1222 }
1223 if (fabs((mEndoFraction + mMidFraction + mEpiFraction) - 1) > 1e-2)
1224 {
1225 EXCEPTION("Summation of epicardial, midmyocardial and endocardial fractions should be 1");
1226 }
1227 if (user_supplied_negative_value)
1228 {
1229 EXCEPTION("Fractions must be positive");
1230 }
1231 }
1232}
1233
1238
1240{
1241 return mEpiFraction;
1242}
1243
1245{
1246 return mEndoFraction;
1247}
1248
1250{
1251 return mMidFraction;
1252}
1253
1255{
1256 return mIndexEpi;
1257}
1258
1260{
1261 return mIndexEndo;
1262}
1263
1265{
1266 return mIndexMid;
1267}
1268
1270{
1271 CheckSimulationIsDefined("ConductivityHeterogeneities");
1272 return mpParameters->Physiological().ConductivityHeterogeneities().present();
1273}
1274
1275template <unsigned DIM>
1277 std::vector<boost::shared_ptr<AbstractChasteRegion<DIM> > >& rConductivitiesHeterogeneityAreas,
1278 std::vector<c_vector<double, 3> >& rIntraConductivities,
1279 std::vector<c_vector<double, 3> >& rExtraConductivities) const
1280{
1281 CheckSimulationIsDefined("ConductivityHeterogeneities");
1282 CHECK_EXISTS(GetConductivityHeterogeneitiesProvided(), "Physiological/ConductivityHeterogeneities");
1283 XSD_ANON_SEQUENCE_TYPE(cp::physiological_type, ConductivityHeterogeneities, ConductivityHeterogeneity)& conductivity_heterogeneity = mpParameters->Physiological().ConductivityHeterogeneities()->ConductivityHeterogeneity();
1284
1285 for (XSD_ANON_ITERATOR_TYPE(cp::physiological_type, ConductivityHeterogeneities, ConductivityHeterogeneity) i = conductivity_heterogeneity.begin();
1286 i != conductivity_heterogeneity.end();
1287 ++i)
1288 {
1289 cp::conductivity_heterogeneity_type ht(*i);
1290
1291 if (ht.Location().Cuboid().present())
1292 {
1293 cp::point_type point_a = ht.Location().Cuboid()->LowerCoordinates();
1294 cp::point_type point_b = ht.Location().Cuboid()->UpperCoordinates();
1295 ChastePoint<DIM> chaste_point_a(point_a.x(), point_a.y(), point_a.z());
1296 ChastePoint<DIM> chaste_point_b(point_b.x(), point_b.y(), point_b.z());
1297 rConductivitiesHeterogeneityAreas.push_back(boost::shared_ptr<AbstractChasteRegion<DIM> >(new ChasteCuboid<DIM>(chaste_point_a, chaste_point_b)));
1298 }
1299 else if (ht.Location().Ellipsoid().present())
1300 {
1301 cp::point_type centre = ht.Location().Ellipsoid()->Centre();
1302 cp::point_type radii = ht.Location().Ellipsoid()->Radii();
1303 ChastePoint<DIM> chaste_point_a(centre.x(), centre.y(), centre.z());
1304 ChastePoint<DIM> chaste_point_b(radii.x(), radii.y(), radii.z());
1305 rConductivitiesHeterogeneityAreas.push_back(boost::shared_ptr<AbstractChasteRegion<DIM> >(new ChasteEllipsoid<DIM>(chaste_point_a, chaste_point_b)));
1306 }
1307 else if (ht.Location().EpiLayer().present() || ht.Location().MidLayer().present() || ht.Location().EndoLayer().present())
1308 {
1310 EXCEPTION("Definition of transmural layers is not allowed for conductivities heterogeneities, you may use fibre orientation support instead");
1311 }
1312 else
1313 {
1314 EXCEPTION("Invalid region type for conductivity definition");
1315 }
1316
1317 if (ht.IntracellularConductivities().present())
1318 {
1319 double intra_x = ht.IntracellularConductivities()->longi();
1320 double intra_y = ht.IntracellularConductivities()->trans();
1321 double intra_z = ht.IntracellularConductivities()->normal();
1322
1323 rIntraConductivities.push_back(Create_c_vector(intra_x, intra_y, intra_z));
1324 }
1325 else
1326 {
1327 c_vector<double, 3> intra_conductivities;
1328 GetIntracellularConductivities(intra_conductivities);
1329 rIntraConductivities.push_back(intra_conductivities);
1330 }
1331
1332 if (ht.ExtracellularConductivities().present())
1333 {
1334 double extra_x = ht.ExtracellularConductivities()->longi();
1335 double extra_y = ht.ExtracellularConductivities()->trans();
1336 double extra_z = ht.ExtracellularConductivities()->normal();
1337
1338 rExtraConductivities.push_back(Create_c_vector(extra_x, extra_y, extra_z));
1339 }
1340 else
1341 {
1342 c_vector<double, 3> extra_conductivities;
1343 GetExtracellularConductivities(extra_conductivities);
1344 rExtraConductivities.push_back(extra_conductivities);
1345 }
1346 }
1347}
1348
1350{
1351 CheckSimulationIsDefined("Simulation/OutputDirectory");
1352 CHECK_EXISTS(mpParameters->Simulation()->OutputDirectory().present(), "Simulation/OutputDirectory");
1353 return mpParameters->Simulation()->OutputDirectory().get();
1354}
1355
1357{
1358 CheckSimulationIsDefined("Simulation/OutputFilenamePrefix");
1359 CHECK_EXISTS(mpParameters->Simulation()->OutputFilenamePrefix().present(), "Simulation/OutputFilenamePrefix");
1360 return mpParameters->Simulation()->OutputFilenamePrefix().get();
1361}
1362
1364{
1365 CheckSimulationIsDefined("OutputVariables");
1366 return mpParameters->Simulation()->OutputVariables().present();
1367}
1368
1369void HeartConfig::GetOutputVariables(std::vector<std::string>& rOutputVariables) const
1370{
1371 CHECK_EXISTS(GetOutputVariablesProvided(), "Simulation/OutputVariables");
1372 XSD_SEQUENCE_TYPE(cp::output_variables_type::Var)& output_variables = mpParameters->Simulation()->OutputVariables()->Var();
1373 rOutputVariables.clear();
1374
1375 for (XSD_ITERATOR_TYPE(cp::output_variables_type::Var) i = output_variables.begin();
1376 i != output_variables.end();
1377 ++i)
1378 {
1379 cp::var_type& r_var(*i);
1380
1381 // Add to outputVariables the string returned by var.name()
1382 rOutputVariables.push_back(r_var.name());
1383 }
1384}
1385
1387{
1388 CheckSimulationIsDefined("OutputUsingOriginalNodeOrdering");
1389 bool result = false;
1390 if (mpParameters->Simulation()->OutputUsingOriginalNodeOrdering().present())
1391 {
1392 result = (mpParameters->Simulation()->OutputUsingOriginalNodeOrdering().get() == cp::yesno_type::yes);
1393 }
1394 return result;
1395}
1396
1398{
1399 return IsSimulationDefined() && mpParameters->Simulation()->CheckpointSimulation().present();
1400}
1401
1403{
1404 CHECK_EXISTS(GetCheckpointSimulation(), "Simulation/CheckpointSimulation");
1405 return mpParameters->Simulation()->CheckpointSimulation()->timestep();
1406}
1407
1409{
1410 CHECK_EXISTS(GetCheckpointSimulation(), "Simulation/CheckpointSimulation");
1411 return mpParameters->Simulation()->CheckpointSimulation()->max_checkpoints_on_disk();
1412}
1413
1415{
1416 CheckResumeSimulationIsDefined("GetArchivedSimulationDir");
1417
1418 return HeartFileFinder(mpParameters->ResumeSimulation()->ArchiveDirectory());
1419}
1420
1421void HeartConfig::GetIntracellularConductivities(c_vector<double, 3>& rIntraConductivities) const
1422{
1423 CHECK_EXISTS(mpParameters->Physiological().IntracellularConductivities().present(), "Physiological/IntracellularConductivities");
1424 cp::conductivities_type intra_conductivities = mpParameters->Physiological().IntracellularConductivities().get();
1425 double intra_x_cond = intra_conductivities.longi();
1426 double intra_y_cond = intra_conductivities.trans();
1427 double intra_z_cond = intra_conductivities.normal();
1428 ;
1429
1430 assert(intra_y_cond != DBL_MAX);
1431 assert(intra_z_cond != DBL_MAX);
1432
1433 rIntraConductivities[0] = intra_x_cond;
1434 rIntraConductivities[1] = intra_y_cond;
1435 rIntraConductivities[2] = intra_z_cond;
1436}
1437
1438void HeartConfig::GetIntracellularConductivities(c_vector<double, 2>& rIntraConductivities) const
1439{
1440 CHECK_EXISTS(mpParameters->Physiological().IntracellularConductivities().present(), "Physiological/IntracellularConductivities");
1441 cp::conductivities_type intra_conductivities = mpParameters->Physiological().IntracellularConductivities().get();
1442 double intra_x_cond = intra_conductivities.longi();
1443 double intra_y_cond = intra_conductivities.trans();
1444
1445 assert(intra_y_cond != DBL_MAX);
1446
1447 rIntraConductivities[0] = intra_x_cond;
1448 rIntraConductivities[1] = intra_y_cond;
1449}
1450
1451void HeartConfig::GetIntracellularConductivities(c_vector<double, 1>& rIntraConductivities) const
1452{
1453 CHECK_EXISTS(mpParameters->Physiological().IntracellularConductivities().present(), "Physiological/IntracellularConductivities");
1454 cp::conductivities_type intra_conductivities = mpParameters->Physiological().IntracellularConductivities().get();
1455 double intra_x_cond = intra_conductivities.longi();
1456
1457 rIntraConductivities[0] = intra_x_cond;
1458}
1459
1460void HeartConfig::GetExtracellularConductivities(c_vector<double, 3>& rExtraConductivities) const
1461{
1462 CHECK_EXISTS(mpParameters->Physiological().ExtracellularConductivities().present(), "Physiological/ExtracellularConductivities");
1463 cp::conductivities_type extra_conductivities = mpParameters->Physiological().ExtracellularConductivities().get();
1464 double extra_x_cond = extra_conductivities.longi();
1465 double extra_y_cond = extra_conductivities.trans();
1466 double extra_z_cond = extra_conductivities.normal();
1467 ;
1468
1469 assert(extra_y_cond != DBL_MAX);
1470 assert(extra_z_cond != DBL_MAX);
1471
1472 rExtraConductivities[0] = extra_x_cond;
1473 rExtraConductivities[1] = extra_y_cond;
1474 rExtraConductivities[2] = extra_z_cond;
1475}
1476
1477void HeartConfig::GetExtracellularConductivities(c_vector<double, 2>& rExtraConductivities) const
1478{
1479 CHECK_EXISTS(mpParameters->Physiological().ExtracellularConductivities().present(), "Physiological/ExtracellularConductivities");
1480 cp::conductivities_type extra_conductivities = mpParameters->Physiological().ExtracellularConductivities().get();
1481 double extra_x_cond = extra_conductivities.longi();
1482 double extra_y_cond = extra_conductivities.trans();
1483
1484 assert(extra_y_cond != DBL_MAX);
1485
1486 rExtraConductivities[0] = extra_x_cond;
1487 rExtraConductivities[1] = extra_y_cond;
1488}
1489
1490void HeartConfig::GetExtracellularConductivities(c_vector<double, 1>& rExtraConductivities) const
1491{
1492 CHECK_EXISTS(mpParameters->Physiological().ExtracellularConductivities().present(), "Physiological/ExtracellularConductivities");
1493 cp::conductivities_type extra_conductivities = mpParameters->Physiological().ExtracellularConductivities().get();
1494 double extra_x_cond = extra_conductivities.longi();
1495
1496 rExtraConductivities[0] = extra_x_cond;
1497}
1498
1499double HeartConfig::GetBathConductivity(unsigned bathRegion) const
1500{
1501 /*
1502 * We have to consider three cases: The user asks for ...
1503 * a) ... the default conductivity (bathRegion=UINT_MAX)
1504 * b) ... the conductivity of region defined to be heterogeneous
1505 * c) ... the conductivity of region NOT defined to be heterogeneous
1506 *
1507 * a) and c) should return the same
1508 */
1509
1510 if (bathRegion == UINT_MAX)
1511 {
1512 /*bath conductivity mS/cm*/
1513 CHECK_EXISTS(mpParameters->Physiological().BathConductivity().present(), "Physiological/BathConductivity");
1514 return mpParameters->Physiological().BathConductivity().get();
1515 }
1516 else
1517 {
1518 assert(HeartRegionCode::IsRegionBath(bathRegion));
1519
1520 std::map<unsigned, double>::const_iterator map_entry = mBathConductivities.find(bathRegion);
1521
1522 if (map_entry != mBathConductivities.end())
1523 {
1524 return map_entry->second;
1525 }
1526 else
1527 {
1528 /*bath conductivity mS/cm*/
1529 CHECK_EXISTS(mpParameters->Physiological().BathConductivity().present(), "Physiological/BathConductivity");
1530 return mpParameters->Physiological().BathConductivity().get();
1531 }
1532 }
1533}
1534const std::set<unsigned>& HeartConfig::rGetTissueIdentifiers()
1535{
1536 return mTissueIdentifiers;
1537}
1538
1539const std::set<unsigned>& HeartConfig::rGetBathIdentifiers()
1540{
1541 return mBathIdentifiers;
1542}
1543
1545{
1546 CHECK_EXISTS(mpParameters->Physiological().SurfaceAreaToVolumeRatio().present(), "Physiological/SurfaceAreaToVolumeRatio");
1547 return mpParameters->Physiological().SurfaceAreaToVolumeRatio().get();
1548}
1549
1551{
1552 CHECK_EXISTS(mpParameters->Physiological().Capacitance().present(), "Physiological/Capacitance");
1553 return mpParameters->Physiological().Capacitance().get();
1554}
1555
1557{
1558 CHECK_EXISTS(mpParameters->Numerical().TimeSteps().present(), "Numerical/TimeSteps");
1559 return mpParameters->Numerical().TimeSteps()->ode();
1560}
1561
1563{
1564 CHECK_EXISTS(mpParameters->Numerical().TimeSteps().present(), "Numerical/TimeSteps");
1565 return mpParameters->Numerical().TimeSteps()->pde();
1566}
1567
1569{
1570 CHECK_EXISTS(mpParameters->Numerical().TimeSteps().present(), "Numerical/TimeSteps");
1571 return mpParameters->Numerical().TimeSteps()->printing();
1572}
1573
1575{
1576 CHECK_EXISTS(mpParameters->Numerical().KSPTolerances().present(), "Numerical/KSPTolerances");
1577 return mpParameters->Numerical().KSPTolerances()->KSPAbsolute().present();
1578}
1579
1581{
1582 CHECK_EXISTS(mpParameters->Numerical().KSPTolerances().present(), "Numerical/KSPTolerances");
1584 {
1585 EXCEPTION("Absolute tolerance is not set in Chaste parameters");
1586 }
1587 return mpParameters->Numerical().KSPTolerances()->KSPAbsolute().get();
1588}
1589
1591{
1592 CHECK_EXISTS(mpParameters->Numerical().KSPTolerances().present(), "Numerical/KSPTolerances");
1593 return mpParameters->Numerical().KSPTolerances()->KSPRelative().present();
1594}
1595
1597{
1598 CHECK_EXISTS(mpParameters->Numerical().KSPTolerances().present(), "Numerical/KSPTolerances");
1600 {
1601 EXCEPTION("Relative tolerance is not set in Chaste parameters");
1602 }
1603 return mpParameters->Numerical().KSPTolerances()->KSPRelative().get();
1604}
1605
1606const char* HeartConfig::GetKSPSolver() const
1607{
1608 CHECK_EXISTS(mpParameters->Numerical().KSPSolver().present(), "Numerical/KSPSolver");
1609 switch (mpParameters->Numerical().KSPSolver().get())
1610 {
1611 case cp::ksp_solver_type::gmres:
1612 return "gmres";
1613 case cp::ksp_solver_type::cg:
1614 return "cg";
1615 case cp::ksp_solver_type::symmlq:
1616 return "symmlq";
1617 case cp::ksp_solver_type::chebychev:
1618 return "chebychev";
1619 }
1620 // LCOV_EXCL_START
1621 EXCEPTION("Unknown ksp solver");
1622 // LCOV_EXCL_STOP
1623}
1624
1626{
1627 CHECK_EXISTS(mpParameters->Numerical().KSPPreconditioner().present(), "Numerical/KSPPreconditioner");
1628 switch (mpParameters->Numerical().KSPPreconditioner().get())
1629 {
1630 case cp::ksp_preconditioner_type::jacobi:
1631 return "jacobi";
1632 case cp::ksp_preconditioner_type::bjacobi:
1633 return "bjacobi";
1634 case cp::ksp_preconditioner_type::hypre:
1635 return "hypre";
1636 case cp::ksp_preconditioner_type::ml:
1637 return "ml";
1638 case cp::ksp_preconditioner_type::spai:
1639 return "spai";
1640 case cp::ksp_preconditioner_type::blockdiagonal:
1641 return "blockdiagonal";
1642 case cp::ksp_preconditioner_type::ldufactorisation:
1643 return "ldufactorisation";
1644 case cp::ksp_preconditioner_type::twolevelsblockdiagonal:
1645 return "twolevelsblockdiagonal";
1646 case cp::ksp_preconditioner_type::none:
1647 return "none";
1648 }
1649 // LCOV_EXCL_START
1650 EXCEPTION("Unknown ksp preconditioner");
1651 // LCOV_EXCL_STOP
1652}
1653
1655{
1656 CHECK_EXISTS(mpParameters->Numerical().MeshPartitioning().present(), "Numerical/MeshPartitioning");
1657 switch (mpParameters->Numerical().MeshPartitioning().get())
1658 {
1659 case cp::mesh_partitioning_type::dumb:
1660 return DistributedTetrahedralMeshPartitionType::DUMB;
1661 case cp::mesh_partitioning_type::metis:
1662 return DistributedTetrahedralMeshPartitionType::METIS_LIBRARY;
1663 case cp::mesh_partitioning_type::parmetis:
1664 return DistributedTetrahedralMeshPartitionType::PARMETIS_LIBRARY;
1665 case cp::mesh_partitioning_type::petsc:
1666 return DistributedTetrahedralMeshPartitionType::PETSC_MAT_PARTITION;
1667 }
1668 // LCOV_EXCL_START
1669 EXCEPTION("Unknown mesh partitioning type");
1670 // LCOV_EXCL_STOP
1671}
1672
1674{
1675 bool IsAdaptivityParametersPresent = mpParameters->Numerical().AdaptivityParameters().present();
1677 {
1678 WARNING("Use of the Adaptivity library is deprecated");
1679 }
1681}
1682
1683/*
1684 * PostProcessing
1685 */
1686
1688{
1689 return mpParameters->PostProcessing().present();
1690}
1691
1693{
1694 ENSURE_SECTION_PRESENT(mpParameters->PostProcessing(), cp::postprocessing_type);
1695}
1696
1709{
1710 bool result = false;
1712 {
1713 auto& apd_maps = mpParameters->PostProcessing()->ActionPotentialDurationMap();
1714 result = (apd_maps.begin() != apd_maps.end());
1715 }
1716 return result;
1717}
1718
1719void HeartConfig::GetApdMaps(std::vector<std::pair<double, double> >& apd_maps) const
1720{
1721 CHECK_EXISTS(IsApdMapsRequested(), "PostProcessing/ActionPotentialDurationMap");
1722 apd_maps.clear();
1723
1724 auto& apd_maps_sequence = mpParameters->PostProcessing()->ActionPotentialDurationMap();
1725
1726 for (XSD_ITERATOR_TYPE(cp::postprocessing_type::ActionPotentialDurationMap) i = apd_maps_sequence.begin();
1727 i != apd_maps_sequence.end();
1728 ++i)
1729 {
1730 std::pair<double, double> map(i->repolarisation_percentage(), i->threshold());
1731
1732 apd_maps.push_back(map);
1733 }
1734}
1735
1737{
1738 bool result = false;
1740 {
1741 auto& upstroke_map = mpParameters->PostProcessing()->UpstrokeTimeMap();
1742 result = (upstroke_map.begin() != upstroke_map.end());
1743 }
1744 return result;
1745}
1746void HeartConfig::GetUpstrokeTimeMaps(std::vector<double>& upstroke_time_maps) const
1747{
1748 CHECK_EXISTS(IsUpstrokeTimeMapsRequested(), "PostProcessing/UpstrokeTimeMap");
1749 assert(upstroke_time_maps.size() == 0);
1750
1751 auto& upstroke_maps_sequence = mpParameters->PostProcessing()->UpstrokeTimeMap();
1752
1753 for (XSD_ITERATOR_TYPE(cp::postprocessing_type::UpstrokeTimeMap) i = upstroke_maps_sequence.begin();
1754 i != upstroke_maps_sequence.end();
1755 ++i)
1756 {
1757 upstroke_time_maps.push_back(i->threshold());
1758 }
1759}
1760
1762{
1763 bool result = false;
1765 {
1766 auto& max_upstroke_velocity_map = mpParameters->PostProcessing()->MaxUpstrokeVelocityMap();
1767 result = (max_upstroke_velocity_map.begin() != max_upstroke_velocity_map.end());
1768 }
1769 return result;
1770}
1771
1772void HeartConfig::GetMaxUpstrokeVelocityMaps(std::vector<double>& upstroke_velocity_maps) const
1773{
1774 CHECK_EXISTS(IsMaxUpstrokeVelocityMapRequested(), "PostProcessing/MaxUpstrokeVelocityMap");
1775 assert(upstroke_velocity_maps.size() == 0);
1776
1777 auto& max_upstroke_velocity_maps_sequence = mpParameters->PostProcessing()->MaxUpstrokeVelocityMap();
1778
1779 for (XSD_ITERATOR_TYPE(cp::postprocessing_type::MaxUpstrokeVelocityMap) i = max_upstroke_velocity_maps_sequence.begin();
1780 i != max_upstroke_velocity_maps_sequence.end();
1781 ++i)
1782 {
1783 upstroke_velocity_maps.push_back(i->threshold());
1784 }
1785}
1786
1788{
1789 bool result = false;
1791 {
1792 auto& cond_vel_maps = mpParameters->PostProcessing()->ConductionVelocityMap();
1793 result = (cond_vel_maps.begin() != cond_vel_maps.end());
1794 }
1795 return result;
1796}
1797
1798void HeartConfig::GetConductionVelocityMaps(std::vector<unsigned>& conduction_velocity_maps) const
1799{
1800 CHECK_EXISTS(IsConductionVelocityMapsRequested(), "PostProcessing/ConductionVelocityMap");
1801 assert(conduction_velocity_maps.size() == 0);
1802
1803 auto& cond_vel_maps_sequence = mpParameters->PostProcessing()->ConductionVelocityMap();
1804
1805 for (XSD_ITERATOR_TYPE(cp::postprocessing_type::ConductionVelocityMap) i = cond_vel_maps_sequence.begin();
1806 i != cond_vel_maps_sequence.end();
1807 ++i)
1808 {
1809 conduction_velocity_maps.push_back(i->origin_node());
1810 }
1811}
1812
1814{
1815 bool result = false;
1817 {
1818 auto& requested_nodes = mpParameters->PostProcessing()->TimeTraceAtNode();
1819 result = (requested_nodes.begin() != requested_nodes.end());
1820 }
1821 return result;
1822}
1823
1824void HeartConfig::GetNodalTimeTraceRequested(std::vector<unsigned>& rRequestedNodes) const
1825{
1826 CHECK_EXISTS(IsAnyNodalTimeTraceRequested(), "PostProcessing/TimeTraceAtNode");
1827 assert(rRequestedNodes.size() == 0);
1828
1829 auto& req_nodes = mpParameters->PostProcessing()->TimeTraceAtNode();
1830
1831 for (XSD_ITERATOR_TYPE(cp::postprocessing_type::TimeTraceAtNode) i = req_nodes.begin();
1832 i != req_nodes.end();
1833 ++i)
1834 {
1835 rRequestedNodes.push_back(i->node_number());
1836 }
1837}
1838
1840{
1841 bool result = false;
1843 {
1844 auto& electrodes = mpParameters->PostProcessing()->PseudoEcgElectrodePosition();
1845 result = (electrodes.begin() != electrodes.end());
1846 }
1847 return result;
1848}
1849
1850template <unsigned SPACE_DIM>
1851void HeartConfig::GetPseudoEcgElectrodePositions(std::vector<ChastePoint<SPACE_DIM> >& rPseudoEcgElectrodePositions) const
1852{
1853 rPseudoEcgElectrodePositions.clear();
1854 auto& electrodes = mpParameters->PostProcessing()->PseudoEcgElectrodePosition();
1855 for (XSD_ITERATOR_TYPE(cp::postprocessing_type::PseudoEcgElectrodePosition) i = electrodes.begin();
1856 i != electrodes.end();
1857 ++i)
1858 {
1859 rPseudoEcgElectrodePositions.push_back(ChastePoint<SPACE_DIM>(i->x(), i->y(), i->z()));
1860 }
1861}
1862
1863/*
1864 * Output visualization
1865 */
1866
1868{
1869 CheckSimulationIsDefined("OutputVisualizer");
1870
1871 return mpParameters->Simulation()->OutputVisualizer().present();
1872}
1873
1875{
1877 {
1878 return false;
1879 }
1880 else
1881 {
1882 return mpParameters->Simulation()->OutputVisualizer()->meshalyzer() == cp::yesno_type::yes;
1883 }
1884}
1885
1887{
1889 {
1890 return false;
1891 }
1892 else
1893 {
1894 return mpParameters->Simulation()->OutputVisualizer()->cmgui() == cp::yesno_type::yes;
1895 }
1896}
1897
1899{
1901 {
1902 return false;
1903 }
1904 else
1905 {
1906 return mpParameters->Simulation()->OutputVisualizer()->parallel_vtk() == cp::yesno_type::yes;
1907 }
1908}
1909
1911{
1913 {
1914 return false;
1915 }
1916 else
1917 {
1918 return mpParameters->Simulation()->OutputVisualizer()->vtk() == cp::yesno_type::yes;
1919 }
1920}
1921
1923{
1925 {
1926 return 0u;
1927 }
1928 else
1929 {
1930 return mpParameters->Simulation()->OutputVisualizer()->precision();
1931 }
1932}
1933
1935{
1936 return mpParameters->Simulation()->Electrodes().present();
1937}
1938
1939/*
1940 * Set methods
1941 */
1942void HeartConfig::SetSpaceDimension(unsigned spaceDimension)
1943{
1944 mpParameters->Simulation()->SpaceDimension().set(spaceDimension);
1945}
1946
1947void HeartConfig::SetSimulationDuration(double simulationDuration)
1948{
1949 XSD_CREATE_WITH_FIXED_ATTR1(cp::time_type, time, simulationDuration, "ms");
1950 mpParameters->Simulation()->SimulationDuration().set(time);
1951}
1952
1953void HeartConfig::SetDomain(const cp::domain_type& rDomain)
1954{
1955 mpParameters->Simulation()->Domain().set(rDomain);
1956}
1957
1958void HeartConfig::SetDefaultIonicModel(const cp::ionic_models_available_type& rIonicModel)
1959{
1960 cp::ionic_model_selection_type ionic_model;
1961 ionic_model.Hardcoded(rIonicModel);
1962 cp::ionic_models_type container(ionic_model);
1963 mpParameters->Simulation()->IonicModels().set(container);
1964}
1965
1966void HeartConfig::SetSlabDimensions(double x, double y, double z, double inter_node_space)
1967{
1968 if (!mpParameters->Simulation()->Mesh().present())
1969 {
1970 XSD_CREATE_WITH_FIXED_ATTR(cp::mesh_type, mesh_to_load, "cm");
1971 mpParameters->Simulation()->Mesh().set(mesh_to_load);
1972 }
1973
1974 cp::slab_type slab_definition(x, y, z, inter_node_space);
1975 mpParameters->Simulation()->Mesh()->Slab().set(slab_definition);
1976}
1977
1978void HeartConfig::SetSheetDimensions(double x, double y, double inter_node_space)
1979{
1980 if (!mpParameters->Simulation()->Mesh().present())
1981 {
1982 XSD_CREATE_WITH_FIXED_ATTR(cp::mesh_type, mesh_to_load, "cm");
1983 mpParameters->Simulation()->Mesh().set(mesh_to_load);
1984 }
1985
1986 cp::sheet_type sheet_definition(x, y, inter_node_space);
1987 mpParameters->Simulation()->Mesh()->Sheet().set(sheet_definition);
1988}
1989
1990void HeartConfig::SetFibreLength(double x, double inter_node_space)
1991{
1992 if (!mpParameters->Simulation()->Mesh().present())
1993 {
1994 XSD_CREATE_WITH_FIXED_ATTR(cp::mesh_type, mesh_to_load, "cm");
1995 mpParameters->Simulation()->Mesh().set(mesh_to_load);
1996 }
1997
1998 cp::fibre_type fibre_definition(x, inter_node_space);
1999 mpParameters->Simulation()->Mesh()->Fibre().set(fibre_definition);
2000}
2001
2002void HeartConfig::SetMeshFileName(std::string meshPrefix, cp::media_type fibreDefinition)
2003{
2004 if (!mpParameters->Simulation()->Mesh().present())
2005 {
2006 XSD_CREATE_WITH_FIXED_ATTR(cp::mesh_type, mesh_to_load, "cm");
2007 mpParameters->Simulation()->Mesh().set(mesh_to_load);
2008 }
2009
2010 XSD_NESTED_TYPE(cp::mesh_type::LoadMesh)
2011 mesh_prefix(meshPrefix, fibreDefinition);
2012 mpParameters->Simulation()->Mesh()->LoadMesh().set(mesh_prefix);
2013}
2014
2015void HeartConfig::SetIonicModelRegions(std::vector<ChasteCuboid<3> >& rDefinedRegions,
2016 std::vector<cp::ionic_model_selection_type>& rIonicModels) const
2017{
2018 assert(rDefinedRegions.size() == rIonicModels.size());
2019 // You need to have defined a default model first...
2020 assert(mpParameters->Simulation()->IonicModels().present());
2021 XSD_SEQUENCE_TYPE(cp::ionic_models_type::Region)& regions = mpParameters->Simulation()->IonicModels()->Region();
2022 regions.clear();
2023 for (unsigned region_index = 0; region_index < rDefinedRegions.size(); region_index++)
2024 {
2025 cp::point_type point_a(rDefinedRegions[region_index].rGetLowerCorner()[0],
2026 rDefinedRegions[region_index].rGetLowerCorner()[1],
2027 rDefinedRegions[region_index].rGetLowerCorner()[2]);
2028
2029 cp::point_type point_b(rDefinedRegions[region_index].rGetUpperCorner()[0],
2030 rDefinedRegions[region_index].rGetUpperCorner()[1],
2031 rDefinedRegions[region_index].rGetUpperCorner()[2]);
2032
2033 XSD_CREATE_WITH_FIXED_ATTR(cp::location_type, locn, "cm");
2034 locn.Cuboid().set(cp::box_type(point_a, point_b));
2035
2036 cp::ionic_model_region_type region(rIonicModels[region_index], locn);
2037 regions.push_back(region);
2038 }
2039}
2040
2042 std::vector<c_vector<double, 3> >& rIntraConductivities,
2043 std::vector<c_vector<double, 3> >& rExtraConductivities)
2044{
2045 assert(rConductivityAreas.size() == rIntraConductivities.size());
2046 assert(rIntraConductivities.size() == rExtraConductivities.size());
2047
2048 XSD_ANON_SEQUENCE_TYPE(cp::physiological_type, ConductivityHeterogeneities, ConductivityHeterogeneity)
2049 heterogeneities_container;
2050
2051 for (unsigned region_index = 0; region_index < rConductivityAreas.size(); region_index++)
2052 {
2053 cp::point_type point_a(rConductivityAreas[region_index].rGetLowerCorner()[0],
2054 rConductivityAreas[region_index].rGetLowerCorner()[1],
2055 rConductivityAreas[region_index].rGetLowerCorner()[2]);
2056
2057 cp::point_type point_b(rConductivityAreas[region_index].rGetUpperCorner()[0],
2058 rConductivityAreas[region_index].rGetUpperCorner()[1],
2059 rConductivityAreas[region_index].rGetUpperCorner()[2]);
2060
2061 XSD_CREATE_WITH_FIXED_ATTR(cp::location_type, locn, "cm");
2062 locn.Cuboid().set(cp::box_type(point_a, point_b));
2063 cp::conductivity_heterogeneity_type ht(locn);
2064
2065 XSD_CREATE_WITH_FIXED_ATTR3(cp::conductivities_type, intra,
2066 rIntraConductivities[region_index][0],
2067 rIntraConductivities[region_index][1],
2068 rIntraConductivities[region_index][2],
2069 "mS/cm");
2070
2071 ht.IntracellularConductivities(intra);
2072
2073 XSD_CREATE_WITH_FIXED_ATTR3(cp::conductivities_type, extra,
2074 rExtraConductivities[region_index][0],
2075 rExtraConductivities[region_index][1],
2076 rExtraConductivities[region_index][2],
2077 "mS/cm");
2078
2079 ht.ExtracellularConductivities(extra);
2080
2081 heterogeneities_container.push_back(ht);
2082 }
2083
2084 XSD_ANON_TYPE(cp::physiological_type, ConductivityHeterogeneities)
2085 heterogeneities_object;
2086 heterogeneities_object.ConductivityHeterogeneity(heterogeneities_container);
2087
2088 mpParameters->Physiological().ConductivityHeterogeneities().set(heterogeneities_object);
2089}
2090
2092 std::vector<c_vector<double, 3> >& rIntraConductivities,
2093 std::vector<c_vector<double, 3> >& rExtraConductivities)
2094{
2095 assert(rConductivityAreas.size() == rIntraConductivities.size());
2096 assert(rIntraConductivities.size() == rExtraConductivities.size());
2097
2098 XSD_ANON_SEQUENCE_TYPE(cp::physiological_type, ConductivityHeterogeneities, ConductivityHeterogeneity)
2099 heterogeneities_container;
2100
2101 for (unsigned region_index = 0; region_index < rConductivityAreas.size(); region_index++)
2102 {
2103 cp::point_type centre(rConductivityAreas[region_index].rGetCentre()[0],
2104 rConductivityAreas[region_index].rGetCentre()[1],
2105 rConductivityAreas[region_index].rGetCentre()[2]);
2106
2107 cp::point_type radii(rConductivityAreas[region_index].rGetRadii()[0],
2108 rConductivityAreas[region_index].rGetRadii()[1],
2109 rConductivityAreas[region_index].rGetRadii()[2]);
2110
2111 XSD_CREATE_WITH_FIXED_ATTR(cp::location_type, locn, "cm");
2112 locn.Ellipsoid().set(cp::ellipsoid_type(centre, radii));
2113 cp::conductivity_heterogeneity_type ht(locn);
2114
2115 XSD_CREATE_WITH_FIXED_ATTR3(cp::conductivities_type, intra,
2116 rIntraConductivities[region_index][0],
2117 rIntraConductivities[region_index][1],
2118 rIntraConductivities[region_index][2],
2119 "mS/cm");
2120
2121 ht.IntracellularConductivities(intra);
2122
2123 XSD_CREATE_WITH_FIXED_ATTR3(cp::conductivities_type, extra,
2124 rExtraConductivities[region_index][0],
2125 rExtraConductivities[region_index][1],
2126 rExtraConductivities[region_index][2],
2127 "mS/cm");
2128
2129 ht.ExtracellularConductivities(extra);
2130
2131 heterogeneities_container.push_back(ht);
2132 }
2133
2134 XSD_ANON_TYPE(cp::physiological_type, ConductivityHeterogeneities)
2135 heterogeneities_object;
2136 heterogeneities_object.ConductivityHeterogeneity(heterogeneities_container);
2137
2138 mpParameters->Physiological().ConductivityHeterogeneities().set(heterogeneities_object);
2139}
2140
2141void HeartConfig::SetOutputDirectory(const std::string& rOutputDirectory)
2142{
2143 mpParameters->Simulation()->OutputDirectory().set(rOutputDirectory);
2144}
2145
2146void HeartConfig::SetOutputFilenamePrefix(const std::string& rOutputFilenamePrefix)
2147{
2148 mpParameters->Simulation()->OutputFilenamePrefix().set(rOutputFilenamePrefix);
2149}
2150
2151void HeartConfig::SetOutputVariables(const std::vector<std::string>& rOutputVariables)
2152{
2153 if (!mpParameters->Simulation()->OutputVariables().present())
2154 {
2155 cp::output_variables_type variables_requested;
2156 mpParameters->Simulation()->OutputVariables().set(variables_requested);
2157 }
2158
2159 XSD_SEQUENCE_TYPE(cp::output_variables_type::Var)& var_type_sequence = mpParameters->Simulation()->OutputVariables()->Var();
2160 // Erase or create a sequence
2161 var_type_sequence.clear();
2162
2163 for (unsigned i = 0; i < rOutputVariables.size(); i++)
2164 {
2165 cp::var_type temp(rOutputVariables[i]);
2166 var_type_sequence.push_back(temp);
2167 }
2168}
2169
2171{
2172 //What if it doesn't exist?
2173 mpParameters->Simulation()->OutputUsingOriginalNodeOrdering().set(useOriginal ? cp::yesno_type::yes : cp::yesno_type::no);
2174}
2175
2176void HeartConfig::SetCheckpointSimulation(bool saveSimulation, double checkpointTimestep, unsigned maxCheckpointsOnDisk)
2177{
2178 if (saveSimulation)
2179 {
2180 // Make sure values for the optional parameters have been provided
2181 assert(checkpointTimestep != -1.0 && maxCheckpointsOnDisk != UINT_MAX);
2182
2183 XSD_CREATE_WITH_FIXED_ATTR2(cp::simulation_type::XSD_NESTED_TYPE(CheckpointSimulation),
2184 cs,
2185 checkpointTimestep,
2186 maxCheckpointsOnDisk,
2187 "ms");
2188 mpParameters->Simulation()->CheckpointSimulation().set(cs);
2189 }
2190 else
2191 {
2192 mpParameters->Simulation()->CheckpointSimulation().reset();
2193 }
2194
2196}
2197
2198// Physiological
2199
2200void HeartConfig::SetIntracellularConductivities(const c_vector<double, 3>& rIntraConductivities)
2201{
2202 XSD_CREATE_WITH_FIXED_ATTR3(cp::conductivities_type, intra,
2203 rIntraConductivities[0],
2204 rIntraConductivities[1],
2205 rIntraConductivities[2],
2206 "mS/cm");
2207
2208 mpParameters->Physiological().IntracellularConductivities().set(intra);
2209}
2210
2211void HeartConfig::SetIntracellularConductivities(const c_vector<double, 2>& rIntraConductivities)
2212{
2213 XSD_CREATE_WITH_FIXED_ATTR3(cp::conductivities_type, intra,
2214 rIntraConductivities[0],
2215 rIntraConductivities[1],
2216 0.0, "mS/cm");
2217
2218 mpParameters->Physiological().IntracellularConductivities().set(intra);
2219}
2220
2221void HeartConfig::SetIntracellularConductivities(const c_vector<double, 1>& rIntraConductivities)
2222{
2223 XSD_CREATE_WITH_FIXED_ATTR3(cp::conductivities_type, intra,
2224 rIntraConductivities[0],
2225 0.0, 0.0, "mS/cm");
2226
2227 mpParameters->Physiological().IntracellularConductivities().set(intra);
2228}
2229
2230void HeartConfig::SetExtracellularConductivities(const c_vector<double, 3>& rExtraConductivities)
2231{
2232 XSD_CREATE_WITH_FIXED_ATTR3(cp::conductivities_type, extra,
2233 rExtraConductivities[0],
2234 rExtraConductivities[1],
2235 rExtraConductivities[2],
2236 "mS/cm");
2237
2238 mpParameters->Physiological().ExtracellularConductivities().set(extra);
2239}
2240
2241void HeartConfig::SetExtracellularConductivities(const c_vector<double, 2>& rExtraConductivities)
2242{
2243 XSD_CREATE_WITH_FIXED_ATTR3(cp::conductivities_type, extra,
2244 rExtraConductivities[0],
2245 rExtraConductivities[1],
2246 0.0, "mS/cm");
2247
2248 mpParameters->Physiological().ExtracellularConductivities().set(extra);
2249}
2250
2251void HeartConfig::SetExtracellularConductivities(const c_vector<double, 1>& rExtraConductivities)
2252{
2253 XSD_CREATE_WITH_FIXED_ATTR3(cp::conductivities_type, extra,
2254 rExtraConductivities[0],
2255 0.0, 0.0, "mS/cm");
2256
2257 mpParameters->Physiological().ExtracellularConductivities().set(extra);
2258}
2259
2260void HeartConfig::SetBathConductivity(double bathConductivity)
2261{
2262 XSD_CREATE_WITH_FIXED_ATTR1(cp::conductivity_type, cond, bathConductivity, "mS/cm");
2263 mpParameters->Physiological().BathConductivity().set(cond);
2264}
2265
2266void HeartConfig::SetBathMultipleConductivities(std::map<unsigned, double> bathConductivities)
2267{
2269 mBathConductivities = bathConductivities;
2270}
2271
2272//void HeartConfig::SetTissueIdentifiers(const std::set<unsigned>& tissueIds)
2273//{
2274// std::set<unsigned> empty_bath_identifiers; //Too dangerous (see GetValidBathId)
2275// SetTissueAndBathIdentifiers(tissueIds, mBathIdentifiers);
2276//}
2277
2278void HeartConfig::SetTissueAndBathIdentifiers(const std::set<unsigned>& tissueIds, const std::set<unsigned>& bathIds)
2279{
2280 if (tissueIds.empty() || bathIds.empty())
2281 {
2282 EXCEPTION("Identifying set must be non-empty");
2283 }
2284 std::set<unsigned> shared_identifiers;
2285 std::set_intersection(tissueIds.begin(),
2286 tissueIds.end(),
2287 bathIds.begin(),
2288 bathIds.end(),
2289 std::inserter(shared_identifiers, shared_identifiers.begin()));
2290
2291 if (!shared_identifiers.empty())
2292 {
2293 EXCEPTION("Tissue identifiers and bath identifiers overlap");
2294 }
2295 mTissueIdentifiers = tissueIds;
2296 mBathIdentifiers = bathIds;
2297}
2298
2300{
2301 XSD_CREATE_WITH_FIXED_ATTR1(cp::inverse_length_type, ratio_object, ratio, "1/cm");
2302 mpParameters->Physiological().SurfaceAreaToVolumeRatio().set(ratio_object);
2303}
2304
2305void HeartConfig::SetCapacitance(double capacitance)
2306{
2307 XSD_CREATE_WITH_FIXED_ATTR1(cp::capacitance_type, capacitance_object, capacitance, "uF/cm^2");
2308 mpParameters->Physiological().Capacitance().set(capacitance_object);
2309}
2310
2311// Numerical
2312void HeartConfig::SetOdePdeAndPrintingTimeSteps(double odeTimeStep, double pdeTimeStep, double printingTimeStep)
2313{
2314 XSD_CREATE_WITH_FIXED_ATTR3(cp::time_steps_type, time_steps,
2315 odeTimeStep, pdeTimeStep, printingTimeStep, "ms");
2316 mpParameters->Numerical().TimeSteps().set(time_steps);
2318}
2319
2320void HeartConfig::SetOdeTimeStep(double odeTimeStep)
2321{
2323}
2324
2325void HeartConfig::SetPdeTimeStep(double pdeTimeStep)
2326{
2328}
2329
2330void HeartConfig::SetPrintingTimeStep(double printingTimeStep)
2331{
2333}
2334
2336{
2337 if (GetOdeTimeStep() <= 0)
2338 {
2339 EXCEPTION("Ode time-step should be positive");
2340 }
2341 if (GetPdeTimeStep() <= 0)
2342 {
2343 EXCEPTION("Pde time-step should be positive");
2344 }
2345 if (GetPrintingTimeStep() <= 0.0)
2346 {
2347 EXCEPTION("Printing time-step should be positive");
2348 }
2349
2351 {
2352 EXCEPTION("Printing time-step should not be smaller than PDE time-step");
2353 }
2354
2355 if (!Divides(GetPdeTimeStep(), GetPrintingTimeStep()))
2356 {
2357 EXCEPTION("Printing time-step should be a multiple of PDE time step");
2358 }
2359
2361 {
2362 EXCEPTION("Ode time-step should not be greater than PDE time-step");
2363 }
2364
2366 {
2367 if (GetCheckpointTimestep() <= 0.0)
2368 {
2369 EXCEPTION("Checkpoint time-step should be positive");
2370 }
2371
2372 if (!Divides(GetPrintingTimeStep(), GetCheckpointTimestep()))
2373 {
2374 EXCEPTION("Checkpoint time-step should be a multiple of printing time-step");
2375 }
2376 }
2377}
2378
2379void HeartConfig::SetUseRelativeTolerance(double relativeTolerance)
2380{
2381 ENSURE_SECTION_PRESENT(mpParameters->Numerical().KSPTolerances(), cp::ksp_tolerances_type);
2382 //Remove any reference to tolerances is user parameters
2383 mpParameters->Numerical().KSPTolerances()->KSPAbsolute().reset();
2384 mpParameters->Numerical().KSPTolerances()->KSPRelative().set(relativeTolerance);
2385}
2386
2387void HeartConfig::SetUseAbsoluteTolerance(double absoluteTolerance)
2388{
2389 ENSURE_SECTION_PRESENT(mpParameters->Numerical().KSPTolerances(), cp::ksp_tolerances_type);
2390 //Remove any reference to tolerances is user parameters
2391 mpParameters->Numerical().KSPTolerances()->KSPRelative().reset();
2392 mpParameters->Numerical().KSPTolerances()->KSPAbsolute().set(absoluteTolerance);
2393}
2394
2395void HeartConfig::SetKSPSolver(const char* kspSolver, bool warnOfChange)
2396{
2397 if (warnOfChange && strcmp(GetKSPSolver(), kspSolver) != 0)
2398 {
2399 //Warn
2400 WARNING("Code has changed the KSP solver type from " << GetKSPSolver() << " to " << kspSolver);
2401 }
2402
2403 /* Note that changes in these conditions need to be reflected in the Doxygen*/
2404 if (strcmp(kspSolver, "gmres") == 0)
2405 {
2406 mpParameters->Numerical().KSPSolver().set(cp::ksp_solver_type::gmres);
2407 return;
2408 }
2409 if (strcmp(kspSolver, "cg") == 0)
2410 {
2411 mpParameters->Numerical().KSPSolver().set(cp::ksp_solver_type::cg);
2412 return;
2413 }
2414 if (strcmp(kspSolver, "symmlq") == 0)
2415 {
2416 mpParameters->Numerical().KSPSolver().set(cp::ksp_solver_type::symmlq);
2417 return;
2418 }
2419 if (strcmp(kspSolver, "chebychev") == 0)
2420 {
2421 mpParameters->Numerical().KSPSolver().set(cp::ksp_solver_type::chebychev);
2422 return;
2423 }
2424
2425 EXCEPTION("Unknown solver type provided");
2426}
2427
2428void HeartConfig::SetKSPPreconditioner(const char* kspPreconditioner)
2429{
2430 /* Note that changes in these conditions need to be reflected in the Doxygen*/
2431 if (strcmp(kspPreconditioner, "jacobi") == 0)
2432 {
2433 mpParameters->Numerical().KSPPreconditioner().set(cp::ksp_preconditioner_type::jacobi);
2434 return;
2435 }
2436 if (strcmp(kspPreconditioner, "bjacobi") == 0)
2437 {
2438 mpParameters->Numerical().KSPPreconditioner().set(cp::ksp_preconditioner_type::bjacobi);
2439 return;
2440 }
2441 if (strcmp(kspPreconditioner, "hypre") == 0)
2442 {
2443 mpParameters->Numerical().KSPPreconditioner().set(cp::ksp_preconditioner_type::hypre);
2444 return;
2445 }
2446 if (strcmp(kspPreconditioner, "ml") == 0)
2447 {
2448 mpParameters->Numerical().KSPPreconditioner().set(cp::ksp_preconditioner_type::ml);
2449 return;
2450 }
2451 if (strcmp(kspPreconditioner, "spai") == 0)
2452 {
2453 mpParameters->Numerical().KSPPreconditioner().set(cp::ksp_preconditioner_type::spai);
2454 return;
2455 }
2456 if (strcmp(kspPreconditioner, "twolevelsblockdiagonal") == 0)
2457 {
2458 mpParameters->Numerical().KSPPreconditioner().set(cp::ksp_preconditioner_type::twolevelsblockdiagonal);
2459 return;
2460 }
2461 if (strcmp(kspPreconditioner, "blockdiagonal") == 0)
2462 {
2463 mpParameters->Numerical().KSPPreconditioner().set(cp::ksp_preconditioner_type::blockdiagonal);
2464 return;
2465 }
2466 if (strcmp(kspPreconditioner, "ldufactorisation") == 0)
2467 {
2468 mpParameters->Numerical().KSPPreconditioner().set(cp::ksp_preconditioner_type::ldufactorisation);
2469 return;
2470 }
2471 if (strcmp(kspPreconditioner, "none") == 0)
2472 {
2473 mpParameters->Numerical().KSPPreconditioner().set(cp::ksp_preconditioner_type::none);
2474 return;
2475 }
2476
2477 EXCEPTION("Unknown preconditioner type provided");
2478}
2479
2480void HeartConfig::SetMeshPartitioning(const char* meshPartioningMethod)
2481{
2482 /* Note that changes in these conditions need to be reflected in the Doxygen*/
2483 if (strcmp(meshPartioningMethod, "dumb") == 0)
2484 {
2485 mpParameters->Numerical().MeshPartitioning().set(cp::mesh_partitioning_type::dumb);
2486 return;
2487 }
2488 if (strcmp(meshPartioningMethod, "metis") == 0)
2489 {
2490 WARNING("METIS library partitioning is deprecated")
2491 mpParameters->Numerical().MeshPartitioning().set(cp::mesh_partitioning_type::metis);
2492 return;
2493 }
2494 if (strcmp(meshPartioningMethod, "parmetis") == 0)
2495 {
2496 mpParameters->Numerical().MeshPartitioning().set(cp::mesh_partitioning_type::parmetis);
2497 return;
2498 }
2499 if (strcmp(meshPartioningMethod, "petsc") == 0)
2500 {
2501 mpParameters->Numerical().MeshPartitioning().set(cp::mesh_partitioning_type::petsc);
2502 return;
2503 }
2504
2505 EXCEPTION("Unknown mesh partitioning method provided");
2506}
2507
2508void HeartConfig::SetApdMaps(const std::vector<std::pair<double, double> >& apdMaps)
2509{
2511 auto& apd_maps_sequence = mpParameters->PostProcessing()->ActionPotentialDurationMap();
2512 //Erase or create a sequence
2513 apd_maps_sequence.clear();
2514
2515 for (unsigned i = 0; i < apdMaps.size(); i++)
2516 {
2517 XSD_CREATE_WITH_FIXED_ATTR2(cp::apd_map_type, temp,
2518 apdMaps[i].first, apdMaps[i].second,
2519 "mV");
2520 apd_maps_sequence.push_back(temp);
2521 }
2522}
2523
2524void HeartConfig::SetUpstrokeTimeMaps(std::vector<double>& upstrokeTimeMaps)
2525{
2527 auto& var_type_sequence = mpParameters->PostProcessing()->UpstrokeTimeMap();
2528
2529 //Erase or create a sequence
2530 var_type_sequence.clear();
2531
2532 for (unsigned i = 0; i < upstrokeTimeMaps.size(); i++)
2533 {
2534 XSD_CREATE_WITH_FIXED_ATTR1(cp::upstrokes_map_type, temp,
2535 upstrokeTimeMaps[i],
2536 "mV");
2537 var_type_sequence.push_back(temp);
2538 }
2539}
2540
2541void HeartConfig::SetMaxUpstrokeVelocityMaps(std::vector<double>& maxUpstrokeVelocityMaps)
2542{
2544 auto& max_upstroke_velocity_maps_sequence = mpParameters->PostProcessing()->MaxUpstrokeVelocityMap();
2545
2546 //Erase or create a sequence
2547 max_upstroke_velocity_maps_sequence.clear();
2548
2549 for (unsigned i = 0; i < maxUpstrokeVelocityMaps.size(); i++)
2550 {
2551 XSD_CREATE_WITH_FIXED_ATTR1(cp::max_upstrokes_velocity_map_type, temp,
2552 maxUpstrokeVelocityMaps[i],
2553 "mV");
2554
2555 max_upstroke_velocity_maps_sequence.push_back(temp);
2556 }
2557}
2558
2559void HeartConfig::SetConductionVelocityMaps(std::vector<unsigned>& conductionVelocityMaps)
2560{
2562 auto& conduction_velocity_maps_sequence = mpParameters->PostProcessing()->ConductionVelocityMap();
2563
2564 //Erase or create a sequence
2565 conduction_velocity_maps_sequence.clear();
2566
2567 for (unsigned i = 0; i < conductionVelocityMaps.size(); i++)
2568 {
2569 cp::conduction_velocity_map_type temp(conductionVelocityMaps[i]);
2570 conduction_velocity_maps_sequence.push_back(temp);
2571 }
2572}
2573
2574void HeartConfig::SetRequestedNodalTimeTraces(std::vector<unsigned>& requestedNodes)
2575{
2577 auto& requested_nodes_sequence = mpParameters->PostProcessing()->TimeTraceAtNode();
2578
2579 //Erase or create a sequence
2580 requested_nodes_sequence.clear();
2581
2582 for (unsigned i = 0; i < requestedNodes.size(); i++)
2583 {
2584 cp::node_number_type temp(requestedNodes[i]);
2585 requested_nodes_sequence.push_back(temp);
2586 }
2587}
2588
2589template <unsigned SPACE_DIM>
2590void HeartConfig::SetPseudoEcgElectrodePositions(const std::vector<ChastePoint<SPACE_DIM> >& rPseudoEcgElectrodePositions)
2591{
2593 auto& electrodes_sequence = mpParameters->PostProcessing()->PseudoEcgElectrodePosition();
2594
2595 //Erase or create a sequence
2596 electrodes_sequence.clear();
2597
2598 for (unsigned i = 0; i < rPseudoEcgElectrodePositions.size(); i++)
2599 {
2600 cp::point_type temp(rPseudoEcgElectrodePositions[i].GetWithDefault(0),
2601 rPseudoEcgElectrodePositions[i].GetWithDefault(1),
2602 rPseudoEcgElectrodePositions[i].GetWithDefault(2));
2603 electrodes_sequence.push_back(temp);
2604 }
2605}
2606
2607/*
2608 * Output visualizer
2609 */
2610
2612{
2613 ENSURE_SECTION_PRESENT(mpParameters->Simulation()->OutputVisualizer(), cp::output_visualizer_type);
2614}
2615
2617{
2619
2620 mpParameters->Simulation()->OutputVisualizer()->meshalyzer(
2621 useMeshalyzer ? cp::yesno_type::yes : cp::yesno_type::no);
2622}
2623
2625{
2627
2628 mpParameters->Simulation()->OutputVisualizer()->cmgui(
2629 useCmgui ? cp::yesno_type::yes : cp::yesno_type::no);
2630}
2631
2633{
2635
2636 mpParameters->Simulation()->OutputVisualizer()->vtk(
2637 useVtk ? cp::yesno_type::yes : cp::yesno_type::no);
2638}
2639
2641{
2643
2644 mpParameters->Simulation()->OutputVisualizer()->parallel_vtk(
2645 useParallelVtk ? cp::yesno_type::yes : cp::yesno_type::no);
2646}
2647
2649{
2651
2652 mpParameters->Simulation()->OutputVisualizer()->precision(numberOfDigits);
2653}
2654
2655void HeartConfig::SetElectrodeParameters(bool groundSecondElectrode,
2656 unsigned index, double magnitude,
2657 double startTime, double duration)
2658{
2659 assert(index < 3);
2660
2661 cp::axis_type axis = cp::axis_type::x;
2662 if (index == 1)
2663 {
2664 axis = cp::axis_type::y;
2665 }
2666 else if (index == 2)
2667 {
2668 axis = cp::axis_type::z;
2669 }
2670
2671 XSD_CREATE_WITH_FIXED_ATTR1(cp::surface_stimulus_strength_type, strength, magnitude, "uA/cm^2");
2672 XSD_CREATE_WITH_FIXED_ATTR1(cp::time_type, start_time, startTime, "ms");
2673 XSD_CREATE_WITH_FIXED_ATTR1(cp::time_type, duration_time, duration, "ms");
2674
2675 if (!IsElectrodesPresent())
2676 {
2677 cp::electrodes_type element(groundSecondElectrode ? cp::yesno_type::yes : cp::yesno_type::no,
2678 axis,
2679 strength,
2680 start_time,
2681 duration_time);
2682 mpParameters->Simulation()->Electrodes().set(element);
2683 }
2684 else
2685 {
2686 mpParameters->Simulation()->Electrodes()->GroundSecondElectrode(groundSecondElectrode ? cp::yesno_type::yes : cp::yesno_type::no);
2687 mpParameters->Simulation()->Electrodes()->PerpendicularToAxis(axis);
2688 mpParameters->Simulation()->Electrodes()->Strength(strength);
2689 mpParameters->Simulation()->Electrodes()->StartTime(start_time);
2690 mpParameters->Simulation()->Electrodes()->Duration(duration_time);
2691 }
2692}
2693
2694void HeartConfig::GetElectrodeParameters(bool& rGroundSecondElectrode,
2695 unsigned& rIndex, double& rMagnitude,
2696 double& rStartTime, double& rDuration)
2697{
2698 if (!IsElectrodesPresent())
2699 {
2700 EXCEPTION("Attempted to get electrodes that have not been defined.");
2701 }
2702 else
2703 {
2704 rGroundSecondElectrode = (mpParameters->Simulation()->Electrodes()->GroundSecondElectrode() == cp::yesno_type::yes);
2705
2706 cp::axis_type axis = mpParameters->Simulation()->Electrodes()->PerpendicularToAxis();
2707 if (axis == cp::axis_type::x)
2708 {
2709 rIndex = 0;
2710 }
2711 else if (axis == cp::axis_type::y)
2712 {
2713 rIndex = 1;
2714 }
2715 else
2716 {
2717 rIndex = 2;
2718 }
2719
2720 rMagnitude = mpParameters->Simulation()->Electrodes()->Strength();
2721 rStartTime = mpParameters->Simulation()->Electrodes()->StartTime();
2722 rDuration = mpParameters->Simulation()->Electrodes()->Duration();
2723 }
2724}
2725
2727{
2728 // If it's an older version parameters & defaults (we're loading a checkpoint) say 'no'
2729 bool result = false;
2730 if (mpParameters->Numerical().UseStateVariableInterpolation().present())
2731 {
2732 result = mpParameters->Numerical().UseStateVariableInterpolation().get() == cp::yesno_type::yes;
2733 }
2734 return result;
2735}
2736
2737void HeartConfig::SetUseStateVariableInterpolation(bool useStateVariableInterpolation)
2738{
2739 if (useStateVariableInterpolation)
2740 {
2741 mpParameters->Numerical().UseStateVariableInterpolation().set(cp::yesno_type::yes);
2742 }
2743 else
2744 {
2745 mpParameters->Numerical().UseStateVariableInterpolation().set(cp::yesno_type::no);
2746 }
2747}
2748
2750{
2751 return mpParameters->Physiological().ApplyDrug().present();
2752}
2753
2755{
2756 CHECK_EXISTS(HasDrugDose(), "Physiological/ApplyDrug");
2757 return mpParameters->Physiological().ApplyDrug()->concentration();
2758}
2759
2760void HeartConfig::SetDrugDose(double drugDose)
2761{
2762 if (!mpParameters->Physiological().ApplyDrug().present())
2763 {
2764 cp::apply_drug_type drug(drugDose);
2765 mpParameters->Physiological().ApplyDrug().set(drug);
2766 }
2767 else
2768 {
2769 mpParameters->Physiological().ApplyDrug()->concentration(drugDose);
2770 }
2771}
2772
2773std::map<std::string, std::pair<double, double> > HeartConfig::GetIc50Values()
2774{
2775 CHECK_EXISTS(HasDrugDose(), "Physiological/ApplyDrug");
2776 std::map<std::string, std::pair<double, double> > ic50s;
2777
2778 XSD_SEQUENCE_TYPE(cp::apply_drug_type::IC50)& ic50_seq = mpParameters->Physiological().ApplyDrug()->IC50();
2779
2780 for (XSD_ITERATOR_TYPE(cp::apply_drug_type::IC50) i = ic50_seq.begin();
2781 i != ic50_seq.end();
2782 ++i)
2783 {
2784 std::pair<double, double> ic50_hill(*i, i->hill());
2785 std::string current = i->current();
2786 ic50s[current] = ic50_hill;
2787 }
2788
2789 return ic50s;
2790}
2791
2792void HeartConfig::SetIc50Value(const std::string& rCurrentName, double ic50, double hill)
2793{
2794 if (!mpParameters->Physiological().ApplyDrug().present())
2795 {
2796 SetDrugDose(0.0);
2797 }
2798 XSD_SEQUENCE_TYPE(cp::apply_drug_type::IC50)& ic50_seq = mpParameters->Physiological().ApplyDrug()->IC50();
2799 if (ic50_seq.empty())
2800 {
2801 // Erase or create a sequence
2802 ic50_seq.clear();
2803 }
2804 bool entry_exists = false;
2805 cp::ic50_type ic50_elt(ic50, rCurrentName);
2806 ic50_elt.hill(hill);
2807 for (XSD_ITERATOR_TYPE(cp::apply_drug_type::IC50) i = ic50_seq.begin();
2808 i != ic50_seq.end();
2809 ++i)
2810 {
2811 if (i->current() == rCurrentName)
2812 {
2813 entry_exists = true;
2814 *i = ic50_elt;
2815 break;
2816 }
2817 }
2818 if (!entry_exists)
2819 {
2820 ic50_seq.push_back(ic50_elt);
2821 }
2822}
2823
2824void HeartConfig::SetUseMassLumping(bool useMassLumping)
2825{
2826 mUseMassLumping = useMassLumping;
2827}
2828
2830{
2831 return mUseMassLumping;
2832}
2833
2835{
2836 mUseMassLumpingForPrecond = useMassLumping;
2837}
2838
2843
2845{
2846 mUseReactionDiffusionOperatorSplitting = useOperatorSplitting;
2847}
2848
2853
2854void HeartConfig::SetUseFixedNumberIterationsLinearSolver(bool useFixedNumberIterations, unsigned evaluateNumItsEveryNSolves)
2855{
2856 mUseFixedNumberIterations = useFixedNumberIterations;
2857 mEvaluateNumItsEveryNSolves = evaluateNumItsEveryNSolves;
2858}
2859
2864
2869
2870//
2871// Purkinje methods
2872//
2873
2875{
2876 CheckSimulationIsDefined("Purkinje");
2877 return mpParameters->Simulation()->Purkinje().present();
2878}
2879
2881{
2882 CHECK_EXISTS(mpParameters->Physiological().Purkinje().present(), "Physiological/Purkinje");
2883 CHECK_EXISTS(mpParameters->Physiological().Purkinje()->Capacitance().present(),
2884 "Physiological/Purkinje/Capacitance");
2885 return mpParameters->Physiological().Purkinje()->Capacitance().get();
2886}
2887
2889{
2890 ENSURE_SECTION_PRESENT(mpParameters->Physiological().Purkinje(), cp::purkinje_physiological_type);
2891 XSD_CREATE_WITH_FIXED_ATTR1(cp::capacitance_type, purk_Cm, capacitance, "uF/cm^2");
2892 mpParameters->Physiological().Purkinje()->Capacitance().set(purk_Cm);
2893}
2894
2896{
2897 CHECK_EXISTS(mpParameters->Physiological().Purkinje().present(), "Physiological/Purkinje");
2898 CHECK_EXISTS(mpParameters->Physiological().Purkinje()->SurfaceAreaToVolumeRatio().present(),
2899 "Physiological/Purkinje/SurfaceAreaToVolumeRatio");
2900 return mpParameters->Physiological().Purkinje()->SurfaceAreaToVolumeRatio().get();
2901}
2902
2904{
2905 ENSURE_SECTION_PRESENT(mpParameters->Physiological().Purkinje(), cp::purkinje_physiological_type);
2906 XSD_CREATE_WITH_FIXED_ATTR1(cp::inverse_length_type, purk_Am, ratio, "1/cm");
2907 mpParameters->Physiological().Purkinje()->SurfaceAreaToVolumeRatio().set(purk_Am);
2908}
2909
2911{
2912 CHECK_EXISTS(mpParameters->Physiological().Purkinje().present(), "Physiological/Purkinje");
2913 CHECK_EXISTS(mpParameters->Physiological().Purkinje()->Conductivity().present(),
2914 "Physiological/Purkinje/Conductivity");
2915 return mpParameters->Physiological().Purkinje()->Conductivity().get();
2916}
2917
2919{
2920 ENSURE_SECTION_PRESENT(mpParameters->Physiological().Purkinje(), cp::purkinje_physiological_type);
2921 XSD_CREATE_WITH_FIXED_ATTR1(cp::conductivity_type, purkinje_conductivity, conductivity, "mS/cm");
2922 mpParameters->Physiological().Purkinje()->Conductivity().set(purkinje_conductivity);
2923}
2924
2925/**********************************************************************
2926 * *
2927 * *
2928 * Utility methods for reading/transforming XML *
2929 * *
2930 * *
2931 **********************************************************************/
2932
2933void XmlTransforms::TransformArchiveDirectory(xercesc::DOMDocument* pDocument,
2934 xercesc::DOMElement* pRootElement)
2935{
2936 using namespace xercesc;
2937 std::vector<xercesc::DOMElement*> elts = XmlTools::FindElements(
2938 pRootElement,
2939 "ResumeSimulation/ArchiveDirectory");
2940 if (elts.size() > 0)
2941 {
2942 // We have an ArchiveDirectory element, so add the relative_to='chaste_test_output' attribute
2943 DOMElement* p_dir_elt = elts[0];
2944 p_dir_elt->setAttribute(X("relative_to"), X("chaste_test_output"));
2945 }
2946}
2947
2948void XmlTransforms::TransformIonicModelDefinitions(xercesc::DOMDocument* pDocument,
2949 xercesc::DOMElement* pRootElement)
2950{
2951 // Default ionic model
2952 std::vector<xercesc::DOMElement*> p_elt_list = XmlTools::FindElements(
2953 pRootElement,
2954 "Simulation/IonicModels/Default");
2955 if (p_elt_list.size() > 0)
2956 {
2957 assert(p_elt_list.size() == 1); // Asserted by schema
2958 XmlTools::WrapContentInElement(pDocument, p_elt_list[0], X("Hardcoded"));
2959 // Now do any region-specific definitions
2960 p_elt_list = XmlTools::FindElements(pRootElement, "Simulation/IonicModels/Region/IonicModel");
2961 for (unsigned i = 0; i < p_elt_list.size(); i++)
2962 {
2963 XmlTools::WrapContentInElement(pDocument, p_elt_list[i], X("Hardcoded"));
2964 }
2965 }
2966}
2967
2968void XmlTransforms::CheckForIluPreconditioner(xercesc::DOMDocument* pDocument,
2969 xercesc::DOMElement* pRootElement)
2970{
2971 std::vector<xercesc::DOMElement*> p_elt_list = XmlTools::FindElements(
2972 pRootElement,
2973 "Numerical/KSPPreconditioner");
2974 if (p_elt_list.size() > 0)
2975 {
2976 assert(p_elt_list.size() == 1); // Asserted by schema
2977 std::string text_value = X2C(p_elt_list[0]->getTextContent());
2978 if (text_value == "ilu")
2979 {
2980 EXCEPTION("PETSc does not have a parallel implementation of ilu, so we no longer allow it as an option. Use bjacobi instead.");
2981 }
2982 }
2983}
2984
2985void XmlTransforms::MoveConductivityHeterogeneities(xercesc::DOMDocument* pDocument,
2986 xercesc::DOMElement* pRootElement)
2987{
2988 std::vector<xercesc::DOMElement*> p_elt_list = XmlTools::FindElements(
2989 pRootElement,
2990 "Simulation/ConductivityHeterogeneities");
2991 if (p_elt_list.size() > 0)
2992 {
2993 assert(p_elt_list.size() == 1); // Asserted by schema
2994 xercesc::DOMNode* p_parent = p_elt_list[0]->getParentNode();
2995 xercesc::DOMNode* p_child = p_parent->removeChild(p_elt_list[0]);
2996 std::vector<xercesc::DOMElement*> p_phys_list = XmlTools::FindElements(pRootElement, "Physiological");
2997 assert(p_phys_list.size() == 1); // Asserted by schema
2998 p_phys_list[0]->appendChild(p_child);
2999 }
3000}
3001
3002void XmlTransforms::SetDefaultVisualizer(xercesc::DOMDocument* pDocument,
3003 xercesc::DOMElement* pRootElement)
3004{
3005 std::vector<xercesc::DOMElement*> p_sim_list = XmlTools::FindElements(pRootElement, "Simulation");
3006 if (p_sim_list.size() > 0)
3007 {
3008 std::vector<xercesc::DOMElement*> p_viz_list = XmlTools::FindElements(p_sim_list[0], "OutputVisualizer");
3009 if (p_viz_list.empty())
3010 {
3011 // Create the element and set meshalyzer (only) to on
3012 xercesc::DOMElement* p_viz_elt = pDocument->createElementNS(X("https://chaste.comlab.ox.ac.uk/nss/parameters/3_3"), X("OutputVisualizer"));
3013 p_sim_list[0]->appendChild(p_viz_elt);
3014 p_viz_elt->setAttribute(X("meshalyzer"), X("yes"));
3015 }
3016 }
3017}
3018
3020// Explicit instantiation of the templated functions
3022// LCOV_EXCL_START //These methods are covered above with DIM=1,2,3 but the instantiations may fail spuriously
3027template void HeartConfig::GetIonicModelRegions<3u>(std::vector<boost::shared_ptr<AbstractChasteRegion<3u> > >&, std::vector<cp::ionic_model_selection_type>&) const;
3028template void HeartConfig::GetStimuli<3u>(std::vector<boost::shared_ptr<AbstractStimulusFunction> >&, std::vector<boost::shared_ptr<AbstractChasteRegion<3u> > >&) const;
3029template 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> >*);
3030template void HeartConfig::GetConductivityHeterogeneities<3u>(std::vector<boost::shared_ptr<AbstractChasteRegion<3u> > >&, std::vector<c_vector<double, 3> >&, std::vector<c_vector<double, 3> >&) const;
3031
3032template void HeartConfig::GetIonicModelRegions<2u>(std::vector<boost::shared_ptr<AbstractChasteRegion<2u> > >&, std::vector<cp::ionic_model_selection_type>&) const;
3033template void HeartConfig::GetStimuli<2u>(std::vector<boost::shared_ptr<AbstractStimulusFunction> >&, std::vector<boost::shared_ptr<AbstractChasteRegion<2u> > >&) const;
3034template 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> >*);
3035template void HeartConfig::GetConductivityHeterogeneities<2u>(std::vector<boost::shared_ptr<AbstractChasteRegion<2u> > >&, std::vector<c_vector<double, 3> >&, std::vector<c_vector<double, 3> >&) const;
3036
3037template void HeartConfig::GetIonicModelRegions<1u>(std::vector<boost::shared_ptr<AbstractChasteRegion<1u> > >&, std::vector<cp::ionic_model_selection_type>&) const;
3038template void HeartConfig::GetStimuli<1u>(std::vector<boost::shared_ptr<AbstractStimulusFunction> >&, std::vector<boost::shared_ptr<AbstractChasteRegion<1u> > >&) const;
3039template 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> >*);
3040template void HeartConfig::GetConductivityHeterogeneities<1u>(std::vector<boost::shared_ptr<AbstractChasteRegion<1u> > >&, std::vector<c_vector<double, 3> >&, std::vector<c_vector<double, 3> >&) const;
3041
3042template void HeartConfig::GetPseudoEcgElectrodePositions(std::vector<ChastePoint<1u> >& rPseudoEcgElectrodePositions) const;
3043template void HeartConfig::GetPseudoEcgElectrodePositions(std::vector<ChastePoint<2u> >& rPseudoEcgElectrodePositions) const;
3044template void HeartConfig::GetPseudoEcgElectrodePositions(std::vector<ChastePoint<3u> >& rPseudoEcgElectrodePositions) const;
3045
3046template void HeartConfig::SetPseudoEcgElectrodePositions(const std::vector<ChastePoint<1u> >& rPseudoEcgElectrodePositions);
3047template void HeartConfig::SetPseudoEcgElectrodePositions(const std::vector<ChastePoint<2u> >& rPseudoEcgElectrodePositions);
3048template void HeartConfig::SetPseudoEcgElectrodePositions(const std::vector<ChastePoint<3u> >& rPseudoEcgElectrodePositions);
3053// LCOV_EXCL_STOP //These methods are covered above with DIM=1,2,3 but the instantiations may fail spuriously
3054
3055// Serialization for Boost >= 1.36
#define EXCEPTION(message)
#define NEVER_REACHED
void MergeDefaults(boost::shared_ptr< cp::chaste_parameters_type > pParams, boost::shared_ptr< cp::chaste_parameters_type > pDefaults)
boost::shared_ptr< cp::chaste_parameters_type > CreateDefaultParameters()
#define CHASTE_CLASS_EXPORT(T)
static std::string GetArchiveDirectory()
static const char * GetRootDir()
virtual void SetPath(const std::string &rPath, RelativeTo::Value relativeTo)
bool Exists() const
FileFinder CopyTo(const FileFinder &rDest) const
static void SetFilePermissions(const fs::path &rPath)
SchemaLocationsMap mSchemaLocations
void SetRequestedNodalTimeTraces(std::vector< unsigned > &requestedNodes)
void GetStimuli(std::vector< boost::shared_ptr< AbstractStimulusFunction > > &rStimuliApplied, std::vector< boost::shared_ptr< AbstractChasteRegion< DIM > > > &rStimulatedAreas) const
DistributedTetrahedralMeshPartitionType::type GetMeshPartitioning() const
bool AreCellularTransmuralHeterogeneitiesRequested()
unsigned GetMaxCheckpointsOnDisk() const
std::map< std::string, std::string > SchemaLocationsMap
bool IsSimulationDefined() const
bool GetLoadMesh() const
void SetUseMassLumpingForPrecond(bool useMassLumping=true)
void SetIntracellularConductivities(const c_vector< double, 3 > &rIntraConductivities)
void GetSheetDimensions(c_vector< double, 2 > &sheetDimensions) const
void SetTissueAndBathIdentifiers(const std::set< unsigned > &rTissueIds, const std::set< unsigned > &rBathIds)
std::string GetMeshName() const
cp::media_type GetConductivityMedia() const
double GetCapacitance() const
std::set< unsigned > mBathIdentifiers
void SetMaxUpstrokeVelocityMaps(std::vector< double > &rMaxUpstrokeVelocityMaps)
void SetConductivityHeterogeneitiesEllipsoid(std::vector< ChasteEllipsoid< 3 > > &rConductivityAreas, std::vector< c_vector< double, 3 > > &rIntraConductivities, std::vector< c_vector< double, 3 > > &rExtraConductivities)
double GetAbsoluteTolerance() const
void SetUseFixedNumberIterationsLinearSolver(bool useFixedNumberIterations=true, unsigned evaluateNumItsEveryNSolves=UINT_MAX)
void SetBathMultipleConductivities(std::map< unsigned, double > bathConductivities)
double GetPurkinjeSurfaceAreaToVolumeRatio()
HeartFileFinder GetArchivedSimulationDir() const
static boost::shared_ptr< HeartConfig > mpInstance
double GetPdeTimeStep() const
bool mUseFixedNumberIterations
double GetDrugDose() const
bool GetCreateFibre() const
double GetPrintingTimeStep() const
void SetDefaultIonicModel(const cp::ionic_models_available_type &rIonicModel)
void CheckResumeSimulationIsDefined(std::string callingMethod="") const
bool GetUseFixedNumberIterationsLinearSolver()
void CopySchema(const std::string &rToDirectory)
void SetElectrodeParameters(bool groundSecondElectrode, unsigned index, double magnitude, double startTime, double duration)
void GetOutputVariables(std::vector< std::string > &rOutputVariables) const
void SetSheetDimensions(double x, double y, double inter_node_space)
bool mUseFixedSchemaLocation
void SetPrintingTimeStep(double printingTimeStep)
boost::shared_ptr< cp::chaste_parameters_type > mpParameters
double GetMidLayerFraction()
void SetFibreLength(double x, double inter_node_space)
unsigned GetVisualizerOutputPrecision()
void SetPurkinjeCapacitance(double capacitance)
bool IsOutputVisualizerPresent() const
void SetUpstrokeTimeMaps(std::vector< double > &rUpstrokeTimeMaps)
void SetApdMaps(const std::vector< std::pair< double, double > > &rApdMaps)
unsigned mIndexEndo
double GetSurfaceAreaToVolumeRatio() const
double GetSimulationDuration() const
void SetDrugDose(double drugDose)
double GetOdeTimeStep() const
FileFinder mParametersFilePath
bool IsPostProcessingSectionPresent() const
bool IsMaxUpstrokeVelocityMapRequested() const
void SetKSPSolver(const char *kspSolver, bool warnOfChange=false)
bool IsPostProcessingRequested() const
void SetUseFixedSchemaLocation(bool useFixedSchemaLocation)
void SetOutputUsingOriginalNodeOrdering(bool useOriginal)
double mMidFraction
bool GetVisualizeWithParallelVtk() const
unsigned GetSpaceDimension() const
bool GetCreateMesh() const
void SetIc50Value(const std::string &rCurrentName, double ic50, double hill=1.0)
bool IsAnyNodalTimeTraceRequested() const
void SetOutputDirectory(const std::string &rOutputDirectory)
std::map< unsigned, double > mBathConductivities
FileFinder GetParametersFilePath()
void EnsurePostProcessingSectionPresent()
void SetUseReactionDiffusionOperatorSplitting(bool useOperatorSplitting=true)
void CheckTimeSteps() const
bool GetUseMassLumping()
void GetConductivityHeterogeneities(std::vector< boost::shared_ptr< AbstractChasteRegion< DIM > > > &conductivitiesHeterogeneityAreas, std::vector< c_vector< double, 3 > > &intraConductivities, std::vector< c_vector< double, 3 > > &extraConductivities) const
void SetDomain(const cp::domain_type &rDomain)
const char * GetKSPPreconditioner() const
bool GetUseAbsoluteTolerance() const
bool IsSimulationResumed() const
void SetFixedSchemaLocations(const SchemaLocationsMap &rSchemaLocations)
bool mUserAskedForCellularTransmuralHeterogeneities
bool GetVisualizeWithCmgui() const
void EnsureOutputVisualizerExists(void)
void SetUseStateVariableInterpolation(bool useStateVariableInterpolation=true)
bool GetOutputUsingOriginalNodeOrdering()
bool IsElectrodesPresent() const
void SetMeshPartitioning(const char *meshPartioningMethod)
bool IsApdMapsRequested() const
bool IsConductionVelocityMapsRequested() const
double GetRelativeTolerance() const
void GetNodalTimeTraceRequested(std::vector< unsigned > &rRequestedNodes) const
unsigned GetMidLayerIndex()
void SetUseRelativeTolerance(double relativeTolerance)
const std::set< unsigned > & rGetBathIdentifiers()
void SetVisualizeWithMeshalyzer(bool useMeshalyzer=true)
void SetPdeTimeStep(double pdeTimeStep)
cp::ionic_model_selection_type GetDefaultIonicModel() const
void SetSlabDimensions(double x, double y, double z, double inter_node_space)
void SetSpaceDimension(unsigned spaceDimension)
unsigned GetEvaluateNumItsEveryNSolves()
boost::shared_ptr< cp::chaste_parameters_type > ReadFile(const std::string &rFileName)
unsigned mEvaluateNumItsEveryNSolves
void GetApdMaps(std::vector< std::pair< double, double > > &rApdMaps) const
void SetSurfaceAreaToVolumeRatio(double ratio)
void GetIonicModelRegions(std::vector< boost::shared_ptr< AbstractChasteRegion< DIM > > > &rDefinedRegions, std::vector< cp::ionic_model_selection_type > &rIonicModels) const
void SetUseAbsoluteTolerance(double absoluteTolerance)
bool GetUseRelativeTolerance() const
void SetPurkinjeSurfaceAreaToVolumeRatio(double ratio)
void SetKSPPreconditioner(const char *kspPreconditioner)
void GetConductionVelocityMaps(std::vector< unsigned > &rConductionVelocityMaps) const
void SetDefaultSchemaLocations()
void SetOdeTimeStep(double odeTimeStep)
bool GetCreateSlab() const
double GetPurkinjeCapacitance()
unsigned GetEpiLayerIndex()
void SetBathConductivity(double bathConductivity)
double GetPurkinjeConductivity()
bool HasDrugDose() const
double mEndoFraction
void SetIonicModelRegions(std::vector< ChasteCuboid< 3 > > &rDefinedRegions, std::vector< cp::ionic_model_selection_type > &rIonicModels) const
bool GetUseReactionDiffusionOperatorSplitting()
void SetVisualizeWithVtk(bool useVtk=true)
void SetExtracellularConductivities(const c_vector< double, 3 > &rExtraConductivities)
std::string GetOutputFilenamePrefix() const
bool GetVisualizeWithMeshalyzer() const
void SetSimulationDuration(double simulationDuration)
void SetCapacitance(double capacitance)
void SetConductionVelocityMaps(std::vector< unsigned > &rConductionVelocityMaps)
unsigned mIndexEpi
double GetEndoLayerFraction()
void SetConductivityHeterogeneities(std::vector< ChasteCuboid< 3 > > &rConductivityAreas, std::vector< c_vector< double, 3 > > &rIntraConductivities, std::vector< c_vector< double, 3 > > &rExtraConductivities)
bool GetConductivityHeterogeneitiesProvided() const
void SetOutputVariables(const std::vector< std::string > &rOutputVariables)
void GetSlabDimensions(c_vector< double, 3 > &slabDimensions) const
void GetPseudoEcgElectrodePositions(std::vector< ChastePoint< SPACE_DIM > > &rPseudoEcgElectrodePositions) const
void GetElectrodeParameters(bool &rGroundSecondElectrode, unsigned &rIndex, double &rMagnitude, double &rStartTime, double &rDuration)
void LoadFromCheckpoint()
unsigned mIndexMid
void Write(bool useArchiveLocationInfo=false, std::string subfolderName="output")
std::map< std::string, std::pair< double, double > > GetIc50Values()
std::set< unsigned > mTissueIdentifiers
double GetEpiLayerFraction()
unsigned GetEndoLayerIndex()
bool mUseMassLumpingForPrecond
double GetCheckpointTimestep() const
bool IsMeshProvided() const
bool GetVisualizeWithVtk() const
void SetOutputFilenamePrefix(const std::string &rOutputFilenamePrefix)
void SetCheckpointSimulation(bool checkpointSimulation, double checkpointTimestep=-1.0, unsigned maxCheckpointsOnDisk=UINT_MAX)
void SetPurkinjeConductivity(double conductivity)
void GetIntracellularConductivities(c_vector< double, 3 > &rIntraConductivities) const
bool GetUseMassLumpingForPrecond()
void SetMeshFileName(std::string meshPrefix, cp::media_type fibreDefinition=cp::media_type::NoFibreOrientation)
void GetCellHeterogeneities(std::vector< boost::shared_ptr< AbstractChasteRegion< DIM > > > &rCellHeterogeneityRegions, std::vector< double > &rScaleFactorGks, std::vector< double > &rScaleFactorIto, std::vector< double > &rScaleFactorGkr, std::vector< std::map< std::string, double > > *pParameterSettings)
void GetUpstrokeTimeMaps(std::vector< double > &rUpstrokeTimeMaps) const
bool GetUseStateVariableInterpolation() const
const std::set< unsigned > & rGetTissueIdentifiers()
static void Reset()
unsigned GetVersionFromNamespace(const std::string &rNamespaceUri)
bool mUseReactionDiffusionOperatorSplitting
void GetMaxUpstrokeVelocityMaps(std::vector< double > &rUpstrokeVelocityMaps) const
double GetInterNodeSpace() const
cp::domain_type GetDomain() const
bool GetOutputVariablesProvided() const
std::string GetOutputDirectory() const
double GetBathConductivity(unsigned bathRegion=UINT_MAX) const
void SetUseMassLumping(bool useMassLumping=true)
bool IsPseudoEcgCalculationRequested() const
void CheckSimulationIsDefined(std::string callingMethod="") const
double mEpiFraction
bool IsUpstrokeTimeMapsRequested() const
void SetVisualizeWithCmgui(bool useCmgui=true)
void GetExtracellularConductivities(c_vector< double, 3 > &rExtraConductivities) const
bool GetCheckpointSimulation() const
void SetVisualizeWithParallelVtk(bool useParallelVtk=true)
void UpdateParametersFromResumeSimulation(boost::shared_ptr< cp::chaste_parameters_type > pResumeParameters)
void SetParametersFile(const std::string &rFileName)
void GetFibreLength(c_vector< double, 1 > &fibreLength) const
static HeartConfig * Instance()
const char * GetKSPSolver() const
void SetVisualizerOutputPrecision(unsigned numberOfDigits)
void SetOdePdeAndPrintingTimeSteps(double odeTimeStep, double pdeTimeStep, double printingTimeStep)
void SetPseudoEcgElectrodePositions(const std::vector< ChastePoint< SPACE_DIM > > &rPseudoEcgElectrodePositions)
bool IsAdaptivityParametersPresent() const
bool GetCreateSheet() const
static bool IsRegionBath(HeartRegionType regionId)
std::string GetOutputDirectoryFullPath() const
static bool AmMaster()
static xercesc::DOMElement * SetNamespace(xercesc::DOMDocument *pDocument, xercesc::DOMElement *pElement, const std::string &rNamespace)
Definition XmlTools.cpp:279
static std::string EscapeSpaces(const std::string &rPath)
Definition XmlTools.cpp:386
static std::vector< xercesc::DOMElement * > FindElements(const xercesc::DOMElement *pContextElement, const std::string &rPath)
Definition XmlTools.cpp:328
static XSD_DOM_AUTO_PTR< xercesc::DOMDocument > ReadXmlFile(const std::string &rFileName, const ::xsd::cxx::tree::properties< char > &rProps, bool validate=true)
Definition XmlTools.cpp:53
static void WrapContentInElement(xercesc::DOMDocument *pDocument, xercesc::DOMElement *pElement, const XMLCh *pNewElementLocalName)
Definition XmlTools.cpp:353
static void TransformArchiveDirectory(xercesc::DOMDocument *pDocument, xercesc::DOMElement *pRootElement)
static void TransformIonicModelDefinitions(xercesc::DOMDocument *pDocument, xercesc::DOMElement *pRootElement)
static void SetDefaultVisualizer(xercesc::DOMDocument *pDocument, xercesc::DOMElement *pRootElement)
static void MoveConductivityHeterogeneities(xercesc::DOMDocument *pDocument, xercesc::DOMElement *pRootElement)
static void CheckForIluPreconditioner(xercesc::DOMDocument *pDocument, xercesc::DOMElement *pRootElement)