Chaste Release::3.1
|
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>;