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 #ifndef PAPILLARYFIBRECALCULATOR_HPP_ 00036 #define PAPILLARYFIBRECALCULATOR_HPP_ 00037 00038 #include "UblasCustomFunctions.hpp" 00039 #include "TetrahedralMesh.hpp" 00040 00046 class PapillaryFibreCalculator 00047 { 00048 // Allow the test class to use the private functions. 00049 friend class TestPapillaryFibreCalculator; 00050 00051 private: 00053 TetrahedralMesh<3,3>& mrMesh; 00055 std::vector< c_vector<double, 3> > mRadiusVectors; 00057 std::vector< c_matrix<double,3,3> > mStructureTensors; 00059 std::vector< c_matrix<double,3,3> > mSmoothedStructureTensors; 00060 00068 c_vector<double,3> GetRadiusVectorForOneElement(unsigned elementIndex); 00069 00074 void GetRadiusVectors(); 00075 00076 00082 void ConstructStructureTensors(); 00083 00093 void SmoothStructureTensors(); 00094 00095 public: 00101 PapillaryFibreCalculator(TetrahedralMesh<3,3>& rMesh); 00102 00108 std::vector<c_vector<double,3> > CalculateFibreOrientations(); 00109 00110 }; 00111 00112 // PUBLIC METHODS 00113 PapillaryFibreCalculator::PapillaryFibreCalculator(TetrahedralMesh<3,3>& rMesh) 00114 : mrMesh(rMesh) 00115 { 00116 mRadiusVectors.resize(mrMesh.GetNumElements()); 00117 mStructureTensors.resize(mrMesh.GetNumElements()); 00118 mSmoothedStructureTensors.resize(mrMesh.GetNumElements()); 00119 } 00120 00121 std::vector<c_vector<double,3> > PapillaryFibreCalculator::CalculateFibreOrientations() 00122 { 00123 GetRadiusVectors(); 00124 00125 ConstructStructureTensors(); 00126 00127 SmoothStructureTensors(); 00128 00129 // Calculate eigenvalues 00130 std::vector<c_vector<double,3> > fibre_orientations(mrMesh.GetNumElements()); 00131 for(unsigned i=0; i<fibre_orientations.size(); i++) 00132 { 00133 fibre_orientations[i] = CalculateEigenvectorForSmallestNonzeroEigenvalue(mSmoothedStructureTensors[i]); 00134 } 00135 00136 return fibre_orientations; 00137 } 00138 00139 // PRIVATE METHODS 00140 c_vector<double,3> PapillaryFibreCalculator::GetRadiusVectorForOneElement(unsigned elementIndex) 00141 { 00142 c_vector<double, 3> centroid = (mrMesh.GetElement(elementIndex))->CalculateCentroid(); 00143 // Loops over all papillary face nodes 00144 c_vector<double,3> coordinates; 00145 00146 double nearest_r_squared=DBL_MAX; 00147 unsigned nearest_face_node = 0; 00148 00149 TetrahedralMesh<3,3>::BoundaryNodeIterator bound_node_iter = mrMesh.GetBoundaryNodeIteratorBegin(); 00150 while (bound_node_iter != mrMesh.GetBoundaryNodeIteratorEnd()) 00151 { 00152 unsigned bound_node_index = (*bound_node_iter)->GetIndex(); 00153 coordinates=mrMesh.GetNode(bound_node_index)->rGetLocation(); 00154 00155 // Calculates the distance between the papillary face node and the centroid 00156 double r_squared = norm_2(centroid-coordinates); 00157 // Checks to see if it is the smallest so far - if it is, update the current smallest distance 00158 if (r_squared < nearest_r_squared) 00159 { 00160 nearest_r_squared = r_squared; 00161 nearest_face_node = bound_node_index; 00162 } 00163 ++bound_node_iter; 00164 } 00165 00166 coordinates = mrMesh.GetNode(nearest_face_node)->rGetLocation(); 00167 c_vector<double,3> radial_vector = coordinates-centroid; 00168 return radial_vector; 00169 } 00170 00171 void PapillaryFibreCalculator::GetRadiusVectors() 00172 { 00173 // Loops over all elements finding radius vector 00174 for (AbstractTetrahedralMesh<3,3>::ElementIterator iter = mrMesh.GetElementIteratorBegin(); 00175 iter != mrMesh.GetElementIteratorEnd(); 00176 ++iter) 00177 { 00178 unsigned element_index = iter->GetIndex(); 00179 mRadiusVectors[element_index] = GetRadiusVectorForOneElement(element_index); 00180 } 00181 } 00182 00183 void PapillaryFibreCalculator::ConstructStructureTensors() 00184 { 00185 for(unsigned i=0;i<mRadiusVectors.size();i++) 00186 { 00187 mStructureTensors[i] = outer_prod(mRadiusVectors[i],mRadiusVectors[i]); 00188 } 00189 } 00190 00191 void PapillaryFibreCalculator::SmoothStructureTensors() 00192 { 00193 const double sigma = 0.05; //cm 00194 const double r_max = 0.1; //cm 00195 double g_factor_sum = 0; 00196 double g_factor = 0; 00197 00198 for (AbstractTetrahedralMesh<3,3>::ElementIterator elem_iter = mrMesh.GetElementIteratorBegin(); 00199 elem_iter != mrMesh.GetElementIteratorEnd(); 00200 ++elem_iter) 00201 { 00202 mSmoothedStructureTensors[ elem_iter->GetIndex()] = zero_matrix<double>(3,3); 00203 00204 c_vector<double, 3> centroid = elem_iter->CalculateCentroid(); 00205 g_factor_sum = 0; 00206 00207 for (AbstractTetrahedralMesh<3,3>::ElementIterator iter_2 = mrMesh.GetElementIteratorBegin(); 00208 iter_2 != mrMesh.GetElementIteratorEnd(); 00209 ++iter_2) 00210 { 00211 c_vector<double, 3> centroid_2 = iter_2->CalculateCentroid(); 00212 double r = norm_2(centroid-centroid_2); 00213 if (r < r_max) 00214 { 00215 g_factor = exp(-r/(2*sigma*sigma)); 00216 00217 g_factor_sum += g_factor; 00218 00219 mSmoothedStructureTensors[elem_iter->GetIndex()] += g_factor*mStructureTensors[iter_2->GetIndex()]; 00220 } 00221 } 00222 00223 mSmoothedStructureTensors[elem_iter->GetIndex()] /= g_factor_sum; 00224 } 00225 } 00226 00227 #endif /*PAPILLARYFIBRECALCULATOR_HPP_*/ 00228