diff --git a/Numeric/BergotBasis.cpp b/Numeric/BergotBasis.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..b0668cc617644a15e9fb58f4b39b209ceda6e911
--- /dev/null
+++ b/Numeric/BergotBasis.cpp
@@ -0,0 +1,157 @@
+#include "BergotBasis.h"
+
+BergotBasis::BergotBasis(int p): order(p) {
+  // allocate function information and fill 
+
+  iOrder = new int[size()];
+  jOrder = new int[size()];
+  kOrder = new int[size()];
+  
+  legendre = new LegendrePolynomials(order);
+
+  int index = 0;
+  for (int i=0;i<=order;i++) {
+    for (int j=0;j<=order;j++) {
+      int mIJ = std::max(i,j);
+      for (int k=0;k<= (int) (order - mIJ);k++,index++) {
+        
+        iOrder[index] = i;
+        jOrder[index] = j;
+        kOrder[index] = k;
+        
+        if (jacobi.find(mIJ) == jacobi.end()) {
+          jacobi[mIJ] = new JacobiPolynomials(2*mIJ+2,0,order);
+        }
+      }
+    }
+  }
+}
+
+BergotBasis::~BergotBasis() {
+
+  delete [] iOrder;
+  delete [] jOrder;
+  delete [] kOrder;
+  
+  delete legendre;
+  std::map<int,JacobiPolynomials*>::iterator jIter = jacobi.begin();
+  for (;jIter!=jacobi.end();++jIter) delete jIter->second;
+}
+
+
+int BergotBasis::size() const {
+  return (2*order*order*order + 9*order*order + 13*order + 6)/6;
+}
+
+
+void BergotBasis::f(double u, double v, double w, double* val) const {
+
+  double uhat = (w == 1.) ? 1 : u/(1.-w);
+  double uFcts[order+1];
+  legendre->f(uhat,uFcts);
+
+  double vhat = (w == 1.) ? 1 : v/(1.-w);
+  double vFcts[order+1];
+  legendre->f(vhat,vFcts);
+
+  double what = 2.*w - 1.;
+  std::map<int,double* > wFcts;
+  std::map<int,JacobiPolynomials*>::const_iterator jIter=jacobi.begin();
+
+  for (;jIter!=jacobi.end();jIter++) {
+    int a = jIter->first;
+    wFcts[a] = new double[order + 1];
+    double* wf = wFcts[a];
+    jIter->second->f(what,wf);
+  }
+  
+  // recombine to find shape function values 
+
+  int index = 0;
+  for (int i=0;i<=order;i++) {
+    for (int j=0;j<=order;j++) {
+      int mIJ = std::max(i,j);
+      double fact = pow_int(1-w,(int) mIJ);
+      double* wf = (wFcts.find(mIJ))->second;
+      for (int k=0;k<=(int) (order - mIJ);k++,index++) {
+        val[index] = uFcts[i] * vFcts[j] * wf[k] * fact;
+      }
+    }
+  }
+  
+  jIter=jacobi.begin();
+
+  for (;jIter!=jacobi.end();jIter++) {
+    int a = jIter->first;
+    delete [] wFcts[a];
+  }
+}
+
+void BergotBasis::df(double u, double v, double w, double grads[][3]) const {
+  double uFcts[order+1];
+  legendre->f(u,uFcts);
+  
+  double uGrads[order+1];
+  legendre->df(u,uGrads);
+
+  double vFcts[order+1];
+  legendre->f(v,vFcts);
+
+  double vGrads[order+1];
+  legendre->df(v,vGrads);
+
+
+  std::map<int,double* > wFcts;
+  std::map<int,double* > wGrads;
+  std::map<int,JacobiPolynomials*>::const_iterator jIter=jacobi.begin();
+  
+  for (;jIter!=jacobi.end();jIter++) {
+    int a = jIter->first;
+    wFcts[a] = new double[order+1]; 
+    double* wf = wFcts[a];
+    jIter->second->f(w,wf);
+    wGrads[a] = new double[order+1];
+    double* wg = wGrads[a];
+    jIter->second->df(w,wg);
+  }
+  
+  // now recombine to find the shape function gradients
+
+  int index = 0;
+  for (int i=0;i<=order;i++) {
+    for (int j=0;j<=order;j++) {
+
+      int mIJ = std::max(i,j);
+
+      double* wf = (wFcts .find(mIJ))->second;
+      double* wg = (wGrads.find(mIJ))->second;
+      
+      double wPowM2 = pow_int(1.-w,((int) mIJ) - 2);
+      double wPowM1 = wPowM2*(1.-w);
+      double wPowM0 = wPowM1*(1.-w);
+
+      for (int k=0;k<= (int) (order - mIJ);k++,index++) {
+
+        grads[index][0] = uGrads[i] * vFcts[j]  * wf[k] * wPowM1;
+
+        grads[index][1] = uFcts[i]  * vGrads[j] * wf[k] * wPowM1;
+
+        grads[index][2]  = 0;
+        grads[index][2] += u   * uGrads[i] * vFcts[j]  * wf[k] * wPowM2;
+        grads[index][2] += v   * uFcts[i]  * vGrads[j] * wf[k] * wPowM2;
+        grads[index][2] -= mIJ * uFcts[i]  * vFcts[j]  * wf[k] * wPowM1;
+        grads[index][2] +=   2 * uFcts[i]  * vFcts[j]  * wg[k] * wPowM0;
+        
+        
+      }
+    }
+  }
+  jIter=jacobi.begin();
+
+  for (;jIter!=jacobi.end();jIter++) {
+    int a = jIter->first;
+    delete [] wFcts[a];
+    delete [] wGrads[a];
+  }
+
+}
diff --git a/Numeric/BergotBasis.h b/Numeric/BergotBasis.h
new file mode 100644
index 0000000000000000000000000000000000000000..a1bc9be529d44882b127a0d5c68e8643ed5481b0
--- /dev/null
+++ b/Numeric/BergotBasis.h
@@ -0,0 +1,34 @@
+#ifndef BERGOTBASIS_H
+#define BERGOTBASIS_H
+
+#include "polynomialBasis.h"
+#include "jacobiPolynomials.h"
+#include "legendrePolynomials.h"
+
+class BergotBasis : public polynomialBasis {
+ public:
+
+  BergotBasis(int p);
+  ~BergotBasis();
+
+  void f(double u, double v, double w, double *val) const;
+  void df(double u, double v, double w, double grads[][3]) const;
+
+ private:
+  int order; //!< maximal order of surrounding functional spaces (on triangle / quad)
+
+  int *iOrder; //!< order of \f$\hat \xi \f$ polynomial 
+  int *jOrder; //!< order of \f$\hat \eta \f$ polynomial 
+  int *kOrder; //!< order of \f$\hat \zeta \f$ polynomial 
+
+  //! list of Legendre polynomials up to order p 
+  LegendrePolynomials* legendre;
+  
+  //! list of Jacobi polynomials up to order p in function of index i (\f$ \alpha = 2*i + 2\f$)
+  std::map<int,JacobiPolynomials*> jacobi;
+
+  int size() const;
+
+};
+
+#endif
diff --git a/Numeric/CMakeLists.txt b/Numeric/CMakeLists.txt
index 29ecc6f1f8b625a3f37584de1c4fcfd11e11da08..8d3f55d120ca3809c573107b7a2b1c3b7b0bb757 100644
--- a/Numeric/CMakeLists.txt
+++ b/Numeric/CMakeLists.txt
@@ -8,6 +8,7 @@ set(SRC
     fullMatrix.cpp
     polynomialBasis.cpp
     JacobianBasis.cpp
+    BergotBasis.cpp
     jacobiPolynomials.cpp
     legendrePolynomials.cpp
   GaussIntegration.cpp