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 "Element.hpp"
00037
00038 #include <cfloat>
00039 #include <cassert>
00040
00042
00044
00045 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00046 Element<ELEMENT_DIM, SPACE_DIM>::Element(unsigned index, const std::vector<Node<SPACE_DIM>*>& rNodes, bool registerWithNodes)
00047 : AbstractTetrahedralElement<ELEMENT_DIM, SPACE_DIM>(index, rNodes)
00048 {
00049 if (registerWithNodes)
00050 {
00051 RegisterWithNodes();
00052 }
00053 }
00054
00055 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00056 Element<ELEMENT_DIM, SPACE_DIM>::Element(const Element& rElement, const unsigned index)
00057 {
00058 *this = rElement;
00059 this->mIndex = index;
00060
00061 RegisterWithNodes();
00062 }
00063
00064 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00065 void Element<ELEMENT_DIM, SPACE_DIM>::RegisterWithNodes()
00066 {
00067 for (unsigned i=0; i<this->mNodes.size(); i++)
00068 {
00069 this->mNodes[i]->AddElement(this->mIndex);
00070 }
00071 }
00072
00073 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00074 void Element<ELEMENT_DIM, SPACE_DIM>::MarkAsDeleted()
00075 {
00076 this->mIsDeleted = true;
00077
00078 for (unsigned i=0; i<this->GetNumNodes(); i++)
00079 {
00080 this->mNodes[i]->RemoveElement(this->mIndex);
00081 }
00082 }
00083
00088 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00089 void Element<ELEMENT_DIM, SPACE_DIM>::UpdateNode(const unsigned& rIndex, Node<SPACE_DIM>* pNode)
00090 {
00091 assert(rIndex < this->mNodes.size());
00092
00093
00094 this->mNodes[rIndex]->RemoveElement(this->mIndex);
00095
00096
00097 this->mNodes[rIndex] = pNode;
00098
00099
00100 this->mNodes[rIndex]->AddElement(this->mIndex);
00101 }
00102
00103 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00104 void Element<ELEMENT_DIM, SPACE_DIM>::ResetIndex(unsigned index)
00105 {
00106
00107 for (unsigned i=0; i<this->GetNumNodes(); i++)
00108 {
00109
00110 this->mNodes[i]->RemoveElement(this->mIndex);
00111 }
00112
00113 this->mIndex=index;
00114 RegisterWithNodes();
00115 }
00116
00117 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00118 c_vector<double,SPACE_DIM+1> Element<ELEMENT_DIM, SPACE_DIM>::CalculateCircumsphere(c_matrix<double, SPACE_DIM, ELEMENT_DIM>& rJacobian, c_matrix<double, ELEMENT_DIM, SPACE_DIM>& rInverseJacobian)
00119 {
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129 assert(ELEMENT_DIM == SPACE_DIM);
00130 c_vector<double, ELEMENT_DIM> rhs;
00131
00132 for (unsigned j=0; j<ELEMENT_DIM; j++)
00133 {
00134 double squared_location=0.0;
00135 for (unsigned i=0; i<SPACE_DIM; i++)
00136 {
00137
00138 squared_location += rJacobian(i,j)*rJacobian(i,j);
00139 }
00140 rhs[j]=squared_location/2.0;
00141 }
00142
00143 c_vector<double, SPACE_DIM> centre;
00144 centre = prod(rhs, rInverseJacobian);
00145 c_vector<double, SPACE_DIM+1> circum;
00146 double squared_radius = 0.0;
00147 for (unsigned i=0; i<SPACE_DIM; i++)
00148 {
00149 circum[i] = centre[i] + this->GetNodeLocation(0,i);
00150 squared_radius += centre[i]*centre[i];
00151 }
00152 circum[SPACE_DIM] = squared_radius;
00153
00154 return circum;
00155 }
00156
00162 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00163 double Element<ELEMENT_DIM, SPACE_DIM>::CalculateQuality()
00164 {
00165 assert(SPACE_DIM == ELEMENT_DIM);
00166 if (SPACE_DIM == 1)
00167 {
00168 return 1.0;
00169 }
00170
00171 c_matrix<double, SPACE_DIM, ELEMENT_DIM> jacobian;
00172 c_matrix<double, ELEMENT_DIM, SPACE_DIM> jacobian_inverse;
00173 double jacobian_determinant;
00174
00175 this->CalculateInverseJacobian(jacobian, jacobian_determinant, jacobian_inverse);
00176
00177 c_vector<double, SPACE_DIM+1> circum=CalculateCircumsphere(jacobian, jacobian_inverse);
00178 if (SPACE_DIM == 2)
00179 {
00180
00181
00182
00183
00184
00185
00186
00187 return 2.0*jacobian_determinant/(3.0*sqrt(3.0)*circum[SPACE_DIM]);
00188 }
00189 assert(SPACE_DIM == 3);
00190
00191
00192
00193
00194
00195
00196
00197
00198 return (3.0*sqrt(3.0)*jacobian_determinant)
00199 /(16.0*circum[SPACE_DIM]*sqrt(circum[SPACE_DIM]));
00200 }
00201
00202 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00203 c_vector <double, 2> Element<ELEMENT_DIM, SPACE_DIM>::CalculateMinMaxEdgeLengths()
00204 {
00205 c_vector <double, 2> min_max;
00206 min_max[0] = DBL_MAX;
00207 min_max[1] = 0.0;
00208 for (unsigned i=0; i<=ELEMENT_DIM; i++)
00209 {
00210 c_vector<double, SPACE_DIM> loc_i = this->GetNodeLocation(i);
00211 for (unsigned j=i+1; j<=ELEMENT_DIM; j++)
00212 {
00213 double length = norm_2(this->GetNodeLocation(j) - loc_i);
00214 if (length < min_max[0])
00215 {
00216 min_max[0] = length;
00217 }
00218 if (length > min_max[1])
00219 {
00220 min_max[1] = length;
00221 }
00222 }
00223 }
00224 return min_max;
00225 }
00226
00227 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00228 c_vector<double, SPACE_DIM+1> Element<ELEMENT_DIM, SPACE_DIM>::CalculateInterpolationWeights(const ChastePoint<SPACE_DIM>& rTestPoint)
00229 {
00230
00231 assert(ELEMENT_DIM == SPACE_DIM);
00232
00233 c_vector<double, SPACE_DIM+1> weights;
00234
00235 c_vector<double, SPACE_DIM> xi=CalculateXi(rTestPoint);
00236
00237
00238 weights[0]=1.0;
00239 for (unsigned i=1; i<=SPACE_DIM; i++)
00240 {
00241 weights[0] -= xi[i-1];
00242 weights[i] = xi[i-1];
00243 }
00244 return weights;
00245 }
00246
00247 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00248 c_vector<double, SPACE_DIM+1> Element<ELEMENT_DIM, SPACE_DIM>::CalculateInterpolationWeightsWithProjection(const ChastePoint<SPACE_DIM>& rTestPoint)
00249 {
00250
00251 assert(ELEMENT_DIM == SPACE_DIM);
00252
00253 c_vector<double, SPACE_DIM+1> weights = CalculateInterpolationWeights(rTestPoint);
00254
00255
00256 bool negative_weight = false;
00257
00258 for (unsigned i=0; i<=SPACE_DIM; i++)
00259 {
00260 if (weights[i] < 0.0)
00261 {
00262 weights[i] = 0.0;
00263
00264 negative_weight = true;
00265 }
00266 }
00267
00268 if (negative_weight == false)
00269 {
00270
00271 return weights;
00272 }
00273
00274
00275
00276
00277 double sum = norm_1 (weights);
00278
00279
00280
00281 assert( sum + DBL_EPSILON >= 1.0);
00282
00283
00284 weights = weights/sum;
00285
00286 return weights;
00287 }
00288
00289 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00290 c_vector<double, SPACE_DIM> Element<ELEMENT_DIM, SPACE_DIM>::CalculateXi(const ChastePoint<SPACE_DIM>& rTestPoint)
00291 {
00292
00293 assert(ELEMENT_DIM == SPACE_DIM);
00294
00295
00298 c_vector<double, SPACE_DIM> test_location=rTestPoint.rGetLocation()-this->GetNodeLocation(0);
00299
00300
00301 c_matrix<double, SPACE_DIM, ELEMENT_DIM> jacobian;
00302 c_matrix<double, ELEMENT_DIM, SPACE_DIM> inverse_jacobian;
00303 double jacobian_determinant;
00304
00306 this->CalculateInverseJacobian(jacobian, jacobian_determinant, inverse_jacobian);
00307
00308 return prod(inverse_jacobian, test_location);
00309 }
00310
00311
00312 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00313 bool Element<ELEMENT_DIM, SPACE_DIM>::IncludesPoint(const ChastePoint<SPACE_DIM>& rTestPoint, bool strict)
00314 {
00315
00316 assert(ELEMENT_DIM == SPACE_DIM);
00317
00318 c_vector<double, SPACE_DIM+1> weights=CalculateInterpolationWeights(rTestPoint);
00319
00320
00321
00322 for (unsigned i=0; i<=SPACE_DIM; i++)
00323 {
00324 if (strict)
00325 {
00326
00327 if (weights[i] <= 2*DBL_EPSILON)
00328 {
00329 return false;
00330 }
00331 }
00332 else
00333 {
00334
00335 if (weights[i] < -2*DBL_EPSILON)
00336 {
00337 return false;
00338 }
00339 }
00340 }
00341 return true;
00342 }
00343
00345
00347
00348 template class Element<1,1>;
00349 template class Element<1,2>;
00350 template class Element<1,3>;
00351 template class Element<2,2>;
00352 template class Element<2,3>;
00353 template class Element<3,3>;