diff --git a/Geo/GFaceCompound.cpp b/Geo/GFaceCompound.cpp
index 74e694db024616c7775777c85a546fe276d5d504..c6ab9e37e7235568bb8397b657cd9a327f337de2 100644
--- a/Geo/GFaceCompound.cpp
+++ b/Geo/GFaceCompound.cpp
@@ -11,6 +11,7 @@
 #include "Octree.h"
 #include "gmshAssembler.h"
 #include "gmshLaplace.h"
+#include "gmshCrossConf.h"
 #include "gmshConvexCombination.h"
 #include "gmshLinearSystemGmm.h"
 #include "gmshLinearSystemCSR.h"
@@ -322,8 +323,12 @@ void GFaceCompound::parametrize() const
 
   if(!oct){
     coordinates.clear(); 
-    parametrize(ITERU);
-    parametrize(ITERV);
+    
+    //parametrize(ITERU);
+    //parametrize(ITERV);
+
+    parametrize_conformal();
+
     //    checkOrientation();
     computeNormals();
     buildOct();
@@ -468,6 +473,7 @@ GFaceCompound::GFaceCompound(GModel *m, int tag, std::list<GFace*> &compound,
     gmshLinearSystemGmm<double> *_lsysb = new gmshLinearSystemGmm<double>;
     //gmshLinearSystemCSRGmm<double> lsys;
     _lsysb->setPrec(1.e-15);
+    _lsysb->setGmres(1);
     if(Msg::GetVerbosity() == 99) _lsysb->setNoisy(2);
     _lsys = _lsysb;
 #else
@@ -784,7 +790,7 @@ void GFaceCompound::parametrize_conformal() const
 
   {
     MVertex *v1 = ordered[0];
-    MVertex *v2 = ordered[1];
+    MVertex *v2 = ordered[ordered.size()/2];
     myAssembler.fixVertex(v1, 0, 1, 0);
     myAssembler.fixVertex(v1, 0, 2, 0);
     myAssembler.fixVertex(v2, 0, 1, 1);
@@ -804,60 +810,20 @@ void GFaceCompound::parametrize_conformal() const
     }    
   }    
 
-#if 0
-  Msg::Debug("Creating term %d dofs numbered %d fixed",
-             myAssembler.sizeOfR(), myAssembler.sizeOfF());
-  for(unsigned int i = 0; i < ordered.size(); i++){
-    MVertex *v1 = ordered[i];
-    MVertex *v2 = ordered[(i+1)%ordered.size()];
-    myAssembler.assemble(v1,0,2,v1,0,1, 0.5);
-    myAssembler.assemble(v1,0,2,v2,0,1, 0.5);
-    myAssembler.assemble(v2,0,2,v1,0,1,-0.5);
-    myAssembler.assemble(v2,0,2,v2,0,1,-0.5);
-    myAssembler.assemble(v1,0,1,v1,0,2, 0.5);
-    myAssembler.assemble(v1,0,1,v2,0,2, 0.5);
-    myAssembler.assemble(v2,0,1,v1,0,2,-0.5);
-    myAssembler.assemble(v2,0,1,v2,0,2,-0.5);
-  }
-  // internal BC's
-  for(std::list<std::list<GEdge*> >::const_iterator itc = _interior_loops.begin();
-      itc != _interior_loops.end(); ++itc){
-    success = orderVertices(*itc, ordered, coords);
-    if(!success){
-      Msg::Error("Could not order vertices on boundary");
-      return;
-    } 
-    for(unsigned int i = 0; i < ordered.size(); i++){
-      MVertex *v1 = ordered[i];
-      MVertex *v2 = ordered[(i+1)%ordered.size()];
-      myAssembler.assemble(v1,0,2,v1,0,1, 0.5);
-      myAssembler.assemble(v1,0,2,v2,0,1, 0.5);
-      myAssembler.assemble(v2,0,2,v1,0,1,-0.5);
-      myAssembler.assemble(v2,0,2,v2,0,1,-0.5);      
-      myAssembler.assemble(v1,0,1,v1,0,2, 0.5);
-      myAssembler.assemble(v1,0,1,v2,0,2, 0.5);
-      myAssembler.assemble(v2,0,1,v1,0,2,-0.5);
-      myAssembler.assemble(v2,0,1,v2,0,2,-0.5);      
-    }
-  }
-#endif
-  
-  //gmshConvexCombinationTerm laplace(model(), &ONE, 1);
   gmshFunction<double>  ONE(1.0);
-  gmshFunction<double> P5(  .5);
-  gmshFunction<double> M5(-0.5);
+  gmshFunction<double> MONE(-1.0 );
   gmshLaplaceTerm laplace1(model(), &ONE, 1);
   gmshLaplaceTerm laplace2(model(), &ONE, 2);
-  gmshLaplaceTerm laplace12(model(), &M5, 1 , 2);
-  gmshLaplaceTerm laplace21(model(), &P5, 2 , 1);
+  gmshCrossConfTerm cross12(model(), &MONE, 1 , 2);
+  gmshCrossConfTerm cross21(model(), &ONE, 2 , 1);
   it = _compound.begin();
   for( ; it != _compound.end() ; ++it){
     for(unsigned int i = 0; i < (*it)->triangles.size(); ++i){
       MTriangle *t = (*it)->triangles[i];
       laplace1.addToMatrix(myAssembler, t);
       laplace2.addToMatrix(myAssembler, t);
-      laplace12.addToMatrix(myAssembler, t);
-      laplace21.addToMatrix(myAssembler, t);
+      cross12.addToMatrix(myAssembler, t);
+      cross21.addToMatrix(myAssembler, t);
     }
   }
  
@@ -1145,7 +1111,7 @@ void GFaceCompound::getTriangle(double u, double v,
 
 void GFaceCompound::buildOct() const
 {
-  //  printStuff();
+  printStuff();
 
   SBoundingBox3d bb;
   int count = 0;
diff --git a/Numeric/CMakeLists.txt b/Numeric/CMakeLists.txt
index cc58bac166867bd809b02d6edcb7126ea345dee6..98786f31df43c2854942dcdc75173aef739f9336 100644
--- a/Numeric/CMakeLists.txt
+++ b/Numeric/CMakeLists.txt
@@ -7,6 +7,7 @@ set(SRC
   Numeric.cpp
     GmshMatrix.cpp
     gmshLaplace.cpp
+  gmshCrossConf.cpp
     gmshConvexCombination.cpp
       gmshHelmholtz.cpp
       gmshElasticity.cpp
diff --git a/Numeric/gmshCrossConf.cpp b/Numeric/gmshCrossConf.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..6fd73a4340027ef82e87423fdf7d10d29b9aaf97
--- /dev/null
+++ b/Numeric/gmshCrossConf.cpp
@@ -0,0 +1,62 @@
+// Gmsh - Copyright (C) 1997-2009 C. Geuzaine, J.-F. Remacle
+//
+// See the LICENSE.txt file for license information. Please report all
+// bugs and problems to <gmsh@geuz.org>.
+
+#include "gmshCrossConf.h"
+#include "Numeric.h"
+
+void gmshCrossConfTerm::elementMatrix(MElement *e, gmshMatrix<double> &m) const
+{
+  int nbNodes = e->getNumVertices();
+  int integrationOrder = 2 * (e->getPolynomialOrder() - 1);
+  int npts;
+  IntPt *GP;
+  double jac[3][3];
+  double invjac[3][3];
+  SVector3 Grads [256];
+  double grads[256][3];
+  e->getIntegrationPoints(integrationOrder, &npts, &GP);
+  
+  m.set_all(0.);
+
+  for (int i = 0; i < npts; i++){
+    const double u = GP[i].pt[0];
+    const double v = GP[i].pt[1];
+    const double w = GP[i].pt[2];
+    const double weight = GP[i].weight;
+    const double detJ = e->getJacobian(u, v, w, jac);   
+    SPoint3 p; e->pnt(u, v, w, p);
+    const double _diff = (*_diffusivity)(p.x(), p.y(), p.z());
+    inv3x3(jac, invjac) ; 
+    e->getGradShapeFunctions(u, v, w, grads);
+    for (int j = 0; j < nbNodes; j++){
+      Grads[j] = SVector3(invjac[0][0] * grads[j][0] + invjac[0][1] * grads[j][1] + 
+			  invjac[0][2] * grads[j][2],
+			  invjac[1][0] * grads[j][0] + invjac[1][1] * grads[j][1] + 
+			  invjac[1][2] * grads[j][2],
+			  invjac[2][0] * grads[j][0] + invjac[2][1] * grads[j][1] +
+			  invjac[2][2] * grads[j][2]);
+    }
+
+    SVector3 N (jac[2][0],jac[2][1],jac[2][2]);
+    //SVector3 N (jac[0][2],jac[1][2],jac[2][2]);
+    
+    double norm = N[0]*N[0]+  N[1]*N[1]+  N[2]*N[2];
+    if (norm != 1.0){
+      printf("Normal N=%g %g %g NORM = %g\n", N[0], N[1], N[2], norm);
+      //exit(1);
+    }
+
+    for (int j = 0; j < nbNodes; j++){
+      for (int k = 0; k <= j; k++){
+        m(j, k) += dot(crossprod(Grads[j],Grads[k]),N) * weight * detJ * _diff;
+      }
+    }
+  }
+
+  for (int j = 0; j < nbNodes; j++)
+    for (int k = 0; k < j; k++)
+      m(k, j) = -1.0*m(j, k);
+}
+
diff --git a/Numeric/gmshCrossConf.h b/Numeric/gmshCrossConf.h
new file mode 100644
index 0000000000000000000000000000000000000000..28ba7cc173daaded4e8941e99b9f4f9d386a4479
--- /dev/null
+++ b/Numeric/gmshCrossConf.h
@@ -0,0 +1,54 @@
+// Gmsh - Copyright (C) 1997-2009 C. Geuzaine, J.-F. Remacle
+//
+// See the LICENSE.txt file for license information. Please report all
+// bugs and problems to <gmsh@geuz.org>.
+
+#ifndef _GMSH_CROSSCONF_H_
+#define _GMSH_CROSSCONF_H_
+
+#include "gmshTermOfFormulation.h"
+#include "gmshFunction.h"
+#include "Gmsh.h"
+#include "GModel.h"
+#include "MElement.h"
+#include "GmshMatrix.h"
+
+class gmshCrossConfTerm : public gmshNodalFemTerm<double> {
+ protected:
+  const gmshFunction<double> *_diffusivity;
+  const int _iField;
+  int _iFieldB ;
+ public:
+  virtual int sizeOfR(MElement *e) const { return e->getNumVertices(); }
+  virtual int sizeOfC(MElement *e) const { return e->getNumVertices(); }
+  void getLocalDofR(MElement *e, int iRow, MVertex **vR, int *iCompR, int *iFieldR) const
+  {
+    *vR = e->getVertex(iRow);
+    *iCompR = 0;
+    *iFieldR = _iField;
+  }
+  void getLocalDofC(MElement *e, int iRow, MVertex **vR, int *iCompR, int *iFieldR) const
+  {
+    *vR = e->getVertex(iRow);
+    *iCompR = 0;
+    *iFieldR = _iFieldB;
+  }
+ public:
+  gmshCrossConfTerm(GModel *gm, gmshFunction<double> *diffusivity, int iField = 0, int iFieldB=-1) : 
+    gmshNodalFemTerm<double>(gm), _diffusivity(diffusivity), _iField(iField)
+    {
+      _iFieldB = (iFieldB==-1) ? _iField : iFieldB;
+    }
+  virtual void elementMatrix(MElement *e, gmshMatrix<double> &m) const;
+};
+
+class gmshCrossConfTerm2DParametric : gmshCrossConfTerm {
+  GFace *_gf;
+ public:
+  gmshCrossConfTerm2DParametric(GFace *gf, gmshFunction<double> *diffusivity, int iField = 0) : 
+    gmshCrossConfTerm(gf->model(), diffusivity, iField), _gf(gf) {}
+  virtual void elementMatrix(MElement *e, gmshMatrix<double> &m) const;
+};
+
+
+#endif
diff --git a/Numeric/gmshLaplace.cpp b/Numeric/gmshLaplace.cpp
index 63550e4744a76699f252ce8c4e2fb80083e0edca..9495e77183ce8cac03e8a7ed8c7717f6f8fc36b7 100644
--- a/Numeric/gmshLaplace.cpp
+++ b/Numeric/gmshLaplace.cpp
@@ -54,6 +54,4 @@ void gmshLaplaceTerm::elementMatrix(MElement *e, gmshMatrix<double> &m) const
       m(k, j) = m(j, k);
 }
 
-void gmshLaplaceTerm2DParametric::elementMatrix(MElement *e, gmshMatrix<double> &m) const
-{
-} 
+
diff --git a/Numeric/gmshLaplace.h b/Numeric/gmshLaplace.h
index e0428c8705ef6758ab0730c30bbdad1137c716b1..fb88b0b61af902f75bf2ad243195251b0db9784e 100644
--- a/Numeric/gmshLaplace.h
+++ b/Numeric/gmshLaplace.h
@@ -42,13 +42,6 @@ class gmshLaplaceTerm : public gmshNodalFemTerm<double> {
   virtual void elementMatrix(MElement *e, gmshMatrix<double> &m) const;
 };
 
-class gmshLaplaceTerm2DParametric : gmshLaplaceTerm {
-  GFace *_gf;
- public:
-  gmshLaplaceTerm2DParametric(GFace *gf, gmshFunction<double> *diffusivity, int iField = 0) : 
-    gmshLaplaceTerm(gf->model(), diffusivity, iField), _gf(gf) {}
-  virtual void elementMatrix(MElement *e, gmshMatrix<double> &m) const;
-};
 
 
 #endif
diff --git a/benchmarks/2d/square.geo b/benchmarks/2d/square.geo
index ec29fb7bdc8f39fcfa8fd9ff2fd4d09415cde094..7d9878cb983e9bd708dba7ad22a3bd9d34cabf3d 100644
--- a/benchmarks/2d/square.geo
+++ b/benchmarks/2d/square.geo
@@ -11,3 +11,4 @@ Line(4) = {1, 2};
 Line Loop(5) = {1, 2, 3, 4};
 Plane Surface(10) = {5};
 
+Compound Surface(11)={10};
diff --git a/benchmarks/boolean/TORUS.geo b/benchmarks/boolean/TORUS.geo
index 71b3e601ea4665bd80e956c36eeaa642fe6263b4..16be03c4a4fb6b4fa029e37195dc3a6e74a9cda9 100644
--- a/benchmarks/boolean/TORUS.geo
+++ b/benchmarks/boolean/TORUS.geo
@@ -1,3 +1,3 @@
 
 OCCShape("Torus",{0,0,0,0,0,1,10,9},"None");
-BoundingBox{0,0,0,10,10,10};
+//BoundingBox{0,0,0,10,10,10};