diff --git a/Geo/STensor3.cpp b/Geo/STensor3.cpp
index fee79d26615752dc0e9970a8e27fba05dfec5947..fc5571630baa3d21e300f64d5481aeebd3cc74cf 100644
--- a/Geo/STensor3.cpp
+++ b/Geo/STensor3.cpp
@@ -48,6 +48,27 @@ SMetric3 intersection (const SMetric3 &m1, const SMetric3 &m2)
   return iv;
 }
 
+SMetric3 intersection_alauzet (const SMetric3 &m1, const SMetric3 &m2)
+{
+  SMetric3 im1 = m1.invert();
+  fullMatrix<double> V(3,3);
+  fullVector<double> S(3);
+  im1 *= m2;
+  im1.eig(V,S,true);
+  SVector3 v0(V(0,0),V(1,0),V(2,0));
+  SVector3 v1(V(0,1),V(1,1),V(2,1));
+  SVector3 v2(V(0,2),V(1,2),V(2,2));
+  // is this required??
+  v0.normalize();
+  v1.normalize();
+  v2.normalize();
+  double l0 = std::max(dot(v0,m1,v0),dot(v0,m2,v0));
+  double l1 = std::max(dot(v1,m1,v1),dot(v1,m2,v1));
+  double l2 = std::max(dot(v2,m1,v2),dot(v2,m2,v2));
+  SMetric3 iv(l0,l1,l2,v0,v1,v2);
+  return iv;
+}
+
 // preserve orientation of m1 !!!
 SMetric3 intersection_conserveM1 (const SMetric3 &m1, const SMetric3 &m2)
 {
diff --git a/Geo/STensor3.h b/Geo/STensor3.h
index 2be7571fa02879748f52a74f66ec925263eb5a9d..220fde14dfa4a636cd1353e3f61a1a5f11fc1a1c 100644
--- a/Geo/STensor3.h
+++ b/Geo/STensor3.h
@@ -173,6 +173,8 @@ SMetric3 intersection_conserve_mostaniso_2d (const SMetric3 &m1, const SMetric3
 // compute the largest inscribed ellipsoid...
 SMetric3 intersection (const SMetric3 &m1,
                        const SMetric3 &m2);
+SMetric3 intersection_alauzet (const SMetric3 &m1,
+                       const SMetric3 &m2);
 SMetric3 interpolation (const SMetric3 &m1,
                         const SMetric3 &m2,
                         const double t);
diff --git a/Mesh/Field.cpp b/Mesh/Field.cpp
index dccd86205228e47a713b294d210cd0cc708977b8..988ed8048d05dc2ad72c6c9317e71e4ce3cda966 100644
--- a/Mesh/Field.cpp
+++ b/Mesh/Field.cpp
@@ -485,6 +485,55 @@ class CylinderField : public Field
   }
 };
 
