diff --git a/Geo/MPyramid.h b/Geo/MPyramid.h index 36bbca031974586a96d7e87ba858bf76c62b6101..836bff3b3595ff38e601f70904edd91f7e8efeb0 100644 --- a/Geo/MPyramid.h +++ b/Geo/MPyramid.h @@ -124,50 +124,6 @@ class MPyramid : public MElement { MVertex *tmp = _v[0]; _v[0] = _v[2]; _v[2] = tmp; } virtual int getVolumeSign(); - /*virtual void getShapeFunctions(double u, double v, double w, double s[], int o) - { - double r = (w != 1.) ? (u * v * w / (1. - w)) : 0.; - s[0] = 0.25 * ((1. - u) * (1. - v) - w + r); - s[1] = 0.25 * ((1. + u) * (1. - v) - w - r); - s[2] = 0.25 * ((1. + u) * (1. + v) - w + r); - s[3] = 0.25 * ((1. - u) * (1. + v) - w - r); - s[4] = w; - } - */ - virtual void getGradShapeFunctions(double u, double v, double w, double s[][3], int o) - { - if(w == 1.) { - s[0][0] = -0.25 ; - s[0][1] = -0.25 ; - s[0][2] = -0.25 ; - s[1][0] = 0.25 ; - s[1][1] = -0.25 ; - s[1][2] = -0.25 ; - s[2][0] = 0.25 ; - s[2][1] = 0.25 ; - s[2][2] = -0.25 ; - s[3][0] = -0.25 ; - s[3][1] = 0.25 ; - s[3][2] = -0.25 ; - } - else{ - s[0][0] = 0.25 * ( -(1. - v) + v * w / (1. - w)) ; - s[0][1] = 0.25 * ( -(1. - u) + u * w / (1. - w)) ; - s[0][2] = 0.25 * ( -1. + u * v / (1. - w) + u * v * w / (1. - w) / (1. - w)) ; - s[1][0] = 0.25 * ( (1. - v) - v * w / (1. - w)) ; - s[1][1] = 0.25 * ( -(1. + u) - u * w / (1. - w)) ; - s[1][2] = 0.25 * ( -1. - u * v / (1. - w) - u * v * w / (1. - w) / (1. - w)) ; - s[2][0] = 0.25 * ( (1. + v) + v * w / (1. - w)) ; - s[2][1] = 0.25 * ( (1. + u) + u * w / (1. - w)) ; - s[2][2] = 0.25 * ( -1. + u * v / (1. - w) + u * v * w / (1. - w) / (1. - w)) ; - s[3][0] = 0.25 * ( -(1. + v) - v * w / (1. - w)) ; - s[3][1] = 0.25 * ( (1. - u) - u * w / (1. - w)) ; - s[3][2] = 0.25 * ( -1. - u * v / (1. - w) - u * v * w / (1. - w) / (1. - w)) ; - } - s[4][0] = 0.; - s[4][1] = 0.; - s[4][2] = 1.; - } virtual void getNode(int num, double &u, double &v, double &w) { switch(num) { diff --git a/Numeric/BergotBasis.cpp b/Numeric/BergotBasis.cpp index 8611c1e0a7835513ec8b7fff6e2f7d55500b6f91..52ac4fa1d93ef9ccf2fbaec1840edf36f158a75b 100644 --- a/Numeric/BergotBasis.cpp +++ b/Numeric/BergotBasis.cpp @@ -3,36 +3,9 @@ // See the LICENSE.txt file for license information. Please report all // bugs and problems to <gmsh@geuz.org>. +#include <cmath> #include "BergotBasis.h" - -/*BergotBasis::BergotBasis() { - - -}*/ - - - -namespace { - -// Private function to compute value and gradients of Jacobi polynomial at 1 (the general -// implementation in class jacobiPolynomials does not handle the indefinite form) -inline void jacobiDiffOne(int alpha, int beta, int n, double *wf, double *wg) -{ - - const int fMax = std::max(n,1)+alpha; - std::vector<double> fact(fMax+1); - fact[0] = 1.; - for (int i=1;i<=fMax;i++) fact[i] = i*fact[i-1]; - wf[0] = 1.; wg[0] = 0.; - for (int k=1;k<=n;k++) { - wf[k] = fact[k+alpha]/(fact[alpha]*fact[k]); - wg[k] = 0.5*(k+alpha+beta+1)*fact[k+alpha]/(fact[alpha+1]*fact[k-1]); - } - -} - -} - +#include "MElement.h" @@ -125,12 +98,9 @@ void BergotBasis::df(double u, double v, double w, double grads[][3]) const std::vector<double> &wf = wFcts[mIJ], &wg = wGrads[mIJ]; wf.resize(kMax+1); wg.resize(kMax+1); - if (what == 1.) jacobiDiffOne(2*mIJ+2,0,kMax,&(wf[0]),&(wg[0])); - else { - JacobiPolynomials jacobi(2.*mIJ+2.,0.,kMax); - jacobi.f(what,&(wf[0])); - jacobi.df(what,&(wg[0])); - } + JacobiPolynomials jacobi(2.*mIJ+2.,0.,kMax); + jacobi.f(what,&(wf[0])); + jacobi.df(what,&(wg[0])); } // Recombine to find the shape function gradients @@ -177,7 +147,7 @@ void BergotBasis::df(double u, double v, double w, double grads[][3]) const grads[index][0] = uGrads[i] * vFcts[j] * wf[k] * powM1; grads[index][1] = uFcts[i] * vGrads[j] * wf[k] * powM1; grads[index][2] = wf[k]*powM2*(u*uGrads[i]*vFcts[j]+v*uFcts[i]*vGrads[j]) - + uFcts[i]*vFcts[j]*powM1*(2.*oMW*wg[k]-mIJ*wf[k]); + + uFcts[i]*vFcts[j]*powM1*(2.*oMW*wg[k]-mIJ*wf[k]); } } } diff --git a/Numeric/JacobianBasis.cpp b/Numeric/JacobianBasis.cpp index e21b2a1736e189c95ad3d29dffa43c3823ee5184..ab0b938ec0bdf6a8d56668d65f325fa823a3f852 100644 --- a/Numeric/JacobianBasis.cpp +++ b/Numeric/JacobianBasis.cpp @@ -1025,6 +1025,26 @@ static void generateGradShapes(JacobianBasis &jfs, const fullMatrix<double> &poi +static void generateGradShapesPyramid(JacobianBasis &jfs, const fullMatrix<double> &points, const pyramidalBasis *F) +{ + + fullMatrix<double> allDPsi; + F->df(points, allDPsi); + + const int NBez = points.size1(), NLag = allDPsi.size1(); + jfs.gradShapeMatX.resize(NBez,NLag); + jfs.gradShapeMatY.resize(NBez,NLag); + jfs.gradShapeMatZ.resize(NBez,NLag); + for (int i=0; i<NBez; i++) + for (int j=0; j<NLag; j++) { + jfs.gradShapeMatX(i,j) = allDPsi(j,3*i); + jfs.gradShapeMatY(i,j) = allDPsi(j,3*i+1); + jfs.gradShapeMatZ(i,j) = allDPsi(j,3*i+2); + } + +} + + std::map<int, bezierBasis> bezierBasis::_bbs; const bezierBasis *bezierBasis::find(int tag) { @@ -1142,6 +1162,8 @@ const JacobianBasis *JacobianBasis::find(int tag) J.bezier = bezierBasis::find(MSH_PYR_14); break; } + pyramidalBasis *F = (pyramidalBasis*)BasisFactory::create(tag); + generateGradShapesPyramid(J, J.bezier->points, F); } else { const int parentType = MElement::ParentTypeFromTag(tag), order = MElement::OrderFromTag(tag); diff --git a/Numeric/jacobiPolynomials.cpp b/Numeric/jacobiPolynomials.cpp index 7a03c9c9b1f7d37ab1f1ac8bc8b05aa0312d5edf..a8693fe5cedad3b9545ccd370e7217cbe9d494e6 100644 --- a/Numeric/jacobiPolynomials.cpp +++ b/Numeric/jacobiPolynomials.cpp @@ -4,6 +4,10 @@ // bugs and problems to <gmsh@geuz.org>. #include "jacobiPolynomials.h" +#include <cmath> +#include <iostream> + + inline double Pochhammer(double x,int n) { @@ -12,11 +16,17 @@ inline double Pochhammer(double x,int n) return result; } + + JacobiPolynomials::JacobiPolynomials(double a, double b, int o): alpha(a),beta(b),n(o),alphaPlusBeta(a+b),a2MinusB2(a*a-b*b) {} + + JacobiPolynomials::~JacobiPolynomials() {;} + + void JacobiPolynomials::f(double u, double *val) const { val[0] = 1.; @@ -37,21 +47,51 @@ void JacobiPolynomials::f(double u, double *val) const } } + + void JacobiPolynomials::df(double u, double *val) const { + + // Indeterminate form for u == -1 and u == 1 + // TODO: Extend to non-integer alpha & beta? + if ((u == 1.) || (u == -1.)) { + + // alpha or beta in formula, depending on u + int coeff = (u == 1.) ? (int)alpha : (int)beta; + + // Compute factorial + const int fMax = std::max(n,1)+coeff; + std::vector<double> fact(fMax+1); + fact[0] = 1.; + for (int i=1;i<=fMax;i++) fact[i] = i*fact[i-1]; + + // Compute formula (with appropriate sign at even orders for u == -1) + val[0] = 0.; + for (int k=1;k<=n;k++) val[k] = 0.5*(k+alphaPlusBeta+1)*fact[k+coeff]/(fact[coeff+1]*fact[k-1]); + if ((u == -1.) && (n >= 2)) for (int k=2;k<=n;k+=2) val[k] = -val[k]; + + return; + + } + + // Now general case + + // Values of the Jacobi polynomials std::vector<double> tmp(n+1); f(u,&(tmp[0])); + // First 2 values of the derivatives val[0] = 0; if (n>=1) val[1] = 0.5*(alphaPlusBeta + 2.); + // Values of the derivative for orders > 1 computed from the values of the polynomials for (int i=2;i<=n;i++) { double ii = (double) i; double aa = (2.*ii + alphaPlusBeta); double g2 = aa*(1.-u*u); double g1 = ii*(alpha - beta - aa*u); double g0 = 2.*(ii+alpha)*(ii+beta); - val[i] = (g1 * tmp[i] + g0 * tmp[i-1])/g2; } + } diff --git a/Numeric/legendrePolynomials.cpp b/Numeric/legendrePolynomials.cpp index b0cc7281c14b5b3ed8bbab47c1925d395bfee216..e5cc0cf48be4c63da9d6d5cfd04dbe02ffe63b77 100644 --- a/Numeric/legendrePolynomials.cpp +++ b/Numeric/legendrePolynomials.cpp @@ -5,11 +5,16 @@ #include "legendrePolynomials.h" -LegendrePolynomials::LegendrePolynomials(int o): n(o) { -} + +LegendrePolynomials::LegendrePolynomials(int o): n(o) {} + + + LegendrePolynomials::~LegendrePolynomials() {} + + void LegendrePolynomials::f(double u, double *val) const { val[0] = 1; @@ -26,18 +31,36 @@ void LegendrePolynomials::f(double u, double *val) const } } + + void LegendrePolynomials::df(double u, double *val) const { + + // Indeterminate form for u == -1 and u == 1 + if ((u == 1.) || (u == -1.)) { + + for (int k=0;k<=n;k++) val[k] = 0.5*k*(k+1); + if ((u == -1.) && (n >= 2)) for (int k=2;k<=n;k+=2) val[k] = -val[k]; + + return; + + } + + // Now general case + + // Values of the Legendre polynomials std::vector<double> tmp(n+1); f(u,&(tmp[0])); + // First value of the derivative val[0] = 0; double g2 = (1.-u*u); + // Values of the derivative for orders > 1 computed from the values of the polynomials for (int i=1;i<=n;i++) { double g1 = - u*i; double g0 = (double) i; - val[i] = (g1 * tmp[i] + g0 * tmp[i-1])/g2; } + } diff --git a/Numeric/nodalBasis.h b/Numeric/nodalBasis.h index da1bc0d723db5e373bfaf0d334dec90da7b45d28..4584bba32e9d8f7565361f0fabd249b974635898 100644 --- a/Numeric/nodalBasis.h +++ b/Numeric/nodalBasis.h @@ -21,11 +21,11 @@ class nodalBasis { // Basis functions evaluation virtual void f(double u, double v, double w, double *sf) const {Msg::Fatal("Not implemented");}; - virtual void f(fullMatrix<double> &coord, fullMatrix<double> &sf) const {Msg::Fatal("Not implemented");}; + virtual void f(const fullMatrix<double> &coord, fullMatrix<double> &sf) const {Msg::Fatal("Not implemented");}; // Basis functions gradients evaluation virtual void df(double u, double v, double w, double grads[][3]) const {Msg::Fatal("Not implemented");}; - virtual void df(fullMatrix<double> &coord, fullMatrix<double> &dfm) const {Msg::Fatal("Not implemented");}; + virtual void df(const fullMatrix<double> &coord, fullMatrix<double> &dfm) const {Msg::Fatal("Not implemented");}; virtual void ddf(double u, double v, double w, double grads[][3][3]) const {Msg::Fatal("Not implemented");}; virtual void dddf(double u, double v, double w, double grads[][3][3][3]) const {Msg::Fatal("Not implemented");}; diff --git a/Numeric/polynomialBasis.cpp b/Numeric/polynomialBasis.cpp index bda418798d7236708948fa4af0c03466bbb250ff..9334222f53aa690a80db01cf9e42737905645849 100644 --- a/Numeric/polynomialBasis.cpp +++ b/Numeric/polynomialBasis.cpp @@ -404,7 +404,7 @@ void polynomialBasis::f(double u, double v, double w, double *sf) const -void polynomialBasis::f(fullMatrix<double> &coord, fullMatrix<double> &sf) const +void polynomialBasis::f(const fullMatrix<double> &coord, fullMatrix<double> &sf) const { double p[1256]; sf.resize (coord.size1(), coefficients.size1()); @@ -418,7 +418,7 @@ void polynomialBasis::f(fullMatrix<double> &coord, fullMatrix<double> &sf) const -void polynomialBasis::df(fullMatrix<double> &coord, fullMatrix<double> &dfm) const +void polynomialBasis::df(const fullMatrix<double> &coord, fullMatrix<double> &dfm) const { double dfv[1256][3]; dfm.resize (coefficients.size1(), coord.size1() * 3, false); diff --git a/Numeric/polynomialBasis.h b/Numeric/polynomialBasis.h index 4444efbb899053ac4368494879d8fc25e20f0f17..0222972faa4c76414f74bfd7a60ed8f813ebed9d 100644 --- a/Numeric/polynomialBasis.h +++ b/Numeric/polynomialBasis.h @@ -89,8 +89,8 @@ class polynomialBasis : public nodalBasis ~polynomialBasis(); virtual void f(double u, double v, double w, double *sf) const; - virtual void f(fullMatrix<double> &coord, fullMatrix<double> &sf) const; - virtual void df(fullMatrix<double> &coord, fullMatrix<double> &dfm) const; + virtual void f(const fullMatrix<double> &coord, fullMatrix<double> &sf) const; + virtual void df(const fullMatrix<double> &coord, fullMatrix<double> &dfm) const; virtual void df(double u, double v, double w, double grads[][3]) const; virtual void ddf(double u, double v, double w, double hess[][3][3]) const; virtual void dddf(double u, double v, double w, double third[][3][3][3]) const; diff --git a/Numeric/pyramidalBasis.cpp b/Numeric/pyramidalBasis.cpp index 4a67e1f0f7f8fc86376c85c812b1adf21ba6cb68..c8b9f8e7537c652bca5e503e35a3dda1bb7e5d6d 100644 --- a/Numeric/pyramidalBasis.cpp +++ b/Numeric/pyramidalBasis.cpp @@ -62,7 +62,7 @@ void pyramidalBasis::f(double u, double v, double w, double *val) const -void pyramidalBasis::f(fullMatrix<double> &coord, fullMatrix<double> &sf) +void pyramidalBasis::f(const fullMatrix<double> &coord, fullMatrix<double> &sf) { const int N = bergot->size(), NPts = coord.size1(); @@ -107,7 +107,7 @@ void pyramidalBasis::df(double u, double v, double w, double grads[][3]) const -void pyramidalBasis::df(fullMatrix<double> &coord, fullMatrix<double> &dfm) const +void pyramidalBasis::df(const fullMatrix<double> &coord, fullMatrix<double> &dfm) const { const int N = bergot->size(), NPts = coord.size1(); diff --git a/Numeric/pyramidalBasis.h b/Numeric/pyramidalBasis.h index 5e7e33283695b283580bec06941c8c60accfbc89..a4cf260705392c2e6f6c47816caf0a5362fec0eb 100644 --- a/Numeric/pyramidalBasis.h +++ b/Numeric/pyramidalBasis.h @@ -27,9 +27,9 @@ class pyramidalBasis: public nodalBasis ~pyramidalBasis(); virtual void f(double u, double v, double w, double *val) const; - virtual void f(fullMatrix<double> &coord, fullMatrix<double> &sf); + virtual void f(const fullMatrix<double> &coord, fullMatrix<double> &sf); virtual void df(double u, double v, double w, double grads[][3]) const; - virtual void df(fullMatrix<double> &coord, fullMatrix<double> &dfm) const; + virtual void df(const fullMatrix<double> &coord, fullMatrix<double> &dfm) const; }; diff --git a/benchmarks/misc/testPyramidalBasis.py b/benchmarks/misc/testPyramidalBasis.py index b2c3b1c45e2abee29f1dc12cdba17e02da1f822b..417a5ee2d70a311e1a546e93db884ad0456812a8 100644 --- a/benchmarks/misc/testPyramidalBasis.py +++ b/benchmarks/misc/testPyramidalBasis.py @@ -6,7 +6,7 @@ import math # Parameters Nr = 100 -p = 8 +p = 2 @@ -144,12 +144,14 @@ polyEval(nodalCoeff,p,poly,basis.points) #for i in range(nodalCoeff.size()) : # print(" -> %g" % nodalCoeff(i)) -# Generate Nr random points in pyramid (well, Nr-1 random plus (0,0,1) to test indeterminate form) +# Generate Nr random points in pyramid (well, Nr-5 random plus vertices to test indeterminate form) uvwr = fullMatrixDouble(Nr,3) -uvwr.set(0,0,0) -uvwr.set(0,1,0) -uvwr.set(0,2,1) -for i in range(1,Nr): +uvwr.set(0,0,-1); uvwr.set(0,1,-1); uvwr.set(0,2,0) +uvwr.set(1,0,-1); uvwr.set(1,1,1); uvwr.set(1,2,0) +uvwr.set(2,0,1); uvwr.set(2,1,1); uvwr.set(2,2,0) +uvwr.set(3,0,1); uvwr.set(3,1,-1); uvwr.set(3,2,0) +uvwr.set(4,0,0); uvwr.set(4,1,0); uvwr.set(4,2,1) +for i in range(5,Nr): uvwr.set(i,0,1000) uvwr.set(i,1,1000) uvwr.set(i,2,1000)