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 #include "Element.hpp"
00032
00033 #include <cassert>
00034
00035
00037
00039
00040
00041 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00042 Element<ELEMENT_DIM, SPACE_DIM>::Element(unsigned index, std::vector<Node<SPACE_DIM>*> nodes)
00043 : AbstractTetrahedralElement<ELEMENT_DIM, SPACE_DIM>(index, nodes)
00044 {
00045 RegisterWithNodes();
00046 }
00047
00048 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00049 Element<ELEMENT_DIM, SPACE_DIM>::Element(const Element& rElement, const unsigned index)
00050 {
00051 *this = rElement;
00052 this->mIndex = index;
00053
00054 RegisterWithNodes();
00055 }
00056
00057 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00058 void Element<ELEMENT_DIM, SPACE_DIM>::RegisterWithNodes()
00059 {
00060 for (unsigned i=0; i<this->mNodes.size(); i++)
00061 {
00062 this->mNodes[i]->AddElement(this->mIndex);
00063 }
00064 }
00065
00066 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00067 void Element<ELEMENT_DIM, SPACE_DIM>::MarkAsDeleted()
00068 {
00069 this->mIsDeleted = true;
00070
00071 for (unsigned i=0; i<this->GetNumNodes(); i++)
00072 {
00073 this->mNodes[i]->RemoveElement(this->mIndex);
00074 }
00075 }
00076
00081 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00082 void Element<ELEMENT_DIM, SPACE_DIM>::UpdateNode(const unsigned& rIndex, Node<SPACE_DIM>* pNode)
00083 {
00084 assert(rIndex < this->mNodes.size());
00085
00086
00087 this->mNodes[rIndex]->RemoveElement(this->mIndex);
00088
00089
00090 this->mNodes[rIndex] = pNode;
00091
00092
00093 this->mNodes[rIndex]->AddElement(this->mIndex);
00094 }
00095
00096 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00097 void Element<ELEMENT_DIM, SPACE_DIM>::ResetIndex(unsigned index)
00098 {
00099
00100 for (unsigned i=0; i<this->GetNumNodes(); i++)
00101 {
00102
00103 this->mNodes[i]->RemoveElement(this->mIndex);
00104 }
00105
00106 this->mIndex=index;
00107 RegisterWithNodes();
00108 }
00109
00110 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00111 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)
00112 {
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122 assert(ELEMENT_DIM == SPACE_DIM);
00123 c_vector<double, ELEMENT_DIM> rhs;
00124
00125 for (unsigned j=0; j<ELEMENT_DIM; j++)
00126 {
00127 double squared_location=0.0;
00128 for (unsigned i=0; i<SPACE_DIM; i++)
00129 {
00130
00131 squared_location += rJacobian(i,j)*rJacobian(i,j);
00132 }
00133 rhs[j]=squared_location/2.0;
00134 }
00135
00136 c_vector<double, SPACE_DIM> centre;
00137 centre = prod(rhs, rInverseJacobian);
00138 c_vector<double, SPACE_DIM+1> circum;
00139 double squared_radius = 0.0;
00140 for (unsigned i=0; i<SPACE_DIM; i++)
00141 {
00142 circum[i] = centre[i] + this->GetNodeLocation(0,i);
00143 squared_radius += centre[i]*centre[i];
00144 }
00145 circum[SPACE_DIM] = squared_radius;
00146
00147 return circum;
00148 }
00149
00155 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00156 double Element<ELEMENT_DIM, SPACE_DIM>::CalculateQuality()
00157 {
00158 assert(SPACE_DIM == ELEMENT_DIM);
00159 if (SPACE_DIM == 1)
00160 {
00161 return 1.0;
00162 }
00163
00164 c_matrix<double, SPACE_DIM, ELEMENT_DIM> jacobian;
00165 c_matrix<double, ELEMENT_DIM, SPACE_DIM> jacobian_inverse;
00166 double jacobian_determinant;
00167
00168 CalculateInverseJacobian(jacobian, jacobian_determinant, jacobian_inverse);
00169
00170 c_vector<double, SPACE_DIM+1> circum=CalculateCircumsphere(jacobian, jacobian_inverse);
00171 if (SPACE_DIM == 2)
00172 {
00173
00174
00175
00176
00177
00178
00179
00180 return 2.0*jacobian_determinant/(3.0*sqrt(3)*circum[SPACE_DIM]);
00181 }
00182 assert(SPACE_DIM == 3);
00183
00184
00185
00186
00187
00188
00189
00190
00191 return (3.0*sqrt(3.0)*jacobian_determinant)
00192 /(16.0*circum[SPACE_DIM]*sqrt(circum[SPACE_DIM]));
00193 }
00194
00195 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00196 c_vector<double, SPACE_DIM+1> Element<ELEMENT_DIM, SPACE_DIM>::CalculateInterpolationWeights(ChastePoint<SPACE_DIM> testPoint)
00197 {
00198
00199 assert(ELEMENT_DIM == SPACE_DIM);
00200
00201 c_vector<double, SPACE_DIM+1> weights;
00202
00203 c_vector<double, SPACE_DIM> psi=CalculatePsi(testPoint);
00204
00205
00206 weights[0]=1.0;
00207 for (unsigned i=1; i<=SPACE_DIM; i++)
00208 {
00209 weights[0] -= psi[i-1];
00210 weights[i] = psi[i-1];
00211 }
00212 return weights;
00213 }
00214
00220 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00221 c_vector<double, SPACE_DIM+1> Element<ELEMENT_DIM, SPACE_DIM>::CalculateInterpolationWeightsWithProjection(ChastePoint<SPACE_DIM> testPoint)
00222 {
00223
00224 assert(ELEMENT_DIM == SPACE_DIM);
00225
00226 c_vector<double, SPACE_DIM+1> weights = CalculateInterpolationWeights(testPoint);
00227
00228
00229 bool negative_weight = false;
00230
00231 for (unsigned i=0; i<=SPACE_DIM; i++)
00232 {
00233 if (weights[i] < 0.0)
00234 {
00235 weights[i] = 0.0;
00236
00237 negative_weight = true;
00238 }
00239 }
00240
00241 if (negative_weight == false)
00242 {
00243
00244 return weights;
00245 }
00246
00247
00248
00249
00250 double sum = norm_1 (weights);
00251
00252
00253
00254 assert( sum + DBL_EPSILON >= 1.0);
00255
00256
00257 weights = weights/sum;
00258
00259 return weights;
00260 }
00261
00262 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00263 c_vector<double, SPACE_DIM> Element<ELEMENT_DIM, SPACE_DIM>::CalculatePsi(ChastePoint<SPACE_DIM> testPoint)
00264 {
00265
00266 assert(ELEMENT_DIM == SPACE_DIM);
00267
00268
00269 c_vector<double, SPACE_DIM> test_location=testPoint.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 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(ChastePoint<SPACE_DIM> testPoint, bool strict)
00285 {
00286
00287 assert(ELEMENT_DIM == SPACE_DIM);
00288
00289 c_vector<double, SPACE_DIM+1> weights=CalculateInterpolationWeights(testPoint);
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>;