HeartConfig.cpp

00001 /*
00002 
00003 Copyright (C) University of Oxford, 2005-2010
00004 
00005 University of Oxford means the Chancellor, Masters and Scholars of the
00006 University of Oxford, having an administrative office at Wellington
00007 Square, Oxford OX1 2JD, UK.
00008 
00009 This file is part of Chaste.
00010 
00011 Chaste is free software: you can redistribute it and/or modify it
00012 under the terms of the GNU Lesser General Public License as published
00013 by the Free Software Foundation, either version 2.1 of the License, or
00014 (at your option) any later version.
00015 
00016 Chaste is distributed in the hope that it will be useful, but WITHOUT
00017 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00018 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
00019 License for more details. The offer of Chaste under the terms of the
00020 License is subject to the License being interpreted in accordance with
00021 English Law and subject to any action against the University of Oxford
00022 being under the jurisdiction of the English Courts.
00023 
00024 You should have received a copy of the GNU Lesser General Public License
00025 along with Chaste. If not, see <http://www.gnu.org/licenses/>.
00026 
00027 */
00028 
00029 // Work-around for newer Boost versions
00030 #include "CheckpointArchiveTypesIfNeeded.hpp"
00031 
00032 #include "UblasCustomFunctions.hpp"
00033 
00034 #include "HeartConfig.hpp"
00035 #include "OutputFileHandler.hpp"
00036 #include "Exception.hpp"
00037 #include "ChastePoint.hpp"
00038 #include "Version.hpp"
00039 #include "AbstractChasteRegion.hpp"
00040 
00041 #include <cassert>
00042 
00043 #include <xercesc/util/PlatformUtils.hpp>
00044 #include <xercesc/util/QName.hpp>
00045 #include <xsd/cxx/tree/error-handler.hxx>
00046 
00047 // Coping with changes to XSD interface
00048 #if (XSD_INT_VERSION >= 3000000L)
00049 #define XSD_SEQUENCE_TYPE(base) base##_sequence
00050 #define XSD_ITERATOR_TYPE(base) base##_iterator
00051 #define XSD_NESTED_TYPE(t) t##_type
00052 #define XSD_ANON_TYPE(t1, t2) \
00053     t1::t2##_type
00054 #else
00055 #define XSD_SEQUENCE_TYPE(base) base::container
00056 #define XSD_ITERATOR_TYPE(base) base::iterator
00057 #define XSD_NESTED_TYPE(t) t::type
00058 #define XSD_ANON_TYPE(t1, t2) \
00059     t1::t2::_xsd_##t2##_::t2
00060 #endif
00061 
00062 // These are for convenience
00063 #define XSD_ANON_SEQUENCE_TYPE(t1, t2, t3) \
00064     XSD_SEQUENCE_TYPE(XSD_ANON_TYPE(t1, t2)::t3)
00065 #define XSD_ANON_ITERATOR_TYPE(t1, t2, t3) \
00066     XSD_ITERATOR_TYPE(XSD_ANON_TYPE(t1, t2)::t3)
00067 
00068 // Newer versions don't allow you to set fixed attributes
00069 #if (XSD_INT_VERSION >= 3020000L)
00070 #define XSD_CREATE_WITH_FIXED_ATTR(type, name, attr) \
00071     type name
00072 #define XSD_CREATE_WITH_FIXED_ATTR1(type, name, arg1, attr) \
00073     type name(arg1)
00074 #define XSD_CREATE_WITH_FIXED_ATTR2(type, name, arg1, arg2, attr) \
00075     type name(arg1, arg2)
00076 #define XSD_CREATE_WITH_FIXED_ATTR3(type, name, arg1, arg2, arg3, attr) \
00077     type name(arg1, arg2, arg3)
00078 #else
00079 #define XSD_CREATE_WITH_FIXED_ATTR(type, name, attr) \
00080     type name(attr)
00081 #define XSD_CREATE_WITH_FIXED_ATTR1(type, name, arg1, attr) \
00082     type name(arg1, attr)
00083 #define XSD_CREATE_WITH_FIXED_ATTR2(type, name, arg1, arg2, attr) \
00084     type name(arg1, arg2, attr)
00085 #define XSD_CREATE_WITH_FIXED_ATTR3(type, name, arg1, arg2, arg3, attr) \
00086     type name(arg1, arg2, arg3, attr)
00087 #endif
00088 
00089 using namespace xsd::cxx::tree;
00090 
00091 //
00092 // Definition of static member variables
00093 //
00094 std::auto_ptr<HeartConfig> HeartConfig::mpInstance;
00095 
00096 //
00097 // Methods
00098 //
00099 
00100 HeartConfig* HeartConfig::Instance()
00101 {
00102     if (mpInstance.get() == NULL)
00103     {
00104         mpInstance.reset(new HeartConfig);
00105     }
00106     return mpInstance.get();
00107 }
00108 
00109 HeartConfig::HeartConfig()
00110 {
00111     assert(mpInstance.get() == NULL);
00112     mUseFixedSchemaLocation = true;
00113     SetDefaultSchemaLocations();
00114 
00115     SetDefaultsFile("ChasteDefaults.xml");
00116 
00117     mpUserParameters = mpDefaultParameters;
00118     //CheckTimeSteps(); // necessity of this line of code is not tested -- remove with caution!
00119 
00120     //initialise the member variable of the layers
00121     mEpiFraction = -1.0;
00122     mEndoFraction =  -1.0;
00123     mMidFraction = -1.0;
00124     mUserAskedForCellularTransmuralHeterogeneities=false;
00125     mUserAskedForCuboidsForCellularHeterogeneities=false;
00126     // initialise to senseless values (these should be only 0, 1 and 2)
00127     // note: the 'minus 3' is for checking purposes as we need to add 0, 1 or 2 to this initial value
00128     // and UINT_MAX+1 seems to be 0
00129     mIndexMid = UINT_MAX-3u;
00130     mIndexEpi = UINT_MAX-3u;
00131     mIndexEndo = UINT_MAX-3u;
00132 }
00133 
00134 HeartConfig::~HeartConfig()
00135 {
00136 }
00137 
00138 void HeartConfig::SetDefaultsFile(const std::string& rFileName)
00139 {
00140     bool same_target = (mpUserParameters == mpDefaultParameters);
00141 
00142     mpDefaultParameters = ReadFile(rFileName);
00143 
00144     if (same_target)
00145     {
00146         mpUserParameters = mpDefaultParameters;
00147     }
00148     CheckTimeSteps();
00149 }
00150 
00151 void HeartConfig::Write(bool useArchiveLocationInfo, std::string subfolderName)
00152 {
00153     //Output file
00154     std::string output_dirname;
00155     if (useArchiveLocationInfo)
00156     {
00157         output_dirname = ArchiveLocationInfo::GetArchiveDirectory();
00158     }
00159     else
00160     {
00161         OutputFileHandler handler(GetOutputDirectory(), false);
00162         output_dirname =  handler.GetOutputDirectoryFullPath() + subfolderName + "/";
00163     }
00164     if (!PetscTools::AmMaster())
00165     {
00166         //Only the master process is writing the configuration files
00167         return;
00168     }
00169     out_stream p_defaults_file( new std::ofstream( (output_dirname+"ChasteDefaults.xml").c_str() ) );
00170     out_stream p_parameters_file( new std::ofstream( (output_dirname+"ChasteParameters.xml").c_str() ) );
00171 
00172     if (!p_defaults_file->is_open() || !p_parameters_file->is_open())
00173     {
00174         EXCEPTION("Could not open XML file in HeartConfig");
00175     }
00176 
00177     //Schema map
00178     //Note - this location is relative to where we are storing the xml
00179     ::xml_schema::namespace_infomap map;
00180     std::string absolute_path_to_xsd = EscapeSpaces(ChasteBuildInfo::GetRootDir());
00181     absolute_path_to_xsd += "/heart/src/io/";
00182     // Release 1.1 (and earlier) didn't use a namespace
00183     map[""].schema = absolute_path_to_xsd + "ChasteParameters_1_1.xsd";
00184     // Later releases use namespaces of the form https://chaste.comlab.ox.ac.uk/nss/parameters/N_M
00185     map["cp20"].name = "https://chaste.comlab.ox.ac.uk/nss/parameters/2_0";
00186     map["cp20"].schema = absolute_path_to_xsd + "ChasteParameters_2_0.xsd";
00187 
00188     cp::ChasteParameters(*p_parameters_file, *mpUserParameters, map);
00189     cp::ChasteParameters(*p_defaults_file, *mpDefaultParameters, map);
00190 }
00191 
00192 void HeartConfig::SetDefaultSchemaLocations()
00193 {
00194     mSchemaLocations.clear();
00195     // Location of schemas in the source tree
00196     std::string root_dir = std::string(ChasteBuildInfo::GetRootDir()) + "/heart/src/io/";
00197     // Release 1.1 (and earlier) didn't use a namespace
00198     mSchemaLocations[""] = root_dir + "ChasteParameters_1_1.xsd";
00199     // Later releases use namespaces of the form https://chaste.comlab.ox.ac.uk/nss/parameters/N_M
00200     mSchemaLocations["https://chaste.comlab.ox.ac.uk/nss/parameters/2_0"] = root_dir + "ChasteParameters_2_0.xsd";
00201 }
00202 
00203 void HeartConfig::SetFixedSchemaLocations(const SchemaLocationsMap& rSchemaLocations)
00204 {
00205     mSchemaLocations = rSchemaLocations;
00206     SetUseFixedSchemaLocation(true);
00207 }
00208 
00209 void HeartConfig::SetUseFixedSchemaLocation(bool useFixedSchemaLocation)
00210 {
00211     mUseFixedSchemaLocation = useFixedSchemaLocation;
00212 }
00213 
00214 std::string HeartConfig::EscapeSpaces(const std::string& rPath)
00215 {
00216     std::string escaped_path;
00217     for (std::string::const_iterator it = rPath.begin(); it != rPath.end(); ++it)
00218     {
00219         if (*it == ' ')
00220         {
00221             escaped_path += "%20";
00222         }
00223         else
00224         {
00225             escaped_path += *it;
00226         }
00227     }
00228     return escaped_path;
00229 }
00230 
00231 boost::shared_ptr<cp::chaste_parameters_type> HeartConfig::ReadFile(const std::string& rFileName)
00232 {
00233     // Determine whether to use the schema path given in the input XML, or our own schema
00234     ::xml_schema::properties props;
00235     if (mUseFixedSchemaLocation)
00236     {
00237         for (SchemaLocationsMap::iterator it = mSchemaLocations.begin();
00238              it != mSchemaLocations.end();
00239              ++it)
00240         {
00241             if (it->first == "")
00242             {
00243                 props.no_namespace_schema_location(EscapeSpaces(it->second));
00244             }
00245             else
00246             {
00247                 props.schema_location(it->first, EscapeSpaces(it->second));
00248             }
00249         }
00250     }
00251 
00252     // Get the parameters using the method 'ChasteParameters(rFileName)',
00253     // which returns a std::auto_ptr. We convert to a shared_ptr for easier semantics.
00254     try
00255     {
00256         // Make sure Xerces initialization & finalization happens
00257         ::xsd::cxx::xml::auto_initializer init_fini(true, true);
00258         // Set up an error handler
00259         ::xsd::cxx::tree::error_handler<char> error_handler;
00260         // Parse XML to DOM
00261         xsd::cxx::xml::dom::auto_ptr<xercesc::DOMDocument> p_doc = ReadFileToDomDocument(rFileName, error_handler, props);
00262         // Any errors?
00263         error_handler.throw_if_failed< ::xsd::cxx::tree::parsing< char > >();
00264         // Test the namespace on the root element
00265         xercesc::DOMElement* p_root_elt = p_doc->getDocumentElement();
00266         std::string namespace_uri(xsd::cxx::xml::transcode<char>(p_root_elt->getNamespaceURI()));
00267         if (namespace_uri == "")
00268         {
00269             // Pretend it's a version 2.0 file
00270             AddNamespace(p_doc.get(), p_root_elt, "https://chaste.comlab.ox.ac.uk/nss/parameters/2_0");
00271             // Change definitions of ionic models
00272             TransformIonicModelDefinitions(p_doc.get(), p_root_elt);
00273         }
00274         // Parse DOM to object model
00275         std::auto_ptr<cp::chaste_parameters_type> p_params(cp::ChasteParameters(*p_doc, ::xml_schema::flags::dont_initialize, props));
00276         // Get rid of the DOM stuff
00277         p_doc.reset();
00278 
00279         return boost::shared_ptr<cp::chaste_parameters_type>(p_params);
00280     }
00281     catch (const xml_schema::parsing& e)
00282     {
00283         // Make sure we don't store invalid parameters
00284         mpUserParameters.reset();
00285         mpDefaultParameters.reset();
00286         // Test for missing schema/xml file
00287 #if (XSD_INT_VERSION >= 3000000L)
00288         const xml_schema::diagnostics& diags = e.diagnostics();
00289         const xml_schema::error& first_error = diags[0];
00290 #else
00291         const xml_schema::errors& errors = e.errors();
00292         const xml_schema::error& first_error = errors[0];
00293 #endif
00294         if (first_error.line() == 0u)
00295         {
00296             std::cerr << first_error << std::endl;
00297             EXCEPTION("Missing file parsing configuration file: " + rFileName);
00298         }
00299         else
00300         {
00301             std::cerr << e << std::endl;
00302             EXCEPTION("XML parsing error in configuration file: " + rFileName);
00303         }
00304     }
00305     catch (const xml_schema::exception& e)
00306     {
00307         std::cerr << e << std::endl;
00308         // Make sure we don't store invalid parameters
00309         mpUserParameters.reset();
00310         mpDefaultParameters.reset();
00311         EXCEPTION("XML parsing error in configuration file: " + rFileName);
00312     }
00313 }
00314 
00315 void HeartConfig::SetParametersFile(const std::string& rFileName)
00316 {
00317     mpUserParameters = ReadFile(rFileName);
00318 
00319     CheckTimeSteps(); // For consistency with SetDefaultsFile
00320 }
00321 
00322 
00323 void HeartConfig::Reset()
00324 {
00325     // Throw it away first, so that mpInstance is NULL when we...
00326     mpInstance.reset();
00327     // ...make a new one
00328     mpInstance.reset(new HeartConfig);
00329 }
00330 
00331 bool HeartConfig::IsSimulationDefined() const
00332 {
00333     return mpUserParameters->Simulation().present();
00334 }
00335 
00336 bool HeartConfig::IsSimulationResumed() const
00337 {
00338     return mpUserParameters->ResumeSimulation().present();
00339 }
00340 
00341 
00342 template<class TYPE>
00343 TYPE* HeartConfig::DecideLocation(TYPE* ptr1, TYPE* ptr2, const std::string& nameParameter) const
00344 {
00345     if (ptr1->present())
00346     {
00347         return ptr1;
00348     }
00349     if (ptr2->present())
00350     {
00351         return ptr2;
00352     }
00353     EXCEPTION("No " + nameParameter + " provided (neither default nor user defined)");
00354 }
00355 
00356 void HeartConfig::CheckSimulationIsDefined(std::string callingMethod) const
00357 {
00358     if (IsSimulationResumed())
00359     {
00360         EXCEPTION(callingMethod + " information is not available in a resumed simulation.");
00361     }
00362 }
00363 
00364 void HeartConfig::CheckResumeSimulationIsDefined(std::string callingMethod) const
00365 {
00366     if (IsSimulationDefined())
00367     {
00368         EXCEPTION(callingMethod + " information is not available in a standard (non-resumed) simulation.");
00369     }
00370 }
00371 
00372 unsigned HeartConfig::GetSpaceDimension() const
00373 {
00374     if (IsSimulationDefined())
00375     {
00376         return DecideLocation( & mpUserParameters->Simulation().get().SpaceDimension(),
00377                                & mpDefaultParameters->Simulation().get().SpaceDimension(),
00378                                "SpaceDimension")->get();
00379     }
00380     else
00381     {
00382         return mpUserParameters->ResumeSimulation().get().SpaceDimension();
00383     }
00384 }
00385 
00386 double HeartConfig::GetSimulationDuration() const
00387 {
00388     if (IsSimulationDefined())
00389     {
00390         return DecideLocation( & mpUserParameters->Simulation().get().SimulationDuration(),
00391                                & mpDefaultParameters->Simulation().get().SimulationDuration(),
00392                                "Simulation/SimulationDuration")->get();
00393     }
00394     else // IsSimulationResumed
00395     {
00396         return mpUserParameters->ResumeSimulation().get().SimulationDuration();
00397     }
00398 }
00399 
00400 cp::domain_type HeartConfig::GetDomain() const
00401 {
00402     if (IsSimulationDefined())
00403     {
00404         return DecideLocation( & mpUserParameters->Simulation().get().Domain(),
00405                                & mpDefaultParameters->Simulation().get().Domain(),
00406                                "Domain")->get();
00407     }
00408     else
00409     {
00410         return mpUserParameters->ResumeSimulation().get().Domain();
00411     }
00412 }
00413 
00414 cp::ionic_model_selection_type HeartConfig::GetDefaultIonicModel() const
00415 {
00416     CheckSimulationIsDefined("DefaultIonicModel");
00417 
00418     return DecideLocation( & mpUserParameters->Simulation().get().IonicModels(),
00419                            & mpDefaultParameters->Simulation().get().IonicModels(),
00420                            "IonicModel")->get().Default();
00421 }
00422 
00423 template<unsigned DIM>
00424 void HeartConfig::GetIonicModelRegions(std::vector<ChasteCuboid<DIM> >& definedRegions,
00425                                        std::vector<cp::ionic_model_selection_type>& ionicModels) const
00426 {
00427     CheckSimulationIsDefined("IonicModelRegions");
00428     definedRegions.clear();
00429     ionicModels.clear();
00430 
00431     XSD_SEQUENCE_TYPE(cp::ionic_models_type::Region)&
00432          regions = DecideLocation( & mpUserParameters->Simulation().get().IonicModels(),
00433                                    & mpDefaultParameters->Simulation().get().IonicModels(),
00434                                    "IonicModel")->get().Region();
00435 
00436     for (XSD_ITERATOR_TYPE(cp::ionic_models_type::Region) i = regions.begin();
00437          i != regions.end();
00438          ++i)
00439     {
00440         cp::ionic_model_region_type ionic_model_region(*i);
00441         if (ionic_model_region.Location().Cuboid().present())
00442         {
00443             cp::point_type point_a = ionic_model_region.Location().Cuboid()->LowerCoordinates();
00444             cp::point_type point_b = ionic_model_region.Location().Cuboid()->UpperCoordinates();
00445 
00446             switch (DIM)
00447             {
00448                 case 1:
00449                 {
00450                     ChastePoint<DIM> chaste_point_a ( point_a.x() );
00451                     ChastePoint<DIM> chaste_point_b ( point_b.x() );
00452                     definedRegions.push_back(ChasteCuboid<DIM>( chaste_point_a, chaste_point_b ));
00453                     break;
00454                 }
00455                 case 2:
00456                 {
00457                     ChastePoint<DIM> chaste_point_a ( point_a.x(), point_a.y() );
00458                     ChastePoint<DIM> chaste_point_b ( point_b.x(), point_b.y() );
00459                     definedRegions.push_back(ChasteCuboid<DIM>( chaste_point_a, chaste_point_b ));
00460                     break;
00461                 }
00462                 case 3:
00463                 {
00464                     ChastePoint<DIM> chaste_point_a ( point_a.x(), point_a.y(), point_a.z() );
00465                     ChastePoint<DIM> chaste_point_b ( point_b.x(), point_b.y(), point_b.z() );
00466                     definedRegions.push_back(ChasteCuboid<DIM>( chaste_point_a, chaste_point_b ));
00467                     break;
00468                 }
00469                 default:
00470                     NEVER_REACHED;
00471                     break;
00472             }
00473 
00474             ionicModels.push_back(ionic_model_region.IonicModel());
00475         }
00476         else
00477         {
00478             if(ionic_model_region.Location().EpiLayer().present() || ionic_model_region.Location().MidLayer().present() || ionic_model_region.Location().EndoLayer().present() )
00479             {
00481                 EXCEPTION("Definition of transmural layers is not yet supported for defining different ionic models, please use cuboids instead");
00482             }
00483         }
00484     }
00485 }
00486 
00487 
00488 bool HeartConfig::IsMeshProvided() const
00489 {
00490     CheckSimulationIsDefined("Mesh");
00491 
00492     try
00493     {
00494         DecideLocation( & mpUserParameters->Simulation().get().Mesh(),
00495                         & mpDefaultParameters->Simulation().get().Mesh(),
00496                         "Mesh");
00497         return true;
00498     }
00499     catch (Exception& e)
00500     {
00501         return false;
00502     }
00503 }
00504 
00505 bool HeartConfig::GetCreateMesh() const
00506 {
00507     CheckSimulationIsDefined("Mesh");
00508 
00509     cp::mesh_type mesh = DecideLocation( & mpUserParameters->Simulation().get().Mesh(),
00510                                          & mpDefaultParameters->Simulation().get().Mesh(),
00511                                          "Mesh")->get();
00512 
00513     return (mesh.Slab().present() || mesh.Sheet().present() || mesh.Fibre().present());
00514 }
00515 
00516 bool HeartConfig::GetCreateSlab() const
00517 {
00518     CheckSimulationIsDefined("Mesh");
00519 
00520     cp::mesh_type mesh = DecideLocation( & mpUserParameters->Simulation().get().Mesh(),
00521                                          & mpDefaultParameters->Simulation().get().Mesh(),
00522                                          "Mesh")->get();
00523 
00524     return (mesh.Slab().present());
00525 }
00526 
00527 bool HeartConfig::GetCreateSheet() const
00528 {
00529     CheckSimulationIsDefined("Mesh");
00530 
00531     cp::mesh_type mesh = DecideLocation( & mpUserParameters->Simulation().get().Mesh(),
00532                                          & mpDefaultParameters->Simulation().get().Mesh(),
00533                                          "Mesh")->get();
00534 
00535     return (mesh.Sheet().present());
00536 }
00537 
00538 bool HeartConfig::GetCreateFibre() const
00539 {
00540     CheckSimulationIsDefined("Mesh");
00541 
00542     cp::mesh_type mesh = DecideLocation( & mpUserParameters->Simulation().get().Mesh(),
00543                                          & mpDefaultParameters->Simulation().get().Mesh(),
00544                                          "Mesh")->get();
00545 
00546     return (mesh.Fibre().present());
00547 }
00548 
00549 
00550 bool HeartConfig::GetLoadMesh() const
00551 {
00552     CheckSimulationIsDefined("Mesh");
00553 
00554     return (DecideLocation( & mpUserParameters->Simulation().get().Mesh(),
00555                             & mpDefaultParameters->Simulation().get().Mesh(),
00556                             "Mesh")->get().LoadMesh().present());
00557 }
00558 
00559 void HeartConfig::GetSlabDimensions(c_vector<double, 3>& slabDimensions) const
00560 {
00561     CheckSimulationIsDefined("Slab");
00562 
00563     if (GetSpaceDimension()!=3 || !GetCreateSlab())
00564     {
00565         EXCEPTION("Tissue slabs can only be defined in 3D");
00566     }
00567 
00568     optional<cp::slab_type, false> slab_dimensions = DecideLocation( & mpUserParameters->Simulation().get().Mesh(),
00569                                                                      & mpDefaultParameters->Simulation().get().Mesh(),
00570                                                                      "Slab")->get().Slab();
00571 
00572     slabDimensions[0] = slab_dimensions->x();
00573     slabDimensions[1] = slab_dimensions->y();
00574     slabDimensions[2] = slab_dimensions->z();
00575 }
00576 
00577 void HeartConfig::GetSheetDimensions(c_vector<double, 2>& sheetDimensions) const
00578 {
00579     CheckSimulationIsDefined("Sheet");
00580 
00581     if (GetSpaceDimension()!=2 || !GetCreateSheet())
00582     {
00583         EXCEPTION("Tissue sheets can only be defined in 2D");
00584     }
00585 
00586     optional<cp::sheet_type, false> sheet_dimensions = DecideLocation( & mpUserParameters->Simulation().get().Mesh(),
00587                                                                        & mpDefaultParameters->Simulation().get().Mesh(),
00588                                                                        "Sheet")->get().Sheet();
00589 
00590     sheetDimensions[0] = sheet_dimensions->x();
00591     sheetDimensions[1] = sheet_dimensions->y();
00592 }
00593 
00594 void HeartConfig::GetFibreLength(c_vector<double, 1>& fibreLength) const
00595 {
00596     CheckSimulationIsDefined("Fibre");
00597 
00598     if (GetSpaceDimension()!=1 || !GetCreateFibre())
00599     {
00600         EXCEPTION("Tissue fibres can only be defined in 1D");
00601     }
00602 
00603     optional<cp::fibre_type, false> fibre_length = DecideLocation( & mpUserParameters->Simulation().get().Mesh(),
00604                                                                    & mpDefaultParameters->Simulation().get().Mesh(),
00605                                                                    "Fibre")->get().Fibre();
00606 
00607     fibreLength[0] = fibre_length->x();
00608 }
00609 
00610 
00611 double HeartConfig::GetInterNodeSpace() const
00612 {
00613     CheckSimulationIsDefined("InterNodeSpace");
00614     assert(GetCreateMesh());
00615 
00616     switch(GetSpaceDimension())
00617     {
00618         case 3:
00619             return DecideLocation( & mpUserParameters->Simulation().get().Mesh(),
00620                                    & mpDefaultParameters->Simulation().get().Mesh(),
00621                                    "Slab")->get().Slab()->inter_node_space();
00622             break;
00623         case 2:
00624             return DecideLocation( & mpUserParameters->Simulation().get().Mesh(),
00625                                    & mpDefaultParameters->Simulation().get().Mesh(),
00626                                    "Sheet")->get().Sheet()->inter_node_space();
00627             break;
00628         case 1:
00629             return DecideLocation( & mpUserParameters->Simulation().get().Mesh(),
00630                                    & mpDefaultParameters->Simulation().get().Mesh(),
00631                                    "Fibre")->get().Fibre()->inter_node_space();
00632             break;
00633         default:
00634             NEVER_REACHED;
00635     }
00636 
00637 
00638 }
00639 
00640 std::string HeartConfig::GetMeshName() const
00641 {
00642     CheckSimulationIsDefined("LoadMesh");
00643     assert(GetLoadMesh());
00644 
00645     return DecideLocation( & mpUserParameters->Simulation().get().Mesh(),
00646                            & mpDefaultParameters->Simulation().get().Mesh(),
00647                            "LoadMesh")->get().LoadMesh()->name();
00648 }
00649 
00650 cp::media_type HeartConfig::GetConductivityMedia() const
00651 {
00652     CheckSimulationIsDefined("LoadMesh");
00653     assert(GetLoadMesh());
00654 
00655     return DecideLocation( & mpUserParameters->Simulation().get().Mesh(),
00656                            & mpDefaultParameters->Simulation().get().Mesh(),
00657                            "LoadMesh")->get().LoadMesh()->conductivity_media();
00658 }
00659 
00660 template <unsigned DIM>
00661 void HeartConfig::GetStimuli(std::vector<boost::shared_ptr<SimpleStimulus> >& rStimuliApplied,
00662                              std::vector<ChasteCuboid<DIM> >& rStimulatedAreas) const
00663 {
00664     CheckSimulationIsDefined("Stimuli");
00665     XSD_ANON_SEQUENCE_TYPE(cp::simulation_type, Stimuli, Stimulus)&
00666          stimuli = DecideLocation( & mpUserParameters->Simulation().get().Stimuli(),
00667                            & mpDefaultParameters->Simulation().get().Stimuli(),
00668                            "Stimuli")->get().Stimulus();
00669     for (XSD_ANON_ITERATOR_TYPE(cp::simulation_type, Stimuli, Stimulus) i = stimuli.begin();
00670          i != stimuli.end();
00671          ++i)
00672     {
00673         cp::stimulus_type stimulus(*i);
00674         if (stimulus.Location().Cuboid().present())
00675         {
00676             cp::point_type point_a = stimulus.Location().Cuboid()->LowerCoordinates();
00677             cp::point_type point_b = stimulus.Location().Cuboid()->UpperCoordinates();
00678             switch (DIM)
00679             {
00680                 case 1:
00681                 {
00682                     ChastePoint<DIM> chaste_point_a ( point_a.x() );
00683                     ChastePoint<DIM> chaste_point_b ( point_b.x() );
00684                     rStimulatedAreas.push_back( ChasteCuboid<DIM>( chaste_point_a, chaste_point_b ) );
00685                     break;
00686                 }
00687                 case 2:
00688                 {
00689                     ChastePoint<DIM> chaste_point_a ( point_a.x(), point_a.y() );
00690                     ChastePoint<DIM> chaste_point_b ( point_b.x(), point_b.y() );
00691                     rStimulatedAreas.push_back( ChasteCuboid<DIM>( chaste_point_a, chaste_point_b ) );
00692                     break;
00693                 }
00694                 case 3:
00695                 {
00696                     ChastePoint<DIM> chaste_point_a ( point_a.x(), point_a.y(), point_a.z() );
00697                     ChastePoint<DIM> chaste_point_b ( point_b.x(), point_b.y(), point_b.z() );
00698                     rStimulatedAreas.push_back( ChasteCuboid<DIM>( chaste_point_a, chaste_point_b ) );
00699                     break;
00700                 }
00701                 default:
00702                     NEVER_REACHED;
00703                     break;
00704             }
00705 
00706             boost::shared_ptr<SimpleStimulus> stim(new SimpleStimulus(stimulus.Strength(),
00707                                                                       stimulus.Duration(),
00708                                                                       stimulus.Delay()));
00709             rStimuliApplied.push_back( stim );
00710         }
00711         else
00712         {
00713             if(stimulus.Location().EpiLayer().present() || stimulus.Location().MidLayer().present() || stimulus.Location().EndoLayer().present() )
00714             {
00715                 EXCEPTION("Definition of transmural layers is not yet supported for specifying stimulated areas, please use cuboids instead");
00716             }
00717         }
00718     }
00719 }
00720 
00721 template<unsigned DIM>
00722 void HeartConfig::GetCellHeterogeneities(std::vector<AbstractChasteRegion<DIM>* >& rCellHeterogeneityRegions,
00723                                          std::vector<double>& rScaleFactorGks,
00724                                          std::vector<double>& rScaleFactorIto,
00725                                          std::vector<double>& rScaleFactorGkr)
00726 {
00727     CheckSimulationIsDefined("CellHeterogeneities");
00728     XSD_ANON_SEQUENCE_TYPE(cp::simulation_type, CellHeterogeneities, CellHeterogeneity)&
00729          cell_heterogeneity = DecideLocation( & mpUserParameters->Simulation().get().CellHeterogeneities(),
00730                                                  & mpDefaultParameters->Simulation().get().CellHeterogeneities(),
00731                                                  "CellHeterogeneities")->get().CellHeterogeneity();
00732 
00733     bool user_supplied_negative_value = false;
00734     bool user_asking_for_transmural_layers = false;
00735     unsigned counter_of_heterogeneities = 0;
00736 
00737     for (XSD_ANON_ITERATOR_TYPE(cp::simulation_type, CellHeterogeneities, CellHeterogeneity) i = cell_heterogeneity.begin();
00738          i != cell_heterogeneity.end();
00739          ++i)
00740     {
00741         cp::cell_heterogeneity_type ht(*i);
00742 
00743         if (ht.Location().Cuboid().present())
00744         {
00745             mUserAskedForCuboidsForCellularHeterogeneities = true;
00746             cp::point_type point_a = ht.Location().Cuboid()->LowerCoordinates();
00747             cp::point_type point_b = ht.Location().Cuboid()->UpperCoordinates();
00748 
00749             switch (DIM)
00750             {
00751                 case 1:
00752                 {
00753                     ChastePoint<DIM> chaste_point_a ( point_a.x() );
00754                     ChastePoint<DIM> chaste_point_b ( point_b.x() );
00755                     rCellHeterogeneityRegions.push_back(new ChasteCuboid<DIM> ( chaste_point_a, chaste_point_b ) );
00756                     break;
00757                 }
00758                 case 2:
00759                 {
00760                     ChastePoint<DIM> chaste_point_a ( point_a.x(), point_a.y() );
00761                     ChastePoint<DIM> chaste_point_b ( point_b.x(), point_b.y() );
00762                     rCellHeterogeneityRegions.push_back(new ChasteCuboid<DIM> ( chaste_point_a, chaste_point_b ) );
00763                     break;
00764                 }
00765                 case 3:
00766                 {
00767                     ChastePoint<DIM> chaste_point_a ( point_a.x(), point_a.y(), point_a.z() );
00768                     ChastePoint<DIM> chaste_point_b ( point_b.x(), point_b.y(), point_b.z() );
00769                     rCellHeterogeneityRegions.push_back(new ChasteCuboid<DIM> ( chaste_point_a, chaste_point_b ) );
00770                     break;
00771                 }
00772                 default:
00773                     NEVER_REACHED;
00774                     break;
00775             }
00776 
00777         }
00778         else
00779         {
00780 
00781             if(ht.Location().EpiLayer().present())
00782             {
00783                 mEpiFraction  =  ht.Location().EpiLayer().get();
00784 
00785                 user_asking_for_transmural_layers = true;
00786                 if (mEpiFraction <0)
00787                 {
00788                     user_supplied_negative_value=true;
00789                 }
00790                 mIndexEpi = counter_of_heterogeneities;
00791             }
00792             if(ht.Location().EndoLayer().present())
00793             {
00794                 mEndoFraction  =  ht.Location().EndoLayer().get();
00795 
00796                 user_asking_for_transmural_layers = true;
00797                 if (mEndoFraction <0)
00798                 {
00799                     user_supplied_negative_value=true;
00800                 }
00801                 mIndexEndo = counter_of_heterogeneities;
00802             }
00803             if(ht.Location().MidLayer().present())
00804             {
00805                 mMidFraction  =  ht.Location().MidLayer().get();
00806 
00807                 user_asking_for_transmural_layers = true;
00808                 if (mMidFraction <0)
00809                 {
00810                     user_supplied_negative_value=true;
00811                 }
00812                 mIndexMid =  counter_of_heterogeneities;
00813             }
00814         }
00815         rScaleFactorGks.push_back (ht.ScaleFactorGks());
00816         rScaleFactorIto.push_back (ht.ScaleFactorIto());
00817         rScaleFactorGkr.push_back (ht.ScaleFactorGkr());
00818         counter_of_heterogeneities++;
00819     }
00820 
00821     //set the flag for request of transmural layers
00822      mUserAskedForCellularTransmuralHeterogeneities = user_asking_for_transmural_layers;
00823 
00824      // cuboids and layers at the same time are not yet supported
00825      if (mUserAskedForCuboidsForCellularHeterogeneities && mUserAskedForCellularTransmuralHeterogeneities)
00826      {
00827          // free the pointers before throwing the exception
00828         for (unsigned index=0;index < rCellHeterogeneityRegions.size(); index++)
00829         {
00830             delete rCellHeterogeneityRegions[index];
00831         }
00832         EXCEPTION ("Specification of cellular heterogeneities by cuboids and layers at the same time is not yet supported");
00833      }
00834      //check the user input if the transmural heterogeneities have been requested
00835      if (mUserAskedForCellularTransmuralHeterogeneities)
00836      {
00837         //check that the user supplied all three layers, the indexes should be 0, 1 and 2.
00838         // As they are initialised to a higher value, if their summation is higher than 3,
00839         // one (or more) is missing
00840         if ((mIndexMid+mIndexEndo+mIndexEpi) > 3)
00841         {
00842             EXCEPTION ("Three specifications of layers must be supplied");
00843         }
00844         if (fabs((mEndoFraction+mMidFraction+mEpiFraction)-1)>1e-2)
00845         {
00846             EXCEPTION ("Summation of epicardial, midmyocardial and endocardial fractions should be 1");
00847         }
00848         if (user_supplied_negative_value)
00849         {
00850            EXCEPTION ("Fractions must be positive");
00851         }
00852      }
00853 }
00854 
00855 bool HeartConfig::AreCellularTransmuralHeterogeneitiesRequested()
00856 {
00857     return mUserAskedForCellularTransmuralHeterogeneities;
00858 }
00859 
00860 bool HeartConfig::AreCellularlHeterogeneitiesSpecifiedByCuboids()
00861 {
00862     return mUserAskedForCuboidsForCellularHeterogeneities;
00863 }
00864 
00865 double HeartConfig::GetEpiLayerFraction()
00866 {
00867     return mEpiFraction;
00868 }
00869 
00870 double HeartConfig::GetEndoLayerFraction()
00871 {
00872     return mEndoFraction;
00873 }
00874 
00875 double HeartConfig::GetMidLayerFraction()
00876 {
00877     return mMidFraction;
00878 }
00879 
00880 unsigned HeartConfig::GetEpiLayerIndex()
00881 {
00882     return mIndexEpi;
00883 }
00884 
00885 unsigned HeartConfig::GetEndoLayerIndex()
00886 {
00887     return mIndexEndo;
00888 }
00889 
00890 unsigned HeartConfig::GetMidLayerIndex()
00891 {
00892     return mIndexMid;
00893 }
00894 
00895 bool HeartConfig::GetConductivityHeterogeneitiesProvided() const
00896 {
00897     CheckSimulationIsDefined("ConductivityHeterogeneities");
00898     try
00899     {
00900         DecideLocation( & mpUserParameters->Simulation().get().ConductivityHeterogeneities(),
00901                         & mpDefaultParameters->Simulation().get().ConductivityHeterogeneities(),
00902                         "ConductivityHeterogeneities");
00903         return true;
00904     }
00905     catch (Exception& e)
00906     {
00907         return false;
00908     }
00909 }
00910 
00911 template<unsigned DIM>
00912 void HeartConfig::GetConductivityHeterogeneities(
00913         std::vector<ChasteCuboid<DIM> >& conductivitiesHeterogeneityAreas,
00914         std::vector< c_vector<double,3> >& intraConductivities,
00915         std::vector< c_vector<double,3> >& extraConductivities) const
00916 {
00917     CheckSimulationIsDefined("ConductivityHeterogeneities");
00918     XSD_ANON_SEQUENCE_TYPE(cp::simulation_type, ConductivityHeterogeneities, ConductivityHeterogeneity)&
00919          conductivity_heterogeneity = DecideLocation( & mpUserParameters->Simulation().get().ConductivityHeterogeneities(),
00920                                                       & mpDefaultParameters->Simulation().get().ConductivityHeterogeneities(),
00921                                                       "ConductivityHeterogeneities")->get().ConductivityHeterogeneity();
00922 
00923     for (XSD_ANON_ITERATOR_TYPE(cp::simulation_type, ConductivityHeterogeneities, ConductivityHeterogeneity) i = conductivity_heterogeneity.begin();
00924          i != conductivity_heterogeneity.end();
00925          ++i)
00926     {
00927         cp::conductivity_heterogeneity_type ht(*i);
00928         if (ht.Location().Cuboid().present())
00929         {
00930             cp::point_type point_a = ht.Location().Cuboid()->LowerCoordinates();
00931             cp::point_type point_b = ht.Location().Cuboid()->UpperCoordinates();
00932 
00933             switch (DIM)
00934             {
00935                 case 1:
00936                 {
00937                     ChastePoint<DIM> chaste_point_a ( point_a.x() );
00938                     ChastePoint<DIM> chaste_point_b ( point_b.x() );
00939                     conductivitiesHeterogeneityAreas.push_back( ChasteCuboid<DIM> ( chaste_point_a, chaste_point_b ) );
00940                     break;
00941                 }
00942                 case 2:
00943                 {
00944                     ChastePoint<DIM> chaste_point_a ( point_a.x(), point_a.y() );
00945                     ChastePoint<DIM> chaste_point_b ( point_b.x(), point_b.y() );
00946                     conductivitiesHeterogeneityAreas.push_back( ChasteCuboid<DIM> ( chaste_point_a, chaste_point_b ) );
00947                     break;
00948                 }
00949                 case 3:
00950                 {
00951                     ChastePoint<DIM> chaste_point_a ( point_a.x(), point_a.y(), point_a.z() );
00952                     ChastePoint<DIM> chaste_point_b ( point_b.x(), point_b.y(), point_b.z() );
00953                     conductivitiesHeterogeneityAreas.push_back( ChasteCuboid<DIM> ( chaste_point_a, chaste_point_b ) );
00954                     break;
00955                 }
00956                 default:
00957                     NEVER_REACHED;
00958                     break;
00959             }
00960 
00961 
00962         }
00963         else
00964         {
00965             if(ht.Location().EpiLayer().present() || ht.Location().MidLayer().present() || ht.Location().EndoLayer().present() )
00966             {
00968                 EXCEPTION("Definition of transmural layers is not allowed for conductivities heterogeneities, you may use fibre orientation support instead");
00969             }
00970         }
00971 
00972         if (ht.IntracellularConductivities().present())
00973         {
00974             double intra_x = ht.IntracellularConductivities().get().longi();
00975             double intra_y = ht.IntracellularConductivities().get().trans();
00976             double intra_z = ht.IntracellularConductivities().get().normal();
00977 
00978             intraConductivities.push_back( Create_c_vector(intra_x, intra_y, intra_z) );
00979         }
00980         else
00981         {
00982             c_vector<double, 3> intra_conductivities;
00983             GetIntracellularConductivities(intra_conductivities);
00984             intraConductivities.push_back(intra_conductivities);
00985         }
00986 
00987         if (ht.ExtracellularConductivities().present())
00988         {
00989             double extra_x = ht.ExtracellularConductivities().get().longi();
00990             double extra_y = ht.ExtracellularConductivities().get().trans();
00991             double extra_z = ht.ExtracellularConductivities().get().normal();
00992 
00993             extraConductivities.push_back( Create_c_vector(extra_x, extra_y, extra_z) );
00994         }
00995         else
00996         {
00997             c_vector<double, 3> extra_conductivities;
00998             GetExtracellularConductivities(extra_conductivities);
00999             extraConductivities.push_back(extra_conductivities);
01000         }
01001 
01002     }
01003 }
01004 
01005 std::string HeartConfig::GetOutputDirectory() const
01006 {
01007     CheckSimulationIsDefined("Simulation/OutputDirectory");
01008     return DecideLocation( & mpUserParameters->Simulation().get().OutputDirectory(),
01009                            & mpDefaultParameters->Simulation().get().OutputDirectory(),
01010                            "Simulation/OutputDirectory")->get();
01011 }
01012 
01013 std::string HeartConfig::GetOutputFilenamePrefix() const
01014 {
01015     CheckSimulationIsDefined("Simulation/OutputFilenamePrefix");
01016     return DecideLocation( & mpUserParameters->Simulation().get().OutputFilenamePrefix(),
01017                            & mpDefaultParameters->Simulation().get().OutputFilenamePrefix(),
01018                            "Simulation/OutputFilenamePrefix")->get();
01019 }
01020 
01021 bool HeartConfig::GetOutputVariablesProvided() const
01022 {
01023     CheckSimulationIsDefined("OutputVariables");
01024 
01025     try
01026     {
01027         DecideLocation( & mpUserParameters->Simulation().get().OutputVariables(),
01028                         & mpDefaultParameters->Simulation().get().OutputVariables(),
01029                         "OutputVariables");
01030         return true;
01031     }
01032     catch (Exception& e)
01033     {
01034         return false;
01035     }
01036 }
01037 
01038 void HeartConfig::GetOutputVariables(std::vector<std::string> &outputVariables) const
01039 {
01040     CheckSimulationIsDefined("OutputVariables");
01041     XSD_SEQUENCE_TYPE(cp::output_variables_type::Var)&
01042          output_variables = DecideLocation( & mpUserParameters->Simulation().get().OutputVariables(),
01043                                             & mpDefaultParameters->Simulation().get().OutputVariables(),
01044                                             "OutputVariables")->get().Var();
01045 
01046     for (XSD_ITERATOR_TYPE(cp::output_variables_type::Var) i = output_variables.begin();
01047          i != output_variables.end();
01048          ++i)
01049     {
01050         cp::var_type var(*i);
01051 
01052         // Add to outputVariables the string returned by var.name()
01053         outputVariables.push_back(var.name());
01054     }
01055 }
01056 
01057 bool HeartConfig::GetCheckpointSimulation() const
01058 {
01059     try
01060     {
01061         if (IsSimulationDefined())
01062         {
01063             CheckSimulationIsDefined("GetSaveSimulation");
01064             DecideLocation( & mpUserParameters->Simulation().get().CheckpointSimulation(),
01065                             & mpDefaultParameters->Simulation().get().CheckpointSimulation(),
01066                             "Simulation/SaveSimulation");
01067         }
01068         else
01069         {
01070             CheckResumeSimulationIsDefined("GetSaveSimulation");
01071             DecideLocation( & mpUserParameters->ResumeSimulation().get().CheckpointSimulation(),
01072                             & mpDefaultParameters->Simulation().get().CheckpointSimulation(),
01073                             "ResumeSimulation/SaveSimulation");
01074         }
01075         return true;
01076     }
01077     catch (Exception& e)
01078     {
01079         return false;
01080     }
01081 }
01082 
01083 double HeartConfig::GetCheckpointTimestep() const
01084 {
01085     if (IsSimulationDefined())
01086     {
01087         CheckSimulationIsDefined("GetSaveSimulation");
01088         return DecideLocation( & mpUserParameters->Simulation().get().CheckpointSimulation(),
01089                         & mpDefaultParameters->Simulation().get().CheckpointSimulation(),
01090                         "Simulation/SaveSimulation")->get().timestep();
01091     }
01092     else
01093     {
01094         CheckResumeSimulationIsDefined("GetSaveSimulation");
01095         return DecideLocation( & mpUserParameters->ResumeSimulation().get().CheckpointSimulation(),
01096                         & mpDefaultParameters->Simulation().get().CheckpointSimulation(),
01097                         "ResumeSimulation/SaveSimulation")->get().timestep();
01098     }
01099 }
01100 
01101 unsigned HeartConfig::GetMaxCheckpointsOnDisk() const
01102 {
01103     if (IsSimulationDefined())
01104     {
01105         CheckSimulationIsDefined("GetSaveSimulation");
01106         return DecideLocation( & mpUserParameters->Simulation().get().CheckpointSimulation(),
01107                         & mpDefaultParameters->Simulation().get().CheckpointSimulation(),
01108                         "Simulation/SaveSimulation")->get().max_checkpoints_on_disk();
01109     }
01110     else
01111     {
01112         CheckResumeSimulationIsDefined("GetSaveSimulation");
01113         return DecideLocation( & mpUserParameters->ResumeSimulation().get().CheckpointSimulation(),
01114                         & mpDefaultParameters->Simulation().get().CheckpointSimulation(),
01115                         "ResumeSimulation/SaveSimulation")->get().max_checkpoints_on_disk();
01116     }
01117 }
01118 
01119 
01120 std::string HeartConfig::GetArchivedSimulationDir() const
01121 {
01122     CheckResumeSimulationIsDefined("GetArchivedSimulationDir");
01123 
01124     return mpUserParameters->ResumeSimulation().get().ArchiveDirectory();
01125 }
01126 
01127 
01128 void HeartConfig::GetIntracellularConductivities(c_vector<double, 3>& intraConductivities) const
01129 {
01130     optional<cp::conductivities_type, false>* intra_conductivities
01131         = DecideLocation( & mpUserParameters->Physiological().IntracellularConductivities(),
01132                           & mpDefaultParameters->Physiological().IntracellularConductivities(),
01133                           "IntracellularConductivities");
01134     double intra_x_cond = intra_conductivities->get().longi();
01135     double intra_y_cond = intra_conductivities->get().trans();
01136     double intra_z_cond = intra_conductivities->get().normal();;
01137 
01138     assert(intra_y_cond != DBL_MAX);
01139     assert(intra_z_cond != DBL_MAX);
01140 
01141     intraConductivities[0] = intra_x_cond;
01142     intraConductivities[1] = intra_y_cond;
01143     intraConductivities[2] = intra_z_cond;
01144 }
01145 
01146 void HeartConfig::GetIntracellularConductivities(c_vector<double, 2>& intraConductivities) const
01147 {
01148     optional<cp::conductivities_type, false>* intra_conductivities
01149         = DecideLocation( & mpUserParameters->Physiological().IntracellularConductivities(),
01150                           & mpDefaultParameters->Physiological().IntracellularConductivities(),
01151                           "IntracellularConductivities");
01152     double intra_x_cond = intra_conductivities->get().longi();
01153     double intra_y_cond = intra_conductivities->get().trans();
01154 
01155     assert(intra_y_cond != DBL_MAX);
01156 
01157     intraConductivities[0] = intra_x_cond;
01158     intraConductivities[1] = intra_y_cond;
01159 }
01160 
01161 void HeartConfig::GetIntracellularConductivities(c_vector<double, 1>& intraConductivities) const
01162 {
01163     optional<cp::conductivities_type, false>* intra_conductivities
01164         = DecideLocation( & mpUserParameters->Physiological().IntracellularConductivities(),
01165                           & mpDefaultParameters->Physiological().IntracellularConductivities(),
01166                           "IntracellularConductivities");
01167     double intra_x_cond = intra_conductivities->get().longi();
01168 
01169     intraConductivities[0] = intra_x_cond;
01170 }
01171 
01172 void HeartConfig::GetExtracellularConductivities(c_vector<double, 3>& extraConductivities) const
01173 {
01174     optional<cp::conductivities_type, false>* extra_conductivities
01175         = DecideLocation( & mpUserParameters->Physiological().ExtracellularConductivities(),
01176                           & mpDefaultParameters->Physiological().ExtracellularConductivities(),
01177                           "ExtracellularConductivities");
01178     double extra_x_cond = extra_conductivities->get().longi();
01179     double extra_y_cond = extra_conductivities->get().trans();
01180     double extra_z_cond = extra_conductivities->get().normal();;
01181 
01182     assert(extra_y_cond != DBL_MAX);
01183     assert(extra_z_cond != DBL_MAX);
01184 
01185     extraConductivities[0] = extra_x_cond;
01186     extraConductivities[1] = extra_y_cond;
01187     extraConductivities[2] = extra_z_cond;
01188 }
01189 
01190 void HeartConfig::GetExtracellularConductivities(c_vector<double, 2>& extraConductivities) const
01191 {
01192     optional<cp::conductivities_type, false>* extra_conductivities
01193         = DecideLocation( & mpUserParameters->Physiological().ExtracellularConductivities(),
01194                           & mpDefaultParameters->Physiological().ExtracellularConductivities(),
01195                           "ExtracellularConductivities");
01196     double extra_x_cond = extra_conductivities->get().longi();
01197     double extra_y_cond = extra_conductivities->get().trans();
01198 
01199     assert(extra_y_cond != DBL_MAX);
01200 
01201     extraConductivities[0] = extra_x_cond;
01202     extraConductivities[1] = extra_y_cond;
01203 }
01204 
01205 void HeartConfig::GetExtracellularConductivities(c_vector<double, 1>& extraConductivities) const
01206 {
01207     optional<cp::conductivities_type, false>* extra_conductivities
01208         = DecideLocation( & mpUserParameters->Physiological().ExtracellularConductivities(),
01209                           & mpDefaultParameters->Physiological().ExtracellularConductivities(),
01210                           "ExtracellularConductivities");
01211     double extra_x_cond = extra_conductivities->get().longi();
01212 
01213     extraConductivities[0] = extra_x_cond;
01214 }
01215 
01216 double HeartConfig::GetBathConductivity() const
01217 {
01218     /*bath conductivity mS/cm*/
01219     return DecideLocation( & mpUserParameters->Physiological().BathConductivity(),
01220                            & mpDefaultParameters->Physiological().BathConductivity(),
01221                            "BathConductivity")->get();
01222 }
01223 
01224 double HeartConfig::GetSurfaceAreaToVolumeRatio() const
01225 {
01226     /*surface area to volume ratio: 1/cm*/
01227     return DecideLocation( & mpUserParameters->Physiological().SurfaceAreaToVolumeRatio(),
01228                            & mpDefaultParameters->Physiological().SurfaceAreaToVolumeRatio(),
01229                            "SurfaceAreaToVolumeRatio")->get();
01230 }
01231 
01232 double HeartConfig::GetCapacitance() const
01233 {
01234     //         capacitance                 : uF/cm^2
01235     return DecideLocation( & mpUserParameters->Physiological().Capacitance(),
01236                            & mpDefaultParameters->Physiological().Capacitance(),
01237                            "Capacitance")->get();
01238 }
01239 
01240 double HeartConfig::GetOdeTimeStep() const
01241 {
01242     return DecideLocation( & mpUserParameters->Numerical().TimeSteps(),
01243                            & mpDefaultParameters->Numerical().TimeSteps(),
01244                            "ode TimeStep")->get().ode();
01245 }
01246 
01247 double HeartConfig::GetPdeTimeStep() const
01248 {
01249     return DecideLocation( & mpUserParameters->Numerical().TimeSteps(),
01250                            & mpDefaultParameters->Numerical().TimeSteps(),
01251                            "pde TimeStep")->get().pde();
01252 }
01253 
01254 double HeartConfig::GetPrintingTimeStep() const
01255 {
01256     return DecideLocation( & mpUserParameters->Numerical().TimeSteps(),
01257                            & mpDefaultParameters->Numerical().TimeSteps(),
01258                            "printing TimeStep")->get().printing();
01259 }
01260 
01261 bool HeartConfig::GetUseAbsoluteTolerance() const
01262 {
01263     return DecideLocation( & mpUserParameters->Numerical().KSPTolerances(),
01264                             & mpDefaultParameters->Numerical().KSPTolerances(),
01265                             "KSPTolerances")->get().KSPAbsolute().present();
01266 }
01267 
01268 double HeartConfig::GetAbsoluteTolerance() const
01269 {
01270     if (!GetUseAbsoluteTolerance())
01271     {
01272         EXCEPTION("Absolute tolerance is not set in Chaste parameters");
01273     }
01274     return DecideLocation( & mpUserParameters->Numerical().KSPTolerances(),
01275                            & mpDefaultParameters->Numerical().KSPTolerances(),
01276                            "KSPTolerances")->get().KSPAbsolute().get();
01277 }
01278 
01279 bool HeartConfig::GetUseRelativeTolerance() const
01280 {
01281      return DecideLocation( & mpUserParameters->Numerical().KSPTolerances(),
01282                             & mpDefaultParameters->Numerical().KSPTolerances(),
01283                             "KSPTolerances")->get().KSPRelative().present();
01284 }
01285 
01286 double HeartConfig::GetRelativeTolerance() const
01287 {
01288     if (!GetUseRelativeTolerance())
01289     {
01290         EXCEPTION("Relative tolerance is not set in Chaste parameters");
01291     }
01292     return DecideLocation( & mpUserParameters->Numerical().KSPTolerances(),
01293                            & mpDefaultParameters->Numerical().KSPTolerances(),
01294                            "KSPTolerances")->get().KSPRelative().get();
01295 }
01296 
01297 const char* HeartConfig::GetKSPSolver() const
01298 {
01299     switch ( DecideLocation( & mpUserParameters->Numerical().KSPSolver(),
01300                              & mpDefaultParameters->Numerical().KSPSolver(),
01301                             "KSPSolver")->get() )
01302     {
01303         case cp::ksp_solver_type::gmres :
01304             return "gmres";
01305         case cp::ksp_solver_type::cg :
01306             return "cg";
01307         case cp::ksp_solver_type::symmlq :
01308             return "symmlq";
01309     }
01310 #define COVERAGE_IGNORE
01311     EXCEPTION("Unknown ksp solver");
01312 #undef COVERAGE_IGNORE
01313 }
01314 
01315 const char* HeartConfig::GetKSPPreconditioner() const
01316 {
01317     switch ( DecideLocation( & mpUserParameters->Numerical().KSPPreconditioner(),
01318                              & mpDefaultParameters->Numerical().KSPPreconditioner(),
01319                              "KSPPreconditioner")->get() )
01320     {
01321         case cp::ksp_preconditioner_type::ilu :
01322             return "ilu";
01323         case cp::ksp_preconditioner_type::jacobi :
01324             return "jacobi";
01325         case cp::ksp_preconditioner_type::bjacobi :
01326             return "bjacobi";
01327         case cp::ksp_preconditioner_type::hypre :
01328             return "hypre";
01329         case cp::ksp_preconditioner_type::ml :
01330             return "ml";
01331         case cp::ksp_preconditioner_type::spai :
01332             return "spai";
01333         case cp::ksp_preconditioner_type::blockdiagonal :
01334             return "blockdiagonal";
01335         case cp::ksp_preconditioner_type::ldufactorisation :
01336             return "ldufactorisation";
01337         case cp::ksp_preconditioner_type::none :
01338             return "none";
01339 
01340     }
01341 #define COVERAGE_IGNORE
01342     EXCEPTION("Unknown ksp preconditioner");
01343 #undef COVERAGE_IGNORE
01344 }
01345 
01346 bool HeartConfig::IsAdaptivityParametersPresent() const
01347 {
01348     try
01349     {
01350         DecideLocation( & mpUserParameters->Numerical().AdaptivityParameters(),
01351                         & mpDefaultParameters->Numerical().AdaptivityParameters(),
01352                         "AdaptivityParameters")->present();
01353         //If there's a section
01354         return true;
01355     }
01356     catch (Exception &e)
01357     {
01358         //No section
01359         return false;
01360     }
01361 }
01362 
01363 double HeartConfig::GetTargetErrorForAdaptivity() const
01364 {
01365     if ( IsAdaptivityParametersPresent() )
01366     {
01367         return DecideLocation( & mpUserParameters->Numerical().AdaptivityParameters(),
01368                                & mpDefaultParameters->Numerical().AdaptivityParameters(),
01369                                "TargetError")->get().target_error();
01370     }
01371     else
01372     {
01373         EXCEPTION("Adaptivity parameters have not been set");
01374     }
01375 }
01376 
01377 double HeartConfig::GetSigmaForAdaptivity() const
01378 {
01379     if ( IsAdaptivityParametersPresent() )
01380     {
01381         return DecideLocation( & mpUserParameters->Numerical().AdaptivityParameters(),
01382                                & mpDefaultParameters->Numerical().AdaptivityParameters(),
01383                                "TargetError")->get().sigma();
01384     }
01385     else
01386     {
01387         EXCEPTION("Adaptivity parameters have not been set");
01388     }
01389 }
01390 
01391 double HeartConfig::GetMaxEdgeLengthForAdaptivity() const
01392 {
01393     if ( IsAdaptivityParametersPresent() )
01394     {
01395     return DecideLocation( & mpUserParameters->Numerical().AdaptivityParameters(),
01396                            & mpDefaultParameters->Numerical().AdaptivityParameters(),
01397                            "TargetError")->get().max_edge_length();
01398     }
01399     else
01400     {
01401         EXCEPTION("Adaptivity parameters have not been set");
01402     }
01403 }
01404 
01405 double HeartConfig::GetMinEdgeLengthForAdaptivity() const
01406 {
01407     if ( IsAdaptivityParametersPresent() )
01408     {
01409         return DecideLocation( & mpUserParameters->Numerical().AdaptivityParameters(),
01410                                & mpDefaultParameters->Numerical().AdaptivityParameters(),
01411                                "TargetError")->get().min_edge_length();
01412     }
01413     else
01414     {
01415         EXCEPTION("Adaptivity parameters have not been set");
01416     }
01417 }
01418 
01419 double HeartConfig::GetGradationForAdaptivity() const
01420 {
01421     if ( IsAdaptivityParametersPresent() )
01422     {
01423         return DecideLocation( & mpUserParameters->Numerical().AdaptivityParameters(),
01424                                & mpDefaultParameters->Numerical().AdaptivityParameters(),
01425                                "TargetError")->get().gradation();
01426     }
01427     else
01428     {
01429         EXCEPTION("Adaptivity parameters have not been set");
01430     }
01431 }
01432 
01433 unsigned HeartConfig::GetMaxNodesForAdaptivity() const
01434 {
01435     if ( IsAdaptivityParametersPresent() )
01436     {
01437         return DecideLocation( & mpUserParameters->Numerical().AdaptivityParameters(),
01438                                & mpDefaultParameters->Numerical().AdaptivityParameters(),
01439                                "TargetError")->get().max_nodes();
01440     }
01441     else
01442     {
01443         EXCEPTION("Adaptivity parameters have not been set");
01444     }
01445 }
01446 
01447 unsigned HeartConfig::GetNumberOfAdaptiveSweeps() const
01448 {
01449     if ( IsAdaptivityParametersPresent() )
01450     {
01451         return DecideLocation( & mpUserParameters->Numerical().AdaptivityParameters(),
01452                                & mpDefaultParameters->Numerical().AdaptivityParameters(),
01453                                "TargetError")->get().num_sweeps();
01454     }
01455     else
01456     {
01457         EXCEPTION("Adaptivity parameters have not been set");
01458     }
01459 }
01460 
01461 /*
01462  * PostProcessing
01463  */
01464 
01465 bool HeartConfig::IsPostProcessingSectionPresent() const
01466 {
01467     try
01468     {
01469         DecideLocation( & mpUserParameters->PostProcessing(),
01470                         & mpDefaultParameters->PostProcessing(),
01471                         "PostProcessing")->present();
01472         //If there's a section
01473         return true;
01474     }
01475     catch (Exception &e)
01476     {
01477         //No section
01478         return false;
01479     }
01480 }
01481 
01482 bool HeartConfig::IsPostProcessingRequested() const
01483 {
01484     if (IsPostProcessingSectionPresent() == false)
01485     {
01486         return false;
01487     }
01488     else
01489     {
01490         return(IsApdMapsRequested() ||
01491                IsUpstrokeTimeMapsRequested() ||
01492                IsMaxUpstrokeVelocityMapRequested() ||
01493                IsConductionVelocityMapsRequested());
01494     }
01495 }
01496 bool HeartConfig::IsApdMapsRequested() const
01497 {
01498     assert(IsPostProcessingSectionPresent());
01499 
01500     XSD_SEQUENCE_TYPE(cp::postprocessing_type::ActionPotentialDurationMap)&
01501         apd_maps = DecideLocation( & mpUserParameters->PostProcessing(),
01502                                    & mpDefaultParameters->PostProcessing(),
01503                                    "ActionPotentialDurationMap")->get().ActionPotentialDurationMap();
01504     return (apd_maps.begin() != apd_maps.end());
01505 }
01506 
01507 void HeartConfig::GetApdMaps(std::vector<std::pair<double,double> >& apd_maps) const
01508 {
01509     assert(IsApdMapsRequested());
01510     apd_maps.clear();
01511 
01512     XSD_SEQUENCE_TYPE(cp::postprocessing_type::ActionPotentialDurationMap)&
01513         apd_maps_sequence = DecideLocation( & mpUserParameters->PostProcessing(),
01514                                             & mpDefaultParameters->PostProcessing(),
01515                                             "ActionPotentialDurationMap")->get().ActionPotentialDurationMap();
01516 
01517     for (XSD_ITERATOR_TYPE(cp::postprocessing_type::ActionPotentialDurationMap) i = apd_maps_sequence.begin();
01518          i != apd_maps_sequence.end();
01519          ++i)
01520     {
01521         std::pair<double,double> map(i->repolarisation_percentage(),i->threshold());
01522 
01523         apd_maps.push_back(map);
01524     }
01525 }
01526 
01527 bool HeartConfig::IsUpstrokeTimeMapsRequested() const
01528 {
01529     assert(IsPostProcessingSectionPresent());
01530 
01531     XSD_SEQUENCE_TYPE(cp::postprocessing_type::UpstrokeTimeMap)&
01532         upstroke_map = DecideLocation( & mpUserParameters->PostProcessing(),
01533                                        & mpDefaultParameters->PostProcessing(),
01534                                        "UpstrokeTimeMap")->get().UpstrokeTimeMap();
01535     return (upstroke_map.begin() != upstroke_map.end());
01536 }
01537 void HeartConfig::GetUpstrokeTimeMaps (std::vector<double>& upstroke_time_maps) const
01538 {
01539     assert(IsUpstrokeTimeMapsRequested());
01540     assert(upstroke_time_maps.size() == 0);
01541 
01542     XSD_SEQUENCE_TYPE(cp::postprocessing_type::UpstrokeTimeMap)&
01543         upstroke_maps_sequence = DecideLocation( & mpUserParameters->PostProcessing(),
01544                                                  & mpDefaultParameters->PostProcessing(),
01545                                                  "UpstrokeTimeMap")->get().UpstrokeTimeMap();
01546 
01547     for (XSD_ITERATOR_TYPE(cp::postprocessing_type::UpstrokeTimeMap) i = upstroke_maps_sequence.begin();
01548          i != upstroke_maps_sequence.end();
01549          ++i)
01550     {
01551         upstroke_time_maps.push_back(i->threshold());
01552     }
01553 }
01554 
01555 bool HeartConfig::IsMaxUpstrokeVelocityMapRequested() const
01556 {
01557     assert(IsPostProcessingSectionPresent());
01558 
01559     XSD_SEQUENCE_TYPE(cp::postprocessing_type::MaxUpstrokeVelocityMap)&
01560         max_upstroke_velocity_map = DecideLocation( & mpUserParameters->PostProcessing(),
01561                                                     & mpDefaultParameters->PostProcessing(),
01562                                                     "MaxUpstrokeVelocityMap")->get().MaxUpstrokeVelocityMap();
01563 
01564     return (max_upstroke_velocity_map.begin() != max_upstroke_velocity_map.end());
01565 }
01566 
01567 void HeartConfig::GetMaxUpstrokeVelocityMaps(std::vector<double>& upstroke_velocity_maps) const
01568 {
01569     assert(IsMaxUpstrokeVelocityMapRequested());
01570     assert(upstroke_velocity_maps.size() == 0);
01571 
01572     XSD_SEQUENCE_TYPE(cp::postprocessing_type::MaxUpstrokeVelocityMap)&
01573         max_upstroke_velocity_maps_sequence = DecideLocation( & mpUserParameters->PostProcessing(),
01574                                                               & mpDefaultParameters->PostProcessing(),
01575                                                               "MaxUpstrokeVelocityMap")->get().MaxUpstrokeVelocityMap();
01576 
01577     for (XSD_ITERATOR_TYPE(cp::postprocessing_type::MaxUpstrokeVelocityMap) i = max_upstroke_velocity_maps_sequence.begin();
01578          i != max_upstroke_velocity_maps_sequence.end();
01579          ++i)
01580     {
01581         upstroke_velocity_maps.push_back(i->threshold());
01582     }
01583 }
01584 
01585 bool HeartConfig::IsConductionVelocityMapsRequested() const
01586 {
01587     assert(IsPostProcessingSectionPresent());
01588 
01589     XSD_SEQUENCE_TYPE(cp::postprocessing_type::ConductionVelocityMap)&
01590         cond_vel_maps = DecideLocation( & mpUserParameters->PostProcessing(),
01591                                         & mpDefaultParameters->PostProcessing(),
01592                                         "ConductionVelocityMap")->get().ConductionVelocityMap();
01593     return (cond_vel_maps.begin() != cond_vel_maps.end());
01594 }
01595 
01596 void HeartConfig::GetConductionVelocityMaps(std::vector<unsigned>& conduction_velocity_maps) const
01597 {
01598     assert(IsConductionVelocityMapsRequested());
01599     assert(conduction_velocity_maps.size() == 0);
01600 
01601     XSD_SEQUENCE_TYPE(cp::postprocessing_type::ConductionVelocityMap)&
01602         cond_vel_maps_sequence = DecideLocation( & mpUserParameters->PostProcessing(),
01603                                                  & mpDefaultParameters->PostProcessing(),
01604                                                  "ConductionVelocityMap")->get().ConductionVelocityMap();
01605 
01606     for (XSD_ITERATOR_TYPE(cp::postprocessing_type::ConductionVelocityMap) i = cond_vel_maps_sequence.begin();
01607          i != cond_vel_maps_sequence.end();
01608          ++i)
01609     {
01610         conduction_velocity_maps.push_back(i->origin_node());
01611     }
01612 }
01613 
01614 /*
01615  * Output visualization
01616  */
01617 
01618 bool HeartConfig::IsOutputVisualizerPresent() const
01619 {
01620     CheckSimulationIsDefined("OutputVisualizer");
01621 
01622     try
01623     {
01624         DecideLocation( & mpUserParameters->Simulation().get().OutputVisualizer(),
01625                         & mpDefaultParameters->Simulation().get().OutputVisualizer(),
01626                         "OutputVisualizer")->present();
01627         // If there's an element
01628         return true;
01629     }
01630     catch (Exception &e)
01631     {
01632         // No element
01633         return false;
01634     }
01635 }
01636 
01637 bool HeartConfig::GetVisualizeWithMeshalyzer() const
01638 {
01639     if (!IsOutputVisualizerPresent())
01640     {
01641         return true;
01642     }
01643     else
01644     {
01645         return DecideLocation( & mpUserParameters->Simulation().get().OutputVisualizer(),
01646                                & mpDefaultParameters->Simulation().get().OutputVisualizer(),
01647                                "OutputVisualizer")->get().meshalyzer() == cp::yesno_type::yes;
01648     }
01649 }
01650 
01651 bool HeartConfig::GetVisualizeWithCmgui() const
01652 {
01653     if (!IsOutputVisualizerPresent())
01654     {
01655         return false;
01656     }
01657     else
01658     {
01659         return DecideLocation( & mpUserParameters->Simulation().get().OutputVisualizer(),
01660                                & mpDefaultParameters->Simulation().get().OutputVisualizer(),
01661                                "OutputVisualizer")->get().cmgui() == cp::yesno_type::yes;
01662     }
01663 }
01664 
01665 bool HeartConfig::GetVisualizeWithVtk() const
01666 {
01667     if (!IsOutputVisualizerPresent())
01668     {
01669         return false;
01670     }
01671     else
01672     {
01673         return DecideLocation( & mpUserParameters->Simulation().get().OutputVisualizer(),
01674                                & mpDefaultParameters->Simulation().get().OutputVisualizer(),
01675                                "OutputVisualizer")->get().vtk() == cp::yesno_type::yes;
01676     }
01677 }
01678 
01679 
01680 /*
01681  *  Set methods
01682  */
01683 void HeartConfig::SetSpaceDimension(unsigned spaceDimension)
01684 {
01685     mpUserParameters->Simulation().get().SpaceDimension().set(spaceDimension);
01686 }
01687 
01688 void HeartConfig::SetSimulationDuration(double simulationDuration)
01689 {
01690     XSD_CREATE_WITH_FIXED_ATTR1(cp::time_type, time, simulationDuration, "ms");
01691     mpUserParameters->Simulation().get().SimulationDuration().set(time);
01692 }
01693 
01694 void HeartConfig::SetDomain(const cp::domain_type& rDomain)
01695 {
01696     mpUserParameters->Simulation().get().Domain().set(rDomain);
01697 }
01698 
01699 void HeartConfig::SetDefaultIonicModel(const cp::ionic_models_available_type& rIonicModel)
01700 {
01701     cp::ionic_model_selection_type ionic_model;
01702     ionic_model.Hardcoded(rIonicModel);
01703     cp::ionic_models_type container(ionic_model);
01704     mpUserParameters->Simulation().get().IonicModels().set(container);
01705 }
01706 
01707 void HeartConfig::SetSlabDimensions(double x, double y, double z, double inter_node_space)
01708 {
01709     if ( ! mpUserParameters->Simulation().get().Mesh().present())
01710     {
01711         XSD_CREATE_WITH_FIXED_ATTR(cp::mesh_type, mesh_to_load, "cm");
01712         mpUserParameters->Simulation().get().Mesh().set(mesh_to_load);
01713     }
01714 
01715     cp::slab_type slab_definition(x, y, z, inter_node_space);
01716     mpUserParameters->Simulation().get().Mesh().get().Slab().set(slab_definition);
01717 }
01718 
01719 void HeartConfig::SetSheetDimensions(double x, double y, double inter_node_space)
01720 {
01721     if ( ! mpUserParameters->Simulation().get().Mesh().present())
01722     {
01723         XSD_CREATE_WITH_FIXED_ATTR(cp::mesh_type, mesh_to_load, "cm");
01724         mpUserParameters->Simulation().get().Mesh().set(mesh_to_load);
01725     }
01726 
01727     cp::sheet_type sheet_definition(x, y, inter_node_space);
01728     mpUserParameters->Simulation().get().Mesh().get().Sheet().set(sheet_definition);
01729 }
01730 
01731 void HeartConfig::SetFibreLength(double x, double inter_node_space)
01732 {
01733     if ( ! mpUserParameters->Simulation().get().Mesh().present())
01734     {
01735         XSD_CREATE_WITH_FIXED_ATTR(cp::mesh_type, mesh_to_load, "cm");
01736         mpUserParameters->Simulation().get().Mesh().set(mesh_to_load);
01737     }
01738 
01739     cp::fibre_type fibre_definition(x, inter_node_space);
01740     mpUserParameters->Simulation().get().Mesh().get().Fibre().set(fibre_definition);
01741 }
01742 
01743 void HeartConfig::SetMeshFileName(std::string meshPrefix, cp::media_type fibreDefinition)
01744 {
01745     if ( ! mpUserParameters->Simulation().get().Mesh().present())
01746     {
01747         XSD_CREATE_WITH_FIXED_ATTR(cp::mesh_type, mesh_to_load, "cm");
01748         mpUserParameters->Simulation().get().Mesh().set(mesh_to_load);
01749     }
01750 
01751     XSD_NESTED_TYPE(cp::mesh_type::LoadMesh) mesh_prefix(meshPrefix, fibreDefinition);
01752     mpUserParameters->Simulation().get().Mesh().get().LoadMesh().set(mesh_prefix);
01753 }
01754 
01755 void HeartConfig::SetIonicModelRegions(std::vector<ChasteCuboid<3> >& rDefinedRegions,
01756                                        std::vector<cp::ionic_model_selection_type>& rIonicModels) const
01757 {
01758     assert(rDefinedRegions.size() == rIonicModels.size());
01760     XSD_SEQUENCE_TYPE(cp::ionic_models_type::Region)&
01761         regions = mpUserParameters->Simulation().get().IonicModels().get().Region();
01762     regions.clear();
01763     for (unsigned region_index=0; region_index<rDefinedRegions.size(); region_index++)
01764     {
01765         cp::point_type point_a(rDefinedRegions[region_index].rGetLowerCorner()[0],
01766                                rDefinedRegions[region_index].rGetLowerCorner()[1],
01767                                rDefinedRegions[region_index].rGetLowerCorner()[2]);
01768 
01769         cp::point_type point_b(rDefinedRegions[region_index].rGetUpperCorner()[0],
01770                                rDefinedRegions[region_index].rGetUpperCorner()[1],
01771                                rDefinedRegions[region_index].rGetUpperCorner()[2]);
01772 
01773         XSD_CREATE_WITH_FIXED_ATTR(cp::location_type, locn, "cm");
01774         locn.Cuboid().set(cp::box_type(point_a, point_b));
01775 
01776         cp::ionic_model_region_type region(rIonicModels[region_index], locn);
01777         regions.push_back(region);
01778     }
01779 }
01780 
01781 void HeartConfig::SetConductivityHeterogeneities(std::vector<ChasteCuboid<3> >& conductivityAreas,
01782         std::vector< c_vector<double,3> >& intraConductivities,
01783         std::vector< c_vector<double,3> >& extraConductivities)
01784 {
01785     assert ( conductivityAreas.size() == intraConductivities.size() );
01786     assert ( intraConductivities.size() == extraConductivities.size());
01787 
01788     XSD_ANON_SEQUENCE_TYPE(cp::simulation_type, ConductivityHeterogeneities, ConductivityHeterogeneity) heterogeneities_container;
01789 
01790     for (unsigned region_index=0; region_index<conductivityAreas.size(); region_index++)
01791     {
01792         cp::point_type point_a(conductivityAreas[region_index].rGetLowerCorner()[0],
01793                            conductivityAreas[region_index].rGetLowerCorner()[1],
01794                            conductivityAreas[region_index].rGetLowerCorner()[2]);
01795 
01796         cp::point_type point_b(conductivityAreas[region_index].rGetUpperCorner()[0],
01797                            conductivityAreas[region_index].rGetUpperCorner()[1],
01798                            conductivityAreas[region_index].rGetUpperCorner()[2]);
01799 
01800         XSD_CREATE_WITH_FIXED_ATTR(cp::location_type, locn, "cm");
01801         locn.Cuboid().set(cp::box_type(point_a, point_b));
01802         cp::conductivity_heterogeneity_type ht(locn);
01803 
01804         XSD_CREATE_WITH_FIXED_ATTR3(cp::conductivities_type, intra,
01805                                     intraConductivities[region_index][0],
01806                                     intraConductivities[region_index][1],
01807                                     intraConductivities[region_index][2],
01808                                     "mS/cm");
01809 
01810         ht.IntracellularConductivities(intra);
01811 
01812         XSD_CREATE_WITH_FIXED_ATTR3(cp::conductivities_type, extra,
01813                                     extraConductivities[region_index][0],
01814                                     extraConductivities[region_index][1],
01815                                     extraConductivities[region_index][2],
01816                                     "mS/cm");
01817 
01818         ht.ExtracellularConductivities(extra);
01819 
01820         heterogeneities_container.push_back(ht);
01821     }
01822 
01823     XSD_ANON_TYPE(cp::simulation_type, ConductivityHeterogeneities) heterogeneities_object;
01824     heterogeneities_object.ConductivityHeterogeneity(heterogeneities_container);
01825 
01826     mpUserParameters->Simulation().get().ConductivityHeterogeneities().set(heterogeneities_object);
01827 }
01828 
01829 
01830 void HeartConfig::SetOutputDirectory(const std::string& rOutputDirectory)
01831 {
01832     mpUserParameters->Simulation().get().OutputDirectory().set(rOutputDirectory);
01833 }
01834 
01835 void HeartConfig::SetOutputFilenamePrefix(const std::string& rOutputFilenamePrefix)
01836 {
01837     mpUserParameters->Simulation().get().OutputFilenamePrefix().set(rOutputFilenamePrefix);
01838 }
01839 
01840 void HeartConfig::SetOutputVariables(const std::vector<std::string>& rOutputVariables)
01841 {
01842     if ( ! mpUserParameters->Simulation().get().OutputVariables().present())
01843     {
01844         cp::output_variables_type variables_requested;
01845         mpUserParameters->Simulation().get().OutputVariables().set(variables_requested);
01846     }
01847 
01848     XSD_SEQUENCE_TYPE(cp::output_variables_type::Var)&
01849     var_type_sequence = mpUserParameters->Simulation().get().OutputVariables()->Var();
01850     //Erase or create a sequence
01851     var_type_sequence.clear();
01852 
01853     for (unsigned i=0; i<rOutputVariables.size(); i++)
01854     {
01855         cp::var_type temp(rOutputVariables[i]);
01856         var_type_sequence.push_back(temp);
01857     }
01858 
01859     if (rOutputVariables.size() > 0)
01860     {
01861         // Turn off Meshalyzer etc. output, to avoid errors
01862         SetVisualizeWithMeshalyzer(false);
01863         SetVisualizeWithCmgui(false);
01864         SetVisualizeWithVtk(false);
01865     }
01866 }
01867 
01868 void HeartConfig::SetCheckpointSimulation(bool saveSimulation, double checkpointTimestep, unsigned maxCheckpointsOnDisk)
01869 {
01870     if (saveSimulation)
01871     {
01872         // Make sure values for the optional parameters have been provided
01873         assert(checkpointTimestep!=-1.0 && maxCheckpointsOnDisk!=UINT_MAX);
01874 
01875         XSD_CREATE_WITH_FIXED_ATTR2(cp::simulation_type::XSD_NESTED_TYPE(CheckpointSimulation),
01876                                     cs,
01877                                     checkpointTimestep,
01878                                     maxCheckpointsOnDisk,
01879                                     "ms");
01880         mpUserParameters->Simulation().get().CheckpointSimulation().set(cs);
01881     }
01882     else
01883     {
01884         mpUserParameters->Simulation().get().CheckpointSimulation().reset();
01885     }
01886 
01887     CheckTimeSteps();
01888 }
01889 
01890 // Physiological
01891 void HeartConfig::SetIntracellularConductivities(const c_vector<double, 3>& intraConductivities)
01892 {
01893     XSD_CREATE_WITH_FIXED_ATTR3(cp::conductivities_type, intra,
01894                                 intraConductivities[0],
01895                                 intraConductivities[1],
01896                                 intraConductivities[2],
01897                                 "mS/cm");
01898 
01899     mpUserParameters->Physiological().IntracellularConductivities().set(intra);
01900 }
01901 
01902 void HeartConfig::SetIntracellularConductivities(const c_vector<double, 2>& intraConductivities)
01903 {
01904     XSD_CREATE_WITH_FIXED_ATTR3(cp::conductivities_type, intra,
01905                                 intraConductivities[0],
01906                                 intraConductivities[1],
01907                                 0.0, "mS/cm");
01908 
01909     mpUserParameters->Physiological().IntracellularConductivities().set(intra);
01910 }
01911 
01912 void HeartConfig::SetIntracellularConductivities(const c_vector<double, 1>& intraConductivities)
01913 {
01914     XSD_CREATE_WITH_FIXED_ATTR3(cp::conductivities_type, intra,
01915                                 intraConductivities[0],
01916                                 0.0, 0.0, "mS/cm");
01917 
01918     mpUserParameters->Physiological().IntracellularConductivities().set(intra);
01919 }
01920 
01921 void HeartConfig::SetExtracellularConductivities(const c_vector<double, 3>& extraConductivities)
01922 {
01923     XSD_CREATE_WITH_FIXED_ATTR3(cp::conductivities_type, extra,
01924                                 extraConductivities[0],
01925                                 extraConductivities[1],
01926                                 extraConductivities[2],
01927                                 "mS/cm");
01928 
01929     mpUserParameters->Physiological().ExtracellularConductivities().set(extra);
01930 }
01931 
01932 void HeartConfig::SetExtracellularConductivities(const c_vector<double, 2>& extraConductivities)
01933 {
01934     XSD_CREATE_WITH_FIXED_ATTR3(cp::conductivities_type, extra,
01935                                 extraConductivities[0],
01936                                 extraConductivities[1],
01937                                 0.0, "mS/cm");
01938 
01939     mpUserParameters->Physiological().ExtracellularConductivities().set(extra);
01940 }
01941 
01942 void HeartConfig::SetExtracellularConductivities(const c_vector<double, 1>& extraConductivities)
01943 {
01944     XSD_CREATE_WITH_FIXED_ATTR3(cp::conductivities_type, extra,
01945                                 extraConductivities[0],
01946                                 0.0, 0.0, "mS/cm");
01947 
01948     mpUserParameters->Physiological().ExtracellularConductivities().set(extra);
01949 }
01950 
01951 void HeartConfig::SetBathConductivity(double bathConductivity)
01952 {
01953     XSD_CREATE_WITH_FIXED_ATTR1(cp::conductivity_type, cond, bathConductivity, "mS/cm");
01954     mpUserParameters->Physiological().BathConductivity().set(cond);
01955 }
01956 
01957 void HeartConfig::SetSurfaceAreaToVolumeRatio(double ratio)
01958 {
01959     XSD_CREATE_WITH_FIXED_ATTR1(cp::inverse_length_type, ratio_object, ratio, "1/cm");
01960     mpUserParameters->Physiological().SurfaceAreaToVolumeRatio().set(ratio_object);
01961 }
01962 
01963 void HeartConfig::SetCapacitance(double capacitance)
01964 {
01965     XSD_CREATE_WITH_FIXED_ATTR1(cp::capacitance_type, capacitance_object, capacitance, "uF/cm^2");
01966     mpUserParameters->Physiological().Capacitance().set(capacitance_object);
01967 }
01968 
01969 
01970 // Numerical
01971 void HeartConfig::SetOdePdeAndPrintingTimeSteps(double odeTimeStep, double pdeTimeStep, double printingTimeStep)
01972 {
01973     XSD_CREATE_WITH_FIXED_ATTR3(cp::time_steps_type, time_steps,
01974                                 odeTimeStep, pdeTimeStep, printingTimeStep, "ms");
01975     mpUserParameters->Numerical().TimeSteps().set(time_steps);
01976     CheckTimeSteps();
01977 }
01978 
01979 void HeartConfig::SetOdeTimeStep(double odeTimeStep)
01980 {
01981     SetOdePdeAndPrintingTimeSteps(odeTimeStep, GetPdeTimeStep(), GetPrintingTimeStep());
01982 }
01983 
01984 void HeartConfig::SetPdeTimeStep(double pdeTimeStep)
01985 {
01986     SetOdePdeAndPrintingTimeSteps(GetOdeTimeStep(), pdeTimeStep, GetPrintingTimeStep());
01987 }
01988 
01989 void HeartConfig::SetPrintingTimeStep(double printingTimeStep)
01990 {
01991     SetOdePdeAndPrintingTimeSteps(GetOdeTimeStep(), GetPdeTimeStep(), printingTimeStep);
01992 }
01993 
01994 void HeartConfig::CheckTimeSteps() const
01995 {
01996     if (GetOdeTimeStep() <= 0)
01997     {
01998         EXCEPTION("Ode time-step should be positive");
01999     }
02000     if (GetPdeTimeStep() <= 0)
02001     {
02002         EXCEPTION("Pde time-step should be positive");
02003     }
02004     if (GetPrintingTimeStep() <= 0.0)
02005     {
02006         EXCEPTION("Printing time-step should be positive");
02007     }
02008 
02009     if (GetPdeTimeStep()>GetPrintingTimeStep())
02010     {
02011         EXCEPTION("Printing time-step should not be smaller than PDE time-step");
02012     }
02013 
02014     //If pde divides printing then the floating remainder ought to be close to
02015     //zero(+a smidge) or pde-a smidge
02016     double remainder=fmod(GetPrintingTimeStep(), GetPdeTimeStep());
02017 
02018     if ( remainder > DBL_EPSILON && remainder < GetPdeTimeStep()-DBL_EPSILON)
02019     {
02020         EXCEPTION("Printing time-step should be a multiple of PDE time step");
02021     }
02022 
02023     if ( GetOdeTimeStep() > GetPdeTimeStep() )
02024     {
02025         EXCEPTION("Ode time-step should not be greater than PDE time-step");
02026     }
02027 
02028     if (GetCheckpointSimulation())
02029     {
02030         if (GetCheckpointTimestep() <= 0.0)
02031         {
02032             EXCEPTION("Checkpoint time-step should be positive");
02033         }
02034 
02035         //If printing divides checkpoint then the floating remainder ought to be close to
02036         //zero(+a smidge) or pde-a smidge
02037         double remainder_checkpoint_over_printing=fmod(GetCheckpointTimestep(), GetPrintingTimeStep());
02038 
02039         // I (migb) had to scale DBL_EPSILON because the comparison wasn't working properly with GetCheckpointTimestep()=10.0 GetPrintingTimeStep()=0.1
02040         if ( remainder_checkpoint_over_printing > DBL_EPSILON && remainder_checkpoint_over_printing < GetPrintingTimeStep()-DBL_EPSILON*(1/GetPrintingTimeStep()))
02041         {
02042             EXCEPTION("Checkpoint time-step should be a multiple of printing time-step");
02043         }
02044     }
02045 }
02046 
02047 
02048 void HeartConfig::SetUseRelativeTolerance(double relativeTolerance)
02049 {
02050     //Remove any reference to tolerances is user parameters
02051     mpUserParameters->Numerical().KSPTolerances().get().KSPAbsolute().reset();
02052     mpUserParameters->Numerical().KSPTolerances().get().KSPRelative().set(relativeTolerance);
02053 }
02054 
02055 void HeartConfig::SetUseAbsoluteTolerance(double absoluteTolerance)
02056 {
02057     //Remove any reference to tolerances is user parameters
02058     mpUserParameters->Numerical().KSPTolerances().get().KSPRelative().reset();
02059     mpUserParameters->Numerical().KSPTolerances().get().KSPAbsolute().set(absoluteTolerance);
02060 }
02061 
02062 void HeartConfig::SetKSPSolver(const char* kspSolver)
02063 {
02064     /* Note that changes in these conditions need to be reflected in the Doxygen*/
02065     if ( strcmp(kspSolver, "gmres") == 0)
02066     {
02067         mpUserParameters->Numerical().KSPSolver().set(cp::ksp_solver_type::gmres);
02068         return;
02069     }
02070     if ( strcmp(kspSolver, "cg") == 0)
02071     {
02072         mpUserParameters->Numerical().KSPSolver().set(cp::ksp_solver_type::cg);
02073         return;
02074     }
02075     if ( strcmp(kspSolver, "symmlq") == 0)
02076     {
02077         mpUserParameters->Numerical().KSPSolver().set(cp::ksp_solver_type::symmlq);
02078         return;
02079     }
02080 
02081     EXCEPTION("Unknown solver type provided");
02082 }
02083 
02084 void HeartConfig::SetKSPPreconditioner(const char* kspPreconditioner)
02085 {
02086     /* Note that changes in these conditions need to be reflected in the Doxygen*/
02087     if ( strcmp(kspPreconditioner, "ilu") == 0)
02088     {
02089         mpUserParameters->Numerical().KSPPreconditioner().set(cp::ksp_preconditioner_type::ilu);
02090         return;
02091     }
02092     if ( strcmp(kspPreconditioner, "jacobi") == 0)
02093     {
02094         mpUserParameters->Numerical().KSPPreconditioner().set(cp::ksp_preconditioner_type::jacobi);
02095         return;
02096     }
02097     if ( strcmp(kspPreconditioner, "bjacobi") == 0)
02098     {
02099         mpUserParameters->Numerical().KSPPreconditioner().set(cp::ksp_preconditioner_type::bjacobi);
02100         return;
02101     }
02102     if ( strcmp(kspPreconditioner, "hypre") == 0)
02103     {
02104         mpUserParameters->Numerical().KSPPreconditioner().set(cp::ksp_preconditioner_type::hypre);
02105         return;
02106     }
02107     if ( strcmp(kspPreconditioner, "ml") == 0)
02108     {
02109         mpUserParameters->Numerical().KSPPreconditioner().set(cp::ksp_preconditioner_type::ml);
02110         return;
02111     }
02112     if ( strcmp(kspPreconditioner, "spai") == 0)
02113     {
02114         mpUserParameters->Numerical().KSPPreconditioner().set(cp::ksp_preconditioner_type::spai);
02115         return;
02116     }
02117     if ( strcmp(kspPreconditioner, "blockdiagonal") == 0)
02118     {
02119         mpUserParameters->Numerical().KSPPreconditioner().set(cp::ksp_preconditioner_type::blockdiagonal);
02120         return;
02121     }
02122     if ( strcmp(kspPreconditioner, "ldufactorisation") == 0)
02123     {
02124         mpUserParameters->Numerical().KSPPreconditioner().set(cp::ksp_preconditioner_type::ldufactorisation);
02125         return;
02126     }
02127     if ( strcmp(kspPreconditioner, "none") == 0)
02128     {
02129         mpUserParameters->Numerical().KSPPreconditioner().set(cp::ksp_preconditioner_type::none);
02130         return;
02131     }
02132 
02133     EXCEPTION("Unknown preconditioner type provided");
02134 }
02135 
02136 void HeartConfig::SetAdaptivityParameters(double targetError,
02137                                           double sigma,
02138                                           double maxEdgeLength,
02139                                           double minEdgeLength,
02140                                           double gradation,
02141                                           unsigned maxNodes,
02142                                           unsigned numSweeps )
02143 {
02144     if ( maxEdgeLength < minEdgeLength )
02145     {
02146         EXCEPTION("AdaptivityParameters: maxEdgeLength must be greater than minEdgeLength.");
02147     }
02148     if (!IsAdaptivityParametersPresent())
02149     {
02150         cp::adaptivity_parameters_type element(targetError,
02151                                                sigma,
02152                                                maxEdgeLength,
02153                                                minEdgeLength,
02154                                                gradation,
02155                                                maxNodes,
02156                                                numSweeps );
02157         mpUserParameters->Numerical().AdaptivityParameters().set(element);
02158     }
02159     else
02160     {
02161         mpUserParameters->Numerical().AdaptivityParameters().get().target_error(targetError);
02162         mpUserParameters->Numerical().AdaptivityParameters().get().sigma(sigma);
02163         mpUserParameters->Numerical().AdaptivityParameters().get().max_edge_length(maxEdgeLength);
02164         mpUserParameters->Numerical().AdaptivityParameters().get().min_edge_length(minEdgeLength);
02165         mpUserParameters->Numerical().AdaptivityParameters().get().gradation(gradation);
02166         mpUserParameters->Numerical().AdaptivityParameters().get().max_nodes(maxNodes);
02167         mpUserParameters->Numerical().AdaptivityParameters().get().num_sweeps(numSweeps);
02168     }
02169 }
02170 
02171 void HeartConfig::SetTargetErrorForAdaptivity(double targetError)
02172 {
02173     SetAdaptivityParameters( targetError,
02174                              GetSigmaForAdaptivity(),
02175                              GetMaxEdgeLengthForAdaptivity(),
02176                              GetMinEdgeLengthForAdaptivity(),
02177                              GetGradationForAdaptivity(),
02178                              GetMaxNodesForAdaptivity(),
02179                              GetNumberOfAdaptiveSweeps() );
02180 }
02181 
02182 void HeartConfig::SetSigmaForAdaptivity(double sigma)
02183 {
02184     SetAdaptivityParameters( GetTargetErrorForAdaptivity(),
02185                              sigma,
02186                              GetMaxEdgeLengthForAdaptivity(),
02187                              GetMinEdgeLengthForAdaptivity(),
02188                              GetGradationForAdaptivity(),
02189                              GetMaxNodesForAdaptivity(),
02190                              GetNumberOfAdaptiveSweeps() );
02191 }
02192 
02193 void HeartConfig::SetMaxEdgeLengthForAdaptivity(double maxEdgeLength)
02194 {
02195     SetAdaptivityParameters( GetTargetErrorForAdaptivity(),
02196                              GetSigmaForAdaptivity(),
02197                              maxEdgeLength,
02198                              GetMinEdgeLengthForAdaptivity(),
02199                              GetGradationForAdaptivity(),
02200                              GetMaxNodesForAdaptivity(),
02201                              GetNumberOfAdaptiveSweeps() );
02202 }
02203 
02204 void HeartConfig::SetMinEdgeLengthForAdaptivity(double minEdgeLength)
02205 {
02206     SetAdaptivityParameters( GetTargetErrorForAdaptivity(),
02207                              GetSigmaForAdaptivity(),
02208                              GetMaxEdgeLengthForAdaptivity(),
02209                              minEdgeLength,
02210                              GetGradationForAdaptivity(),
02211                              GetMaxNodesForAdaptivity(),
02212                              GetNumberOfAdaptiveSweeps() );
02213 }
02214 
02215 void HeartConfig::SetGradationForAdaptivity(double gradation)
02216 {
02217     SetAdaptivityParameters( GetTargetErrorForAdaptivity(),
02218                              GetSigmaForAdaptivity(),
02219                              GetMaxEdgeLengthForAdaptivity(),
02220                              GetMinEdgeLengthForAdaptivity(),
02221                              gradation,
02222                              GetMaxNodesForAdaptivity(),
02223                              GetNumberOfAdaptiveSweeps() );
02224 }
02225 
02226 void HeartConfig::SetMaxNodesForAdaptivity(unsigned maxNodes)
02227 {
02228     SetAdaptivityParameters( GetTargetErrorForAdaptivity(),
02229                              GetSigmaForAdaptivity(),
02230                              GetMaxEdgeLengthForAdaptivity(),
02231                              GetMinEdgeLengthForAdaptivity(),
02232                              GetGradationForAdaptivity(),
02233                              maxNodes,
02234                              GetNumberOfAdaptiveSweeps() );
02235 }
02236 
02237 void HeartConfig::SetNumberOfAdaptiveSweeps(unsigned numSweeps)
02238 {
02239     SetAdaptivityParameters( GetTargetErrorForAdaptivity(),
02240                              GetSigmaForAdaptivity(),
02241                              GetMaxEdgeLengthForAdaptivity(),
02242                              GetMinEdgeLengthForAdaptivity(),
02243                              GetGradationForAdaptivity(),
02244                              GetMaxNodesForAdaptivity(),
02245                              numSweeps );
02246 }
02247 
02248 void HeartConfig::SetApdMaps(const std::vector<std::pair<double,double> >& apdMaps)
02249 {
02250     XSD_SEQUENCE_TYPE(cp::postprocessing_type::ActionPotentialDurationMap)& apd_maps_sequence
02251         = mpUserParameters->PostProcessing()->ActionPotentialDurationMap();
02252     //Erase or create a sequence
02253     apd_maps_sequence.clear();
02254 
02255     for (unsigned i=0; i<apdMaps.size(); i++)
02256     {
02257         XSD_CREATE_WITH_FIXED_ATTR2(cp::apd_map_type, temp,
02258                                     apdMaps[i].first, apdMaps[i].second,
02259                                     "mV");
02260         apd_maps_sequence.push_back( temp);
02261     }
02262 }
02263 
02264 
02265 void HeartConfig::SetUpstrokeTimeMaps (std::vector<double>& upstrokeTimeMaps)
02266 {
02267     XSD_SEQUENCE_TYPE(cp::postprocessing_type::UpstrokeTimeMap)& var_type_sequence
02268         = mpUserParameters->PostProcessing()->UpstrokeTimeMap();
02269 
02270     //Erase or create a sequence
02271     var_type_sequence.clear();
02272 
02273     for (unsigned i=0; i<upstrokeTimeMaps.size(); i++)
02274     {
02275         XSD_CREATE_WITH_FIXED_ATTR1(cp::upstrokes_map_type, temp,
02276                                     upstrokeTimeMaps[i],
02277                                     "mV");
02278         var_type_sequence.push_back(temp);
02279     }
02280 }
02281 
02282 void HeartConfig::SetMaxUpstrokeVelocityMaps (std::vector<double>& maxUpstrokeVelocityMaps)
02283 {
02284     XSD_SEQUENCE_TYPE(cp::postprocessing_type::MaxUpstrokeVelocityMap)& max_upstroke_velocity_maps_sequence
02285         = mpUserParameters->PostProcessing()->MaxUpstrokeVelocityMap();
02286 
02287     //Erase or create a sequence
02288     max_upstroke_velocity_maps_sequence.clear();
02289 
02290     for (unsigned i=0; i<maxUpstrokeVelocityMaps.size(); i++)
02291     {
02292         XSD_CREATE_WITH_FIXED_ATTR1(cp::max_upstrokes_velocity_map_type, temp,
02293                                     maxUpstrokeVelocityMaps[i],
02294                                     "mV");
02295 
02296 
02297         max_upstroke_velocity_maps_sequence.push_back(temp);
02298     }
02299 
02300 }
02301 
02302 void HeartConfig::SetConductionVelocityMaps (std::vector<unsigned>& conductionVelocityMaps)
02303 {
02304     XSD_SEQUENCE_TYPE(cp::postprocessing_type::ConductionVelocityMap)& conduction_velocity_maps_sequence
02305         = mpUserParameters->PostProcessing()->ConductionVelocityMap();
02306 
02307     //Erase or create a sequence
02308     conduction_velocity_maps_sequence.clear();
02309 
02310     for (unsigned i=0; i<conductionVelocityMaps.size(); i++)
02311     {
02312         cp::conduction_velocity_map_type temp(conductionVelocityMaps[i]);
02313         conduction_velocity_maps_sequence.push_back(temp);
02314     }
02315 }
02316 
02317 /*
02318  * Output visualizer
02319  */
02320 
02321 void HeartConfig::EnsureOutputVisualizerExists()
02322 {
02323     if (!IsOutputVisualizerPresent())
02324     {
02325         cp::output_visualizer_type element;
02326         mpUserParameters->Simulation().get().OutputVisualizer().set(element);
02327     }
02328 }
02329 
02330 void HeartConfig::SetVisualizeWithMeshalyzer(bool useMeshalyzer)
02331 {
02332     EnsureOutputVisualizerExists();
02333 
02334     mpUserParameters->Simulation().get().OutputVisualizer().get().meshalyzer(
02335         useMeshalyzer ? cp::yesno_type::yes : cp::yesno_type::no);
02336 }
02337 
02338 void HeartConfig::SetVisualizeWithCmgui(bool useCmgui)
02339 {
02340     EnsureOutputVisualizerExists();
02341 
02342     mpUserParameters->Simulation().get().OutputVisualizer().get().cmgui(
02343         useCmgui ? cp::yesno_type::yes : cp::yesno_type::no);
02344 }
02345 
02346 void HeartConfig::SetVisualizeWithVtk(bool useVtk)
02347 {
02348     EnsureOutputVisualizerExists();
02349 
02350     mpUserParameters->Simulation().get().OutputVisualizer().get().vtk(
02351         useVtk ? cp::yesno_type::yes : cp::yesno_type::no);
02352 }
02353 
02354 /**********************************************************************
02355  *                                                                    *
02356  *                                                                    *
02357  *                Utility methods for reading files                   *
02358  *                                                                    *
02359  *                                                                    *
02360  **********************************************************************/
02361 
02362 #include <string>
02363 #include <istream>
02364 #include <fstream>
02365 
02366 #include <xercesc/util/XMLUniDefs.hpp> // chLatin_*
02367 #include <xercesc/framework/Wrapper4InputSource.hpp>
02368 #include <xercesc/validators/common/Grammar.hpp>
02369 
02370 #include <xsd/cxx/xml/string.hxx>
02371 #include <xsd/cxx/xml/dom/auto-ptr.hxx>
02372 #include <xsd/cxx/xml/sax/std-input-source.hxx>
02373 #include <xsd/cxx/xml/dom/bits/error-handler-proxy.hxx>
02374 
02375 #include <xsd/cxx/tree/exceptions.hxx>
02376 #include <xsd/cxx/tree/error-handler.hxx>
02377 
02378 
02379 xsd::cxx::xml::dom::auto_ptr<xercesc::DOMDocument> HeartConfig::ReadFileToDomDocument(
02380         const std::string& rFileName,
02381         ::xml_schema::error_handler& rErrorHandler,
02382         const ::xml_schema::properties& rProps)
02383 {
02384     using namespace xercesc;
02385     namespace xml = xsd::cxx::xml;
02386     namespace tree = xsd::cxx::tree;
02387 
02388     // Get an implementation of the Load-Store (LS) interface.
02389     const XMLCh ls_id [] = {chLatin_L, chLatin_S, chNull};
02390     DOMImplementation* p_impl(DOMImplementationRegistry::getDOMImplementation(ls_id));
02391 
02392 #if _XERCES_VERSION >= 30000
02393     // Xerces-C++ 3.0.0 and later.
02394     xml::dom::auto_ptr<DOMLSParser> p_parser(p_impl->createLSParser(DOMImplementationLS::MODE_SYNCHRONOUS, 0));
02395     DOMConfiguration* p_conf(p_parser->getDomConfig());
02396 
02397     // Discard comment nodes in the document.
02398     p_conf->setParameter(XMLUni::fgDOMComments, false);
02399 
02400     // Enable datatype normalization.
02401     p_conf->setParameter(XMLUni::fgDOMDatatypeNormalization, true);
02402 
02403     // Do not create EntityReference nodes in the DOM tree.  No
02404     // EntityReference nodes will be created, only the nodes
02405     // corresponding to their fully expanded substitution text
02406     // will be created.
02407     p_conf->setParameter(XMLUni::fgDOMEntities, false);
02408 
02409     // Perform namespace processing.
02410     p_conf->setParameter(XMLUni::fgDOMNamespaces, true);
02411 
02412     // Do not include ignorable whitespace in the DOM tree.
02413     p_conf->setParameter(XMLUni::fgDOMElementContentWhitespace, false);
02414 
02415     // Enable validation.
02416     p_conf->setParameter(XMLUni::fgDOMValidate, true);
02417     p_conf->setParameter(XMLUni::fgXercesSchema, true);
02418     p_conf->setParameter(XMLUni::fgXercesSchemaFullChecking, false);
02419     // Code taken from xsd/cxx/xml/dom/parsing-source.txx
02420     if (!rProps.schema_location().empty())
02421     {
02422         xml::string locn(rProps.schema_location());
02423         const void* p_locn(locn.c_str());
02424         p_conf->setParameter(XMLUni::fgXercesSchemaExternalSchemaLocation,
02425                              const_cast<void*>(p_locn));
02426     }
02427     if (!rProps.no_namespace_schema_location().empty())
02428     {
02429         xml::string locn(rProps.no_namespace_schema_location());
02430         const void* p_locn(locn.c_str());
02431 
02432         p_conf->setParameter(XMLUni::fgXercesSchemaExternalNoNameSpaceSchemaLocation,
02433                              const_cast<void*>(p_locn));
02434     }
02435 
02436     // We will release the DOM document ourselves.
02437     p_conf->setParameter(XMLUni::fgXercesUserAdoptsDOMDocument, true);
02438 
02439     // Set error handler.
02440     xml::dom::bits::error_handler_proxy<char> ehp(rErrorHandler);
02441     p_conf->setParameter(XMLUni::fgDOMErrorHandler, &ehp);
02442 
02443 #else // _XERCES_VERSION >= 30000
02444     // Same as above but for Xerces-C++ 2 series.
02445     xml::dom::auto_ptr<DOMBuilder> p_parser(p_impl->createDOMBuilder(DOMImplementationLS::MODE_SYNCHRONOUS, 0));
02446 
02447     p_parser->setFeature(XMLUni::fgDOMComments, false);
02448     p_parser->setFeature(XMLUni::fgDOMDatatypeNormalization, true);
02449     p_parser->setFeature(XMLUni::fgDOMEntities, false);
02450     p_parser->setFeature(XMLUni::fgDOMNamespaces, true);
02451     p_parser->setFeature(XMLUni::fgDOMWhitespaceInElementContent, false);
02452     p_parser->setFeature(XMLUni::fgDOMValidation, true);
02453     p_parser->setFeature(XMLUni::fgXercesSchema, true);
02454     p_parser->setFeature(XMLUni::fgXercesSchemaFullChecking, false);
02455     p_parser->setFeature(XMLUni::fgXercesUserAdoptsDOMDocument, true);
02456 
02457     // Code taken from xsd/cxx/xml/dom/parsing-source.txx
02458     if (!rProps.schema_location().empty())
02459     {
02460         xml::string locn(rProps.schema_location());
02461         const void* p_locn(locn.c_str());
02462         p_parser->setProperty(XMLUni::fgXercesSchemaExternalSchemaLocation,
02463                               const_cast<void*>(p_locn));
02464     }
02465 
02466     if (!rProps.no_namespace_schema_location().empty())
02467     {
02468         xml::string locn(rProps.no_namespace_schema_location());
02469         const void* p_locn(locn.c_str());
02470 
02471         p_parser->setProperty(XMLUni::fgXercesSchemaExternalNoNameSpaceSchemaLocation,
02472                               const_cast<void*>(p_locn));
02473     }
02474 
02475     xml::dom::bits::error_handler_proxy<char> ehp(rErrorHandler);
02476     p_parser->setErrorHandler(&ehp);
02477 
02478 #endif // _XERCES_VERSION >= 30000
02479 
02480     // Do the parse
02481     xml::dom::auto_ptr<DOMDocument> p_doc(p_parser->parseURI(rFileName.c_str()));
02482 
02483     if (ehp.failed())
02484     {
02485         p_doc.reset();
02486     }
02487 
02488     return p_doc;
02489 }
02490 
02491 xercesc::DOMElement* HeartConfig::AddNamespace(xercesc::DOMDocument* pDocument,
02492                                                xercesc::DOMElement* pElement,
02493                                                const XMLCh* pNamespace)
02494 {
02495     using namespace xercesc;
02496 
02497     DOMElement* p_new_elt = static_cast<DOMElement*>(
02498         pDocument->renameNode(pElement, pNamespace, pElement->getLocalName()));
02499 
02500     for (DOMNode* p_node = p_new_elt->getFirstChild();
02501          p_node != NULL;
02502          p_node = p_node->getNextSibling())
02503     {
02504         if (p_node->getNodeType() == DOMNode::ELEMENT_NODE)
02505         {
02506             p_node = AddNamespace(pDocument, static_cast<DOMElement*>(p_node), pNamespace);
02507         }
02508     }
02509 
02510     return p_new_elt;
02511 }
02512 
02513 xercesc::DOMElement* HeartConfig::AddNamespace(xercesc::DOMDocument* pDocument,
02514                                                xercesc::DOMElement* pElement,
02515                                                const std::string& rNamespace)
02516 {
02517     return AddNamespace(pDocument, pElement, xsd::cxx::xml::string(rNamespace).c_str());
02518 }
02519 
02526 class XStr
02527 {
02528 public :
02533     XStr(const char* const toTranscode)
02534     {
02535         // Call the private transcoding method
02536         mUnicodeForm = xercesc::XMLString::transcode(toTranscode);
02537     }
02538 
02540     ~XStr()
02541     {
02542         xercesc::XMLString::release(&mUnicodeForm);
02543     }
02544 
02545 
02547     const XMLCh* UnicodeForm() const
02548     {
02549         return mUnicodeForm;
02550     }
02551 
02552 private :
02554     XMLCh* mUnicodeForm;
02555 };
02556 
02557 //#define X(str) XStr(str).UnicodeForm()
02558 #define X(str) xsd::cxx::xml::string(str).c_str()
02559 
02560 
02561 void HeartConfig::TransformIonicModelDefinitions(xercesc::DOMDocument* pDocument,
02562                                                  xercesc::DOMElement* pRootElement)
02563 {
02564     xercesc::DOMNodeList* p_sim_elt_list = pRootElement->getElementsByTagName(X("Simulation"));
02565     if (p_sim_elt_list->getLength() > 0)
02566     {
02567         xercesc::DOMElement* p_sim_elt = static_cast<xercesc::DOMElement*>(p_sim_elt_list->item(0));
02568         xercesc::DOMNodeList* p_ionic_models_elt_list = p_sim_elt->getElementsByTagName(X("IonicModels"));
02569         if (p_ionic_models_elt_list->getLength() > 0)
02570         {
02571             xercesc::DOMElement* p_ionic_models_elt = static_cast<xercesc::DOMElement*>(p_ionic_models_elt_list->item(0));
02572             // Do the default ionic model
02573             xercesc::DOMNodeList* p_default_list = p_ionic_models_elt->getElementsByTagName(X("Default"));
02574             assert(p_default_list->getLength() > 0); // Asserted by schema
02575             xercesc::DOMElement* p_default_elt = static_cast<xercesc::DOMElement*>(p_default_list->item(0));
02576             WrapContentInElement(pDocument, p_default_elt, X("Hardcoded"));
02577             // Now do any region-specific definitions
02578             xercesc::DOMNodeList* p_region_list = p_ionic_models_elt->getElementsByTagName(X("Region"));
02579             for (unsigned i=0; i<p_region_list->getLength(); i++)
02580             {
02581                 xercesc::DOMElement* p_region_elt = static_cast<xercesc::DOMElement*>(p_region_list->item(0));
02582                 xercesc::DOMNodeList* p_ionic_model_list = p_region_elt->getElementsByTagName(X("IonicModel"));
02583                 assert(p_ionic_model_list->getLength() > 0); // Asserted by schema
02584                 xercesc::DOMElement* p_ionic_model_elt = static_cast<xercesc::DOMElement*>(p_ionic_model_list->item(0));
02585                 WrapContentInElement(pDocument, p_ionic_model_elt, X("Hardcoded"));
02586             }
02587         }
02588     }
02589 }
02590 
02591 void HeartConfig::WrapContentInElement(xercesc::DOMDocument* pDocument,
02592                                        xercesc::DOMElement* pElement,
02593                                        const XMLCh* pNewElementLocalName)
02594 {
02595     const XMLCh* p_namespace_uri = pElement->getNamespaceURI();
02596     const XMLCh* p_prefix = pElement->getPrefix();
02597     const XMLCh* p_qualified_name;
02598     if (p_prefix)
02599     {
02600 #define COVERAGE_IGNORE
02601         // We can't actually cover this code, since previous versions of the parameters file didn't use a namespace,
02602         // so can't have a namespace prefix!
02603         xercesc::QName qname(p_prefix, pNewElementLocalName, 0);
02604         p_qualified_name = qname.getRawName();
02605 #undef COVERAGE_IGNORE
02606     }
02607     else
02608     {
02609         p_qualified_name = pNewElementLocalName;
02610     }
02611     xercesc::DOMElement* p_wrapper_elt = pDocument->createElementNS(p_namespace_uri, p_qualified_name);
02612     // Move all child nodes of pElement to be children of p_wrapper_elt
02613     xercesc::DOMNodeList* p_children = pElement->getChildNodes();
02614     for (unsigned i=0; i<p_children->getLength(); i++)
02615     {
02616         xercesc::DOMNode* p_child = pElement->removeChild(p_children->item(i));
02617         p_wrapper_elt->appendChild(p_child);
02618     }
02619     // Add the wrapper as the sole child of pElement
02620     pElement->appendChild(p_wrapper_elt);
02621 }
02622 
02624 // Explicit instantiation of the templated functions
02626 #define COVERAGE_IGNORE //These methods are covered above with DIM=1,2,3 but the instantiations may fail spuriously
02627 
02631 template void HeartConfig::GetIonicModelRegions<3u>(std::vector<ChasteCuboid<3u> >& , std::vector<cp::ionic_model_selection_type>&) const;
02632 template void HeartConfig::GetStimuli<3u>(std::vector<boost::shared_ptr<SimpleStimulus> >& , std::vector<ChasteCuboid<3u> >& ) const;
02633 template void HeartConfig::GetCellHeterogeneities<3u>(std::vector<AbstractChasteRegion<3u>* >& ,std::vector<double>& ,std::vector<double>& ,std::vector<double>& ) ;
02634 template void HeartConfig::GetConductivityHeterogeneities<3u>(std::vector<ChasteCuboid<3u> >& ,std::vector< c_vector<double,3> >& ,std::vector< c_vector<double,3> >& ) const;
02635 
02636 template void HeartConfig::GetIonicModelRegions<2u>(std::vector<ChasteCuboid<2u> >& , std::vector<cp::ionic_model_selection_type>&) const;
02637 template void HeartConfig::GetStimuli<2u>(std::vector<boost::shared_ptr<SimpleStimulus> >& , std::vector<ChasteCuboid<2u> >& ) const;
02638 template void HeartConfig::GetCellHeterogeneities<2u>(std::vector<AbstractChasteRegion<2u>* >& ,std::vector<double>& ,std::vector<double>& ,std::vector<double>& ) ;
02639 template void HeartConfig::GetConductivityHeterogeneities<2u>(std::vector<ChasteCuboid<2u> >& ,std::vector< c_vector<double,3> >& ,std::vector< c_vector<double,3> >& ) const;
02640 
02641 template void HeartConfig::GetIonicModelRegions<1u>(std::vector<ChasteCuboid<1u> >& , std::vector<cp::ionic_model_selection_type>&) const;
02642 template void HeartConfig::GetStimuli<1u>(std::vector<boost::shared_ptr<SimpleStimulus> >& , std::vector<ChasteCuboid<1u> >& ) const;
02643 template void HeartConfig::GetCellHeterogeneities<1u>(std::vector<AbstractChasteRegion<1u>* >& ,std::vector<double>& ,std::vector<double>& ,std::vector<double>& );
02644 template void HeartConfig::GetConductivityHeterogeneities<1u>(std::vector<ChasteCuboid<1u> >& ,std::vector< c_vector<double,3> >& ,std::vector< c_vector<double,3> >& ) const;
02649 #undef COVERAGE_IGNORE //These methods are covered above with DIM=1,2,3 but the instantiations may fail spuriously
02650 
02651 
02652 // Serialization for Boost >= 1.36
02653 #include "SerializationExportWrapperForCpp.hpp"
02654 CHASTE_CLASS_EXPORT(HeartConfig);

Generated by  doxygen 1.6.2