AbstractPurkinjeCellFactory.cpp

00001 /*
00002 
00003 Copyright (c) 2005-2015, University of Oxford.
00004 All rights reserved.
00005 
00006 University of Oxford means the Chancellor, Masters and Scholars of the
00007 University of Oxford, having an administrative office at Wellington
00008 Square, Oxford OX1 2JD, UK.
00009 
00010 This file is part of Chaste.
00011 
00012 Redistribution and use in source and binary forms, with or without
00013 modification, are permitted provided that the following conditions are met:
00014  * Redistributions of source code must retain the above copyright notice,
00015    this list of conditions and the following disclaimer.
00016  * Redistributions in binary form must reproduce the above copyright notice,
00017    this list of conditions and the following disclaimer in the documentation
00018    and/or other materials provided with the distribution.
00019  * Neither the name of the University of Oxford nor the names of its
00020    contributors may be used to endorse or promote products derived from this
00021    software without specific prior written permission.
00022 
00023 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00024 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00025 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00026 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
00027 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00028 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
00029 GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00030 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00031 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
00032 OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00033 
00034 */
00035 
00036 
00037 #include "AbstractPurkinjeCellFactory.hpp"
00038 #include "PurkinjeVentricularJunctionStimulus.hpp"
00039 #include "MultiStimulus.hpp"
00040 #include "HeartConfig.hpp"
00041 #include "Warnings.hpp"
00042 
00043 
00044 
00045 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00046 AbstractPurkinjeCellFactory<ELEMENT_DIM,SPACE_DIM>::AbstractPurkinjeCellFactory()
00047     : AbstractCardiacCellFactory<ELEMENT_DIM,SPACE_DIM>(),
00048       mpMixedDimensionMesh(NULL)
00049 {
00050 }
00051 
00052 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00053 void AbstractPurkinjeCellFactory<ELEMENT_DIM,SPACE_DIM>::ReadJunctionsFile()
00054 {
00055     std::string pvj_file_name;
00056     bool file_specified = true;
00057 
00058     try
00059     {
00060         // HeartConfig::Instance()->GetMeshName() will throw an exception if no mesh name is defined
00061         pvj_file_name = HeartConfig::Instance()->GetMeshName() + ".pvj";
00062     }
00063     catch(Exception&)
00064     {
00065         file_specified = false;
00066     }
00067 
00068     FileFinder junction_file(pvj_file_name, RelativeTo::AbsoluteOrCwd);
00069     if (!file_specified || !junction_file.Exists() )
00070     {
00071         // In this case we expect the user to specify PVJ programmatically, so return immediately.
00072         WARNING("No Purkinje-Ventricular junction (.pvj) file found. Junctions must be specified manually.");
00073         return;
00074     }
00075 
00076     std::ifstream junction_stream(junction_file.GetAbsolutePath().c_str());
00077 
00078     if(!junction_stream.good())
00079     {   // file couldn't be opened
00080         EXCEPTION("Couldn't open data file: " << junction_file.GetAbsolutePath());
00081     }
00082 
00083     // Reads in file defining nodes and resistance (separated by space)
00084     while(junction_stream.good())
00085     {
00086         std::string this_line;
00087         getline(junction_stream, this_line);
00088 
00089         if (this_line=="" || this_line=="\r")
00090         {
00091             if (junction_stream.eof())
00092             {   // If the blank line is the last line carry on OK.
00093                 break;
00094             }
00095             else
00096             {
00097                 EXCEPTION("No data found on line in file: " << junction_file.GetAbsolutePath());
00098             }
00099         }
00100         std::stringstream line(this_line);
00101 
00102         unsigned node_id;
00103         line >> node_id;
00104         double resistance;
00105         line >> resistance;
00106 
00107         if(mpMixedDimensionMesh->rGetNodePermutation().size() != 0) //Do we have a permuted mesh?
00108         {
00109             unsigned mapped_node_id = mpMixedDimensionMesh->rGetNodePermutation()[node_id];
00110 
00111             mJunctionMap[mapped_node_id] = resistance;
00112         }
00113         else
00114         {
00115             mJunctionMap[node_id] = resistance;
00116         }
00117     }
00118 }
00119 
00120 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00121 void AbstractPurkinjeCellFactory<ELEMENT_DIM,SPACE_DIM>::CreateJunction(const Node<SPACE_DIM>* pNode,
00122                                                                         AbstractCardiacCellInterface* pPurkinjeCell,
00123                                                                         AbstractCardiacCellInterface* pCardiacCell,
00124                                                                         double resistance)
00125 {
00126     // Figure out the effective resistance for this mesh, in kOhm.cm^3
00127     if (pNode) // Should always be provided apart from low-level tests!
00128     {
00129         assert(mpMixedDimensionMesh);
00130         typedef typename MixedDimensionMesh<ELEMENT_DIM,SPACE_DIM>::CableRangeAtNode CableRangeAtNode;
00131         CableRangeAtNode cable_range = mpMixedDimensionMesh->GetCablesAtNode(pNode);
00132         double total_cross_sectional_area = 0.0;
00133         for (typename MixedDimensionMesh<ELEMENT_DIM,SPACE_DIM>::NodeCableIterator iter=cable_range.first;
00134              iter != cable_range.second;
00135              ++iter)
00136         {
00137             Element<1u,SPACE_DIM>* p_cable = iter->second;
00138             double cable_radius = p_cable->GetAttribute();
00139             total_cross_sectional_area += M_PI*cable_radius*cable_radius;
00140         }
00141         resistance *= total_cross_sectional_area / HeartConfig::Instance()->GetPurkinjeSurfaceAreaToVolumeRatio();
00142     }
00143     // Create the junction stimuli, and associate them with the cells
00144     boost::shared_ptr<PurkinjeVentricularJunctionStimulus> p_pvj_ventricular_stim(new PurkinjeVentricularJunctionStimulus(resistance));
00145     boost::shared_ptr<PurkinjeVentricularJunctionStimulus> p_pvj_purkinje_stim(new PurkinjeVentricularJunctionStimulus(resistance));
00146     p_pvj_purkinje_stim->SetAppliedToPurkinjeCellModel();
00147     p_pvj_ventricular_stim->SetVentricularCellModel(pCardiacCell);
00148     p_pvj_ventricular_stim->SetPurkinjeCellModel(pPurkinjeCell);
00149     p_pvj_purkinje_stim->SetVentricularCellModel(pCardiacCell);
00150     p_pvj_purkinje_stim->SetPurkinjeCellModel(pPurkinjeCell);
00151 
00152     // Create new combined stimuli which add the junction stimuli to those already in the cells
00153     boost::shared_ptr<MultiStimulus> p_multi_stim_ventricular(new MultiStimulus);
00154     p_multi_stim_ventricular->AddStimulus(p_pvj_ventricular_stim);
00155     p_multi_stim_ventricular->AddStimulus(pCardiacCell->GetStimulusFunction());
00156     pCardiacCell->SetStimulusFunction(p_multi_stim_ventricular);
00157 
00158     boost::shared_ptr<MultiStimulus> p_multi_stim_purkinje(new MultiStimulus);
00159     p_multi_stim_purkinje->AddStimulus(p_pvj_purkinje_stim);
00160     p_multi_stim_purkinje->AddStimulus(pPurkinjeCell->GetStimulusFunction());
00161     pPurkinjeCell->SetStimulusFunction(p_multi_stim_purkinje);
00162 }
00163 
00164 
00165 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00166 void AbstractPurkinjeCellFactory<ELEMENT_DIM,SPACE_DIM>::SetMesh(AbstractTetrahedralMesh<ELEMENT_DIM,SPACE_DIM>* pMesh)
00167 {
00168     mpMixedDimensionMesh = dynamic_cast<MixedDimensionMesh<ELEMENT_DIM,SPACE_DIM>*>(pMesh);
00169     if (mpMixedDimensionMesh == NULL)
00170     {
00171         EXCEPTION("AbstractPurkinjeCellFactory must take a MixedDimensionMesh");
00172     }
00173     mLocalPurkinjeNodes.clear();
00174     for (typename MixedDimensionMesh<ELEMENT_DIM,SPACE_DIM>::CableElementIterator iter = mpMixedDimensionMesh->GetCableElementIteratorBegin();
00175           iter != mpMixedDimensionMesh->GetCableElementIteratorEnd();
00176           ++iter)
00177     {
00178         mLocalPurkinjeNodes.insert((*iter)->GetNodeGlobalIndex(0u));
00179         mLocalPurkinjeNodes.insert((*iter)->GetNodeGlobalIndex(1u));
00180     }
00181     AbstractCardiacCellFactory<ELEMENT_DIM,SPACE_DIM>::SetMesh(pMesh);
00182 
00183     ReadJunctionsFile();
00184 }
00185 
00186 
00187 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00188 AbstractCardiacCellInterface*  AbstractPurkinjeCellFactory<ELEMENT_DIM,SPACE_DIM>::CreatePurkinjeCellForNode(
00189         Node<SPACE_DIM>* pNode,
00190         AbstractCardiacCellInterface* pCardiacCell)
00191 {
00192     unsigned node_index = pNode->GetIndex();
00193     if (mLocalPurkinjeNodes.count(node_index)>0)
00194     {
00195         return CreatePurkinjeCellForTissueNode(pNode, pCardiacCell);
00196     }
00197     else
00198     {
00199         return new FakeBathCell(this->mpSolver, this->mpZeroStimulus);
00200     }
00201 }
00202 
00203 
00204 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00205 MixedDimensionMesh<ELEMENT_DIM,SPACE_DIM>* AbstractPurkinjeCellFactory<ELEMENT_DIM,SPACE_DIM>::GetMixedDimensionMesh()
00206 {
00207     if (mpMixedDimensionMesh == NULL)
00208     {
00209         EXCEPTION("The mixed dimension mesh object has not been set in the cell factory");
00210     }
00211     return mpMixedDimensionMesh;
00212 }
00213 
00214 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00215 void AbstractPurkinjeCellFactory<ELEMENT_DIM,SPACE_DIM>::CreateJunctionFromFile(const Node<SPACE_DIM>* pNode,
00216                                                                                 AbstractCardiacCellInterface* pPurkinjeCell,
00217                                                                                 AbstractCardiacCellInterface* pCardiacCell)
00218 {
00219     std::map<unsigned, double>::iterator iter = mJunctionMap.find(pNode->GetIndex());
00220     if(iter != mJunctionMap.end())
00221     {
00222         CreateJunction(pNode, pPurkinjeCell, pCardiacCell, iter->second);
00223     }
00224 }
00225 
00227 // Explicit instantiation
00229 
00230 template class AbstractPurkinjeCellFactory<1,1>;
00231 template class AbstractPurkinjeCellFactory<2,2>;
00232 template class AbstractPurkinjeCellFactory<3,3>;
00233 template class AbstractPurkinjeCellFactory<1,2>;
00234 template class AbstractPurkinjeCellFactory<1,3>;

Generated by  doxygen 1.6.2