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
00030
00031
00032
00033
00034
00035
00036 #include "UblasCustomFunctions.hpp"
00037 #include "AbstractTetrahedralElement.hpp"
00038 #include "Exception.hpp"
00039
00040 #include <cassert>
00041
00043
00045
00046 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00047 void AbstractTetrahedralElement<ELEMENT_DIM, SPACE_DIM>::RefreshJacobian(c_matrix<double, SPACE_DIM, ELEMENT_DIM>& rJacobian)
00048 {
00049 if (this->mIsDeleted)
00050 {
00051 EXCEPTION("Attempting to Refresh a deleted element");
00052 }
00053 for (unsigned i=0; i<SPACE_DIM; i++)
00054 {
00055 for (unsigned j=0; j!=ELEMENT_DIM; j++)
00056 {
00057 rJacobian(i,j) = this->GetNodeLocation(j+1,i) - this->GetNodeLocation(0,i);
00058 }
00059 }
00060 }
00061
00062 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00063 AbstractTetrahedralElement<ELEMENT_DIM, SPACE_DIM>::AbstractTetrahedralElement(unsigned index, const std::vector<Node<SPACE_DIM>*>& rNodes)
00064 : AbstractElement<ELEMENT_DIM, SPACE_DIM>(index, rNodes)
00065 {
00066
00067 unsigned num_vectices = ELEMENT_DIM+1;
00068
00069 double det;
00070
00071 if (SPACE_DIM == ELEMENT_DIM)
00072 {
00073
00074
00075 c_matrix<double, SPACE_DIM, ELEMENT_DIM> jacobian;
00076 try
00077 {
00078 CalculateJacobian(jacobian, det);
00079 }
00080 catch (Exception)
00081 {
00082
00083
00084
00085 this->mNodes[num_vectices-1] = rNodes[num_vectices-2];
00086 this->mNodes[num_vectices-2] = rNodes[num_vectices-1];
00087
00088 CalculateJacobian(jacobian, det);
00089
00090
00091 assert(det > 0.0);
00092 }
00093 }
00094 else
00095 {
00096
00097 c_vector<double, SPACE_DIM> weighted_direction;
00098 CalculateWeightedDirection(weighted_direction, det);
00099 }
00100
00101 }
00102
00103 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00104 AbstractTetrahedralElement<ELEMENT_DIM, SPACE_DIM>::AbstractTetrahedralElement(unsigned index)
00105 : AbstractElement<ELEMENT_DIM,SPACE_DIM>(index)
00106 {}
00107
00108 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00109 void AbstractTetrahedralElement<ELEMENT_DIM, SPACE_DIM>::CalculateJacobian(c_matrix<double, SPACE_DIM, ELEMENT_DIM>& rJacobian, double& rJacobianDeterminant)
00110 {
00111
00112 assert(ELEMENT_DIM <= SPACE_DIM);
00113 RefreshJacobian(rJacobian);
00114
00115 {
00116 rJacobianDeterminant = Determinant(rJacobian);
00117 if (rJacobianDeterminant <= DBL_EPSILON)
00118 {
00119 EXCEPTION("Jacobian determinant is non-positive: "
00120 << "determinant = " << rJacobianDeterminant
00121 << " for element " << this->mIndex);
00122 }
00123 }
00124 }
00125
00126 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00127 void AbstractTetrahedralElement<ELEMENT_DIM, SPACE_DIM>::CalculateWeightedDirection(c_vector<double, SPACE_DIM>& rWeightedDirection, double& rJacobianDeterminant)
00128 {
00129
00130 if (ELEMENT_DIM >= SPACE_DIM)
00131 {
00132 assert(ELEMENT_DIM == SPACE_DIM);
00133 EXCEPTION("WeightedDirection undefined for fully dimensional element");
00134 }
00135
00136 c_matrix<double, SPACE_DIM, ELEMENT_DIM> jacobian;
00137 RefreshJacobian(jacobian);
00138
00139
00140
00141
00142
00143
00144
00145
00146 switch (ELEMENT_DIM)
00147 {
00148 case 0:
00149
00150 NEVER_REACHED;
00151 break;
00152 case 1:
00153
00154 rWeightedDirection=matrix_column<c_matrix<double,SPACE_DIM,ELEMENT_DIM> >(jacobian, 0);
00155 break;
00156 case 2:
00157
00158 assert(SPACE_DIM == 3);
00159 rWeightedDirection(0) = -SubDeterminant(jacobian, 0, 2);
00160 rWeightedDirection(1) = SubDeterminant(jacobian, 1, 2);
00161 rWeightedDirection(2) = -SubDeterminant(jacobian, 2, 2);
00162 break;
00163 default:
00164 ;
00165 }
00166 rJacobianDeterminant = norm_2(rWeightedDirection);
00167
00168 if (rJacobianDeterminant < DBL_EPSILON)
00169 {
00170 EXCEPTION("Jacobian determinant is zero");
00171 }
00172 }
00173
00174
00175 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00176 c_vector<double, SPACE_DIM> AbstractTetrahedralElement<ELEMENT_DIM, SPACE_DIM>::CalculateNormal()
00177 {
00178 if (ELEMENT_DIM == 1 && SPACE_DIM == 3)
00179 {
00180 EXCEPTION("Don't have enough information to calculate a normal vector");
00181 }
00182 c_vector<double, SPACE_DIM> normal;
00183 double determinant;
00184 CalculateWeightedDirection(normal, determinant);
00185 normal /= determinant;
00186 if (ELEMENT_DIM == 1)
00187 {
00188
00189 double x = normal[0];
00190 normal[0] = normal[1];
00191 normal[1] = -x;
00192 }
00193 return normal;
00194 }
00195
00196 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00197 c_vector<double, SPACE_DIM> AbstractTetrahedralElement<ELEMENT_DIM, SPACE_DIM>::CalculateCentroid() const
00198 {
00199 c_vector<double, SPACE_DIM> centroid = zero_vector<double>(SPACE_DIM);
00200 for (unsigned i=0; i<=ELEMENT_DIM; i++)
00201 {
00202 centroid += this->mNodes[i]->rGetLocation();
00203 }
00204 return centroid/((double)(ELEMENT_DIM + 1));
00205 }
00206
00207 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00208 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)
00209 {
00210 assert(ELEMENT_DIM <= SPACE_DIM);
00211 CalculateJacobian(rJacobian, rJacobianDeterminant);
00212
00213
00214 assert(rJacobianDeterminant > 0.0);
00215 rInverseJacobian = Inverse(rJacobian);
00216 }
00217
00218 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00219 double AbstractTetrahedralElement<ELEMENT_DIM, SPACE_DIM>::GetVolume(double determinant) const
00220 {
00221
00222 if (this->mIsDeleted)
00223 {
00224 return 0.0;
00225 }
00226
00227 double scale_factor = 1.0;
00228
00229 if (ELEMENT_DIM == 2)
00230 {
00231 scale_factor = 2.0;
00232 }
00233 else if (ELEMENT_DIM == 3)
00234 {
00235 scale_factor = 6.0;
00236 }
00237 return determinant/scale_factor;
00238 }
00239
00240 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00241 void AbstractTetrahedralElement<ELEMENT_DIM, SPACE_DIM>::GetStiffnessMatrixGlobalIndices(unsigned problemDim, unsigned* pIndices) const
00242 {
00243 for (unsigned local_index=0; local_index<ELEMENT_DIM+1; local_index++)
00244 {
00245 unsigned node = this->GetNodeGlobalIndex(local_index);
00246
00247 for (unsigned problem_index=0; problem_index<problemDim; problem_index++)
00248 {
00249
00250 pIndices[local_index*problemDim + problem_index] = node*problemDim + problem_index;
00251 }
00252 }
00253 }
00254
00255
00257
00259
00264 template<unsigned SPACE_DIM>
00265 AbstractTetrahedralElement<0, SPACE_DIM>::AbstractTetrahedralElement(unsigned index, const std::vector<Node<SPACE_DIM>*>& rNodes)
00266 : AbstractElement<0, SPACE_DIM>(index, rNodes)
00267 {
00268
00269
00270 assert(this->mNodes.size() == 1);
00271 assert(SPACE_DIM > 0);
00272
00273
00274
00275 c_vector<double, SPACE_DIM> weighted_direction;
00276 double det;
00277
00278 CalculateWeightedDirection(weighted_direction, det);
00279
00280
00281
00282 assert(det > 0.0);
00283 }
00284
00285 template<unsigned SPACE_DIM>
00286 AbstractTetrahedralElement<0, SPACE_DIM>::AbstractTetrahedralElement(unsigned index)
00287 : AbstractElement<0, SPACE_DIM>(index)
00288 {
00289 }
00290
00291 template<unsigned SPACE_DIM>
00292 void AbstractTetrahedralElement<0, SPACE_DIM>::CalculateWeightedDirection(
00293 c_vector<double, SPACE_DIM>& rWeightedDirection,
00294 double& rJacobianDeterminant)
00295 {
00296 assert(SPACE_DIM > 0);
00297
00298
00299 rWeightedDirection = zero_vector<double>(SPACE_DIM);
00300 rWeightedDirection(0) = 1.0;
00301
00302 rJacobianDeterminant = 1.0;
00303 }
00304
00305 template<unsigned SPACE_DIM>
00306 c_vector<double, SPACE_DIM> AbstractTetrahedralElement<0, SPACE_DIM>::CalculateNormal()
00307 {
00308 assert(SPACE_DIM > 0);
00309
00310
00311 c_vector<double, SPACE_DIM> normal = zero_vector<double>(SPACE_DIM);
00313 return normal;
00314 }
00315
00316 template<unsigned SPACE_DIM>
00317 c_vector<double, SPACE_DIM> AbstractTetrahedralElement<0, SPACE_DIM>::CalculateCentroid() const
00318 {
00319 c_vector<double, SPACE_DIM> centroid = this->mNodes[0]->rGetLocation();
00320 return centroid;
00321 }
00322
00323 template<unsigned SPACE_DIM>
00324 void AbstractTetrahedralElement<0, SPACE_DIM>::GetStiffnessMatrixGlobalIndices(unsigned problemDim, unsigned* pIndices) const
00325 {
00326 for (unsigned local_index=0; local_index<1; local_index++)
00327 {
00328 unsigned node = this->GetNodeGlobalIndex(local_index);
00329
00330 for (unsigned problem_index=0; problem_index<problemDim; problem_index++)
00331 {
00332
00333 pIndices[local_index*problemDim + problem_index] = node*problemDim + problem_index;
00334 }
00335 }
00336 }
00337
00339
00341
00342 template class AbstractTetrahedralElement<0,1>;
00343 template class AbstractTetrahedralElement<1,1>;
00344 template class AbstractTetrahedralElement<0,2>;
00345 template class AbstractTetrahedralElement<1,2>;
00346 template class AbstractTetrahedralElement<2,2>;
00347 template class AbstractTetrahedralElement<0,3>;
00348 template class AbstractTetrahedralElement<1,3>;
00349 template class AbstractTetrahedralElement<2,3>;
00350 template class AbstractTetrahedralElement<3,3>;