+class SphereField : public Field
+{
+  double v_in, v_out;
+  double xc,yc,zc;
+  double R;
+
+ public:
+  std::string getDescription()
+  {
+    return "The value of this field is VIn inside a sphere, VOut outside. "
+      "The sphere is given by\n\n"
+      "  ||dX||^2 < R^2 &&\n"
+      "  dX = (X - XC)^2 + (Y-YC)^2 + (Z-ZC)^2";
+  }
+  SphereField()
+  {
+    v_in = v_out = xc = yc = zc = R = 0;
+
+    options["VIn"] = new FieldOptionDouble
+      (v_in, "Value inside the sphere");
+    options["VOut"] = new FieldOptionDouble
+      (v_out, "Value outside the sphere");
+
+    options["XCenter"] = new FieldOptionDouble
+      (xc, "X coordinate of the sphere center");
+    options["YCenter"] = new FieldOptionDouble
+      (yc, "Y coordinate of the sphere center");
+    options["ZCenter"] = new FieldOptionDouble
+      (zc, "Z coordinate of the sphere center");
+
+
+    options["Radius"] = new FieldOptionDouble
+      (R,"Radius");
+
+  }
+  const char *getName()
+  {
+    return "Sphere";
+  }
+  double operator() (double x, double y, double z, GEntity *ge=0)
+  {
+    double dx = x-xc;
+    double dy = y-yc;
+    double dz = z-zc;
+
+    return ( (dx*dx + dy*dy + dz*dz < R*R) ) ? v_in : v_out;
+  }
+};
+
 class FrustumField : public Field
 {
   double x1,y1,z1;
@@ -1026,15 +1075,17 @@ class MathEvalField : public Field
   std::string f;
 
  public:
-  void myAction(){
-    printf("doing sthg \n");
+  void myAction()
+  {
+    printf("doing sthg\n");
   }
   MathEvalField()
   {
     options["F"] = new FieldOptionString
       (f, "Mathematical function to evaluate.", &update_needed);
     f = "F2 + Sin(z)";
-    callbacks["test"] = new FieldCallbackGeneric<MathEvalField>(this, &MathEvalField::myAction, "description blabla");
+    callbacks["test"] = new FieldCallbackGeneric<MathEvalField>
+      (this, &MathEvalField::myAction, "description blabla");
   }
   double operator() (double x, double y, double z, GEntity *ge=0)
   {
@@ -1337,6 +1388,76 @@ class MinAnisoField : public Field
   }
 };
 
+class IntersectAnisoField : public Field
+{
+  std::list<int> idlist;
+ public:
+  IntersectAnisoField()
+  {
+    options["FieldsList"] = new FieldOptionList
+      (idlist, "Field indices", &update_needed);
+  }
+  virtual bool isotropic () const {return false;}
+  std::string getDescription()
+  {
+    return "Take the intersection of 2 anisotropic fields according to Alauzet.";
+  }
+  virtual void operator() (double x, double y, double z, SMetric3 &metr, GEntity *ge=0)
+  {
+    // check if idlist contains 2 elements other error message
+    SMetric3 v;
+    for(std::list<int>::iterator it = idlist.begin(); it != idlist.end(); it++) {
+      Field *f = (GModel::current()->getFields()->get(*it));
+      SMetric3 ff;
+      if(f && *it != id) {
+	if (f->isotropic()){
+	  double l = (*f) (x, y, z, ge);
+	  ff = SMetric3(1./(l*l));
+	}
+	else{
+	  (*f) (x, y, z, ff, ge);
+	}
+	if (it == idlist.begin())
+          v = ff;
+	else
+          v = intersection_alauzet(v,ff);
+      }
+    }
+    metr = v;
+  }
+  double operator() (double x, double y, double z, GEntity *ge=0)
+  {
+    // check if idlist contains 2 elements other error message
+    SMetric3 metr;
+    for(std::list<int>::iterator it = idlist.begin(); it != idlist.end(); it++) {
+      Field *f = (GModel::current()->getFields()->get(*it));
+      SMetric3 m;
+      if(f && *it != id){
+        if (!f->isotropic()){
+          (*f)(x, y, z, m, ge);
+        }
+	else {
+          double L = (*f)(x, y, z, ge);
+          for (int i = 0; i < 3; i++)
+            m(i,i) = 1. / (L*L);
+	}
+      }
+      if (it == idlist.begin())
+        metr = m;
+      else
+        metr = intersection_alauzet(metr,m);
+    }
+    fullMatrix<double> V(3,3);
+    fullVector<double> S(3);
+    metr.eig(V, S, 1);
+    return sqrt(1./S(2)); //S(2) is largest eigenvalue
+  }
+  const char *getName()
+  {
+    return "IntersectAniso";
+  }
+};
+
 class MinField : public Field
 {
   std::list<int> idlist;
@@ -1355,7 +1476,18 @@ class MinField : public Field
     double v = MAX_LC;
     for(std::list<int>::iterator it = idlist.begin(); it != idlist.end(); it++) {
       Field *f = (GModel::current()->getFields()->get(*it));
-      if(f && *it != id) v = std::min(v, (*f) (x, y, z, ge));
+      if(f && *it != id) {
+        if (f->isotropic())
+	   v = std::min(v, (*f) (x, y, z, ge));
+	else{
+	   SMetric3 ff;
+	   (*f) (x, y, z, ff, ge);
+	   fullMatrix<double> V(3,3);
+	   fullVector<double> S(3);
+	   ff.eig(V, S, 1);
+	   v = std::min(v, sqrt(1./S(2))); //S(2) is largest eigenvalue
+	}
+      }
     }
     return v;
   }
@@ -1383,7 +1515,18 @@ class MaxField : public Field
     double v = -MAX_LC;
     for(std::list<int>::iterator it = idlist.begin(); it != idlist.end(); it++) {
       Field *f = (GModel::current()->getFields()->get(*it));
-      if(f && *it != id) v = std::max(v, (*f) (x, y, z, ge));
+      if(f && *it != id) {
+        if (f->isotropic())
+	   v = std::max(v, (*f) (x, y, z, ge));
+	else{
+	   SMetric3 ff;
+	   (*f) (x, y, z, ff, ge);
+	   fullMatrix<double> V(3,3);
+	   fullVector<double> S(3);
+	   ff.eig(V, S, 1);
+	   v = std::max(v, sqrt(1./S(0))); //S(0) is smallest eigenvalue
+	}
+      }
     }
     return v;
   }
@@ -2157,6 +2300,7 @@ FieldManager::FieldManager()
 #endif
   map_type_name["Box"] = new FieldFactoryT<BoxField>();
   map_type_name["Cylinder"] = new FieldFactoryT<CylinderField>();
+  map_type_name["Sphere"] = new FieldFactoryT<SphereField>();
   map_type_name["Frustum"] = new FieldFactoryT<FrustumField>();
   map_type_name["LonLat"] = new FieldFactoryT<LonLatField>();
 #if defined(HAVE_POST)
@@ -2166,6 +2310,7 @@ FieldManager::FieldManager()
   map_type_name["Restrict"] = new FieldFactoryT<RestrictField>();
   map_type_name["Min"] = new FieldFactoryT<MinField>();
   map_type_name["MinAniso"] = new FieldFactoryT<MinAnisoField>();
+  map_type_name["IntersectAniso"] = new FieldFactoryT<IntersectAnisoField>();
   map_type_name["Max"] = new FieldFactoryT<MaxField>();
   map_type_name["Laplacian"] = new FieldFactoryT<LaplacianField>();
   map_type_name["Mean"] = new FieldFactoryT<MeanField>();