diff --git a/Geo/MElement.cpp b/Geo/MElement.cpp index d58c857965fd0a9986be6bad026e7143738b4b11..eda15b5d7c5c3b34bcc4227bf2d84bf3010e5a56 100644 --- a/Geo/MElement.cpp +++ b/Geo/MElement.cpp @@ -337,36 +337,31 @@ std::string MElement::getInfoString() return std::string(tmp); } -double MElement::getJacobian(double u, double v, double w, double jac[3][3]) +static double _computeDeterminantAndRegularize(MElement *ele, double jac[3][3]) { - - const gmshFunctionSpace* fs = getFunctionSpace(); - - jac[0][0] = jac[0][1] = jac[0][2] = 0.; - jac[1][0] = jac[1][1] = jac[1][2] = 0.; - jac[2][0] = jac[2][1] = jac[2][2] = 0.; - - double gsf[256][3]; - fs->df(u,v,w,gsf); - for (int i=0;i<getNumVertices();i++) { - - const MVertex* v = getVertex(i); - double* gg = gsf[i]; - - for (int j=0;j<3;j++) { - jac[j][0] += v->x() * gg[j]; - jac[j][1] += v->y() * gg[j]; - jac[j][2] += v->z() * gg[j]; - } - } - double dJ = 0; - switch (fs->monomials.size2()) { + switch (ele->getDim()) { case 1: { - dJ = sqrt(jac[0][0] * jac[0][0] + jac[1][1] * jac[0][0] + jac[2][2] * jac[2][2]); + dJ = sqrt(SQU(jac[0][0]) + SQU(jac[0][1]) + SQU(jac[0][2])); + + // regularize matrix + double a[3], b[3], c[3]; + a[0] = ele->getVertex(1)->x() - ele->getVertex(0)->x(); + a[1] = ele->getVertex(1)->y() - ele->getVertex(0)->y(); + a[2] = ele->getVertex(1)->z() - ele->getVertex(0)->z(); + if((fabs(a[0]) >= fabs(a[1]) && fabs(a[0]) >= fabs(a[2])) || + (fabs(a[1]) >= fabs(a[0]) && fabs(a[1]) >= fabs(a[2]))) { + b[0] = a[1]; b[1] = -a[0]; b[2] = 0.; + } + else { + b[0] = 0.; b[1] = a[2]; b[2] = -a[1]; + } + prodve(a, b, c); + jac[1][0] = b[0]; jac[1][1] = b[1]; jac[1][2] = b[2]; + jac[2][0] = c[0]; jac[2][1] = c[1]; jac[2][2] = c[2]; break; } case 2: @@ -374,6 +369,18 @@ double MElement::getJacobian(double u, double v, double w, double jac[3][3]) dJ = sqrt(SQU(jac[0][0] * jac[1][1] - jac[0][1] * jac[1][0]) + SQU(jac[0][2] * jac[1][0] - jac[0][0] * jac[1][2]) + SQU(jac[0][1] * jac[1][2] - jac[0][2] * jac[1][1])); + + // regularize matrix + double a[3], b[3], c[3]; + a[0] = jac[0][0]; + a[1] = jac[0][1]; + a[2] = jac[0][2]; + b[0] = jac[1][0]; + b[1] = jac[1][1]; + b[2] = jac[1][2]; + prodve(a, b, c); + norme(c); + jac[2][0] = c[0]; jac[2][1] = c[1]; jac[2][2] = c[2]; break; } case 3: @@ -387,112 +394,88 @@ double MElement::getJacobian(double u, double v, double w, double jac[3][3]) return dJ; } - - -double MElement::getPrimaryJacobian(double u, double v, double w, double jac[3][3]) +double MElement::getJacobian(double u, double v, double w, double jac[3][3]) { - - const gmshFunctionSpace* fs = getFunctionSpace(1); + const gmshFunctionSpace* fs = getFunctionSpace(); jac[0][0] = jac[0][1] = jac[0][2] = 0.; jac[1][0] = jac[1][1] = jac[1][2] = 0.; jac[2][0] = jac[2][1] = jac[2][2] = 0.; double gsf[256][3]; - fs->df(u,v,w,gsf); - - for (int i=0;i<getNumPrimaryVertices();i++) { - + fs->df(u, v, w, gsf); + for (int i = 0; i < getNumVertices(); i++) { const MVertex* v = getVertex(i); double* gg = gsf[i]; - - for (int j=0;j<3;j++) { + for (int j = 0; j < 3; j++) { jac[j][0] += v->x() * gg[j]; jac[j][1] += v->y() * gg[j]; jac[j][2] += v->z() * gg[j]; } } - double dJ = 0; + return _computeDeterminantAndRegularize(this, jac); +} + +double MElement::getPrimaryJacobian(double u, double v, double w, double jac[3][3]) +{ + const gmshFunctionSpace* fs = getFunctionSpace(1); - switch (fs->monomials.size2()) { + jac[0][0] = jac[0][1] = jac[0][2] = 0.; + jac[1][0] = jac[1][1] = jac[1][2] = 0.; + jac[2][0] = jac[2][1] = jac[2][2] = 0.; - case 1: - { - dJ = sqrt(jac[0][0] * jac[0][0] + jac[0][0] * jac[0][0] + jac[0][0] * jac[0][0]); - break; - } - case 2: - { - dJ = sqrt(SQU(jac[0][0] * jac[1][1] - jac[0][1] * jac[1][0]) + - SQU(jac[0][2] * jac[1][0] - jac[0][0] * jac[1][2]) + - SQU(jac[0][1] * jac[1][2] - jac[0][2] * jac[1][1])); - break; - } - case 3: - { - dJ = fabs(jac[0][0] * jac[1][1] * jac[2][2] + jac[0][2] * jac[1][0] * jac[2][1] + - jac[0][1] * jac[1][2] * jac[2][0] - jac[0][2] * jac[1][1] * jac[2][0] - - jac[0][0] * jac[1][2] * jac[2][1] - jac[0][1] * jac[1][0] * jac[2][2]); - break; + double gsf[256][3]; + fs->df(u, v, w, gsf); + for(int i = 0; i < getNumPrimaryVertices(); i++) { + const MVertex* v = getVertex(i); + double* gg = gsf[i]; + for (int j = 0; j < 3; j++) { + jac[j][0] += v->x() * gg[j]; + jac[j][1] += v->y() * gg[j]; + jac[j][2] += v->z() * gg[j]; } } - return dJ; -} - -void MElement::pnt(double uu, double vv, double ww, SPoint3 &p) { + return _computeDeterminantAndRegularize(this, jac); +} - double x=0.; - double y=0.; - double z=0.; - +void MElement::pnt(double uu, double vv, double ww, SPoint3 &p) +{ + double x = 0., y = 0., z = 0.; const gmshFunctionSpace* fs = getFunctionSpace(); - - if (fs) { - + if(fs){ double sf[256]; - fs->f(uu,vv,ww,sf); - - for (int j=0;j<getNumVertices();j++) { + fs->f(uu, vv, ww, sf); + for (int j = 0; j < getNumVertices(); j++) { const MVertex* v = getVertex(j); x += sf[j] * v->x(); y += sf[j] * v->y(); z += sf[j] * v->z(); } } - else Msg::Fatal("Could not find function space\n"); - - p = SPoint3(x,y,z); - + else + Msg::Error("Could not find function space"); + p = SPoint3(x, y, z); } -void MElement::primaryPnt(double uu, double vv, double ww, SPoint3 &p) { - - double x=0.; - double y=0.; - double z=0.; - +void MElement::primaryPnt(double uu, double vv, double ww, SPoint3 &p) +{ + double x = 0., y = 0., z = 0.; const gmshFunctionSpace* fs = getFunctionSpace(1); - - if (fs) { - + if(fs){ double sf[256]; - fs->f(uu,vv,ww,sf); - if (getNumPrimaryVertices() != 4) printf("Incorrect number of vertices %d\n",getNumPrimaryVertices() - ); - - - for (int j=0;j<getNumPrimaryVertices();j++) { + fs->f(uu, vv, ww, sf); + if (getNumPrimaryVertices() != 4) + Msg::Error("Incorrect number of vertices %d", getNumPrimaryVertices()); + for (int j = 0; j < getNumPrimaryVertices(); j++) { const MVertex* v = getVertex(j); x += sf[j] * v->x(); y += sf[j] * v->y(); z += sf[j] * v->z(); } } - p = SPoint3(x,y,z); - } void MElement::xyz2uvw(double xyz[3], double uvw[3]) @@ -902,7 +885,10 @@ const gmshFunctionSpace* MLine::getFunctionSpace(int o) const { case 3: return &gmshFunctionSpaces::find(MSH_LIN_4); break; case 4: return &gmshFunctionSpaces::find(MSH_LIN_5); break; case 5: return &gmshFunctionSpaces::find(MSH_LIN_6); break; - default: Msg::Error("Order %d line point interpolation not implemented", getPolynomialOrder()); break; + default: + Msg::Error("Order %d line point interpolation not implemented", + getPolynomialOrder()); + break; } return NULL; } diff --git a/Geo/MElement.h b/Geo/MElement.h index 785e14ec06808a61c0f5e867d062df64021d54d1..3ca34e483c465ead312025c9edec9d7d48ebacd5 100644 --- a/Geo/MElement.h +++ b/Geo/MElement.h @@ -102,9 +102,7 @@ class MElement // get the number of primary vertices (first-order element) int getNumPrimaryVertices() { - return getNumVertices() - - getNumEdgeVertices() - - getNumFaceVertices() - + return getNumVertices() - getNumEdgeVertices() - getNumFaceVertices() - getNumVolumeVertices(); } @@ -141,11 +139,10 @@ class MElement virtual double minEdge(); // get the quality measures - virtual double rhoShapeMeasure(); virtual double gammaShapeMeasure(){ return 0.; } virtual double etaShapeMeasure(){ return 0.; } - virtual double distoShapeMeasure() {return 1.0;} + virtual double distoShapeMeasure(){ return 1.0; } // compute the barycenter virtual SPoint3 barycenter(); @@ -162,28 +159,31 @@ class MElement // return an information string for the element virtual std::string getInfoString(); - virtual const gmshFunctionSpace* getFunctionSpace(int ord = -1) const { - Msg::Fatal("Function space not implemented for element %s",getStringForPOS()); - return NULL; + // get the function space for the element + virtual const gmshFunctionSpace* getFunctionSpace(int ord = -1) const + { + Msg::Fatal("Function space not implemented for element %s", getStringForPOS()); + return 0; } // return the interpolating nodal shape function associated with // node num, evaluated at point (u,v,w) in parametric coordinates - virtual void getShapeFunction(int num, double u, double v, double w,double &s); + virtual void getShapeFunction(int num, double u, double v, double w, double &s); // return the gradient of of the nodal shape function associated // with node num, evaluated at point (u,v,w) in parametric // coordinates - virtual void getGradShapeFunction(int num, double u, double v, double w,double s[3]); + virtual void getGradShapeFunction(int num, double u, double v, double w, double s[3]); // return the Jacobian of the element evaluated at point (u,v,w) in // parametric coordinates - double getJacobian(double u, double v, double w, double jac[3][3]); double getPrimaryJacobian(double u, double v, double w, double jac[3][3]); - virtual void pnt (double u,double v,double w,SPoint3 &p); - virtual void primaryPnt(double u,double v,double w,SPoint3 &p); + // get the point in cartesian coordinates corresponding to the point + // (u,v,w) in parametric coordinates + virtual void pnt(double u, double v, double w, SPoint3 &p); + virtual void primaryPnt(double u, double v, double w, SPoint3 &p); // invert the parametrisation virtual void xyz2uvw(double xyz[3], double uvw[3]); @@ -351,17 +351,13 @@ class MLine : public MElement { { MVertex *tmp = _v[0]; _v[0] = _v[1]; _v[1] = tmp; } - - virtual const gmshFunctionSpace* getFunctionSpace(int=-1) const; - virtual bool isInside(double u, double v, double w, double tol=1.e-8) { if(u < -(1. + tol) || u > (1. + tol)) return false; return true; } - virtual void getIntegrationPoints(int pOrder, int *npts, IntPt **pts) const; }; @@ -405,14 +401,12 @@ class MLine3 : public MLine { }; _getEdgeRep(getVertex(e[num][0]), getVertex(e[num][1]), x, y, z, n); } - virtual void getEdgeVertices(const int num, std::vector<MVertex*> &v) const { v.resize(3); MLine::_getEdgeVertices(v); v[2] = _vs[0]; } - virtual int getTypeForMSH() const { return MSH_LIN_3; } virtual int getTypeForUNV() const { return 24; } // parabolic beam virtual int getTypeForVTK() const { return 21; } @@ -568,17 +562,13 @@ class MTriangle : public MElement { { MVertex *tmp = _v[1]; _v[1] = _v[2]; _v[2] = tmp; } - - virtual const gmshFunctionSpace* getFunctionSpace(int=-1) const; - virtual bool isInside(double u, double v, double w, double tol=1.e-8) { if(u < (-tol) || v < (-tol) || u > ((1. + tol) - v)) return false; return true; } - virtual void getIntegrationPoints(int pOrder, int *npts, IntPt **pts) const; virtual SPoint3 circumcenter(); private: @@ -1192,7 +1182,6 @@ class MTetrahedron : public MElement { return false; return true; } - virtual void getIntegrationPoints(int pOrder, int *npts, IntPt **pts) const; virtual SPoint3 circumcenter(); private: