Chaste Release::3.1
AxisymmetricConductivityTensors.cpp
00001 /*
00002 
00003 Copyright (c) 2005-2012, 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 #include <vector>
00037 #include "UblasIncludes.hpp"
00038 #include "AxisymmetricConductivityTensors.hpp"
00039 #include "Exception.hpp"
00040 
00041 
00042 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00043 AxisymmetricConductivityTensors<ELEMENT_DIM, SPACE_DIM>::AxisymmetricConductivityTensors()
00044 {
00045     if (SPACE_DIM != 3)
00046     {
00047         EXCEPTION("Axisymmetric anisotropic conductivity only makes sense in 3D");
00048     }
00049 }
00050 
00051 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00052 void AxisymmetricConductivityTensors<ELEMENT_DIM, SPACE_DIM>::SetConstantConductivities(c_vector<double, 3> constantConductivities)
00053 {
00054     //assert(SPACE_DIM == 3);//Otherwise constructor would have thrown
00055     if (constantConductivities[1] != constantConductivities[2])
00056     {
00057         EXCEPTION("Axisymmetric media defined: transversal and normal conductivities should have the same value");
00058     }
00059 
00060     this->mUseNonConstantConductivities = false;
00061     this->mConstantConductivities = constantConductivities;
00062 }
00063 
00064 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00065 void AxisymmetricConductivityTensors<ELEMENT_DIM, SPACE_DIM>::Init(AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM> *pMesh) throw (Exception)
00066 {
00067     this->mpMesh = pMesh;
00068 
00069     if (!this->mUseNonConstantConductivities && !this->mUseFibreOrientation)
00070     {
00071         // Constant tensor for every element
00072         c_matrix<double, SPACE_DIM, SPACE_DIM> conductivity_matrix(zero_matrix<double>(SPACE_DIM,SPACE_DIM));
00073 
00074         for (unsigned dim=0; dim<SPACE_DIM; dim++)
00075         {
00076             assert(this->mConstantConductivities(dim) != DBL_MAX);
00077             conductivity_matrix(dim,dim) = this->mConstantConductivities(dim);
00078         }
00079         this->mTensors.push_back(conductivity_matrix);
00080     }
00081     else
00082     {
00083         c_vector<double,SPACE_DIM> fibre_vector((zero_vector<double>(SPACE_DIM)));
00084         fibre_vector[0]=1.0;
00085 
00086         if (this->mUseFibreOrientation)
00087         {
00088             // open file
00089             this->mFileReader.reset(new FibreReader<SPACE_DIM>(this->mFibreOrientationFile, AXISYM));
00090             if(this->mFileReader->GetNumLinesOfData() != this->mpMesh->GetNumElements())
00091             {
00092                 EXCEPTION("The size of the fibre file does not match the number of elements in the mesh");
00093             }
00094         }
00095 
00096         if (this->mUseNonConstantConductivities)
00097         {
00098             if(this->mpNonConstantConductivities->size() != this->mpMesh->GetNumLocalElements())
00099             {
00100                 EXCEPTION("The size of the conductivities vector does not match the number of elements in the mesh");
00101             }
00102         }
00103 
00104         // reserve() allocates all the memory at once, more efficient than relying
00105         // on the automatic reallocation scheme.
00106         this->mTensors.reserve(this->mpMesh->GetNumLocalElements());
00107 
00108         c_matrix<double, SPACE_DIM, SPACE_DIM> conductivity_matrix(zero_matrix<double>(SPACE_DIM,SPACE_DIM));
00109 
00110         unsigned local_element_index = 0;
00111 
00112         for (typename AbstractTetrahedralMesh<ELEMENT_DIM,SPACE_DIM>::ElementIterator it = this->mpMesh->GetElementIteratorBegin();
00113              it != this->mpMesh->GetElementIteratorEnd();
00114              ++it)
00115         {
00116             /*
00117              *  For every element of the mesh we compute its tensor like (from
00118              * "Laminar Arrangement of VentricularMyocites Influences Electrical
00119              * Behavior of the Heart", Darren et al. 2007):
00120              *
00121              *                         [g_f  0   0 ] [a_f']
00122              *  tensor = [a_f a_l a_n] [ 0  g_l  0 ] [a_l']
00123              *                         [ 0   0  g_n] [a_n']
00124              *
00125              *              [x_i]
00126              *  where a_i = [y_i], i={f,l,n} are read from the fibre orientation file and
00127              *              [z_i]
00128              *
00129              *  g_f = fibre/longitudinal conductivity (constant or element specific)
00130              *  g_l = laminar/transverse conductivity (constant or element specific)
00131              *  g_n = normal conductivity (constant or element specific)
00132              *
00133              *
00134              *  For axisymmetric anisotropic media (g_l = g_n) we can simplify previous expression to
00135              *
00136              *
00137              *  tensor = g_l * I + (g_f - g_l) * a_f * a_f'
00138              *
00139              */
00140 
00141             if (this->mUseNonConstantConductivities)
00142             {
00143                 for (unsigned dim=0; dim<SPACE_DIM; dim++)
00144                 {
00145                     conductivity_matrix(dim,dim) = (*this->mpNonConstantConductivities)[local_element_index][dim];
00146                 }
00147             }
00148             else
00149             {
00150                 for (unsigned dim=0; dim<SPACE_DIM; dim++)
00151                 {
00152                     assert(this->mConstantConductivities(dim) != DBL_MAX);
00153                     conductivity_matrix(dim,dim) = this->mConstantConductivities(dim);
00154                 }
00155             }
00156 
00157             if (this->mUseFibreOrientation)
00158             {
00159                 unsigned current_fibre_global_index = it->GetIndex();
00160                 this->mFileReader->GetFibreVector(current_fibre_global_index, fibre_vector);
00161             }
00162 
00163             this->mTensors.push_back( conductivity_matrix(1,1) * identity_matrix<double>(SPACE_DIM) +
00164                                       (conductivity_matrix(0,0) - conductivity_matrix(1,1)) * outer_prod(fibre_vector,fibre_vector));
00165 
00166             local_element_index++;
00167         }
00168 
00169         assert(this->mTensors.size() == this->mpMesh->GetNumLocalElements());
00170         assert(this->mTensors.size() == local_element_index);
00171 
00172         if (this->mUseFibreOrientation)
00173         {
00174             // close fibre file
00175             this->mFileReader.reset();
00176         }
00177     }
00178 
00179     this->mInitialised = true;
00180 }
00181 
00182 
00183 
00185 // Explicit instantiation
00187 
00188 // only makes sense for 3d elements in 3d, but we need the other to compile
00189 // AbstractCardiacTissue and BidomainTissue.
00190 template class AxisymmetricConductivityTensors<1,1>;
00191 template class AxisymmetricConductivityTensors<1,2>;
00192 template class AxisymmetricConductivityTensors<1,3>;
00193 template class AxisymmetricConductivityTensors<2,2>;
00194 template class AxisymmetricConductivityTensors<2,3>;
00195 template class AxisymmetricConductivityTensors<3,3>;