00001
00029 #ifndef TRIANGLE
00030 #define TRIANGLE
00031
00032 #include "AuxDefs.h"
00033 #include "ElementGeometry.h"
00034 #include "Segment.h"
00035
00036 #include <cmath>
00037 #include <cassert>
00038
00039
00040
00069 template<size_t SPD>
00070 class Triangle: public AbstractGeom<SPD> {
00071 public:
00073 Triangle (const std::vector<double>& globalCoordVec, const std::vector<GlobalNodalIndex>& connectivity)
00074 :AbstractGeom<SPD> (globalCoordVec, connectivity) {
00075 assert (connectivity.size () == 3);
00076 }
00077
00078
00079 inline virtual ~Triangle(){}
00080
00081 Triangle(const Triangle<SPD> & that) : AbstractGeom<SPD>(that) {
00082 }
00083
00084 virtual Triangle<SPD>* clone() const {
00085 return new Triangle<SPD>(*this);
00086 }
00087
00088
00089 inline const size_t getNumVertices() const { return 3; }
00090
00091 inline const std::string getPolytopeName() const { return "TRIANGLE"; }
00092
00093 inline const size_t getParametricDimension() const { return 2; }
00094
00095 inline const size_t getEmbeddingDimension() const { return SPD; }
00096
00097 void map(const double * X, double *Y) const;
00098
00099 void dMap(const double * X, double *DY, double &Jac) const;
00100
00101 inline size_t getNumFaces() const { return 3; }
00102
00103 virtual const double getInRadius(void) const;
00104
00105 virtual const double getOutRadius(void) const;
00106
00107 virtual Segment<SPD> * getFaceGeometry(size_t e) const;
00108
00109 virtual void computeNormal (size_t e, std::vector<double>& vNormal) const;
00110
00111 private:
00112 static const size_t SegmentNodes[];
00113 static const double ParamCoord[];
00114 };
00115
00116
00117
00118
00119 template <size_t SPD>
00120 const size_t Triangle<SPD>::SegmentNodes[] = {0,1,1,2,2,0};
00121
00122 template <size_t SPD>
00123 const double Triangle<SPD>::ParamCoord[] = {1,0,0,1,0,0};
00124
00125
00126 template<size_t SPD>
00127 void Triangle<SPD>::map(const double * X, double *Y) const
00128 {
00129 for(size_t i=0; i<SPD; i++)
00130 Y[i] = X[0]*AbstractGeom<SPD>::getCoordinate(0,i) + X[1]*AbstractGeom<SPD>::getCoordinate(1,i) + (1-X[0]-X[1])*AbstractGeom<SPD>::getCoordinate(2,i);
00131
00132 return;
00133 }
00134
00135
00136
00137
00138 template<size_t SPD>
00139 void Triangle<SPD>::dMap(const double * X, double *DY, double &Jac) const
00140 {
00141 for(size_t i=0; i<SPD; i++)
00142 {
00143 DY[ i] = AbstractGeom<SPD>::getCoordinate(0,i) - AbstractGeom<SPD>::getCoordinate(2,i);
00144 DY[SPD+i] = AbstractGeom<SPD>::getCoordinate(1,i) - AbstractGeom<SPD>::getCoordinate(2,i);
00145 }
00146
00147 double g11=0;
00148 double g22=0;
00149 double g12=0;
00150
00151 for(size_t i=0; i<SPD; i++)
00152 {
00153 g11 += DY[i]*DY[i];
00154 g22 += DY[SPD+i]*DY[SPD+i];
00155 g12 += DY[SPD+i]*DY[i];
00156 }
00157
00158 Jac=sqrt(g11*g22-g12*g12);
00159
00160 return;
00161 }
00162
00163
00164 template<size_t SPD>
00165 Segment<SPD> * Triangle<SPD>::getFaceGeometry(size_t e) const
00166 {
00167 std::vector<GlobalNodalIndex> conn(2);
00168 switch(e)
00169 {
00170 case 0:
00171 conn[0] = AbstractGeom<SPD>::getConnectivity ()[0];
00172 conn[1] = AbstractGeom<SPD>::getConnectivity ()[1];
00173 break;
00174
00175 case 1:
00176 conn[0] = AbstractGeom<SPD>::getConnectivity ()[1];
00177 conn[1] = AbstractGeom<SPD>::getConnectivity ()[2];
00178 break;
00179
00180 case 2:
00181 conn[0] = AbstractGeom<SPD>::getConnectivity ()[2];
00182 conn[1] = AbstractGeom<SPD>::getConnectivity ()[0];
00183 break;
00184
00185 default:
00186 return 0;
00187 }
00188
00189 return new Segment<SPD> (AbstractGeom<SPD>::getGlobalCoordVec (), conn);
00190 }
00191
00192 template<size_t SPD>
00193 const double Triangle<SPD>:: getInRadius(void) const {
00194 double a,b,c,s;
00195 a = b = c = s = 0.0;
00196 for(size_t i=0; i<SPD; i++) {
00197 a += (AbstractGeom<SPD>::getCoordinate(1,i) - AbstractGeom<SPD>::getCoordinate(0,i))*
00198 (AbstractGeom<SPD>::getCoordinate(1,i) - AbstractGeom<SPD>::getCoordinate(0,i)) ;
00199 b += (AbstractGeom<SPD>::getCoordinate(2,i) - AbstractGeom<SPD>::getCoordinate(1,i))*
00200 (AbstractGeom<SPD>::getCoordinate(2,i) - AbstractGeom<SPD>::getCoordinate(1,i)) ;
00201 c += (AbstractGeom<SPD>::getCoordinate(0,i) - AbstractGeom<SPD>::getCoordinate(2,i))*
00202 (AbstractGeom<SPD>::getCoordinate(0,i) - AbstractGeom<SPD>::getCoordinate(2,i)) ;
00203 }
00204 a = sqrt(a);
00205 b = sqrt(b);
00206 c = sqrt(c);
00207 s = (a + b + c)/2.0;
00208 return(2.0*sqrt(s*(s-a)*(s-b)*(s-c))/(a+b+c));
00209 };
00210
00211
00212 template<size_t SPD>
00213 const double Triangle<SPD>:: getOutRadius(void) const {
00214 double a,b,c;
00215 a = b = c = 0.0;
00216 for(size_t i=0; i<SPD; i++) {
00217 a += (AbstractGeom<SPD>::getCoordinate(1,i) - AbstractGeom<SPD>::getCoordinate(0,i))*
00218 (AbstractGeom<SPD>::getCoordinate(1,i) - AbstractGeom<SPD>::getCoordinate(0,i)) ;
00219 b += (AbstractGeom<SPD>::getCoordinate(2,i) - AbstractGeom<SPD>::getCoordinate(1,i))*
00220 (AbstractGeom<SPD>::getCoordinate(2,i) - AbstractGeom<SPD>::getCoordinate(1,i)) ;
00221 c += (AbstractGeom<SPD>::getCoordinate(0,i) - AbstractGeom<SPD>::getCoordinate(2,i))*
00222 (AbstractGeom<SPD>::getCoordinate(0,i) - AbstractGeom<SPD>::getCoordinate(2,i)) ;
00223 }
00224 a = sqrt(a);
00225 b = sqrt(b);
00226 c = sqrt(c);
00227 return(a*b*c/sqrt((a+b+c)*(b+c-a)*(c+a-b)*(a+b-c)));
00228 };
00229
00230 template <size_t SPD>
00231 void Triangle<SPD>::computeNormal(size_t e, std::vector<double> &VNormal) const {
00232 double NodalCoord[4];
00233
00234 size_t n[2];
00235 double v[2];
00236
00237 n[0] = SegmentNodes[e*2];
00238 n[1] = SegmentNodes[e*2+1];
00239
00240 Triangle<SPD>::map(&Triangle<SPD>::ParamCoord[2*n[0]], NodalCoord );
00241 Triangle<SPD>::map(&Triangle<SPD>::ParamCoord[2*n[1]], NodalCoord+2);
00242
00243 v[0] = NodalCoord[2]-NodalCoord[0];
00244 v[1] = NodalCoord[3]-NodalCoord[1];
00245
00246 double norm = sqrt(v[0]*v[0]+v[1]*v[1]);
00247
00248 if(norm<=0) {
00249 std::cerr <<
00250 "The normal cannot be computed. Two vertices of a polytope seem to coincide\n";
00251 }
00252
00253 VNormal.push_back( v[1]/norm);
00254 VNormal.push_back(-v[0]/norm);
00255 }
00256
00257
00258 #endif