]> SALOME platform Git repositories - tools/medcoupling.git/commitdiff
Salome HOME
BUG correction : During P0P0 remapping on tetra. If tetra is very small the TetraAffi... V9_2_0 V9_2_0rc1 V9_2_0rc2
authorAnthony Geay <anthony.geay@edf.fr>
Mon, 19 Nov 2018 12:29:11 +0000 (13:29 +0100)
committerAnthony Geay <anthony.geay@edf.fr>
Mon, 19 Nov 2018 12:29:41 +0000 (13:29 +0100)
src/INTERP_KERNEL/TetraAffineTransform.cxx
src/INTERP_KERNEL/VectorUtils.hxx
src/MEDCoupling_Swig/MEDCouplingRemapperTest.py

index be3b8090e33600706e25d73a36d1d93b7ddf1eac..a06e5f16facdfb7c9346ce6a03273de2a20935ef 100644 (file)
@@ -62,10 +62,14 @@ namespace INTERP_KERNEL
     calculateDeterminant();
     
     LOG(3, "determinant before inverse = " << _determinant);
+
+    double ni(1./INTERP_KERNEL::normInf(_linear_transform));
+    ni = ni*ni*ni;
     
     // check that tetra is non-planar -> determinant is not zero
+    // AGY : the check to 0. must integrate the infinite norm of _linear_transform matrix.
     // otherwise set _determinant to zero to signal caller that transformation did not work
-    if(epsilonEqual(_determinant, 0.0))
+    if(epsilonEqual(ni*_determinant, 0.0))
       {
         _determinant = 0.0;
         return;
index 00b2bf042cb1f20d28ccbfd5ccc6a9deda64d998..21aaa723f3e6c0c415bb28f5d338a299f8e6f741 100644 (file)
@@ -185,6 +185,23 @@ namespace INTERP_KERNEL
     return relError < relTol;
   }
 
+  inline double sumOfAbsoluteValues(const double row[3])
+  {
+    double ret(0.);
+    std::for_each(row,row+3,[&ret](double v) { ret += std::abs(v); });
+    return ret;
+  }
+
+  /*!
+   * Returns the infinite norm of a 3x3 input matrix \a mat.
+   * The max of absolute value of row sum.
+   */
+  inline double normInf(const double mat[9])
+  {
+    double ret(std::max(sumOfAbsoluteValues(mat),sumOfAbsoluteValues(mat+3)));
+    return std::max(ret,sumOfAbsoluteValues(mat+6));
+  }
+
 }
 
 #endif
index 679d8fe82caf741b636347528fe0c3ce5167c596..d6481d805b7ed44d585071c8cec6157e94e673e9 100644 (file)
@@ -1278,6 +1278,27 @@ class MEDCouplingBasicsTest(unittest.TestCase):
         rem2.setCrudeMatrix(ms,mt,"P0P0",mat)
         self.assertTrue(rem2.transferField(fs,1e300).getArray().isEqual(DataArrayDouble([54.25,11.75,79.25,16.75]),1e-12))
         pass
+
+    def testSmallTetraCell(self):
+        """This test is a non regression test. When using tetra/tetra P0P0 interpolation on very small cells the
+        3x3 matrix in the TetraAffine contains very small values and so the determinant is small (cubic).
+        So the tetra was detected as flat. Now the infinite norm of matrix is considered to establish if matrix is inversible or not."""
+        coords = [(-0.019866666666666668, 0.02, 0.002), (-0.020000073463967143, 0.019999926535763005, 0.0018666666666666673), (-0.020000073463967143, 0.019999926535763005, 0.002), (-0.020000072974206463, 0.019866593202430387, 0.002)]
+        m=MEDCouplingUMesh("mesh",3)
+        m.allocateCells()
+        m.insertNextCell(NORM_TETRA4,[0,1,2,3])
+        m.setCoords(DataArrayDouble(coords))
+        rem=MEDCouplingRemapper()
+        rem.setPrecision(1e-12)
+        rem.prepare(m,m,"P0P0")
+        mat=rem.getCrudeMatrix()
+        self.assertTrue(len(mat)==1)
+        self.assertTrue(len(mat[0])==1)
+        self.assertTrue(list(mat[0].keys())==[0])
+        res=list(mat[0].values())[0]
+        ref=float(m.getMeasureField(True).getArray())
+        self.assertTrue(abs(res-ref)/ref<1e-12)
+        pass
         
     def checkMatrix(self,mat1,mat2,nbCols,eps):
         self.assertEqual(len(mat1),len(mat2))