00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #include "UblasCustomFunctions.hpp"
00030
00031 #include "AbstractTetrahedralElement.hpp"
00032
00033 #include "Exception.hpp"
00034
00035 #include <cassert>
00036
00038
00040
00041 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00042 void AbstractTetrahedralElement<ELEMENT_DIM, SPACE_DIM>::RefreshJacobian(c_matrix<double, SPACE_DIM, ELEMENT_DIM>& rJacobian)
00043 {
00044 if (this->mIsDeleted)
00045 {
00046 EXCEPTION("Attempting to Refresh a deleted element");
00047 }
00048 for (unsigned i=0; i<SPACE_DIM; i++)
00049 {
00050 for (unsigned j=0; j!=ELEMENT_DIM; j++)
00051 {
00052 rJacobian(i,j) = this->GetNodeLocation(j+1,i) - this->GetNodeLocation(0,i);
00053 }
00054 }
00055 }
00056
00057 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00058 AbstractTetrahedralElement<ELEMENT_DIM, SPACE_DIM>::AbstractTetrahedralElement(unsigned index, const std::vector<Node<SPACE_DIM>*>& rNodes)
00059 : AbstractElement<ELEMENT_DIM, SPACE_DIM>(index, rNodes)
00060 {
00061
00062 unsigned num_vectices = ELEMENT_DIM+1;
00063
00064 double det;
00065
00066 if (SPACE_DIM == ELEMENT_DIM)
00067 {
00068
00069
00070 c_matrix<double, SPACE_DIM, ELEMENT_DIM> jacobian;
00071 try
00072 {
00073 CalculateJacobian(jacobian, det);
00074 }
00075 catch (Exception)
00076 {
00077
00078
00079
00080 this->mNodes[num_vectices-1] = rNodes[num_vectices-2];
00081 this->mNodes[num_vectices-2] = rNodes[num_vectices-1];
00082
00083 CalculateJacobian(jacobian, det);
00084
00085
00086 assert(det > 0.0);
00087 }
00088 }
00089 else
00090 {
00091
00092 c_vector<double, SPACE_DIM> weighted_direction;
00093 double det;
00094 CalculateWeightedDirection(weighted_direction, det);
00095 }
00096
00097 }
00098
00099 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00100 AbstractTetrahedralElement<ELEMENT_DIM, SPACE_DIM>::AbstractTetrahedralElement(unsigned index)
00101 : AbstractElement<ELEMENT_DIM,SPACE_DIM>(index)
00102 {}
00103
00104 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00105 void AbstractTetrahedralElement<ELEMENT_DIM, SPACE_DIM>::CalculateJacobian(c_matrix<double, SPACE_DIM, ELEMENT_DIM>& rJacobian, double& rJacobianDeterminant)
00106 {
00107
00108 assert(ELEMENT_DIM <= SPACE_DIM);
00109 RefreshJacobian(rJacobian);
00110
00111 {
00112 rJacobianDeterminant = Determinant(rJacobian);
00113 if (rJacobianDeterminant <= DBL_EPSILON)
00114 {
00115 std::stringstream string_stream;
00116 string_stream << "Jacobian determinant is non-positive: "
00117 << "determinant = " << rJacobianDeterminant
00118 << " for element " << this->mIndex;
00119 EXCEPTION(string_stream.str());
00120 }
00121 }
00122 }
00123
00124 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00125 void AbstractTetrahedralElement<ELEMENT_DIM, SPACE_DIM>::CalculateWeightedDirection(c_vector<double, SPACE_DIM>& rWeightedDirection, double& rJacobianDeterminant)
00126 {
00127
00128 if (ELEMENT_DIM >= SPACE_DIM)
00129 {
00130 assert(ELEMENT_DIM == SPACE_DIM);
00131 EXCEPTION("WeightedDirection undefined for fully dimensional element");
00132 }
00133
00134 c_matrix<double, SPACE_DIM, ELEMENT_DIM> jacobian;
00135 RefreshJacobian(jacobian);
00136
00137
00138
00139
00140
00141
00142 switch (ELEMENT_DIM)
00143 {
00144 case 0:
00145
00146 NEVER_REACHED;
00147 break;
00148 case 1:
00149
00150
00151 rWeightedDirection=matrix_column<c_matrix<double,SPACE_DIM,ELEMENT_DIM> >(jacobian, 0);
00152 break;
00153 case 2:
00154
00155 assert(SPACE_DIM == 3);
00156 rWeightedDirection(0) = -SubDeterminant(jacobian, 0, 2);
00157 rWeightedDirection(1) = SubDeterminant(jacobian, 1, 2);
00158 rWeightedDirection(2) = -SubDeterminant(jacobian, 2, 2);
00159 break;
00160 default:
00161 ;
00162 }
00163 rJacobianDeterminant = norm_2(rWeightedDirection);
00164
00165 if (rJacobianDeterminant < DBL_EPSILON)
00166 {
00167 EXCEPTION("Jacobian determinant is zero");
00168 }
00169 }
00170
00171 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00172 c_vector<double, SPACE_DIM> AbstractTetrahedralElement<ELEMENT_DIM, SPACE_DIM>::CalculateCentroid() const
00173 {
00174 c_vector<double, SPACE_DIM> centroid = zero_vector<double>(SPACE_DIM);
00175 for (unsigned i=0; i<=ELEMENT_DIM; i++)
00176 {
00177 centroid += this->mNodes[i]->rGetLocation();
00178 }
00179 return centroid/((double)(ELEMENT_DIM + 1));
00180 }
00181
00182 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00183 void AbstractTetrahedralElement<ELEMENT_DIM, SPACE_DIM>::CalculateInverseJacobian(c_matrix<double, SPACE_DIM, ELEMENT_DIM>& rJacobian, double& rJacobianDeterminant, c_matrix<double, ELEMENT_DIM, SPACE_DIM>& rInverseJacobian)
00184 {
00185 assert(ELEMENT_DIM <= SPACE_DIM);
00186 CalculateJacobian(rJacobian, rJacobianDeterminant);
00187
00188
00189 assert(rJacobianDeterminant > 0.0);
00190 rInverseJacobian = Inverse(rJacobian);
00191 }
00192
00193 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00194 double AbstractTetrahedralElement<ELEMENT_DIM, SPACE_DIM>::GetVolume(double determinant) const
00195 {
00196 assert(SPACE_DIM == ELEMENT_DIM);
00197
00198 if (this->mIsDeleted)
00199 {
00200 return 0.0;
00201 }
00202
00203 double scale_factor = 1.0;
00204
00205 if (ELEMENT_DIM == 2)
00206 {
00207 scale_factor = 2.0;
00208 }
00209 else if (ELEMENT_DIM == 3)
00210 {
00211 scale_factor = 6.0;
00212 }
00213 return determinant/scale_factor;
00214 }
00215
00216 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00217 void AbstractTetrahedralElement<ELEMENT_DIM, SPACE_DIM>::GetStiffnessMatrixGlobalIndices(unsigned problemDim, unsigned* pIndices) const
00218 {
00219 for (unsigned local_index=0; local_index<ELEMENT_DIM+1; local_index++)
00220 {
00221 unsigned node = this->GetNodeGlobalIndex(local_index);
00222
00223 for (unsigned problem_index=0; problem_index<problemDim; problem_index++)
00224 {
00225
00226 pIndices[local_index*problemDim + problem_index] = node*problemDim + problem_index;
00227 }
00228 }
00229 }
00230
00231
00233
00235
00240 template<unsigned SPACE_DIM>
00241 AbstractTetrahedralElement<0, SPACE_DIM>::AbstractTetrahedralElement(unsigned index, const std::vector<Node<SPACE_DIM>*>& rNodes)
00242 : AbstractElement<0, SPACE_DIM>(index, rNodes)
00243 {
00244
00245
00246 assert(this->mNodes.size() == 1);
00247 assert(SPACE_DIM > 0);
00248
00249
00250
00251 c_vector<double, SPACE_DIM> weighted_direction;
00252 double det;
00253
00254 CalculateWeightedDirection(weighted_direction, det);
00255
00256
00257
00258 assert(det > 0.0);
00259 }
00260
00261 template<unsigned SPACE_DIM>
00262 AbstractTetrahedralElement<0, SPACE_DIM>::AbstractTetrahedralElement(unsigned index)
00263 : AbstractElement<0, SPACE_DIM>(index)
00264 {
00265 }
00266
00267 template<unsigned SPACE_DIM>
00268 void AbstractTetrahedralElement<0, SPACE_DIM>::CalculateWeightedDirection(
00269 c_vector<double, SPACE_DIM>& rWeightedDirection,
00270 double& rJacobianDeterminant)
00271 {
00272 assert(SPACE_DIM > 0);
00273
00274
00275 rWeightedDirection = zero_vector<double>(SPACE_DIM);
00276 rWeightedDirection(0) = 1.0;
00277
00278 rJacobianDeterminant = 1.0;
00279 }
00280
00281 template<unsigned SPACE_DIM>
00282 c_vector<double, SPACE_DIM> AbstractTetrahedralElement<0, SPACE_DIM>::CalculateCentroid() const
00283 {
00284 c_vector<double, SPACE_DIM> centroid = this->mNodes[0]->rGetLocation();
00285 return centroid;
00286 }
00287
00288 template<unsigned SPACE_DIM>
00289 void AbstractTetrahedralElement<0, SPACE_DIM>::GetStiffnessMatrixGlobalIndices(unsigned problemDim, unsigned* pIndices) const
00290 {
00291 for (unsigned local_index=0; local_index<1; local_index++)
00292 {
00293 unsigned node = this->GetNodeGlobalIndex(local_index);
00294
00295 for (unsigned problem_index=0; problem_index<problemDim; problem_index++)
00296 {
00297
00298 pIndices[local_index*problemDim + problem_index] = node*problemDim + problem_index;
00299 }
00300 }
00301 }
00302
00304
00306
00307 template class AbstractTetrahedralElement<0,1>;
00308 template class AbstractTetrahedralElement<1,1>;
00309 template class AbstractTetrahedralElement<0,2>;
00310 template class AbstractTetrahedralElement<1,2>;
00311 template class AbstractTetrahedralElement<2,2>;
00312 template class AbstractTetrahedralElement<0,3>;
00313 template class AbstractTetrahedralElement<1,3>;
00314 template class AbstractTetrahedralElement<2,3>;
00315 template class AbstractTetrahedralElement<3,3>;