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