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