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