HeartConfig.cpp

00001 /*
00002 
00003 Copyright (C) University of Oxford, 2005-2009
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 
00030 #include "HeartConfig.hpp"
00031 using namespace xsd::cxx::tree;
00032 
00033 std::auto_ptr<HeartConfig> HeartConfig::mpInstance;
00034 
00035 HeartConfig* HeartConfig::Instance()
00036 {
00037     if (mpInstance.get() == NULL)
00038     {
00039         mpInstance.reset(new HeartConfig);
00040     }
00041     return mpInstance.get();
00042 }
00043 
00044 HeartConfig::HeartConfig()
00045 {
00046     assert(mpInstance.get() == NULL);
00047     mpDefaultParameters = NULL;
00048     mpUserParameters = NULL;
00049     mpDefaultParameters = ReadFile("ChasteDefaults.xml");
00050     mpUserParameters = mpDefaultParameters;
00051     //CheckTimeSteps(); // necessity of this line of code is not tested -- remove with caution!
00052 }
00053 
00054 HeartConfig::~HeartConfig()
00055 {
00056     if (mpUserParameters != mpDefaultParameters)
00057     {
00058         delete mpUserParameters;
00059     }
00060 
00061     delete mpDefaultParameters;    
00062 }
00063 
00064 void HeartConfig::SetDefaultsFile(std::string fileName)
00065 {
00066     bool same_target = (mpUserParameters == mpDefaultParameters);
00067     
00068     delete mpDefaultParameters;
00069     mpDefaultParameters = ReadFile(fileName);
00070 
00071     if (same_target)
00072     {
00073         mpUserParameters = mpDefaultParameters;
00074     }
00075     CheckTimeSteps();
00076 }
00077 
00078 void HeartConfig::Write(std::string dirName, std::string fileName)
00079 {
00080     //Output file
00081     OutputFileHandler output_file_handler(dirName, false);
00082     out_stream p_file = output_file_handler.OpenOutputFile(fileName);
00083 
00084     //Schema map
00085     //Note - this location is relative to where we are storing the xml
00086     xml_schema::namespace_infomap map;
00087     char buf[10000];
00088     std::string absolute_path_to_xsd=getcwd(buf, 10000);
00089     absolute_path_to_xsd += "/heart/src/io/ChasteParameters.xsd";
00090     map[""].schema = absolute_path_to_xsd;
00091     
00092     ChasteParameters(*p_file, *mpUserParameters, map);   
00093 }
00094 chaste_parameters_type* HeartConfig::ReadFile(std::string fileName)
00095 {
00096     // get the parameters using the method 'ChasteParameters(filename)',
00097     // which returns a std::auto_ptr. We don't want to use a std::auto_ptr because
00098     // it will delete memory when out of scope, or no longer point when it is copied,
00099     // so we reallocate memory using a normal pointer and copy the data to there
00100     try
00101     {
00102         std::auto_ptr<chaste_parameters_type> p_default(ChasteParameters(fileName));
00103         return new chaste_parameters_type(*p_default);
00104     }
00105     catch (const xml_schema::exception& e)
00106     {
00107          std::cerr << e << std::endl;
00108          //More clunky memory management
00109          mpUserParameters = NULL;
00110          mpDefaultParameters = NULL;
00111          EXCEPTION("XML parsing error in configuration file: " + fileName);
00112     }
00113 }
00114 
00115 void HeartConfig::SetParametersFile(std::string fileName)
00116 {
00117     // handles multiple calls to the method in the same context
00118     if (mpUserParameters != mpDefaultParameters)
00119     {        
00120         delete mpUserParameters;         
00121     }
00122     mpUserParameters = ReadFile(fileName);
00123 }
00124 
00125 chaste_parameters_type* HeartConfig::UserParameters()
00126 {
00127     return mpUserParameters;
00128 }
00129 
00130 chaste_parameters_type* HeartConfig::DefaultParameters()
00131 {
00132     return mpDefaultParameters;
00133 }
00134 
00135 void HeartConfig::Reset()
00136 {
00137     //Throw it away
00138     mpInstance.reset(0);
00139     //Make a new one
00140     mpInstance.reset(new HeartConfig);
00141 }
00142 
00143 template<class TYPE>
00144 TYPE* HeartConfig::DecideLocation(TYPE* ptr1, TYPE* ptr2, const std::string& nameParameter) const
00145 {
00146     if (ptr1->present())
00147     {
00148         return ptr1;
00149     }
00150     if (ptr2->present())
00151     {
00152         return ptr2;
00153     }
00154     EXCEPTION("No " + nameParameter + " provided (neither default nor user defined)");
00155 }
00156 
00157 unsigned HeartConfig::GetSpaceDimension() const
00158 {
00159     return DecideLocation( & mpUserParameters->Simulation().SpaceDimension(),
00160                            & mpDefaultParameters->Simulation().SpaceDimension(),
00161                            "SpaceDimension")->get();
00162 }
00163 
00164 double HeartConfig::GetSimulationDuration() const
00165 {
00166     return DecideLocation( & mpUserParameters->Simulation().SimulationDuration(),
00167                            & mpDefaultParameters->Simulation().SimulationDuration(),
00168                            "SimulationDuration")->get();
00169 }
00170 
00171 domain_type HeartConfig::GetDomain() const
00172 {
00173     return DecideLocation( & mpUserParameters->Simulation().Domain(),
00174                            & mpDefaultParameters->Simulation().Domain(),
00175                            "Domain")->get();
00176 }
00177 
00178 ionic_models_available_type HeartConfig::GetDefaultIonicModel() const
00179 {
00180     return DecideLocation( & mpUserParameters->Simulation().IonicModels(),
00181                            & mpDefaultParameters->Simulation().IonicModels(),
00182                            "IonicModel")->get().Default();
00183 }
00184 
00185 void HeartConfig::GetIonicModelRegions(std::vector<ChasteCuboid>& definedRegions,
00186                                        std::vector<ionic_models_available_type>& ionicModels) const
00187 {
00188     ionic_models_type::Region::container&
00189          regions = DecideLocation( & mpUserParameters->Simulation().IonicModels(),
00190                                    & mpDefaultParameters->Simulation().IonicModels(),
00191                                    "IonicModel")->get().Region();
00192 
00193     for (ionic_models_type::Region::iterator i = regions.begin();
00194          i != regions.end();
00195          ++i)
00196     {
00197         ionic_model_region_type ionic_model_region(*i);
00198         point_type point_a = ionic_model_region.Location().Cuboid().LowerCoordinates();
00199         point_type point_b = ionic_model_region.Location().Cuboid().UpperCoordinates();
00200 
00201         ChastePoint<3> chaste_point_a ( point_a.x(),
00202                                         point_a.y(),
00203                                         point_a.z());
00204 
00205         ChastePoint<3> chaste_point_b ( point_b.x(),
00206                                         point_b.y(),
00207                                         point_b.z());
00208         
00209         definedRegions.push_back(ChasteCuboid( chaste_point_a, chaste_point_b ));
00210         ionicModels.push_back(ionic_model_region.IonicModel());
00211     }
00212 }
00213 
00214 
00215 bool HeartConfig::GetIsMeshProvided() const
00216 {
00217     try
00218     {
00219         DecideLocation( & mpUserParameters->Simulation().Mesh(),
00220                         & mpDefaultParameters->Simulation().Mesh(),
00221                         "Mesh");                        
00222         return true;
00223     }
00224     catch (Exception& e)
00225     {            
00226         return false;
00227     }
00228 }    
00229 
00230 bool HeartConfig::GetCreateMesh() const
00231 {
00232     mesh_type mesh = DecideLocation( & mpUserParameters->Simulation().Mesh(),
00233                                      & mpDefaultParameters->Simulation().Mesh(),
00234                                      "Mesh")->get();
00235                                      
00236     return (mesh.Slab().present() || mesh.Sheet().present() || mesh.Fibre().present());
00237 }
00238 
00239 bool HeartConfig::GetCreateSlab() const
00240 {
00241     mesh_type mesh = DecideLocation( & mpUserParameters->Simulation().Mesh(),
00242                                      & mpDefaultParameters->Simulation().Mesh(),
00243                                      "Mesh")->get();
00244                                      
00245     return (mesh.Slab().present());
00246 }
00247 
00248 bool HeartConfig::GetCreateSheet() const
00249 {
00250     mesh_type mesh = DecideLocation( & mpUserParameters->Simulation().Mesh(),
00251                                      & mpDefaultParameters->Simulation().Mesh(),
00252                                      "Mesh")->get();
00253                                      
00254     return (mesh.Sheet().present());
00255 }
00256 
00257 bool HeartConfig::GetCreateFibre() const
00258 {
00259     mesh_type mesh = DecideLocation( & mpUserParameters->Simulation().Mesh(),
00260                                      & mpDefaultParameters->Simulation().Mesh(),
00261                                      "Mesh")->get();
00262                                      
00263     return (mesh.Fibre().present());
00264 }
00265 
00266 
00267 bool HeartConfig::GetLoadMesh() const
00268 {
00269     return (DecideLocation( & mpUserParameters->Simulation().Mesh(),
00270                             & mpDefaultParameters->Simulation().Mesh(),
00271                             "Mesh")->get().LoadMesh().present());
00272 }
00273  
00274 void HeartConfig::GetSlabDimensions(c_vector<double, 3>& slabDimensions) const
00275 {
00276     if (GetSpaceDimension()!=3 || !GetCreateSlab())
00277     {
00278         EXCEPTION("Tissue slabs can only be defined in 3D");
00279     }
00280     
00281     optional<slab_type, false> slab_dimensions = DecideLocation( & mpUserParameters->Simulation().Mesh(),
00282                                                                   & mpDefaultParameters->Simulation().Mesh(),
00283                                                                   "Slab")->get().Slab();
00284     
00285     slabDimensions[0] = slab_dimensions->x();
00286     slabDimensions[1] = slab_dimensions->y();
00287     slabDimensions[2] = slab_dimensions->z();
00288 }
00289 
00290 void HeartConfig::GetSheetDimensions(c_vector<double, 2>& sheetDimensions) const
00291 {
00292     if (GetSpaceDimension()!=2 || !GetCreateSheet())
00293     {
00294         EXCEPTION("Tissue sheets can only be defined in 2D");
00295     }
00296 
00297     optional<sheet_type, false> sheet_dimensions = DecideLocation( & mpUserParameters->Simulation().Mesh(),
00298                                                                   & mpDefaultParameters->Simulation().Mesh(),
00299                                                                   "Sheet")->get().Sheet();
00300     
00301     sheetDimensions[0] = sheet_dimensions->x();
00302     sheetDimensions[1] = sheet_dimensions->y();    
00303 }
00304 
00305 void HeartConfig::GetFibreLength(c_vector<double, 1>& fibreLength) const
00306 {
00307     if (GetSpaceDimension()!=1 || !GetCreateFibre())
00308     {
00309         EXCEPTION("Tissue fibres can only be defined in 1D");
00310     }
00311 
00312     optional<fibre_type, false> fibre_length = DecideLocation( & mpUserParameters->Simulation().Mesh(),
00313                                                                   & mpDefaultParameters->Simulation().Mesh(),
00314                                                                   "Fibre")->get().Fibre();
00315     
00316     fibreLength[0] = fibre_length->x();
00317 }    
00318 
00319 
00320 double HeartConfig::GetInterNodeSpace() const
00321 {
00322     assert(GetCreateMesh());
00323 
00324     switch(GetSpaceDimension())
00325     {
00326         case 3:
00327             return DecideLocation( & mpUserParameters->Simulation().Mesh(),
00328                                    & mpDefaultParameters->Simulation().Mesh(),
00329                                    "Slab")->get().Slab()->inter_node_space();
00330             break;                                  
00331         case 2:
00332             return DecideLocation( & mpUserParameters->Simulation().Mesh(),
00333                                    & mpDefaultParameters->Simulation().Mesh(),
00334                                    "Sheet")->get().Sheet()->inter_node_space();
00335             break;
00336         case 1:
00337             return DecideLocation( & mpUserParameters->Simulation().Mesh(),
00338                                    & mpDefaultParameters->Simulation().Mesh(),
00339                                    "Fibre")->get().Fibre()->inter_node_space();
00340             break;
00341         default:
00342             NEVER_REACHED;
00343     }
00344                                               
00345                                
00346 }
00347 
00348 std::string HeartConfig::GetMeshName() const
00349 {
00350     assert(GetLoadMesh());
00351     
00352     return DecideLocation( & mpUserParameters->Simulation().Mesh(),
00353                            & mpDefaultParameters->Simulation().Mesh(),
00354                            "LoadMesh")->get().LoadMesh()->name();
00355 }
00356 
00357 media_type HeartConfig::GetConductivityMedia() const
00358 {
00359     assert(GetLoadMesh());
00360 
00361     return DecideLocation( & mpUserParameters->Simulation().Mesh(),
00362                            & mpDefaultParameters->Simulation().Mesh(),
00363                            "LoadMesh")->get().LoadMesh()->conductivity_media();           
00364 }
00365 
00366 void HeartConfig::GetStimuli(std::vector<SimpleStimulus>& stimuliApplied, std::vector<ChasteCuboid>& stimulatedAreas) const
00367 {
00368 
00369     simulation_type::Stimuli::_xsd_Stimuli_::Stimuli::Stimulus::container&
00370          stimuli = DecideLocation( & mpUserParameters->Simulation().Stimuli(),
00371                            & mpDefaultParameters->Simulation().Stimuli(),
00372                            "Stimuli")->get().Stimulus();
00373     for (simulation_type::Stimuli::_xsd_Stimuli_::Stimuli::Stimulus::iterator i = stimuli.begin();
00374          i != stimuli.end();
00375          ++i)
00376     {
00377         stimulus_type stimulus(*i);
00378         point_type point_a = stimulus.Location().Cuboid().LowerCoordinates();
00379         point_type point_b = stimulus.Location().Cuboid().UpperCoordinates();
00380 
00381         ChastePoint<3> chaste_point_a ( point_a.x(),
00382                                         point_a.y(),
00383                                         point_a.z());
00384 
00385         ChastePoint<3> chaste_point_b ( point_b.x(),
00386                                         point_b.y(),
00387                                         point_b.z());
00388 
00389         stimuliApplied.push_back( SimpleStimulus(stimulus.Strength(), stimulus.Duration(), stimulus.Delay() ) );
00390         stimulatedAreas.push_back( ChasteCuboid( chaste_point_a, chaste_point_b ) );
00391     }
00392 }
00393 
00394 void HeartConfig::GetCellHeterogeneities(std::vector<ChasteCuboid>& cellHeterogeneityAreas,
00395                                          std::vector<double>& scaleFactorGks,
00396                                          std::vector<double>& scaleFactorIto,
00397                                          std::vector<double>& scaleFactorGkr) const
00398 {
00399     simulation_type::CellHeterogeneities::_xsd_CellHeterogeneities_::CellHeterogeneities::CellHeterogeneity::container&
00400          cell_heterogeneity = DecideLocation( & mpUserParameters->Simulation().CellHeterogeneities(),
00401                                                  & mpDefaultParameters->Simulation().CellHeterogeneities(),
00402                                                  "CellHeterogeneities")->get().CellHeterogeneity();
00403 
00404     for (simulation_type::CellHeterogeneities::_xsd_CellHeterogeneities_::CellHeterogeneities::CellHeterogeneity::iterator i = cell_heterogeneity.begin();
00405          i != cell_heterogeneity.end();
00406          ++i)
00407     {
00408         cell_heterogeneity_type ht(*i);
00409         point_type point_a = ht.Location().Cuboid().LowerCoordinates();
00410         point_type point_b = ht.Location().Cuboid().UpperCoordinates();
00411 
00412         ChastePoint<3> chaste_point_a (point_a.x(),
00413                                        point_a.y(),
00414                                        point_a.z());
00415 
00416         ChastePoint<3> chaste_point_b (point_b.x(),
00417                                        point_b.y(),
00418                                        point_b.z());
00419 
00420         scaleFactorGks.push_back (ht.ScaleFactorGks());
00421         scaleFactorIto.push_back (ht.ScaleFactorIto());
00422         scaleFactorGkr.push_back (ht.ScaleFactorGkr());
00423         cellHeterogeneityAreas.push_back( ChasteCuboid( chaste_point_a, chaste_point_b ) );
00424     }
00425 }
00426 
00427 bool HeartConfig::GetConductivityHeterogeneitiesProvided() const
00428 {
00429     try
00430     {
00431         DecideLocation( & mpUserParameters->Simulation().ConductivityHeterogeneities(),
00432                         & mpDefaultParameters->Simulation().ConductivityHeterogeneities(),
00433                         "CellHeterogeneities");                        
00434         return true;
00435     }
00436     catch (Exception& e)
00437     {            
00438         return false;
00439     }    
00440 }
00441 
00442 void HeartConfig::GetConductivityHeterogeneities(std::vector<ChasteCuboid>& conductivitiesHeterogeneityAreas,
00443                                                  std::vector< c_vector<double,3> >& intraConductivities,
00444                                                  std::vector< c_vector<double,3> >& extraConductivities) const
00445 {
00446     simulation_type::ConductivityHeterogeneities::_xsd_ConductivityHeterogeneities_::ConductivityHeterogeneities::ConductivityHeterogeneity::container&
00447          conductivity_heterogeneity = DecideLocation( & mpUserParameters->Simulation().ConductivityHeterogeneities(),
00448                                                          & mpDefaultParameters->Simulation().ConductivityHeterogeneities(),
00449                                                            "CellHeterogeneities")->get().ConductivityHeterogeneity();
00450 
00451     for (simulation_type::ConductivityHeterogeneities::_xsd_ConductivityHeterogeneities_::ConductivityHeterogeneities::ConductivityHeterogeneity::iterator i = conductivity_heterogeneity.begin();
00452          i != conductivity_heterogeneity.end();
00453          ++i)
00454     {
00455         conductivity_heterogeneity_type ht(*i);
00456         point_type point_a = ht.Location().Cuboid().LowerCoordinates();
00457         point_type point_b = ht.Location().Cuboid().UpperCoordinates();
00458 
00459         ChastePoint<3> chaste_point_a (point_a.x(),
00460                                        point_a.y(),
00461                                        point_a.z());
00462 
00463         ChastePoint<3> chaste_point_b (point_b.x(),
00464                                        point_b.y(),
00465                                        point_b.z());
00466 
00467         conductivitiesHeterogeneityAreas.push_back( ChasteCuboid( chaste_point_a, chaste_point_b ) );
00468 
00469         if (ht.IntracellularConductivities().present())
00470         {
00471             double intra_x = ht.IntracellularConductivities().get().longi();
00472             double intra_y = ht.IntracellularConductivities().get().trans();
00473             double intra_z = ht.IntracellularConductivities().get().normal();
00474 
00475             intraConductivities.push_back( Create_c_vector(intra_x, intra_y, intra_z) );
00476         }
00477         else
00478         {
00479             c_vector<double, 3> intra_conductivities;
00480             GetIntracellularConductivities(intra_conductivities);
00481             intraConductivities.push_back(intra_conductivities);
00482         }
00483 
00484         if (ht.ExtracellularConductivities().present())
00485         {
00486             double extra_x = ht.ExtracellularConductivities().get().longi();
00487             double extra_y = ht.ExtracellularConductivities().get().trans();
00488             double extra_z = ht.ExtracellularConductivities().get().normal();
00489 
00490             extraConductivities.push_back( Create_c_vector(extra_x, extra_y, extra_z) );
00491         }
00492         else
00493         {
00494             c_vector<double, 3> extra_conductivities;
00495             GetExtracellularConductivities(extra_conductivities);
00496             extraConductivities.push_back(extra_conductivities);
00497         }
00498 
00499     }
00500 }
00501 
00502 std::string HeartConfig::GetOutputDirectory() const
00503 {
00504     return DecideLocation( & mpUserParameters->Simulation().OutputDirectory(),
00505                            & mpDefaultParameters->Simulation().OutputDirectory(),
00506                            "OutputDirectory")->get();
00507 }
00508 
00509 std::string HeartConfig::GetOutputFilenamePrefix() const
00510 {
00511     return DecideLocation( & mpUserParameters->Simulation().OutputFilenamePrefix(),
00512                            & mpDefaultParameters->Simulation().OutputFilenamePrefix(),
00513                            "OutputFilenamePrefix")->get();    
00514 }
00515 
00516 void HeartConfig::GetIntracellularConductivities(c_vector<double, 3>& intraConductivities) const
00517 {
00518     optional<conductivities_type, false>* intra_conductivities  = DecideLocation( & mpUserParameters->Physiological().IntracellularConductivities(),
00519                                                                                   & mpDefaultParameters->Physiological().IntracellularConductivities(),
00520                                                                                   "IntracellularConductivities");
00521     double intra_x_cond = intra_conductivities->get().longi();
00522     double intra_y_cond = intra_conductivities->get().trans();
00523     double intra_z_cond = intra_conductivities->get().normal();;
00524 
00525     assert(intra_y_cond != DBL_MAX); 
00526     assert(intra_z_cond != DBL_MAX); 
00527 
00528     intraConductivities[0] = intra_x_cond;
00529     intraConductivities[1] = intra_y_cond;
00530     intraConductivities[2] = intra_z_cond;
00531 }
00532 
00533 void HeartConfig::GetIntracellularConductivities(c_vector<double, 2>& intraConductivities) const
00534 {
00535     optional<conductivities_type, false>* intra_conductivities  = DecideLocation( & mpUserParameters->Physiological().IntracellularConductivities(),
00536                                                                                   & mpDefaultParameters->Physiological().IntracellularConductivities(),
00537                                                                                   "IntracellularConductivities");
00538     double intra_x_cond = intra_conductivities->get().longi();
00539     double intra_y_cond = intra_conductivities->get().trans();
00540 
00541     assert(intra_y_cond != DBL_MAX);  
00542 
00543     intraConductivities[0] = intra_x_cond;
00544     intraConductivities[1] = intra_y_cond;
00545 }
00546 
00547 void HeartConfig::GetIntracellularConductivities(c_vector<double, 1>& intraConductivities) const
00548 {
00549     optional<conductivities_type, false>* intra_conductivities  = DecideLocation( & mpUserParameters->Physiological().IntracellularConductivities(),
00550                                                                                   & mpDefaultParameters->Physiological().IntracellularConductivities(),
00551                                                                                   "IntracellularConductivities");
00552     double intra_x_cond = intra_conductivities->get().longi();
00553 
00554     intraConductivities[0] = intra_x_cond;
00555 }
00556 
00557 void HeartConfig::GetExtracellularConductivities(c_vector<double, 3>& extraConductivities) const
00558 {
00559     optional<conductivities_type, false>* extra_conductivities  = DecideLocation( & mpUserParameters->Physiological().ExtracellularConductivities(),
00560                                                                                   & mpDefaultParameters->Physiological().ExtracellularConductivities(),
00561                                                                                   "ExtracellularConductivities");
00562     double extra_x_cond = extra_conductivities->get().longi();
00563     double extra_y_cond = extra_conductivities->get().trans();
00564     double extra_z_cond = extra_conductivities->get().normal();;
00565 
00566     assert(extra_y_cond != DBL_MAX); 
00567     assert(extra_z_cond != DBL_MAX); 
00568 
00569     extraConductivities[0] = extra_x_cond;
00570     extraConductivities[1] = extra_y_cond;
00571     extraConductivities[2] = extra_z_cond;
00572 }
00573 
00574 void HeartConfig::GetExtracellularConductivities(c_vector<double, 2>& extraConductivities) const
00575 {
00576     optional<conductivities_type, false>* extra_conductivities  = DecideLocation( & mpUserParameters->Physiological().ExtracellularConductivities(),
00577                                                                                   & mpDefaultParameters->Physiological().ExtracellularConductivities(),
00578                                                                                   "ExtracellularConductivities");
00579     double extra_x_cond = extra_conductivities->get().longi();
00580     double extra_y_cond = extra_conductivities->get().trans();
00581 
00582     assert(extra_y_cond != DBL_MAX);  
00583 
00584     extraConductivities[0] = extra_x_cond;
00585     extraConductivities[1] = extra_y_cond;
00586 }
00587 
00588 void HeartConfig::GetExtracellularConductivities(c_vector<double, 1>& extraConductivities) const
00589 {
00590     optional<conductivities_type, false>* extra_conductivities  = DecideLocation( & mpUserParameters->Physiological().ExtracellularConductivities(),
00591                                                                                   & mpDefaultParameters->Physiological().ExtracellularConductivities(),
00592                                                                                   "ExtracellularConductivities");
00593     double extra_x_cond = extra_conductivities->get().longi();
00594 
00595     extraConductivities[0] = extra_x_cond;
00596 }
00597 
00598 double HeartConfig::GetBathConductivity() const
00599 {
00600     /*bath conductivity mS/cm*/
00601     return DecideLocation( & mpUserParameters->Physiological().BathConductivity(),
00602                            & mpDefaultParameters->Physiological().BathConductivity(),
00603                            "BathConductivity")->get();
00604 }
00605 
00606 double HeartConfig::GetSurfaceAreaToVolumeRatio() const
00607 {
00608     /*surface area to volume ratio: 1/cm*/
00609     return DecideLocation( & mpUserParameters->Physiological().SurfaceAreaToVolumeRatio(),
00610                            & mpDefaultParameters->Physiological().SurfaceAreaToVolumeRatio(),
00611                            "SurfaceAreaToVolumeRatio")->get();
00612 }
00613 
00614 double HeartConfig::GetCapacitance() const
00615 {
00616     //         capacitance                 : uF/cm^2
00617     return DecideLocation( & mpUserParameters->Physiological().Capacitance(),
00618                            & mpDefaultParameters->Physiological().Capacitance(),
00619                            "Capacitance")->get();
00620 }
00621 
00622 double HeartConfig::GetOdeTimeStep() const
00623 {
00624     return DecideLocation( & mpUserParameters->Numerical().TimeSteps(),
00625                            & mpDefaultParameters->Numerical().TimeSteps(),
00626                            "ode TimeStep")->get().ode();
00627 }
00628 
00629 double HeartConfig::GetPdeTimeStep() const
00630 {
00631     return DecideLocation( & mpUserParameters->Numerical().TimeSteps(),
00632                            & mpDefaultParameters->Numerical().TimeSteps(),
00633                            "pde TimeStep")->get().pde();
00634 }
00635 
00636 double HeartConfig::GetPrintingTimeStep() const
00637 {
00638     return DecideLocation( & mpUserParameters->Numerical().TimeSteps(),
00639                            & mpDefaultParameters->Numerical().TimeSteps(),
00640                            "printing TimeStep")->get().printing();
00641 }
00642 
00643 bool HeartConfig::GetUseAbsoluteTolerance() const
00644 {
00645      /*
00646       * Note that it may be the case that absolute tolerance exists in the default
00647       * parameters file, but has been overridden in the user parameters
00648       */
00649      if (mpUserParameters->Numerical().KSPTolerances().get().KSPRelative().present() )
00650      {
00651         return false;
00652      }
00653 
00654      return DecideLocation( & mpUserParameters->Numerical().KSPTolerances(),
00655                                              & mpDefaultParameters->Numerical().KSPTolerances(),
00656                                              "KSPTolerances")->get().KSPAbsolute().present();
00657 }
00658 
00659 double HeartConfig::GetAbsoluteTolerance() const
00660 {
00661     if (!GetUseAbsoluteTolerance())
00662     {
00663         EXCEPTION("Absolute tolerance is not set in Chaste parameters");
00664     }    
00665     return DecideLocation( & mpUserParameters->Numerical().KSPTolerances(),
00666                            & mpDefaultParameters->Numerical().KSPTolerances(),
00667                            "KSPTolerances")->get().KSPAbsolute().get();
00668 }
00669 
00670 bool HeartConfig::GetUseRelativeTolerance() const
00671 {
00672     /*
00673       * Note that it may be the case that relative tolerance exists in the default
00674       * parameters file, but has been overridden in the user parameters
00675       */
00676      
00677      
00678      if (mpUserParameters->Numerical().KSPTolerances().get().KSPAbsolute().present() )
00679      {
00680         return false;
00681      }
00682      return DecideLocation( & mpUserParameters->Numerical().KSPTolerances(),
00683                                              & mpDefaultParameters->Numerical().KSPTolerances(),
00684                                              "KSPTolerances")->get().KSPRelative().present();
00685 }
00686 
00687 double HeartConfig::GetRelativeTolerance() const
00688 {
00689     if (!GetUseRelativeTolerance())
00690     {
00691         EXCEPTION("Relative tolerance is not set in Chaste parameters");
00692     }   
00693     
00694     return DecideLocation( & mpUserParameters->Numerical().KSPTolerances(),
00695                            & mpDefaultParameters->Numerical().KSPTolerances(),
00696                            "KSPTolerances")->get().KSPRelative().get();
00697 }
00698 
00699 const char* HeartConfig::GetKSPSolver() const
00700 {
00701     switch ( DecideLocation( & mpUserParameters->Numerical().KSPSolver(),
00702                              & mpDefaultParameters->Numerical().KSPSolver(),
00703                             "KSPSolver")->get() )
00704     {
00705         case ksp_solver_type::gmres :
00706             return "gmres";
00707         case ksp_solver_type::cg :
00708             return "cg";
00709         case ksp_solver_type::symmlq :
00710             return "symmlq";
00711     }
00712 #define COVERAGE_IGNORE
00713     EXCEPTION("Unknown ksp solver");
00714 #undef COVERAGE_IGNORE
00715 }
00716 
00717 const char* HeartConfig::GetKSPPreconditioner() const
00718 {
00719     switch ( DecideLocation( & mpUserParameters->Numerical().KSPPreconditioner(),
00720                              & mpDefaultParameters->Numerical().KSPPreconditioner(),
00721                              "KSPPreconditioner")->get() )
00722     {
00723         case ksp_preconditioner_type::ilu :
00724             return "ilu";
00725         case ksp_preconditioner_type::jacobi :
00726             return "jacobi";
00727         case ksp_preconditioner_type::bjacobi :
00728             return "bjacobi";
00729         case ksp_preconditioner_type::hypre :
00730             return "hypre";
00731         case ksp_preconditioner_type::none :
00732             return "none";
00733         
00734     }
00735 #define COVERAGE_IGNORE
00736     EXCEPTION("Unknown ksp preconditioner");
00737 #undef COVERAGE_IGNORE
00738 }
00739 
00740 
00741 /*
00742  *  Set methods
00743  */
00744 void HeartConfig::SetSpaceDimension(unsigned spaceDimension)
00745 {
00746     mpUserParameters->Simulation().SpaceDimension().set(spaceDimension);    
00747 }
00748 
00749 void HeartConfig::SetSimulationDuration(double simulationDuration)
00750 {
00751     time_type time(simulationDuration, "ms");
00752     mpUserParameters->Simulation().SimulationDuration().set(time);
00753 }
00754 
00755 void HeartConfig::SetDomain(domain_type domain)
00756 {
00757     mpUserParameters->Simulation().Domain().set(domain);
00758 }
00759 
00760 void HeartConfig::SetDefaultIonicModel(ionic_models_available_type ionicModel)
00761 {
00762     mpUserParameters->Simulation().IonicModels().set(ionicModel);
00763 }
00764 
00765 void HeartConfig::SetSlabDimensions(double x, double y, double z, double inter_node_space)
00766 {
00767     if ( ! mpUserParameters->Simulation().Mesh().present())
00768     {
00769         mesh_type mesh_to_load("cm");
00770         mpUserParameters->Simulation().Mesh().set(mesh_to_load);
00771     }
00772 
00773     slab_type slab_definition(x, y, z, inter_node_space);    
00774     mpUserParameters->Simulation().Mesh().get().Slab().set(slab_definition);        
00775 }
00776 
00777 void HeartConfig::SetSheetDimensions(double x, double y, double inter_node_space)
00778 {
00779     if ( ! mpUserParameters->Simulation().Mesh().present())
00780     {
00781         mesh_type mesh_to_load("cm");
00782         mpUserParameters->Simulation().Mesh().set(mesh_to_load);
00783     }
00784 
00785     sheet_type sheet_definition(x, y, inter_node_space);    
00786     mpUserParameters->Simulation().Mesh().get().Sheet().set(sheet_definition);        
00787 }
00788 
00789 void HeartConfig::SetFibreLength(double x, double inter_node_space)
00790 {
00791     if ( ! mpUserParameters->Simulation().Mesh().present())
00792     {
00793         mesh_type mesh_to_load("cm");
00794         mpUserParameters->Simulation().Mesh().set(mesh_to_load);
00795     }
00796 
00797     fibre_type fibre_definition(x, inter_node_space);    
00798     mpUserParameters->Simulation().Mesh().get().Fibre().set(fibre_definition);    
00799 }
00800 
00801 void HeartConfig::SetMeshFileName(std::string meshPrefix, media_type fibreDefinition)
00802 {
00803     if ( ! mpUserParameters->Simulation().Mesh().present())
00804     {
00805         mesh_type mesh_to_load("cm");
00806         mpUserParameters->Simulation().Mesh().set(mesh_to_load);
00807     }
00808     
00809     mesh_type::LoadMesh::type mesh_prefix(meshPrefix, fibreDefinition);    
00810     mpUserParameters->Simulation().Mesh().get().LoadMesh().set(mesh_prefix);
00811 }
00812 
00813 void  HeartConfig::SetConductivityHeterogeneities(std::vector< c_vector<double,3> >& cornerA,
00814                                                    std::vector< c_vector<double,3> >& cornerB,
00815                                                      std::vector< c_vector<double,3> >& intraConductivities,
00816                                                   std::vector< c_vector<double,3> >& extraConductivities)
00817 {
00818     assert ( cornerA.size() == cornerB.size() );    
00819     assert ( cornerB.size() == intraConductivities.size() );    
00820     assert ( intraConductivities.size() == extraConductivities.size());    
00821 
00822     simulation_type::ConductivityHeterogeneities::_xsd_ConductivityHeterogeneities_::ConductivityHeterogeneities::ConductivityHeterogeneity::container heterogeneities_container;
00823 
00824     for (unsigned region_index=0; region_index<cornerA.size(); region_index++) 
00825     {
00826         point_type point_a(cornerA[region_index][0],
00827                            cornerA[region_index][1],
00828                            cornerA[region_index][2]);
00829 
00830         point_type point_b(cornerB[region_index][0],
00831                            cornerB[region_index][1],
00832                            cornerB[region_index][2]);
00833         
00834         conductivity_heterogeneity_type ht(location_type(box_type(point_a, point_b), "cm"));
00835         
00836         conductivities_type intra(intraConductivities[region_index][0],
00837                                   intraConductivities[region_index][1],
00838                                   intraConductivities[region_index][2],
00839                                   "mS/cm");
00840         
00841         ht.IntracellularConductivities(intra);
00842 
00843         conductivities_type extra(extraConductivities[region_index][0],
00844                                   extraConductivities[region_index][1],
00845                                   extraConductivities[region_index][2],
00846                                   "mS/cm");
00847         
00848         ht.ExtracellularConductivities(extra);
00849         
00850         heterogeneities_container.push_back(ht);        
00851     }
00852     
00853     simulation_type::ConductivityHeterogeneities::_xsd_ConductivityHeterogeneities_::ConductivityHeterogeneities heterogeneities_object;    
00854     heterogeneities_object.ConductivityHeterogeneity(heterogeneities_container);
00855 
00856     mpUserParameters->Simulation().ConductivityHeterogeneities().set(heterogeneities_object);        
00857 }
00858 
00859 
00860 void HeartConfig::SetOutputDirectory(std::string outputDirectory)
00861 {
00862     mpUserParameters->Simulation().OutputDirectory().set(outputDirectory);
00863 }
00864 
00865 void HeartConfig::SetOutputFilenamePrefix(std::string outputFilenamePrefix)
00866 {
00867     mpUserParameters->Simulation().OutputFilenamePrefix().set(outputFilenamePrefix);
00868 }
00869 
00870 
00871 // Physiological
00872 void HeartConfig::SetIntracellularConductivities(const c_vector<double, 3>& intraConductivities)
00873 {
00874     conductivities_type intra(intraConductivities[0],
00875                               intraConductivities[1],
00876                               intraConductivities[2],
00877                               "mS/cm");
00878 
00879     mpUserParameters->Physiological().IntracellularConductivities().set(intra);
00880 }
00881 
00882 void HeartConfig::SetIntracellularConductivities(const c_vector<double, 2>& intraConductivities)
00883 {
00884     conductivities_type intra(intraConductivities[0],
00885                               intraConductivities[1],
00886                               DBL_MAX,
00887                               "mS/cm");
00888 
00889     mpUserParameters->Physiological().IntracellularConductivities().set(intra);
00890 }
00891 
00892 void HeartConfig::SetIntracellularConductivities(const c_vector<double, 1>& intraConductivities)
00893 {
00894     conductivities_type intra(intraConductivities[0],
00895                               DBL_MAX,
00896                               DBL_MAX,
00897                               "mS/cm");
00898 
00899     mpUserParameters->Physiological().IntracellularConductivities().set(intra);
00900 }
00901 
00902 void HeartConfig::SetExtracellularConductivities(const c_vector<double, 3>& extraConductivities)
00903 {
00904     conductivities_type extra(extraConductivities[0],
00905                               extraConductivities[1],
00906                               extraConductivities[2],
00907                               "mS/cm");
00908 
00909     mpUserParameters->Physiological().ExtracellularConductivities().set(extra);
00910 }
00911 
00912 void HeartConfig::SetExtracellularConductivities(const c_vector<double, 2>& extraConductivities)
00913 {
00914     conductivities_type extra(extraConductivities[0],
00915                               extraConductivities[1],
00916                               DBL_MAX,
00917                               "mS/cm");
00918 
00919     mpUserParameters->Physiological().ExtracellularConductivities().set(extra);
00920 }
00921 
00922 void HeartConfig::SetExtracellularConductivities(const c_vector<double, 1>& extraConductivities)
00923 {
00924     conductivities_type extra(extraConductivities[0],
00925                               DBL_MAX,
00926                               DBL_MAX,
00927                               "mS/cm");
00928 
00929     mpUserParameters->Physiological().ExtracellularConductivities().set(extra);
00930 }
00931 
00932 void HeartConfig::SetBathConductivity(double bathConductivity)
00933 {
00934     conductivity_type cond(bathConductivity, "mS/cm");
00935     mpUserParameters->Physiological().BathConductivity().set(cond);
00936 }
00937 
00938 void HeartConfig::SetSurfaceAreaToVolumeRatio(double ratio)
00939 {
00940     inverse_length_type ratio_object(ratio, "1/cm");
00941     mpUserParameters->Physiological().SurfaceAreaToVolumeRatio().set(ratio_object);
00942 }
00943 
00944 void HeartConfig::SetCapacitance(double capacitance)
00945 {
00946     capacitance_type capacitance_object(capacitance, "uF/cm^2");
00947     mpUserParameters->Physiological().Capacitance().set(capacitance_object);
00948 }
00949 
00950 
00951 // Numerical
00952 void HeartConfig::SetOdePdeAndPrintingTimeSteps(double odeTimeStep, double pdeTimeStep, double printingTimeStep)
00953 {
00954     time_steps_type TimeSteps(odeTimeStep, pdeTimeStep, printingTimeStep, "ms");
00955     mpUserParameters->Numerical().TimeSteps().set(TimeSteps);
00956     CheckTimeSteps();
00957 }
00958 
00959 void HeartConfig::SetOdeTimeStep(double odeTimeStep)
00960 {
00961     SetOdePdeAndPrintingTimeSteps(odeTimeStep, GetPdeTimeStep(), GetPrintingTimeStep());
00962 }
00963 
00964 void HeartConfig::SetPdeTimeStep(double pdeTimeStep)
00965 {
00966     SetOdePdeAndPrintingTimeSteps(GetOdeTimeStep(), pdeTimeStep, GetPrintingTimeStep());
00967 }
00968 
00969 void HeartConfig::SetPrintingTimeStep(double printingTimeStep)
00970 {
00971     SetOdePdeAndPrintingTimeSteps(GetOdeTimeStep(), GetPdeTimeStep(), printingTimeStep);
00972 }
00973 
00974 void HeartConfig::CheckTimeSteps() const
00975 {
00976     if (GetOdeTimeStep() <= 0)
00977     {
00978         EXCEPTION("Ode time-step should be positive");
00979     }
00980     if (GetPdeTimeStep() <= 0)
00981     {
00982         EXCEPTION("Pde time-step should be positive");
00983     }
00984     if (GetPrintingTimeStep() <= 0.0)
00985     {
00986         EXCEPTION("Printing time-step should be positive");
00987     }
00988     if (GetPdeTimeStep()>GetPrintingTimeStep())
00989     {
00990         EXCEPTION("Printing time-step should not be smaller than PDE time step");
00991     }
00992 
00993     //If pde divides printing then the floating remainder ought to be close to
00994     //zero(+a smidge) or pde-a smidge
00995     double remainder=fmod(GetPrintingTimeStep(), GetPdeTimeStep());
00996 
00997     if ( remainder > DBL_EPSILON && remainder < GetPdeTimeStep()-DBL_EPSILON)
00998     {
00999         EXCEPTION("Printing time-step should a multiple of PDE time step");
01000     }
01001     
01002     if ( GetOdeTimeStep() > GetPdeTimeStep() )
01003     {
01004         EXCEPTION("Ode time-step should not be greater than pde time-step");
01005     }
01006 }
01007 
01008 
01009 void HeartConfig::SetUseRelativeTolerance(double relativeTolerance)
01010 {
01011     //Remove any reference to tolerances is user parameters
01012     mpUserParameters->Numerical().KSPTolerances().get().KSPAbsolute().reset();
01013     mpUserParameters->Numerical().KSPTolerances().get().KSPRelative().set(relativeTolerance);
01014 }
01015 
01016 void HeartConfig::SetUseAbsoluteTolerance(double absoluteTolerance)
01017 {
01018     //Remove any reference to tolerances is user parameters
01019     mpUserParameters->Numerical().KSPTolerances().get().KSPRelative().reset();
01020     mpUserParameters->Numerical().KSPTolerances().get().KSPAbsolute().set(absoluteTolerance);
01021 }
01022 
01023 void HeartConfig::SetKSPSolver(const char* kspSolver)
01024 {
01025     if ( strcmp(kspSolver, "gmres") == 0)
01026     {
01027         mpUserParameters->Numerical().KSPSolver().set(ksp_solver_type::gmres);
01028         return;
01029     }
01030     if ( strcmp(kspSolver, "cg") == 0)
01031     {
01032         mpUserParameters->Numerical().KSPSolver().set(ksp_solver_type::cg);
01033         return;
01034     }
01035     if ( strcmp(kspSolver, "symmlq") == 0)
01036     {
01037         mpUserParameters->Numerical().KSPSolver().set(ksp_solver_type::symmlq);
01038         return;
01039     }
01040     
01041     EXCEPTION("Unknown solver type provided");
01042 }
01043 
01044 void HeartConfig::SetKSPPreconditioner(const char* kspPreconditioner)
01045 {
01046     if ( strcmp(kspPreconditioner, "ilu") == 0)
01047     {
01048         mpUserParameters->Numerical().KSPPreconditioner().set(ksp_preconditioner_type::ilu);
01049         return;
01050     }
01051     if ( strcmp(kspPreconditioner, "jacobi") == 0)
01052     {
01053         mpUserParameters->Numerical().KSPPreconditioner().set(ksp_preconditioner_type::jacobi);
01054         return;
01055     }
01056     if ( strcmp(kspPreconditioner, "bjacobi") == 0)
01057     {
01058         mpUserParameters->Numerical().KSPPreconditioner().set(ksp_preconditioner_type::bjacobi);
01059         return;
01060     }
01061     if ( strcmp(kspPreconditioner, "hypre") == 0)
01062     {
01063         mpUserParameters->Numerical().KSPPreconditioner().set(ksp_preconditioner_type::hypre);
01064         return;
01065     }
01066     if ( strcmp(kspPreconditioner, "none") == 0)
01067     {
01068         mpUserParameters->Numerical().KSPPreconditioner().set(ksp_preconditioner_type::none);
01069         return;
01070     }
01071     
01072     EXCEPTION("Unknown preconditioner type provided");
01073 }

Generated on Wed Mar 18 12:51:52 2009 for Chaste by  doxygen 1.5.5