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
00065
00066 c_matrix<double, SPACE_DIM, ELEMENT_DIM> jacobian;
00067
00068 if (SPACE_DIM == ELEMENT_DIM)
00069 {
00070 double det;
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
00090 }
00091
00092 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00093 AbstractTetrahedralElement<ELEMENT_DIM, SPACE_DIM>::AbstractTetrahedralElement(unsigned index)
00094 : AbstractElement<ELEMENT_DIM,SPACE_DIM>(index)
00095 {}
00096
00097 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00098 void AbstractTetrahedralElement<ELEMENT_DIM, SPACE_DIM>::CalculateJacobian(c_matrix<double, SPACE_DIM, ELEMENT_DIM>& rJacobian, double& rJacobianDeterminant)
00099 {
00100
00101 assert(ELEMENT_DIM <= SPACE_DIM);
00102 RefreshJacobian(rJacobian);
00103
00104 {
00105 rJacobianDeterminant = Determinant(rJacobian);
00106 if (rJacobianDeterminant <= DBL_EPSILON)
00107 {
00108 std::stringstream string_stream;
00109 string_stream << "Jacobian determinant is non-positive: "
00110 << "determinant = " << rJacobianDeterminant
00111 << " for element " << this->mIndex;
00112 EXCEPTION(string_stream.str());
00113 }
00114 }
00115 }
00116
00117 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00118 void AbstractTetrahedralElement<ELEMENT_DIM, SPACE_DIM>::CalculateWeightedDirection(c_vector<double, SPACE_DIM>& rWeightedDirection, double& rJacobianDeterminant)
00119 {
00120
00121 if (ELEMENT_DIM >= SPACE_DIM)
00122 {
00123 assert(ELEMENT_DIM == SPACE_DIM);
00124 EXCEPTION("WeightedDirection undefined for fully dimensional element");
00125 }
00126
00127 c_matrix<double, SPACE_DIM, ELEMENT_DIM> jacobian;
00128 RefreshJacobian(jacobian);
00129
00130
00131
00132
00133
00134
00135 switch (ELEMENT_DIM)
00136 {
00137 case 0:
00138
00139 NEVER_REACHED;
00140 break;
00141 case 1:
00142
00143
00144 rWeightedDirection=matrix_column<c_matrix<double,SPACE_DIM,ELEMENT_DIM> >(jacobian, 0);
00145 break;
00146 case 2:
00147
00148 assert(SPACE_DIM == 3);
00149 rWeightedDirection(0) = -SubDeterminant(jacobian, 0, 2);
00150 rWeightedDirection(1) = SubDeterminant(jacobian, 1, 2);
00151 rWeightedDirection(2) = -SubDeterminant(jacobian, 2, 2);
00152 break;
00153 default:
00154 ;
00155 }
00156 rJacobianDeterminant = norm_2(rWeightedDirection);
00157
00158 if (rJacobianDeterminant < DBL_EPSILON)
00159 {
00160 EXCEPTION("Jacobian determinant is zero");
00161 }
00162 }
00163
00164 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00165 c_vector<double, SPACE_DIM> AbstractTetrahedralElement<ELEMENT_DIM, SPACE_DIM>::CalculateCentroid() const
00166 {
00167 c_vector<double, SPACE_DIM> centroid = zero_vector<double>(SPACE_DIM);
00168 for (unsigned i=0; i<=ELEMENT_DIM; i++)
00169 {
00170 centroid += this->mNodes[i]->rGetLocation();
00171 }
00172 return centroid/((double)(ELEMENT_DIM + 1));
00173 }
00174
00175 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00176 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)
00177 {
00178 assert(ELEMENT_DIM <= SPACE_DIM);
00179 CalculateJacobian(rJacobian, rJacobianDeterminant);
00180
00181
00182 assert(rJacobianDeterminant > 0.0);
00183 rInverseJacobian = Inverse(rJacobian);
00184 }
00185
00186 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00187 double AbstractTetrahedralElement<ELEMENT_DIM, SPACE_DIM>::GetVolume(double determinant) const
00188 {
00189 assert(SPACE_DIM == ELEMENT_DIM);
00190
00191 if (this->mIsDeleted)
00192 {
00193 return 0.0;
00194 }
00195
00196 double scale_factor = 1.0;
00197
00198 if (ELEMENT_DIM == 2)
00199 {
00200 scale_factor = 2.0;
00201 }
00202 else if (ELEMENT_DIM == 3)
00203 {
00204 scale_factor = 6.0;
00205 }
00206 return determinant/scale_factor;
00207 }
00208
00209 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00210 void AbstractTetrahedralElement<ELEMENT_DIM, SPACE_DIM>::GetStiffnessMatrixGlobalIndices(unsigned problemDim, unsigned* pIndices) const
00211 {
00212 for (unsigned local_index=0; local_index<ELEMENT_DIM+1; local_index++)
00213 {
00214 unsigned node = this->GetNodeGlobalIndex(local_index);
00215
00216 for (unsigned problem_index=0; problem_index<problemDim; problem_index++)
00217 {
00218
00219 pIndices[local_index*problemDim + problem_index] = node*problemDim + problem_index;
00220 }
00221 }
00222 }
00223
00224
00226
00228
00233 template<unsigned SPACE_DIM>
00234 class AbstractTetrahedralElement<0, SPACE_DIM> : public AbstractElement<0,SPACE_DIM>
00235 {
00236 public:
00237
00244 AbstractTetrahedralElement(unsigned index, const std::vector<Node<SPACE_DIM>*>& rNodes);
00245
00252 AbstractTetrahedralElement(unsigned index=INDEX_IS_NOT_USED);
00253
00257 virtual ~AbstractTetrahedralElement()
00258 {}
00259
00263 c_vector<double, SPACE_DIM> CalculateCentroid() const;
00264
00271 void CalculateWeightedDirection(c_vector<double, SPACE_DIM>& rWeightedDirection, double& rJacobianDeterminant);
00272
00281 void GetStiffnessMatrixGlobalIndices(unsigned problemDim, unsigned* pIndices) const;
00282 };
00283
00284 #include <cassert>
00285
00286 template<unsigned SPACE_DIM>
00287 AbstractTetrahedralElement<0, SPACE_DIM>::AbstractTetrahedralElement(unsigned index, const std::vector<Node<SPACE_DIM>*>& rNodes)
00288 : AbstractElement<0, SPACE_DIM>(index, rNodes)
00289 {
00290
00291
00292 assert(this->mNodes.size() == 1);
00293 assert(SPACE_DIM > 0);
00294
00295
00296
00297 c_vector<double, SPACE_DIM> weighted_direction;
00298 double det;
00299
00300 CalculateWeightedDirection(weighted_direction, det);
00301
00302
00303
00304 assert(det > 0.0);
00305 }
00306
00307 template<unsigned SPACE_DIM>
00308 AbstractTetrahedralElement<0, SPACE_DIM>::AbstractTetrahedralElement(unsigned index)
00309 : AbstractElement<0, SPACE_DIM>(index)
00310 {
00311 }
00312
00313 template<unsigned SPACE_DIM>
00314 void AbstractTetrahedralElement<0, SPACE_DIM>::CalculateWeightedDirection(
00315 c_vector<double, SPACE_DIM>& rWeightedDirection,
00316 double& rJacobianDeterminant)
00317 {
00318 assert(SPACE_DIM > 0);
00319
00320
00321 rWeightedDirection = zero_vector<double>(SPACE_DIM);
00322 rWeightedDirection(0) = 1.0;
00323
00324 rJacobianDeterminant = 1.0;
00325 }
00326
00327 template<unsigned SPACE_DIM>
00328 c_vector<double, SPACE_DIM> AbstractTetrahedralElement<0, SPACE_DIM>::CalculateCentroid() const
00329 {
00330 c_vector<double, SPACE_DIM> centroid = this->mNodes[0]->rGetLocation();
00331 return centroid;
00332 }
00333
00334 template<unsigned SPACE_DIM>
00335 void AbstractTetrahedralElement<0, SPACE_DIM>::GetStiffnessMatrixGlobalIndices(unsigned problemDim, unsigned* pIndices) const
00336 {
00337 for (unsigned local_index=0; local_index<1; local_index++)
00338 {
00339 unsigned node = this->GetNodeGlobalIndex(local_index);
00340
00341 for (unsigned problem_index=0; problem_index<problemDim; problem_index++)
00342 {
00343
00344 pIndices[local_index*problemDim + problem_index] = node*problemDim + problem_index;
00345 }
00346 }
00347 }
00348
00349
00351
00353
00354 template class AbstractTetrahedralElement<0,1>;
00355 template class AbstractTetrahedralElement<1,1>;
00356 template class AbstractTetrahedralElement<0,2>;
00357 template class AbstractTetrahedralElement<1,2>;
00358 template class AbstractTetrahedralElement<2,2>;
00359 template class AbstractTetrahedralElement<0,3>;
00360 template class AbstractTetrahedralElement<1,3>;
00361 template class AbstractTetrahedralElement<2,3>;
00362 template class AbstractTetrahedralElement<3,3>;