]> SALOME platform Git repositories - tools/medcoupling.git/commitdiff
Salome HOME
Update from V515BR
authorageay <ageay>
Wed, 13 Oct 2010 10:24:39 +0000 (10:24 +0000)
committerageay <ageay>
Wed, 13 Oct 2010 10:24:39 +0000 (10:24 +0000)
66 files changed:
src/INTERP_KERNEL/CellModel.cxx
src/INTERP_KERNEL/CellModel.hxx
src/INTERP_KERNEL/CurveIntersectorP0P1.txx
src/INTERP_KERNEL/CurveIntersectorP1P0.txx
src/INTERP_KERNEL/CurveIntersectorP1P1.txx
src/INTERP_KERNEL/DirectedBoundingBox.cxx
src/INTERP_KERNEL/DirectedBoundingBox.hxx
src/INTERP_KERNEL/ExprEval/InterpKernelAsmX86.cxx [new file with mode: 0644]
src/INTERP_KERNEL/ExprEval/InterpKernelAsmX86.hxx [new file with mode: 0644]
src/INTERP_KERNEL/ExprEval/InterpKernelExprParser.cxx
src/INTERP_KERNEL/ExprEval/InterpKernelExprParser.hxx
src/INTERP_KERNEL/ExprEval/InterpKernelFunction.cxx
src/INTERP_KERNEL/ExprEval/InterpKernelFunction.hxx
src/INTERP_KERNEL/ExprEval/Makefile.am
src/INTERP_KERNEL/GenMathFormulae.hxx [new file with mode: 0644]
src/INTERP_KERNEL/InterpolationOptions.cxx
src/INTERP_KERNEL/InterpolationOptions.hxx
src/INTERP_KERNEL/InterpolationUtils.hxx
src/INTERP_KERNEL/Makefile.am
src/INTERP_KERNEL/TranslationRotationMatrix.cxx [new file with mode: 0644]
src/INTERP_KERNEL/TranslationRotationMatrix.hxx
src/INTERP_KERNEL/VolSurfFormulae.hxx
src/INTERP_KERNEL/VolSurfUser.hxx
src/INTERP_KERNEL/VolSurfUser.txx
src/MEDCoupling/MEDCouplingAutoRefCountObjectPtr.hxx [new file with mode: 0644]
src/MEDCoupling/MEDCouplingCMesh.cxx
src/MEDCoupling/MEDCouplingCMesh.hxx
src/MEDCoupling/MEDCouplingExtrudedMesh.cxx
src/MEDCoupling/MEDCouplingExtrudedMesh.hxx
src/MEDCoupling/MEDCouplingField.cxx
src/MEDCoupling/MEDCouplingField.hxx
src/MEDCoupling/MEDCouplingFieldDiscretization.cxx
src/MEDCoupling/MEDCouplingFieldDiscretization.hxx
src/MEDCoupling/MEDCouplingFieldDouble.cxx
src/MEDCoupling/MEDCouplingFieldDouble.hxx
src/MEDCoupling/MEDCouplingGaussLocalization.cxx [new file with mode: 0644]
src/MEDCoupling/MEDCouplingGaussLocalization.hxx [new file with mode: 0644]
src/MEDCoupling/MEDCouplingMemArray.cxx
src/MEDCoupling/MEDCouplingMemArray.hxx
src/MEDCoupling/MEDCouplingMemArray.txx
src/MEDCoupling/MEDCouplingMesh.cxx
src/MEDCoupling/MEDCouplingMesh.hxx
src/MEDCoupling/MEDCouplingNatureOfField.cxx [new file with mode: 0644]
src/MEDCoupling/MEDCouplingNatureOfField.hxx
src/MEDCoupling/MEDCouplingNormalizedCartesianMesh.hxx
src/MEDCoupling/MEDCouplingNormalizedUnstructuredMesh.hxx
src/MEDCoupling/MEDCouplingPointSet.cxx
src/MEDCoupling/MEDCouplingPointSet.hxx
src/MEDCoupling/MEDCouplingPointSet.txx
src/MEDCoupling/MEDCouplingRefCountObject.hxx
src/MEDCoupling/MEDCouplingRemapper.cxx
src/MEDCoupling/MEDCouplingRemapper.hxx
src/MEDCoupling/MEDCouplingTimeDiscretization.cxx
src/MEDCoupling/MEDCouplingTimeDiscretization.hxx
src/MEDCoupling/MEDCouplingUMesh.cxx
src/MEDCoupling/MEDCouplingUMesh.hxx
src/MEDCoupling/MEDCouplingUMeshDesc.cxx
src/MEDCoupling/MEDCouplingUMeshDesc.hxx
src/MEDCoupling/Makefile.am
src/MEDCoupling/Test/MEDCouplingBasicsTest.hxx
src/MEDCoupling/Test/MEDCouplingBasicsTest0.cxx
src/MEDCoupling/Test/MEDCouplingBasicsTest1.cxx
src/MEDCoupling/Test/MEDCouplingBasicsTest2.cxx [new file with mode: 0644]
src/MEDCoupling/Test/MEDCouplingRemapperTest.cxx
src/MEDCoupling/Test/MEDCouplingRemapperTest.hxx
src/MEDCoupling/Test/Makefile.am

index af6dac5ad779cf0f18bc0ba782d8e874433734ee..88bc7a820cee19dca29bf05748b40f6e1e99a656 100644 (file)
 
 namespace INTERP_KERNEL
 {
+  const char *CellModel::CELL_TYPES_REPR[]={"NORM_POINT0", "NORM_SEG2", "NORM_SEG3", "NORM_TRI3", "NORM_QUAD4",// 0->4
+                                            "NORM_POLYGON", "NORM_TRI6", "" , "NORM_QUAD8", "",//5->9
+                                            "", "", "", "", "NORM_TETRA4",//10->14
+                                            "NORM_PYRA5", "NORM_PENTA6", "", "NORM_HEXA8", "",//15->19
+                                            "NORM_TETRA10", "", "", "NORM_PYRA13", "",//20->24
+                                            "NORM_PENTA15", "", "", "", "",//25->29
+                                            "NORM_HEXA20", "NORM_POLYHED", "", "", "",//30->34
+                                            "", "", "", "", "",//35->39
+                                            "NORM_ERROR"};
+
   std::map<NormalizedCellType,CellModel> CellModel::_map_of_unique_instance;
 
   const CellModel& CellModel::getCellModel(NormalizedCellType type)
@@ -42,6 +52,11 @@ namespace INTERP_KERNEL
     return (*iter).second;
   }
 
+  const char *CellModel::getRepr() const
+  {
+    return CELL_TYPES_REPR[(int)_type];
+  }
+
   /*!
    * This method is compatible with all types including dynamic one.
    */
@@ -87,6 +102,8 @@ namespace INTERP_KERNEL
     _quadratic=false;
     _dyn=false;
     _extruded_type=NORM_ERROR;
+    _linear_type=NORM_ERROR;
+    _quadratic_type=NORM_ERROR;
     switch(type)
       {
       case NORM_POINT0:
@@ -96,17 +113,17 @@ namespace INTERP_KERNEL
         break;
       case NORM_SEG2:
         {
-          _nb_of_pts=2; _nb_of_sons=0; _dim=1; _extruded_type=NORM_QUAD4;
+          _nb_of_pts=2; _nb_of_sons=0; _dim=1; _extruded_type=NORM_QUAD4; _quadratic_type=NORM_SEG3;
         }
         break;
       case NORM_SEG3:
         {
-          _nb_of_pts=3; _nb_of_sons=0; _dim=1; _extruded_type=NORM_QUAD8;
+          _nb_of_pts=3; _nb_of_sons=0; _dim=1; _extruded_type=NORM_QUAD8; _linear_type=NORM_SEG2;
         }
         break;
       case NORM_TETRA4:
         {
-          _nb_of_pts=4; _nb_of_sons=4; _dim=3;
+          _nb_of_pts=4; _nb_of_sons=4; _dim=3; _quadratic_type=NORM_TETRA10;
           _sons_type[0]=NORM_TRI3; _sons_type[1]=NORM_TRI3; _sons_type[2]=NORM_TRI3; _sons_type[3]=NORM_TRI3;
           _sons_con[0][0]=0; _sons_con[0][1]=1; _sons_con[0][2]=2; _nb_of_sons_con[0]=3;
           _sons_con[1][0]=0; _sons_con[1][1]=3; _sons_con[1][2]=1; _nb_of_sons_con[1]=3;
@@ -116,7 +133,7 @@ namespace INTERP_KERNEL
         break;
       case NORM_HEXA8:
         {
-          _nb_of_pts=8; _nb_of_sons=6; _dim=3;
+          _nb_of_pts=8; _nb_of_sons=6; _dim=3; _quadratic_type=NORM_HEXA20;
           _sons_type[0]=NORM_QUAD4; _sons_type[1]=NORM_QUAD4; _sons_type[2]=NORM_QUAD4; _sons_type[3]=NORM_QUAD4; _sons_type[4]=NORM_QUAD4; _sons_type[5]=NORM_QUAD4;
           _sons_con[0][0]=0; _sons_con[0][1]=1; _sons_con[0][2]=2; _sons_con[0][3]=3; _nb_of_sons_con[0]=4;
           _sons_con[1][0]=4; _sons_con[1][1]=7; _sons_con[1][2]=6; _sons_con[1][3]=5; _nb_of_sons_con[1]=4;
@@ -128,7 +145,7 @@ namespace INTERP_KERNEL
         break;
       case NORM_QUAD4:
         {
-          _nb_of_pts=4; _nb_of_sons=4; _dim=2;
+          _nb_of_pts=4; _nb_of_sons=4; _dim=2; _quadratic_type=NORM_QUAD8;
           _sons_type[0]=NORM_SEG2; _sons_type[1]=NORM_SEG2; _sons_type[2]=NORM_SEG2; _sons_type[3]=NORM_SEG2;
           _sons_con[0][0]=0; _sons_con[0][1]=1; _nb_of_sons_con[0]=2;
           _sons_con[1][0]=1; _sons_con[1][1]=2; _nb_of_sons_con[1]=2;
@@ -138,7 +155,7 @@ namespace INTERP_KERNEL
         break;
       case NORM_TRI3:
         {
-          _nb_of_pts=3; _nb_of_sons=3; _dim=2;
+          _nb_of_pts=3; _nb_of_sons=3; _dim=2; _quadratic_type=NORM_TRI6;
           _sons_type[0]=NORM_SEG2; _sons_type[1]=NORM_SEG2; _sons_type[2]=NORM_SEG2;
           _sons_con[0][0]=0; _sons_con[0][1]=1; _nb_of_sons_con[0]=2;
           _sons_con[1][0]=1; _sons_con[1][1]=2; _nb_of_sons_con[1]=2;
@@ -147,7 +164,7 @@ namespace INTERP_KERNEL
         break;
       case NORM_TRI6:
         {
-          _nb_of_pts=6; _nb_of_sons=3; _dim=2;
+          _nb_of_pts=6; _nb_of_sons=3; _dim=2; _linear_type=NORM_TRI3;
           _sons_type[0]=NORM_SEG3; _sons_type[1]=NORM_SEG3; _sons_type[2]=NORM_SEG3;
           _sons_con[0][0]=0; _sons_con[0][1]=1; _sons_con[0][2]=3; _nb_of_sons_con[0]=3;
           _sons_con[1][0]=1; _sons_con[1][1]=2; _sons_con[1][2]=4; _nb_of_sons_con[1]=3;
@@ -156,7 +173,7 @@ namespace INTERP_KERNEL
         break;
       case NORM_QUAD8:
         {
-          _nb_of_pts=8; _nb_of_sons=4; _dim=2;
+          _nb_of_pts=8; _nb_of_sons=4; _dim=2; _linear_type=NORM_QUAD4;
           _sons_type[0]=NORM_SEG3; _sons_type[1]=NORM_SEG3; _sons_type[2]=NORM_SEG3; _sons_type[3]=NORM_SEG3;
           _sons_con[0][0]=0; _sons_con[0][1]=1; _sons_con[0][2]=4; _nb_of_sons_con[0]=3;
           _sons_con[1][0]=1; _sons_con[1][1]=2; _sons_con[1][2]=5; _nb_of_sons_con[1]=3;
@@ -166,7 +183,7 @@ namespace INTERP_KERNEL
         break;
       case NORM_PYRA5:
         {
-          _nb_of_pts=5; _nb_of_sons=5; _dim=3;
+          _nb_of_pts=5; _nb_of_sons=5; _dim=3; _quadratic_type=NORM_PYRA13;
           _sons_type[0]=NORM_QUAD4; _sons_type[1]=NORM_TRI3; _sons_type[2]=NORM_TRI3; _sons_type[3]=NORM_TRI3; _sons_type[4]=NORM_TRI3;
           _sons_con[0][0]=0; _sons_con[0][1]=1; _sons_con[0][2]=2; _sons_con[0][3]=3; _nb_of_sons_con[0]=4;
           _sons_con[1][0]=0; _sons_con[1][1]=4; _sons_con[1][2]=1; _nb_of_sons_con[1]=3;
@@ -177,7 +194,7 @@ namespace INTERP_KERNEL
         break;
       case NORM_PENTA6:
         {
-          _nb_of_pts=6; _nb_of_sons=5; _dim=3;
+          _nb_of_pts=6; _nb_of_sons=5; _dim=3; _quadratic_type=NORM_PENTA15;
           _sons_type[0]=NORM_TRI3; _sons_type[1]=NORM_TRI3; _sons_type[2]=NORM_QUAD4; _sons_type[3]=NORM_QUAD4; _sons_type[4]=NORM_QUAD4;
           _sons_con[0][0]=0; _sons_con[0][1]=1; _sons_con[0][2]=2; _nb_of_sons_con[0]=3;
           _sons_con[1][0]=3; _sons_con[1][1]=5; _sons_con[1][2]=4; _nb_of_sons_con[1]=3;
@@ -188,7 +205,7 @@ namespace INTERP_KERNEL
         break;
       case NORM_TETRA10:
         {
-          _nb_of_pts=10; _nb_of_sons=4; _dim=3;
+          _nb_of_pts=10; _nb_of_sons=4; _dim=3; _linear_type=NORM_TETRA4;
           _sons_type[0]=NORM_TRI6; _sons_type[1]=NORM_TRI6; _sons_type[2]=NORM_TRI6; _sons_type[3]=NORM_TRI6;
           _sons_con[0][0]=0; _sons_con[0][1]=1; _sons_con[0][2]=2; _sons_con[0][3]=4; _sons_con[0][4]=5; _sons_con[0][5]=6; _nb_of_sons_con[0]=6;
           _sons_con[1][0]=0; _sons_con[1][1]=3; _sons_con[1][2]=1; _sons_con[1][3]=7; _sons_con[1][4]=8; _sons_con[1][5]=4; _nb_of_sons_con[1]=6;
@@ -198,7 +215,7 @@ namespace INTERP_KERNEL
         break;
       case NORM_PYRA13:
         {
-          _nb_of_pts=13; _nb_of_sons=5; _dim=3;
+          _nb_of_pts=13; _nb_of_sons=5; _dim=3; _linear_type=NORM_PYRA5;
           _sons_type[0]=NORM_QUAD8; _sons_type[1]=NORM_TRI6; _sons_type[2]=NORM_TRI6; _sons_type[3]=NORM_TRI6; _sons_type[4]=NORM_TRI6;
           _sons_con[0][0]=0; _sons_con[0][1]=1; _sons_con[0][2]=2; _sons_con[0][3]=3; _sons_con[0][4]=5; _sons_con[0][5]=6; _sons_con[0][6]=7; _sons_con[0][7]=8; _nb_of_sons_con[0]=8;
           _sons_con[1][0]=0; _sons_con[1][1]=4; _sons_con[1][2]=1; _sons_con[1][3]=9; _sons_con[1][4]=10; _sons_con[1][5]=5; _nb_of_sons_con[1]=6;
@@ -209,7 +226,7 @@ namespace INTERP_KERNEL
         break;
       case NORM_PENTA15:
         {
-          _nb_of_pts=15; _nb_of_sons=5; _dim=3;
+          _nb_of_pts=15; _nb_of_sons=5; _dim=3; _linear_type=NORM_PENTA6;
           _sons_type[0]=NORM_TRI6; _sons_type[1]=NORM_TRI6; _sons_type[2]=NORM_QUAD8; _sons_type[3]=NORM_QUAD8; _sons_type[4]=NORM_QUAD8;
           _sons_con[0][0]=0; _sons_con[0][1]=1; _sons_con[0][2]=2; _sons_con[0][3]=6; _sons_con[0][4]=7; _sons_con[0][5]=8; _nb_of_sons_con[0]=6;
           _sons_con[1][0]=3; _sons_con[1][1]=5; _sons_con[1][2]=4; _sons_con[1][3]=11; _sons_con[1][4]=10; _sons_con[1][5]=9; _nb_of_sons_con[1]=6;
@@ -220,7 +237,7 @@ namespace INTERP_KERNEL
         break;
       case NORM_HEXA20:
         {
-          _nb_of_pts=20; _nb_of_sons=6; _dim=3;
+          _nb_of_pts=20; _nb_of_sons=6; _dim=3; _linear_type=NORM_HEXA8;
           _sons_type[0]=NORM_QUAD8; _sons_type[1]=NORM_QUAD8; _sons_type[2]=NORM_QUAD8; _sons_type[3]=NORM_QUAD8; _sons_type[4]=NORM_QUAD8; _sons_type[5]=NORM_QUAD8;
           _sons_con[0][0]=0; _sons_con[0][1]=1; _sons_con[0][2]=2; _sons_con[0][3]=3; _sons_con[0][4]=8; _sons_con[0][5]=9; _sons_con[0][6]=10; _sons_con[0][7]=11; _nb_of_sons_con[0]=8;
           _sons_con[1][0]=4; _sons_con[1][1]=7; _sons_con[1][2]=6; _sons_con[1][3]=5; _sons_con[1][4]=15; _sons_con[1][5]=14; _sons_con[1][6]=13; _sons_con[1][7]=12; _nb_of_sons_con[1]=8;
index 393fea0eb723d9eba2c8f864968752d34bff3009..23b7355127c89ad32b991904f024104f0b9fd5d4 100644 (file)
@@ -41,6 +41,7 @@ namespace INTERP_KERNEL
     static void buildUniqueInstance();
   public:
     INTERPKERNEL_EXPORT static const CellModel& getCellModel(NormalizedCellType type);
+    INTERPKERNEL_EXPORT const char *getRepr() const;
     INTERPKERNEL_EXPORT bool isDynamic() const { return _dyn; }
     INTERPKERNEL_EXPORT bool isQuadratic() const { return _quadratic; }
     INTERPKERNEL_EXPORT unsigned getDimension() const { return _dim; }
@@ -53,6 +54,8 @@ namespace INTERP_KERNEL
     INTERPKERNEL_EXPORT unsigned getNumberOfNodesConstituentTheSon(unsigned sonId) const { return _nb_of_sons_con[sonId]; }
     INTERPKERNEL_EXPORT unsigned getNumberOfNodesConstituentTheSon2(unsigned sonId, const int *nodalConn, int lgth) const;
     INTERPKERNEL_EXPORT NormalizedCellType getExtrudedType() const { return _extruded_type; }
+    INTERPKERNEL_EXPORT NormalizedCellType getLinearType() const { return _linear_type; }
+    INTERPKERNEL_EXPORT NormalizedCellType getQuadraticType() const { return _quadratic_type; }
     INTERPKERNEL_EXPORT NormalizedCellType getSonType(unsigned sonId) const { return _sons_type[sonId]; }
     INTERPKERNEL_EXPORT NormalizedCellType getSonType2(unsigned sonId) const;
     INTERPKERNEL_EXPORT unsigned fillSonCellNodalConnectivity(int sonId, const int *nodalConn, int *sonNodalConn) const;
@@ -65,10 +68,13 @@ namespace INTERP_KERNEL
     unsigned _nb_of_sons;
     NormalizedCellType _type;
     NormalizedCellType _extruded_type;
+    NormalizedCellType _linear_type;
+    NormalizedCellType _quadratic_type;
     unsigned _sons_con[MAX_NB_OF_SONS][MAX_NB_OF_NODES_PER_ELEM];
     unsigned _nb_of_sons_con[MAX_NB_OF_SONS];
     NormalizedCellType _sons_type[MAX_NB_OF_SONS];
     static std::map<NormalizedCellType,CellModel> _map_of_unique_instance;
+    static const char *CELL_TYPES_REPR[];
   };
 }
 
index c25136b5d4608eeae0a86bbecdddb57e580ada2a..1947a9f5bfb23ba66d5bc472fc8ea78ce616b406 100644 (file)
@@ -60,7 +60,7 @@ namespace INTERP_KERNEL
   {
     std::vector<typename BASE_INTERSECTOR::TDualSegment> segmentsT;
     BASE_INTERSECTOR::getDualSegments( icellT, BASE_INTERSECTOR::_meshT, segmentsT);
-    for ( int t = 0; t < segmentsT.size(); ++t )
+    for ( int t = 0; t < (int)segmentsT.size(); ++t )
       {
         typename MyMatrix::value_type& resRow = res[ OTT<ConnType,numPol>::ind2C( segmentsT[t]._nodeId )];
         for(typename std::vector<ConnType>::const_iterator
index bafd3ad9ed4b116c324f41eb1ef93e988ea607a9..f4e136dd301bc03898c7faeb97e0e4e6329b82e0 100644 (file)
@@ -69,7 +69,7 @@ namespace INTERP_KERNEL
           int iS = *iter;
           BASE_INTERSECTOR::getDualSegments( OTT<ConnType,numPol>::ind2C(iS),
                                              BASE_INTERSECTOR::_meshS, segmentsS);
-          for ( int s = 0; s < segmentsS.size(); ++s )
+          for ( int s = 0; s < (int)segmentsS.size(); ++s )
             {
               double surf = BASE_INTERSECTOR::intersectSegments(&segmentsS[s]._coords[0],
                                                                 &coordsT[0] + t*SPACEDIM);
index fd43fe7fc6f635a490e677c8f0cd458547768002..7be7429bb21049ce78aae4447918cc7a85863682 100644 (file)
@@ -54,7 +54,7 @@ namespace INTERP_KERNEL
   {
     std::vector<typename BASE_INTERSECTOR::TDualSegment> segmentsT, segmentsS;
     BASE_INTERSECTOR::getDualSegments( icellT, BASE_INTERSECTOR::_meshT, segmentsT);
-    for ( int t = 0; t < segmentsT.size(); ++t )
+    for ( int t = 0; t < (int)segmentsT.size(); ++t )
       {
         typename MyMatrix::value_type& resRow = res[ OTT<ConnType,numPol>::ind2C( segmentsT[t]._nodeId )];
         for(typename std::vector<ConnType>::const_iterator
@@ -63,7 +63,7 @@ namespace INTERP_KERNEL
             int iS = *iter;
             BASE_INTERSECTOR::getDualSegments( OTT<ConnType,numPol>::ind2C(iS),
                                                BASE_INTERSECTOR::_meshS, segmentsS);
-            for ( int s = 0; s < segmentsS.size(); ++s )
+            for ( int s = 0; s < (int)segmentsS.size(); ++s )
               {
                 double surf = BASE_INTERSECTOR::intersectSegments(&segmentsT[t]._coords[0],
                                                                   &segmentsS[s]._coords[0]);
index 72b5c51016b38f4a15e85c6ca3f941a1d2b3bca9..b59f78db6b0b8f48e8e3f1aaba8cb5221590f55b 100644 (file)
@@ -20,7 +20,6 @@
 // Created   : Mon Apr 12 14:41:22 2010
 // Author    : Edward AGAPOV (eap)
 
-
 #include "DirectedBoundingBox.hxx"
 
 #include "InterpolationUtils.hxx"
@@ -31,7 +30,7 @@
 #define __MAX(i)      _minmax[i*2+1]
 #define __MYID        (long(this)%10000)
 #define __DMP(msg) \
-   //cout << msg << endl
+  //  cout << msg << endl
 
 using namespace std;
 
@@ -237,9 +236,9 @@ namespace INTERP_KERNEL
     if ( dim > 1 )
       {
         for ( coord = pts; coord < coordEnd; )
-          for ( int i = 0; i < dim; ++i )
+          for ( int i = 0; i < (int)dim; ++i )
             gc[i] += *coord++;
-        for ( int j = 0; j < dim; ++j )
+        for ( int j = 0; j < (int)dim; ++j )
           gc[j] /= numPts;
 
       }
@@ -309,9 +308,9 @@ namespace INTERP_KERNEL
     if ( dim > 1 )
       {
         for ( unsigned i = 0; i < numPts; ++i )
-          for ( int j = 0; j < dim; ++j )
+          for ( int j = 0; j < (int)dim; ++j )
             gc[j] += pts[i][j];
-        for ( int j = 0; j < dim; ++j )
+        for ( int j = 0; j < (int)dim; ++j )
           gc[j] /= numPts;
       }
 
@@ -347,6 +346,7 @@ namespace INTERP_KERNEL
             if ( pts[i][0] < _minmax[0] ) _minmax[0] = pts[i][0];
             if ( pts[i][0] > _minmax[1] ) _minmax[1] = pts[i][0];
           }
+        _axes[0] = 1.0;
       }
   }
 
@@ -568,7 +568,7 @@ namespace INTERP_KERNEL
                                        const double*        minmax) const
   {
     int iC, nbCorners = 1;
-    for ( int i=0;i<_dim;++i ) nbCorners *= 2;
+    for ( int i=0;i<(int)_dim;++i ) nbCorners *= 2;
     corners.resize( nbCorners * _dim );
     // each coordinate is filled with either min or max, nbSwap is number of corners
     // after which min and max swap
@@ -595,6 +595,8 @@ namespace INTERP_KERNEL
   bool DirectedBoundingBox::isDisjointWith(const DirectedBoundingBox& box) const
   {
     if ( _dim < 1 || box._dim < 1 ) return false; // empty box includes all
+    if ( _dim == 1 )
+      return isMinMaxOut( &box._minmax[0], &this->_minmax[0], _dim );
 
     // boxes are disjoined if their minmaxes in local CS of either of boxes do not intersect
     for ( int isThisCS = 0; isThisCS < 2; ++isThisCS )
@@ -632,6 +634,8 @@ namespace INTERP_KERNEL
   bool DirectedBoundingBox::isDisjointWith(const double* box) const
   {
     if ( _dim < 1 ) return false; // empty box includes all
+    if ( _dim == 1 )
+      return isMinMaxOut( &_minmax[0], box, _dim );
 
     // boxes are disjoined if their minmaxes in local CS of either of boxes do not intersect
 
@@ -657,7 +661,7 @@ namespace INTERP_KERNEL
       for ( int iC = 0, nC = cornersThis.size()/_dim; iC < nC; ++iC)
         {
           fromLocalCS( &cornersThis[iC*_dim], globCorner );
-          for ( int i = 0; i < _dim; ++i )
+          for ( int i = 0; i < (int)_dim; ++i )
             {
               if ( globCorner[i] < mmBox._minmax[i*2] )   mmBox._minmax[i*2] = globCorner[i];
               if ( globCorner[i] > mmBox._minmax[i*2+1] ) mmBox._minmax[i*2+1] = globCorner[i];
@@ -710,7 +714,7 @@ namespace INTERP_KERNEL
       data.insert( data.end(), &_axes[0], &_axes[0] + _axes.size());
       data.insert( data.end(), &_minmax[0], &_minmax[0] + _minmax.size());
     }
-    if ( data.size() < dataSize( _dim ))
+    if ( data.size() < (unsigned)dataSize( _dim ))
       data.resize( dataSize( _dim ), 0 );
     return data;
   }
index 93874acdb8fddda234f98d28e9b4ce0439f09f78..344f659090f767cd377c57ee04037db896775fb9 100644 (file)
@@ -16,8 +16,9 @@
 //
 //  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
 //
-#ifndef __DirectedBoundingBox_HXX__
-#define __DirectedBoundingBox_HXX__
+
+#ifndef __DIRECTEDBOUNDINGBOX_HXX__
+#define __DIRECTEDBOUNDINGBOX_HXX__
 
 #include "INTERPKERNELDefines.hxx"
 
@@ -92,7 +93,7 @@ namespace INTERP_KERNEL
 
   inline bool DirectedBoundingBox::isLocalOut(const double* pLoc) const
     {
-      for ( int i = 0; i < _dim; ++i )
+      for ( int i = 0; i < (int)_dim; ++i )
         if ( pLoc[i] < _minmax[i*2] || pLoc[i] > _minmax[i*2+1] )
           return true;
       return false;
@@ -106,10 +107,10 @@ namespace INTERP_KERNEL
 
   inline void DirectedBoundingBox::addPointToBox(const double* coord)
   {
-    for ( int i = 0; i < _dim; ++i )
+    for ( int i = 0; i < (int)_dim; ++i )
       {
         double c = 0;
-        for ( int j = 0; j < _dim; ++j ) c += coord[j]*_axes[i*_dim+j];
+        for ( int j = 0; j < (int)_dim; ++j ) c += coord[j]*_axes[i*_dim+j];
         if ( c < _minmax[i*2] )   _minmax[i*2] = c;
         if ( c > _minmax[i*2+1] ) _minmax[i*2+1] = c;
       }
diff --git a/src/INTERP_KERNEL/ExprEval/InterpKernelAsmX86.cxx b/src/INTERP_KERNEL/ExprEval/InterpKernelAsmX86.cxx
new file mode 100644 (file)
index 0000000..ee7116f
--- /dev/null
@@ -0,0 +1,477 @@
+//  Copyright (C) 2007-2010  CEA/DEN, EDF R&D
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU Lesser General Public
+//  License as published by the Free Software Foundation; either
+//  version 2.1 of the License.
+//
+//  This library is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  Lesser General Public License for more details.
+//
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+//  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+#include "InterpKernelAsmX86.hxx"
+
+#include <cstring>
+#include <sstream>
+#include <algorithm>
+
+const char *INTERP_KERNEL::AsmX86::OPS[NB_OF_OPS]={"mov","push","pop","fld","faddp","fsubp","fmulp","fdivp","fcos","fsin","fabs","fchs","fsqrt","sub","add","ret","leave","movsd","fst"};
+
+std::vector<char> INTERP_KERNEL::AsmX86::convertIntoMachineLangage(const std::vector<std::string>& asmb) const throw(INTERP_KERNEL::Exception)
+{
+  std::vector<char> ret;
+  for(std::vector<std::string>::const_iterator iter=asmb.begin();iter!=asmb.end();iter++)
+    convertOneInstructionInML(*iter,ret);
+  return ret;
+}
+
+char *INTERP_KERNEL::AsmX86::convertMachineLangageInBasic(const std::vector<char>& ml, int& lgth) const
+{
+  lgth=ml.size();
+  char *ret=new char[lgth];
+  std::copy(ml.begin(),ml.end(),ret);
+  return ret;
+}
+
+void INTERP_KERNEL::AsmX86::convertOneInstructionInML(const std::string& inst, std::vector<char>& ml) const throw(INTERP_KERNEL::Exception)
+{
+  std::string::size_type pos=inst.find_first_of(' ');
+  std::string op;
+  std::string param;
+  if(pos!=std::string::npos)
+    {
+      op=inst.substr(0,pos);
+      param=inst.substr(pos+1);
+    }
+  else
+    op=inst;
+  int id=0;
+  for(const char **it=OPS;it!=OPS+NB_OF_OPS;it++,id++)
+    {
+      std::string tmp(*it);
+      if(op==tmp)
+        break;
+    }
+  switch(id)
+    {
+    case 0:
+      convertMov(param,ml);
+      break;
+    case 1:
+      convertPush(param,ml);
+      break;
+    case 2:
+      convertPop(param,ml);
+      break;
+    case 3:
+      convertFld(param,ml);
+      break;
+    case 4:
+      convertFaddp(param,ml);
+      break;
+    case 5:
+      convertFsubp(param,ml);
+      break;
+    case 6:
+      convertFmulp(param,ml);
+      break;
+    case 7:
+      convertFdivp(param,ml);
+      break;
+    case 8:
+      convertFcos(param,ml);
+      break;
+    case 9:
+      convertFsin(param,ml);
+      break;
+    case 10:
+      convertFabs(param,ml);
+      break;
+    case 11:
+      convertFchs(param,ml);
+      break;
+    case 12:
+      convertFsqrt(param,ml);
+      break;
+    case 13:
+      convertSub(param,ml);
+      break;
+    case 14:
+      convertAdd(param,ml);
+      break;
+    case 15:
+      convertRet(param,ml);
+      break;
+    case 16:
+      convertLeave(param,ml);
+      break;
+    case 17:
+      convertMovsd(param,ml);
+      break;
+    case 18:
+      convertFst(param,ml);
+      break;
+    default:
+      {
+        std::ostringstream oss; oss << "Unrecognized op : " << op << " in assembly line : " << inst;
+        throw INTERP_KERNEL::Exception(oss.str().c_str());
+      }
+    }
+}
+
+#include <iostream>
+
+void INTERP_KERNEL::AsmX86::convertMov(const std::string& inst, std::vector<char>& ml) throw(INTERP_KERNEL::Exception)
+{
+  const char ASM1[]="ebp,esp";
+  const char ML1[2]={0x89,0xe5};
+  if(inst==ASM1)
+    {
+      ml.insert(ml.end(),ML1,ML1+sizeof(ML1));
+      return ;
+    }
+  const char ASM2[]="rbp,rsp";
+  const char ML2[3]={0x48,0x89,0xe5};
+  if(inst==ASM2)
+    {
+      ml.insert(ml.end(),ML2,ML2+sizeof(ML2));
+      return ;
+    }
+  std::string::size_type pos=inst.find_first_of(' ');
+  if(pos==std::string::npos)
+    {
+      std::ostringstream oss; oss << "not recognized instruction mov : " << inst;
+      throw INTERP_KERNEL::Exception(oss.str().c_str());
+    }
+  std::string inst2=inst.substr(pos+1);
+  pos=inst2.find_first_of(',');
+  if(pos==std::string::npos)
+    {
+      std::ostringstream oss; oss << "not recognized instruction mov : " << inst;
+      throw INTERP_KERNEL::Exception(oss.str().c_str());
+    }
+  std::string inst3=inst2.substr(0,pos);
+  std::string inst4=inst2.substr(pos+1);
+  convertMovToEsp(inst3,inst4,ml);
+}
+
+void INTERP_KERNEL::AsmX86::convertMovToEsp(const std::string& inst1, const std::string& inst2, std::vector<char>& ml) throw(INTERP_KERNEL::Exception)
+{
+  if(inst1[0]!='[' || inst1[inst1.length()-1]!=']')
+    throw INTERP_KERNEL::Exception("not recognized convertMovToEsp exp !");
+  std::string inst1bis=inst1.substr(1,inst1.length()-2);
+  const char ASM1[]="esp";
+  const char ML1[3]={0xc7,0x04,0x24};
+  if(inst1bis==ASM1)
+    {//mov dword [esp],0x3ff3c0ca
+      ml.insert(ml.end(),ML1,ML1+sizeof(ML1));
+      appendAddress(inst2,4,ml);
+      return ;
+    }
+  if(inst1bis.substr(0,3)==ASM1)
+    {
+      if(inst1bis[3]=='+')
+        {//mov dword [esp+4],0x3ff3c0ca
+          const char ML2[3]={0xc7,0x44,0x24};
+          ml.insert(ml.end(),ML2,ML2+sizeof(ML2));
+          std::string::size_type pos=inst1bis.find_first_of(']');
+          std::string inst1_1=inst1bis.substr(4,pos-4-1);
+          appendAddress(inst1_1,1,ml);
+          appendAddress(inst2,4,ml);
+          return;
+        }
+      else
+        throw INTERP_KERNEL::Exception("Not recognized exp : mov [esp@..],...");
+    }
+  const char ASM3[]="rsp";
+  const char ML3[3]={0xc7,0x04,0x24};
+  if(inst1bis==ASM3)
+    {//mov dword [rsp],0x3ff3c0ca
+      ml.insert(ml.end(),ML3,ML3+sizeof(ML3));
+      appendAddress(inst2,4,ml);
+      return ;
+    }
+  if(inst1bis.substr(0,3)==ASM3)
+    {
+      if(inst1bis[3]=='+')
+        {//mov dword [rsp+4],0x3ff3c0ca
+          const char ML2[3]={0xc7,0x44,0x24};
+          ml.insert(ml.end(),ML2,ML2+sizeof(ML2));
+          std::string::size_type pos=inst1bis.find_first_of(']');
+          std::string inst1_1=inst1bis.substr(4,pos-4-1);
+          appendAddress(inst1_1,1,ml);
+          appendAddress(inst2,4,ml);
+          return;
+        }
+      else
+        throw INTERP_KERNEL::Exception("Not recognized exp : mov [esp@..],...");
+    }
+  throw INTERP_KERNEL::Exception("Not recognized exp : mov");
+}
+
+void INTERP_KERNEL::AsmX86::convertPush(const std::string& inst, std::vector<char>& ml) throw(INTERP_KERNEL::Exception)
+{
+  std::string::size_type pos=inst.find_first_of(' ');
+  std::string inst2=inst.substr(pos+1);
+  const char ASM1[]="ebp";
+  const char ML1[1]={0x55};
+  if(inst2==ASM1)
+    {//push ebp
+      ml.insert(ml.end(),ML1,ML1+sizeof(ML1));
+      return ;
+    }
+  const char ASM2[]="ebx";
+  const char ML2[1]={0x53};
+  if(inst2==ASM2)
+    {//push ebx
+      ml.insert(ml.end(),ML2,ML2+sizeof(ML2));
+      return ;
+    }
+  const char ASM3[]="rbp";
+  const char ML3[1]={0x55};
+  if(inst2==ASM3)
+    {//push rbp
+      ml.insert(ml.end(),ML3,ML3+sizeof(ML3));
+      return ;
+    }
+  throw INTERP_KERNEL::Exception("Unrecognized push instruction");
+}
+
+void INTERP_KERNEL::AsmX86::convertPop(const std::string& inst, std::vector<char>& ml) throw(INTERP_KERNEL::Exception)
+{
+  std::string::size_type pos=inst.find_first_of(' ');
+  std::string inst2=inst.substr(pos+1);
+  const char ASM1[]="ebp";
+  const char ML1[1]={0x5d};
+  if(inst2==ASM1)
+    {//push ebp
+      ml.insert(ml.end(),ML1,ML1+sizeof(ML1));
+      return ;
+    }
+  const char ASM2[]="ebx";
+  const char ML2[1]={0x5b};
+  if(inst2==ASM2)
+    {//push ebx
+      ml.insert(ml.end(),ML2,ML2+sizeof(ML2));
+      return ;
+    }
+  throw INTERP_KERNEL::Exception("Unrecognized pop instruction");
+}
+
+void INTERP_KERNEL::AsmX86::convertFld(const std::string& inst, std::vector<char>& ml) throw(INTERP_KERNEL::Exception)
+{
+  std::string::size_type pos=inst.find_first_of(' ');
+  std::string params=inst.substr(pos+1);
+  std::string params2=params.substr(1,params.length()-2);
+  if(params2.substr(0,3)=="esp")
+    {
+      const char ML1[3]={0xdd,0x04,0x24};
+      if(params2.length()==3)
+        {//fld qword [esp]
+          ml.insert(ml.end(),ML1,ML1+sizeof(ML1));
+          return ;
+        }
+      pos=params2.find_first_of('+');
+      if(pos!=std::string::npos)
+        {//fld qword [esp+@]
+          ml.insert(ml.end(),ML1,ML1+sizeof(ML1));
+          std::string params3=params2.substr(pos+1);
+          appendAddress(params3,1,ml);
+          return ;
+        }
+      throw INTERP_KERNEL::Exception("Unrecognized fld esp...");
+    }
+  if(params2.substr(0,3)=="ebp")
+    {
+      const char ML2[2]={0xdd,0x45};
+      if(params2.length()==3)
+        {//fld qword [ebp]
+          ml.insert(ml.end(),ML2,ML2+sizeof(ML2));
+          ml.push_back(0);
+          return ;
+        }
+      pos=params2.find_first_of('+');
+      if(pos!=std::string::npos)
+        {//fld qword [esp+@]
+          ml.insert(ml.end(),ML2,ML2+sizeof(ML2));
+          std::string params3=params2.substr(pos+1);
+          appendAddress(params3,1,ml);
+          return ;
+        }
+      throw INTERP_KERNEL::Exception("Unrecognized fld ebp...");
+    }
+  if(params2.substr(0,3)=="rsp")
+    {
+      const char ML2[3]={0xdd,0x04,0x24};
+      ml.insert(ml.end(),ML2,ML2+sizeof(ML2));// to improve ! no fully managed !
+      return ;
+    }
+  throw INTERP_KERNEL::Exception("Unrecognized fld instruction");
+}
+
+void INTERP_KERNEL::AsmX86::convertFaddp(const std::string& inst, std::vector<char>& ml) throw(INTERP_KERNEL::Exception)
+{
+  const char ML1[2]={0xde,0xc1};
+  ml.insert(ml.end(),ML1,ML1+sizeof(ML1));
+}
+
+void INTERP_KERNEL::AsmX86::convertFsubp(const std::string& inst, std::vector<char>& ml) throw(INTERP_KERNEL::Exception)
+{
+  const char ML1[2]={0xde,0xe9};
+  ml.insert(ml.end(),ML1,ML1+sizeof(ML1));
+}
+
+void INTERP_KERNEL::AsmX86::convertFmulp(const std::string& inst, std::vector<char>& ml) throw(INTERP_KERNEL::Exception)
+{
+  const char ML1[2]={0xde,0xc9};
+  ml.insert(ml.end(),ML1,ML1+sizeof(ML1));
+}
+
+void INTERP_KERNEL::AsmX86::convertFdivp(const std::string& inst, std::vector<char>& ml) throw(INTERP_KERNEL::Exception)
+{
+  const char ML1[2]={0xde,0xf9};
+  ml.insert(ml.end(),ML1,ML1+sizeof(ML1));
+}
+
+void INTERP_KERNEL::AsmX86::convertFcos(const std::string& inst, std::vector<char>& ml) throw(INTERP_KERNEL::Exception)
+{
+  const char ML[2]={0xd9,0xff};
+  ml.insert(ml.end(),ML,ML+sizeof(ML));
+}
+
+void INTERP_KERNEL::AsmX86::convertFsin(const std::string& inst, std::vector<char>& ml) throw(INTERP_KERNEL::Exception)
+{
+  const char ML[2]={0xd9,0xfe};
+  ml.insert(ml.end(),ML,ML+sizeof(ML));
+}
+
+void INTERP_KERNEL::AsmX86::convertFabs(const std::string& inst, std::vector<char>& ml) throw(INTERP_KERNEL::Exception)
+{
+  const char ML[2]={0xd9,0xe1};
+  ml.insert(ml.end(),ML,ML+sizeof(ML));
+}
+
+void INTERP_KERNEL::AsmX86::convertFchs(const std::string& inst, std::vector<char>& ml) throw(INTERP_KERNEL::Exception)
+{
+  const char ML[2]={0xd9,0xe0};
+  ml.insert(ml.end(),ML,ML+sizeof(ML));
+}
+
+void INTERP_KERNEL::AsmX86::convertFsqrt(const std::string& inst, std::vector<char>& ml) throw(INTERP_KERNEL::Exception)
+{
+  const char ML[2]={0xd9,0xfa};
+  ml.insert(ml.end(),ML,ML+sizeof(ML));
+}
+
+void INTERP_KERNEL::AsmX86::convertSub(const std::string& inst, std::vector<char>& ml) throw(INTERP_KERNEL::Exception)
+{
+  if(inst.substr(0,4)=="esp,")
+    {
+      const char ML[2]={0x81,0xec};
+      ml.insert(ml.end(),ML,ML+sizeof(ML));
+      std::string inst2=inst.substr(4);
+      appendAddress(inst2,4,ml);
+      return;
+    }
+  if(inst.substr(0,4)=="rsp,")
+    {
+      const char ML[4]={0x48,0x83,0xec,0x08};
+      ml.insert(ml.end(),ML,ML+sizeof(ML)); // to improve 8 statically put (last of element of ML) !!!!
+      return;
+    }
+  throw INTERP_KERNEL::Exception("Not recognized sub instruction.");
+}
+
+void INTERP_KERNEL::AsmX86::convertAdd(const std::string& inst, std::vector<char>& ml) throw(INTERP_KERNEL::Exception)
+{
+  if(inst.substr(0,4)=="esp,")
+    {
+      const char ML[2]={0x81,0xc4};
+      ml.insert(ml.end(),ML,ML+sizeof(ML));
+      std::string inst2=inst.substr(4);
+      appendAddress(inst2,4,ml);
+      return;
+    }
+  if(inst.substr(0,4)=="rsp,")
+    {
+      const char ML[4]={0x48,0x83,0xc4,0x08};
+      ml.insert(ml.end(),ML,ML+sizeof(ML)); // to improve 8 statically put (last of element of ML) !!!!
+      return;
+    }
+  throw INTERP_KERNEL::Exception("Not recognized add instruction.");
+}
+
+void INTERP_KERNEL::AsmX86::convertRet(const std::string& inst, std::vector<char>& ml) throw(INTERP_KERNEL::Exception)
+{
+  const char ML[1]={0xc3};
+  ml.insert(ml.end(),ML,ML+sizeof(ML));
+}
+
+void INTERP_KERNEL::AsmX86::convertLeave(const std::string& inst, std::vector<char>& ml) throw(INTERP_KERNEL::Exception)
+{
+  const char ML[1]={0xc9};
+  ml.insert(ml.end(),ML,ML+sizeof(ML));
+}
+
+void INTERP_KERNEL::AsmX86::convertMovsd(const std::string& inst, std::vector<char>& ml) throw(INTERP_KERNEL::Exception)
+{
+  const char ASM1[]="[rsp],xmm0";
+  const char ML1[5]={0xf2,0x0f,0x11,0x04,0x24};
+  if(inst==ASM1)
+    {
+      ml.insert(ml.end(),ML1,ML1+sizeof(ML1));
+      return ;
+    }
+  const char ASM2[]="xmm0,[rsp]";
+  const char ML2[5]={0xf2,0x0f,0x10,0x04,0x24};
+  if(inst==ASM2)
+    {
+      ml.insert(ml.end(),ML2,ML2+sizeof(ML2));
+      return ;
+    }
+  std::ostringstream oss; oss << "not recognized instruction movsd : " << inst;
+  throw INTERP_KERNEL::Exception(oss.str().c_str());
+}
+
+void INTERP_KERNEL::AsmX86::convertFst(const std::string& inst, std::vector<char>& ml) throw(INTERP_KERNEL::Exception)
+{
+  const char ASM1[]="qword [rsp]";
+  const char ML1[3]={0xdd,0x14,0x24};
+  if(inst==ASM1)
+    {
+      ml.insert(ml.end(),ML1,ML1+sizeof(ML1));
+      return ;
+    }
+  std::ostringstream oss; oss << "not recognized instruction fst : " << inst;
+  throw INTERP_KERNEL::Exception(oss.str().c_str());
+  //tony
+}
+
+
+void INTERP_KERNEL::AsmX86::appendAddress(const std::string& addr, int nbOfByte, std::vector<char>& ml) throw(INTERP_KERNEL::Exception)
+{
+  int i,j;
+  char v;
+  std::istringstream iss(addr);
+  if(addr.length()>2)
+    {
+      if(addr[0]=='0' && addr[1]=='x')
+        iss >> std::hex;
+    }
+  iss >> i;
+  for(int k=0;k<nbOfByte;k++)
+    {
+      j=i&255;
+      v=j;
+      ml.push_back(v);
+      i>>=8;
+    }
+}
diff --git a/src/INTERP_KERNEL/ExprEval/InterpKernelAsmX86.hxx b/src/INTERP_KERNEL/ExprEval/InterpKernelAsmX86.hxx
new file mode 100644 (file)
index 0000000..11b8733
--- /dev/null
@@ -0,0 +1,67 @@
+//  Copyright (C) 2007-2010  CEA/DEN, EDF R&D
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU Lesser General Public
+//  License as published by the Free Software Foundation; either
+//  version 2.1 of the License.
+//
+//  This library is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  Lesser General Public License for more details.
+//
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+//  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+#ifndef __INTERPKERNELASMX86_HXX__
+#define __INTERPKERNELASMX86_HXX__
+
+#include "INTERPKERNELEXPREVALDefines.hxx"
+#include "InterpKernelException.hxx"
+
+#include <vector>
+#include <string>
+
+namespace INTERP_KERNEL
+{
+  class AsmX86
+  {
+  public:
+    std::vector<char> convertIntoMachineLangage(const std::vector<std::string>& asmb) const throw(INTERP_KERNEL::Exception);
+    char *convertMachineLangageInBasic(const std::vector<char>& ml, int& lgth) const;
+  private:
+    void convertOneInstructionInML(const std::string& inst, std::vector<char>& ml) const throw(INTERP_KERNEL::Exception);
+  private:
+    static void convertMov(const std::string& inst, std::vector<char>& ml) throw(INTERP_KERNEL::Exception);
+    static void convertPush(const std::string& inst, std::vector<char>& ml) throw(INTERP_KERNEL::Exception);
+    static void convertPop(const std::string& inst, std::vector<char>& ml) throw(INTERP_KERNEL::Exception);
+    static void convertFld(const std::string& inst, std::vector<char>& ml) throw(INTERP_KERNEL::Exception);
+    static void convertFaddp(const std::string& inst, std::vector<char>& ml) throw(INTERP_KERNEL::Exception);
+    static void convertFsubp(const std::string& inst, std::vector<char>& ml) throw(INTERP_KERNEL::Exception);
+    static void convertFmulp(const std::string& inst, std::vector<char>& ml) throw(INTERP_KERNEL::Exception);
+    static void convertFdivp(const std::string& inst, std::vector<char>& ml) throw(INTERP_KERNEL::Exception);
+    static void convertFcos(const std::string& inst, std::vector<char>& ml) throw(INTERP_KERNEL::Exception);
+    static void convertFsin(const std::string& inst, std::vector<char>& ml) throw(INTERP_KERNEL::Exception);
+    static void convertFabs(const std::string& inst, std::vector<char>& ml) throw(INTERP_KERNEL::Exception);
+    static void convertFchs(const std::string& inst, std::vector<char>& ml) throw(INTERP_KERNEL::Exception);
+    static void convertFsqrt(const std::string& inst, std::vector<char>& ml) throw(INTERP_KERNEL::Exception);
+    static void convertSub(const std::string& inst, std::vector<char>& ml) throw(INTERP_KERNEL::Exception);
+    static void convertAdd(const std::string& inst, std::vector<char>& ml) throw(INTERP_KERNEL::Exception);
+    static void convertRet(const std::string& inst, std::vector<char>& ml) throw(INTERP_KERNEL::Exception);
+    static void convertLeave(const std::string& inst, std::vector<char>& ml) throw(INTERP_KERNEL::Exception);
+    static void convertMovsd(const std::string& inst, std::vector<char>& ml) throw(INTERP_KERNEL::Exception);
+    static void convertFst(const std::string& inst, std::vector<char>& ml) throw(INTERP_KERNEL::Exception);
+    //
+    static void convertMovToEsp(const std::string& inst1, const std::string& inst2, std::vector<char>& ml) throw(INTERP_KERNEL::Exception);
+    static void appendAddress(const std::string& addr, int nbOfByte, std::vector<char>& ml) throw(INTERP_KERNEL::Exception);
+  private:
+    static const int NB_OF_OPS=19;
+    static const char *OPS[NB_OF_OPS];
+  };
+}
+
+#endif
index 5dde84961d5cebec8b5d5743b489a79010340ef6..585fac2f832a1ff3d6c4162e90854de62a304efb 100644 (file)
 
 #include "InterpKernelExprParser.hxx"
 #include "InterpKernelValue.hxx"
+#include "InterpKernelAsmX86.hxx"
 
 #include <cctype>
 #include <sstream>
 #include <vector>
 #include <iterator>
+#include <iostream>
 #include <algorithm>
 
+#ifdef _POSIX_MAPPED_FILES
+#include <sys/mman.h>
+#else
+#ifdef WNT
+#include <windows.h>
+#endif
+#endif
+
 using namespace INTERP_KERNEL;
 
 const char LeafExprVar::END_OF_RECOGNIZED_VAR[]="Vec";
@@ -120,12 +130,12 @@ LeafExprVar::~LeafExprVar()
 {
 }
 
-ExprParser::ExprParser(const char *expr):_is_parsed(false),_leaf(0),_is_parsing_ok(false),_expr(expr)
+ExprParser::ExprParser(const char *expr, ExprParser *father):_father(father),_is_parsed(false),_leaf(0),_is_parsing_ok(false),_expr(expr)
 {
 }
 
 //! For \b NOT null terminated strings coming from FORTRAN.
-ExprParser::ExprParser(const char *expr, int lgth):_is_parsed(false),_leaf(0),_is_parsing_ok(false)
+ExprParser::ExprParser(const char *expr, int lgth, ExprParser *father):_father(father),_is_parsed(false),_leaf(0),_is_parsing_ok(false)
 {
   _expr=buildStringFromFortran(expr,lgth);
 }
@@ -228,7 +238,7 @@ DecompositionInUnitBase ExprParser::evaluateUnit() const throw(INTERP_KERNEL::Ex
   return ret;
 }
 
-void ExprParser::evaluateExpr(int szOfOutParam, double *outParam, const double *inParam) const throw(INTERP_KERNEL::Exception)
+void ExprParser::evaluateExpr(int szOfOutParam, const double *inParam, double *outParam) const throw(INTERP_KERNEL::Exception)
 {
   Value *gen=new ValueDoubleExpr(szOfOutParam,inParam);
   ValueDoubleExpr *res=0;
@@ -404,7 +414,7 @@ void ExprParser::parseUnaryFunc() throw(INTERP_KERNEL::Exception)
       if(pos5!=std::string::npos)
         len=pos5-pos6;
       std::string newExp3=newExp2.substr(pos6,len);
-      _sub_expr.push_back(ExprParser(newExp3.c_str()));
+      _sub_expr.push_back(ExprParser(newExp3.c_str(),this));
       pos6=pos5+1;
     }
   _is_parsing_ok=true;
@@ -456,7 +466,7 @@ void ExprParser::parseForAddMin() throw(INTERP_KERNEL::Exception)
                   if(*accessor!='*' && *accessor!='/' && *accessor!='^')
                     {
                       isParsingSucceed=true;
-                      _sub_expr.push_back(ExprParser(curPart.c_str()));
+                      _sub_expr.push_back(ExprParser(curPart.c_str(),this));
                       curPart.clear();
                       _func_btw_sub_expr.push_back(FunctionsFactory::buildBinaryFuncFromString(*iter));
                     }
@@ -483,7 +493,7 @@ void ExprParser::parseForAddMin() throw(INTERP_KERNEL::Exception)
     {
       if(!curPart.empty())
         {
-          _sub_expr.push_back(ExprParser(curPart.c_str()));
+          _sub_expr.push_back(ExprParser(curPart.c_str(),this));
           _is_parsing_ok=true;
         }
       else
@@ -515,7 +525,7 @@ void ExprParser::parseForMulDiv() throw(INTERP_KERNEL::Exception)
               isParsingSucceed=true;
               if(!curPart.empty())
                 {
-                  _sub_expr.push_back(ExprParser(curPart.c_str()));
+                  _sub_expr.push_back(ExprParser(curPart.c_str(),this));
                   curPart.clear();
                   _func_btw_sub_expr.push_back(FunctionsFactory::buildBinaryFuncFromString(*iter));
                 }
@@ -546,7 +556,7 @@ void ExprParser::parseForMulDiv() throw(INTERP_KERNEL::Exception)
     {
       if(!curPart.empty())
         {
-          _sub_expr.push_back(ExprParser(curPart.c_str()));
+          _sub_expr.push_back(ExprParser(curPart.c_str(),this));
           _is_parsing_ok=true;
         }
       else
@@ -576,7 +586,7 @@ void ExprParser::parseForPow() throw(INTERP_KERNEL::Exception)
             if(!curPart.empty())
               {
                 isParsingSucceed=true;
-                _sub_expr.push_back(ExprParser(curPart.c_str()));
+                _sub_expr.push_back(ExprParser(curPart.c_str(),this));
                 curPart.clear();
                 _func_btw_sub_expr.push_back(FunctionsFactory::buildBinaryFuncFromString(*iter));
               }
@@ -606,7 +616,7 @@ void ExprParser::parseForPow() throw(INTERP_KERNEL::Exception)
     {
       if(!curPart.empty())
         {
-          _sub_expr.push_back(ExprParser(curPart.c_str()));
+          _sub_expr.push_back(ExprParser(curPart.c_str(),this));
           _is_parsing_ok=true;
         }
       else
@@ -691,3 +701,169 @@ void ExprParser::locateError(std::ostream& stringToDisp, const std::string& srcO
 {
   stringToDisp << "Position is " << posOfErr << " of string : \"" <<  srcOfErr << "\"" << std::endl;
 }
+
+char *ExprParser::compileX86() const
+{
+  std::vector<std::string> ass;
+  //need in stack
+  ass.push_back("push ebp");
+  ass.push_back("mov ebp,esp");
+  compileX86LowLev(ass);
+  ass.push_back("pop ebp");
+  ass.push_back("ret");
+  std::cout << std::endl;
+  for(std::vector<std::string>::const_iterator iter=ass.begin();iter!=ass.end();iter++)
+    std::cout << "        " << *iter << std::endl;
+  AsmX86 asmb;
+  std::vector<char> output=asmb.convertIntoMachineLangage(ass);
+  for(std::vector<char>::const_iterator iter=output.begin();iter!=output.end();iter++)
+    std::cout << std::hex << (int)((unsigned char)(*iter)) << " ";
+  std::cout << std::endl;
+  int lgth;
+  char *lm=asmb.convertMachineLangageInBasic(output,lgth);
+  char *ret=0;
+#ifdef _POSIX_MAPPED_FILES
+  ret=(char *)mmap(0,lgth,PROT_EXEC | PROT_WRITE,MAP_ANONYMOUS | MAP_PRIVATE,-1,0);
+#else
+#ifdef WNT
+  HANDLE h=CreateFileMapping(INVALID_HANDLE_VALUE,NULL,PAGE_EXECUTE_READWRITE,0,lgth,NULL);
+  ret=(char *)MapViewOfFile(h,FILE_MAP_EXECUTE | FILE_MAP_READ | FILE_MAP_WRITE,0,0,lgth);
+#endif
+#endif
+  if(ret)
+    std::copy(lm,lm+lgth,ret);
+  delete [] lm;
+  return ret;
+}
+
+char *ExprParser::compileX86_64() const
+{
+  std::vector<std::string> ass;
+  //need in stack
+  ass.push_back("push rbp");
+  ass.push_back("mov rbp,rsp");
+  compileX86_64LowLev(ass);
+  ass.push_back("sub rsp,8");
+  ass.push_back("fst qword [rsp]");
+  ass.push_back("movsd xmm0,[rsp]");
+  ass.push_back("add rsp,8");
+  ass.push_back("leave");
+  ass.push_back("ret");
+  std::cout << std::endl;
+  for(std::vector<std::string>::const_iterator iter=ass.begin();iter!=ass.end();iter++)
+    std::cout << "        " << *iter << std::endl;
+  AsmX86 asmb;
+  std::vector<char> output=asmb.convertIntoMachineLangage(ass);
+  for(std::vector<char>::const_iterator iter=output.begin();iter!=output.end();iter++)
+    std::cout << std::hex << (int)((unsigned char)(*iter)) << " ";
+  std::cout << std::endl;
+  int lgth;
+  char *lm=asmb.convertMachineLangageInBasic(output,lgth);
+  char *ret=0;
+#ifdef _POSIX_MAPPED_FILES
+  ret=(char *)mmap(0,lgth,PROT_EXEC | PROT_WRITE,MAP_ANONYMOUS | MAP_PRIVATE,-1,0);
+#else
+#ifdef WNT
+  HANDLE h=CreateFileMapping(INVALID_HANDLE_VALUE,NULL,PAGE_EXECUTE_READWRITE,0,lgth,NULL);
+  ret=(char *)MapViewOfFile(h,FILE_MAP_EXECUTE | FILE_MAP_READ | FILE_MAP_WRITE,0,0,lgth);
+#endif
+#endif
+  if(ret)
+    std::copy(lm,lm+lgth,ret);
+  delete [] lm;
+  return ret;
+}
+
+void ExprParser::compileX86LowLev(std::vector<std::string>& ass) const
+{
+  if(_leaf)
+    _leaf->compileX86(ass);
+  else
+    {
+      for(std::list<ExprParser>::const_iterator iter=_sub_expr.begin();iter!=_sub_expr.end();iter++)
+        (*iter).compileX86LowLev(ass);
+      for(std::list<Function *>::const_iterator iter2=_func_btw_sub_expr.begin();iter2!=_func_btw_sub_expr.end();iter2++)
+        (*iter2)->operateX86(ass);
+    }
+}
+
+void ExprParser::compileX86_64LowLev(std::vector<std::string>& ass) const
+{
+  if(_leaf)
+    _leaf->compileX86_64(ass);
+  else
+    {
+      for(std::list<ExprParser>::const_iterator iter=_sub_expr.begin();iter!=_sub_expr.end();iter++)
+        (*iter).compileX86_64LowLev(ass);
+      for(std::list<Function *>::const_iterator iter2=_func_btw_sub_expr.begin();iter2!=_func_btw_sub_expr.end();iter2++)
+        (*iter2)->operateX86(ass);
+    }
+}
+
+void LeafExprVal::compileX86(std::vector<std::string>& ass) const
+{
+  ass.push_back("sub esp,8");
+  int *b=(int *)&_value,*c=(int *)&_value;
+  c++;
+  std::ostringstream oss;
+  oss << std::hex;
+  oss << "mov dword [esp+4],0x" << *c;
+  ass.push_back(oss.str());
+  oss.str("");
+  oss << "mov dword [esp],0x" << *b;
+  ass.push_back(oss.str());
+  ass.push_back("fld qword [esp]");
+  ass.push_back("add esp,8");
+}
+
+void LeafExprVal::compileX86_64(std::vector<std::string>& ass) const
+{
+  ass.push_back("sub rsp,8");
+  int *b=(int *)&_value,*c=(int *)&_value;
+  c++;
+  std::ostringstream oss;
+  oss << std::hex;
+  oss << "mov dword [rsp+4],0x" << *c;
+  ass.push_back(oss.str());
+  oss.str("");
+  oss << "mov dword [rsp],0x" << *b;
+  ass.push_back(oss.str());
+  ass.push_back("fld qword [rsp]");
+  ass.push_back("add rsp,8");
+}
+
+void LeafExprVar::compileX86(std::vector<std::string>& ass) const
+{
+  ass.push_back("fld qword [ebp+8]");
+}
+
+void LeafExprVar::compileX86_64(std::vector<std::string>& ass) const
+{
+  ass.push_back("sub rsp,8");
+  ass.push_back("movsd [rsp],xmm0");
+  ass.push_back("fld qword [rsp]");
+  ass.push_back("add rsp,8");
+}
+
+int ExprParser::getStackSizeToPlayX86(const ExprParser *asker) const
+{
+  if(asker)
+    {
+      int sz=_father->getStackSizeToPlayX86(this);
+      int i=0;
+      for(std::list<ExprParser>::const_reverse_iterator iter=_sub_expr.rbegin();iter!=_sub_expr.rend();iter++,i++)
+        {
+          const ExprParser& obj=(*iter);
+          const ExprParser *pt=&obj;
+          if(pt==asker)
+            return sz-i;
+        }
+      throw INTERP_KERNEL::Exception("error getStackSizeToPlayX86 an object ExprParser called as father, whereas it is not one !");
+    }
+  else
+    {
+      if(!_father)
+        return MAX_X86_FP_ST;
+      return _father->getStackSizeToPlayX86(this);
+    }
+}
index 032f7070afe8175b9d569eaab8aabd332d3e7835..7ff8babb57eb193d2983fb4540041f375a78f3c7 100644 (file)
@@ -39,6 +39,8 @@ namespace INTERP_KERNEL
   public:
     virtual ~LeafExpr();
     virtual void fillValue(Value *val) const throw(INTERP_KERNEL::Exception) = 0;
+    virtual void compileX86(std::vector<std::string>& ass) const = 0;
+    virtual void compileX86_64(std::vector<std::string>& ass) const = 0;
     static LeafExpr *buildInstanceFrom(const std::string& expr) throw(INTERP_KERNEL::Exception);
   };
 
@@ -47,6 +49,8 @@ namespace INTERP_KERNEL
   public:
     LeafExprVal(double value);
     ~LeafExprVal();
+    void compileX86(std::vector<std::string>& ass) const;
+    void compileX86_64(std::vector<std::string>& ass) const;
     void fillValue(Value *val) const throw(INTERP_KERNEL::Exception);
   private:
     double _value;
@@ -57,6 +61,8 @@ namespace INTERP_KERNEL
   public:
     LeafExprVar(const std::string& var);
     ~LeafExprVar();
+    void compileX86(std::vector<std::string>& ass) const;
+    void compileX86_64(std::vector<std::string>& ass) const;
     void fillValue(Value *val) const throw(INTERP_KERNEL::Exception);
     std::string getVar() const { return _var_name; }
     void prepareExprEvaluation(const std::vector<std::string>& vars) const throw(INTERP_KERNEL::Exception);
@@ -72,18 +78,25 @@ namespace INTERP_KERNEL
   class INTERPKERNELEXPREVAL_EXPORT ExprParser
   {
   public:
-    ExprParser(const char *expr);
-    ExprParser(const char *expr, int lgth);
+    ExprParser(const char *expr, ExprParser *father=0);
+    ExprParser(const char *expr, int lgth, ExprParser *father=0);
     ~ExprParser();
     void parse() throw(INTERP_KERNEL::Exception);
     bool isParsingSuccessfull() const { return _is_parsing_ok; }
     double evaluate() const throw(INTERP_KERNEL::Exception);
     DecompositionInUnitBase evaluateUnit() const throw(INTERP_KERNEL::Exception);
     void prepareExprEvaluation(const std::vector<std::string>& vars) const throw(INTERP_KERNEL::Exception);
-    void evaluateExpr(int szOfOutParam, double *outParam, const double *inParam) const throw(INTERP_KERNEL::Exception);
+    void evaluateExpr(int szOfOutParam, const double *inParam, double *outParam) const throw(INTERP_KERNEL::Exception);
     void prepareExprEvaluationVec() const throw(INTERP_KERNEL::Exception);
     void getSetOfVars(std::set<std::string>& vars) const;
     void getTrueSetOfVars(std::set<std::string>& vars) const;
+    //
+    char *compileX86() const;
+    char *compileX86_64() const;
+    void compileX86LowLev(std::vector<std::string>& ass) const;
+    void compileX86_64LowLev(std::vector<std::string>& ass) const;
+    int getStackSizeToPlayX86(const ExprParser *asker) const;
+    //
     static std::string buildStringFromFortran(const char *expr, int lgth);
     static std::string deleteWhiteSpaces(const std::string& expr);
   private:
@@ -102,6 +115,7 @@ namespace INTERP_KERNEL
     static std::size_t findCorrespondingOpenBracket(const std::string& expr, std::size_t posOfCloseBracket);
     static void locateError(std::ostream& stringToDisp, const std::string& srcOfErr, int posOfErr);
   private:
+    ExprParser *_father;
     bool _is_parsed;
     LeafExpr *_leaf;
     bool _is_parsing_ok;
@@ -109,6 +123,7 @@ namespace INTERP_KERNEL
     std::list<ExprParser> _sub_expr;
     std::list<Function *> _func_btw_sub_expr;
   private:
+    static const int MAX_X86_FP_ST=8;
     static const char WHITE_SPACES[];
     static const char EXPR_PARSE_ERR_MSG[];
   };
index 6e8316526a41e0dd4c949b00d6ee04604f21cfbf..dd16329f6d43afacacdb496ecb4b973be26458b2 100644 (file)
@@ -140,6 +140,10 @@ void IdentityFunction::operate(std::vector<Value *>& stack) const throw(INTERP_K
 {
 }
 
+void IdentityFunction::operateX86(std::vector<std::string>& asmb) const throw(INTERP_KERNEL::Exception)
+{
+}
+
 const char *IdentityFunction::getRepr() const
 {
   return REPR;
@@ -163,6 +167,10 @@ void PositiveFunction::operate(std::vector<Value *>& stack) const throw(INTERP_K
 {
 }
 
+void PositiveFunction::operateX86(std::vector<std::string>& asmb) const throw(INTERP_KERNEL::Exception)
+{
+}
+
 const char *PositiveFunction::getRepr() const
 {
   return REPR;
@@ -183,6 +191,11 @@ void NegateFunction::operate(std::vector<Value *>& stack) const throw(INTERP_KER
   val->negate();
 }
 
+void NegateFunction::operateX86(std::vector<std::string>& asmb) const throw(INTERP_KERNEL::Exception)
+{
+  asmb.push_back("fchs");
+}
+
 const char *NegateFunction::getRepr() const
 {
   return REPR;
@@ -203,6 +216,11 @@ void CosFunction::operate(std::vector<Value *>& stack) const throw(INTERP_KERNEL
   val->cos();
 }
 
+void CosFunction::operateX86(std::vector<std::string>& asmb) const throw(INTERP_KERNEL::Exception)
+{
+  asmb.push_back("fcos");
+}
+
 const char *CosFunction::getRepr() const
 {
   return REPR;
@@ -223,6 +241,11 @@ void SinFunction::operate(std::vector<Value *>& stack) const throw(INTERP_KERNEL
   val->sin();
 }
 
+void SinFunction::operateX86(std::vector<std::string>& asmb) const throw(INTERP_KERNEL::Exception)
+{
+  asmb.push_back("fsin");
+}
+
 const char *SinFunction::getRepr() const
 {
   return REPR;
@@ -243,6 +266,11 @@ void TanFunction::operate(std::vector<Value *>& stack) const throw(INTERP_KERNEL
   val->tan();
 }
 
+void TanFunction::operateX86(std::vector<std::string>& asmb) const throw(INTERP_KERNEL::Exception)
+{
+  throw INTERP_KERNEL::Exception("Assembly Not implemented yet !");
+}
+
 const char *TanFunction::getRepr() const
 {
   return REPR;
@@ -263,6 +291,11 @@ void SqrtFunction::operate(std::vector<Value *>& stack) const throw(INTERP_KERNE
   val->sqrt();
 }
 
+void SqrtFunction::operateX86(std::vector<std::string>& asmb) const throw(INTERP_KERNEL::Exception)
+{
+  asmb.push_back("fsqrt");
+}
+
 const char *SqrtFunction::getRepr() const
 {
   return REPR;
@@ -283,6 +316,11 @@ void AbsFunction::operate(std::vector<Value *>& stack) const throw(INTERP_KERNEL
   val->abs();
 }
 
+void AbsFunction::operateX86(std::vector<std::string>& asmb) const throw(INTERP_KERNEL::Exception)
+{
+  asmb.push_back("fabs");
+}
+
 const char *AbsFunction::getRepr() const
 {
   return REPR;
@@ -298,7 +336,12 @@ void ExpFunction::operate(std::vector<Value *>& stack) const throw(INTERP_KERNEL
   Value *val=stack.back();
   val->exp();
 }
+
+void ExpFunction::operateX86(std::vector<std::string>& asmb) const throw(INTERP_KERNEL::Exception)
+{
+  throw INTERP_KERNEL::Exception("Assembly Not implemented yet !");
+}
+
 const char *ExpFunction::getRepr() const
 {
   return REPR;
@@ -319,6 +362,11 @@ void LnFunction::operate(std::vector<Value *>& stack) const throw(INTERP_KERNEL:
   val->ln();
 }
 
+void LnFunction::operateX86(std::vector<std::string>& asmb) const throw(INTERP_KERNEL::Exception)
+{
+  throw INTERP_KERNEL::Exception("Assembly Not implemented yet !");
+}
+
 const char *LnFunction::getRepr() const
 {
   return REPR;
@@ -358,6 +406,11 @@ void PlusFunction::operate(std::vector<Value *>& stack) const throw(INTERP_KERNE
   val2=val3;
 }
 
+void PlusFunction::operateX86(std::vector<std::string>& asmb) const throw(INTERP_KERNEL::Exception)
+{
+  asmb.push_back("faddp st1");
+}
+
 const char *PlusFunction::getRepr() const
 {
   return REPR;
@@ -392,6 +445,11 @@ void MinusFunction::operate(std::vector<Value *>& stack) const throw(INTERP_KERN
   val2=val3;
 }
 
+void MinusFunction::operateX86(std::vector<std::string>& asmb) const throw(INTERP_KERNEL::Exception)
+{
+  asmb.push_back("fsubp st1");
+}
+
 const char *MinusFunction::getRepr() const
 {
   return REPR;
@@ -417,6 +475,11 @@ void MultFunction::operate(std::vector<Value *>& stack) const throw(INTERP_KERNE
   val2=val3;
 }
 
+void MultFunction::operateX86(std::vector<std::string>& asmb) const throw(INTERP_KERNEL::Exception)
+{
+  asmb.push_back("fmulp st1");
+}
+
 const char *MultFunction::getRepr() const
 {
   return REPR;
@@ -451,6 +514,11 @@ void DivFunction::operate(std::vector<Value *>& stack) const throw(INTERP_KERNEL
   val2=val3;
 }
 
+void DivFunction::operateX86(std::vector<std::string>& asmb) const throw(INTERP_KERNEL::Exception)
+{
+  asmb.push_back("fdivp st1");
+}
+
 const char *DivFunction::getRepr() const
 {
   return REPR;
@@ -485,6 +553,11 @@ void PowFunction::operate(std::vector<Value *>& stack) const throw(INTERP_KERNEL
   val2=val3;
 }
 
+void PowFunction::operateX86(std::vector<std::string>& asmb) const throw(INTERP_KERNEL::Exception)
+{
+  throw INTERP_KERNEL::Exception("Assembly Not implemented yet !");
+}
+
 const char *PowFunction::getRepr() const
 {
   return REPR;
@@ -523,6 +596,11 @@ void MaxFunction::operate(std::vector<Value *>& stack) const throw(INTERP_KERNEL
   val2=val3;
 }
 
+void MaxFunction::operateX86(std::vector<std::string>& asmb) const throw(INTERP_KERNEL::Exception)
+{
+  throw INTERP_KERNEL::Exception("Assembly Not implemented yet !");
+}
+
 const char *MaxFunction::getRepr() const
 {
   return REPR;
@@ -557,6 +635,11 @@ void MinFunction::operate(std::vector<Value *>& stack) const throw(INTERP_KERNEL
   val2=val3;
 }
 
+void MinFunction::operateX86(std::vector<std::string>& asmb) const throw(INTERP_KERNEL::Exception)
+{
+  throw INTERP_KERNEL::Exception("Assembly Not implemented yet !");
+}
+
 const char *MinFunction::getRepr() const
 {
   return REPR;
index 548a09f1edf68afc050d0bb825150c60029c438d..160e15ba92031c0d880a4d62d5cb074277114485 100644 (file)
@@ -46,6 +46,7 @@ namespace INTERP_KERNEL
     virtual ~Function();
     virtual int getNbInputParams() const = 0;
     virtual void operate(std::vector<Value *>& stack) const throw(INTERP_KERNEL::Exception) = 0;
+    virtual void operateX86(std::vector<std::string>& asmb) const throw(INTERP_KERNEL::Exception) = 0;
     virtual const char *getRepr() const = 0;
     virtual bool isACall() const = 0;
   };
@@ -61,6 +62,7 @@ namespace INTERP_KERNEL
   public:
     ~IdentityFunction();
     void operate(std::vector<Value *>& stack) const throw(INTERP_KERNEL::Exception);
+    void operateX86(std::vector<std::string>& asmb) const throw(INTERP_KERNEL::Exception);
     const char *getRepr() const;
     bool isACall() const;
   public:
@@ -72,6 +74,7 @@ namespace INTERP_KERNEL
   public:
     ~PositiveFunction();
     void operate(std::vector<Value *>& stack) const throw(INTERP_KERNEL::Exception);
+    void operateX86(std::vector<std::string>& asmb) const throw(INTERP_KERNEL::Exception);
     const char *getRepr() const;
     bool isACall() const;
   public:
@@ -83,6 +86,7 @@ namespace INTERP_KERNEL
   public:
     ~NegateFunction();
     void operate(std::vector<Value *>& stack) const throw(INTERP_KERNEL::Exception);
+    void operateX86(std::vector<std::string>& asmb) const throw(INTERP_KERNEL::Exception);
     const char *getRepr() const;
     bool isACall() const;
   public:
@@ -94,6 +98,7 @@ namespace INTERP_KERNEL
   public:
     ~CosFunction();
     void operate(std::vector<Value *>& stack) const throw(INTERP_KERNEL::Exception);
+    void operateX86(std::vector<std::string>& asmb) const throw(INTERP_KERNEL::Exception);
     const char *getRepr() const;
     bool isACall() const;
   public:
@@ -105,6 +110,7 @@ namespace INTERP_KERNEL
   public:
     ~SinFunction();
     void operate(std::vector<Value *>& stack) const throw(INTERP_KERNEL::Exception);
+    void operateX86(std::vector<std::string>& asmb) const throw(INTERP_KERNEL::Exception);
     const char *getRepr() const;
     bool isACall() const;
   public:
@@ -116,6 +122,7 @@ namespace INTERP_KERNEL
   public:
     ~TanFunction();
     void operate(std::vector<Value *>& stack) const throw(INTERP_KERNEL::Exception);
+    void operateX86(std::vector<std::string>& asmb) const throw(INTERP_KERNEL::Exception);
     const char *getRepr() const;
     bool isACall() const;
   public:
@@ -127,6 +134,7 @@ namespace INTERP_KERNEL
   public:
     ~SqrtFunction();
     void operate(std::vector<Value *>& stack) const throw(INTERP_KERNEL::Exception);
+    void operateX86(std::vector<std::string>& asmb) const throw(INTERP_KERNEL::Exception);
     const char *getRepr() const;
     bool isACall() const;
   public:
@@ -138,6 +146,7 @@ namespace INTERP_KERNEL
   public:
     ~AbsFunction();
     void operate(std::vector<Value *>& stack) const throw(INTERP_KERNEL::Exception);
+    void operateX86(std::vector<std::string>& asmb) const throw(INTERP_KERNEL::Exception);
     const char *getRepr() const;
     bool isACall() const;
   public:
@@ -149,6 +158,7 @@ namespace INTERP_KERNEL
   public:
     ~ExpFunction();
     void operate(std::vector<Value *>& stack) const throw(INTERP_KERNEL::Exception);
+    void operateX86(std::vector<std::string>& asmb) const throw(INTERP_KERNEL::Exception);
     const char *getRepr() const;
     bool isACall() const;
   public:
@@ -160,6 +170,7 @@ namespace INTERP_KERNEL
   public:
     ~LnFunction();
     void operate(std::vector<Value *>& stack) const throw(INTERP_KERNEL::Exception);
+    void operateX86(std::vector<std::string>& asmb) const throw(INTERP_KERNEL::Exception);
     const char *getRepr() const;
     bool isACall() const;
   public:
@@ -177,6 +188,7 @@ namespace INTERP_KERNEL
   public:
     ~PlusFunction();
     void operate(std::vector<Value *>& stack) const throw(INTERP_KERNEL::Exception);
+    void operateX86(std::vector<std::string>& asmb) const throw(INTERP_KERNEL::Exception);
     const char *getRepr() const;
     bool isACall() const;
   public:
@@ -188,6 +200,7 @@ namespace INTERP_KERNEL
   public:
     ~MinusFunction();
     void operate(std::vector<Value *>& stack) const throw(INTERP_KERNEL::Exception);
+    void operateX86(std::vector<std::string>& asmb) const throw(INTERP_KERNEL::Exception);
     const char *getRepr() const;
     bool isACall() const;
   public:
@@ -199,6 +212,7 @@ namespace INTERP_KERNEL
   public:
     ~MultFunction();
     void operate(std::vector<Value *>& stack) const throw(INTERP_KERNEL::Exception);
+    void operateX86(std::vector<std::string>& asmb) const throw(INTERP_KERNEL::Exception);
     const char *getRepr() const;
     bool isACall() const;
   public:
@@ -210,6 +224,7 @@ namespace INTERP_KERNEL
   public:
     ~DivFunction();
     void operate(std::vector<Value *>& stack) const throw(INTERP_KERNEL::Exception);
+    void operateX86(std::vector<std::string>& asmb) const throw(INTERP_KERNEL::Exception);
     const char *getRepr() const;
     bool isACall() const;
   public:
@@ -221,6 +236,7 @@ namespace INTERP_KERNEL
   public:
     ~PowFunction();
     void operate(std::vector<Value *>& stack) const throw(INTERP_KERNEL::Exception);
+    void operateX86(std::vector<std::string>& asmb) const throw(INTERP_KERNEL::Exception);
     const char *getRepr() const;
     bool isACall() const;
   public:
@@ -232,6 +248,7 @@ namespace INTERP_KERNEL
   public:
     ~MaxFunction();
     void operate(std::vector<Value *>& stack) const throw(INTERP_KERNEL::Exception);
+    void operateX86(std::vector<std::string>& asmb) const throw(INTERP_KERNEL::Exception);
     const char *getRepr() const;
     bool isACall() const;
   public:
@@ -243,6 +260,7 @@ namespace INTERP_KERNEL
   public:
     ~MinFunction();
     void operate(std::vector<Value *>& stack) const throw(INTERP_KERNEL::Exception);
+    void operateX86(std::vector<std::string>& asmb) const throw(INTERP_KERNEL::Exception);
     const char *getRepr() const;
     bool isACall() const;
   public:
index 4a67afba5125fb69a5d8a1c4a2afa9ab1d092fca..28f5e91242b8e6b8e6c57b9bd1b1f6ead2e99f94 100644 (file)
@@ -30,8 +30,8 @@ INTERPKERNELEXPREVALDefines.hxx         \
 InterpKernelExprParser.hxx              \
 InterpKernelFunction.hxx                \
 InterpKernelUnit.hxx                    \
-InterpKernelValue.hxx
-
+InterpKernelValue.hxx                   \
+InterpKernelAsmX86.hxx
 
 EXTRA_DIST +=                          \
 INTERPKERNELEXPREVALDefines.hxx         \
@@ -44,7 +44,8 @@ dist_libinterpkernelexpreval_la_SOURCES = \
        InterpKernelExprParser.cxx        \
        InterpKernelFunction.cxx          \
        InterpKernelUnit.cxx              \
-       InterpKernelValue.cxx
+       InterpKernelValue.cxx             \
+       InterpKernelAsmX86.cxx
 
 libinterpkernelexpreval_la_CPPFLAGS=-I$(srcdir)/../Bases
 
diff --git a/src/INTERP_KERNEL/GenMathFormulae.hxx b/src/INTERP_KERNEL/GenMathFormulae.hxx
new file mode 100644 (file)
index 0000000..42ce4f4
--- /dev/null
@@ -0,0 +1,95 @@
+//  Copyright (C) 2007-2010  CEA/DEN, EDF R&D
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU Lesser General Public
+//  License as published by the Free Software Foundation; either
+//  version 2.1 of the License.
+//
+//  This library is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  Lesser General Public License for more details.
+//
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+//  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+#ifndef __GENMATHFORMULAE_HXX__
+#define __GENMATHFORMULAE_HXX__
+
+#include "InterpKernelException.hxx"
+
+#include <cmath>
+
+namespace INTERP_KERNEL
+{
+  /*!
+   * This method computes eigenvalues of a 3x3 symetric matrix stored with 6 values in 'matrix'. The convension chosen for 'matrix' is described here:
+   * matrix[0]=m_xx, matrix[1]=m_yy, matrix[2]=m_zz,
+   * matrix[3]=m_xy, matrix[4]=m_yz, matrix[5]=m_xz
+   * This method returns the 3 eigenvalues in 'eigenVals'.
+   */
+  void computeEigenValues6(const double *matrix, double *eigenVals)
+  {
+    double tr=(matrix[0]+matrix[1]+matrix[2])/3.;
+    double K[6]={matrix[0]-tr,matrix[1]-tr,matrix[2]-tr,matrix[3],matrix[4],matrix[5]};
+    double q=(K[0]*K[1]*K[2]+2.*K[4]*K[5]*K[3]-K[0]*K[4]*K[4]-K[2]*K[3]*K[3]-K[1]*K[5]*K[5])/2.;
+    double p=K[0]*K[0]+K[1]*K[1]+K[2]*K[2]+2*(K[3]*K[3]+K[4]*K[4]+K[5]*K[5]);
+    p/=6.;
+    double sqp=sqrt(p);
+    double tmp=p*sqp;
+    double phi;
+    if(fabs(q)<=fabs(tmp))
+      phi=1./3.*acos(q/tmp);
+    else
+      phi=0.;
+    if(phi<0.)
+      phi+=M_PI/3.;
+    eigenVals[0]=tr+2.*sqp*cos(phi);
+    eigenVals[1]=tr-sqp*(cos(phi)+sqrt(3.)*sin(phi));
+    eigenVals[2]=tr-sqp*(cos(phi)-sqrt(3.)*sin(phi));
+  }
+  
+  /*!
+   * This method computes one eigenvector of a 3x3 symetric matrix stored with 6 values in 'matrix'. The convension chosen for 'matrix' is described here:
+   * matrix[0]=m_xx, matrix[1]=m_yy, matrix[2]=m_zz,
+   * matrix[3]=m_xy, matrix[4]=m_yz, matrix[5]=m_xz
+   * This method returns the eigenvector of the corresponding eigenvalue in 'eigenVal'. The returned eigenValue is normalized.
+   */
+  void computeEigenVectorForEigenValue6(const double *matrix, double eigenVal, double eps, double *eigenVector) throw(INTERP_KERNEL::Exception)
+  {
+    //if(fabs(eigenVal)>eps)
+      {
+        const double m9[9]={matrix[0]-eigenVal,matrix[3],matrix[5],matrix[3],matrix[1]-eigenVal,matrix[4],matrix[5],matrix[4],matrix[2]-eigenVal};
+        for(int i=0;i<3;i++)
+          {
+            double w[9]={m9[0+3*i],m9[1+3*i],m9[2+3*i],m9[0+(3*(i+1))%6],m9[1+(3*(i+1))%6],m9[2+(3*(i+1))%6],1.,1.,1.};
+            double det=w[0]*w[4]*w[8]+w[1]*w[5]*w[6]+w[2]*w[3]*w[7]-w[0]*w[5]*w[7]-w[1]*w[3]*w[8]-w[2]*w[4]*w[6];
+            if(fabs(det)>eps)
+              {
+                eigenVector[0]=(w[1]*w[5]-w[4]*w[2])/det;
+                eigenVector[1]=(w[2]*w[3]-w[0]*w[5])/det;
+                eigenVector[2]=(w[0]*w[4]-w[1]*w[3])/det;
+                double norm=sqrt(eigenVector[0]*eigenVector[0]+eigenVector[1]*eigenVector[1]+eigenVector[2]*eigenVector[2]);
+                eigenVector[0]/=norm;
+                eigenVector[1]/=norm;
+                eigenVector[2]/=norm;
+                return;
+              }
+          }
+      }
+      //else
+      {
+        eigenVector[0]=0.;
+        eigenVector[1]=0.;
+        eigenVector[2]=0.;
+        return;
+      }
+      //throw INTERP_KERNEL::Exception("computeEigenVector : Do not succed in finding eigen vector !");
+  }
+}
+
+#endif
index 6eb93e9aa25a2a2deaed0bb83f388eb8c23c75d4..6069bf22df01a275b65c29fffa1e23a666d04cbb 100644 (file)
@@ -121,7 +121,7 @@ bool INTERP_KERNEL::InterpolationOptions::setOptionInt(const std::string& key, i
       return false;
 }
 
-bool INTERP_KERNEL::InterpolationOptions::setOptionString(const std::string& key, std::string& value)
+bool INTERP_KERNEL::InterpolationOptions::setOptionString(const std::string& key, const std::string& value)
 {
   if(key==INTERSEC_TYPE_STR) 
     {
index 49068a01a9c5c55fc1b9df1615b49b9be5270228..667e320b69da80251b82cd285820daca285d952d 100644 (file)
@@ -118,10 +118,10 @@ namespace INTERP_KERNEL
                                  bool measure_abs,
                                  std::string splitting_policy,
                                  bool P1P0_bary_method );
-    void copyOptions(InterpolationOptions & other) { *this = other; }
+    void copyOptions(const InterpolationOptions & other) { *this = other; }
     bool setOptionDouble(const std::string& key, double value);
     bool setOptionInt(const std::string& key, int value);
-    bool setOptionString(const std::string& key, std::string& value);
+    bool setOptionString(const std::string& key, const std::string& value);
   private:
     static const double DFT_MEDIAN_PLANE;
     static const double DFT_SURF3D_ADJ_EPS;
index 2d5ca00df45742707df0a320556ab740089b97e3..e96f3fc1bd555779db0e97473e6a1c30a01bf76a 100644 (file)
@@ -221,13 +221,13 @@ namespace INTERP_KERNEL
     // make upper triangular matrix (forward elimination)
 
     int iR[nbRow];// = { 0, 1, 2 };
-    for ( int i = 0; i < nbRow; ++i ) iR[i] = i;
+    for ( int i = 0; i < (int) nbRow; ++i ) iR[i] = i;
 
-    for ( int i = 0; i < nbRow-1; ++i ) // nullify nbRow-1 rows
+    for ( int i = 0; i < (int)(nbRow-1); ++i ) // nullify nbRow-1 rows
       {
         // swap rows to have max value of i-th column in i-th row
         double max = std::fabs( M[ iR[i] ][i] );
-        for ( int r = i+1; r < nbRow; ++r ) {
+        for ( int r = i+1; r < (int)nbRow; ++r ) {
           double m = std::fabs( M[ iR[r] ][i] );
           if ( m > max ) {
             max = m;
@@ -240,7 +240,7 @@ namespace INTERP_KERNEL
         }
         // make 0 below M[i][i] (actually we do not modify i-th column)
         double* tUpRow = M[ iR[i] ];
-        for ( int r = i+1; r < nbRow; ++r ) {
+        for ( int r = i+1; r < (int)nbRow; ++r ) {
           double* mRow = M[ iR[r] ];
           double coef = mRow[ i ] / tUpRow[ i ];
           for ( int c = i+1; c < nbCol; ++c )
index a125070120d5435e9922194a96ad1ba293a2150e..afbe7285db05c6d3be80f6857b04ac4528bd6256 100644 (file)
@@ -141,6 +141,7 @@ VTKNormalizedUnstructuredMesh.hxx   \
 VTKNormalizedUnstructuredMesh.txx      \
 VectorUtils.hxx                         \
 VolSurfFormulae.hxx                     \
+GenMathFormulae.hxx                     \
 VolSurfUser.hxx                         \
 VolSurfUser.txx                         \
 CurveIntersector.hxx                    \
@@ -177,12 +178,13 @@ VolSurfUser.txx
 # Libraries targets
 
 dist_libinterpkernel_la_SOURCES = \
-       TransformedTriangle.cxx\
-       TransformedTriangleIntersect.cxx\
-       TransformedTriangleMath.cxx\
+       TransformedTriangle.cxx \
+       TransformedTriangleIntersect.cxx \
+       TransformedTriangleMath.cxx \
        BoundingBox.cxx \
-       TetraAffineTransform.cxx\
-       CellModel.cxx\
+       TranslationRotationMatrix.cxx \
+       TetraAffineTransform.cxx \
+       CellModel.cxx \
        UnitTetraIntersectionBary.cxx \
        InterpolationOptions.cxx \
        DirectedBoundingBox.cxx
diff --git a/src/INTERP_KERNEL/TranslationRotationMatrix.cxx b/src/INTERP_KERNEL/TranslationRotationMatrix.cxx
new file mode 100644 (file)
index 0000000..0e31b21
--- /dev/null
@@ -0,0 +1,22 @@
+//  Copyright (C) 2007-2010  CEA/DEN, EDF R&D
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU Lesser General Public
+//  License as published by the Free Software Foundation; either
+//  version 2.1 of the License.
+//
+//  This library is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  Lesser General Public License for more details.
+//
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+//  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+#include "TranslationRotationMatrix.hxx"
+
+const double INTERP_KERNEL::TranslationRotationMatrix::EPS=1e-12;
index 8258cf18e28412661b58be0c875b4af34740a31b..e1108573b41ba71fca8e0bd0ae0e37119ca5c936 100644 (file)
 #ifndef __TRANSLATIONROTATIONMATRIX_HXX__
 #define __TRANSLATIONROTATIONMATRIX_HXX__
 
+#include "INTERPKERNELDefines.hxx"
+
 #include <cmath>
 
 namespace INTERP_KERNEL
 {
-  class TranslationRotationMatrix
+  class INTERPKERNEL_EXPORT TranslationRotationMatrix
   {
 
   public:
@@ -125,7 +127,6 @@ namespace INTERP_KERNEL
     double _rotation_coeffs[ROT_SIZE];
     double _translation_coeffs[TRANSL_SIZE];
   };
-  const double TranslationRotationMatrix::EPS=1e-12;
 }
 
 #endif
index e62956e2935ec6a032981ecffd8583e21705a89f..e9bdd855d6d4387b0e9a9309e3332eee70a71a85 100644 (file)
@@ -20,7 +20,9 @@
 #ifndef __VOLSURFFORMULAE_HXX__
 #define __VOLSURFFORMULAE_HXX__
 
-#include <math.h>
+#include "InterpolationUtils.hxx"
+
+#include <cmath>
 
 namespace INTERP_KERNEL
 {
@@ -31,6 +33,19 @@ namespace INTERP_KERNEL
                                       int spaceDim);
 
 
+  inline double calculateLgthForSeg2(const double *p1, const double *p2, int spaceDim)
+  {
+    if(spaceDim==1)
+      return *p2-*p1;
+    else
+      {
+        double ret=0;
+        for(int i=0;i<spaceDim;i++)
+          ret+=(p2[i]-p1[i])*(p2[i]-p1[i]);
+        return sqrt(ret);
+      }
+  }
+
   // ===========================
   // Calculate Area for triangle
   // ===========================
@@ -398,6 +413,125 @@ namespace INTERP_KERNEL
     return -volume/3.;
   }
 
+  /*!
+   * Calculate Volume for Generic Polyedron, even not convex one, WARNING !!! The polyedron's faces must be correctly ordered.
+   * 2nd API avoiding to create double** arrays. The returned value could be negative if polyhedrons faces are not oriented with normal outside of the
+   * polyhedron
+   */
+  template<class ConnType, NumberingPolicy numPol>
+  inline double calculateVolumeForPolyh2(const ConnType *connec, int lgth, const double *coords)
+  {
+    int nbOfFaces=std::count(connec,connec+lgth,-1)+1;
+    double volume=0.;
+    const int *work=connec;
+    for(int iFace=0;iFace<nbOfFaces;iFace++)
+      {
+        const int *work2=std::find(work+1,connec+lgth,-1);
+        int nbOfNodesOfCurFace=std::distance(work,work2);
+        double areaVector[3]={0.,0.,0.};
+        for(int ptId=0;ptId<nbOfNodesOfCurFace;ptId++)
+          {
+            const double *pti=coords+3*OTT<ConnType,numPol>::coo2C(work[ptId]);
+            const double *pti1=coords+3*OTT<ConnType,numPol>::coo2C(work[(ptId+1)%nbOfNodesOfCurFace]);
+            areaVector[0]+=pti[1]*pti1[2]-pti[2]*pti1[1];
+            areaVector[1]+=pti[2]*pti1[0]-pti[0]*pti1[2];
+            areaVector[2]+=pti[0]*pti1[1]-pti[1]*pti1[0];
+          }
+        const double *pt=coords+3*work[0];
+        volume+=pt[0]*areaVector[0]+pt[1]*areaVector[1]+pt[2]*areaVector[2];
+        work=work2+1;
+      }
+    return volume/6.;
+  }
+
+  /*!
+   * This method returns the area oriented vector of a polygon. This method is useful for normal computation without
+   * any troubles if several edges are colinears.
+   * @param res must be of size at least 3 to store the result.
+   */
+  template<class ConnType, NumberingPolicy numPol>
+  inline void areaVectorOfPolygon(const ConnType *connec, int lgth, const double *coords, double *res)
+  {
+    res[0]=0.; res[1]=0.; res[2]=0.;
+    for(int ptId=0;ptId<lgth;ptId++)
+      {
+        const double *pti=coords+3*OTT<ConnType,numPol>::coo2C(connec[ptId]);
+        const double *pti1=coords+3*OTT<ConnType,numPol>::coo2C(connec[(ptId+1)%lgth]);
+        res[0]+=pti[1]*pti1[2]-pti[2]*pti1[1];
+        res[1]+=pti[2]*pti1[0]-pti[0]*pti1[2];
+        res[2]+=pti[0]*pti1[1]-pti[1]*pti1[0];
+      }
+  }
+
+  inline double integrationOverA3DLine(double u1, double v1, double u2, double v2, double A, double B, double C)
+  {
+    return (u1-u2)*(6.*C*C*(v1+v2)+B*B*(v1*v1*v1+v1*v1*v2+v1*v2*v2+v2*v2*v2)+A*A*(2.*u1*u2*(v1+v2)+u1*u1*(3.*v1+v2)+u2*u2*(v1+3.*v2))+ 
+                    4.*C*(A*(2*u1*v1+u2*v1+u1*v2+2.*u2*v2)+B*(v1*v1+v1*v2+v2*v2))+A*B*(u1*(3.*v1*v1+2.*v1*v2+v2*v2)+u2*(v1*v1+2.*v1*v2+3.*v2*v2)))/24.;
+  }
+
+  template<class ConnType, NumberingPolicy numPol>
+  inline void barycenterOfPolyhedron(const ConnType *connec, int lgth, const double *coords, double *res)
+  {
+    int nbOfFaces=std::count(connec,connec+lgth,-1)+1;
+    res[0]=0.; res[1]=0.; res[2]=0.;
+    const int *work=connec;
+    for(int i=0;i<nbOfFaces;i++)
+      {
+        const int *work2=std::find(work+1,connec+lgth,-1);
+        int nbOfNodesOfCurFace=std::distance(work,work2);
+        // projection to (u,v) of each faces of polyh to compute integral(x^2/2) on each faces.
+        double normal[3];
+        areaVectorOfPolygon<ConnType,numPol>(work,nbOfNodesOfCurFace,coords,normal);
+        double normOfNormal=sqrt(normal[0]*normal[0]+normal[1]*normal[1]+normal[2]*normal[2]);
+        normal[0]/=normOfNormal; normal[1]/=normOfNormal; normal[2]/=normOfNormal;
+        double u[2]={normal[1],-normal[0]};
+        double s=sqrt(u[0]*u[0]+u[1]*u[1]);
+        double c=normal[2];
+        if(fabs(s)>1e-12)
+          {
+            u[0]/=std::abs(s); u[1]/=std::abs(s);
+          }
+        else
+          { u[0]=1.; u[1]=0.; }
+        //C : high in plane of polyhedron face : always constant
+        double w=normal[0]*coords[3*OTT<ConnType,numPol>::coo2C(work[0])]+
+          normal[1]*coords[3*OTT<ConnType,numPol>::coo2C(work[0])+1]+
+          normal[2]*coords[3*OTT<ConnType,numPol>::coo2C(work[0])+2];
+        // A,B,D,F,G,H,L,M,N coeffs of rotation matrix defined by (u,c,s)
+        double A=u[0]*u[0]*(1-c)+c;
+        double B=u[0]*u[1]*(1-c);
+        double D=u[1]*s;
+        double F=B;
+        double G=u[1]*u[1]*(1-c)+c;
+        double H=-u[0]*s;
+        double L=-u[1]*s;
+        double M=u[0]*s;
+        double N=c;
+        double CX=-w*D;
+        double CY=-w*H;
+        double CZ=-w*N;
+        for(int j=0;j<nbOfNodesOfCurFace;j++)
+          {
+            const double *p1=coords+3*OTT<ConnType,numPol>::coo2C(work[j]);
+            const double *p2=coords+3*OTT<ConnType,numPol>::coo2C(work[(j+1)%nbOfNodesOfCurFace]);
+            double u1=A*p1[0]+B*p1[1]+D*p1[2];
+            double u2=A*p2[0]+B*p2[1]+D*p2[2];
+            double v1=F*p1[0]+G*p1[1]+H*p1[2];
+            double v2=F*p2[0]+G*p2[1]+H*p2[2];
+            //
+            double gx=integrationOverA3DLine(u1,v1,u2,v2,A,B,CX);
+            double gy=integrationOverA3DLine(u1,v1,u2,v2,F,G,CY);
+            double gz=integrationOverA3DLine(u1,v1,u2,v2,L,M,CZ);
+            res[0]+=gx*normal[0];
+            res[1]+=gy*normal[1];
+            res[2]+=gz*normal[2];
+          }
+        work=work2+1;
+      }
+    double vol=calculateVolumeForPolyh2<ConnType,numPol>(connec,lgth,coords);
+    res[0]/=vol; res[1]/=vol; res[2]/=vol;
+  }
+
   // ============================================================================================================================================
   // Calculate Volume for NON Generic Polyedron. Only polydrons with bary included in pts is supported by this method. Result is always positive.
   // ============================================================================================================================================
@@ -503,6 +637,56 @@ namespace INTERP_KERNEL
         bary[i]=temp/nbPts;
       }
   }
+  
+  template<class ConnType, NumberingPolicy numPol>
+  inline void computePolygonBarycenter2D(const ConnType *connec, int lgth, const double *coords, double *res)
+  {
+    double area=0.;
+    res[0]=0.; res[1]=0.;
+    for(int i=0;i<lgth;i++)
+      {
+        double cp=coords[2*OTT<ConnType,numPol>::coo2C(connec[i])]*coords[2*OTT<ConnType,numPol>::coo2C(connec[(i+1)%lgth])+1]-
+          coords[2*OTT<ConnType,numPol>::coo2C(connec[i])+1]*coords[2*OTT<ConnType,numPol>::coo2C(connec[(i+1)%lgth])];
+        area+=cp;
+        res[0]+=cp*(coords[2*OTT<ConnType,numPol>::coo2C(connec[i])]+coords[2*OTT<ConnType,numPol>::coo2C(connec[(i+1)%lgth])]);
+        res[1]+=cp*(coords[2*OTT<ConnType,numPol>::coo2C(connec[i])+1]+coords[2*OTT<ConnType,numPol>::coo2C(connec[(i+1)%lgth])+1]);
+      }
+    res[0]/=3.*area;
+    res[1]/=3.*area;
+  }
+
+  template<class ConnType, NumberingPolicy numPol>
+  inline void computePolygonBarycenter3D(const ConnType *connec, int lgth, const double *coords, double *res)
+  {
+    double area[3];
+    areaVectorOfPolygon<ConnType,numPol>(connec,lgth,coords,area);
+    double norm=sqrt(area[0]*area[0]+area[1]*area[1]+area[2]*area[2]);
+    area[0]/=norm; area[1]/=norm; area[2]/=norm;
+    res[0]=0.; res[1]=0.; res[2]=0.;
+    for(int i=1;i<lgth-1;i++)
+      {
+        double v[3];
+        double tmpArea[3];
+        v[0]=(coords[3*OTT<ConnType,numPol>::coo2C(connec[0])]+
+              coords[3*OTT<ConnType,numPol>::coo2C(connec[i])]+
+              coords[3*OTT<ConnType,numPol>::coo2C(connec[i+1])])/3.;
+        v[1]=(coords[3*OTT<ConnType,numPol>::coo2C(connec[0])+1]+
+              coords[3*OTT<ConnType,numPol>::coo2C(connec[i])+1]+
+              coords[3*OTT<ConnType,numPol>::coo2C(connec[i+1])+1])/3.;
+        v[2]=(coords[3*OTT<ConnType,numPol>::coo2C(connec[0])+2]+
+              coords[3*OTT<ConnType,numPol>::coo2C(connec[i])+2]+
+              coords[3*OTT<ConnType,numPol>::coo2C(connec[i+1])+2])/3.;
+        ConnType tmpConn[3]={connec[0],connec[i],connec[i+1]};
+        areaVectorOfPolygon<ConnType,numPol>(tmpConn,3,coords,tmpArea);
+        double norm2=sqrt(tmpArea[0]*tmpArea[0]+tmpArea[1]*tmpArea[1]+tmpArea[2]*tmpArea[2]);
+        if(norm2>1e-12)
+          {
+            tmpArea[0]/=norm2; tmpArea[1]/=norm2; tmpArea[2]/=norm2;
+            double signOfArea=area[0]*tmpArea[0]+area[1]*tmpArea[1]+area[2]*tmpArea[2];
+            res[0]+=signOfArea*norm2*v[0]/norm; res[1]+=signOfArea*norm2*v[1]/norm; res[2]+=signOfArea*norm2*v[2]/norm;
+          }
+      }   
+  }
 }
 
 #endif
index a0eafd221234138e38bdb347320309cea880dc61..99083c319dff1a4b62be84b8034529cc28a5f610 100644 (file)
@@ -29,6 +29,12 @@ namespace INTERP_KERNEL
 
   template<class ConnType, NumberingPolicy numPolConn>
   double computeVolSurfOfCell2(NormalizedCellType type, const ConnType *connec, int lgth, const double *coords, int spaceDim);
+
+  template<class ConnType, NumberingPolicy numPolConn, int SPACEDIM>
+  void computeBarycenter(NormalizedCellType type, const ConnType *connec, int lgth, const double *coords, double *res);
+
+  template<class ConnType, NumberingPolicy numPolConn>
+  void computeBarycenter2(NormalizedCellType type, const ConnType *connec, int lgth, const double *coords, int spaceDim, double *res);
 }
 
 #endif
index d6fcd11bf1974298f8569ec3a8a6c55ca2f68119..5a0109a43020dd2157d7fd764c915dbfd247ebf2 100644 (file)
@@ -23,6 +23,8 @@
 #include "VolSurfFormulae.hxx"
 #include "InterpolationUtils.hxx"
 
+#include <algorithm>
+
 namespace INTERP_KERNEL
 {
   template<class ConnType, NumberingPolicy numPol, int SPACEDIM>
@@ -30,6 +32,13 @@ namespace INTERP_KERNEL
   {
     switch(type)
       {
+      case INTERP_KERNEL::NORM_SEG2 :
+      case INTERP_KERNEL::NORM_SEG3 :
+        {
+          int N1 = OTT<ConnType,numPol>::coo2C(connec[0]);
+          int N2 = OTT<ConnType,numPol>::coo2C(connec[1]);
+          return INTERP_KERNEL::calculateLgthForSeg2(coords+(SPACEDIM*N1),coords+(SPACEDIM*N2),SPACEDIM);
+        }
       case INTERP_KERNEL::NORM_TRI3 :
       case INTERP_KERNEL::NORM_TRI6 :
         {
@@ -64,7 +73,7 @@ namespace INTERP_KERNEL
         {          
           const double **pts=new const double *[lgth];
           for(int inod=0;inod<lgth;inod++)
-            pts[inod] = coords+3*OTT<ConnType,numPol>::coo2C(connec[inod]);
+            pts[inod] = coords+SPACEDIM*OTT<ConnType,numPol>::coo2C(connec[inod]);
           double val=INTERP_KERNEL::calculateAreaForPolyg(pts,lgth,SPACEDIM);
           delete [] pts;
           return val;
@@ -146,11 +155,11 @@ namespace INTERP_KERNEL
             
       case INTERP_KERNEL::NORM_POLYHED :
         {
-          throw INTERP_KERNEL::Exception("Polyedra Not yet implemented !");
+          return calculateVolumeForPolyh2<ConnType,numPol>(connec,lgth,coords);
         }
         break;
       default:
-        throw INTERP_KERNEL::Exception("Not recognized cell type to get Area/Volume on it !");
+        throw INTERP_KERNEL::Exception("Not recognized cell type to get Length/Area/Volume on it !");
       }
   }
 
@@ -161,7 +170,102 @@ namespace INTERP_KERNEL
       return computeVolSurfOfCell<ConnType,numPolConn,3>(type,connec,lgth,coords);
     if(spaceDim==2)
       return computeVolSurfOfCell<ConnType,numPolConn,2>(type,connec,lgth,coords);
-    throw INTERP_KERNEL::Exception("Invalid spaceDim specified : must be 2 or 3");
+    if(spaceDim==1)
+      return computeVolSurfOfCell<ConnType,numPolConn,1>(type,connec,lgth,coords);
+    throw INTERP_KERNEL::Exception("Invalid spaceDim specified : must be 1, 2 or 3");
+  }
+
+  template<class ConnType, NumberingPolicy numPol,int SPACEDIM>
+  void computeBarycenter(NormalizedCellType type, const ConnType *connec, int lgth, const double *coords, double *res)
+  {
+    switch(type)
+      {
+      case NORM_SEG3:
+      case NORM_SEG2:
+        {
+          std::copy(coords+SPACEDIM*OTT<ConnType,numPol>::coo2C(connec[0]),
+                    coords+SPACEDIM*OTT<ConnType,numPol>::coo2C(connec[0]+1),res);
+          std::transform(res,res+SPACEDIM,coords+SPACEDIM*OTT<ConnType,numPol>::coo2C(connec[1]),res,std::plus<double>());
+          std::transform(res,res+SPACEDIM,res,std::bind2nd(std::multiplies<double>(),0.5));
+          break;
+        }
+      case NORM_TRI3:
+      case NORM_TRI6:
+        {
+          std::copy(coords+SPACEDIM*OTT<ConnType,numPol>::coo2C(connec[0]),
+                    coords+SPACEDIM*OTT<ConnType,numPol>::coo2C(connec[0]+1),res);
+          std::transform(res,res+SPACEDIM,coords+SPACEDIM*OTT<ConnType,numPol>::coo2C(connec[1]),res,std::plus<double>());
+          std::transform(res,res+SPACEDIM,coords+SPACEDIM*OTT<ConnType,numPol>::coo2C(connec[2]),res,std::plus<double>());
+          std::transform(res,res+SPACEDIM,res,std::bind2nd(std::multiplies<double>(),1./3.));
+          break;
+        }
+      case NORM_QUAD4:
+      case NORM_POLYGON:
+        {
+          if(SPACEDIM==2)
+            computePolygonBarycenter2D<ConnType,numPol>(connec,lgth,coords,res);
+          else if(SPACEDIM==3)
+            computePolygonBarycenter3D<ConnType,numPol>(connec,lgth,coords,res);
+          else
+            throw INTERP_KERNEL::Exception("Impossible spacedim linked to cell 2D Cell !");
+          break;
+        }
+      case NORM_QUAD8:
+        {
+          if(SPACEDIM==2)
+            computePolygonBarycenter2D<ConnType,numPol>(connec,lgth/2,coords,res);
+          else if(SPACEDIM==3)
+            computePolygonBarycenter3D<ConnType,numPol>(connec,lgth/2,coords,res);
+          else
+            throw INTERP_KERNEL::Exception("Impossible spacedim linked to cell 2D Cell !");
+          break;
+        }
+      case NORM_TETRA4:
+        {
+          res[0]=coords[3*OTT<ConnType,numPol>::coo2C(connec[0])]; 
+          res[1]=coords[3*OTT<ConnType,numPol>::coo2C(connec[0])+1];
+          res[2]=coords[3*OTT<ConnType,numPol>::coo2C(connec[0])+2];
+          res[0]+=coords[3*OTT<ConnType,numPol>::coo2C(connec[1])]; 
+          res[1]+=coords[3*OTT<ConnType,numPol>::coo2C(connec[1])+1];
+          res[2]+=coords[3*OTT<ConnType,numPol>::coo2C(connec[1])+2];
+          res[0]+=coords[3*OTT<ConnType,numPol>::coo2C(connec[2])]; 
+          res[1]+=coords[3*OTT<ConnType,numPol>::coo2C(connec[2])+1];
+          res[2]+=coords[3*OTT<ConnType,numPol>::coo2C(connec[2])+2];
+          res[0]+=coords[3*OTT<ConnType,numPol>::coo2C(connec[3])]; 
+          res[1]+=coords[3*OTT<ConnType,numPol>::coo2C(connec[3])+1];
+          res[2]+=coords[3*OTT<ConnType,numPol>::coo2C(connec[3])+2];
+          res[0]/=4.; res[1]/=4.; res[2]/=4.;
+          break;
+        }
+      case NORM_PYRA5:
+        {
+          double tmp[3];
+          computePolygonBarycenter3D<ConnType,numPol>(connec,lgth,coords,tmp);
+          res[0]=(coords[3*OTT<ConnType,numPol>::coo2C(connec[4])]+3.*tmp[0])/4.;
+          res[1]=(coords[3*OTT<ConnType,numPol>::coo2C(connec[4])+1]+3.*tmp[1])/4.;
+          res[1]=(coords[3*OTT<ConnType,numPol>::coo2C(connec[4])+2]+3.*tmp[2])/4.;
+          break;
+        }
+      case NORM_POLYHED:
+        {
+          barycenterOfPolyhedron<ConnType,numPol>(connec,lgth,coords,res);
+          break;
+        }
+      default:
+        throw INTERP_KERNEL::Exception("Not recognized cell type to get Barycenter on it !");
+      }
+  }
+
+  template<class ConnType, NumberingPolicy numPolConn>
+  void computeBarycenter2(NormalizedCellType type, const ConnType *connec, int lgth, const double *coords, int spaceDim, double *res)
+  {
+    if(spaceDim==3)
+      return computeBarycenter<ConnType,numPolConn,3>(type,connec,lgth,coords,res);
+    if(spaceDim==2)
+      return computeBarycenter<ConnType,numPolConn,2>(type,connec,lgth,coords,res);
+    if(spaceDim==1)
+      return computeBarycenter<ConnType,numPolConn,1>(type,connec,lgth,coords,res);
+    throw INTERP_KERNEL::Exception("Invalid spaceDim specified for compute barycenter : must be 1, 2 or 3");
   }
 }
 
diff --git a/src/MEDCoupling/MEDCouplingAutoRefCountObjectPtr.hxx b/src/MEDCoupling/MEDCouplingAutoRefCountObjectPtr.hxx
new file mode 100644 (file)
index 0000000..9a30b7d
--- /dev/null
@@ -0,0 +1,50 @@
+//  Copyright (C) 2007-2010  CEA/DEN, EDF R&D
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU Lesser General Public
+//  License as published by the Free Software Foundation; either
+//  version 2.1 of the License.
+//
+//  This library is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  Lesser General Public License for more details.
+//
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+//  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+#ifndef __PARAMEDMEM_MEDCOUPLINGAUTOREFCOUNTOBJECTPTR_HXX__
+#define __PARAMEDMEM_MEDCOUPLINGAUTOREFCOUNTOBJECTPTR_HXX__
+
+#include "MEDCouplingRefCountObject.hxx"
+
+namespace ParaMEDMEM
+{
+  template<class T>
+  class MEDCouplingAutoRefCountObjectPtr
+  {
+  public:
+    MEDCouplingAutoRefCountObjectPtr(const MEDCouplingAutoRefCountObjectPtr& other):_ptr(0) { referPtr(other._ptr); }
+    MEDCouplingAutoRefCountObjectPtr(T *ptr=0):_ptr(ptr) { }
+    ~MEDCouplingAutoRefCountObjectPtr() { destroyPtr(); }
+    MEDCouplingAutoRefCountObjectPtr &operator=(const MEDCouplingAutoRefCountObjectPtr& other) { if(_ptr!=other._ptr) { destroyPtr(); referPtr(other._ptr); } return *this; }
+    MEDCouplingAutoRefCountObjectPtr &operator=(T *ptr) { if(_ptr!=ptr) { destroyPtr(); _ptr=ptr; } return *this; }
+    T *operator->() { return _ptr ; }
+    const T *operator->() const { return _ptr; }
+    T& operator*() { return *_ptr; }
+    const T& operator*() const { return *_ptr; }
+    operator T *() { return _ptr; }
+    operator const T *() const { return _ptr; }
+  private:
+    void referPtr(T *ptr) { _ptr=ptr; if(_ptr) _ptr->incrRef(); }
+    void destroyPtr() { if(_ptr) _ptr->decrRef(); }
+  private:
+    T *_ptr;
+  };
+}
+
+#endif
index 8829b19de25764788ccde8ecb4f179700c8ae794..3fd5fd4046bf1bf9ccaaf77d6d9943929cf3ec40 100644 (file)
@@ -31,6 +31,31 @@ MEDCouplingCMesh::MEDCouplingCMesh():_x_array(0),_y_array(0),_z_array(0)
 {
 }
 
+MEDCouplingCMesh::MEDCouplingCMesh(const MEDCouplingCMesh& other, bool deepCpy):MEDCouplingMesh(other)
+{
+  if(deepCpy)
+    {
+      if(other._x_array)
+        _x_array=_x_array->deepCopy();
+      if(other._y_array)
+        _y_array=_y_array->deepCopy();
+      if(other._z_array)
+        _z_array=_z_array->deepCopy();
+    }
+  else
+    {
+      _x_array=other._x_array;
+      if(_x_array)
+        _x_array->incrRef();
+      _y_array=other._y_array;
+      if(_y_array)
+        _y_array->incrRef();
+      _z_array=other._z_array;
+      if(_z_array)
+        _z_array->incrRef();
+    }
+}
+
 MEDCouplingCMesh::~MEDCouplingCMesh()
 {
   if(_x_array)
@@ -46,6 +71,16 @@ MEDCouplingCMesh *MEDCouplingCMesh::New()
   return new MEDCouplingCMesh;
 }
 
+MEDCouplingMesh *MEDCouplingCMesh::deepCpy() const
+{
+  return clone(true);
+}
+
+MEDCouplingCMesh *MEDCouplingCMesh::clone(bool recDeepCpy) const
+{
+  return new MEDCouplingCMesh(*this,recDeepCpy);
+}
+
 void MEDCouplingCMesh::updateTime()
 {
   if(_x_array)
@@ -56,41 +91,119 @@ void MEDCouplingCMesh::updateTime()
     updateTimeWith(*_z_array);
 }
 
+/*!
+ * This method copyies all tiny strings from other (name and components name).
+ * @throw if other and this have not same mesh type.
+ */
+void MEDCouplingCMesh::copyTinyStringsFrom(const MEDCouplingMesh *other) throw(INTERP_KERNEL::Exception)
+{ 
+  const MEDCouplingCMesh *otherC=dynamic_cast<const MEDCouplingCMesh *>(other);
+  if(!otherC)
+    throw INTERP_KERNEL::Exception("MEDCouplingCMesh::copyTinyStringsFrom : meshes have not same type !");
+  MEDCouplingMesh::copyTinyStringsFrom(other);
+  if(_x_array && otherC->_x_array)
+    _x_array->copyStringInfoFrom(*otherC->_x_array);
+  if(_y_array && otherC->_y_array)
+    _y_array->copyStringInfoFrom(*otherC->_y_array);
+  if(_z_array && otherC->_z_array)
+    _z_array->copyStringInfoFrom(*otherC->_z_array);
+}
+
 bool MEDCouplingCMesh::isEqual(const MEDCouplingMesh *other, double prec) const
 {
   const MEDCouplingCMesh *otherC=dynamic_cast<const MEDCouplingCMesh *>(other);
   if(!otherC)
     return false;
+  if(!MEDCouplingMesh::isEqual(other,prec))
+    return false;
+  const DataArrayDouble *thisArr[3]={_x_array,_y_array,_z_array};
+  const DataArrayDouble *otherArr[3]={otherC->_x_array,otherC->_y_array,otherC->_z_array};
+  for(int i=0;i<3;i++)
+    {
+      if((thisArr[i]!=0 && otherArr[i]==0) || (thisArr[i]==0 && otherArr[i]!=0))
+        return false;
+      if(thisArr[i])
+        if(!thisArr[i]->isEqual(*otherArr[i],prec))
+          return false;
+    }
   return true;
 }
 
+bool MEDCouplingCMesh::isEqualWithoutConsideringStr(const MEDCouplingMesh *other, double prec) const
+{
+  const MEDCouplingCMesh *otherC=dynamic_cast<const MEDCouplingCMesh *>(other);
+  if(!otherC)
+    return false;
+  const DataArrayDouble *thisArr[3]={_x_array,_y_array,_z_array};
+  const DataArrayDouble *otherArr[3]={otherC->_x_array,otherC->_y_array,otherC->_z_array};
+  for(int i=0;i<3;i++)
+    {
+      if((thisArr[i]!=0 && otherArr[i]==0) || (thisArr[i]==0 && otherArr[i]!=0))
+        return false;
+      if(thisArr[i])
+        if(!thisArr[i]->isEqualWithoutConsideringStr(*otherArr[i],prec))
+          return false;
+    }
+  return true;
+}
+
+void MEDCouplingCMesh::checkDeepEquivalWith(const MEDCouplingMesh *other, int cellCompPol, double prec,
+                                            DataArrayInt *&cellCor, DataArrayInt *&nodeCor) const throw(INTERP_KERNEL::Exception)
+{
+  throw INTERP_KERNEL::Exception("Not implemented yet !");
+}
+
+void MEDCouplingCMesh::checkDeepEquivalOnSameNodesWith(const MEDCouplingMesh *other, int cellCompPol, double prec,
+                                                       DataArrayInt *&cellCor) const throw(INTERP_KERNEL::Exception)
+{
+  throw INTERP_KERNEL::Exception("Not implemented yet !");
+}
+
 void MEDCouplingCMesh::checkCoherency() const throw(INTERP_KERNEL::Exception)
 {
   const char msg0[]="Invalid ";
   const char msg1[]=" array ! Must contain more than 1 element.";
+  const char msg2[]=" array ! Must be with only one component.";
   if(_x_array)
-    if(_x_array->getNbOfElems()<2)
-      {
-        std::ostringstream os; os << msg0 << 'X' << msg1;
-        throw INTERP_KERNEL::Exception(os.str().c_str());
-      }
+    {
+      if(_x_array->getNbOfElems()<2)
+        {
+          std::ostringstream os; os << msg0 << 'X' << msg1;
+          throw INTERP_KERNEL::Exception(os.str().c_str());
+        }
+      if(_x_array->getNumberOfComponents()!=1)
+        {
+          std::ostringstream os; os << msg0 << 'X' << msg2;
+          throw INTERP_KERNEL::Exception(os.str().c_str());
+        }
+    }
   if(_y_array)
-    if(_y_array->getNbOfElems()<2)
-      {
-        std::ostringstream os; os << msg0 << 'Y' << msg1;
-        throw INTERP_KERNEL::Exception(os.str().c_str());
-      }
+    {
+      if(_y_array->getNbOfElems()<2)
+        {
+          std::ostringstream os; os << msg0 << 'Y' << msg1;
+          throw INTERP_KERNEL::Exception(os.str().c_str());
+        }
+      if(_y_array->getNumberOfComponents()!=1)
+        {
+          std::ostringstream os; os << msg0 << 'Y' << msg2;
+          throw INTERP_KERNEL::Exception(os.str().c_str());
+        }
+      
+    }
   if(_z_array)
-    if(_z_array->getNbOfElems()<2)
-      {
-        std::ostringstream os; os << msg0 << 'Z' << msg1;
-        throw INTERP_KERNEL::Exception(os.str().c_str());
-      }
-}
-
-bool MEDCouplingCMesh::isStructured() const
-{
-  return true;
+    {
+      if(_z_array->getNbOfElems()<2)
+        {
+          std::ostringstream os; os << msg0 << 'Z' << msg1;
+          throw INTERP_KERNEL::Exception(os.str().c_str());
+        }
+      if(_z_array->getNumberOfComponents()!=1)
+        {
+          std::ostringstream os; os << msg0 << 'Z' << msg2;
+          throw INTERP_KERNEL::Exception(os.str().c_str());
+        }
+    }
 }
 
 int MEDCouplingCMesh::getNumberOfCells() const
@@ -204,6 +317,27 @@ INTERP_KERNEL::NormalizedCellType MEDCouplingCMesh::getTypeOfCell(int cellId) co
     }
 }
 
+int MEDCouplingCMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
+{
+  int ret=getNumberOfCells();
+  int dim=getMeshDimension();
+  switch(type)
+    {
+    case INTERP_KERNEL::NORM_HEXA8:
+      if(dim==3)
+        return ret;
+    case INTERP_KERNEL::NORM_QUAD4:
+      if(dim==2)
+      return ret;
+    case INTERP_KERNEL::NORM_SEG2:
+      if(dim==1)
+        return ret;
+    default:
+      throw INTERP_KERNEL::Exception("Unexpected dimension for MEDCouplingCMesh::getTypeOfCell !");
+    }
+  return 0;
+}
+
 void MEDCouplingCMesh::getNodeIdsOfCell(int cellId, std::vector<int>& conn) const
 {
   //not implemented yet
@@ -214,6 +348,34 @@ void MEDCouplingCMesh::getCoordinatesOfNode(int nodeId, std::vector<double>& coo
   //not implemented yet
 }
 
+std::string MEDCouplingCMesh::simpleRepr() const
+{
+  std::ostringstream ret;
+  ret << "Cartesian mesh with name : \"" << getName() << "\"\n";
+  ret << "Mesh and SpaceDimension dimension : " << getSpaceDimension() << "\n\nArrays :\n________\n\n";
+  if(_x_array)
+    {
+      ret << "X Array :\n";
+      _x_array->reprZipWithoutNameStream(ret);
+    }
+  if(_y_array)
+    {
+      ret << "Y Array :\n";
+      _y_array->reprZipWithoutNameStream(ret);
+    }
+  if(_z_array)
+    {
+      ret << "Z Array :\n";
+      _z_array->reprZipWithoutNameStream(ret);
+    }
+  return ret.str();
+}
+
+std::string MEDCouplingCMesh::advancedRepr() const
+{
+  return simpleRepr();
+}
+
 DataArrayDouble *MEDCouplingCMesh::getCoordsAt(int i) const throw(INTERP_KERNEL::Exception)
 {
   switch(i)
@@ -229,6 +391,22 @@ DataArrayDouble *MEDCouplingCMesh::getCoordsAt(int i) const throw(INTERP_KERNEL:
     }
 }
 
+void MEDCouplingCMesh::setCoordsAt(int i, DataArrayDouble *arr) throw(INTERP_KERNEL::Exception)
+{
+  DataArrayDouble **thisArr[3]={&_x_array,&_y_array,&_z_array};
+  if(i<0 || i>2)
+    throw INTERP_KERNEL::Exception("Invalid rank specified must be 0 or 1 or 2.");
+  if(arr!=*(thisArr[i]))
+    {
+      if(*(thisArr[i]))
+        (*(thisArr[i]))->decrRef();
+      (*(thisArr[i]))=arr;
+      if(*(thisArr[i]))
+        (*(thisArr[i]))->incrRef();
+      declareAsNew();
+    }
+}
+
 void MEDCouplingCMesh::setCoords(DataArrayDouble *coordsX, DataArrayDouble *coordsY, DataArrayDouble *coordsZ)
 {
   if(_x_array)
@@ -249,6 +427,18 @@ void MEDCouplingCMesh::setCoords(DataArrayDouble *coordsX, DataArrayDouble *coor
   declareAsNew();
 }
 
+MEDCouplingMesh *MEDCouplingCMesh::buildPart(const int *start, const int *end) const
+{
+  //not implemented yet !
+  return 0;
+}
+
+MEDCouplingMesh *MEDCouplingCMesh::buildPartAndReduceNodes(const int *start, const int *end, DataArrayInt*& arr) const
+{
+  //not implemented yet !
+  return 0;
+}
+
 void MEDCouplingCMesh::getBoundingBox(double *bbox) const
 {
   //not implemented yet !
@@ -364,3 +554,77 @@ DataArrayDouble *MEDCouplingCMesh::getBarycenterAndOwner() const
     }
   return ret;
 }
+
+void MEDCouplingCMesh::renumberCells(const int *old2NewBg, bool check) throw(INTERP_KERNEL::Exception)
+{
+  throw INTERP_KERNEL::Exception("Functionnality of renumbering cell not available for CMesh !");
+}
+
+void MEDCouplingCMesh::getTinySerializationInformation(std::vector<int>& tinyInfo, std::vector<std::string>& littleStrings) const
+{
+  tinyInfo.clear();
+  littleStrings.clear();
+  littleStrings.push_back(getName());
+  const DataArrayDouble *thisArr[3]={_x_array,_y_array,_z_array};
+  for(int i=0;i<3;i++)
+    {
+      int val=-1;
+      std::string st;
+      if(thisArr[i])
+        {
+          val=thisArr[i]->getNumberOfTuples();
+          st=thisArr[i]->getInfoOnComponent(0);
+        }
+      tinyInfo.push_back(val);
+      littleStrings.push_back(st);
+    }
+}
+
+void MEDCouplingCMesh::resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings) const
+{
+  a1->alloc(0,1);
+  int sum=0;
+  for(int i=0;i<3;i++)
+    if(tinyInfo[i]!=-1)
+      sum+=tinyInfo[i];
+  a2->alloc(sum,1);
+}
+
+void MEDCouplingCMesh::serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const
+{
+  a1=DataArrayInt::New();
+  a1->alloc(0,1);
+  const DataArrayDouble *thisArr[3]={_x_array,_y_array,_z_array};
+  int sz=0;
+  for(int i=0;i<3;i++)
+    {
+      if(thisArr[i])
+        sz+=thisArr[i]->getNumberOfTuples();
+    }
+  a2=DataArrayDouble::New();
+  a2->alloc(sz,1);
+  double *a2Ptr=a2->getPointer();
+  for(int i=0;i<3;i++)
+    if(thisArr[i])
+      a2Ptr=std::copy(thisArr[i]->getConstPointer(),thisArr[i]->getConstPointer()+thisArr[i]->getNumberOfTuples(),a2Ptr);
+}
+
+void MEDCouplingCMesh::unserialization(const std::vector<int>& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2,
+                                       const std::vector<std::string>& littleStrings)
+{
+  setName(littleStrings[0].c_str());
+  DataArrayDouble **thisArr[3]={&_x_array,&_y_array,&_z_array};
+  const double *data=a2->getConstPointer();
+  for(int i=0;i<3;i++)
+    {
+      if(tinyInfo[i]!=-1)
+        {
+          (*(thisArr[i]))=DataArrayDouble::New();
+          (*(thisArr[i]))->alloc(tinyInfo[i],1);
+          (*(thisArr[i]))->setInfoOnComponent(0,littleStrings[i+1].c_str());
+          std::copy(data,data+tinyInfo[i],(*(thisArr[i]))->getPointer());
+          data+=tinyInfo[i];
+        }
+    }
+}
+
index a8f0b53011c320a2bf11ea0fa3dea1332f07ec84..e08226512e0ab67ff01019a92850bd35de8f9915 100644 (file)
@@ -31,11 +31,18 @@ namespace ParaMEDMEM
   {
   public:
     static MEDCouplingCMesh *New();
+    MEDCouplingMesh *deepCpy() const;
+    MEDCouplingCMesh *clone(bool recDeepCpy) const;
     void updateTime();
     MEDCouplingMeshType getType() const { return CARTESIAN; }
+    void copyTinyStringsFrom(const MEDCouplingMesh *other) throw(INTERP_KERNEL::Exception);
     bool isEqual(const MEDCouplingMesh *other, double prec) const;
+    bool isEqualWithoutConsideringStr(const MEDCouplingMesh *other, double prec) const;
+    void checkDeepEquivalWith(const MEDCouplingMesh *other, int cellCompPol, double prec,
+                              DataArrayInt *&cellCor, DataArrayInt *&nodeCor) const throw(INTERP_KERNEL::Exception);
+    void checkDeepEquivalOnSameNodesWith(const MEDCouplingMesh *other, int cellCompPol, double prec,
+                                         DataArrayInt *&cellCor) const throw(INTERP_KERNEL::Exception);
     void checkCoherency() const throw(INTERP_KERNEL::Exception);
-    bool isStructured() const;
     int getNumberOfCells() const;
     int getNumberOfNodes() const;
     int getSpaceDimension() const;
@@ -44,13 +51,19 @@ namespace ParaMEDMEM
     int getNodeIdFromPos(int i, int j, int k) const;
     static void getPosFromId(int nodeId, int spaceDim, const int *split, int *res);
     INTERP_KERNEL::NormalizedCellType getTypeOfCell(int cellId) const;
+    int getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType type) const;
     void getNodeIdsOfCell(int cellId, std::vector<int>& conn) const;
     void getCoordinatesOfNode(int nodeId, std::vector<double>& coo) const;
+    std::string simpleRepr() const;
+    std::string advancedRepr() const;
     DataArrayDouble *getCoordsAt(int i) const throw(INTERP_KERNEL::Exception);
+    void setCoordsAt(int i, DataArrayDouble *arr) throw(INTERP_KERNEL::Exception);
     void setCoords(DataArrayDouble *coordsX,
                    DataArrayDouble *coordsY=0,
                    DataArrayDouble *coordsZ=0);
     // tools
+    MEDCouplingMesh *buildPart(const int *start, const int *end) const;
+    MEDCouplingMesh *buildPartAndReduceNodes(const int *start, const int *end, DataArrayInt*& arr) const;
     void getBoundingBox(double *bbox) const;
     MEDCouplingFieldDouble *getMeasureField(bool isAbs) const;
     MEDCouplingFieldDouble *getMeasureFieldOnNode(bool isAbs) const;
@@ -61,11 +74,19 @@ namespace ParaMEDMEM
     MEDCouplingMesh *mergeMyselfWith(const MEDCouplingMesh *other) const;
     DataArrayDouble *getCoordinatesAndOwner() const;
     DataArrayDouble *getBarycenterAndOwner() const;
+    void renumberCells(const int *old2NewBg, bool check) throw(INTERP_KERNEL::Exception);
     //some useful methods
     void getSplitCellValues(int *res) const;
     void getSplitNodeValues(int *res) const;
+    //serialisation-unserialization
+    void getTinySerializationInformation(std::vector<int>& tinyInfo, std::vector<std::string>& littleStrings) const;
+    void resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings) const;
+    void serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const;
+    void unserialization(const std::vector<int>& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2,
+                         const std::vector<std::string>& littleStrings);
   private:
     MEDCouplingCMesh();
+    MEDCouplingCMesh(const MEDCouplingCMesh& other, bool deepCpy);
     ~MEDCouplingCMesh();
   private:
     DataArrayDouble *_x_array;
index 3233ac549d6844ce51933712f460f8b771f4d377..29d27ade982186d402fb7cbf0932d1c6991f3003 100644 (file)
@@ -47,25 +47,77 @@ MEDCouplingExtrudedMesh *MEDCouplingExtrudedMesh::New(const MEDCouplingUMesh *me
   return new MEDCouplingExtrudedMesh(mesh3D,mesh2D,cell2DId);
 }
 
+/*!
+ * This constructor is here only for unserialisation process.
+ * This constructor is normally completely useless for end user.
+ */
+MEDCouplingExtrudedMesh *MEDCouplingExtrudedMesh::New()
+{
+  return new MEDCouplingExtrudedMesh;
+}
+
 MEDCouplingMeshType MEDCouplingExtrudedMesh::getType() const
 {
   return EXTRUDED;
 }
 
+/*!
+ * This method copyies all tiny strings from other (name and components name).
+ * @throw if other and this have not same mesh type.
+ */
+void MEDCouplingExtrudedMesh::copyTinyStringsFrom(const MEDCouplingMesh *other) throw(INTERP_KERNEL::Exception)
+{
+  const MEDCouplingExtrudedMesh *otherC=dynamic_cast<const MEDCouplingExtrudedMesh *>(other);
+  if(!otherC)
+    throw INTERP_KERNEL::Exception("MEDCouplingExtrudedMesh::copyTinyStringsFrom : meshes have not same type !");
+  MEDCouplingMesh::copyTinyStringsFrom(other);
+  _mesh2D->copyTinyStringsFrom(otherC->_mesh2D);
+  _mesh1D->copyTinyStringsFrom(otherC->_mesh1D);
+}
+
 MEDCouplingExtrudedMesh::MEDCouplingExtrudedMesh(const MEDCouplingUMesh *mesh3D, MEDCouplingUMesh *mesh2D, int cell2DId) throw(INTERP_KERNEL::Exception)
 try:_mesh2D(mesh2D),_mesh1D(MEDCouplingUMesh::New()),_mesh3D_ids(0),_cell_2D_id(cell2DId)
 {
   if(_mesh2D!=0)
     _mesh2D->incrRef();
   computeExtrusion(mesh3D);
+  setName(mesh3D->getName());
 }
-catch(INTERP_KERNEL::Exception&)
+catch(INTERP_KERNEL::Exception& e)
   {
+    if(_mesh2D)
+      _mesh2D->decrRef();
+    if(_mesh1D)
+      _mesh1D->decrRef();
+    if(_mesh3D_ids)
+      _mesh3D_ids->decrRef();
+    throw e;
   }
 
-bool MEDCouplingExtrudedMesh::isStructured() const
+MEDCouplingExtrudedMesh::MEDCouplingExtrudedMesh():_mesh2D(0),_mesh1D(0),_mesh3D_ids(0),_cell_2D_id(-1)
+{
+}
+
+MEDCouplingExtrudedMesh::MEDCouplingExtrudedMesh(const MEDCouplingExtrudedMesh& other, bool deepCpy):MEDCouplingMesh(other),_cell_2D_id(other._cell_2D_id)
 {
-  return false;
+  if(deepCpy)
+    {
+      _mesh2D=other._mesh2D->clone(true);
+      _mesh1D=other._mesh1D->clone(true);
+      _mesh3D_ids=other._mesh3D_ids->deepCopy();
+    }
+  else
+    {
+      _mesh2D=other._mesh2D;
+      if(_mesh2D)
+        _mesh2D->incrRef();
+      _mesh1D=other._mesh1D;
+      if(_mesh1D)
+        _mesh1D->incrRef();
+      _mesh3D_ids=other._mesh3D_ids;
+      if(_mesh3D_ids)
+        _mesh3D_ids->incrRef();
+    }
 }
 
 int MEDCouplingExtrudedMesh::getNumberOfCells() const
@@ -88,14 +140,88 @@ int MEDCouplingExtrudedMesh::getMeshDimension() const
   return 3;
 }
 
+MEDCouplingMesh *MEDCouplingExtrudedMesh::deepCpy() const
+{
+  return clone(true);
+}
+
+MEDCouplingExtrudedMesh *MEDCouplingExtrudedMesh::clone(bool recDeepCpy) const
+{
+  return new MEDCouplingExtrudedMesh(*this,recDeepCpy);
+}
+
+bool MEDCouplingExtrudedMesh::isEqual(const MEDCouplingMesh *other, double prec) const
+{
+  const MEDCouplingExtrudedMesh *otherC=dynamic_cast<const MEDCouplingExtrudedMesh *>(other);
+  if(!otherC)
+    return false;
+  if(!MEDCouplingMesh::isEqual(other,prec))
+    return false;
+  if(!_mesh2D->isEqual(otherC->_mesh2D,prec))
+    return false;
+  if(!_mesh1D->isEqual(otherC->_mesh1D,prec))
+    return false;
+  if(!_mesh3D_ids->isEqual(*otherC->_mesh3D_ids))
+    return false;
+  if(_cell_2D_id!=otherC->_cell_2D_id)
+    return false;
+  return true;
+}
+
+bool MEDCouplingExtrudedMesh::isEqualWithoutConsideringStr(const MEDCouplingMesh *other, double prec) const
+{
+  const MEDCouplingExtrudedMesh *otherC=dynamic_cast<const MEDCouplingExtrudedMesh *>(other);
+  if(!otherC)
+    return false;
+  if(!_mesh2D->isEqualWithoutConsideringStr(otherC->_mesh2D,prec))
+    return false;
+  if(!_mesh1D->isEqualWithoutConsideringStr(otherC->_mesh1D,prec))
+    return false;
+  if(!_mesh3D_ids->isEqualWithoutConsideringStr(*otherC->_mesh3D_ids))
+    return false;
+  if(_cell_2D_id!=otherC->_cell_2D_id)
+    return false;
+  return true;
+}
+
+void MEDCouplingExtrudedMesh::checkDeepEquivalWith(const MEDCouplingMesh *other, int cellCompPol, double prec,
+                                                   DataArrayInt *&cellCor, DataArrayInt *&nodeCor) const throw(INTERP_KERNEL::Exception)
+{
+  throw INTERP_KERNEL::Exception("MEDCouplingExtrudedMesh::checkDeepEquivalWith : not implemented yet !");
+}
+
+void MEDCouplingExtrudedMesh::checkDeepEquivalOnSameNodesWith(const MEDCouplingMesh *other, int cellCompPol, double prec,
+                                                              DataArrayInt *&cellCor) const throw(INTERP_KERNEL::Exception)
+{
+  throw INTERP_KERNEL::Exception("MEDCouplingExtrudedMesh::checkDeepEquivalOnSameNodesWith : not implemented yet !");
+}
+
 INTERP_KERNEL::NormalizedCellType MEDCouplingExtrudedMesh::getTypeOfCell(int cellId) const
 {
+  const int *ids=_mesh3D_ids->getConstPointer();
+  int nbOf3DCells=_mesh3D_ids->getNumberOfTuples();
+  const int *where=std::find(ids,ids+nbOf3DCells,cellId);
+  if(where==ids+nbOf3DCells)
+    throw INTERP_KERNEL::Exception("Invalid cellId specified >= getNumberOfCells() !");
   int nbOfCells2D=_mesh2D->getNumberOfCells();
-  int locId=cellId%nbOfCells2D;
+  int locId=std::distance(ids,where)%nbOfCells2D;
   INTERP_KERNEL::NormalizedCellType tmp=_mesh2D->getTypeOfCell(locId);
   return INTERP_KERNEL::CellModel::getCellModel(tmp).getExtrudedType();
 }
 
+int MEDCouplingExtrudedMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
+{
+  int ret=0;
+  int nbOfCells2D=_mesh2D->getNumberOfCells();
+  for(int i=0;i<nbOfCells2D;i++)
+    {
+      INTERP_KERNEL::NormalizedCellType t=_mesh2D->getTypeOfCell(i);
+      if(INTERP_KERNEL::CellModel::getCellModel(t).getExtrudedType()==type)
+        ret++;
+    }
+  return ret*_mesh1D->getNumberOfCells();
+}
+
 void MEDCouplingExtrudedMesh::getNodeIdsOfCell(int cellId, std::vector<int>& conn) const
 {
   int nbOfCells2D=_mesh2D->getNumberOfCells();
@@ -127,6 +253,31 @@ void MEDCouplingExtrudedMesh::getCoordinatesOfNode(int nodeId, std::vector<doubl
   coo.insert(coo.end(),tmp2.begin(),tmp2.end());
 }
 
+std::string MEDCouplingExtrudedMesh::simpleRepr() const
+{
+  std::ostringstream ret;
+  ret << "3D Extruded mesh from a 2D Surf Mesh with name : \"" << getName() << "\"\n";
+  ret << "Cell id where 1D mesh has been deduced : " << _cell_2D_id << "\n";
+  ret << "Number of cells : " << getNumberOfCells() << "(" << _mesh2D->getNumberOfCells() << "x" << _mesh1D->getNumberOfCells() << ")\n";
+  ret << "1D Mesh info : _____________________\n\n\n";
+  ret << _mesh1D->simpleRepr();
+  ret << "\n\n\n2D Mesh info : _____________________\n\n\n" << _mesh2D->simpleRepr() << "\n\n\n";
+  return ret.str();
+}
+
+std::string MEDCouplingExtrudedMesh::advancedRepr() const
+{
+  std::ostringstream ret;
+  ret << "3D Extruded mesh from a 2D Surf Mesh with name : \"" << getName() << "\"\n";
+  ret << "Cell id where 1D mesh has been deduced : " << _cell_2D_id << "\n";
+  ret << "Number of cells : " << getNumberOfCells() << "(" << _mesh2D->getNumberOfCells() << "x" << _mesh1D->getNumberOfCells() << ")\n";
+  ret << "1D Mesh info : _____________________\n\n\n";
+  ret << _mesh1D->advancedRepr();
+  ret << "\n\n\n2D Mesh info : _____________________\n\n\n" << _mesh2D->advancedRepr() << "\n\n\n";
+  ret << "3D cell ids per level :\n";
+  return ret.str();
+}
+
 void MEDCouplingExtrudedMesh::checkCoherency() const throw (INTERP_KERNEL::Exception)
 {
 }
@@ -165,13 +316,49 @@ void MEDCouplingExtrudedMesh::updateTime()
     }
 }
 
+void MEDCouplingExtrudedMesh::renumberCells(const int *old2NewBg, bool check) throw(INTERP_KERNEL::Exception)
+{
+  throw INTERP_KERNEL::Exception("Functionnality of renumbering cells unavailable for ExtrudedMesh");
+}
+
+MEDCouplingUMesh *MEDCouplingExtrudedMesh::build3DUnstructuredMesh() const
+{
+  MEDCouplingUMesh *ret=_mesh2D->buildExtrudedMeshFromThis(_mesh1D,0);
+  const int *renum=_mesh3D_ids->getConstPointer();
+  ret->renumberCells(renum,false);
+  ret->setName(getName());
+  return ret;
+}
+
 MEDCouplingFieldDouble *MEDCouplingExtrudedMesh::getMeasureField(bool) const
 {
-  //not implemented yet
-  return 0;
+  std::string name="MeasureOfMesh_";
+  name+=getName();
+  MEDCouplingFieldDouble *ret2D=_mesh2D->getMeasureField(true);
+  MEDCouplingFieldDouble *ret1D=_mesh1D->getMeasureField(true);
+  const double *ret2DPtr=ret2D->getArray()->getConstPointer();
+  const double *ret1DPtr=ret1D->getArray()->getConstPointer();
+  int nbOf2DCells=_mesh2D->getNumberOfCells();
+  int nbOf1DCells=_mesh1D->getNumberOfCells();
+  int nbOf3DCells=nbOf2DCells*nbOf1DCells;
+  const int *renum=_mesh3D_ids->getConstPointer();
+  MEDCouplingFieldDouble *ret=MEDCouplingFieldDouble::New(ON_CELLS,NO_TIME);
+  ret->setMesh(this);
+  DataArrayDouble *da=DataArrayDouble::New();
+  da->alloc(nbOf3DCells,1);
+  double *retPtr=da->getPointer();
+  for(int i=0;i<nbOf1DCells;i++)
+    for(int j=0;j<nbOf2DCells;j++)
+      retPtr[renum[i*nbOf2DCells+j]]=ret2DPtr[j]*ret1DPtr[i];
+  ret->setArray(da);
+  da->decrRef();
+  ret->setName(name.c_str());
+  ret2D->decrRef();
+  ret1D->decrRef();
+  return ret;
 }
 
-MEDCouplingFieldDouble *MEDCouplingExtrudedMesh::getMeasureFieldOnNode(bool) const
+MEDCouplingFieldDouble *MEDCouplingExtrudedMesh::getMeasureFieldOnNode(bool isAbs) const
 {
   //not implemented yet
   return 0;
@@ -179,8 +366,7 @@ MEDCouplingFieldDouble *MEDCouplingExtrudedMesh::getMeasureFieldOnNode(bool) con
 
 MEDCouplingFieldDouble *MEDCouplingExtrudedMesh::buildOrthogonalField() const
 {
-  //not implemented yet
-  throw INTERP_KERNEL::Exception("MEDCouplingExtrudedMesh::buildOrthogonalField not implemented yet !");
+  throw INTERP_KERNEL::Exception("MEDCouplingExtrudedMesh::buildOrthogonalField : This method has no sense for MEDCouplingExtrudedMesh that is 3D !");
 }
 
 int MEDCouplingExtrudedMesh::getCellContainingPoint(const double *pos, double eps) const
@@ -376,6 +562,18 @@ void MEDCouplingExtrudedMesh::translate(const double *vector)
   _mesh1D->translate(vector);
 }
 
+MEDCouplingMesh *MEDCouplingExtrudedMesh::buildPart(const int *start, const int *end) const
+{
+  // not implemented yet !
+  return 0;
+}
+
+MEDCouplingMesh *MEDCouplingExtrudedMesh::buildPartAndReduceNodes(const int *start, const int *end, DataArrayInt*& arr) const
+{
+  // not implemented yet !
+  return 0;
+}
+
 MEDCouplingMesh *MEDCouplingExtrudedMesh::mergeMyselfWith(const MEDCouplingMesh *other) const
 {
   // not implemented yet !
@@ -470,3 +668,109 @@ void MEDCouplingExtrudedMesh::computeExtrusionAlg(const MEDCouplingUMesh *mesh3D
   revDesc->decrRef();
   revDescIndx->decrRef();
 }
+
+void MEDCouplingExtrudedMesh::getTinySerializationInformation(std::vector<int>& tinyInfo, std::vector<std::string>& littleStrings) const
+{
+  std::vector<int> tinyInfo1;
+  std::vector<std::string> ls1;
+  _mesh2D->getTinySerializationInformation(tinyInfo1,ls1);
+  std::vector<int> tinyInfo2;
+  std::vector<std::string> ls2;
+  _mesh1D->getTinySerializationInformation(tinyInfo2,ls2);
+  tinyInfo.clear(); littleStrings.clear();
+  tinyInfo.insert(tinyInfo.end(),tinyInfo1.begin(),tinyInfo1.end());
+  littleStrings.insert(littleStrings.end(),ls1.begin(),ls1.end());
+  tinyInfo.insert(tinyInfo.end(),tinyInfo2.begin(),tinyInfo2.end());
+  littleStrings.insert(littleStrings.end(),ls2.begin(),ls2.end());
+  tinyInfo.push_back(_cell_2D_id);
+  tinyInfo.push_back(tinyInfo1.size());
+  tinyInfo.push_back(_mesh3D_ids->getNbOfElems());
+  littleStrings.push_back(getName());
+}
+
+void MEDCouplingExtrudedMesh::resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings) const
+{
+  int sz=tinyInfo.size();
+  int sz1=tinyInfo[sz-2];
+  std::vector<int> ti1(tinyInfo.begin(),tinyInfo.begin()+sz1);
+  std::vector<int> ti2(tinyInfo.begin()+sz1,tinyInfo.end()-3);
+  MEDCouplingUMesh *um=MEDCouplingUMesh::New();
+  DataArrayInt *a1tmp=DataArrayInt::New();
+  DataArrayDouble *a2tmp=DataArrayDouble::New();
+  int la1=0,la2=0;
+  std::vector<std::string> ls1,ls2;
+  um->resizeForUnserialization(ti1,a1tmp,a2tmp,ls1);
+  la1+=a1tmp->getNbOfElems(); la2+=a2tmp->getNbOfElems();
+  a1tmp->decrRef(); a2tmp->decrRef();
+  a1tmp=DataArrayInt::New(); a2tmp=DataArrayDouble::New();
+  um->resizeForUnserialization(ti2,a1tmp,a2tmp,ls2);
+  la1+=a1tmp->getNbOfElems(); la2+=a2tmp->getNbOfElems();
+  a1tmp->decrRef(); a2tmp->decrRef();
+  um->decrRef();
+  //
+  a1->alloc(la1+tinyInfo[sz-1],1);
+  a2->alloc(la2,1);
+  littleStrings.resize(ls1.size()+ls2.size()+1);
+}
+
+void MEDCouplingExtrudedMesh::serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const
+{
+  a1=DataArrayInt::New(); a2=DataArrayDouble::New();
+  DataArrayInt *a1_1=0,*a1_2=0;
+  DataArrayDouble *a2_1=0,*a2_2=0;
+  _mesh2D->serialize(a1_1,a2_1);
+  _mesh1D->serialize(a1_2,a2_2);
+  a1->alloc(a1_1->getNbOfElems()+a1_2->getNbOfElems()+_mesh3D_ids->getNbOfElems(),1);
+  int *ptri=a1->getPointer();
+  ptri=std::copy(a1_1->getConstPointer(),a1_1->getConstPointer()+a1_1->getNbOfElems(),ptri);
+  a1_1->decrRef();
+  ptri=std::copy(a1_2->getConstPointer(),a1_2->getConstPointer()+a1_2->getNbOfElems(),ptri);
+  a1_2->decrRef();
+  std::copy(_mesh3D_ids->getConstPointer(),_mesh3D_ids->getConstPointer()+_mesh3D_ids->getNbOfElems(),ptri);
+  a2->alloc(a2_1->getNbOfElems()+a2_2->getNbOfElems(),1);
+  double *ptrd=a2->getPointer();
+  ptrd=std::copy(a2_1->getConstPointer(),a2_1->getConstPointer()+a2_1->getNbOfElems(),ptrd);
+  a2_1->decrRef();
+  std::copy(a2_2->getConstPointer(),a2_2->getConstPointer()+a2_2->getNbOfElems(),ptrd);
+  a2_2->decrRef();
+}
+
+void MEDCouplingExtrudedMesh::unserialization(const std::vector<int>& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2, const std::vector<std::string>& littleStrings)
+{
+  setName(littleStrings.back().c_str());
+  int sz=tinyInfo.size();
+  int sz1=tinyInfo[sz-2];
+  _cell_2D_id=tinyInfo[sz-3];
+  std::vector<int> ti1(tinyInfo.begin(),tinyInfo.begin()+sz1);
+  std::vector<int> ti2(tinyInfo.begin()+sz1,tinyInfo.end()-3);
+  DataArrayInt *a1tmp=DataArrayInt::New();
+  DataArrayDouble *a2tmp=DataArrayDouble::New();
+  const int *a1Ptr=a1->getConstPointer();
+  const double *a2Ptr=a2->getConstPointer();
+  _mesh2D=MEDCouplingUMesh::New();
+  std::vector<std::string> ls1,ls2;
+  _mesh2D->resizeForUnserialization(ti1,a1tmp,a2tmp,ls1);
+  std::copy(a2Ptr,a2Ptr+a2tmp->getNbOfElems(),a2tmp->getPointer());
+  std::copy(a1Ptr,a1Ptr+a1tmp->getNbOfElems(),a1tmp->getPointer());
+  a2Ptr+=a2tmp->getNbOfElems();
+  a1Ptr+=a1tmp->getNbOfElems();
+  ls2.insert(ls2.end(),littleStrings.begin(),littleStrings.begin()+ls1.size());
+  _mesh2D->unserialization(ti1,a1tmp,a2tmp,ls2);
+  a1tmp->decrRef(); a2tmp->decrRef();
+  //
+  ls2.clear();
+  ls2.insert(ls2.end(),littleStrings.begin()+ls1.size(),littleStrings.end()-1);
+  _mesh1D=MEDCouplingUMesh::New();
+  a1tmp=DataArrayInt::New(); a2tmp=DataArrayDouble::New();
+  _mesh1D->resizeForUnserialization(ti2,a1tmp,a2tmp,ls1);
+  std::copy(a2Ptr,a2Ptr+a2tmp->getNbOfElems(),a2tmp->getPointer());
+  std::copy(a1Ptr,a1Ptr+a1tmp->getNbOfElems(),a1tmp->getPointer());
+  a1Ptr+=a1tmp->getNbOfElems();
+  _mesh1D->unserialization(ti2,a1tmp,a2tmp,ls2);
+  a1tmp->decrRef(); a2tmp->decrRef();
+  //
+  _mesh3D_ids=DataArrayInt::New();
+  int szIds=std::distance(a1Ptr,a1->getConstPointer()+a1->getNbOfElems());
+  _mesh3D_ids->alloc(szIds,1);
+  std::copy(a1Ptr,a1Ptr+szIds,_mesh3D_ids->getPointer());
+}
index 60f46c0478c672832234b1f63f3a27f5d5810bdb..e8915f4eebf3d483ec293fde18d104cb006a75c7 100644 (file)
@@ -36,21 +36,35 @@ namespace ParaMEDMEM
   {
   public:
     static MEDCouplingExtrudedMesh *New(const MEDCouplingUMesh *mesh3D, MEDCouplingUMesh *mesh2D, int cell2DId) throw(INTERP_KERNEL::Exception);
+    static MEDCouplingExtrudedMesh *New();
     MEDCouplingMeshType getType() const;
-    bool isStructured() const;
+    void copyTinyStringsFrom(const MEDCouplingMesh *other) throw(INTERP_KERNEL::Exception);
     int getNumberOfCells() const;
     int getNumberOfNodes() const;
     int getSpaceDimension() const;
     int getMeshDimension() const;
+    MEDCouplingMesh *deepCpy() const;
+    MEDCouplingExtrudedMesh *clone(bool recDeepCpy) const;
+    bool isEqual(const MEDCouplingMesh *other, double prec) const;
+    bool isEqualWithoutConsideringStr(const MEDCouplingMesh *other, double prec) const;
+    void checkDeepEquivalWith(const MEDCouplingMesh *other, int cellCompPol, double prec,
+                              DataArrayInt *&cellCor, DataArrayInt *&nodeCor) const throw(INTERP_KERNEL::Exception);
+    void checkDeepEquivalOnSameNodesWith(const MEDCouplingMesh *other, int cellCompPol, double prec,
+                                         DataArrayInt *&cellCor) const throw(INTERP_KERNEL::Exception);
     INTERP_KERNEL::NormalizedCellType getTypeOfCell(int cellId) const;
+    int getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType type) const;
     void getNodeIdsOfCell(int cellId, std::vector<int>& conn) const;
     void getCoordinatesOfNode(int nodeId, std::vector<double>& coo) const;
+    std::string simpleRepr() const;
+    std::string advancedRepr() const;
     void checkCoherency() const throw (INTERP_KERNEL::Exception);
     void getBoundingBox(double *bbox) const;
     void updateTime();
+    void renumberCells(const int *old2NewBg, bool check) throw(INTERP_KERNEL::Exception);
     MEDCouplingUMesh *getMesh2D() const { return _mesh2D; }
     MEDCouplingUMesh *getMesh1D() const { return _mesh1D; }
     DataArrayInt *getMesh3DIds() const { return _mesh3D_ids; }
+    MEDCouplingUMesh *build3DUnstructuredMesh() const;
     MEDCouplingFieldDouble *getMeasureField(bool) const;
     MEDCouplingFieldDouble *getMeasureFieldOnNode(bool) const;
     MEDCouplingFieldDouble *buildOrthogonalField() const;
@@ -61,11 +75,21 @@ namespace ParaMEDMEM
                                 MEDCouplingUMesh *&m1r, MEDCouplingUMesh *&m2r, double *v) throw(INTERP_KERNEL::Exception);
     void rotate(const double *center, const double *vector, double angle);
     void translate(const double *vector);
+    MEDCouplingMesh *buildPart(const int *start, const int *end) const;
+    MEDCouplingMesh *buildPartAndReduceNodes(const int *start, const int *end, DataArrayInt*& arr) const;
     MEDCouplingMesh *mergeMyselfWith(const MEDCouplingMesh *other) const;
     DataArrayDouble *getCoordinatesAndOwner() const;
     DataArrayDouble *getBarycenterAndOwner() const;
+    //Serialization unserialisation
+    void getTinySerializationInformation(std::vector<int>& tinyInfo, std::vector<std::string>& littleStrings) const;
+    void resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings) const;
+    void serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const;
+    void unserialization(const std::vector<int>& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2,
+                         const std::vector<std::string>& littleStrings);
   private:
     MEDCouplingExtrudedMesh(const MEDCouplingUMesh *mesh3D, MEDCouplingUMesh *mesh2D, int cell2DId) throw(INTERP_KERNEL::Exception);
+    MEDCouplingExtrudedMesh(const MEDCouplingExtrudedMesh& other, bool deepCpy);
+    MEDCouplingExtrudedMesh();
     void computeExtrusion(const MEDCouplingUMesh *mesh3D) throw(INTERP_KERNEL::Exception);
     void computeExtrusionAlg(const MEDCouplingUMesh *mesh3D) throw(INTERP_KERNEL::Exception);
     void build1DExtrusion(int idIn3DDesc, int newId, int nbOf1DLev, MEDCouplingUMesh *subMesh,
@@ -80,6 +104,7 @@ namespace ParaMEDMEM
   private:
     MEDCouplingUMesh *_mesh2D;
     MEDCouplingUMesh *_mesh1D;
+    //! New to old 3D cell Ids Array
     DataArrayInt *_mesh3D_ids;
     int _cell_2D_id;
   };
index d64a03822c882d3a51e892ad759343e0c97ae9a8..3a917c753fc9337005b156a839652de4e8e8ccb0 100644 (file)
@@ -29,7 +29,7 @@ bool MEDCouplingField::isEqual(const MEDCouplingField *other, double meshPrec, d
     return false;
   if(_desc!=other->_desc)
     return false;
-  if(!_type->isEqual(other->_type))
+  if(!_type->isEqual(other->_type,valsPrec))
     return false;
   if(_mesh==0 && other->_mesh==0)
     return true;
@@ -40,21 +40,50 @@ bool MEDCouplingField::isEqual(const MEDCouplingField *other, double meshPrec, d
   return _mesh->isEqual(other->_mesh,meshPrec);
 }
 
-bool MEDCouplingField::areCompatible(const MEDCouplingField *other) const
+bool MEDCouplingField::isEqualWithoutConsideringStr(const MEDCouplingField *other, double meshPrec, double valsPrec) const
 {
-  if(!_type->isEqual(other->_type))
+  if(!_type->isEqualWithoutConsideringStr(other->_type,valsPrec))
+    return false;
+  if(_mesh==0 && other->_mesh==0)
+    return true;
+  if(_mesh==0 || other->_mesh==0)
+    return false;
+  if(_mesh==other->_mesh)
+    return true;
+  return _mesh->isEqualWithoutConsideringStr(other->_mesh,meshPrec);
+}
+
+/*!
+ * This method states if 'this' and 'other' are compatibles each other before performing any treatment.
+ * This method is good for methods like : mergeFields.
+ * This method is not very demanding compared to areStrictlyCompatible that is better for operation on fields.
+ */
+bool MEDCouplingField::areCompatibleForMerge(const MEDCouplingField *other) const
+{
+  if(!_type->isEqual(other->_type,1.))
     return false;
   if(_mesh==other->_mesh)
     return true;
-  if(!_mesh->areCompatible(other->_mesh))
+  return _mesh->areCompatibleForMerge(other->_mesh);
+}
+
+/*!
+ * This method is more strict than MEDCouplingField::areCompatibleForMerge method.
+ * This method is used for operation on fields to operate a first check before attempting operation.
+ */
+bool MEDCouplingField::areStrictlyCompatible(const MEDCouplingField *other) const
+{
+  if(!_type->isEqual(other->_type,1.e-12))
     return false;
-  return true;
+  return _mesh==other->_mesh;
 }
 
 void MEDCouplingField::updateTime()
 {
   if(_mesh)
     updateTimeWith(*_mesh);
+  if(_type)
+    updateTimeWith(*_type);
 }
 
 TypeOfField MEDCouplingField::getTypeOfField() const
@@ -62,6 +91,17 @@ TypeOfField MEDCouplingField::getTypeOfField() const
   return _type->getEnum();
 }
 
+/*!
+ * This method retrieves the weighting field of 'this'. If no '_mesh' is defined an exception will be thrown.
+ * Warning the retrieved field life cycle is the responsability of caller.
+ */
+MEDCouplingFieldDouble *MEDCouplingField::buildWeightingField(bool isAbs) const throw(INTERP_KERNEL::Exception)
+{
+  if(_mesh==0)
+    throw INTERP_KERNEL::Exception("MEDCouplingField::getWeightingField : no mesh defined !!!");
+  return _type->getWeightingField(_mesh,isAbs);
+}
+
 void MEDCouplingField::setMesh(const MEDCouplingMesh *mesh)
 {
   if(mesh!=_mesh)
@@ -77,6 +117,126 @@ void MEDCouplingField::setMesh(const MEDCouplingMesh *mesh)
     }
 }
 
+/*!
+ * This method sets gauss localization by geometric type.
+ * @param type geometric type on which the gauss localization will be set.
+ * @param refCoo is the reference coordinates of the specified element. Its size has to be equal to nbOfNodesPerCell*dimOfType
+ * @param gsCoo are the coordinates of Gauss points in reference element specified by 'refCoo'. Its size must be equal to wg.size()*dimOfType
+ * @param wg are the weights on Gauss points. The size of this array is used to determine the number of Gauss point in the element.
+ * @throw when size of 'RefCoo' is not valid regarding 'type' parameter, it throws too when the mesh is not set before or if it is not a field on Gauss points.
+ */
+void MEDCouplingField::setGaussLocalizationOnType(INTERP_KERNEL::NormalizedCellType type, const std::vector<double>& refCoo,
+                                                  const std::vector<double>& gsCoo, const std::vector<double>& wg) throw(INTERP_KERNEL::Exception)
+{
+  if(!_mesh)
+    throw INTERP_KERNEL::Exception("Mesh has to be set before calling setGaussLocalizationOnType method !");
+  _type->setGaussLocalizationOnType(_mesh,type,refCoo,gsCoo,wg);
+}
+
+/*!
+ * This method sets on ids defined by [begin;end) their gauss localization. This method checks the coherency of cells ids in [begin;end) and 'refCoo' size.
+ * If an incoherence appears an exception will be thrown and no seting will be performed.
+ * An exception is thrown too if [begin,end) has a size lesser than 1.
+ * 
+ * @param refCoo is the reference coordinates of the specified element. Its size has to be equal to nbOfNodesPerCell*dimOfType
+ * @param gsCoo are the coordinates of Gauss points in reference element specified by 'refCoo'. Its size must be equal to wg.size()*dimOfType
+ * @param wg are the weights on Gauss points. The size of this array is used to determine the number of Gauss point in the element.
+ * @throw when size of 'RefCoo' is not valid regarding cells in [begin,end) parameters, it throws too when the mesh is not set before or if it is not a field on Gauss points.
+ */
+void MEDCouplingField::setGaussLocalizationOnCells(const int *begin, const int *end, const std::vector<double>& refCoo,
+                                                   const std::vector<double>& gsCoo, const std::vector<double>& wg) throw(INTERP_KERNEL::Exception)
+{
+  if(!_mesh)
+    throw INTERP_KERNEL::Exception("Mesh has to be set before calling setGaussLocalizationOnCells method !");
+  _type->setGaussLocalizationOnCells(_mesh,begin,end,refCoo,gsCoo,wg);
+}
+
+/*!
+ * This method resets all Gauss loalizations if any.
+ */
+void MEDCouplingField::clearGaussLocalizations()
+{
+  if(!_mesh)
+    throw INTERP_KERNEL::Exception("Mesh has to be set before calling clearGaussLocalizations method !");
+  _type->clearGaussLocalizations();
+}
+
+/*!
+ * This method returns reference to the Gauss localization object corresponding to 'locId' id.
+ * This method throws an exception if there is no mesh, invalid FieldDescription (different from Gauss) and if 'locId' is invalid because out of range given by
+ * MEDCouplingField::getNbOfGaussLocalization method.
+ * Warning this method is not const, so the returned object could be modified without any problem.
+ */
+MEDCouplingGaussLocalization& MEDCouplingField::getGaussLocalization(int locId) throw(INTERP_KERNEL::Exception)
+{
+  if(!_mesh)
+    throw INTERP_KERNEL::Exception("Mesh has to be set before calling getGaussLocalization method !");
+  return _type->getGaussLocalization(locId);
+}
+
+/*!
+ * This method returns reference to the Gauss localization object corresponding to 'locId' id.
+ * This method throws an exception if there is no mesh, invalid FieldDescription (different from Gauss) and if several localization ids have been found
+ * for a type.
+ */
+int MEDCouplingField::getGaussLocalizationIdOfOneType(INTERP_KERNEL::NormalizedCellType type) const throw(INTERP_KERNEL::Exception)
+{
+  if(!_mesh)
+    throw INTERP_KERNEL::Exception("Mesh has to be set before calling getGaussLocalizationIdOfOneType method !");
+  return _type->getGaussLocalizationIdOfOneType(type);
+}
+
+/*!
+ * This method returns number of Gauss localization available. Implicitely all ids in [0,getNbOfGaussLocalization()) is a valid Gauss localisation id.
+ * This method throws an exception if there is no mesh, invalid FieldDescription (different from Gauss)
+ */
+int MEDCouplingField::getNbOfGaussLocalization() const throw(INTERP_KERNEL::Exception)
+{
+  if(!_mesh)
+    throw INTERP_KERNEL::Exception("Mesh has to be set before calling getNbOfGaussLocalization method !");
+  return _type->getNbOfGaussLocalization();
+}
+
+/*!
+ * This method returns an id of Gauss localization in [0,getNbOfGaussLocalization()) that corresponds to the localization of the cell specified by its cellId.
+ * This methods throws an exception if there is no mesh, invalid FieldDescription (different from Gauss) or if at the cell with id 'cellId' in this->_mesh no
+ * Gauss localization has been set.
+ */
+int MEDCouplingField::getGaussLocalizationIdOfOneCell(int cellId) const throw(INTERP_KERNEL::Exception)
+{
+  if(!_mesh)
+    throw INTERP_KERNEL::Exception("Mesh has to be set before calling getGaussLocalizationIdOfOneCell method !");
+  return _type->getGaussLocalizationIdOfOneCell(cellId);
+}
+
+/*!
+ * This method returns all cellIds that share the same Gauss localization given by 'locId' parameter (in range [0,getNbOfGaussLocalization()) ).
+ * If no cells fit the Gauss localization given by 'locId' cellIds will be returned empty.
+ * @param locId input that specifies the id of Gauss localization.
+ * @param cellIds output parameter, that will contain the result if this method succeds. This parameter is systematically cleared when called.
+ * @throw  if there is no mesh, invalid FieldDescription (different from Gauss) or if locId not in [0,getNbOfGaussLocalization())
+ */
+void MEDCouplingField::getCellIdsHavingGaussLocalization(int locId, std::vector<int>& cellIds) const throw(INTERP_KERNEL::Exception)
+{
+  cellIds.clear();
+  if(!_mesh)
+    throw INTERP_KERNEL::Exception("Mesh has to be set before calling getGaussLocalizationIdOfOneCell method !");
+  _type->getCellIdsHavingGaussLocalization(locId,cellIds);
+}
+
+/*!
+ * This method returns reference to the Gauss localization object corresponding to 'locId' id.
+ * This method throws an exception if there is no mesh, invalid FieldDescription (different from Gauss) and if 'locId' is invalid because out of range given by
+ * MEDCouplingField::getNbOfGaussLocalization method.
+ * Warning this method is const.
+ */
+const MEDCouplingGaussLocalization& MEDCouplingField::getGaussLocalization(int locId) const throw(INTERP_KERNEL::Exception)
+{
+  if(!_mesh)
+    throw INTERP_KERNEL::Exception("Mesh has to be set before calling getGaussLocalization method !");
+  return _type->getGaussLocalization(locId);
+}
+
 MEDCouplingField::~MEDCouplingField()
 {
   if(_mesh)
@@ -84,11 +244,15 @@ MEDCouplingField::~MEDCouplingField()
   delete _type;
 }
 
+MEDCouplingField::MEDCouplingField(MEDCouplingFieldDiscretization *type):_mesh(0),_type(type)
+{
+}
+
 MEDCouplingField::MEDCouplingField(TypeOfField type):_mesh(0),_type(MEDCouplingFieldDiscretization::New(type))
 {
 }
 
-MEDCouplingField::MEDCouplingField(const MEDCouplingField& other):_name(other._name),_desc(other._name),
+MEDCouplingField::MEDCouplingField(const MEDCouplingField& other):_name(other._name),_desc(other._desc),
                                                                   _mesh(0),_type(other._type->clone())
 {
   if(other._mesh)
@@ -98,8 +262,11 @@ MEDCouplingField::MEDCouplingField(const MEDCouplingField& other):_name(other._n
     }
 }
 
-
+/*!
+ * This method returns a submesh of 'mesh' instance constituting cell ids contained in array defined as an interval [start;end).
+ * @ param di is an array returned that specifies entity ids (nodes, cells ids...) in mesh 'mesh' of entity in returned submesh.
+ */
 MEDCouplingMesh *MEDCouplingField::buildSubMeshData(const int *start, const int *end, DataArrayInt *&di) const
 {
-  return _type->buildSubMeshData(start,end,_mesh,di);
+  return _type->buildSubMeshData(_mesh,start,end,di);
 }
index 932c5d54c4d69d6ce6ccf3dd377d0a6eb0783268..d1ed3a27f63bdd21613a438db44d4c1e9aa34abe 100644 (file)
 #include "MEDCoupling.hxx"
 #include "MEDCouplingTimeLabel.hxx"
 #include "MEDCouplingRefCountObject.hxx"
+#include "NormalizedUnstructuredMesh.hxx"
 #include "InterpKernelException.hxx"
 
 #include <string>
+#include <vector>
 
 namespace ParaMEDMEM
 {
   class DataArrayInt;
   class MEDCouplingMesh;
+  class MEDCouplingFieldDouble;
   class MEDCouplingFieldDiscretization;
+  class MEDCouplingGaussLocalization;
 
   class MEDCOUPLING_EXPORT MEDCouplingField : public RefCountObject, public TimeLabel
   {
   public:
     virtual void checkCoherency() const throw(INTERP_KERNEL::Exception) = 0;
-    virtual bool areCompatible(const MEDCouplingField *other) const;
+    virtual bool areCompatibleForMerge(const MEDCouplingField *other) const;
+    virtual bool areStrictlyCompatible(const MEDCouplingField *other) const;
     virtual bool isEqual(const MEDCouplingField *other, double meshPrec, double valsPrec) const;
+    virtual bool isEqualWithoutConsideringStr(const MEDCouplingField *other, double meshPrec, double valsPrec) const;
     void setMesh(const ParaMEDMEM::MEDCouplingMesh *mesh);
     const ParaMEDMEM::MEDCouplingMesh *getMesh() const { return _mesh; }
     void setName(const char *name) { _name=name; }
@@ -46,13 +52,27 @@ namespace ParaMEDMEM
     void setDescription(const char *desc) { _desc=desc; }
     const char *getName() const { return _name.c_str(); }
     TypeOfField getTypeOfField() const;
+    MEDCouplingFieldDouble *buildWeightingField(bool isAbs) const throw(INTERP_KERNEL::Exception);
     MEDCouplingMesh *buildSubMeshData(const int *start, const int *end, DataArrayInt *&di) const;
     MEDCouplingFieldDiscretization *getDiscretization() const { return _type; }
+    // Gauss point specific methods
+    void setGaussLocalizationOnType(INTERP_KERNEL::NormalizedCellType type, const std::vector<double>& refCoo,
+                                    const std::vector<double>& gsCoo, const std::vector<double>& wg) throw(INTERP_KERNEL::Exception);
+    void setGaussLocalizationOnCells(const int *begin, const int *end, const std::vector<double>& refCoo,
+                                     const std::vector<double>& gsCoo, const std::vector<double>& wg) throw(INTERP_KERNEL::Exception);
+    void clearGaussLocalizations();
+    MEDCouplingGaussLocalization& getGaussLocalization(int locId) throw(INTERP_KERNEL::Exception);
+    int getGaussLocalizationIdOfOneType(INTERP_KERNEL::NormalizedCellType type) const throw(INTERP_KERNEL::Exception);
+    int getNbOfGaussLocalization() const throw(INTERP_KERNEL::Exception);
+    int getGaussLocalizationIdOfOneCell(int cellId) const throw(INTERP_KERNEL::Exception);
+    void getCellIdsHavingGaussLocalization(int locId, std::vector<int>& cellIds) const throw(INTERP_KERNEL::Exception);
+    const MEDCouplingGaussLocalization& getGaussLocalization(int locId) const throw(INTERP_KERNEL::Exception);
   protected:
     void updateTime();
   protected:
     MEDCouplingField(TypeOfField type);
     MEDCouplingField(const MEDCouplingField& other);
+    MEDCouplingField(MEDCouplingFieldDiscretization *type);
     virtual ~MEDCouplingField();
   protected:
     std::string _name;
index 7e7c7b29893d7519560d452a4fd0564b6f205f09..8633dc1f35634949baf8c861f1ae9b6ea8deb9a2 100644 (file)
 //
 
 #include "MEDCouplingFieldDiscretization.hxx"
-#include "MEDCouplingPointSet.hxx"
 #include "MEDCouplingCMesh.hxx"
 #include "MEDCouplingFieldDouble.hxx"
+#include "CellModel.hxx"
 
 #include "InterpolationUtils.hxx"
 
+#include <set>
 #include <limits>
 #include <algorithm>
-#include  <functional>
+#include <functional>
 
 using namespace ParaMEDMEM;
 
@@ -40,6 +41,14 @@ const char MEDCouplingFieldDiscretizationP1::REPR[]="P1";
 
 const TypeOfField MEDCouplingFieldDiscretizationP1::TYPE=ON_NODES;
 
+const char MEDCouplingFieldDiscretizationGauss::REPR[]="GAUSS";
+
+const TypeOfField MEDCouplingFieldDiscretizationGauss::TYPE=ON_GAUSS_PT;
+
+const char MEDCouplingFieldDiscretizationGaussNE::REPR[]="GSSNE";
+
+const TypeOfField MEDCouplingFieldDiscretizationGaussNE::TYPE=ON_GAUSS_NE;
+
 MEDCouplingFieldDiscretization::MEDCouplingFieldDiscretization():_precision(DFLT_PRECISION)
 {
 }
@@ -52,6 +61,10 @@ MEDCouplingFieldDiscretization *MEDCouplingFieldDiscretization::New(TypeOfField
       return new MEDCouplingFieldDiscretizationP0;
     case MEDCouplingFieldDiscretizationP1::TYPE:
       return new MEDCouplingFieldDiscretizationP1;
+    case MEDCouplingFieldDiscretizationGauss::TYPE:
+      return new MEDCouplingFieldDiscretizationGauss;
+    case MEDCouplingFieldDiscretizationGaussNE::TYPE:
+      return new MEDCouplingFieldDiscretizationGaussNE;
     default:
       throw INTERP_KERNEL::Exception("Choosen discretization is not implemented yet.");
     }
@@ -64,9 +77,187 @@ TypeOfField MEDCouplingFieldDiscretization::getTypeOfFieldFromStringRepr(const c
     return MEDCouplingFieldDiscretizationP0::TYPE;
   if(reprCpp==MEDCouplingFieldDiscretizationP1::REPR)
     return MEDCouplingFieldDiscretizationP1::TYPE;
+  if(reprCpp==MEDCouplingFieldDiscretizationGauss::REPR)
+    return MEDCouplingFieldDiscretizationGauss::TYPE;
+  if(reprCpp==MEDCouplingFieldDiscretizationGaussNE::REPR)
+    return MEDCouplingFieldDiscretizationGaussNE::TYPE;
   throw INTERP_KERNEL::Exception("Representation does not match with any field discretization !");
 }
 
+bool MEDCouplingFieldDiscretization::isEqualWithoutConsideringStr(const MEDCouplingFieldDiscretization *other, double eps) const
+{
+  return isEqual(other,eps);
+}
+
+/*!
+ * Excepted for MEDCouplingFieldDiscretizationPerCell no underlying TimeLabel object : nothing to do in generally.
+ */
+void MEDCouplingFieldDiscretization::updateTime()
+{
+}
+
+/*!
+ * Computes normL1 of DataArrayDouble instance arr.
+ * @param res output parameter expected to be of size arr->getNumberOfComponents();
+ * @throw when the field discretization fails on getWeighting fields (gauss points for example)
+ */
+void MEDCouplingFieldDiscretization::normL1(const MEDCouplingMesh *mesh, const DataArrayDouble *arr, double *res) const throw(INTERP_KERNEL::Exception)
+{
+  MEDCouplingFieldDouble *vol=getWeightingField(mesh,true);
+  int nbOfCompo=arr->getNumberOfComponents();
+  int nbOfElems=getNumberOfTuples(mesh);
+  std::fill(res,res+nbOfCompo,0.);
+  const double *arrPtr=arr->getConstPointer();
+  const double *volPtr=vol->getArray()->getConstPointer();
+  for(int i=0;i<nbOfElems;i++)
+    {
+      for(int j=0;j<nbOfCompo;j++)
+        res[j]+=fabs(arrPtr[i*nbOfCompo+j])*volPtr[i];
+    }
+  vol->decrRef();
+}
+
+/*!
+ * Computes normL2 of DataArrayDouble instance arr.
+ * @param res output parameter expected to be of size arr->getNumberOfComponents();
+ * @throw when the field discretization fails on getWeighting fields (gauss points for example)
+ */
+void MEDCouplingFieldDiscretization::normL2(const MEDCouplingMesh *mesh, const DataArrayDouble *arr, double *res) const throw(INTERP_KERNEL::Exception)
+{
+  MEDCouplingFieldDouble *vol=getWeightingField(mesh,true);
+  int nbOfCompo=arr->getNumberOfComponents();
+  int nbOfElems=getNumberOfTuples(mesh);
+  std::fill(res,res+nbOfCompo,0.);
+  const double *arrPtr=arr->getConstPointer();
+  const double *volPtr=vol->getArray()->getConstPointer();
+  for(int i=0;i<nbOfElems;i++)
+    {
+      for(int j=0;j<nbOfCompo;j++)
+        res[j]+=arrPtr[i*nbOfCompo+j]*arrPtr[i*nbOfCompo+j]*fabs(volPtr[i]);
+    }
+  std::transform(res,res+nbOfCompo,res,std::ptr_fun<double,double>(std::sqrt));
+  vol->decrRef();
+}
+
+/*!
+ * Computes integral of DataArrayDouble instance arr.
+ * @param res output parameter expected to be of size arr->getNumberOfComponents();
+ * @throw when the field discretization fails on getWeighting fields (gauss points for example)
+ */
+void MEDCouplingFieldDiscretization::integral(const MEDCouplingMesh *mesh, const DataArrayDouble *arr, bool isWAbs, double *res) const throw(INTERP_KERNEL::Exception)
+{
+  MEDCouplingFieldDouble *vol=getWeightingField(mesh,isWAbs);
+  int nbOfCompo=arr->getNumberOfComponents();
+  int nbOfElems=getNumberOfTuples(mesh);
+  std::fill(res,res+nbOfCompo,0.);
+  const double *arrPtr=arr->getConstPointer();
+  const double *volPtr=vol->getArray()->getConstPointer();
+  double *tmp=new double[nbOfCompo];
+  for (int i=0;i<nbOfElems;i++)
+    {
+      std::transform(arrPtr+i*nbOfCompo,arrPtr+(i+1)*nbOfCompo,tmp,std::bind2nd(std::multiplies<double>(),volPtr[i]));
+      std::transform(tmp,tmp+nbOfCompo,res,res,std::plus<double>());
+    }
+  delete [] tmp;
+  vol->decrRef();
+}
+
+void MEDCouplingFieldDiscretization::getSerializationIntArray(DataArrayInt *& arr) const
+{
+  arr=0;
+}
+
+/*!
+ * Empty : Not a bug
+ */
+void MEDCouplingFieldDiscretization::getTinySerializationIntInformation(std::vector<int>& tinyInfo) const
+{
+}
+
+/*!
+ * Empty : Not a bug
+ */
+void MEDCouplingFieldDiscretization::getTinySerializationDbleInformation(std::vector<double>& tinyInfo) const
+{
+}
+
+void MEDCouplingFieldDiscretization::resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *& arr)
+{
+  arr=0;
+}
+
+/*!
+ * Empty : Not a bug
+ */
+void MEDCouplingFieldDiscretization::finishUnserialization(const std::vector<double>& tinyInfo)
+{
+}
+
+/*!
+ * This method is typically the first step of renumbering. The implementation is empty it is not a bug only gauss is impacted
+ * virtualy by this method.
+ */
+void MEDCouplingFieldDiscretization::renumberCells(const int *old2NewBg, bool check) throw(INTERP_KERNEL::Exception)
+{
+}
+
+double MEDCouplingFieldDiscretization::getIJK(const MEDCouplingMesh *mesh, const DataArrayDouble *da,
+                                              int cellId, int nodeIdInCell, int compoId) const throw(INTERP_KERNEL::Exception)
+{
+  throw INTERP_KERNEL::Exception("getIJK Invalid ! only for GaussPoint and GaussNE discretizations !");
+}
+
+void MEDCouplingFieldDiscretization::setGaussLocalizationOnType(const MEDCouplingMesh *m, INTERP_KERNEL::NormalizedCellType type, const std::vector<double>& refCoo,
+                                                                const std::vector<double>& gsCoo, const std::vector<double>& wg) throw(INTERP_KERNEL::Exception)
+{
+  throw INTERP_KERNEL::Exception("Invalid method for the corresponding field discretization : available only for GaussPoint discretization !");
+}
+
+void MEDCouplingFieldDiscretization::setGaussLocalizationOnCells(const MEDCouplingMesh *m, const int *begin, const int *end, const std::vector<double>& refCoo,
+                                                                 const std::vector<double>& gsCoo, const std::vector<double>& wg) throw(INTERP_KERNEL::Exception)
+{
+  throw INTERP_KERNEL::Exception("Invalid method for the corresponding field discretization : available only for GaussPoint discretization !");
+}
+
+void MEDCouplingFieldDiscretization::clearGaussLocalizations() throw(INTERP_KERNEL::Exception)
+{
+  throw INTERP_KERNEL::Exception("Invalid method for the corresponding field discretization : available only for GaussPoint discretization !");
+}
+
+MEDCouplingGaussLocalization& MEDCouplingFieldDiscretization::getGaussLocalization(int locId) throw(INTERP_KERNEL::Exception)
+{
+  throw INTERP_KERNEL::Exception("Invalid method for the corresponding field discretization : available only for GaussPoint discretization !");
+}
+
+const MEDCouplingGaussLocalization& MEDCouplingFieldDiscretization::getGaussLocalization(int locId) const throw(INTERP_KERNEL::Exception)
+{
+  throw INTERP_KERNEL::Exception("Invalid method for the corresponding field discretization : available only for GaussPoint discretization !");
+}
+
+int MEDCouplingFieldDiscretization::getNbOfGaussLocalization() const throw(INTERP_KERNEL::Exception)
+{
+  throw INTERP_KERNEL::Exception("Invalid method for the corresponding field discretization : available only for GaussPoint discretization !");
+}
+
+int MEDCouplingFieldDiscretization::getGaussLocalizationIdOfOneCell(int cellId) const throw(INTERP_KERNEL::Exception)
+{
+  throw INTERP_KERNEL::Exception("Invalid method for the corresponding field discretization : available only for GaussPoint discretization !");
+}
+
+int MEDCouplingFieldDiscretization::getGaussLocalizationIdOfOneType(INTERP_KERNEL::NormalizedCellType type) const throw(INTERP_KERNEL::Exception)
+{
+  throw INTERP_KERNEL::Exception("Invalid method for the corresponding field discretization : available only for GaussPoint discretization !");
+}
+
+void MEDCouplingFieldDiscretization::getCellIdsHavingGaussLocalization(int locId, std::vector<int>& cellIds) const throw(INTERP_KERNEL::Exception)
+{
+  throw INTERP_KERNEL::Exception("Invalid method for the corresponding field discretization : available only for GaussPoint discretization !");
+}
+
+MEDCouplingFieldDiscretization::~MEDCouplingFieldDiscretization()
+{
+}
+
 TypeOfField MEDCouplingFieldDiscretizationP0::getEnum() const
 {
   return TYPE;
@@ -82,7 +273,7 @@ const char *MEDCouplingFieldDiscretizationP0::getStringRepr() const
   return REPR;
 }
 
-bool MEDCouplingFieldDiscretizationP0::isEqual(const MEDCouplingFieldDiscretization *other) const
+bool MEDCouplingFieldDiscretizationP0::isEqual(const MEDCouplingFieldDiscretization *other, double eps) const
 {
   const MEDCouplingFieldDiscretizationP0 *otherC=dynamic_cast<const MEDCouplingFieldDiscretizationP0 *>(other);
   return otherC!=0;
@@ -93,11 +284,34 @@ int MEDCouplingFieldDiscretizationP0::getNumberOfTuples(const MEDCouplingMesh *m
   return mesh->getNumberOfCells();
 }
 
+void MEDCouplingFieldDiscretizationP0::renumberArraysForCell(const MEDCouplingMesh *mesh, const std::vector<DataArrayDouble *>& arrays,
+                                                             const int *old2NewBg, bool check) throw(INTERP_KERNEL::Exception)
+{
+  const int *array=old2NewBg;
+  if(check)
+    array=DataArrayInt::checkAndPreparePermutation(old2NewBg,old2NewBg+mesh->getNumberOfCells());
+  for(std::vector<DataArrayDouble *>::const_iterator it=arrays.begin();it!=arrays.end();it++)
+    {
+      if(*it)
+        (*it)->renumberInPlace(array);
+    }
+  if(check)
+    delete [] array;
+}
+
 DataArrayDouble *MEDCouplingFieldDiscretizationP0::getLocalizationOfDiscValues(const MEDCouplingMesh *mesh) const
 {
   return mesh->getBarycenterAndOwner();
 }
 
+void MEDCouplingFieldDiscretizationP0::computeMeshRestrictionFromTupleIds(const MEDCouplingMesh *mesh, const int *partBg, const int *partEnd,
+                                                                          DataArrayInt *&cellRest)
+{
+  cellRest=DataArrayInt::New();
+  cellRest->alloc(std::distance(partBg,partEnd),1);
+  std::copy(partBg,partEnd,cellRest->getPointer());
+}
+
 void MEDCouplingFieldDiscretizationP0::checkCompatibilityWithNature(NatureOfField nat) const throw(INTERP_KERNEL::Exception)
 {
 }
@@ -138,7 +352,7 @@ void MEDCouplingFieldDiscretizationP0::getValueOnPos(const DataArrayDouble *arr,
 /*!
  * Nothing to do. It's not a bug.
  */
-void MEDCouplingFieldDiscretizationP0::renumberValuesOnNodes(const DataArrayInt *old2New, DataArrayDouble *arr) const
+void MEDCouplingFieldDiscretizationP0::renumberValuesOnNodes(const int *, DataArrayDouble *) const
 {
 }
 
@@ -147,11 +361,11 @@ void MEDCouplingFieldDiscretizationP0::renumberValuesOnNodes(const DataArrayInt
  * @ param di is an array returned that specifies entity ids (here cells ids) in mesh 'mesh' of entity in returned submesh.
  * Example : The first cell id of returned mesh has the (*di)[0] id in 'mesh'
  */
-MEDCouplingMesh *MEDCouplingFieldDiscretizationP0::buildSubMeshData(const int *start, const int *end, const MEDCouplingMesh *mesh, DataArrayInt *&di) const
+MEDCouplingMesh *MEDCouplingFieldDiscretizationP0::buildSubMeshData(const MEDCouplingMesh *mesh, const int *start, const int *end, DataArrayInt *&di) const
 {
-  MEDCouplingPointSet* ret=((const MEDCouplingPointSet *) mesh)->buildPartOfMySelf(start,end,false);
+  MEDCouplingMesh *ret=mesh->buildPart(start,end);
   di=DataArrayInt::New();
-  di->alloc(end-start,1);
+  di->alloc(std::distance(start,end),1);
   int *pt=di->getPointer();
   std::copy(start,end,pt);
   return ret;
@@ -172,12 +386,20 @@ const char *MEDCouplingFieldDiscretizationP1::getStringRepr() const
   return REPR;
 }
 
-bool MEDCouplingFieldDiscretizationP1::isEqual(const MEDCouplingFieldDiscretization *other) const
+bool MEDCouplingFieldDiscretizationP1::isEqual(const MEDCouplingFieldDiscretization *other, double eps) const
 {
   const MEDCouplingFieldDiscretizationP1 *otherC=dynamic_cast<const MEDCouplingFieldDiscretizationP1 *>(other);
   return otherC!=0;
 }
 
+/*!
+ * Nothing to do here.
+ */
+void MEDCouplingFieldDiscretizationP1::renumberArraysForCell(const MEDCouplingMesh *, const std::vector<DataArrayDouble *>& arrays,
+                                                             const int *old2NewBg, bool check) throw(INTERP_KERNEL::Exception)
+{
+}
+
 int MEDCouplingFieldDiscretizationP1::getNumberOfTuples(const MEDCouplingMesh *mesh) const
 {
   return mesh->getNumberOfNodes();
@@ -188,6 +410,12 @@ DataArrayDouble *MEDCouplingFieldDiscretizationP1::getLocalizationOfDiscValues(c
   return mesh->getCoordinatesAndOwner();
 }
 
+void MEDCouplingFieldDiscretizationP1::computeMeshRestrictionFromTupleIds(const MEDCouplingMesh *mesh, const int *partBg, const int *partEnd,
+                                                                          DataArrayInt *&cellRest)
+{
+  cellRest=mesh->getCellIdsFullyIncludedInNodeIds(partBg,partEnd);
+}
+
 void MEDCouplingFieldDiscretizationP1::checkCompatibilityWithNature(NatureOfField nat) const throw(INTERP_KERNEL::Exception)
 {
   if(nat!=ConservativeVolumic)
@@ -200,7 +428,7 @@ void MEDCouplingFieldDiscretizationP1::checkCoherencyBetween(const MEDCouplingMe
     {
       std::ostringstream message;
       message << "Field on nodes invalid because there are " << mesh->getNumberOfNodes();
-      message << " cells in mesh and " << da->getNumberOfTuples() << " tuples in field !";
+      message << " nodes in mesh and " << da->getNumberOfTuples() << " tuples in field !";
       throw INTERP_KERNEL::Exception(message.str().c_str());
     }
 }
@@ -252,10 +480,9 @@ void MEDCouplingFieldDiscretizationP1::getValueOnPos(const DataArrayDouble *arr,
   arr->getTuple(id,res);
 }
 
-void MEDCouplingFieldDiscretizationP1::renumberValuesOnNodes(const DataArrayInt *old2New, DataArrayDouble *arr) const
+void MEDCouplingFieldDiscretizationP1::renumberValuesOnNodes(const int *old2NewPtr, DataArrayDouble *arr) const
 {
-  int oldNbOfElems=old2New->getNbOfElems();
-  const int *old2NewPtr=old2New->getConstPointer();
+  int oldNbOfElems=arr->getNumberOfTuples();
   int nbOfComp=arr->getNumberOfComponents();
   int newNbOfTuples=(*std::max_element(old2NewPtr,old2NewPtr+oldNbOfElems))+1;
   DataArrayDouble *arrCpy=arr->deepCopy();
@@ -285,31 +512,642 @@ void MEDCouplingFieldDiscretizationP1::renumberValuesOnNodes(const DataArrayInt
 }
 
 /*!
- * This method invert array 'di' that is a conversion map from Old to New node numbering to New to Old node numbering.
+ * This method returns a submesh of 'mesh' instance constituting cell ids contained in array defined as an interval [start;end).
+* @ param di is an array returned that specifies entity ids (here nodes ids) in mesh 'mesh' of entity in returned submesh.
+ * Example : The first node id of returned mesh has the (*di)[0] id in 'mesh'
  */
-DataArrayInt *MEDCouplingFieldDiscretizationP1::invertArrayO2N2N2O(const MEDCouplingMesh *mesh, const DataArrayInt *di)
-{
-  DataArrayInt *ret=DataArrayInt::New();
-  ret->alloc(mesh->getNumberOfNodes(),1);
-  int nbOfOldNodes=di->getNumberOfTuples();
-  const int *old2New=di->getConstPointer();
-  int *pt=ret->getPointer();
-  for(int i=0;i!=nbOfOldNodes;i++)
-    if(old2New[i]!=-1)
-      pt[old2New[i]]=i;
+MEDCouplingMesh *MEDCouplingFieldDiscretizationP1::buildSubMeshData(const MEDCouplingMesh *mesh, const int *start, const int *end, DataArrayInt *&di) const
+{
+  MEDCouplingMesh *ret=mesh->buildPartAndReduceNodes(start,end,di);
   return ret;
 }
 
+MEDCouplingFieldDiscretizationPerCell::MEDCouplingFieldDiscretizationPerCell():_discr_per_cell(0)
+{
+}
+
+MEDCouplingFieldDiscretizationPerCell::~MEDCouplingFieldDiscretizationPerCell()
+{
+  if(_discr_per_cell)
+    _discr_per_cell->decrRef();
+}
+
+MEDCouplingFieldDiscretizationPerCell::MEDCouplingFieldDiscretizationPerCell(const MEDCouplingFieldDiscretizationPerCell& other):_discr_per_cell(0)
+{
+  DataArrayInt *arr=other._discr_per_cell;
+  if(arr)
+    _discr_per_cell=arr->deepCopy();
+}
+
+void MEDCouplingFieldDiscretizationPerCell::updateTime()
+{
+  if(_discr_per_cell)
+    updateTimeWith(*_discr_per_cell);
+}
+
+void MEDCouplingFieldDiscretizationPerCell::checkCoherencyBetween(const MEDCouplingMesh *mesh, const DataArrayDouble *da) const throw(INTERP_KERNEL::Exception)
+{
+  if(!_discr_per_cell)
+    throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationPerCell has no discretization per cell !");
+  int nbOfTuples=_discr_per_cell->getNumberOfTuples();
+  if(nbOfTuples!=mesh->getNumberOfCells())
+    throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationPerCell has a discretization per cell but it's not matching the underlying mesh !");
+}
+
+bool MEDCouplingFieldDiscretizationPerCell::isEqual(const MEDCouplingFieldDiscretization *other, double eps) const
+{
+  const MEDCouplingFieldDiscretizationPerCell *otherC=dynamic_cast<const MEDCouplingFieldDiscretizationPerCell *>(other);
+  if(!otherC)
+    return false;
+  if(_discr_per_cell==0)
+    return otherC->_discr_per_cell==0;
+  if(otherC->_discr_per_cell==0)
+    return false;
+  return _discr_per_cell->isEqual(*otherC->_discr_per_cell);
+}
+
+bool MEDCouplingFieldDiscretizationPerCell::isEqualWithoutConsideringStr(const MEDCouplingFieldDiscretization *other, double eps) const
+{
+  const MEDCouplingFieldDiscretizationPerCell *otherC=dynamic_cast<const MEDCouplingFieldDiscretizationPerCell *>(other);
+  if(!otherC)
+    return false;
+  if(_discr_per_cell==0)
+    return otherC->_discr_per_cell==0;
+  if(otherC->_discr_per_cell==0)
+    return false;
+  return _discr_per_cell->isEqualWithoutConsideringStr(*otherC->_discr_per_cell);
+}
+
 /*!
- * This method returns a submesh of 'mesh' instance constituting cell ids contained in array defined as an interval [start;end).
-* @ param di is an array returned that specifies entity ids (here nodes ids) in mesh 'mesh' of entity in returned submesh.
- * Example : The first node id of returned mesh has the (*di)[0] id in 'mesh'
+ * This method is typically the first step of renumbering. The impact on _discr_per_cell is necessary here.
+ * virtualy by this method.
+ */
+void MEDCouplingFieldDiscretizationPerCell::renumberCells(const int *old2NewBg, bool check) throw(INTERP_KERNEL::Exception)
+{
+  int nbCells=_discr_per_cell->getNumberOfTuples();
+  const int *array=old2NewBg;
+  if(check)
+    array=DataArrayInt::checkAndPreparePermutation(old2NewBg,old2NewBg+nbCells);
+  //
+  DataArrayInt *dpc=_discr_per_cell->renumber(array);
+  _discr_per_cell->decrRef();
+  _discr_per_cell=dpc;
+  //
+  if(check)
+    delete [] (int *)array;
+}
+
+void MEDCouplingFieldDiscretizationPerCell::buildDiscrPerCellIfNecessary(const MEDCouplingMesh *m)
+{
+  if(!_discr_per_cell)
+    {
+      _discr_per_cell=DataArrayInt::New();
+      int nbTuples=m->getNumberOfCells();
+      _discr_per_cell->alloc(nbTuples,1);
+      int *ptr=_discr_per_cell->getPointer();
+      std::fill(ptr,ptr+nbTuples,-1);
+    }
+}
+
+MEDCouplingFieldDiscretizationGauss::MEDCouplingFieldDiscretizationGauss()
+{
+}
+
+MEDCouplingFieldDiscretizationGauss::MEDCouplingFieldDiscretizationGauss(const MEDCouplingFieldDiscretizationGauss& other):MEDCouplingFieldDiscretizationPerCell(other),_loc(other._loc)
+{
+}
+
+TypeOfField MEDCouplingFieldDiscretizationGauss::getEnum() const
+{
+  return TYPE;
+}
+
+bool MEDCouplingFieldDiscretizationGauss::isEqual(const MEDCouplingFieldDiscretization *other, double eps) const
+{
+  const MEDCouplingFieldDiscretizationGauss *otherC=dynamic_cast<const MEDCouplingFieldDiscretizationGauss *>(other);
+  if(!otherC)
+    return false;
+  if(!MEDCouplingFieldDiscretizationPerCell::isEqual(other,eps))
+    return false;
+  if(_loc.size()!=otherC->_loc.size())
+    return false;
+  int sz=_loc.size();
+  for(int i=0;i<sz;i++)
+    if(!_loc[i].isEqual(otherC->_loc[i],eps))
+      return false;
+  return true;
+}
+
+bool MEDCouplingFieldDiscretizationGauss::isEqualWithoutConsideringStr(const MEDCouplingFieldDiscretization *other, double eps) const
+{
+  const MEDCouplingFieldDiscretizationGauss *otherC=dynamic_cast<const MEDCouplingFieldDiscretizationGauss *>(other);
+  if(!otherC)
+    return false;
+  if(!MEDCouplingFieldDiscretizationPerCell::isEqualWithoutConsideringStr(other,eps))
+    return false;
+  if(_loc.size()!=otherC->_loc.size())
+    return false;
+  int sz=_loc.size();
+  for(int i=0;i<sz;i++)
+    if(!_loc[i].isEqual(otherC->_loc[i],eps))
+      return false;
+  return true;
+}
+
+MEDCouplingFieldDiscretization *MEDCouplingFieldDiscretizationGauss::clone() const
+{
+  return new MEDCouplingFieldDiscretizationGauss(*this);
+}
+
+const char *MEDCouplingFieldDiscretizationGauss::getStringRepr() const
+{
+  return REPR;
+}
+
+int MEDCouplingFieldDiscretizationGauss::getNumberOfTuples(const MEDCouplingMesh *) const
+{
+  int ret=0;
+  const int *dcPtr=_discr_per_cell->getConstPointer();
+  int nbOfTuples=_discr_per_cell->getNumberOfTuples();
+  for(const int *w=dcPtr;w!=dcPtr+nbOfTuples;w++)
+    ret+=_loc[*w].getNumberOfGaussPt();
+  return ret;
+}
+
+void MEDCouplingFieldDiscretizationGauss::renumberArraysForCell(const MEDCouplingMesh *mesh, const std::vector<DataArrayDouble *>& arrays,
+                                                                const int *old2NewBg, bool check) throw(INTERP_KERNEL::Exception)
+{
+  const int *array=old2NewBg;
+  if(check)
+    array=DataArrayInt::checkAndPreparePermutation(old2NewBg,old2NewBg+mesh->getNumberOfCells());
+  int nbOfCells=_discr_per_cell->getNumberOfTuples();
+  int nbOfTuples=getNumberOfTuples(0);
+  const int *dcPtr=_discr_per_cell->getConstPointer();
+  int *array2=new int[nbOfTuples];//stores the final conversion array old2New to give to arrays in renumberInPlace.
+  int *array3=new int[nbOfCells];//store for each cell in present dcp array (already renumbered) the offset needed by each cell in new numbering.
+  array3[0]=0;
+  for(int i=1;i<nbOfCells;i++)
+    array3[i]=array3[i-1]+_loc[dcPtr[i-1]].getNumberOfGaussPt();
+  int j=0;
+  for(int i=0;i<nbOfCells;i++)
+    {
+      int nbOfGaussPt=_loc[dcPtr[array[i]]].getNumberOfGaussPt();
+      for(int k=0;k<nbOfGaussPt;k++,j++)
+        array2[j]=array3[array[i]]+k;
+    }
+  delete [] array3;
+  for(std::vector<DataArrayDouble *>::const_iterator it=arrays.begin();it!=arrays.end();it++)
+    if(*it)
+      (*it)->renumberInPlace(array2);
+  delete [] array2;
+  if(check)
+    delete [] (int*)array;
+}
+
+DataArrayDouble *MEDCouplingFieldDiscretizationGauss::getLocalizationOfDiscValues(const MEDCouplingMesh *mesh) const
+{
+  throw INTERP_KERNEL::Exception("Not implemented yet !");
+}
+
+void MEDCouplingFieldDiscretizationGauss::computeMeshRestrictionFromTupleIds(const MEDCouplingMesh *mesh, const int *partBg, const int *partEnd,
+                                                                             DataArrayInt *&cellRest)
+{
+  throw INTERP_KERNEL::Exception("Not implemented yet !");
+}
+
+/*!
+ * Empty : not a bug
+ */
+void MEDCouplingFieldDiscretizationGauss::checkCompatibilityWithNature(NatureOfField nat) const throw(INTERP_KERNEL::Exception)
+{
+}
+
+void MEDCouplingFieldDiscretizationGauss::getTinySerializationIntInformation(std::vector<int>& tinyInfo) const
+{
+  int val=-1;
+  if(_discr_per_cell)
+    val=_discr_per_cell->getNumberOfTuples();
+  tinyInfo.push_back(val);
+  tinyInfo.push_back(_loc.size());
+  if(_loc.empty())
+    tinyInfo.push_back(-1);
+  else
+    tinyInfo.push_back(_loc[0].getDimension());
+  for(std::vector<MEDCouplingGaussLocalization>::const_iterator iter=_loc.begin();iter!=_loc.end();iter++)
+    (*iter).pushTinySerializationIntInfo(tinyInfo);
+}
+
+void MEDCouplingFieldDiscretizationGauss::getTinySerializationDbleInformation(std::vector<double>& tinyInfo) const
+{
+  for(std::vector<MEDCouplingGaussLocalization>::const_iterator iter=_loc.begin();iter!=_loc.end();iter++)
+    (*iter).pushTinySerializationDblInfo(tinyInfo);
+}
+
+void MEDCouplingFieldDiscretizationGauss::getSerializationIntArray(DataArrayInt *& arr) const
+{
+  arr=0;
+  if(_discr_per_cell)
+    arr=_discr_per_cell;
+}
+
+void MEDCouplingFieldDiscretizationGauss::resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *& arr)
+{
+  int val=tinyInfo[0];
+  if(val>=0)
+    {
+      _discr_per_cell=DataArrayInt::New();
+      _discr_per_cell->alloc(val,1);
+    }
+  else
+    _discr_per_cell=0;
+  arr=_discr_per_cell;
+  int nbOfLoc=tinyInfo[1];
+  _loc.clear();
+  int dim=tinyInfo[2];
+  int delta=-1;
+  if(nbOfLoc>0)
+    delta=(tinyInfo.size()-3)/nbOfLoc;
+  for(int i=0;i<nbOfLoc;i++)
+    {
+      std::vector<int> tmp(tinyInfo.begin()+3+i*delta,tinyInfo.begin()+3+(i+1)*delta);
+      MEDCouplingGaussLocalization elt=MEDCouplingGaussLocalization::buildNewInstanceFromTinyInfo(dim,tmp);
+      _loc.push_back(elt);
+    }
+}
+
+void MEDCouplingFieldDiscretizationGauss::finishUnserialization(const std::vector<double>& tinyInfo)
+{
+  double *tmp=new double[tinyInfo.size()];
+  std::copy(tinyInfo.begin(),tinyInfo.end(),tmp);
+  const double *work=tmp;
+  for(std::vector<MEDCouplingGaussLocalization>::iterator iter=_loc.begin();iter!=_loc.end();iter++)
+    work=(*iter).fillWithValues(work);
+  delete [] tmp;
+}
+
+double MEDCouplingFieldDiscretizationGauss::getIJK(const MEDCouplingMesh *mesh, const DataArrayDouble *da,
+                                                   int cellId, int nodeIdInCell, int compoId) const throw(INTERP_KERNEL::Exception)
+{
+  int offset=getOffsetOfCell(cellId);
+  return da->getIJ(offset+nodeIdInCell,compoId);
+}
+
+void MEDCouplingFieldDiscretizationGauss::checkCoherencyBetween(const MEDCouplingMesh *mesh, const DataArrayDouble *da) const throw(INTERP_KERNEL::Exception)
+{
+  MEDCouplingFieldDiscretizationPerCell::checkCoherencyBetween(mesh,da);
+  for(std::vector<MEDCouplingGaussLocalization>::const_iterator iter=_loc.begin();iter!=_loc.end();iter++)
+    (*iter).checkCoherency();
+  int nbOfDesc=_loc.size();
+  int nbOfCells=mesh->getNumberOfCells();
+  const int *dc=_discr_per_cell->getConstPointer();
+  for(int i=0;i<nbOfCells;i++)
+    {
+      if(dc[i]>=nbOfDesc)
+        {
+          std::ostringstream oss; oss << "Cell # " << i << " of mesh \"" << mesh->getName() << "\" has an undefined gauss location ! Should never happend !";
+          throw INTERP_KERNEL::Exception(oss.str().c_str());
+        }
+      if(dc[i]<0)
+        {
+          std::ostringstream oss; oss << "Cell # " << i << " of mesh \"" << mesh->getName() << "\" has no gauss location !";
+          throw INTERP_KERNEL::Exception(oss.str().c_str());
+        }
+      if(mesh->getTypeOfCell(i)!=_loc[dc[i]].getType())
+        {
+          std::ostringstream oss; oss << "Types of mesh and gauss location mismatch for cell # " << i;
+          throw INTERP_KERNEL::Exception(oss.str().c_str());
+        }
+    }
+  int nbOfTuples=getNumberOfTuples(mesh);
+  if(nbOfTuples!=da->getNumberOfTuples())
+    {
+      std::ostringstream oss; oss << "Invalid number of tuples in the array : expecting " << nbOfTuples << " !";
+      throw INTERP_KERNEL::Exception(oss.str().c_str());
+    }
+}
+
+MEDCouplingFieldDouble *MEDCouplingFieldDiscretizationGauss::getWeightingField(const MEDCouplingMesh *mesh, bool isAbs) const
+{
+  throw INTERP_KERNEL::Exception("Not implemented yet !");
+}
+
+void MEDCouplingFieldDiscretizationGauss::getValueOn(const DataArrayDouble *arr, const MEDCouplingMesh *mesh, const double *loc, double *res) const
+{
+  throw INTERP_KERNEL::Exception("Not implemented yet !");
+}
+
+void MEDCouplingFieldDiscretizationGauss::getValueOnPos(const DataArrayDouble *arr, const MEDCouplingMesh *mesh, int i, int j, int k, double *res) const
+{
+  throw INTERP_KERNEL::Exception("getValueOnPos(i,j,k) : Not applyable for Gauss points !");
+}
+
+MEDCouplingMesh *MEDCouplingFieldDiscretizationGauss::buildSubMeshData(const MEDCouplingMesh *mesh, const int *start, const int *end, DataArrayInt *&di) const
+{
+  throw INTERP_KERNEL::Exception("Not implemented yet !");
+}
+
+/*!
+ * No implementation needed !
+ */
+void MEDCouplingFieldDiscretizationGauss::renumberValuesOnNodes(const int *, DataArrayDouble *) const
+{
+}
+
+void MEDCouplingFieldDiscretizationGauss::setGaussLocalizationOnType(const MEDCouplingMesh *m, INTERP_KERNEL::NormalizedCellType type, const std::vector<double>& refCoo,
+                                                                     const std::vector<double>& gsCoo, const std::vector<double>& wg) throw(INTERP_KERNEL::Exception)
+{
+  buildDiscrPerCellIfNecessary(m);
+  int id=_loc.size();
+  MEDCouplingGaussLocalization elt(type,refCoo,gsCoo,wg);
+  _loc.push_back(elt);
+  int *ptr=_discr_per_cell->getPointer();
+  int nbCells=m->getNumberOfCells();
+  for(int i=0;i<nbCells;i++)
+    if(m->getTypeOfCell(i)==type)
+      ptr[i]=id;
+  zipGaussLocalizations();
+}
+
+void MEDCouplingFieldDiscretizationGauss::setGaussLocalizationOnCells(const MEDCouplingMesh *m, const int *begin, const int *end, const std::vector<double>& refCoo,
+                                                                      const std::vector<double>& gsCoo, const std::vector<double>& wg) throw(INTERP_KERNEL::Exception)
+{
+  buildDiscrPerCellIfNecessary(m);
+  if(std::distance(begin,end)<1)
+    throw INTERP_KERNEL::Exception("Size of [begin,end) must be equal or greater than 1 !");
+  INTERP_KERNEL::NormalizedCellType type=m->getTypeOfCell(*begin);
+  MEDCouplingGaussLocalization elt(type,refCoo,gsCoo,wg);
+  int id=_loc.size();
+  int *ptr=_discr_per_cell->getPointer();
+  for(const int *w=begin+1;w!=end;w++)
+    {
+      if(m->getTypeOfCell(*w)!=type)
+        {
+          std::ostringstream oss; oss << "The cell with id " << *w << " has been detected to be incompatible in the [begin,end) array specified !";
+          throw INTERP_KERNEL::Exception(oss.str().c_str());
+        }
+    }
+  //
+  for(const int *w2=begin;w2!=end;w2++)
+    ptr[*w2]=id;
+  //
+  _loc.push_back(elt);
+  zipGaussLocalizations();
+}
+
+void MEDCouplingFieldDiscretizationGauss::clearGaussLocalizations() throw(INTERP_KERNEL::Exception)
+{
+  if(_discr_per_cell)
+    {
+      _discr_per_cell->decrRef();
+      _discr_per_cell=0;
+    }
+  _loc.clear();
+}
+
+MEDCouplingGaussLocalization& MEDCouplingFieldDiscretizationGauss::getGaussLocalization(int locId) throw(INTERP_KERNEL::Exception)
+{
+  checkLocalizationId(locId);
+  return _loc[locId];
+}
+
+int MEDCouplingFieldDiscretizationGauss::getNbOfGaussLocalization() const throw(INTERP_KERNEL::Exception)
+{
+  return _loc.size();
+}
+
+int MEDCouplingFieldDiscretizationGauss::getGaussLocalizationIdOfOneCell(int cellId) const throw(INTERP_KERNEL::Exception)
+{
+  if(!_discr_per_cell)
+    throw INTERP_KERNEL::Exception("No Gauss localization still set !");
+  int locId=_discr_per_cell->getConstPointer()[cellId];
+  if(locId<0)
+    throw INTERP_KERNEL::Exception("No Gauss localization set for the specified cell !");
+  return locId;
+}
+
+int MEDCouplingFieldDiscretizationGauss::getGaussLocalizationIdOfOneType(INTERP_KERNEL::NormalizedCellType type) const throw(INTERP_KERNEL::Exception)
+{
+  if(!_discr_per_cell)
+    throw INTERP_KERNEL::Exception("No Gauss localization still set !");
+  std::set<int> ret;
+  int id=0;
+  for(std::vector<MEDCouplingGaussLocalization>::const_iterator iter=_loc.begin();iter!=_loc.end();iter++,id++)
+    if((*iter).getType()==type)
+      ret.insert(id);
+  if(ret.empty())
+    throw INTERP_KERNEL::Exception("No gauss discretization found for the specified type !");
+  if(ret.size()>1)
+    throw INTERP_KERNEL::Exception("Several gauss discretizations have been found for the specified type !");
+  return *ret.begin();
+}
+
+void MEDCouplingFieldDiscretizationGauss::getCellIdsHavingGaussLocalization(int locId, std::vector<int>& cellIds) const throw(INTERP_KERNEL::Exception)
+{
+  if(locId<0 || locId>=(int)_loc.size())
+    throw INTERP_KERNEL::Exception("Invalid locId given : must be in range [0:getNbOfGaussLocalization()) !");
+  int nbOfTuples=_discr_per_cell->getNumberOfTuples();
+  const int *ptr=_discr_per_cell->getConstPointer();
+  for(int i=0;i<nbOfTuples;i++)
+    if(ptr[i]==locId)
+      cellIds.push_back(i);
+}
+
+const MEDCouplingGaussLocalization& MEDCouplingFieldDiscretizationGauss::getGaussLocalization(int locId) const throw(INTERP_KERNEL::Exception)
+{
+  checkLocalizationId(locId);
+  return _loc[locId];
+}
+
+void MEDCouplingFieldDiscretizationGauss::checkLocalizationId(int locId) const throw(INTERP_KERNEL::Exception)
+{
+  if(locId<0 || locId>=(int)_loc.size())
+    throw INTERP_KERNEL::Exception("Invalid locId given : must be in range [0:getNbOfGaussLocalization()) !");
+}
+
+int MEDCouplingFieldDiscretizationGauss::getOffsetOfCell(int cellId) const throw(INTERP_KERNEL::Exception)
+{
+  int ret=0;
+  const int *start=_discr_per_cell->getConstPointer();
+  for(const int *w=start;w!=start+cellId;w++)
+    ret+=_loc[*w].getNumberOfGaussPt();
+  return ret;
+}
+
+/*!
+ * This method makes the assumption that _discr_per_cell is set.
+ * This method reduces as much as possible number size of _loc.
+ * This method is usefull when several set on same cells has been done and that some Gauss Localization are no more used.
  */
-MEDCouplingMesh *MEDCouplingFieldDiscretizationP1::buildSubMeshData(const int *start, const int *end, const MEDCouplingMesh *mesh, DataArrayInt *&di) const
+void MEDCouplingFieldDiscretizationGauss::zipGaussLocalizations()
 {
-  MEDCouplingPointSet* ret=((const MEDCouplingPointSet *) mesh)->buildPartOfMySelf(start,end,true);
-  DataArrayInt *diInv=ret->zipCoordsTraducer();
-  di=invertArrayO2N2N2O(ret,diInv);
-  diInv->decrRef();
+  const int *start=_discr_per_cell->getConstPointer();
+  int nbOfTuples=_discr_per_cell->getNumberOfTuples();
+  int *tmp=new int[_loc.size()];
+  std::fill(tmp,tmp+_loc.size(),-2);
+  for(const int *w=start;w!=start+nbOfTuples;w++)
+    if(*w>=0)
+      tmp[*w]=1;
+  int fid=0;
+  for(int i=0;i<(int)_loc.size();i++)
+    if(tmp[i]!=-2)
+      tmp[i]=fid++;
+  if(fid==(int)_loc.size())
+    {//no zip needed
+      delete [] tmp;
+      return;
+    }
+  // zip needed
+  int *start2=_discr_per_cell->getPointer();
+  for(int *w2=start2;w2!=start2+nbOfTuples;w2++)
+    *w2=tmp[*w2];
+  std::vector<MEDCouplingGaussLocalization> tmpLoc;
+  for(int i=0;i<(int)_loc.size();i++)
+    if(tmp[i]!=-2)
+      tmpLoc.push_back(_loc[tmp[i]]);
+  delete [] tmp;
+  _loc=tmpLoc;
+}
+
+MEDCouplingFieldDiscretizationGaussNE::MEDCouplingFieldDiscretizationGaussNE()
+{
+}
+
+TypeOfField MEDCouplingFieldDiscretizationGaussNE::getEnum() const
+{
+  return TYPE;
+}
+
+MEDCouplingFieldDiscretization *MEDCouplingFieldDiscretizationGaussNE::clone() const
+{
+  return new MEDCouplingFieldDiscretizationGaussNE(*this);
+}
+
+const char *MEDCouplingFieldDiscretizationGaussNE::getStringRepr() const
+{
+  return REPR;
+}
+
+bool MEDCouplingFieldDiscretizationGaussNE::isEqual(const MEDCouplingFieldDiscretization *other, double eps) const
+{
+  const MEDCouplingFieldDiscretizationGaussNE *otherC=dynamic_cast<const MEDCouplingFieldDiscretizationGaussNE *>(other);
+  return otherC!=0;
+}
+
+int MEDCouplingFieldDiscretizationGaussNE::getNumberOfTuples(const MEDCouplingMesh *mesh) const
+{
+  int ret=0;
+  int nbOfCells=mesh->getNumberOfCells();
+  for(int i=0;i<nbOfCells;i++)
+    {
+      INTERP_KERNEL::NormalizedCellType type=mesh->getTypeOfCell(i);
+      const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::getCellModel(type);
+      if(cm.isDynamic())
+        throw INTERP_KERNEL::Exception("Not implemented yet Gauss node on elements for polygons and polyedrons !");
+      ret+=cm.getNumberOfNodes();
+    }
   return ret;
 }
+
+void MEDCouplingFieldDiscretizationGaussNE::renumberArraysForCell(const MEDCouplingMesh *mesh, const std::vector<DataArrayDouble *>& arrays,
+                                                                  const int *old2NewBg, bool check) throw(INTERP_KERNEL::Exception)
+{
+  const int *array=old2NewBg;
+  if(check)
+    array=DataArrayInt::checkAndPreparePermutation(old2NewBg,old2NewBg+mesh->getNumberOfCells());
+  int nbOfCells=mesh->getNumberOfCells();
+  int nbOfTuples=getNumberOfTuples(mesh);
+  int *array2=new int[nbOfTuples];//stores the final conversion array old2New to give to arrays in renumberInPlace.
+  int *array3=new int[nbOfCells];//store for each cell in after renumbering the offset needed by each cell in new numbering.
+  array3[0]=0;
+  for(int i=1;i<nbOfCells;i++)
+    {
+      INTERP_KERNEL::NormalizedCellType type=mesh->getTypeOfCell(std::distance(array,std::find(array,array+nbOfCells,i-1)));
+      const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::getCellModel(type);
+      array3[i]=array3[i-1]+cm.getNumberOfNodes();
+    }
+  int j=0;
+  for(int i=0;i<nbOfCells;i++)
+    {
+      INTERP_KERNEL::NormalizedCellType type=mesh->getTypeOfCell(i);
+      const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::getCellModel(type);
+      for(int k=0;k<(int)cm.getNumberOfNodes();k++,j++)
+        array2[j]=array3[array[i]]+k;
+    }
+  delete [] array3;
+  for(std::vector<DataArrayDouble *>::const_iterator it=arrays.begin();it!=arrays.end();it++)
+    if(*it)
+      (*it)->renumberInPlace(array2);
+  delete [] array2;
+  if(check)
+    delete [] (int*)array;
+}
+
+DataArrayDouble *MEDCouplingFieldDiscretizationGaussNE::getLocalizationOfDiscValues(const MEDCouplingMesh *mesh) const
+{
+  throw INTERP_KERNEL::Exception("Not implemented yet !");
+}
+
+void MEDCouplingFieldDiscretizationGaussNE::computeMeshRestrictionFromTupleIds(const MEDCouplingMesh *mesh, const int *partBg, const int *partEnd,
+                                                                               DataArrayInt *&cellRest)
+{
+  throw INTERP_KERNEL::Exception("Not implemented yet !");
+}
+
+void MEDCouplingFieldDiscretizationGaussNE::checkCompatibilityWithNature(NatureOfField nat) const throw(INTERP_KERNEL::Exception)
+{
+}
+
+double MEDCouplingFieldDiscretizationGaussNE::getIJK(const MEDCouplingMesh *mesh, const DataArrayDouble *da,
+                                                     int cellId, int nodeIdInCell, int compoId) const throw(INTERP_KERNEL::Exception)
+{
+  int offset=0;
+  for(int i=0;i<cellId;i++)
+    {
+      INTERP_KERNEL::NormalizedCellType type=mesh->getTypeOfCell(i);
+      const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::getCellModel(type);
+      offset+=cm.getNumberOfNodes();
+    }
+  return da->getIJ(offset+nodeIdInCell,compoId);
+}
+
+void MEDCouplingFieldDiscretizationGaussNE::checkCoherencyBetween(const MEDCouplingMesh *mesh, const DataArrayDouble *da) const throw(INTERP_KERNEL::Exception)
+{
+  int nbOfTuples=getNumberOfTuples(mesh);
+  if(nbOfTuples!=da->getNumberOfTuples())
+    {
+      std::ostringstream oss; oss << "Invalid number of tuples in the array : expecting " << nbOfTuples << " !";
+      throw INTERP_KERNEL::Exception(oss.str().c_str());
+    }
+}
+
+MEDCouplingFieldDouble *MEDCouplingFieldDiscretizationGaussNE::getWeightingField(const MEDCouplingMesh *mesh, bool isAbs) const
+{
+  throw INTERP_KERNEL::Exception("Not implemented yet !");
+}
+
+void MEDCouplingFieldDiscretizationGaussNE::getValueOn(const DataArrayDouble *arr, const MEDCouplingMesh *mesh, const double *loc, double *res) const
+{
+  throw INTERP_KERNEL::Exception("Not implemented yet !");
+}
+
+void MEDCouplingFieldDiscretizationGaussNE::getValueOnPos(const DataArrayDouble *arr, const MEDCouplingMesh *mesh, int i, int j, int k, double *res) const
+{
+  throw INTERP_KERNEL::Exception("getValueOnPos(i,j,k) : Not applyable for Gauss points !");
+}
+
+MEDCouplingMesh *MEDCouplingFieldDiscretizationGaussNE::buildSubMeshData(const MEDCouplingMesh *mesh, const int *start, const int *end, DataArrayInt *&di) const
+{
+  throw INTERP_KERNEL::Exception("Not implemented yet !");
+}
+
+/*!
+ * No implementation needed !
+ */
+void MEDCouplingFieldDiscretizationGaussNE::renumberValuesOnNodes(const int *, DataArrayDouble *) const
+{
+}
+
+MEDCouplingFieldDiscretizationGaussNE::MEDCouplingFieldDiscretizationGaussNE(const MEDCouplingFieldDiscretizationGaussNE& other):MEDCouplingFieldDiscretization(other)
+{
+}
+
index 25d52f542b137e666bb8f43f9686a81bb02ce05d..0773d13e70ce844b1dc8ecf0dd58b2b1a3eca8bf 100644 (file)
 //  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
 //
 
-#ifndef __MEDCOUPLINGFIELDDISCRETIZATION_HXX__
-#define __MEDCOUPLINGFIELDDISCRETIZATION_HXX__
+#ifndef __PARAMEDMEM_MEDCOUPLINGFIELDDISCRETIZATION_HXX__
+#define __PARAMEDMEM_MEDCOUPLINGFIELDDISCRETIZATION_HXX__
 
 #include "MEDCoupling.hxx"
 #include "MEDCouplingRefCountObject.hxx"
 #include "InterpKernelException.hxx"
+#include "MEDCouplingTimeLabel.hxx"
 #include "MEDCouplingNatureOfField.hxx"
+#include "MEDCouplingGaussLocalization.hxx"
+
+#include <vector>
 
 namespace ParaMEDMEM
 {
@@ -32,26 +36,54 @@ namespace ParaMEDMEM
   class DataArrayDouble;
   class MEDCouplingFieldDouble;
 
-  class MEDCOUPLING_EXPORT MEDCouplingFieldDiscretization
+  class MEDCOUPLING_EXPORT MEDCouplingFieldDiscretization : public TimeLabel
   {
   public:
     static MEDCouplingFieldDiscretization *New(TypeOfField type);
     double getPrecision() const { return _precision; }
     void setPrecision(double val) { _precision=val; }
+    void updateTime();
     static TypeOfField getTypeOfFieldFromStringRepr(const char *repr) throw(INTERP_KERNEL::Exception);
     virtual TypeOfField getEnum() const = 0;
-    virtual bool isEqual(const MEDCouplingFieldDiscretization *other) const = 0;
+    virtual bool isEqual(const MEDCouplingFieldDiscretization *other, double eps) const = 0;
+    virtual bool isEqualWithoutConsideringStr(const MEDCouplingFieldDiscretization *other, double eps) const;
     virtual MEDCouplingFieldDiscretization *clone() const = 0;
     virtual const char *getStringRepr() const = 0;
     virtual int getNumberOfTuples(const MEDCouplingMesh *mesh) const = 0;
+    virtual void normL1(const MEDCouplingMesh *mesh, const DataArrayDouble *arr, double *res) const throw(INTERP_KERNEL::Exception);
+    virtual void normL2(const MEDCouplingMesh *mesh, const DataArrayDouble *arr, double *res) const throw(INTERP_KERNEL::Exception);
+    virtual void integral(const MEDCouplingMesh *mesh, const DataArrayDouble *arr, bool isWAbs, double *res) const throw(INTERP_KERNEL::Exception);
     virtual DataArrayDouble *getLocalizationOfDiscValues(const MEDCouplingMesh *mesh) const = 0;
+    virtual void computeMeshRestrictionFromTupleIds(const MEDCouplingMesh *mesh, const int *partBg, const int *partEnd,
+                                                    DataArrayInt *&cellRest) = 0;
     virtual void checkCompatibilityWithNature(NatureOfField nat) const throw(INTERP_KERNEL::Exception) = 0;
+    virtual void renumberCells(const int *old2NewBg, bool check) throw(INTERP_KERNEL::Exception);
+    virtual void renumberArraysForCell(const MEDCouplingMesh *mesh, const std::vector<DataArrayDouble *>& arrays,
+                                       const int *old2NewBg, bool check) throw(INTERP_KERNEL::Exception) = 0;
+    virtual double getIJK(const MEDCouplingMesh *mesh, const DataArrayDouble *da, int cellId, int nodeIdInCell, int compoId) const throw(INTERP_KERNEL::Exception);
     virtual void checkCoherencyBetween(const MEDCouplingMesh *mesh, const DataArrayDouble *da) const throw(INTERP_KERNEL::Exception) = 0;
     virtual MEDCouplingFieldDouble *getWeightingField(const MEDCouplingMesh *mesh, bool isAbs) const = 0;
     virtual void getValueOn(const DataArrayDouble *arr, const MEDCouplingMesh *mesh, const double *loc, double *res) const = 0;
     virtual void getValueOnPos(const DataArrayDouble *arr, const MEDCouplingMesh *mesh, int i, int j, int k, double *res) const = 0;
-    virtual MEDCouplingMesh *buildSubMeshData(const int *start, const int *end, const MEDCouplingMesh *mesh, DataArrayInt *&di) const = 0;
-    virtual void renumberValuesOnNodes(const DataArrayInt *old2New, DataArrayDouble *arr) const = 0;
+    virtual MEDCouplingMesh *buildSubMeshData(const MEDCouplingMesh *mesh, const int *start, const int *end, DataArrayInt *&di) const = 0;
+    virtual void renumberValuesOnNodes(const int *old2New, DataArrayDouble *arr) const = 0;
+    virtual void getSerializationIntArray(DataArrayInt *& arr) const;
+    virtual void getTinySerializationIntInformation(std::vector<int>& tinyInfo) const;
+    virtual void getTinySerializationDbleInformation(std::vector<double>& tinyInfo) const;
+    virtual void finishUnserialization(const std::vector<double>& tinyInfo);
+    virtual void resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *& arr);
+    virtual void setGaussLocalizationOnType(const MEDCouplingMesh *m, INTERP_KERNEL::NormalizedCellType type, const std::vector<double>& refCoo,
+                                            const std::vector<double>& gsCoo, const std::vector<double>& wg) throw(INTERP_KERNEL::Exception);
+    virtual void setGaussLocalizationOnCells(const MEDCouplingMesh *m, const int *begin, const int *end, const std::vector<double>& refCoo,
+                                             const std::vector<double>& gsCoo, const std::vector<double>& wg) throw(INTERP_KERNEL::Exception);
+    virtual void clearGaussLocalizations() throw(INTERP_KERNEL::Exception);
+    virtual MEDCouplingGaussLocalization& getGaussLocalization(int locId) throw(INTERP_KERNEL::Exception);
+    virtual int getNbOfGaussLocalization() const throw(INTERP_KERNEL::Exception);
+    virtual int getGaussLocalizationIdOfOneCell(int cellId) const throw(INTERP_KERNEL::Exception);
+    virtual int getGaussLocalizationIdOfOneType(INTERP_KERNEL::NormalizedCellType type) const throw(INTERP_KERNEL::Exception);
+    virtual void getCellIdsHavingGaussLocalization(int locId, std::vector<int>& cellIds) const throw(INTERP_KERNEL::Exception);
+    virtual const MEDCouplingGaussLocalization& getGaussLocalization(int locId) const throw(INTERP_KERNEL::Exception);
+    virtual ~MEDCouplingFieldDiscretization();
   protected:
     MEDCouplingFieldDiscretization();
   protected:
@@ -65,16 +97,20 @@ namespace ParaMEDMEM
     TypeOfField getEnum() const;
     MEDCouplingFieldDiscretization *clone() const;
     const char *getStringRepr() const;
-    bool isEqual(const MEDCouplingFieldDiscretization *other) const;
+    bool isEqual(const MEDCouplingFieldDiscretization *other, double eps) const;
     int getNumberOfTuples(const MEDCouplingMesh *mesh) const;
+    void renumberArraysForCell(const MEDCouplingMesh *mesh, const std::vector<DataArrayDouble *>& arrays,
+                               const int *old2NewBg, bool check) throw(INTERP_KERNEL::Exception);
     DataArrayDouble *getLocalizationOfDiscValues(const MEDCouplingMesh *mesh) const;
     void checkCompatibilityWithNature(NatureOfField nat) const throw(INTERP_KERNEL::Exception);
+    void computeMeshRestrictionFromTupleIds(const MEDCouplingMesh *mesh, const int *partBg, const int *partEnd,
+                                            DataArrayInt *&cellRest);
     void checkCoherencyBetween(const MEDCouplingMesh *mesh, const DataArrayDouble *da) const throw(INTERP_KERNEL::Exception);
     MEDCouplingFieldDouble *getWeightingField(const MEDCouplingMesh *mesh, bool isAbs) const;
     void getValueOn(const DataArrayDouble *arr, const MEDCouplingMesh *mesh, const double *loc, double *res) const;
     void getValueOnPos(const DataArrayDouble *arr, const MEDCouplingMesh *mesh, int i, int j, int k, double *res) const;
-    void renumberValuesOnNodes(const DataArrayInt *old2New, DataArrayDouble *arr) const;
-    MEDCouplingMesh *buildSubMeshData(const int *start, const int *end, const MEDCouplingMesh *mesh, DataArrayInt *&di) const;
+    void renumberValuesOnNodes(const int *old2New, DataArrayDouble *arr) const;
+    MEDCouplingMesh *buildSubMeshData(const MEDCouplingMesh *mesh, const int *start, const int *end, DataArrayInt *&di) const;
   public:
     static const char REPR[];
     static const TypeOfField TYPE;
@@ -86,17 +122,124 @@ namespace ParaMEDMEM
     TypeOfField getEnum() const;
     MEDCouplingFieldDiscretization *clone() const;
     const char *getStringRepr() const;
-    bool isEqual(const MEDCouplingFieldDiscretization *other) const;
+    bool isEqual(const MEDCouplingFieldDiscretization *other, double eps) const;
+    int getNumberOfTuples(const MEDCouplingMesh *mesh) const;
+    void renumberArraysForCell(const MEDCouplingMesh *mesh, const std::vector<DataArrayDouble *>& arrays,
+                               const int *old2NewBg, bool check) throw(INTERP_KERNEL::Exception);
+    DataArrayDouble *getLocalizationOfDiscValues(const MEDCouplingMesh *mesh) const;
+    void computeMeshRestrictionFromTupleIds(const MEDCouplingMesh *mesh, const int *partBg, const int *partEnd,
+                                            DataArrayInt *&cellRest);
+    void checkCompatibilityWithNature(NatureOfField nat) const throw(INTERP_KERNEL::Exception);
+    void checkCoherencyBetween(const MEDCouplingMesh *mesh, const DataArrayDouble *da) const throw(INTERP_KERNEL::Exception);
+    MEDCouplingFieldDouble *getWeightingField(const MEDCouplingMesh *mesh, bool isAbs) const;
+    void getValueOn(const DataArrayDouble *arr, const MEDCouplingMesh *mesh, const double *loc, double *res) const;
+    void getValueOnPos(const DataArrayDouble *arr, const MEDCouplingMesh *mesh, int i, int j, int k, double *res) const;
+    MEDCouplingMesh *buildSubMeshData(const MEDCouplingMesh *mesh, const int *start, const int *end, DataArrayInt *&di) const;
+    void renumberValuesOnNodes(const int *old2New, DataArrayDouble *arr) const;
+  public:
+    static const char REPR[];
+    static const TypeOfField TYPE;
+  };
+
+  /*!
+   * This class abstracts MEDCouplingFieldDiscretization that needs an information on each cell to perform their job.
+   * All classes that inherits from this are more linked to mesh.
+   */
+  class MEDCOUPLING_EXPORT MEDCouplingFieldDiscretizationPerCell : public MEDCouplingFieldDiscretization
+  {
+  protected:
+    MEDCouplingFieldDiscretizationPerCell();
+    MEDCouplingFieldDiscretizationPerCell(const MEDCouplingFieldDiscretizationPerCell& other);
+    ~MEDCouplingFieldDiscretizationPerCell();
+    void updateTime();
+    void checkCoherencyBetween(const MEDCouplingMesh *mesh, const DataArrayDouble *da) const throw(INTERP_KERNEL::Exception);
+    bool isEqual(const MEDCouplingFieldDiscretization *other, double eps) const;
+    bool isEqualWithoutConsideringStr(const MEDCouplingFieldDiscretization *other, double eps) const;
+    void renumberCells(const int *old2NewBg, bool check) throw(INTERP_KERNEL::Exception);
+  protected:
+    void buildDiscrPerCellIfNecessary(const MEDCouplingMesh *m);
+  protected:
+    DataArrayInt *_discr_per_cell;
+  };
+
+  class MEDCOUPLING_EXPORT MEDCouplingFieldDiscretizationGauss : public MEDCouplingFieldDiscretizationPerCell
+  {
+  public:
+    MEDCouplingFieldDiscretizationGauss();
+    TypeOfField getEnum() const;
+    bool isEqual(const MEDCouplingFieldDiscretization *other, double eps) const;
+    bool isEqualWithoutConsideringStr(const MEDCouplingFieldDiscretization *other, double eps) const;
+    MEDCouplingFieldDiscretization *clone() const;
+    const char *getStringRepr() const;
+    int getNumberOfTuples(const MEDCouplingMesh *mesh) const;
+    void renumberArraysForCell(const MEDCouplingMesh *mesh, const std::vector<DataArrayDouble *>& arrays,
+                               const int *old2NewBg, bool check) throw(INTERP_KERNEL::Exception);
+    DataArrayDouble *getLocalizationOfDiscValues(const MEDCouplingMesh *mesh) const;
+    void computeMeshRestrictionFromTupleIds(const MEDCouplingMesh *mesh, const int *partBg, const int *partEnd,
+                                            DataArrayInt *&cellRest);
+    void checkCompatibilityWithNature(NatureOfField nat) const throw(INTERP_KERNEL::Exception);
+    void getTinySerializationIntInformation(std::vector<int>& tinyInfo) const;
+    void getTinySerializationDbleInformation(std::vector<double>& tinyInfo) const;
+    void finishUnserialization(const std::vector<double>& tinyInfo);
+    void getSerializationIntArray(DataArrayInt *& arr) const;
+    void resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *& arr);
+    double getIJK(const MEDCouplingMesh *mesh, const DataArrayDouble *da, int cellId, int nodeIdInCell, int compoId) const throw(INTERP_KERNEL::Exception);
+    void checkCoherencyBetween(const MEDCouplingMesh *mesh, const DataArrayDouble *da) const throw(INTERP_KERNEL::Exception);
+    MEDCouplingFieldDouble *getWeightingField(const MEDCouplingMesh *mesh, bool isAbs) const;
+    void getValueOn(const DataArrayDouble *arr, const MEDCouplingMesh *mesh, const double *loc, double *res) const;
+    void getValueOnPos(const DataArrayDouble *arr, const MEDCouplingMesh *mesh, int i, int j, int k, double *res) const;
+    MEDCouplingMesh *buildSubMeshData(const MEDCouplingMesh *mesh, const int *start, const int *end, DataArrayInt *&di) const;
+    void renumberValuesOnNodes(const int *old2New, DataArrayDouble *arr) const;
+    void setGaussLocalizationOnType(const MEDCouplingMesh *m, INTERP_KERNEL::NormalizedCellType type, const std::vector<double>& refCoo,
+                                    const std::vector<double>& gsCoo, const std::vector<double>& wg) throw(INTERP_KERNEL::Exception);
+    void setGaussLocalizationOnCells(const MEDCouplingMesh *m, const int *begin, const int *end, const std::vector<double>& refCoo,
+                                     const std::vector<double>& gsCoo, const std::vector<double>& wg) throw(INTERP_KERNEL::Exception);
+    void clearGaussLocalizations() throw(INTERP_KERNEL::Exception);
+    MEDCouplingGaussLocalization& getGaussLocalization(int locId) throw(INTERP_KERNEL::Exception);
+    int getNbOfGaussLocalization() const throw(INTERP_KERNEL::Exception);
+    int getGaussLocalizationIdOfOneCell(int cellId) const throw(INTERP_KERNEL::Exception);
+    int getGaussLocalizationIdOfOneType(INTERP_KERNEL::NormalizedCellType type) const throw(INTERP_KERNEL::Exception);
+    void getCellIdsHavingGaussLocalization(int locId, std::vector<int>& cellIds) const throw(INTERP_KERNEL::Exception);
+    const MEDCouplingGaussLocalization& getGaussLocalization(int locId) const throw(INTERP_KERNEL::Exception);
+  protected:
+    MEDCouplingFieldDiscretizationGauss(const MEDCouplingFieldDiscretizationGauss& other);
+    void zipGaussLocalizations();
+    int getOffsetOfCell(int cellId) const throw(INTERP_KERNEL::Exception);
+    void checkLocalizationId(int locId) const throw(INTERP_KERNEL::Exception);
+  public:
+    static const char REPR[];
+    static const TypeOfField TYPE;
+  private:
+    std::vector<MEDCouplingGaussLocalization> _loc;
+  };
+
+  /*!
+   * Gauss with points of values located on nodes of element. This is a specialization of MEDCouplingFieldDiscretizationGauss.
+   */
+  class MEDCOUPLING_EXPORT MEDCouplingFieldDiscretizationGaussNE : public MEDCouplingFieldDiscretization
+  {
+  public:
+    MEDCouplingFieldDiscretizationGaussNE();
+    TypeOfField getEnum() const;
+    MEDCouplingFieldDiscretization *clone() const;
+    const char *getStringRepr() const;
+    bool isEqual(const MEDCouplingFieldDiscretization *other, double eps) const;
     int getNumberOfTuples(const MEDCouplingMesh *mesh) const;
+    void renumberArraysForCell(const MEDCouplingMesh *mesh, const std::vector<DataArrayDouble *>& arrays,
+                               const int *old2NewBg, bool check) throw(INTERP_KERNEL::Exception);
     DataArrayDouble *getLocalizationOfDiscValues(const MEDCouplingMesh *mesh) const;
+    void computeMeshRestrictionFromTupleIds(const MEDCouplingMesh *mesh, const int *partBg, const int *partEnd,
+                                            DataArrayInt *&cellRest);
     void checkCompatibilityWithNature(NatureOfField nat) const throw(INTERP_KERNEL::Exception);
+    double getIJK(const MEDCouplingMesh *mesh, const DataArrayDouble *da, int cellId, int nodeIdInCell, int compoId) const throw(INTERP_KERNEL::Exception);
     void checkCoherencyBetween(const MEDCouplingMesh *mesh, const DataArrayDouble *da) const throw(INTERP_KERNEL::Exception);
     MEDCouplingFieldDouble *getWeightingField(const MEDCouplingMesh *mesh, bool isAbs) const;
     void getValueOn(const DataArrayDouble *arr, const MEDCouplingMesh *mesh, const double *loc, double *res) const;
     void getValueOnPos(const DataArrayDouble *arr, const MEDCouplingMesh *mesh, int i, int j, int k, double *res) const;
-    MEDCouplingMesh *buildSubMeshData(const int *start, const int *end, const MEDCouplingMesh *mesh, DataArrayInt *&di) const;
-    void renumberValuesOnNodes(const DataArrayInt *old2New, DataArrayDouble *arr) const;
-    static DataArrayInt *invertArrayO2N2N2O(const MEDCouplingMesh *mesh, const DataArrayInt *di);
+    MEDCouplingMesh *buildSubMeshData(const MEDCouplingMesh *mesh, const int *start, const int *end, DataArrayInt *&di) const;
+    void renumberValuesOnNodes(const int *old2New, DataArrayDouble *arr) const;
+  protected:
+    MEDCouplingFieldDiscretizationGaussNE(const MEDCouplingFieldDiscretizationGaussNE& other);
   public:
     static const char REPR[];
     static const TypeOfField TYPE;
index fcbfd84f72727e9e350441b6d33021a5a2eb9e75..81758deda1e15ded35b630cb610738ee6e946b54 100644 (file)
 #include "MEDCouplingPointSet.hxx"
 #include "MEDCouplingTimeDiscretization.hxx"
 #include "MEDCouplingFieldDiscretization.hxx"
+#include "MEDCouplingAutoRefCountObjectPtr.hxx"
+#include "MEDCouplingNatureOfField.hxx"
 
 #include <sstream>
+#include <limits>
 #include <functional>
 
 using namespace ParaMEDMEM;
@@ -37,16 +40,86 @@ MEDCouplingFieldDouble *MEDCouplingFieldDouble::clone(bool recDeepCpy) const
   return new MEDCouplingFieldDouble(*this,recDeepCpy);
 }
 
+MEDCouplingFieldDouble *MEDCouplingFieldDouble::cloneWithMesh(bool recDeepCpy) const
+{
+  MEDCouplingFieldDouble *ret=clone(recDeepCpy);
+  if(_mesh)
+    {
+      MEDCouplingMesh *mCpy=_mesh->deepCpy();
+      ret->setMesh(mCpy);
+      mCpy->decrRef();
+    }
+  return ret;
+}
+
 MEDCouplingFieldDouble *MEDCouplingFieldDouble::buildNewTimeReprFromThis(TypeOfTimeDiscretization td, bool deepCpy) const
 {
   MEDCouplingTimeDiscretization *tdo=_time_discr->buildNewTimeReprFromThis(_time_discr,td,deepCpy);
-  MEDCouplingFieldDouble *ret=new MEDCouplingFieldDouble(getNature(),tdo,getTypeOfField());
+  MEDCouplingFieldDouble *ret=new MEDCouplingFieldDouble(getNature(),tdo,_type->clone());
   ret->setMesh(getMesh());
   ret->setName(getName());
   ret->setDescription(getDescription());
   return ret;
 }
 
+/*!
+ * Copy tiny info (component names, name, description) but warning the underlying mesh is not renamed (for safety reason).
+ */
+void MEDCouplingFieldDouble::copyTinyStringsFrom(const MEDCouplingFieldDouble *other) throw(INTERP_KERNEL::Exception)
+{
+  if(other)
+    {
+      setName(other->_name.c_str());
+      setDescription(other->_desc.c_str());
+      _time_discr->copyTinyStringsFrom(*other->_time_discr);
+    }
+}
+
+std::string MEDCouplingFieldDouble::simpleRepr() const
+{
+  std::ostringstream ret;
+  ret << "FieldDouble with name : \"" << getName() << "\"\n";
+  ret << "Description of field is : \"" << getDescription() << "\"\n";
+  ret << "FieldDouble space discretization is : " << _type->getStringRepr() << "\n";
+  ret << "FieldDouble time discretization is : " << _time_discr->getStringRepr() << "\n";
+  ret << "FieldDouble nature of field is : " << MEDCouplingNatureOfField::getRepr(_nature) << "\n";
+  if(getArray())
+    ret << "FieldDouble default array has " << getArray()->getNumberOfComponents() << " components and " << getArray()->getNumberOfTuples() << " tuples.\n";
+  if(_mesh)
+    ret << "Mesh support information :\n__________________________\n" << _mesh->simpleRepr();
+  else
+    ret << "Mesh support information : No mesh set !\n";
+  return ret.str();
+}
+
+std::string MEDCouplingFieldDouble::advancedRepr() const
+{
+  std::ostringstream ret;
+  ret << "FieldDouble with name : \"" << getName() << "\"\n";
+  ret << "Description of field is : \"" << getDescription() << "\"\n";
+  ret << "FieldDouble space discretization is : " << _type->getStringRepr() << "\n";
+  ret << "FieldDouble time discretization is : " << _time_discr->getStringRepr() << "\n";
+  if(getArray())
+    ret << "FieldDouble default array has " << getArray()->getNumberOfComponents() << " components and " << getArray()->getNumberOfTuples() << " tuples.\n";
+  if(_mesh)
+    ret << "Mesh support information :\n__________________________\n" << _mesh->simpleRepr();
+  else
+    ret << "Mesh support information : No mesh set !\n";
+  std::vector<DataArrayDouble *> arrays;
+  _time_discr->getArrays(arrays);
+  int arrayId=0;
+  for(std::vector<DataArrayDouble *>::const_iterator iter=arrays.begin();iter!=arrays.end();iter++,arrayId++)
+    {
+      ret << "Array #" << arrayId << " :\n__________\n";
+      if(*iter)
+        (*iter)->reprWithoutNameStream(ret);
+      else
+        ret << "Array empty !";
+      ret << "\n";
+    }
+  return ret.str();
+}
+
 bool MEDCouplingFieldDouble::isEqual(const MEDCouplingField *other, double meshPrec, double valsPrec) const
 {
   const MEDCouplingFieldDouble *otherC=dynamic_cast<const MEDCouplingFieldDouble *>(other);
@@ -61,9 +134,28 @@ bool MEDCouplingFieldDouble::isEqual(const MEDCouplingField *other, double meshP
   return true;
 }
 
-bool MEDCouplingFieldDouble::areCompatible(const MEDCouplingField *other) const
+bool MEDCouplingFieldDouble::isEqualWithoutConsideringStr(const MEDCouplingField *other, double meshPrec, double valsPrec) const
 {
-  if(!MEDCouplingField::areCompatible(other))
+  const MEDCouplingFieldDouble *otherC=dynamic_cast<const MEDCouplingFieldDouble *>(other);
+  if(!otherC)
+    return false;
+  if(_nature!=otherC->_nature)
+    return false;
+  if(!MEDCouplingField::isEqualWithoutConsideringStr(other,meshPrec,valsPrec))
+    return false;
+  if(!_time_discr->isEqualWithoutConsideringStr(otherC->_time_discr,valsPrec))
+    return false;
+  return true;
+}
+
+/*!
+ * This method states if 'this' and 'other' are compatibles each other before performing any treatment.
+ * This method is good for methods like : mergeFields.
+ * This method is not very demanding compared to areStrictlyCompatible that is better for operation on fields.
+ */
+bool MEDCouplingFieldDouble::areCompatibleForMerge(const MEDCouplingField *other) const
+{
+  if(!MEDCouplingField::areCompatibleForMerge(other))
     return false;
   const MEDCouplingFieldDouble *otherC=dynamic_cast<const MEDCouplingFieldDouble *>(other);
   if(!otherC)
@@ -75,20 +167,166 @@ bool MEDCouplingFieldDouble::areCompatible(const MEDCouplingField *other) const
   return true;
 }
 
+/*!
+ * This method is more strict than MEDCouplingField::areCompatibleForMerge method.
+ * This method is used for operation on fields to operate a first check before attempting operation.
+ */
+bool MEDCouplingFieldDouble::areStrictlyCompatible(const MEDCouplingField *other) const
+{
+  if(!MEDCouplingField::areStrictlyCompatible(other))
+    return false;
+  const MEDCouplingFieldDouble *otherC=dynamic_cast<const MEDCouplingFieldDouble *>(other);
+  if(!otherC)
+    return false;
+  if(_nature!=otherC->_nature)
+    return false;
+  if(!_time_discr->areStrictlyCompatible(otherC->_time_discr))
+    return false;
+  return true;
+}
+
+/*!
+ * Method with same principle than MEDCouplingFieldDouble::areStrictlyCompatible method except that
+ * number of components between 'this' and 'other' can be different here (for operator*).
+ */
 bool MEDCouplingFieldDouble::areCompatibleForMul(const MEDCouplingField *other) const
 {
-  if(!MEDCouplingField::areCompatible(other))
+  if(!MEDCouplingField::areStrictlyCompatible(other))
     return false;
   const MEDCouplingFieldDouble *otherC=dynamic_cast<const MEDCouplingFieldDouble *>(other);
   if(!otherC)
     return false;
   if(_nature!=otherC->_nature)
     return false;
-  if(!_time_discr->areCompatibleForMul(otherC->_time_discr))
+  if(!_time_discr->areStrictlyCompatibleForMul(otherC->_time_discr))
     return false;
   return true;
 }
 
+/*!
+ * This method performs a clone of mesh and a renumbering of underlying cells of it. The number of cells remains the same.
+ * The values of field are impacted in consequence to have the same geometrical field.
+ */
+void MEDCouplingFieldDouble::renumberCells(const int *old2NewBg, bool check) throw(INTERP_KERNEL::Exception)
+{
+  renumberCellsWithoutMesh(old2NewBg,check);
+  MEDCouplingAutoRefCountObjectPtr<MEDCouplingMesh> m=_mesh->deepCpy();
+  m->renumberCells(old2NewBg,check);
+  setMesh(m);
+  updateTime();
+}
+
+/*!
+ * \b WARNING : use this method with lot of care !
+ * This method performs half job of MEDCouplingFieldDouble::renumberCells. That is to say no permutation of cells is done on underlying mesh.
+ * That is to say, the field content is changed by this method. The reason of this method is only for multi-field instances lying on the same mesh to
+ * avoid a systematic duplication and renumbering of _mesh attribute.
+ */
+void MEDCouplingFieldDouble::renumberCellsWithoutMesh(const int *old2NewBg, bool check) throw(INTERP_KERNEL::Exception)
+{
+   if(!_mesh)
+    throw INTERP_KERNEL::Exception("Expecting a defined mesh to be able to operate a renumbering !");
+  //
+  _type->renumberCells(old2NewBg,check);
+  std::vector<DataArrayDouble *> arrays;
+  _time_discr->getArrays(arrays);
+  _type->renumberArraysForCell(_mesh,arrays,old2NewBg,check);
+  //
+  updateTime();
+}
+
+/*!
+ * This method performs a clone of mesh and a renumbering of underlying nodes of it. The number of nodes remains not compulsory the same as renumberCells method.
+ * The values of field are impacted in consequence to have the same geometrical field.
+ */
+void MEDCouplingFieldDouble::renumberNodes(const int *old2NewBg) throw(INTERP_KERNEL::Exception)
+{
+  const MEDCouplingPointSet *meshC=dynamic_cast<const MEDCouplingPointSet *>(_mesh);
+  if(!meshC)
+    throw INTERP_KERNEL::Exception("Invalid mesh to apply renumberNodes on it !");
+  int nbOfNodes=meshC->getNumberOfNodes();
+  MEDCouplingAutoRefCountObjectPtr<MEDCouplingPointSet> meshC2((MEDCouplingPointSet *)meshC->deepCpy());
+  renumberNodesWithoutMesh(old2NewBg);
+  meshC2->renumberNodes(old2NewBg,*std::max_element(old2NewBg,old2NewBg+nbOfNodes)+1);
+  setMesh(meshC2);
+}
+
+/*!
+ * \b WARNING : use this method with lot of care !
+ * This method performs half job of MEDCouplingFieldDouble::renumberNodes. That is to say no permutation of cells is done on underlying mesh.
+ * That is to say, the field content is changed by this method.
+ */
+void MEDCouplingFieldDouble::renumberNodesWithoutMesh(const int *old2NewBg) throw(INTERP_KERNEL::Exception)
+{
+  std::vector<DataArrayDouble *> arrays;
+  _time_discr->getArrays(arrays);
+  for(std::vector<DataArrayDouble *>::const_iterator iter=arrays.begin();iter!=arrays.end();iter++)
+    _type->renumberValuesOnNodes(old2NewBg,*iter);
+}
+
+/*!
+ * This method makes the assumption that the default array is set. If not an exception will be thrown.
+ * This method is usable only if the default array has exactly one component. If not an exception will be thrown too.
+ * This method returns all tuples ids that fit the range [vmin,vmax].
+ * The caller has the responsability of the returned DataArrayInt.
+ */
+DataArrayInt *MEDCouplingFieldDouble::getIdsInRange(double vmin, double vmax) const throw(INTERP_KERNEL::Exception)
+{
+  if(getArray()==0)
+    throw INTERP_KERNEL::Exception("MEDCouplingFieldDouble::getIdsInRange : no default array set !");
+  return getArray()->getIdsInRange(vmin,vmax);
+}
+
+/*!
+ * Builds a newly created field, that the caller will have the responsability.
+ * This method makes the assumption that the field is correctly defined when this method is called, no check of this will be done.
+ * This method returns a restriction of 'this' so that only tuples id specified in 'part' will be contained in returned field. 
+ */
+MEDCouplingFieldDouble *MEDCouplingFieldDouble::buildSubPart(const DataArrayInt *part) const throw(INTERP_KERNEL::Exception)
+{
+  if(part==0)
+    throw INTERP_KERNEL::Exception("MEDCouplingFieldDouble::buildSubPart : not empty array must be passed to this method !");
+  const int *start=part->getConstPointer();
+  const int *end=start+part->getNbOfElems();
+  return buildSubPart(start,end);
+}
+
+/*!
+ * Builds a newly created field, that the caller will have the responsability.
+ * This method makes the assumption that the field is correctly defined when this method is called, no check of this will be done.
+ * This method returns a restriction of 'this' so that only tuples id specified in ['partBg';'partEnd') will be contained in returned field. 
+ */
+MEDCouplingFieldDouble *MEDCouplingFieldDouble::buildSubPart(const int *partBg, const int *partEnd) const throw(INTERP_KERNEL::Exception)
+{
+  DataArrayInt *cellRest;
+  _type->computeMeshRestrictionFromTupleIds(_mesh,partBg,partEnd,cellRest);
+  DataArrayInt *arrSelect;
+  MEDCouplingMesh *m=_type->buildSubMeshData(_mesh,cellRest->getConstPointer(),cellRest->getConstPointer()+cellRest->getNbOfElems(),arrSelect);
+  if(cellRest)
+    cellRest->decrRef();
+  MEDCouplingFieldDouble *ret=clone(false);//quick shallow copy.
+  ret->setMesh(m);
+  m->decrRef();
+  std::vector<DataArrayDouble *> arrays;
+  _time_discr->getArrays(arrays);
+  std::vector<DataArrayDouble *> arrs;
+  const int *arrSelBg=arrSelect->getConstPointer();
+  const int *arrSelEnd=arrSelBg+arrSelect->getNbOfElems();
+  for(std::vector<DataArrayDouble *>::const_iterator iter=arrays.begin();iter!=arrays.end();iter++)
+    {
+      DataArrayDouble *arr=0;
+      if(*iter)
+        arr=(*iter)->selectByTupleId(arrSelBg,arrSelEnd);
+      arrs.push_back(arr);
+    }
+  ret->_time_discr->setArrays(arrs,0);
+  for(std::vector<DataArrayDouble *>::const_iterator iter=arrs.begin();iter!=arrs.end();iter++)
+    if(*iter)
+      (*iter)->decrRef();
+  arrSelect->decrRef();
+  return ret;
+}
+
 TypeOfTimeDiscretization MEDCouplingFieldDouble::getTimeDiscretization() const
 {
   return _time_discr->getEnum();
@@ -104,8 +342,8 @@ MEDCouplingFieldDouble::MEDCouplingFieldDouble(const MEDCouplingFieldDouble& oth
 {
 }
 
-MEDCouplingFieldDouble::MEDCouplingFieldDouble(NatureOfField n, MEDCouplingTimeDiscretization *td, TypeOfField type):MEDCouplingField(type),
-                                                                                                                     _nature(n),_time_discr(td)
+MEDCouplingFieldDouble::MEDCouplingFieldDouble(NatureOfField n, MEDCouplingTimeDiscretization *td, MEDCouplingFieldDiscretization *type):MEDCouplingField(type),
+                                                                                                                                         _nature(n),_time_discr(td)
 {
 }
 
@@ -118,37 +356,195 @@ void MEDCouplingFieldDouble::checkCoherency() const throw(INTERP_KERNEL::Excepti
 {
   if(!_mesh)
     throw INTERP_KERNEL::Exception("Field invalid because no mesh specified !");
-  if(!getArray())
-    throw INTERP_KERNEL::Exception("Field invalid because no values set !");
+  _time_discr->checkCoherency();
   _type->checkCoherencyBetween(_mesh,getArray());
 }
 
 /*!
- * Returns the accumulation (the sum) of comId_th component of each tuples of default array.
+ * Returns the accumulation (the sum) of comId_th component of each tuples of \b default and \b only \b default array.
  */
 double MEDCouplingFieldDouble::accumulate(int compId) const
 {
-  const double *ptr=getArray()->getConstPointer();
-  int nbTuple=getArray()->getNumberOfTuples();
+  if(getArray()==0)
+    throw INTERP_KERNEL::Exception("MEDCouplingFieldDouble::accumulate : no default array defined !");
+  return getArray()->accumulate(compId);
+}
+
+/*!
+ * Returns the accumulation (the sum) of all tuples of \b default and \b only default array.
+ * The res is expected to be of size getNumberOfComponents().
+ */
+void MEDCouplingFieldDouble::accumulate(double *res) const
+{
+  if(getArray()==0)
+    throw INTERP_KERNEL::Exception("MEDCouplingFieldDouble::accumulate : no default array defined !");
+  getArray()->accumulate(res);
+}
+
+/*!
+ * This method returns the max value in 'this'. 'This' is expected to be a field with exactly \b one component. If not an exception will be thrown.
+ * To getMaxValue on vector field applyFunc is needed before. This method looks only on all arrays stored in 'this->_time_discr'.
+ * If no arrays exists, an exception will be thrown.
+ */
+double MEDCouplingFieldDouble::getMaxValue() const throw(INTERP_KERNEL::Exception)
+{
+  std::vector<DataArrayDouble *> arrays;
+  _time_discr->getArrays(arrays);
+  double ret=-std::numeric_limits<double>::max();
+  bool isExistingArr=false;
+  for(std::vector<DataArrayDouble *>::const_iterator iter=arrays.begin();iter!=arrays.end();iter++)
+    {
+      if(*iter)
+        {
+          isExistingArr=true;
+          int loc;
+          ret=std::max(ret,(*iter)->getMaxValue(loc));
+        }
+    }
+  if(!isExistingArr)
+    throw INTERP_KERNEL::Exception("getMaxValue : No arrays defined !");
+  return ret;
+}
+
+/*!
+ * This method returns the min value in 'this'. 'This' is expected to be a field with exactly \b one component. If not an exception will be thrown.
+ * To getMinValue on vector field applyFunc is needed before. This method looks only on all arrays stored in 'this->_time_discr'.
+ * If no arrays exists, an exception will be thrown.
+ */
+double MEDCouplingFieldDouble::getMinValue() const throw(INTERP_KERNEL::Exception)
+{
+  std::vector<DataArrayDouble *> arrays;
+  _time_discr->getArrays(arrays);
+  double ret=std::numeric_limits<double>::max();
+  bool isExistingArr=false;
+  for(std::vector<DataArrayDouble *>::const_iterator iter=arrays.begin();iter!=arrays.end();iter++)
+    {
+      if(*iter)
+        {
+          isExistingArr=true;
+          int loc;
+          ret=std::min(ret,(*iter)->getMinValue(loc));
+        }
+    }
+  if(!isExistingArr)
+    throw INTERP_KERNEL::Exception("getMinValue : No arrays defined !");
+  return ret;
+}
+
+/*!
+ * This method returns the average value in 'this'. 'This' is expected to be a field with exactly \b one component. If not an exception will be thrown.
+ * To getAverageValue on vector field applyFunc is needed before. This method looks only \b default array \b and \b only \b default.
+ * If default array does not exist, an exception will be thrown.
+ */
+double MEDCouplingFieldDouble::getAverageValue() const throw(INTERP_KERNEL::Exception)
+{
+  if(getArray()==0)
+    throw INTERP_KERNEL::Exception("MEDCouplingFieldDouble::getAverageValue : no default array defined !");
+  return getArray()->getAverageValue();
+}
+
+/*!
+ * This method returns the average value in 'this' weighted by ParaMEDMEM::MEDCouplingField::buildWeightingField.
+ * 'This' is expected to be a field with exactly \b one component. If not an exception will be thrown.
+ * To getAverageValue on vector field applyFunc is needed before. This method looks only \b default array \b and \b only \b default.
+ * If default array does not exist, an exception will be thrown.
+ */
+double MEDCouplingFieldDouble::getWeightedAverageValue() const throw(INTERP_KERNEL::Exception)
+{
+  if(getArray()==0)
+    throw INTERP_KERNEL::Exception("MEDCouplingFieldDouble::getWeightedAverageValue : no default array defined !");
+  MEDCouplingFieldDouble *w=buildWeightingField(true);
+  double deno=w->getArray()->accumulate(0);
+  w->getArray()->multiplyEqual(getArray());
+  double res=w->getArray()->accumulate(0);
+  w->decrRef();
+  return res/deno;
+}
+
+/*!
+ * Returns the normL1 of current field on compId component :
+ * \f[
+ * \frac{\sum_{0 \leq i < nbOfEntity}|val[i]*Vol[i]|}{\sum_{0 \leq i < nbOfEntity}|Vol[i]|}
+ * \f]
+ * If compId>=nbOfComponent an exception is thrown.
+ */
+double MEDCouplingFieldDouble::normL1(int compId) const throw(INTERP_KERNEL::Exception)
+{
+  if(!_mesh)
+    throw INTERP_KERNEL::Exception("No mesh underlying this field to perform normL1");
   int nbComps=getArray()->getNumberOfComponents();
-  double ret=0.;
-  for(int i=0;i<nbTuple;i++)
-    ret+=ptr[i*nbComps+compId];
+  if(compId>=nbComps)
+    throw INTERP_KERNEL::Exception("Invalid compId specified : No such nb of components !");
+  double *res=new double[nbComps];
+  try
+    {
+      _type->normL1(_mesh,getArray(),res);
+    }
+  catch(INTERP_KERNEL::Exception& e)
+    {
+      delete [] res;
+      throw e;
+    }
+  double ret=res[compId];
+  delete [] res;
   return ret;
 }
 
 /*!
- * Returns the accumulation (the sum) of all tuples of default array.
+ * Returns the normL1 of current field on each components :
+ * \f[
+ * \frac{\sum_{0 \leq i < nbOfEntity}|val[i]*Vol[i]|}{\sum_{0 \leq i < nbOfEntity}|Vol[i]|}
+ * \f]
  * The res is expected to be of size getNumberOfComponents().
  */
-void MEDCouplingFieldDouble::accumulate(double *res) const
+void MEDCouplingFieldDouble::normL1(double *res) const throw(INTERP_KERNEL::Exception)
+{
+  if(!_mesh)
+    throw INTERP_KERNEL::Exception("No mesh underlying this field to perform normL1");
+  _type->normL1(_mesh,getArray(),res);
+}
+
+/*!
+ * Returns the normL2 of current field on compId component :
+ * \f[
+ * \sqrt{\frac{\sum_{0 \leq i < nbOfEntity}|val[i]^{2}*Vol[i]|}{\sum_{0 \leq i < nbOfEntity}|Vol[i]|}}
+ * \f]
+ * If compId>=nbOfComponent an exception is thrown.
+ */
+double MEDCouplingFieldDouble::normL2(int compId) const throw(INTERP_KERNEL::Exception)
 {
-  const double *ptr=getArray()->getConstPointer();
-  int nbTuple=getArray()->getNumberOfTuples();
+  if(!_mesh)
+    throw INTERP_KERNEL::Exception("No mesh underlying this field to perform normL2");
   int nbComps=getArray()->getNumberOfComponents();
-  std::fill(res,res+nbComps,0.);
-  for(int i=0;i<nbTuple;i++)
-    std::transform(ptr+i*nbComps,ptr+(i+1)*nbComps,res,res,std::plus<double>());
+  if(compId>=nbComps)
+    throw INTERP_KERNEL::Exception("Invalid compId specified : No such nb of components !");
+  double *res=new double[nbComps];
+  try
+    {
+      _type->normL2(_mesh,getArray(),res);
+    }
+  catch(INTERP_KERNEL::Exception& e)
+    {
+      delete [] res;
+      throw e;
+    }
+  double ret=res[compId];
+  delete [] res;
+  return ret;
+}
+
+/*!
+ * Returns the normL2 of current field on each components :
+ * \f[
+ * \sqrt{\frac{\sum_{0 \leq i < nbOfEntity}|val[i]^{2}*Vol[i]|}{\sum_{0 \leq i < nbOfEntity}|Vol[i]|}}
+ * \f]
+ * The res is expected to be of size getNumberOfComponents().
+ */
+void MEDCouplingFieldDouble::normL2(double *res) const throw(INTERP_KERNEL::Exception)
+{
+  if(!_mesh)
+    throw INTERP_KERNEL::Exception("No mesh underlying this field to perform normL2");
+  _type->normL2(_mesh,getArray(),res);
 }
 
 /*!
@@ -156,17 +552,25 @@ void MEDCouplingFieldDouble::accumulate(double *res) const
  * returns by getWeightingField relative of the _type of field of default array.
  * This method is usefull to check the conservativity of interpolation method.
  */
-double MEDCouplingFieldDouble::measureAccumulate(int compId, bool isWAbs) const
+double MEDCouplingFieldDouble::integral(int compId, bool isWAbs) const throw(INTERP_KERNEL::Exception)
 {
   if(!_mesh)
-    throw INTERP_KERNEL::Exception("No mesh underlying this field to perform measureAccumulate");
-  MEDCouplingFieldDouble *weight=_type->getWeightingField(_mesh,isWAbs);
-  const double *ptr=weight->getArray()->getConstPointer();
-  int nbOfValues=weight->getArray()->getNbOfElems();
-  double ret=0.;
-  for (int i=0; i<nbOfValues; i++)
-    ret+=getIJ(i,compId)*ptr[i];
-  weight->decrRef();
+    throw INTERP_KERNEL::Exception("No mesh underlying this field to perform integral");
+  int nbComps=getArray()->getNumberOfComponents();
+  if(compId>=nbComps)
+    throw INTERP_KERNEL::Exception("Invalid compId specified : No such nb of components !");
+  double *res=new double[nbComps];
+  try
+    {
+      _type->integral(_mesh,getArray(),isWAbs,res);
+    }
+  catch(INTERP_KERNEL::Exception& e)
+    {
+      delete [] res;
+      throw e;
+    }
+  double ret=res[compId];
+  delete [] res;
   return ret;
 }
 
@@ -175,24 +579,11 @@ double MEDCouplingFieldDouble::measureAccumulate(int compId, bool isWAbs) const
  * returns by getWeightingField relative of the _type of field of default array.
  * This method is usefull to check the conservativity of interpolation method.
  */
-void MEDCouplingFieldDouble::measureAccumulate(bool isWAbs, double *res) const
+void MEDCouplingFieldDouble::integral(bool isWAbs, double *res) const throw(INTERP_KERNEL::Exception)
 {
   if(!_mesh)
-    throw INTERP_KERNEL::Exception("No mesh underlying this field to perform measureAccumulate2");
-  MEDCouplingFieldDouble *weight=_type->getWeightingField(_mesh,isWAbs);
-  const double *ptr=weight->getArray()->getConstPointer();
-  int nbOfValues=weight->getArray()->getNbOfElems();
-  int nbComps=getArray()->getNumberOfComponents();
-  const double *vals=getArray()->getConstPointer();
-  std::fill(res,res+nbComps,0.);
-  double *tmp=new double[nbComps];
-  for (int i=0; i<nbOfValues; i++)
-    {
-      std::transform(vals+i*nbComps,vals+(i+1)*nbComps,tmp,std::bind2nd(std::multiplies<double>(),ptr[i]));
-      std::transform(tmp,tmp+nbComps,res,res,std::plus<double>());
-    }
-  weight->decrRef();
-  delete [] tmp;
+    throw INTERP_KERNEL::Exception("No mesh underlying this field to perform integral2");
+  _type->integral(_mesh,getArray(),isWAbs,res);
 }
 
 /*!
@@ -271,11 +662,40 @@ void MEDCouplingFieldDouble::applyFunc(const char *func)
   _time_discr->applyFunc(func);
 }
 
-int MEDCouplingFieldDouble::getNumberOfComponents() const
+/*!
+ * Applyies the function specified by the string repr 'func' on each tuples on all arrays contained in _time_discr.
+ * The field will contain exactly the same number of components after the call.
+ * Use is not warranted and can cause SIGSEGV !
+ */
+void MEDCouplingFieldDouble::applyFuncFast32(const char *func) throw(INTERP_KERNEL::Exception)
 {
+  _time_discr->applyFuncFast32(func);
+}
+
+void MEDCouplingFieldDouble::applyFuncFast64(const char *func) throw(INTERP_KERNEL::Exception)
+{
+  _time_discr->applyFuncFast64(func);
+}
+
+/*!
+ * This method makes the assumption that the default array has been set before.
+ * If not an exception will be sent.
+ * If default array set, the number of components will be sent.
+ */
+int MEDCouplingFieldDouble::getNumberOfComponents() const throw(INTERP_KERNEL::Exception)
+{
+  if(getArray()==0)
+    throw INTERP_KERNEL::Exception("MEDCouplingFieldDouble::getNumberOfComponents : No array specified !");
   return getArray()->getNumberOfComponents();
 }
 
+/*!
+ * This method makes the assumption that _mesh has be set before the call of this method and description of gauss
+ * localizations in case of Gauss field. If not an exception will sent.
+ * \b Contrary to MEDCouplingFieldDouble::getNumberOfComponents and MEDCouplingFieldDouble::getNumberOfValues is
+ * \b not aware of the presence of the default array.
+ * \b WARNING \b no coherency check is done here. MEDCouplingFieldDouble::checkCoherency method should be called to check that !
+ */
 int MEDCouplingFieldDouble::getNumberOfTuples() const throw(INTERP_KERNEL::Exception)
 {
   if(!_mesh)
@@ -283,6 +703,18 @@ int MEDCouplingFieldDouble::getNumberOfTuples() const throw(INTERP_KERNEL::Excep
   return _type->getNumberOfTuples(_mesh);
 }
 
+/*!
+ * This method makes the assumption that the default array has been set before.
+ * If not an exception will be sent.
+ * If default array set, the number of values present in the default array will be sent.
+ */
+int MEDCouplingFieldDouble::getNumberOfValues() const throw(INTERP_KERNEL::Exception)
+{
+  if(getArray()==0)
+    throw INTERP_KERNEL::Exception("MEDCouplingFieldDouble::getNumberOfValues : No array specified !");
+  return getArray()->getNbOfElems();
+}
+
 void MEDCouplingFieldDouble::updateTime()
 {
   MEDCouplingField::updateTime();
@@ -295,11 +727,21 @@ void MEDCouplingFieldDouble::setNature(NatureOfField nat) throw(INTERP_KERNEL::E
   _nature=nat;
 }
 
+double MEDCouplingFieldDouble::getIJK(int cellId, int nodeIdInCell, int compoId) const
+{
+  return _type->getIJK(_mesh,getArray(),cellId,nodeIdInCell,compoId);
+}
+
 void MEDCouplingFieldDouble::setArray(DataArrayDouble *array)
 {
   _time_discr->setArray(array,this);
 }
 
+void MEDCouplingFieldDouble::setEndArray(DataArrayDouble *array)
+{
+  _time_discr->setEndArray(array,this);
+}
+
 void MEDCouplingFieldDouble::getTinySerializationStrInformation(std::vector<std::string>& tinyInfo) const
 {
   tinyInfo.clear();
@@ -320,6 +762,10 @@ void MEDCouplingFieldDouble::getTinySerializationIntInformation(std::vector<int>
   tinyInfo.push_back((int)_time_discr->getEnum());
   tinyInfo.push_back((int)_nature);
   _time_discr->getTinySerializationIntInformation(tinyInfo);
+  std::vector<int> tinyInfo2;
+  _type->getTinySerializationIntInformation(tinyInfo2);
+  tinyInfo.insert(tinyInfo.end(),tinyInfo2.begin(),tinyInfo2.end());
+  tinyInfo.push_back(tinyInfo2.size());
 }
 
 /*!
@@ -330,25 +776,45 @@ void MEDCouplingFieldDouble::getTinySerializationDbleInformation(std::vector<dou
 {
   tinyInfo.clear();
   _time_discr->getTinySerializationDbleInformation(tinyInfo);
+  std::vector<double> tinyInfo2;
+  _type->getTinySerializationDbleInformation(tinyInfo2);
+  tinyInfo.insert(tinyInfo.end(),tinyInfo2.begin(),tinyInfo2.end());
+  tinyInfo.push_back(tinyInfo2.size());
 }
 
 /*!
  * This method has to be called to the new instance filled by CORBA, MPI, File...
  * @param tinyInfoI is the value retrieves from distant result of getTinySerializationIntInformation on source instance to be copied.
+ * @param dataInt out parameter. If not null the pointer is already owned by 'this' after the call of this method. In this case no decrRef must be applied.
  * @param arrays out parameter is a vector resized to the right size. The pointers in the vector is already owned by 'this' after the call of this method.
  *               No decrRef must be applied to every instances in returned vector.
  */
-void MEDCouplingFieldDouble::resizeForUnserialization(const std::vector<int>& tinyInfoI, std::vector<DataArrayDouble *>& arrays)
+void MEDCouplingFieldDouble::resizeForUnserialization(const std::vector<int>& tinyInfoI, DataArrayInt *&dataInt, std::vector<DataArrayDouble *>& arrays)
 {
-  std::vector<int> tinyInfoI2(tinyInfoI.begin()+3,tinyInfoI.end());
+  dataInt=0;
+  std::vector<int> tinyInfoITmp(tinyInfoI);
+  int sz=tinyInfoITmp.back();
+  tinyInfoITmp.pop_back();
+  std::vector<int> tinyInfoITmp2(tinyInfoITmp.begin(),tinyInfoITmp.end()-sz);
+  std::vector<int> tinyInfoI2(tinyInfoITmp2.begin()+3,tinyInfoITmp2.end());
   _time_discr->resizeForUnserialization(tinyInfoI2,arrays);
+  std::vector<int> tinyInfoITmp3(tinyInfoITmp.end()-sz,tinyInfoITmp.end());
+  _type->resizeForUnserialization(tinyInfoITmp3,dataInt);
 }
 
 void MEDCouplingFieldDouble::finishUnserialization(const std::vector<int>& tinyInfoI, const std::vector<double>& tinyInfoD, const std::vector<std::string>& tinyInfoS)
 {
   std::vector<int> tinyInfoI2(tinyInfoI.begin()+3,tinyInfoI.end());
-  _time_discr->finishUnserialization(tinyInfoI2,tinyInfoD,tinyInfoS);
+  //
+  std::vector<double> tmp(tinyInfoD);
+  int sz=tinyInfoD.back();
+  tmp.pop_back();
+  std::vector<double> tmp1(tmp.begin(),tmp.end()-sz);
+  std::vector<double> tmp2(tmp.end()-sz,tmp.end());
+  //
+  _time_discr->finishUnserialization(tinyInfoI2,tmp1,tinyInfoS);
   _nature=(NatureOfField)tinyInfoI[2];
+  _type->finishUnserialization(tmp2);
   int nbOfElemS=tinyInfoS.size();
   _name=tinyInfoS[nbOfElemS-2];
   _desc=tinyInfoS[nbOfElemS-1];
@@ -358,48 +824,185 @@ void MEDCouplingFieldDouble::finishUnserialization(const std::vector<int>& tinyI
  * Contrary to MEDCouplingPointSet class the returned arrays are \b not the responsabilities of the caller.
  * The values returned must be consulted only in readonly mode.
  */
-void MEDCouplingFieldDouble::serialize(std::vector<DataArrayDouble *>& arrays) const
+void MEDCouplingFieldDouble::serialize(DataArrayInt *&dataInt, std::vector<DataArrayDouble *>& arrays) const
 {
   _time_discr->getArrays(arrays);
+  _type->getSerializationIntArray(dataInt);
+}
+
+/*!
+ * This method tries to to change the mesh support of 'this' following the parameter 'levOfCheck' and 'prec'.
+ * Semantic of 'levOfCheck' is explained in MEDCouplingMesh::checkGeoEquivalWith method. This method is used to perform the job.
+ * If this->_mesh is not defined or other an exeption will be throw.
+ */
+void MEDCouplingFieldDouble::changeUnderlyingMesh(const MEDCouplingMesh *other, int levOfCheck, double prec) throw(INTERP_KERNEL::Exception)
+{
+  if(_mesh==0 || other==0)
+    throw INTERP_KERNEL::Exception("MEDCouplingFieldDouble::changeUnderlyingMesh : is expected to operate on not null meshes !");
+  DataArrayInt *cellCor,*nodeCor;
+  _mesh->checkGeoEquivalWith(other,levOfCheck,prec,cellCor,nodeCor);
+  if(cellCor)
+    {
+      renumberCellsWithoutMesh(cellCor->getConstPointer(),false);
+      cellCor->decrRef();
+    }
+  if(nodeCor)
+    {
+      renumberNodesWithoutMesh(nodeCor->getConstPointer());
+      nodeCor->decrRef();
+    }
+  setMesh((MEDCouplingMesh *)other);
 }
 
 /*!
- * \b Warning ! This method potentially modifies the underlying mesh ! If the mesh is shared by other fields, these fields could be unavailable.
+ * This method is an extension of MEDCouplingFieldDouble::operator-=. It allows a user to operate a difference of 2 fields ('this' and 'f') even if they do not share same meshes.
+ * No interpolation will be done here only an analyze of two underlying mesh will be done to see if the meshes are geometrically equivalent. If yes, the eventual renumbering will be done and operator-= applyed after.
+ * This method requires that 'f' and 'this' are coherent (check coherency) and that 'f' and 'this' would be coherent for a merge.
+ * Semantic of 'levOfCheck' is explained in MEDCouplingMesh::checkGeoEquivalWith method.
  */
-bool MEDCouplingFieldDouble::mergeNodes(double eps)
+void MEDCouplingFieldDouble::substractInPlaceDM(const MEDCouplingFieldDouble *f, int levOfCheck, double prec) throw(INTERP_KERNEL::Exception)
 {
-  MEDCouplingPointSet *meshC=dynamic_cast<MEDCouplingPointSet *>((MEDCouplingMesh *)(_mesh));
+  checkCoherency();
+  f->checkCoherency();
+  if(!areCompatibleForMerge(f))
+    throw INTERP_KERNEL::Exception("MEDCouplingFieldDouble::diffWith : Fields are not compatible ; unable to apply mergeFields on them !");
+  changeUnderlyingMesh(f->getMesh(),levOfCheck,prec);
+  operator-=(*f);
+}
+
+/*!
+ * Merge nodes of underlying mesh. In case of some node will be merged the underlying mesh instance will change.
+ */
+bool MEDCouplingFieldDouble::mergeNodes(double eps) throw(INTERP_KERNEL::Exception)
+{
+  const MEDCouplingPointSet *meshC=dynamic_cast<const MEDCouplingPointSet *>(_mesh);
   if(!meshC)
     throw INTERP_KERNEL::Exception("Invalid mesh to apply mergeNodes on it !");
+  MEDCouplingAutoRefCountObjectPtr<MEDCouplingPointSet> meshC2((MEDCouplingPointSet *)meshC->deepCpy());
   bool ret;
-  DataArrayInt *arr=meshC->mergeNodes(eps,ret);
+  int ret2;
+  MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arr=meshC2->mergeNodes(eps,ret,ret2);
   if(!ret)//no nodes have been merged.
     return ret;
   std::vector<DataArrayDouble *> arrays;
   _time_discr->getArrays(arrays);
-  try
-    {
-      for(std::vector<DataArrayDouble *>::const_iterator iter=arrays.begin();iter!=arrays.end();iter++)
-        _type->renumberValuesOnNodes(arr,*iter);
-    }
-  catch(INTERP_KERNEL::Exception& e)
-    {
-      arr->decrRef();
-      throw e;
-    }
-  arr->decrRef();
+  for(std::vector<DataArrayDouble *>::const_iterator iter=arrays.begin();iter!=arrays.end();iter++)
+    _type->renumberValuesOnNodes(arr->getConstPointer(),*iter);
+  setMesh(meshC2);
   return true;
 }
 
+MEDCouplingFieldDouble *MEDCouplingFieldDouble::doublyContractedProduct() const throw(INTERP_KERNEL::Exception)
+{
+  MEDCouplingTimeDiscretization *td=_time_discr->doublyContractedProduct();
+  td->copyTinyAttrFrom(*_time_discr);
+  MEDCouplingFieldDouble *ret=new MEDCouplingFieldDouble(getNature(),td,_type->clone());
+  ret->setName("DoublyContractedProduct");
+  ret->setMesh(getMesh());
+  return ret;
+}
+
+MEDCouplingFieldDouble *MEDCouplingFieldDouble::determinant() const throw(INTERP_KERNEL::Exception)
+{
+  MEDCouplingTimeDiscretization *td=_time_discr->determinant();
+  td->copyTinyAttrFrom(*_time_discr);
+  MEDCouplingFieldDouble *ret=new MEDCouplingFieldDouble(getNature(),td,_type->clone());
+  ret->setName("Determinant");
+  ret->setMesh(getMesh());
+  return ret;
+}
+
+MEDCouplingFieldDouble *MEDCouplingFieldDouble::eigenValues() const throw(INTERP_KERNEL::Exception)
+{
+  MEDCouplingTimeDiscretization *td=_time_discr->eigenValues();
+  td->copyTinyAttrFrom(*_time_discr);
+  MEDCouplingFieldDouble *ret=new MEDCouplingFieldDouble(getNature(),td,_type->clone());
+  ret->setName("EigenValues");
+  ret->setMesh(getMesh());
+  return ret;
+}
+
+MEDCouplingFieldDouble *MEDCouplingFieldDouble::eigenVectors() const throw(INTERP_KERNEL::Exception)
+{
+  MEDCouplingTimeDiscretization *td=_time_discr->eigenVectors();
+  td->copyTinyAttrFrom(*_time_discr);
+  MEDCouplingFieldDouble *ret=new MEDCouplingFieldDouble(getNature(),td,_type->clone());
+  ret->setName("EigenVectors");
+  ret->setMesh(getMesh());
+  return ret;
+}
+
+MEDCouplingFieldDouble *MEDCouplingFieldDouble::inverse() const throw(INTERP_KERNEL::Exception)
+{
+  MEDCouplingTimeDiscretization *td=_time_discr->inverse();
+  td->copyTinyAttrFrom(*_time_discr);
+  MEDCouplingFieldDouble *ret=new MEDCouplingFieldDouble(getNature(),td,_type->clone());
+  ret->setName("Inversion");
+  ret->setMesh(getMesh());
+  return ret;
+}
+
+MEDCouplingFieldDouble *MEDCouplingFieldDouble::trace() const throw(INTERP_KERNEL::Exception)
+{
+  MEDCouplingTimeDiscretization *td=_time_discr->trace();
+  td->copyTinyAttrFrom(*_time_discr);
+  MEDCouplingFieldDouble *ret=new MEDCouplingFieldDouble(getNature(),td,_type->clone());
+  ret->setName("Trace");
+  ret->setMesh(getMesh());
+  return ret;
+}
+
+MEDCouplingFieldDouble *MEDCouplingFieldDouble::deviator() const throw(INTERP_KERNEL::Exception)
+{
+  MEDCouplingTimeDiscretization *td=_time_discr->deviator();
+  td->copyTinyAttrFrom(*_time_discr);
+  MEDCouplingFieldDouble *ret=new MEDCouplingFieldDouble(getNature(),td,_type->clone());
+  ret->setName("Trace");
+  ret->setMesh(getMesh());
+  return ret;
+}
+
+MEDCouplingFieldDouble *MEDCouplingFieldDouble::magnitude() const throw(INTERP_KERNEL::Exception)
+{
+  MEDCouplingTimeDiscretization *td=_time_discr->magnitude();
+  td->copyTinyAttrFrom(*_time_discr);
+  MEDCouplingFieldDouble *ret=new MEDCouplingFieldDouble(getNature(),td,_type->clone());
+  ret->setName("Magnitude");
+  ret->setMesh(getMesh());
+  return ret;
+}
+
+MEDCouplingFieldDouble *MEDCouplingFieldDouble::maxPerTuple() const throw(INTERP_KERNEL::Exception)
+{
+  MEDCouplingTimeDiscretization *td=_time_discr->maxPerTuple();
+  td->copyTinyAttrFrom(*_time_discr);
+  MEDCouplingFieldDouble *ret=new MEDCouplingFieldDouble(getNature(),td,_type->clone());
+  std::ostringstream oss;
+  oss << "Max_" << getName();
+  ret->setName(oss.str().c_str());
+  ret->setMesh(getMesh());
+  return ret;
+}
+
+void MEDCouplingFieldDouble::changeNbOfComponents(int newNbOfComp, double dftValue) throw(INTERP_KERNEL::Exception)
+{
+  _time_discr->changeNbOfComponents(newNbOfComp,dftValue);
+}
+
+void MEDCouplingFieldDouble::sortPerTuple(bool asc) throw(INTERP_KERNEL::Exception)
+{
+  _time_discr->sortPerTuple(asc);
+}
+
 MEDCouplingFieldDouble *MEDCouplingFieldDouble::mergeFields(const MEDCouplingFieldDouble *f1, const MEDCouplingFieldDouble *f2)
 {
-  if(!f1->areCompatible(f2))
+  if(!f1->areCompatibleForMerge(f2))
     throw INTERP_KERNEL::Exception("Fields are not compatible ; unable to apply mergeFields on them !");
   const MEDCouplingMesh *m1=f1->getMesh();
   const MEDCouplingMesh *m2=f2->getMesh();
   MEDCouplingMesh *m=m1->mergeMyselfWith(m2);
   MEDCouplingTimeDiscretization *td=f1->_time_discr->aggregate(f2->_time_discr);
-  MEDCouplingFieldDouble *ret=new MEDCouplingFieldDouble(f1->getNature(),td,f1->getTypeOfField());
+  MEDCouplingFieldDouble *ret=new MEDCouplingFieldDouble(f1->getNature(),td,f1->_type->clone());
   ret->setMesh(m);
   m->decrRef();
   ret->setName(f1->getName());
@@ -407,38 +1010,86 @@ MEDCouplingFieldDouble *MEDCouplingFieldDouble::mergeFields(const MEDCouplingFie
   return ret;
 }
 
+MEDCouplingFieldDouble *MEDCouplingFieldDouble::dotFields(const MEDCouplingFieldDouble *f1, const MEDCouplingFieldDouble *f2)
+{
+  if(!f1->areStrictlyCompatible(f2))
+    throw INTERP_KERNEL::Exception("Fields are not compatible ; unable to apply dotFields on them !");
+  MEDCouplingTimeDiscretization *td=f1->_time_discr->dot(f2->_time_discr);
+  td->copyTinyAttrFrom(*f1->_time_discr);
+  MEDCouplingFieldDouble *ret=new MEDCouplingFieldDouble(f1->getNature(),td,f1->_type->clone());
+  ret->setMesh(f1->getMesh());
+  return ret;
+}
+
+MEDCouplingFieldDouble *MEDCouplingFieldDouble::crossProductFields(const MEDCouplingFieldDouble *f1, const MEDCouplingFieldDouble *f2)
+{
+  if(!f1->areStrictlyCompatible(f2))
+    throw INTERP_KERNEL::Exception("Fields are not compatible ; unable to apply crossProductFields on them !");
+  MEDCouplingTimeDiscretization *td=f1->_time_discr->crossProduct(f2->_time_discr);
+  td->copyTinyAttrFrom(*f1->_time_discr);
+  MEDCouplingFieldDouble *ret=new MEDCouplingFieldDouble(f1->getNature(),td,f1->_type->clone());
+  ret->setMesh(f1->getMesh());
+  return ret;
+}
+
+MEDCouplingFieldDouble *MEDCouplingFieldDouble::maxFields(const MEDCouplingFieldDouble *f1, const MEDCouplingFieldDouble *f2)
+{
+  if(!f1->areStrictlyCompatible(f2))
+    throw INTERP_KERNEL::Exception("Fields are not compatible ; unable to apply maxFields on them !");
+  MEDCouplingTimeDiscretization *td=f1->_time_discr->max(f2->_time_discr);
+  td->copyTinyAttrFrom(*f1->_time_discr);
+  MEDCouplingFieldDouble *ret=new MEDCouplingFieldDouble(f1->getNature(),td,f1->_type->clone());
+  ret->setMesh(f1->getMesh());
+  return ret;
+}
+
+MEDCouplingFieldDouble *MEDCouplingFieldDouble::minFields(const MEDCouplingFieldDouble *f1, const MEDCouplingFieldDouble *f2)
+{
+  if(!f1->areStrictlyCompatible(f2))
+    throw INTERP_KERNEL::Exception("Fields are not compatible ; unable to apply minFields on them !");
+  MEDCouplingTimeDiscretization *td=f1->_time_discr->min(f2->_time_discr);
+  td->copyTinyAttrFrom(*f1->_time_discr);
+  MEDCouplingFieldDouble *ret=new MEDCouplingFieldDouble(f1->getNature(),td,f1->_type->clone());
+  ret->setMesh(f1->getMesh());
+  return ret;
+}
+
 MEDCouplingFieldDouble *MEDCouplingFieldDouble::addFields(const MEDCouplingFieldDouble *f1, const MEDCouplingFieldDouble *f2)
 {
-  if(!f1->areCompatible(f2))
+  if(!f1->areStrictlyCompatible(f2))
     throw INTERP_KERNEL::Exception("Fields are not compatible ; unable to apply addFields on them !");
   MEDCouplingTimeDiscretization *td=f1->_time_discr->add(f2->_time_discr);
-  MEDCouplingFieldDouble *ret=new MEDCouplingFieldDouble(f1->getNature(),td,f1->getTypeOfField());
+  td->copyTinyAttrFrom(*f1->_time_discr);
+  MEDCouplingFieldDouble *ret=new MEDCouplingFieldDouble(f1->getNature(),td,f1->_type->clone());
   ret->setMesh(f1->getMesh());
   return ret;
 }
 
-void MEDCouplingFieldDouble::operator+=(const MEDCouplingFieldDouble& other)
+const MEDCouplingFieldDouble &MEDCouplingFieldDouble::operator+=(const MEDCouplingFieldDouble& other)
 {
-  if(!areCompatible(&other))
+  if(!areStrictlyCompatible(&other))
     throw INTERP_KERNEL::Exception("Fields are not compatible ; unable to apply += on them !");
   _time_discr->addEqual(other._time_discr);
+  return *this;
 }
 
 MEDCouplingFieldDouble *MEDCouplingFieldDouble::substractFields(const MEDCouplingFieldDouble *f1, const MEDCouplingFieldDouble *f2)
 {
-  if(!f1->areCompatible(f2))
+  if(!f1->areStrictlyCompatible(f2))
     throw INTERP_KERNEL::Exception("Fields are not compatible ; unable to apply substractFields on them !");
   MEDCouplingTimeDiscretization *td=f1->_time_discr->substract(f2->_time_discr);
-  MEDCouplingFieldDouble *ret=new MEDCouplingFieldDouble(f1->getNature(),td,f1->getTypeOfField());
+  td->copyTinyAttrFrom(*f1->_time_discr);
+  MEDCouplingFieldDouble *ret=new MEDCouplingFieldDouble(f1->getNature(),td,f1->_type->clone());
   ret->setMesh(f1->getMesh());
   return ret;
 }
 
-void MEDCouplingFieldDouble::operator-=(const MEDCouplingFieldDouble& other)
+const MEDCouplingFieldDouble &MEDCouplingFieldDouble::operator-=(const MEDCouplingFieldDouble& other)
 {
-  if(!areCompatible(&other))
+  if(!areStrictlyCompatible(&other))
     throw INTERP_KERNEL::Exception("Fields are not compatible ; unable to apply -= on them !");
   _time_discr->substractEqual(other._time_discr);
+  return *this;
 }
 
 MEDCouplingFieldDouble *MEDCouplingFieldDouble::multiplyFields(const MEDCouplingFieldDouble *f1, const MEDCouplingFieldDouble *f2)
@@ -446,31 +1097,35 @@ MEDCouplingFieldDouble *MEDCouplingFieldDouble::multiplyFields(const MEDCoupling
   if(!f1->areCompatibleForMul(f2))
     throw INTERP_KERNEL::Exception("Fields are not compatible ; unable to apply multiplyFields on them !");
   MEDCouplingTimeDiscretization *td=f1->_time_discr->multiply(f2->_time_discr);
-  MEDCouplingFieldDouble *ret=new MEDCouplingFieldDouble(f1->getNature(),td,f1->getTypeOfField());
+  td->copyTinyAttrFrom(*f1->_time_discr);
+  MEDCouplingFieldDouble *ret=new MEDCouplingFieldDouble(f1->getNature(),td,f1->_type->clone());
   ret->setMesh(f1->getMesh());
   return ret;
 }
 
-void MEDCouplingFieldDouble::operator*=(const MEDCouplingFieldDouble& other)
+const MEDCouplingFieldDouble &MEDCouplingFieldDouble::operator*=(const MEDCouplingFieldDouble& other)
 {
   if(!areCompatibleForMul(&other))
     throw INTERP_KERNEL::Exception("Fields are not compatible ; unable to apply *= on them !");
   _time_discr->multiplyEqual(other._time_discr);
+  return *this;
 }
 
 MEDCouplingFieldDouble *MEDCouplingFieldDouble::divideFields(const MEDCouplingFieldDouble *f1, const MEDCouplingFieldDouble *f2)
 {
-  if(!f1->areCompatible(f2))
+  if(!f1->areStrictlyCompatible(f2))
     throw INTERP_KERNEL::Exception("Fields are not compatible ; unable to apply divideFields on them !");
   MEDCouplingTimeDiscretization *td=f1->_time_discr->divide(f2->_time_discr);
-  MEDCouplingFieldDouble *ret=new MEDCouplingFieldDouble(f1->getNature(),td,f1->getTypeOfField());
+  td->copyTinyAttrFrom(*f1->_time_discr);
+  MEDCouplingFieldDouble *ret=new MEDCouplingFieldDouble(f1->getNature(),td,f1->_type->clone());
   ret->setMesh(f1->getMesh());
   return ret;
 }
 
-void MEDCouplingFieldDouble::operator/=(const MEDCouplingFieldDouble& other)
+const MEDCouplingFieldDouble &MEDCouplingFieldDouble::operator/=(const MEDCouplingFieldDouble& other)
 {
-  if(!areCompatible(&other))
+  if(!areStrictlyCompatible(&other))
     throw INTERP_KERNEL::Exception("Fields are not compatible ; unable to apply /= on them !");
   _time_discr->divideEqual(other._time_discr);
+  return *this;
 }
index bffdc3e17ed743765c7a52a2ccf3ee22e8f94251..cbc0cf924e0deb3d8c6165eb6fbcba5028ffbb37 100644 (file)
@@ -32,28 +32,52 @@ namespace ParaMEDMEM
   {
   public:
     static MEDCouplingFieldDouble *New(TypeOfField type, TypeOfTimeDiscretization td=NO_TIME);
+    void copyTinyStringsFrom(const MEDCouplingFieldDouble *other) throw(INTERP_KERNEL::Exception);
+    std::string simpleRepr() const;
+    std::string advancedRepr() const;
     bool isEqual(const MEDCouplingField *other, double meshPrec, double valsPrec) const;
-    bool areCompatible(const MEDCouplingField *other) const;
+    bool isEqualWithoutConsideringStr(const MEDCouplingField *other, double meshPrec, double valsPrec) const;
+    bool areCompatibleForMerge(const MEDCouplingField *other) const;
+    bool areStrictlyCompatible(const MEDCouplingField *other) const;
     bool areCompatibleForMul(const MEDCouplingField *other) const;
+    void renumberCells(const int *old2NewBg, bool check) throw(INTERP_KERNEL::Exception);
+    void renumberCellsWithoutMesh(const int *old2NewBg, bool check) throw(INTERP_KERNEL::Exception);
+    void renumberNodes(const int *old2NewBg) throw(INTERP_KERNEL::Exception);
+    void renumberNodesWithoutMesh(const int *old2NewBg) throw(INTERP_KERNEL::Exception);
+    DataArrayInt *getIdsInRange(double vmin, double vmax) const throw(INTERP_KERNEL::Exception);
+    MEDCouplingFieldDouble *buildSubPart(const DataArrayInt *part) const throw(INTERP_KERNEL::Exception);
+    MEDCouplingFieldDouble *buildSubPart(const int *partBg, const int *partEnd) const throw(INTERP_KERNEL::Exception);
     MEDCouplingFieldDouble *clone(bool recDeepCpy) const;
+    MEDCouplingFieldDouble *cloneWithMesh(bool recDeepCpy) const;
     MEDCouplingFieldDouble *buildNewTimeReprFromThis(TypeOfTimeDiscretization td, bool deepCpy) const;
     TypeOfTimeDiscretization getTimeDiscretization() const;
     void checkCoherency() const throw(INTERP_KERNEL::Exception);
     NatureOfField getNature() const { return _nature; }
     void setNature(NatureOfField nat) throw(INTERP_KERNEL::Exception);
-    void setTime(double val, int dt, int it) { _time_discr->setTime(val,dt,it); }
-    void setStartTime(double val, int dt, int it) { _time_discr->setStartTime(val,dt,it); }
-    void setEndTime(double val, int dt, int it) { _time_discr->setEndTime(val,dt,it); }
-    double getTime(int& dt, int& it) const { return _time_discr->getTime(dt,it); }
-    double getStartTime(int& dt, int& it) const { return _time_discr->getStartTime(dt,it); }
-    double getEndTime(int& dt, int& it) const { return _time_discr->getEndTime(dt,it); }
+    void setTime(double val, int iteration, int order) { _time_discr->setTime(val,iteration,order); }
+    void setStartTime(double val, int iteration, int order) { _time_discr->setStartTime(val,iteration,order); }
+    void setEndTime(double val, int iteration, int order) { _time_discr->setEndTime(val,iteration,order); }
+    double getTime(int& iteration, int& order) const { return _time_discr->getTime(iteration,order); }
+    double getStartTime(int& iteration, int& order) const { return _time_discr->getStartTime(iteration,order); }
+    double getEndTime(int& iteration, int& order) const { return _time_discr->getEndTime(iteration,order); }
     double getIJ(int tupleId, int compoId) const { return getArray()->getIJ(tupleId,compoId); }
+    double getIJK(int cellId, int nodeIdInCell, int compoId) const;
     void setArray(DataArrayDouble *array);
+    void setEndArray(DataArrayDouble *array);
     DataArrayDouble *getArray() const { return _time_discr->getArray(); }
+    DataArrayDouble *getEndArray() const { return _time_discr->getEndArray(); }
     double accumulate(int compId) const;
     void accumulate(double *res) const;
-    double measureAccumulate(int compId, bool isWAbs) const;
-    void measureAccumulate(bool isWAbs, double *res) const;
+    double getMaxValue() const throw(INTERP_KERNEL::Exception);
+    double getMinValue() const throw(INTERP_KERNEL::Exception);
+    double getAverageValue() const throw(INTERP_KERNEL::Exception);
+    double getWeightedAverageValue() const throw(INTERP_KERNEL::Exception);
+    double normL1(int compId) const throw(INTERP_KERNEL::Exception);
+    void normL1(double *res) const throw(INTERP_KERNEL::Exception);
+    double normL2(int compId) const throw(INTERP_KERNEL::Exception);
+    void normL2(double *res) const throw(INTERP_KERNEL::Exception);
+    double integral(int compId, bool isWAbs) const throw(INTERP_KERNEL::Exception);
+    void integral(bool isWAbs, double *res) const throw(INTERP_KERNEL::Exception);
     void getValueOnPos(int i, int j, int k, double *res) const throw(INTERP_KERNEL::Exception);
     void getValueOn(const double *spaceLoc, double *res) const throw(INTERP_KERNEL::Exception);
     void getValueOn(const double *spaceLoc, double time, double *res) const throw(INTERP_KERNEL::Exception);
@@ -62,34 +86,59 @@ namespace ParaMEDMEM
     void applyFunc(int nbOfComp, FunctionToEvaluate func);
     void applyFunc(int nbOfComp, const char *func);
     void applyFunc(const char *func);
-    int getNumberOfComponents() const;
+    void applyFuncFast32(const char *func) throw(INTERP_KERNEL::Exception);
+    void applyFuncFast64(const char *func) throw(INTERP_KERNEL::Exception);
+    int getNumberOfComponents() const throw(INTERP_KERNEL::Exception);
     int getNumberOfTuples() const throw(INTERP_KERNEL::Exception);
+    int getNumberOfValues() const throw(INTERP_KERNEL::Exception);
     void updateTime();
     //
     void getTinySerializationIntInformation(std::vector<int>& tinyInfo) const;
     void getTinySerializationDbleInformation(std::vector<double>& tinyInfo) const;
     void getTinySerializationStrInformation(std::vector<std::string>& tinyInfo) const;
-    void resizeForUnserialization(const std::vector<int>& tinyInfoI, std::vector<DataArrayDouble *>& arrays);
+    void resizeForUnserialization(const std::vector<int>& tinyInfoI, DataArrayInt *&dataInt, std::vector<DataArrayDouble *>& arrays);
     void finishUnserialization(const std::vector<int>& tinyInfoI, const std::vector<double>& tinyInfoD, const std::vector<std::string>& tinyInfoS);
-    void serialize(std::vector<DataArrayDouble *>& arrays) const;
-    bool mergeNodes(double eps);
+    void serialize(DataArrayInt *&dataInt, std::vector<DataArrayDouble *>& arrays) const;
+    //
+    void changeUnderlyingMesh(const MEDCouplingMesh *other, int levOfCheck, double prec) throw(INTERP_KERNEL::Exception);
+    void substractInPlaceDM(const MEDCouplingFieldDouble *f, int levOfCheck, double prec) throw(INTERP_KERNEL::Exception);
+    bool mergeNodes(double eps) throw(INTERP_KERNEL::Exception);
+    MEDCouplingFieldDouble *doublyContractedProduct() const throw(INTERP_KERNEL::Exception);
+    MEDCouplingFieldDouble *determinant() const throw(INTERP_KERNEL::Exception);
+    MEDCouplingFieldDouble *eigenValues() const throw(INTERP_KERNEL::Exception);
+    MEDCouplingFieldDouble *eigenVectors() const throw(INTERP_KERNEL::Exception);
+    MEDCouplingFieldDouble *inverse() const throw(INTERP_KERNEL::Exception);
+    MEDCouplingFieldDouble *trace() const throw(INTERP_KERNEL::Exception);
+    MEDCouplingFieldDouble *deviator() const throw(INTERP_KERNEL::Exception);
+    MEDCouplingFieldDouble *magnitude() const throw(INTERP_KERNEL::Exception);
+    MEDCouplingFieldDouble *maxPerTuple() const throw(INTERP_KERNEL::Exception);
+    void changeNbOfComponents(int newNbOfComp, double dftValue=0.) throw(INTERP_KERNEL::Exception);
+    void sortPerTuple(bool asc) throw(INTERP_KERNEL::Exception);
     static MEDCouplingFieldDouble *mergeFields(const MEDCouplingFieldDouble *f1, const MEDCouplingFieldDouble *f2);
+    static MEDCouplingFieldDouble *dotFields(const MEDCouplingFieldDouble *f1, const MEDCouplingFieldDouble *f2);
+    MEDCouplingFieldDouble *dot(const MEDCouplingFieldDouble& other) const { return dotFields(this,&other); }
+    static MEDCouplingFieldDouble *crossProductFields(const MEDCouplingFieldDouble *f1, const MEDCouplingFieldDouble *f2);
+    MEDCouplingFieldDouble *crossProduct(const MEDCouplingFieldDouble& other) const { return crossProductFields(this,&other); }
+    static MEDCouplingFieldDouble *maxFields(const MEDCouplingFieldDouble *f1, const MEDCouplingFieldDouble *f2);
+    MEDCouplingFieldDouble *max(const MEDCouplingFieldDouble& other) const { return maxFields(this,&other); }
+    static MEDCouplingFieldDouble *minFields(const MEDCouplingFieldDouble *f1, const MEDCouplingFieldDouble *f2);
+    MEDCouplingFieldDouble *min(const MEDCouplingFieldDouble& other) const { return minFields(this,&other); }
     MEDCouplingFieldDouble *operator+(const MEDCouplingFieldDouble& other) const { return addFields(this,&other); }
-    void operator+=(const MEDCouplingFieldDouble& other);
+    const MEDCouplingFieldDouble &operator+=(const MEDCouplingFieldDouble& other);
     static MEDCouplingFieldDouble *addFields(const MEDCouplingFieldDouble *f1, const MEDCouplingFieldDouble *f2);
     MEDCouplingFieldDouble *operator-(const MEDCouplingFieldDouble& other) const { return substractFields(this,&other); }
-    void operator-=(const MEDCouplingFieldDouble& other);
+    const MEDCouplingFieldDouble &operator-=(const MEDCouplingFieldDouble& other);
     static MEDCouplingFieldDouble *substractFields(const MEDCouplingFieldDouble *f1, const MEDCouplingFieldDouble *f2);
     MEDCouplingFieldDouble *operator*(const MEDCouplingFieldDouble& other) const { return multiplyFields(this,&other); }
-    void operator*=(const MEDCouplingFieldDouble& other);
+    const MEDCouplingFieldDouble &operator*=(const MEDCouplingFieldDouble& other);
     static MEDCouplingFieldDouble *multiplyFields(const MEDCouplingFieldDouble *f1, const MEDCouplingFieldDouble *f2);
     MEDCouplingFieldDouble *operator/(const MEDCouplingFieldDouble& other) const { return divideFields(this,&other); }
-    void operator/=(const MEDCouplingFieldDouble& other);
+    const MEDCouplingFieldDouble &operator/=(const MEDCouplingFieldDouble& other);
     static MEDCouplingFieldDouble *divideFields(const MEDCouplingFieldDouble *f1, const MEDCouplingFieldDouble *f2);
   private:
     MEDCouplingFieldDouble(TypeOfField type, TypeOfTimeDiscretization td);
     MEDCouplingFieldDouble(const MEDCouplingFieldDouble& other, bool deepCpy);
-    MEDCouplingFieldDouble(NatureOfField n, MEDCouplingTimeDiscretization *td, TypeOfField type);
+    MEDCouplingFieldDouble(NatureOfField n, MEDCouplingTimeDiscretization *td, MEDCouplingFieldDiscretization *type);
     ~MEDCouplingFieldDouble();
   private:
     NatureOfField _nature;
diff --git a/src/MEDCoupling/MEDCouplingGaussLocalization.cxx b/src/MEDCoupling/MEDCouplingGaussLocalization.cxx
new file mode 100644 (file)
index 0000000..68c9a06
--- /dev/null
@@ -0,0 +1,215 @@
+//  Copyright (C) 2007-2010  CEA/DEN, EDF R&D
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU Lesser General Public
+//  License as published by the Free Software Foundation; either
+//  version 2.1 of the License.
+//
+//  This library is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  Lesser General Public License for more details.
+//
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+//  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+#include "MEDCouplingGaussLocalization.hxx"
+#include "CellModel.hxx"
+
+#include <cmath>
+#include <numeric>
+#include <sstream>
+#include <algorithm>
+
+ParaMEDMEM::MEDCouplingGaussLocalization::MEDCouplingGaussLocalization(INTERP_KERNEL::NormalizedCellType type, const std::vector<double>& refCoo,
+                                                                       const std::vector<double>& gsCoo, const std::vector<double>& w) throw(INTERP_KERNEL::Exception)
+try:_type(type),_ref_coord(refCoo),_gauss_coord(gsCoo),_weight(w)
+  {
+    checkCoherency();
+  }
+catch(INTERP_KERNEL::Exception& e)
+  {
+    _type=INTERP_KERNEL::NORM_ERROR;
+    _ref_coord.clear();
+    _gauss_coord.clear();
+    _weight.clear();
+    throw e;
+  }
+
+void ParaMEDMEM::MEDCouplingGaussLocalization::checkCoherency() const throw(INTERP_KERNEL::Exception)
+{
+  const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::getCellModel(_type);
+  int nbNodes=cm.getNumberOfNodes();
+  int dim=cm.getDimension();
+  if(!cm.isDynamic())
+    {
+      if((int)_ref_coord.size()!=nbNodes*dim)
+        {
+          std::ostringstream oss; oss << "Invalid size of refCoo : expecting to be : " << nbNodes << " (nbNodePerCell) * " << dim << " (dim) !";
+          throw INTERP_KERNEL::Exception(oss.str().c_str());
+        }
+    }
+  if(_gauss_coord.size()!=dim*_weight.size())
+    {
+       std::ostringstream oss; oss << "Invalid gsCoo size and weight size : gsCoo.size() must be equal to _weight.size() * " << dim << " (dim) !";
+       throw INTERP_KERNEL::Exception(oss.str().c_str());
+    }
+}
+
+int ParaMEDMEM::MEDCouplingGaussLocalization::getDimension() const
+{
+  if(_weight.empty())
+    return -1;
+  return _gauss_coord.size()/_weight.size();
+}
+
+int ParaMEDMEM::MEDCouplingGaussLocalization::getNumberOfPtsInRefCell() const
+{
+  int dim=getDimension();
+  if(dim==0)
+    return -1;
+  return _ref_coord.size()/dim;
+}
+
+bool ParaMEDMEM::MEDCouplingGaussLocalization::isEqual(const MEDCouplingGaussLocalization& other, double eps) const
+{
+  if(_type!=other._type)
+    return false;
+  if(!areAlmostEqual(_ref_coord,other._ref_coord,eps))
+    return false;
+  if(!areAlmostEqual(_gauss_coord,other._gauss_coord,eps))
+    return false;
+  if(!areAlmostEqual(_weight,other._weight,eps))
+    return false;
+  return true;
+}
+
+double ParaMEDMEM::MEDCouplingGaussLocalization::getRefCoord(int ptIdInCell, int comp) const throw(INTERP_KERNEL::Exception)
+{
+  const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::getCellModel(_type);
+  int nbNodes=cm.getNumberOfNodes();
+  int dim=cm.getDimension();
+  if(ptIdInCell<0 || ptIdInCell>=nbNodes)
+    throw INTERP_KERNEL::Exception("ptIdInCell specified is invalid : must be in [0;nbNodesPerCell) !");
+  if(comp<0 || comp>=dim)
+    throw INTERP_KERNEL::Exception("comp specified is invalid : must be in [0:dimOfCell) !");
+  return _ref_coord[ptIdInCell*dim+comp];
+}
+
+double ParaMEDMEM::MEDCouplingGaussLocalization::getGaussCoord(int gaussPtIdInCell, int comp) const throw(INTERP_KERNEL::Exception)
+{
+  int dim=checkCoherencyOfRequest(gaussPtIdInCell,comp);
+  return _gauss_coord[gaussPtIdInCell*dim+comp];
+}
+
+double ParaMEDMEM::MEDCouplingGaussLocalization::getWeight(int gaussPtIdInCell, double newVal) const throw(INTERP_KERNEL::Exception)
+{
+  checkCoherencyOfRequest(gaussPtIdInCell,0);
+  return _weight[gaussPtIdInCell];
+}
+
+/*!
+ * Completely useless method for end user. Only for CORBA MPI serialization/unserialization.
+ * push at the end of tinyInfo its basic serialization info. The size of pushed data is always the same.
+ * @param tinyInfo inout parameter.
+ */
+void ParaMEDMEM::MEDCouplingGaussLocalization::pushTinySerializationIntInfo(std::vector<int>& tinyInfo) const
+{
+  tinyInfo.push_back((int)_type);
+  tinyInfo.push_back(getNumberOfPtsInRefCell());
+  tinyInfo.push_back(getNumberOfGaussPt());
+}
+
+/*!
+ * Completely useless method for end user. Only for CORBA MPI serialization/unserialization.
+ * push at the end of tinyInfo its basic serialization info. The size of pushed data is \b NOT always the same contrary to pushTinySerializationIntInfo.
+ * @param tinyInfo inout parameter.
+ */
+void ParaMEDMEM::MEDCouplingGaussLocalization::pushTinySerializationDblInfo(std::vector<double>& tinyInfo) const
+{
+  tinyInfo.insert(tinyInfo.end(),_ref_coord.begin(),_ref_coord.end());
+  tinyInfo.insert(tinyInfo.end(),_gauss_coord.begin(),_gauss_coord.end());
+  tinyInfo.insert(tinyInfo.end(),_weight.begin(),_weight.end());
+}
+
+/*!
+ * This method operates the exact inverse operation than ParaMEDMEM::MEDCouplingGaussLocalization::pushTinySerializationDblInfo method. This is one of the last step of unserialization process.
+ * This method should be called on an object resized by buildNewInstanceFromTinyInfo static method.
+ * This method takes in argument a pointer 'vals' that point to the begin of double data pushed remotely by pushTinySerializationDblInfo method.
+ * This method returns the pointer 'vals' with an offset of size what it has been read in this method.
+ */
+const double *ParaMEDMEM::MEDCouplingGaussLocalization::fillWithValues(const double *vals)
+{
+  const double *work=vals;
+  std::copy(work,work+_ref_coord.size(),_ref_coord.begin());
+  work+=_ref_coord.size();
+  std::copy(work,work+_gauss_coord.size(),_gauss_coord.begin());
+  work+=_gauss_coord.size();
+  std::copy(work,work+_weight.size(),_weight.begin());
+  work+=_weight.size();
+  return work;
+}
+
+/*!
+ * This method sets the comp_th component of ptIdInCell_th point coordinate of reference element of type this->_type.
+ * @throw if not 0<=ptIdInCell<nbOfNodePerCell or if not 0<=comp<dim
+ */
+void ParaMEDMEM::MEDCouplingGaussLocalization::setRefCoord(int ptIdInCell, int comp, double newVal) throw(INTERP_KERNEL::Exception)
+{
+  const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::getCellModel(_type);
+  int nbNodes=cm.getNumberOfNodes();
+  int dim=cm.getDimension();
+  if(ptIdInCell<0 || ptIdInCell>=nbNodes)
+    throw INTERP_KERNEL::Exception("ptIdInCell specified is invalid : must be in [0;nbNodesPerCell) !");
+  if(comp<0 || comp>=dim)
+    throw INTERP_KERNEL::Exception("comp specified is invalid : must be in [0:dimOfCell) !");
+  _ref_coord[ptIdInCell*dim+comp]=newVal;
+}
+
+void ParaMEDMEM::MEDCouplingGaussLocalization::setGaussCoord(int gaussPtIdInCell, int comp, double newVal) throw(INTERP_KERNEL::Exception)
+{
+  int dim=checkCoherencyOfRequest(gaussPtIdInCell,comp);
+  _gauss_coord[gaussPtIdInCell*dim+comp]=newVal;
+}
+
+void ParaMEDMEM::MEDCouplingGaussLocalization::setWeight(int gaussPtIdInCell, double newVal) throw(INTERP_KERNEL::Exception)
+{
+  checkCoherencyOfRequest(gaussPtIdInCell,0);
+  _weight[gaussPtIdInCell]=newVal;
+}
+
+/*!
+ * The format of 'tinyData' parameter is the same than pushed in method ParaMEDMEM::MEDCouplingGaussLocalization::pushTinySerializationIntInfo.
+ */
+ParaMEDMEM::MEDCouplingGaussLocalization ParaMEDMEM::MEDCouplingGaussLocalization::buildNewInstanceFromTinyInfo(int dim, const std::vector<int>& tinyData)
+{
+  std::vector<double> v1(dim*tinyData[1]),v2(dim*tinyData[2]),v3(tinyData[2]);
+  return ParaMEDMEM::MEDCouplingGaussLocalization((INTERP_KERNEL::NormalizedCellType)tinyData[0],v1,v2,v3);
+}
+
+int ParaMEDMEM::MEDCouplingGaussLocalization::checkCoherencyOfRequest(int gaussPtIdInCell, int comp) const throw(INTERP_KERNEL::Exception)
+{
+  const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::getCellModel(_type);
+  int dim=cm.getDimension();
+  int nbGsPts=getNumberOfGaussPt();
+  if(gaussPtIdInCell<0 || gaussPtIdInCell>=nbGsPts)
+    throw INTERP_KERNEL::Exception("gaussPtIdInCell specified is invalid : must be in [0:nbGsPts) !");
+  if(comp<0 || comp>=dim)
+    throw INTERP_KERNEL::Exception("comp specified is invalid : must be in [0:dimOfCell) !");
+  return dim;
+}
+
+bool ParaMEDMEM::MEDCouplingGaussLocalization::areAlmostEqual(const std::vector<double>& v1, const std::vector<double>& v2, double eps)
+{
+  int sz=v1.size();
+  if(sz!=(int)v2.size())
+    return false;
+  std::vector<double> tmp(sz);
+  std::transform(v1.begin(),v1.end(),v2.begin(),tmp.begin(),std::minus<double>());
+  std::transform(tmp.begin(),tmp.end(),tmp.begin(),std::ptr_fun<double,double>(fabs));
+  return *std::max_element(tmp.begin(),tmp.end())<eps;
+}
diff --git a/src/MEDCoupling/MEDCouplingGaussLocalization.hxx b/src/MEDCoupling/MEDCouplingGaussLocalization.hxx
new file mode 100644 (file)
index 0000000..791e243
--- /dev/null
@@ -0,0 +1,70 @@
+//  Copyright (C) 2007-2010  CEA/DEN, EDF R&D
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU Lesser General Public
+//  License as published by the Free Software Foundation; either
+//  version 2.1 of the License.
+//
+//  This library is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  Lesser General Public License for more details.
+//
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+//  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+#ifndef __PARAMEDMEM_MEDCOUPLINGGAUSSLOCALIZATION_HXX__
+#define __PARAMEDMEM_MEDCOUPLINGGAUSSLOCALIZATION_HXX__
+
+#include "MEDCoupling.hxx"
+#include "NormalizedUnstructuredMesh.hxx"
+#include "InterpKernelException.hxx"
+
+#include <vector>
+
+namespace ParaMEDMEM
+{
+  class MEDCouplingMesh;
+
+  class MEDCOUPLING_EXPORT MEDCouplingGaussLocalization
+  {
+  public:
+    MEDCouplingGaussLocalization(INTERP_KERNEL::NormalizedCellType type, const std::vector<double>& refCoo,
+                                 const std::vector<double>& gsCoo, const std::vector<double>& w) throw(INTERP_KERNEL::Exception);
+    INTERP_KERNEL::NormalizedCellType getType() const { return _type; }
+    int getNumberOfGaussPt() const { return _weight.size(); }
+    int getDimension() const;
+    int getNumberOfPtsInRefCell() const;
+    void checkCoherency() const throw(INTERP_KERNEL::Exception);
+    bool isEqual(const MEDCouplingGaussLocalization& other, double eps) const;
+    void pushTinySerializationIntInfo(std::vector<int>& tinyInfo) const;
+    void pushTinySerializationDblInfo(std::vector<double>& tinyInfo) const;
+    const double *fillWithValues(const double *vals);
+    //
+    const std::vector<double>& getRefCoords() const { return _ref_coord; }
+    double getRefCoord(int ptIdInCell, int comp) const throw(INTERP_KERNEL::Exception);
+    const std::vector<double>& getGaussCoords() const { return _gauss_coord; }
+    double getGaussCoord(int gaussPtIdInCell, int comp) const throw(INTERP_KERNEL::Exception);
+    const std::vector<double>& getWeights() const { return _weight; }
+    double getWeight(int gaussPtIdInCell, double newVal) const throw(INTERP_KERNEL::Exception);
+    void setRefCoord(int ptIdInCell, int comp, double newVal) throw(INTERP_KERNEL::Exception);
+    void setGaussCoord(int gaussPtIdInCell, int comp, double newVal) throw(INTERP_KERNEL::Exception);
+    void setWeight(int gaussPtIdInCell, double newVal) throw(INTERP_KERNEL::Exception);
+    //
+    static MEDCouplingGaussLocalization buildNewInstanceFromTinyInfo(int dim, const std::vector<int>& tinyData);
+  private:
+    int checkCoherencyOfRequest(int gaussPtIdInCell, int comp) const throw(INTERP_KERNEL::Exception);
+    static bool areAlmostEqual(const std::vector<double>& v1, const std::vector<double>& v2, double eps);
+  private:
+    INTERP_KERNEL::NormalizedCellType _type;
+    std::vector<double> _ref_coord;
+    std::vector<double> _gauss_coord;
+    std::vector<double> _weight;
+  };
+}
+
+#endif
index 3456e329b73c0e36f7d0673c3b20e17e8212e21e..7ced3782b46665c8c91e8c294685f41f13be8168 100644 (file)
 
 #include "MEDCouplingMemArray.txx"
 
+#include "GenMathFormulae.hxx"
+#include "InterpKernelExprParser.hxx"
+
+#include <set>
+#include <cmath>
+#include <numeric>
 #include <functional>
 
+typedef double (*MYFUNCPTR)(double);
+
 using namespace ParaMEDMEM;
 
 void DataArray::setName(const char *name)
@@ -45,6 +53,37 @@ bool DataArray::areInfoEquals(const DataArray& other) const
   return _info_on_compo==other._info_on_compo;
 }
 
+void DataArray::reprWithoutNameStream(std::ostream& stream) const
+{
+  stream << "Nb of components : "<< getNumberOfComponents() << "\n";
+  stream << "Info of these components : ";
+  for(std::vector<std::string>::const_iterator iter=_info_on_compo.begin();iter!=_info_on_compo.end();iter++)
+    stream << "\"" << *iter << "\"   ";
+  stream << "\n";
+}
+
+std::string DataArray::getInfoOnComponent(int i) const throw(INTERP_KERNEL::Exception)
+{
+  if(i<(int)_info_on_compo.size())
+    return _info_on_compo[i];
+  else
+    {
+      std::ostringstream oss; oss << "getInfoOnComponent : Invalid component id transmitted (" << i << ") >= " << (int) _info_on_compo.size();
+      throw INTERP_KERNEL::Exception(oss.str().c_str());
+    }
+}
+
+void DataArray::setInfoOnComponent(int i, const char *info) throw(INTERP_KERNEL::Exception)
+{
+  if(i<(int)_info_on_compo.size())
+    _info_on_compo[i]=info;
+  else
+    {
+      std::ostringstream oss; oss << "setInfoOnComponent : Invalid component id transmitted (" << i << ") >= " << (int) _info_on_compo.size();
+      throw INTERP_KERNEL::Exception(oss.str().c_str());
+    }
+}
+
 DataArrayDouble *DataArrayDouble::New()
 {
   return new DataArrayDouble;
@@ -74,6 +113,51 @@ void DataArrayDouble::alloc(int nbOfTuple, int nbOfCompo)
   declareAsNew();
 }
 
+void DataArrayDouble::fillWithZero()
+{
+  _mem.fillWithValue(0.);
+}
+
+std::string DataArrayDouble::repr() const
+{
+  std::ostringstream ret;
+  reprStream(ret);
+  return ret.str();
+}
+
+std::string DataArrayDouble::reprZip() const
+{
+  std::ostringstream ret;
+  reprZipStream(ret);
+  return ret.str();
+}
+
+void DataArrayDouble::reprStream(std::ostream& stream) const
+{
+  stream << "Name of double array : \"" << _name << "\"\n";
+  reprWithoutNameStream(stream);
+}
+
+void DataArrayDouble::reprZipStream(std::ostream& stream) const
+{
+  stream << "Name of double array : \"" << _name << "\"\n";
+  reprZipWithoutNameStream(stream);
+}
+
+void DataArrayDouble::reprWithoutNameStream(std::ostream& stream) const
+{
+  DataArray::reprWithoutNameStream(stream);
+  stream.precision(15);
+  _mem.repr(getNumberOfComponents(),stream);
+}
+
+void DataArrayDouble::reprZipWithoutNameStream(std::ostream& stream) const
+{
+  DataArray::reprWithoutNameStream(stream);
+  stream.precision(15);
+  _mem.reprZip(getNumberOfComponents(),stream);
+}
+
 bool DataArrayDouble::isEqual(const DataArrayDouble& other, double prec) const
 {
   if(!areInfoEquals(other))
@@ -81,6 +165,11 @@ bool DataArrayDouble::isEqual(const DataArrayDouble& other, double prec) const
   return _mem.isEqual(other._mem,prec);
 }
 
+bool DataArrayDouble::isEqualWithoutConsideringStr(const DataArrayDouble& other, double prec) const
+{
+  return _mem.isEqual(other._mem,prec);
+}
+
 void DataArrayDouble::reAlloc(int nbOfTuples)
 {
   _mem.reAlloc(_info_on_compo.size()*nbOfTuples);
@@ -88,6 +177,127 @@ void DataArrayDouble::reAlloc(int nbOfTuples)
   declareAsNew();
 }
 
+DataArrayInt *DataArrayDouble::convertToIntArr() const
+{
+  DataArrayInt *ret=DataArrayInt::New();
+  ret->alloc(getNumberOfTuples(),getNumberOfComponents());
+  int nbOfVals=getNbOfElems();
+  const double *src=getConstPointer();
+  int *dest=ret->getPointer();
+  std::copy(src,src+nbOfVals,dest);
+  ret->copyStringInfoFrom(*this);
+  return ret;
+}
+
+/*!
+ * This method does \b not change the number of tuples after this call.
+ * Only a permutation is done. If a permutation reduction is needed substr, or selectByTupleId should be used.
+ */
+void DataArrayDouble::renumberInPlace(const int *old2New)
+{
+  int nbTuples=getNumberOfTuples();
+  int nbOfCompo=getNumberOfComponents();
+  double *tmp=new double[nbTuples*nbOfCompo];
+  const double *iptr=getConstPointer();
+  for(int i=0;i<nbTuples;i++)
+    std::copy(iptr+nbOfCompo*i,iptr+nbOfCompo*(i+1),tmp+nbOfCompo*old2New[i]);
+  std::copy(tmp,tmp+nbTuples*nbOfCompo,getPointer());
+  delete [] tmp;
+  declareAsNew();
+}
+
+/*!
+ * This method does \b not change the number of tuples after this call.
+ * Only a permutation is done. If a permutation reduction is needed substr, or selectByTupleId should be used.
+ */
+DataArrayDouble *DataArrayDouble::renumber(const int *old2New) const
+{
+  int nbTuples=getNumberOfTuples();
+  int nbOfCompo=getNumberOfComponents();
+  DataArrayDouble *ret=DataArrayDouble::New();
+  ret->alloc(nbTuples,nbOfCompo);
+  ret->copyStringInfoFrom(*this);
+  const double *iptr=getConstPointer();
+  double *optr=ret->getPointer();
+  for(int i=0;i<nbTuples;i++)
+    std::copy(iptr+nbOfCompo*i,iptr+nbOfCompo*(i+1),optr+nbOfCompo*old2New[i]);
+  return ret;
+}
+
+/*!
+ * This methods has a similar behaviour than std::string::substr. This method returns a newly created DataArrayInt that is part of this with same number of components.
+ * The intervall is specified by [tupleIdBg,tupleIdEnd) except if tupleIdEnd ==-1 in this case the [tupleIdBg,this->end()) will be kept.
+ * This method check that interval is valid regarding this, if not an exception will be thrown.
+ */
+DataArrayDouble *DataArrayDouble::substr(int tupleIdBg, int tupleIdEnd) const throw(INTERP_KERNEL::Exception)
+{
+  int nbt=getNumberOfTuples();
+  if(tupleIdBg<0)
+    throw INTERP_KERNEL::Exception("DataArrayInt::substr : The tupleIdBg parameter must be greater than 0 !");
+  if(tupleIdBg>=nbt)
+    throw INTERP_KERNEL::Exception("DataArrayInt::substr : The tupleIdBg parameter is greater or equal than number of tuples !");
+  int trueEnd=tupleIdEnd;
+  if(tupleIdEnd!=-1)
+    {
+      if(tupleIdEnd>nbt)
+        throw INTERP_KERNEL::Exception("DataArrayInt::substr : The tupleIdBg parameter is greater or equal than number of tuples !");
+    }
+  else
+    trueEnd=nbt;
+  int nbComp=getNumberOfComponents();
+  DataArrayDouble *ret=DataArrayDouble::New();
+  ret->alloc(trueEnd-tupleIdBg,nbComp);
+  ret->copyStringInfoFrom(*this);
+  std::copy(getConstPointer()+tupleIdBg*nbComp,getConstPointer()+trueEnd*nbComp,ret->getPointer());
+  return ret;
+}
+
+/*!
+ * This method builds a new instance of DataArrayDouble (to deal with) that is reduction or an extension of 'this'.
+ * if 'newNbOfComp' < this->getNumberOfComponents() a reduction is done and for each tuple 'newNbOfComp' first components are kept.
+ * If 'newNbOfComp' > this->getNumberOfComponents() an extension is done, and for each components i such that i > getNumberOfComponents() 'dftValue' parameter is taken.
+ */
+DataArrayDouble *DataArrayDouble::changeNbOfComponents(int newNbOfComp, double dftValue) const throw(INTERP_KERNEL::Exception)
+{
+  DataArrayDouble *ret=DataArrayDouble::New();
+  ret->alloc(getNumberOfTuples(),newNbOfComp);
+  const double *oldc=getConstPointer();
+  double *nc=ret->getPointer();
+  int nbOfTuples=getNumberOfTuples();
+  int oldNbOfComp=getNumberOfComponents();
+  int dim=std::min(oldNbOfComp,newNbOfComp);
+  for(int i=0;i<nbOfTuples;i++)
+    {
+      int j=0;
+      for(;j<dim;j++)
+        nc[newNbOfComp*i+j]=oldc[i*oldNbOfComp+j];
+      for(;j<newNbOfComp;j++)
+        nc[newNbOfComp*i+j]=dftValue;
+    }
+  ret->setName(getName().c_str());
+  for(int i=0;i<dim;i++)
+    ret->setInfoOnComponent(i,getInfoOnComponent(i).c_str());
+  ret->setName(getName().c_str());
+  return ret;
+}
+
+/*!
+ * This method is a generalization of DataArrayDouble::substr method because a not contigous range can be specified here.
+ */
+DataArrayDouble *DataArrayDouble::selectByTupleId(const int *start, const int *end) const
+{
+  DataArrayDouble *ret=DataArrayDouble::New();
+  int nbComp=getNumberOfComponents();
+  ret->alloc(std::distance(start,end),nbComp);
+  ret->copyStringInfoFrom(*this);
+  double *pt=ret->getPointer();
+  const double *srcPt=getConstPointer();
+  int i=0;
+  for(const int *w=start;w!=end;w++,i++)
+    std::copy(srcPt+(*w)*nbComp,srcPt+((*w)+1)*nbComp,pt+i*nbComp);
+  return ret;
+}
+
 void DataArrayDouble::setArrayIn(DataArrayDouble *newArray, DataArrayDouble* &arrayToSet)
 {
   if(newArray!=arrayToSet)
@@ -117,7 +327,432 @@ void DataArrayDouble::checkNoNullValues() const throw(INTERP_KERNEL::Exception)
     throw INTERP_KERNEL::Exception("A value 0.0 have been detected !");
 }
 
-DataArrayDouble *DataArrayDouble::aggregate(const DataArrayDouble *a1, const DataArrayDouble *a2)
+double DataArrayDouble::getMaxValue(int& tupleId) const throw(INTERP_KERNEL::Exception)
+{
+  if(getNumberOfComponents()!=1)
+    throw INTERP_KERNEL::Exception("DataArrayDouble::getMaxValue : must be applied on DataArrayDouble with only one component !");
+  int nbOfTuples=getNumberOfTuples();
+  if(nbOfTuples<=0)
+    throw INTERP_KERNEL::Exception("DataArrayDouble::getMaxValue : array exists but number of tuples must be > 0 !");
+  const double *vals=getConstPointer();
+  const double *loc=std::max_element(vals,vals+nbOfTuples);
+  tupleId=std::distance(vals,loc);
+  return *loc;
+}
+
+double DataArrayDouble::getMinValue(int& tupleId) const throw(INTERP_KERNEL::Exception)
+{
+  if(getNumberOfComponents()!=1)
+    throw INTERP_KERNEL::Exception("DataArrayDouble::getMinValue : must be applied on DataArrayDouble with only one component !");
+  int nbOfTuples=getNumberOfTuples();
+  if(nbOfTuples<=0)
+    throw INTERP_KERNEL::Exception("DataArrayDouble::getMinValue : array exists but number of tuples must be > 0 !");
+  const double *vals=getConstPointer();
+  const double *loc=std::min_element(vals,vals+nbOfTuples);
+  tupleId=std::distance(vals,loc);
+  return *loc;
+}
+
+double DataArrayDouble::getAverageValue() const throw(INTERP_KERNEL::Exception)
+{
+  if(getNumberOfComponents()!=1)
+    throw INTERP_KERNEL::Exception("DataArrayDouble::getAverageValue : must be applied on DataArrayDouble with only one component !");
+  int nbOfTuples=getNumberOfTuples();
+  if(nbOfTuples<=0)
+    throw INTERP_KERNEL::Exception("DataArrayDouble::getAverageValue : array exists but number of tuples must be > 0 !");
+  const double *vals=getConstPointer();
+  double ret=std::accumulate(vals,vals+nbOfTuples,0.);
+  return ret/nbOfTuples;
+}
+
+void DataArrayDouble::accumulate(double *res) const
+{
+  const double *ptr=getConstPointer();
+  int nbTuple=getNumberOfTuples();
+  int nbComps=getNumberOfComponents();
+  std::fill(res,res+nbComps,0.);
+  for(int i=0;i<nbTuple;i++)
+    std::transform(ptr+i*nbComps,ptr+(i+1)*nbComps,res,res,std::plus<double>());
+}
+
+double DataArrayDouble::accumulate(int compId) const
+{
+  const double *ptr=getConstPointer();
+  int nbTuple=getNumberOfTuples();
+  int nbComps=getNumberOfComponents();
+  if(compId>=nbComps)
+    throw INTERP_KERNEL::Exception("DataArrayDouble::accumulate : Invalid compId specified : No such nb of components !");
+  double ret=0.;
+  for(int i=0;i<nbTuple;i++)
+    ret+=ptr[i*nbComps+compId];
+  return ret;
+}
+
+DataArrayDouble *DataArrayDouble::doublyContractedProduct() const throw(INTERP_KERNEL::Exception)
+{
+  int nbOfComp=getNumberOfComponents();
+  if(nbOfComp!=6)
+    throw INTERP_KERNEL::Exception("DataArrayDouble::doublyContractedProduct : must be an array with exactly 6 components !");
+  DataArrayDouble *ret=DataArrayDouble::New();
+  int nbOfTuple=getNumberOfTuples();
+  ret->alloc(nbOfTuple,1);
+  const double *src=getConstPointer();
+  double *dest=ret->getPointer();
+  for(int i=0;i<nbOfTuple;i++,dest++,src+=6)
+    *dest=src[0]*src[0]+src[1]*src[1]+src[2]*src[2]+2.*src[3]*src[3]+2.*src[4]*src[4]+2.*src[5]*src[5];
+  return ret;
+}
+
+DataArrayDouble *DataArrayDouble::determinant() const throw(INTERP_KERNEL::Exception)
+{
+  DataArrayDouble *ret=DataArrayDouble::New();
+  int nbOfTuple=getNumberOfTuples();
+  ret->alloc(nbOfTuple,1);
+  const double *src=getConstPointer();
+  double *dest=ret->getPointer();
+  switch(getNumberOfComponents())
+    {
+    case 6:
+      for(int i=0;i<nbOfTuple;i++,dest++,src+=6)
+        *dest=src[0]*src[1]*src[2]+2.*src[4]*src[5]*src[3]-src[0]*src[4]*src[4]-src[2]*src[3]*src[3]-src[1]*src[5]*src[5];
+        return ret;
+    case 4:
+      for(int i=0;i<nbOfTuple;i++,dest++,src+=4)
+        *dest=src[0]*src[3]-src[1]*src[2];
+      return ret;
+    case 9:
+      for(int i=0;i<nbOfTuple;i++,dest++,src+=9)
+        *dest=src[0]*src[4]*src[8]+src[1]*src[5]*src[6]+src[2]*src[3]*src[7]-src[0]*src[5]*src[7]-src[1]*src[3]*src[8]-src[2]*src[4]*src[6];
+      return ret;
+    default:
+      ret->decrRef();
+      throw INTERP_KERNEL::Exception("DataArrayDouble::determinant : Invalid number of components ! must be in 4,6,9 !");
+    }
+}
+
+DataArrayDouble *DataArrayDouble::eigenValues() const throw(INTERP_KERNEL::Exception)
+{
+  int nbOfComp=getNumberOfComponents();
+  if(nbOfComp!=6)
+    throw INTERP_KERNEL::Exception("DataArrayDouble::eigenValues : must be an array with exactly 6 components !");
+  DataArrayDouble *ret=DataArrayDouble::New();
+  int nbOfTuple=getNumberOfTuples();
+  ret->alloc(nbOfTuple,3);
+  const double *src=getConstPointer();
+  double *dest=ret->getPointer();
+  for(int i=0;i<nbOfTuple;i++,dest+=3,src+=6)
+    INTERP_KERNEL::computeEigenValues6(src,dest);
+  return ret;
+}
+
+DataArrayDouble *DataArrayDouble::eigenVectors() const throw(INTERP_KERNEL::Exception)
+{
+  int nbOfComp=getNumberOfComponents();
+  if(nbOfComp!=6)
+    throw INTERP_KERNEL::Exception("DataArrayDouble::eigenVectors : must be an array with exactly 6 components !");
+  DataArrayDouble *ret=DataArrayDouble::New();
+  int nbOfTuple=getNumberOfTuples();
+  ret->alloc(nbOfTuple,9);
+  const double *src=getConstPointer();
+  double *dest=ret->getPointer();
+  for(int i=0;i<nbOfTuple;i++,src+=6)
+    {
+      double tmp[3];
+      INTERP_KERNEL::computeEigenValues6(src,tmp);
+      for(int j=0;j<3;j++,dest+=3)
+        INTERP_KERNEL::computeEigenVectorForEigenValue6(src,tmp[j],1e-12,dest);
+    }
+  return ret;
+}
+
+DataArrayDouble *DataArrayDouble::inverse() const throw(INTERP_KERNEL::Exception)
+{
+  int nbOfComp=getNumberOfComponents();
+  if(nbOfComp!=6 && nbOfComp!=9 && nbOfComp!=4)
+    throw INTERP_KERNEL::Exception("DataArrayDouble::inversion : must be an array with 4,6 or 9 components !");
+  DataArrayDouble *ret=DataArrayDouble::New();
+  int nbOfTuple=getNumberOfTuples();
+  ret->alloc(nbOfTuple,nbOfComp);
+  const double *src=getConstPointer();
+  double *dest=ret->getPointer();
+if(nbOfComp==6)
+    for(int i=0;i<nbOfTuple;i++,dest+=6,src+=6)
+      {
+        double det=src[0]*src[1]*src[2]+2.*src[4]*src[5]*src[3]-src[0]*src[4]*src[4]-src[2]*src[3]*src[3]-src[1]*src[5]*src[5];
+        dest[0]=(src[1]*src[2]-src[4]*src[4])/det;
+        dest[1]=(src[0]*src[2]-src[5]*src[5])/det;
+        dest[2]=(src[0]*src[1]-src[3]*src[3])/det;
+        dest[3]=(src[5]*src[4]-src[3]*src[2])/det;
+        dest[4]=(src[5]*src[3]-src[0]*src[4])/det;
+        dest[5]=(src[3]*src[4]-src[1]*src[5])/det;
+      }
+  else if(nbOfComp==4)
+    for(int i=0;i<nbOfTuple;i++,dest+=4,src+=4)
+      {
+        double det=src[0]*src[3]-src[1]*src[2];
+        dest[0]=src[3]/det;
+        dest[1]=-src[1]/det;
+        dest[2]=-src[2]/det;
+        dest[3]=src[0]/det;
+      }
+  else
+    for(int i=0;i<nbOfTuple;i++,dest+=9,src+=9)
+      {
+        double det=src[0]*src[4]*src[8]+src[1]*src[5]*src[6]+src[2]*src[3]*src[7]-src[0]*src[5]*src[7]-src[1]*src[3]*src[8]-src[2]*src[4]*src[6];
+        dest[0]=(src[4]*src[8]-src[7]*src[5])/det;
+        dest[1]=(src[7]*src[2]-src[1]*src[8])/det;
+        dest[2]=(src[1]*src[5]-src[4]*src[2])/det;
+        dest[3]=(src[6]*src[5]-src[3]*src[8])/det;
+        dest[4]=(src[0]*src[8]-src[6]*src[2])/det;
+        dest[5]=(src[2]*src[3]-src[0]*src[5])/det;
+        dest[6]=(src[3]*src[7]-src[6]*src[4])/det;
+        dest[7]=(src[6]*src[1]-src[0]*src[7])/det;
+        dest[8]=(src[0]*src[4]-src[1]*src[3])/det;
+      }
+  return ret;
+}
+
+DataArrayDouble *DataArrayDouble::trace() const throw(INTERP_KERNEL::Exception)
+{
+  int nbOfComp=getNumberOfComponents();
+  if(nbOfComp!=6 && nbOfComp!=9 && nbOfComp!=4)
+    throw INTERP_KERNEL::Exception("DataArrayDouble::trace : must be an array with 4,6 or 9 components !");
+  DataArrayDouble *ret=DataArrayDouble::New();
+  int nbOfTuple=getNumberOfTuples();
+  ret->alloc(nbOfTuple,1);
+  const double *src=getConstPointer();
+  double *dest=ret->getPointer();
+  if(nbOfComp==6)
+    for(int i=0;i<nbOfTuple;i++,dest++,src+=6)
+      *dest=src[0]+src[1]+src[2];
+  else if(nbOfComp==4)
+    for(int i=0;i<nbOfTuple;i++,dest++,src+=4)
+      *dest=src[0]+src[3];
+  else
+    for(int i=0;i<nbOfTuple;i++,dest++,src+=9)
+      *dest=src[0]+src[4]+src[8];
+  return ret;
+}
+
+DataArrayDouble *DataArrayDouble::deviator() const throw(INTERP_KERNEL::Exception)
+{
+  int nbOfComp=getNumberOfComponents();
+  if(nbOfComp!=6)
+    throw INTERP_KERNEL::Exception("DataArrayDouble::deviator : must be an array with exactly 6 components !");
+  DataArrayDouble *ret=DataArrayDouble::New();
+  int nbOfTuple=getNumberOfTuples();
+  ret->alloc(nbOfTuple,6);
+  const double *src=getConstPointer();
+  double *dest=ret->getPointer();
+  for(int i=0;i<nbOfTuple;i++,dest+=6,src+=6)
+    {
+      double tr=(src[0]+src[1]+src[2])/3.;
+      dest[0]=src[0]-tr;
+      dest[1]=src[1]-tr;
+      dest[2]=src[2]-tr;
+      dest[3]=src[3];
+      dest[4]=src[4];
+      dest[5]=src[5];
+    }
+  return ret;
+}
+
+DataArrayDouble *DataArrayDouble::magnitude() const throw(INTERP_KERNEL::Exception)
+{
+  int nbOfComp=getNumberOfComponents();
+  DataArrayDouble *ret=DataArrayDouble::New();
+  int nbOfTuple=getNumberOfTuples();
+  ret->alloc(nbOfTuple,1);
+  const double *src=getConstPointer();
+  double *dest=ret->getPointer();
+  for(int i=0;i<nbOfTuple;i++,dest++)
+    {
+      double sum=0.;
+      for(int j=0;j<nbOfComp;j++,src++)
+        sum+=(*src)*(*src);
+      *dest=sqrt(sum);
+    }
+  return ret;
+}
+
+DataArrayDouble *DataArrayDouble::maxPerTuple() const throw(INTERP_KERNEL::Exception)
+{
+  int nbOfComp=getNumberOfComponents();
+  DataArrayDouble *ret=DataArrayDouble::New();
+  int nbOfTuple=getNumberOfTuples();
+  ret->alloc(nbOfTuple,1);
+  const double *src=getConstPointer();
+  double *dest=ret->getPointer();
+  for(int i=0;i<nbOfTuple;i++,dest++,src+=nbOfComp)
+    *dest=*std::max_element(src,src+nbOfComp);
+  return ret;
+}
+
+void DataArrayDouble::sortPerTuple(bool asc) throw(INTERP_KERNEL::Exception)
+{
+  double *pt=getPointer();
+  int nbOfTuple=getNumberOfTuples();
+  int nbOfComp=getNumberOfComponents();
+  if(asc)
+    for(int i=0;i<nbOfTuple;i++,pt+=nbOfComp)
+      std::sort(pt,pt+nbOfComp);
+  else
+    for(int i=0;i<nbOfTuple;i++,pt+=nbOfComp)
+      std::sort(pt,pt+nbOfComp,std::greater<double>());
+  declareAsNew();
+}
+
+void DataArrayDouble::applyLin(double a, double b, int compoId)
+{
+  double *ptr=getPointer()+compoId;
+  int nbOfComp=getNumberOfComponents();
+  int nbOfTuple=getNumberOfTuples();
+  for(int i=0;i<nbOfTuple;i++,ptr+=nbOfComp)
+    *ptr=a*(*ptr)+b;
+  declareAsNew();
+}
+
+DataArrayDouble *DataArrayDouble::applyFunc(int nbOfComp, FunctionToEvaluate func) const throw(INTERP_KERNEL::Exception)
+{
+  DataArrayDouble *newArr=DataArrayDouble::New();
+  int nbOfTuples=getNumberOfTuples();
+  int oldNbOfComp=getNumberOfComponents();
+  newArr->alloc(nbOfTuples,nbOfComp);
+  const double *ptr=getConstPointer();
+  double *ptrToFill=newArr->getPointer();
+  for(int i=0;i<nbOfTuples;i++)
+    {
+      if(!func(ptr+i*oldNbOfComp,ptrToFill+i*nbOfComp))
+        {
+          std::ostringstream oss; oss << "For tuple # " << i << " with value (";
+          std::copy(ptr+oldNbOfComp*i,ptr+oldNbOfComp*(i+1),std::ostream_iterator<double>(oss,", "));
+          oss << ") : Evaluation of function failed !";
+          newArr->decrRef();
+          throw INTERP_KERNEL::Exception(oss.str().c_str());
+        }
+    }
+  return newArr;
+}
+
+DataArrayDouble *DataArrayDouble::applyFunc(int nbOfComp, const char *func) const throw(INTERP_KERNEL::Exception)
+{
+  INTERP_KERNEL::ExprParser expr(func);
+  expr.parse();
+  std::set<std::string> vars;
+  expr.getTrueSetOfVars(vars);
+  int oldNbOfComp=getNumberOfComponents();
+  if((int)vars.size()>oldNbOfComp)
+    {
+      std::ostringstream oss; oss << "The field has a " << oldNbOfComp << " components and there are ";
+      oss << vars.size() << " variables : ";
+      std::copy(vars.begin(),vars.end(),std::ostream_iterator<std::string>(oss," "));
+      throw INTERP_KERNEL::Exception(oss.str().c_str());
+    }
+  std::vector<std::string> varsV(vars.begin(),vars.end());
+  expr.prepareExprEvaluation(varsV);
+  //
+  DataArrayDouble *newArr=DataArrayDouble::New();
+  int nbOfTuples=getNumberOfTuples();
+  newArr->alloc(nbOfTuples,nbOfComp);
+  const double *ptr=getConstPointer();
+  double *ptrToFill=newArr->getPointer();
+  for(int i=0;i<nbOfTuples;i++)
+    {
+      try
+        {
+          expr.evaluateExpr(nbOfComp,ptr+i*oldNbOfComp,ptrToFill+i*nbOfComp);
+        }
+      catch(INTERP_KERNEL::Exception& e)
+        {
+          std::ostringstream oss; oss << "For tuple # " << i << " with value (";
+          std::copy(ptr+oldNbOfComp*i,ptr+oldNbOfComp*(i+1),std::ostream_iterator<double>(oss,", "));
+          oss << ") : Evaluation of function failed !" << e.what();
+          newArr->decrRef();
+          throw INTERP_KERNEL::Exception(oss.str().c_str());
+        }
+    }
+  return newArr;
+}
+
+DataArrayDouble *DataArrayDouble::applyFunc(const char *func) const throw(INTERP_KERNEL::Exception)
+{
+  INTERP_KERNEL::ExprParser expr(func);
+  expr.parse();
+  expr.prepareExprEvaluationVec();
+  //
+  DataArrayDouble *newArr=DataArrayDouble::New();
+  int nbOfTuples=getNumberOfTuples();
+  int nbOfComp=getNumberOfComponents();
+  newArr->alloc(nbOfTuples,nbOfComp);
+  const double *ptr=getConstPointer();
+  double *ptrToFill=newArr->getPointer();
+  for(int i=0;i<nbOfTuples;i++)
+    {
+      try
+        {
+          expr.evaluateExpr(nbOfComp,ptr+i*nbOfComp,ptrToFill+i*nbOfComp);
+        }
+      catch(INTERP_KERNEL::Exception& e)
+        {
+          std::ostringstream oss; oss << "For tuple # " << i << " with value (";
+          std::copy(ptr+nbOfComp*i,ptr+nbOfComp*(i+1),std::ostream_iterator<double>(oss,", "));
+          oss << ") : Evaluation of function failed ! " << e.what();
+          newArr->decrRef();
+          throw INTERP_KERNEL::Exception(oss.str().c_str());
+        }
+    }
+  return newArr;
+}
+
+void DataArrayDouble::applyFuncFast32(const char *func)
+{
+  INTERP_KERNEL::ExprParser expr(func);
+  expr.parse();
+  char *funcStr=expr.compileX86();
+  MYFUNCPTR funcPtr=(MYFUNCPTR)funcStr;//he he...
+  //
+  double *ptr=getPointer();
+  int nbOfComp=getNumberOfComponents();
+  int nbOfTuples=getNumberOfTuples();
+  int nbOfElems=nbOfTuples*nbOfComp;
+  for(int i=0;i<nbOfElems;i++,ptr++)
+    *ptr=funcPtr(*ptr);
+  declareAsNew();
+}
+
+void DataArrayDouble::applyFuncFast64(const char *func)
+{
+  INTERP_KERNEL::ExprParser expr(func);
+  expr.parse();
+  char *funcStr=expr.compileX86_64();
+  MYFUNCPTR funcPtr=(MYFUNCPTR)funcStr;//he he...
+  //
+  double *ptr=getPointer();
+  int nbOfComp=getNumberOfComponents();
+  int nbOfTuples=getNumberOfTuples();
+  int nbOfElems=nbOfTuples*nbOfComp;
+  for(int i=0;i<nbOfElems;i++,ptr++)
+    *ptr=funcPtr(*ptr);
+  declareAsNew();
+}
+
+DataArrayInt *DataArrayDouble::getIdsInRange(double vmin, double vmax) const throw(INTERP_KERNEL::Exception)
+{
+  if(getNumberOfComponents()!=1)
+    throw INTERP_KERNEL::Exception("DataArrayDouble::getIdsInRange : the default array must have only one component !");
+  const double *cptr=getConstPointer();
+  std::vector<int> res;
+  int nbOfTuples=getNumberOfTuples();
+  for(int i=0;i<nbOfTuples;i++,cptr++)
+    if(*cptr>=vmin && *cptr<=vmax)
+      res.push_back(i);
+  DataArrayInt *ret=DataArrayInt::New();
+  ret->alloc(res.size(),1);
+  std::copy(res.begin(),res.end(),ret->getPointer());
+  return ret;
+}
+
+DataArrayDouble *DataArrayDouble::aggregate(const DataArrayDouble *a1, const DataArrayDouble *a2) throw(INTERP_KERNEL::Exception)
 {
   int nbOfComp=a1->getNumberOfComponents();
   if(nbOfComp!=a2->getNumberOfComponents())
@@ -132,7 +767,97 @@ DataArrayDouble *DataArrayDouble::aggregate(const DataArrayDouble *a1, const Dat
   return ret;
 }
 
-DataArrayDouble *DataArrayDouble::add(const DataArrayDouble *a1, const DataArrayDouble *a2)
+DataArrayDouble *DataArrayDouble::dot(const DataArrayDouble *a1, const DataArrayDouble *a2) throw(INTERP_KERNEL::Exception)
+{
+  int nbOfComp=a1->getNumberOfComponents();
+  if(nbOfComp!=a2->getNumberOfComponents())
+    throw INTERP_KERNEL::Exception("Nb of components mismatch for array dot !");
+  int nbOfTuple=a1->getNumberOfTuples();
+  if(nbOfTuple!=a2->getNumberOfTuples())
+    throw INTERP_KERNEL::Exception("Nb of tuples mismatch for array dot !");
+  DataArrayDouble *ret=DataArrayDouble::New();
+  ret->alloc(nbOfTuple,1);
+  double *retPtr=ret->getPointer();
+  const double *a1Ptr=a1->getConstPointer();
+  const double *a2Ptr=a2->getConstPointer();
+  for(int i=0;i<nbOfTuple;i++)
+    {
+      double sum=0.;
+      for(int j=0;j<nbOfComp;j++)
+        sum+=a1Ptr[i*nbOfComp+j]*a2Ptr[i*nbOfComp+j];
+      retPtr[i]=sum;
+    }
+  ret->setInfoOnComponent(0,a1->getInfoOnComponent(0).c_str());
+  ret->setName(a1->getName().c_str());
+  return ret;
+}
+
+DataArrayDouble *DataArrayDouble::crossProduct(const DataArrayDouble *a1, const DataArrayDouble *a2) throw(INTERP_KERNEL::Exception)
+{
+  int nbOfComp=a1->getNumberOfComponents();
+  if(nbOfComp!=a2->getNumberOfComponents())
+    throw INTERP_KERNEL::Exception("Nb of components mismatch for array crossProduct !");
+  if(nbOfComp!=3)
+    throw INTERP_KERNEL::Exception("Nb of components must be equal to 3 for array crossProduct !");
+  int nbOfTuple=a1->getNumberOfTuples();
+  if(nbOfTuple!=a2->getNumberOfTuples())
+    throw INTERP_KERNEL::Exception("Nb of tuples mismatch for array crossProduct !");
+  DataArrayDouble *ret=DataArrayDouble::New();
+  ret->alloc(nbOfTuple,3);
+  double *retPtr=ret->getPointer();
+  const double *a1Ptr=a1->getConstPointer();
+  const double *a2Ptr=a2->getConstPointer();
+  for(int i=0;i<nbOfTuple;i++)
+    {
+      retPtr[3*i]=a1Ptr[3*i+1]*a2Ptr[3*i+2]-a1Ptr[3*i+2]*a2Ptr[3*i+1];
+      retPtr[3*i+1]=a1Ptr[3*i+2]*a2Ptr[3*i]-a1Ptr[3*i]*a2Ptr[3*i+2];
+      retPtr[3*i+2]=a1Ptr[3*i]*a2Ptr[3*i+1]-a1Ptr[3*i+1]*a2Ptr[3*i];
+    }
+  ret->copyStringInfoFrom(*a1);
+  return ret;
+}
+
+DataArrayDouble *DataArrayDouble::max(const DataArrayDouble *a1, const DataArrayDouble *a2) throw(INTERP_KERNEL::Exception)
+{
+  int nbOfComp=a1->getNumberOfComponents();
+  if(nbOfComp!=a2->getNumberOfComponents())
+    throw INTERP_KERNEL::Exception("Nb of components mismatch for array max !");
+  int nbOfTuple=a1->getNumberOfTuples();
+  if(nbOfTuple!=a2->getNumberOfTuples())
+    throw INTERP_KERNEL::Exception("Nb of tuples mismatch for array max !");
+  DataArrayDouble *ret=DataArrayDouble::New();
+  ret->alloc(nbOfTuple,nbOfComp);
+  double *retPtr=ret->getPointer();
+  const double *a1Ptr=a1->getConstPointer();
+  const double *a2Ptr=a2->getConstPointer();
+  int nbElem=nbOfTuple*nbOfComp;
+  for(int i=0;i<nbElem;i++)
+    retPtr[i]=std::max(a1Ptr[i],a2Ptr[i]);
+  ret->copyStringInfoFrom(*a1);
+  return ret;
+}
+
+DataArrayDouble *DataArrayDouble::min(const DataArrayDouble *a1, const DataArrayDouble *a2) throw(INTERP_KERNEL::Exception)
+{
+  int nbOfComp=a1->getNumberOfComponents();
+  if(nbOfComp!=a2->getNumberOfComponents())
+    throw INTERP_KERNEL::Exception("Nb of components mismatch for array min !");
+  int nbOfTuple=a1->getNumberOfTuples();
+  if(nbOfTuple!=a2->getNumberOfTuples())
+    throw INTERP_KERNEL::Exception("Nb of tuples mismatch for array min !");
+  DataArrayDouble *ret=DataArrayDouble::New();
+  ret->alloc(nbOfTuple,nbOfComp);
+  double *retPtr=ret->getPointer();
+  const double *a1Ptr=a1->getConstPointer();
+  const double *a2Ptr=a2->getConstPointer();
+  int nbElem=nbOfTuple*nbOfComp;
+  for(int i=0;i<nbElem;i++)
+    retPtr[i]=std::min(a1Ptr[i],a2Ptr[i]);
+  ret->copyStringInfoFrom(*a1);
+  return ret;
+}
+
+DataArrayDouble *DataArrayDouble::add(const DataArrayDouble *a1, const DataArrayDouble *a2) throw(INTERP_KERNEL::Exception)
 {
   int nbOfComp=a1->getNumberOfComponents();
   if(nbOfComp!=a2->getNumberOfComponents())
@@ -147,7 +872,7 @@ DataArrayDouble *DataArrayDouble::add(const DataArrayDouble *a1, const DataArray
   return ret;
 }
 
-void DataArrayDouble::addEqual(const DataArrayDouble *other)
+void DataArrayDouble::addEqual(const DataArrayDouble *other) throw(INTERP_KERNEL::Exception)
 {
   int nbOfComp=getNumberOfComponents();
   if(nbOfComp!=other->getNumberOfComponents())
@@ -159,7 +884,7 @@ void DataArrayDouble::addEqual(const DataArrayDouble *other)
   declareAsNew();
 }
 
-DataArrayDouble *DataArrayDouble::substract(const DataArrayDouble *a1, const DataArrayDouble *a2)
+DataArrayDouble *DataArrayDouble::substract(const DataArrayDouble *a1, const DataArrayDouble *a2) throw(INTERP_KERNEL::Exception)
 {
   int nbOfComp=a1->getNumberOfComponents();
   if(nbOfComp!=a2->getNumberOfComponents())
@@ -174,7 +899,7 @@ DataArrayDouble *DataArrayDouble::substract(const DataArrayDouble *a1, const Dat
   return ret;
 }
 
-void DataArrayDouble::substractEqual(const DataArrayDouble *other)
+void DataArrayDouble::substractEqual(const DataArrayDouble *other) throw(INTERP_KERNEL::Exception)
 {
   int nbOfComp=getNumberOfComponents();
   if(nbOfComp!=other->getNumberOfComponents())
@@ -186,7 +911,7 @@ void DataArrayDouble::substractEqual(const DataArrayDouble *other)
   declareAsNew();
 }
 
-DataArrayDouble *DataArrayDouble::multiply(const DataArrayDouble *a1, const DataArrayDouble *a2)
+DataArrayDouble *DataArrayDouble::multiply(const DataArrayDouble *a1, const DataArrayDouble *a2) throw(INTERP_KERNEL::Exception)
 {
   int nbOfTuple=a1->getNumberOfTuples();
   int nbOfTuple2=a2->getNumberOfTuples();
@@ -233,7 +958,7 @@ DataArrayDouble *DataArrayDouble::multiply(const DataArrayDouble *a1, const Data
   return ret;
 }
 
-void DataArrayDouble::multiplyEqual(const DataArrayDouble *other)
+void DataArrayDouble::multiplyEqual(const DataArrayDouble *other) throw(INTERP_KERNEL::Exception)
 {
   int nbOfTuple=getNumberOfTuples();
   int nbOfTuple2=other->getNumberOfTuples();
@@ -241,11 +966,8 @@ void DataArrayDouble::multiplyEqual(const DataArrayDouble *other)
   int nbOfComp2=other->getNumberOfComponents();
   if(nbOfTuple!=nbOfTuple2)
     throw INTERP_KERNEL::Exception("Nb of tuples mismatch for array multiplyEqual !");
-  DataArrayDouble *ret=0;
   if(nbOfComp==nbOfComp2)
     {
-      ret=DataArrayDouble::New();
-      ret->alloc(nbOfTuple,nbOfComp);
       std::transform(getConstPointer(),getConstPointer()+nbOfTuple*nbOfComp,other->getConstPointer(),getPointer(),std::multiplies<double>());
     }
   else
@@ -263,7 +985,7 @@ void DataArrayDouble::multiplyEqual(const DataArrayDouble *other)
   declareAsNew();
 }
 
-DataArrayDouble *DataArrayDouble::divide(const DataArrayDouble *a1, const DataArrayDouble *a2)
+DataArrayDouble *DataArrayDouble::divide(const DataArrayDouble *a1, const DataArrayDouble *a2) throw(INTERP_KERNEL::Exception)
 {
   int nbOfComp=a1->getNumberOfComponents();
   if(nbOfComp!=a2->getNumberOfComponents())
@@ -278,7 +1000,7 @@ DataArrayDouble *DataArrayDouble::divide(const DataArrayDouble *a1, const DataAr
   return ret;
 }
 
-void DataArrayDouble::divideEqual(const DataArrayDouble *other)
+void DataArrayDouble::divideEqual(const DataArrayDouble *other) throw(INTERP_KERNEL::Exception)
 {
   int nbOfComp=getNumberOfComponents();
   if(nbOfComp!=other->getNumberOfComponents())
@@ -319,6 +1041,75 @@ void DataArrayInt::alloc(int nbOfTuple, int nbOfCompo)
   declareAsNew();
 }
 
+void DataArrayInt::fillWithZero()
+{
+  _mem.fillWithValue(0);
+}
+
+std::string DataArrayInt::repr() const
+{
+  std::ostringstream ret;
+  reprStream(ret);
+  return ret.str();
+}
+
+std::string DataArrayInt::reprZip() const
+{
+  std::ostringstream ret;
+  reprZipStream(ret);
+  return ret.str();
+}
+
+void DataArrayInt::reprStream(std::ostream& stream) const
+{
+  stream << "Name of int array : \"" << _name << "\"\n";
+  reprWithoutNameStream(stream);
+}
+
+void DataArrayInt::reprZipStream(std::ostream& stream) const
+{
+  stream << "Name of int array : \"" << _name << "\"\n";
+  reprZipWithoutNameStream(stream);
+}
+
+void DataArrayInt::reprWithoutNameStream(std::ostream& stream) const
+{
+  DataArray::reprWithoutNameStream(stream);
+  _mem.repr(getNumberOfComponents(),stream);
+}
+
+void DataArrayInt::reprZipWithoutNameStream(std::ostream& stream) const
+{
+  DataArray::reprWithoutNameStream(stream);
+  _mem.reprZip(getNumberOfComponents(),stream);
+}
+
+void DataArrayInt::transformWithIndArr(const int *indArr)
+{
+  if(getNumberOfComponents()!=1)
+    throw INTERP_KERNEL::Exception("Call transformWithIndArr method on DataArrayInt with only one component !");
+  int nbOfTuples=getNumberOfTuples();
+  int *pt=getPointer();
+  for(int i=0;i<nbOfTuples;i++)
+    pt[i]=indArr[pt[i]];
+}
+
+/*!
+ * This method invert array 'di' that is a conversion map from Old to New node numbering to New to Old node numbering.
+ */
+DataArrayInt *DataArrayInt::invertArrayO2N2N2O(int newNbOfElem) const
+{
+  DataArrayInt *ret=DataArrayInt::New();
+  ret->alloc(newNbOfElem,1);
+  int nbOfOldNodes=getNumberOfTuples();
+  const int *old2New=getConstPointer();
+  int *pt=ret->getPointer();
+  for(int i=0;i!=nbOfOldNodes;i++)
+    if(old2New[i]!=-1)
+      pt[old2New[i]]=i;
+  return ret;
+}
+
 bool DataArrayInt::isEqual(const DataArrayInt& other) const
 {
   if(!areInfoEquals(other))
@@ -326,6 +1117,11 @@ bool DataArrayInt::isEqual(const DataArrayInt& other) const
   return _mem.isEqual(other._mem,0);
 }
 
+bool DataArrayInt::isEqualWithoutConsideringStr(const DataArrayInt& other) const
+{
+  return _mem.isEqual(other._mem,0);
+}
+
 void DataArrayInt::useArray(const int *array, bool ownership,  DeallocType type, int nbOfTuple, int nbOfCompo)
 {
   _nb_of_tuples=nbOfTuple;
@@ -334,6 +1130,137 @@ void DataArrayInt::useArray(const int *array, bool ownership,  DeallocType type,
   declareAsNew();
 }
 
+void DataArrayInt::renumberInPlace(const int *old2New)
+{
+  int nbTuples=getNumberOfTuples();
+  int nbOfCompo=getNumberOfComponents();
+  int *tmp=new int[nbTuples*nbOfCompo];
+  const int *iptr=getConstPointer();
+  for(int i=0;i<nbTuples;i++)
+    std::copy(iptr+nbOfCompo*i,iptr+nbOfCompo*(i+1),tmp+nbOfCompo*old2New[i]);
+  std::copy(tmp,tmp+nbTuples*nbOfCompo,getPointer());
+  delete [] tmp;
+  declareAsNew();
+}
+
+DataArrayInt *DataArrayInt::renumber(const int *old2New) const
+{
+  int nbTuples=getNumberOfTuples();
+  int nbOfCompo=getNumberOfComponents();
+  DataArrayInt *ret=DataArrayInt::New();
+  ret->alloc(nbTuples,nbOfCompo);
+  ret->copyStringInfoFrom(*this);
+  const int *iptr=getConstPointer();
+  int *optr=ret->getPointer();
+  for(int i=0;i<nbTuples;i++)
+    std::copy(iptr+nbOfCompo*i,iptr+nbOfCompo*(i+1),optr+nbOfCompo*old2New[i]);
+  return ret;
+}
+
+/*!
+ * This method checks that 'this' is with numberofcomponents == 1 and that it is equal to
+ * stdext::iota() of size getNumberOfTuples. This method is particalary usefull for DataArrayInt instances
+ * that represents a renumbering array to check the real need in renumbering. 
+ */
+bool DataArrayInt::isIdentity() const
+{
+  if(getNumberOfComponents()!=1)
+    return false;
+  int nbOfTuples=getNumberOfTuples();
+  const int *pt=getConstPointer();
+  for(int i=0;i<nbOfTuples;i++,pt++)
+    if(*pt!=i)
+      return false;
+  return true;
+}
+
+DataArrayDouble *DataArrayInt::convertToDblArr() const
+{
+  DataArrayDouble *ret=DataArrayDouble::New();
+  ret->alloc(getNumberOfTuples(),getNumberOfComponents());
+  int nbOfVals=getNbOfElems();
+  const int *src=getConstPointer();
+  double *dest=ret->getPointer();
+  std::copy(src,src+nbOfVals,dest);
+  ret->copyStringInfoFrom(*this);
+  return ret;
+}
+
+/*!
+ * This methods has a similar behaviour than std::string::substr. This method returns a newly created DataArrayInt that is part of this with same number of components.
+ * The intervall is specified by [tupleIdBg,tupleIdEnd) except if tupleIdEnd ==-1 in this case the [tupleIdBg,this->end()) will be kept.
+ * This method check that interval is valid regarding this, if not an exception will be thrown.
+ */
+DataArrayInt *DataArrayInt::substr(int tupleIdBg, int tupleIdEnd) const throw(INTERP_KERNEL::Exception)
+{
+  int nbt=getNumberOfTuples();
+  if(tupleIdBg<0)
+    throw INTERP_KERNEL::Exception("DataArrayInt::substr : The tupleIdBg parameter must be greater than 0 !");
+  if(tupleIdBg>=nbt)
+    throw INTERP_KERNEL::Exception("DataArrayInt::substr : The tupleIdBg parameter is greater or equal than number of tuples !");
+  int trueEnd=tupleIdEnd;
+  if(tupleIdEnd!=-1)
+    {
+      if(tupleIdEnd>nbt)
+        throw INTERP_KERNEL::Exception("DataArrayInt::substr : The tupleIdBg parameter is greater or equal than number of tuples !");
+    }
+  else
+    trueEnd=nbt;
+  int nbComp=getNumberOfComponents();
+  DataArrayInt *ret=DataArrayInt::New();
+  ret->alloc(trueEnd-tupleIdBg,nbComp);
+  ret->copyStringInfoFrom(*this);
+  std::copy(getConstPointer()+tupleIdBg*nbComp,getConstPointer()+trueEnd*nbComp,ret->getPointer());
+  return ret;
+}
+
+/*!
+ * This method builds a new instance of DataArrayInt (to deal with) that is reduction or an extension of 'this'.
+ * if 'newNbOfComp' < this->getNumberOfComponents() a reduction is done and for each tuple 'newNbOfComp' first components are kept.
+ * If 'newNbOfComp' > this->getNumberOfComponents() an extension is done, and for each components i such that i > getNumberOfComponents() 'dftValue' parameter is taken.
+ */
+DataArrayInt *DataArrayInt::changeNbOfComponents(int newNbOfComp, int dftValue) const throw(INTERP_KERNEL::Exception)
+{
+  DataArrayInt *ret=DataArrayInt::New();
+  ret->alloc(getNumberOfTuples(),newNbOfComp);
+  const int *oldc=getConstPointer();
+  int *nc=ret->getPointer();
+  int nbOfTuples=getNumberOfTuples();
+  int oldNbOfComp=getNumberOfComponents();
+  int dim=std::min(oldNbOfComp,newNbOfComp);
+  for(int i=0;i<nbOfTuples;i++)
+    {
+      int j=0;
+      for(;j<dim;j++)
+        nc[newNbOfComp*i+j]=oldc[i*oldNbOfComp+j];
+      for(;j<newNbOfComp;j++)
+        nc[newNbOfComp*i+j]=dftValue;
+    }
+  ret->setName(getName().c_str());
+  for(int i=0;i<dim;i++)
+    ret->setInfoOnComponent(i,getInfoOnComponent(i).c_str());
+  ret->setName(getName().c_str());
+  return ret;
+}
+
+
+/*!
+ * This method is a generalization of DataArrayDouble::substr method because a not contigous range can be specified here.
+ */
+DataArrayInt *DataArrayInt::selectByTupleId(const int *start, const int *end) const
+{
+  DataArrayInt *ret=DataArrayInt::New();
+  int nbComp=getNumberOfComponents();
+  ret->alloc(std::distance(start,end),nbComp);
+  ret->copyStringInfoFrom(*this);
+  int *pt=ret->getPointer();
+  const int *srcPt=getConstPointer();
+  int i=0;
+  for(const int *w=start;w!=end;w++,i++)
+    std::copy(srcPt+(*w)*nbComp,srcPt+((*w)+1)*nbComp,pt+i*nbComp);
+  return ret;
+}
+
 void DataArrayInt::reAlloc(int nbOfTuples)
 {
   _mem.reAlloc(_info_on_compo.size()*nbOfTuples);
@@ -368,6 +1295,57 @@ DataArrayInt *DataArrayInt::aggregate(const DataArrayInt *a1, const DataArrayInt
   return ret;
 }
 
+/*!
+ * This method create a minimal partition of groups 'groups' the std::iota array of size 'newNb'.
+ * This method returns an array of size 'newNb' that specifies for each item at which familyId it owns to, and this method returns
+ * for each group the familyId it contains. If an id so that id<newNb and that appears in no groups will appears with 0 in return array.
+ *
+ * @param groups in arrays specifying ids of each groups.
+ * @param newNb specifies size of whole set. Must be at least equal to max eltid in 'groups'.
+ * @return an array of size newNb specifying fid of each item.
+ */
+DataArrayInt *DataArrayInt::makePartition(const std::vector<DataArrayInt *>& groups, int newNb, std::vector< std::vector<int> >& fidsOfGroups)
+{
+  DataArrayInt *ret=DataArrayInt::New();
+  ret->alloc(newNb,1);
+  int *retPtr=ret->getPointer();
+  std::fill(retPtr,retPtr+newNb,0);
+  int fid=1;
+  for(std::vector<DataArrayInt *>::const_iterator iter=groups.begin();iter!=groups.end();iter++)
+    {
+      const int *ptr=(*iter)->getConstPointer();
+      int nbOfElem=(*iter)->getNbOfElems();
+      int sfid=fid;
+      for(int j=0;j<sfid;j++)
+        {
+          bool found=false;
+          for(int i=0;i<nbOfElem;i++)
+            {
+              if(retPtr[ptr[i]]==j)
+                {
+                  retPtr[ptr[i]]=fid;
+                  found=true;
+                }
+            }
+          if(found)
+            fid++;
+        }
+    }
+  fidsOfGroups.clear();
+  fidsOfGroups.resize(groups.size());
+  int grId=0;
+  for(std::vector<DataArrayInt *>::const_iterator iter=groups.begin();iter!=groups.end();iter++,grId++)
+    {
+      std::set<int> tmp;
+      const int *ptr=(*iter)->getConstPointer();
+      int nbOfElem=(*iter)->getNbOfElems();
+      for(const int *p=ptr;p!=ptr+nbOfElem;p++)
+        tmp.insert(retPtr[*p]);
+      fidsOfGroups[grId].insert(fidsOfGroups[grId].end(),tmp.begin(),tmp.end());
+    }
+  return ret;
+}
+
 int *DataArrayInt::checkAndPreparePermutation(const int *start, const int *end)
 {
   int sz=std::distance(start,end);
index 74d165bb983217cc4e79a560adde2997c6546021..33b8896b6fb677fee7adc600300c38177675b59a 100644 (file)
@@ -27,6 +27,7 @@
 
 #include <string>
 #include <vector>
+#include <iterator>
 
 namespace ParaMEDMEM
 {
@@ -60,6 +61,9 @@ namespace ParaMEDMEM
     T operator[](int id) const { return _pointer.getConstPointer()[id]; }
     T& operator[](int id) { return _pointer.getPointer()[id]; }
     bool isEqual(const MemArray<T>& other, T prec) const;
+    void repr(int sl, std::ostream& stream) const;
+    void reprZip(int sl, std::ostream& stream) const;
+    void fillWithValue(const T& val);
     void alloc(int nbOfElements);
     void reAlloc(int newNbOfElements);
     void useArray(const T *array, bool ownership, DeallocType type, int nbOfElem);
@@ -72,7 +76,6 @@ namespace ParaMEDMEM
     int _nb_of_elem;
     bool _ownership;
     MEDCouplingPointer<T> _pointer;
-    //T *_pointer;
     DeallocType _dealloc;
   };
 
@@ -82,9 +85,11 @@ namespace ParaMEDMEM
     MEDCOUPLING_EXPORT void setName(const char *name);
     MEDCOUPLING_EXPORT void copyStringInfoFrom(const DataArray& other) throw(INTERP_KERNEL::Exception);
     MEDCOUPLING_EXPORT bool areInfoEquals(const DataArray& other) const;
+    MEDCOUPLING_EXPORT void reprWithoutNameStream(std::ostream& stream) const;
     MEDCOUPLING_EXPORT std::string getName() const { return _name; }
-    MEDCOUPLING_EXPORT std::string getInfoOnComponent(int i) const { return _info_on_compo[i]; }
-    MEDCOUPLING_EXPORT void setInfoOnComponent(int i, const char *info) { _info_on_compo[i]=info; }
+    MEDCOUPLING_EXPORT const std::vector<std::string> &getInfoOnComponent() const { return _info_on_compo; }
+    MEDCOUPLING_EXPORT std::string getInfoOnComponent(int i) const throw(INTERP_KERNEL::Exception);
+    MEDCOUPLING_EXPORT void setInfoOnComponent(int i, const char *info) throw(INTERP_KERNEL::Exception);
     MEDCOUPLING_EXPORT int getNumberOfComponents() const { return _info_on_compo.size(); }
     MEDCOUPLING_EXPORT int getNumberOfTuples() const { return _nb_of_tuples; }
     MEDCOUPLING_EXPORT int getNbOfElems() const { return _info_on_compo.size()*_nb_of_tuples; }
@@ -101,6 +106,7 @@ namespace ParaMEDMEM
 
 namespace ParaMEDMEM
 {
+  class DataArrayInt;
   class DataArrayDouble : public DataArray
   {
   public:
@@ -108,27 +114,67 @@ namespace ParaMEDMEM
     MEDCOUPLING_EXPORT DataArrayDouble *deepCopy() const;
     MEDCOUPLING_EXPORT DataArrayDouble *performCpy(bool deepCpy) const;
     MEDCOUPLING_EXPORT void alloc(int nbOfTuple, int nbOfCompo);
+    MEDCOUPLING_EXPORT void fillWithZero();
+    MEDCOUPLING_EXPORT std::string repr() const;
+    MEDCOUPLING_EXPORT std::string reprZip() const;
+    MEDCOUPLING_EXPORT void reprStream(std::ostream& stream) const;
+    MEDCOUPLING_EXPORT void reprZipStream(std::ostream& stream) const;
+    MEDCOUPLING_EXPORT void reprWithoutNameStream(std::ostream& stream) const;
+    MEDCOUPLING_EXPORT void reprZipWithoutNameStream(std::ostream& stream) const;
     MEDCOUPLING_EXPORT bool isEqual(const DataArrayDouble& other, double prec) const;
+    MEDCOUPLING_EXPORT bool isEqualWithoutConsideringStr(const DataArrayDouble& other, double prec) const;
     //!alloc or useArray should have been called before.
     MEDCOUPLING_EXPORT void reAlloc(int nbOfTuples);
+    MEDCOUPLING_EXPORT DataArrayInt *convertToIntArr() const;
+    MEDCOUPLING_EXPORT void renumberInPlace(const int *old2New);
+    MEDCOUPLING_EXPORT DataArrayDouble *renumber(const int *old2New) const;
+    MEDCOUPLING_EXPORT DataArrayDouble *substr(int tupleIdBg, int tupleIdEnd=-1) const throw(INTERP_KERNEL::Exception);
+    MEDCOUPLING_EXPORT DataArrayDouble *changeNbOfComponents(int newNbOfComp, double dftValue) const throw(INTERP_KERNEL::Exception);
+    MEDCOUPLING_EXPORT DataArrayDouble *selectByTupleId(const int *start, const int *end) const;
     MEDCOUPLING_EXPORT void getTuple(int tupleId, double *res) const { std::copy(_mem.getConstPointerLoc(tupleId*_info_on_compo.size()),_mem.getConstPointerLoc((tupleId+1)*_info_on_compo.size()),res); }
     MEDCOUPLING_EXPORT double getIJ(int tupleId, int compoId) const { return _mem[tupleId*_info_on_compo.size()+compoId]; }
-    MEDCOUPLING_EXPORT void setIJ(int tupleId, int compoId, double newVal) { _mem[tupleId*_info_on_compo.size()+compoId]=newVal; }
+    MEDCOUPLING_EXPORT void setIJ(int tupleId, int compoId, double newVal) { _mem[tupleId*_info_on_compo.size()+compoId]=newVal; declareAsNew(); }
     MEDCOUPLING_EXPORT double *getPointer() const { return _mem.getPointer(); }
     MEDCOUPLING_EXPORT static void setArrayIn(DataArrayDouble *newArray, DataArrayDouble* &arrayToSet);
     MEDCOUPLING_EXPORT const double *getConstPointer() const { return _mem.getConstPointer(); }
     MEDCOUPLING_EXPORT void useArray(const double *array, bool ownership, DeallocType type, int nbOfTuple, int nbOfCompo);
     MEDCOUPLING_EXPORT void writeOnPlace(int id, double element0, const double *others, int sizeOfOthers) { _mem.writeOnPlace(id,element0,others,sizeOfOthers); }
     MEDCOUPLING_EXPORT void checkNoNullValues() const throw(INTERP_KERNEL::Exception);
-    MEDCOUPLING_EXPORT static DataArrayDouble *aggregate(const DataArrayDouble *a1, const DataArrayDouble *a2);
-    MEDCOUPLING_EXPORT static DataArrayDouble *add(const DataArrayDouble *a1, const DataArrayDouble *a2);
-    MEDCOUPLING_EXPORT void addEqual(const DataArrayDouble *other);
-    MEDCOUPLING_EXPORT static DataArrayDouble *substract(const DataArrayDouble *a1, const DataArrayDouble *a2);
-    MEDCOUPLING_EXPORT void substractEqual(const DataArrayDouble *other);
-    MEDCOUPLING_EXPORT static DataArrayDouble *multiply(const DataArrayDouble *a1, const DataArrayDouble *a2);
-    MEDCOUPLING_EXPORT void multiplyEqual(const DataArrayDouble *other);
-    MEDCOUPLING_EXPORT static DataArrayDouble *divide(const DataArrayDouble *a1, const DataArrayDouble *a2);
-    MEDCOUPLING_EXPORT void divideEqual(const DataArrayDouble *other);
+    MEDCOUPLING_EXPORT double getMaxValue(int& tupleId) const throw(INTERP_KERNEL::Exception);
+    MEDCOUPLING_EXPORT double getMinValue(int& tupleId) const throw(INTERP_KERNEL::Exception);
+    MEDCOUPLING_EXPORT double getAverageValue() const throw(INTERP_KERNEL::Exception);
+    MEDCOUPLING_EXPORT void accumulate(double *res) const;
+    MEDCOUPLING_EXPORT double accumulate(int compId) const;
+    MEDCOUPLING_EXPORT DataArrayDouble *doublyContractedProduct() const throw(INTERP_KERNEL::Exception);
+    MEDCOUPLING_EXPORT DataArrayDouble *determinant() const throw(INTERP_KERNEL::Exception);
+    MEDCOUPLING_EXPORT DataArrayDouble *eigenValues() const throw(INTERP_KERNEL::Exception);
+    MEDCOUPLING_EXPORT DataArrayDouble *eigenVectors() const throw(INTERP_KERNEL::Exception);
+    MEDCOUPLING_EXPORT DataArrayDouble *inverse() const throw(INTERP_KERNEL::Exception);
+    MEDCOUPLING_EXPORT DataArrayDouble *trace() const throw(INTERP_KERNEL::Exception);
+    MEDCOUPLING_EXPORT DataArrayDouble *deviator() const throw(INTERP_KERNEL::Exception);
+    MEDCOUPLING_EXPORT DataArrayDouble *magnitude() const throw(INTERP_KERNEL::Exception);
+    MEDCOUPLING_EXPORT DataArrayDouble *maxPerTuple() const throw(INTERP_KERNEL::Exception);
+    MEDCOUPLING_EXPORT void sortPerTuple(bool asc) throw(INTERP_KERNEL::Exception);
+    MEDCOUPLING_EXPORT void applyLin(double a, double b, int compoId);
+    MEDCOUPLING_EXPORT DataArrayDouble *applyFunc(int nbOfComp, FunctionToEvaluate func) const throw(INTERP_KERNEL::Exception);
+    MEDCOUPLING_EXPORT DataArrayDouble *applyFunc(int nbOfComp, const char *func) const throw(INTERP_KERNEL::Exception);
+    MEDCOUPLING_EXPORT DataArrayDouble *applyFunc(const char *func) const throw(INTERP_KERNEL::Exception);
+    MEDCOUPLING_EXPORT void applyFuncFast32(const char *func);
+    MEDCOUPLING_EXPORT void applyFuncFast64(const char *func);
+    MEDCOUPLING_EXPORT DataArrayInt *getIdsInRange(double vmin, double vmax) const throw(INTERP_KERNEL::Exception);
+    MEDCOUPLING_EXPORT static DataArrayDouble *aggregate(const DataArrayDouble *a1, const DataArrayDouble *a2) throw(INTERP_KERNEL::Exception);
+    MEDCOUPLING_EXPORT static DataArrayDouble *dot(const DataArrayDouble *a1, const DataArrayDouble *a2) throw(INTERP_KERNEL::Exception);
+    MEDCOUPLING_EXPORT static DataArrayDouble *crossProduct(const DataArrayDouble *a1, const DataArrayDouble *a2) throw(INTERP_KERNEL::Exception);
+    MEDCOUPLING_EXPORT static DataArrayDouble *max(const DataArrayDouble *a1, const DataArrayDouble *a2) throw(INTERP_KERNEL::Exception);
+    MEDCOUPLING_EXPORT static DataArrayDouble *min(const DataArrayDouble *a1, const DataArrayDouble *a2) throw(INTERP_KERNEL::Exception);
+    MEDCOUPLING_EXPORT static DataArrayDouble *add(const DataArrayDouble *a1, const DataArrayDouble *a2) throw(INTERP_KERNEL::Exception);
+    MEDCOUPLING_EXPORT void addEqual(const DataArrayDouble *other) throw(INTERP_KERNEL::Exception);
+    MEDCOUPLING_EXPORT static DataArrayDouble *substract(const DataArrayDouble *a1, const DataArrayDouble *a2) throw(INTERP_KERNEL::Exception);
+    MEDCOUPLING_EXPORT void substractEqual(const DataArrayDouble *other) throw(INTERP_KERNEL::Exception);
+    MEDCOUPLING_EXPORT static DataArrayDouble *multiply(const DataArrayDouble *a1, const DataArrayDouble *a2) throw(INTERP_KERNEL::Exception);
+    MEDCOUPLING_EXPORT void multiplyEqual(const DataArrayDouble *other) throw(INTERP_KERNEL::Exception);
+    MEDCOUPLING_EXPORT static DataArrayDouble *divide(const DataArrayDouble *a1, const DataArrayDouble *a2) throw(INTERP_KERNEL::Exception);
+    MEDCOUPLING_EXPORT void divideEqual(const DataArrayDouble *other) throw(INTERP_KERNEL::Exception);
     //! nothing to do here because this class does not aggregate any TimeLabel instance.
     MEDCOUPLING_EXPORT void updateTime() { }
   private:
@@ -145,8 +191,25 @@ namespace ParaMEDMEM
     MEDCOUPLING_EXPORT DataArrayInt *performCpy(bool deepCpy) const;
     MEDCOUPLING_EXPORT void alloc(int nbOfTuple, int nbOfCompo);
     MEDCOUPLING_EXPORT bool isEqual(const DataArrayInt& other) const;
+    MEDCOUPLING_EXPORT bool isEqualWithoutConsideringStr(const DataArrayInt& other) const;
+    MEDCOUPLING_EXPORT void fillWithZero();
+    MEDCOUPLING_EXPORT std::string repr() const;
+    MEDCOUPLING_EXPORT std::string reprZip() const;
+    MEDCOUPLING_EXPORT void reprStream(std::ostream& stream) const;
+    MEDCOUPLING_EXPORT void reprZipStream(std::ostream& stream) const;
+    MEDCOUPLING_EXPORT void reprWithoutNameStream(std::ostream& stream) const;
+    MEDCOUPLING_EXPORT void reprZipWithoutNameStream(std::ostream& stream) const;
+    MEDCOUPLING_EXPORT void transformWithIndArr(const int *indArr);
+    MEDCOUPLING_EXPORT DataArrayInt *invertArrayO2N2N2O(int newNbOfElem) const;
     //!alloc or useArray should have been called before.
     MEDCOUPLING_EXPORT void reAlloc(int nbOfTuples);
+    MEDCOUPLING_EXPORT DataArrayDouble *convertToDblArr() const;
+    MEDCOUPLING_EXPORT void renumberInPlace(const int *old2New);
+    MEDCOUPLING_EXPORT DataArrayInt *renumber(const int *old2New) const;
+    MEDCOUPLING_EXPORT bool isIdentity() const;
+    MEDCOUPLING_EXPORT DataArrayInt *substr(int tupleIdBg, int tupleIdEnd=-1) const throw(INTERP_KERNEL::Exception);
+    MEDCOUPLING_EXPORT DataArrayInt *changeNbOfComponents(int newNbOfComp, int dftValue) const throw(INTERP_KERNEL::Exception);
+    MEDCOUPLING_EXPORT DataArrayInt *selectByTupleId(const int *start, const int *end) const;
     MEDCOUPLING_EXPORT void getTuple(int tupleId, int *res) const { std::copy(_mem.getConstPointerLoc(tupleId*_info_on_compo.size()),_mem.getConstPointerLoc((tupleId+1)*_info_on_compo.size()),res); }
     MEDCOUPLING_EXPORT int getIJ(int tupleId, int compoId) const { return _mem[tupleId*_info_on_compo.size()+compoId]; }
     MEDCOUPLING_EXPORT void setIJ(int tupleId, int compoId, int newVal) { _mem[tupleId*_info_on_compo.size()+compoId]=newVal; }
@@ -154,6 +217,7 @@ namespace ParaMEDMEM
     MEDCOUPLING_EXPORT static void setArrayIn(DataArrayInt *newArray, DataArrayInt* &arrayToSet);
     MEDCOUPLING_EXPORT const int *getConstPointer() const { return _mem.getConstPointer(); }
     MEDCOUPLING_EXPORT static DataArrayInt *aggregate(const DataArrayInt *a1, const DataArrayInt *a2, int offsetA2);
+    MEDCOUPLING_EXPORT static DataArrayInt *makePartition(const std::vector<DataArrayInt *>& groups, int newNb, std::vector< std::vector<int> >& fidsOfGroups);
     MEDCOUPLING_EXPORT void useArray(const int *array, bool ownership, DeallocType type, int nbOfTuple, int nbOfCompo);
     MEDCOUPLING_EXPORT void writeOnPlace(int id, int element0, const int *others, int sizeOfOthers) { _mem.writeOnPlace(id,element0,others,sizeOfOthers); }
     //! nothing to do here because this class does not aggregate any TimeLabel instance.
index 476f147aeb1d505f42160008474826792ca3bf47..5a1a048d553304d659ae378bf2870fa0b0dcf828 100644 (file)
@@ -87,11 +87,99 @@ namespace ParaMEDMEM
       return true;
     if(pt1==0 || pt2==0)
       return false;
+    if(pt1==pt2)
+      return true;
     for(int i=0;i<_nb_of_elem;i++)
       if(pt1[i]-pt2[i]<-prec || (pt1[i]-pt2[i])>prec)
         return false;
     return true;
   }
+  
+  /*!
+   * @param sl is typically the number of components [in parameter]
+   */
+  template<class T>
+  void MemArray<T>::repr(int sl, std::ostream& stream) const
+  {
+    stream << "Number of tuples : ";
+    if(!_pointer.isNull())
+      {
+        if(sl!=0)
+          stream << _nb_of_elem/sl;
+        else
+          stream << "Empty Data";
+      }
+    else
+      stream << "No data";
+    stream << "\n";
+    stream << "Data content :\n";
+    const T *data=getConstPointer();
+    if(!_pointer.isNull())
+      {
+        if(_nb_of_elem!=0 && sl!=0)
+          {
+            int nbOfTuples=_nb_of_elem/sl;
+            for(int i=0;i<nbOfTuples;i++)
+              {
+                stream << "Tuple #" << i << " : ";
+                std::copy(data,data+sl,std::ostream_iterator<T>(stream," "));
+                stream << "\n";
+                data+=sl;
+              }
+          }
+        else
+          stream << "Empty Data\n";
+      }
+    else
+      stream << "No data !\n";
+  }
+  
+  /*!
+   * @param sl is typically the number of components [in parameter]
+   */
+  template<class T>
+  void MemArray<T>::reprZip(int sl, std::ostream& stream) const
+  {
+    stream << "Number of tuples : ";
+    if(!_pointer.isNull())
+      {
+        if(sl!=0)
+          stream << _nb_of_elem/sl;
+        else
+          stream << "Empty Data";
+      }
+    else
+      stream << "No data";
+    stream << "\n";
+    stream << "Data content : ";
+    const T *data=getConstPointer();
+    if(!_pointer.isNull())
+      {
+        if(_nb_of_elem!=0 && sl!=0)
+          {
+            int nbOfTuples=_nb_of_elem/sl;
+            for(int i=0;i<nbOfTuples;i++)
+              {
+                stream << "|";
+                std::copy(data,data+sl,std::ostream_iterator<T>(stream," "));
+                stream << "| ";
+                data+=sl;
+              }
+            stream << "\n";
+          }
+        else
+          stream << "Empty Data\n";
+      }
+    else
+      stream << "No data !\n";
+  }
+  
+  template<class T>
+  void MemArray<T>::fillWithValue(const T& val)
+  {
+    T *pt=_pointer.getPointer();
+    std::fill(pt,pt+_nb_of_elem,val);
+  }
 
   template<class T>
   void MemArray<T>::alloc(int nbOfElements)
index a552ea588b192af4eede092d06f7252abb197a90..1f60dc66955d525b1664364cacde76a44225edd6 100644 (file)
 
 using namespace ParaMEDMEM;
 
-bool MEDCouplingMesh::areCompatible(const MEDCouplingMesh *other) const
+/*!
+ * This method is only for ParaMEDMEM in ParaFIELD constructor.
+ */
+bool MEDCouplingMesh::isStructured() const
+{
+  return getType()==CARTESIAN;
+}
+
+bool MEDCouplingMesh::isEqual(const MEDCouplingMesh *other, double prec) const
+{
+  return _name==other->_name;
+}
+
+/*!
+ * This method checks geo equivalence between two meshes : 'this' and 'other'.
+ * If no exception is throw 'this' and 'other' are geometrically equivalent regarding 'levOfCheck' level.
+ * This method is typically used to change the mesh of a field "safely" depending the 'levOfCheck' level considered.
+ * 
+ * @param levOfCheck input that specifies the level of check specified. The possible values are listed below.
+ * @param prec input that specifies precision for double float data used for comparison in meshes.
+ * @param cellCor output array not always informed (depending 'levOfCheck' param) that gives the corresponding array for cells from 'other' to 'this'.
+ * @param nodeCor output array not always informed (depending 'levOfCheck' param) that gives the corresponding array for nodes from 'other' to 'this'.
+ *
+ * Possible values for levOfCheck :
+ *   - 0 for strict equality. This is the strongest level. 'cellCor' and 'nodeCor' params are never informed.
+ *   - 10,11,12 for less strict equality. Two meshes are compared geometrically. In case of success 'cellCor' and 'nodeCor' are informed. Warning ! These equivalences are CPU/Mem costly. The 3 values correspond respectively to policy used for cell comparison (see MEDCouplingUMesh::zipConnectivityTraducer to have more details)
+ *   - 20,21,22, for less strict equality. Two meshes are compared geometrically. The difference with the previous version is that nodes(coordinates) are expected to be the same between this and other. In case of success 'cellCor' is informed. Warning ! These equivalences are CPU/Mem costly. The 3 values correspond respectively to policy used for cell comparison (see MEDCouplingUMesh::zipConnectivityTraducer to have more details)
+ *   - 1 for fast 'equality'. This is a lazy level. Just number of cells and number of nodes are considered here and 3 cells (begin,middle,end)
+ *   - 2 for deep 'equality' as 0 option except that no control is done on all strings in mesh.
+ */
+void MEDCouplingMesh::checkGeoEquivalWith(const MEDCouplingMesh *other, int levOfCheck, double prec,
+                                          DataArrayInt *&cellCor, DataArrayInt *&nodeCor) const throw(INTERP_KERNEL::Exception)
+{
+  cellCor=0;
+  nodeCor=0;
+  if(this==other)
+    return ;
+  switch(levOfCheck)
+    {
+    case 0:
+      {
+        if(!isEqual(other,prec))
+          throw INTERP_KERNEL::Exception("checkGeoFitWith : Meshes are not equal !");
+        return ;
+      }
+    case 10:
+    case 11:
+    case 12:
+      {
+        checkDeepEquivalWith(other,levOfCheck-10,prec,cellCor,nodeCor);
+        return ;
+      }
+    case 20:
+    case 21:
+    case 22:
+      {
+        checkDeepEquivalOnSameNodesWith(other,levOfCheck-20,prec,cellCor);
+        return ;
+      }
+    case 1:
+      {
+        checkFastEquivalWith(other,prec);
+        return;
+      }
+    case 2:
+      {
+        if(!isEqualWithoutConsideringStr(other,prec))
+          throw INTERP_KERNEL::Exception("checkGeoFitWith : Meshes are not equal without considering strings !");
+        return ;
+      }
+    default:
+      throw INTERP_KERNEL::Exception("checkGeoFitWith : Invalid levOfCheck specified ! Value must be in 0,1,2,10,11 or 12.");
+    }
+}
+
+/*!
+ * Given a nodeIds range ['partBg','partEnd'), this method returns the set of cell ids in ascendant order that are \b fully whose connectivity of
+ * these cells are fully included in the range. As a consequence the returned set of cell ids does not \b always fit the nodes in ['partBg','partEnd')
+ * This method returns the corresponding cells in a newly created array that the caller has the responsability.
+ */
+DataArrayInt *MEDCouplingMesh::getCellIdsFullyIncludedInNodeIds(const int *partBg, const int *partEnd) const
+{
+  std::vector<int> crest;
+  std::set<int> p(partBg,partEnd);
+  int nbOfCells=getNumberOfCells();
+  for(int i=0;i<nbOfCells;i++)
+    {
+      std::vector<int> conn;
+      getNodeIdsOfCell(i,conn);
+      bool cont=true;
+      for(std::vector<int>::const_iterator iter=conn.begin();iter!=conn.end() && cont;iter++)
+        if(p.find(*iter)==p.end())
+          cont=false;
+      if(cont)
+        crest.push_back(i);
+    }
+  DataArrayInt *ret=DataArrayInt::New();
+  ret->alloc(crest.size(),1);
+  std::copy(crest.begin(),crest.end(),ret->getPointer());
+  return ret;
+}
+
+/*!
+ * This method checks fastly that 'this' and 'other' are equal. All common checks are done here.
+ */
+void MEDCouplingMesh::checkFastEquivalWith(const MEDCouplingMesh *other, double prec) const throw(INTERP_KERNEL::Exception)
+{
+  if(getMeshDimension()!=other->getMeshDimension())
+    throw INTERP_KERNEL::Exception("checkFastEquivalWith : Mesh dimensions are not equal !");
+  if(getSpaceDimension()!=other->getSpaceDimension())
+    throw INTERP_KERNEL::Exception("checkFastEquivalWith : Space dimensions are not equal !");
+  if(getNumberOfCells()!=other->getNumberOfCells())
+    throw INTERP_KERNEL::Exception("checkFastEquivalWith : number of cells are not equal !");
+}
+
+/*!
+ * This method is very poor and looks only if 'this' and 'other' are candidate for merge of fields lying repectively on them.
+ */
+bool MEDCouplingMesh::areCompatibleForMerge(const MEDCouplingMesh *other) const
 {
   if(getMeshDimension()!=other->getMeshDimension())
     return false;
@@ -80,6 +198,15 @@ MEDCouplingFieldDouble *MEDCouplingMesh::fillFromAnalytic(TypeOfField t, int nbO
   return ret;
 }
 
+/*!
+ * This method copyies all tiny strings from other (name and components name).
+ * @throw if other and this have not same mesh type.
+ */
+void MEDCouplingMesh::copyTinyStringsFrom(const MEDCouplingMesh *other) throw(INTERP_KERNEL::Exception)
+{
+  _name=other->_name;
+}
+
 /*!
  * This method builds a field lying on 'this' with 'nbOfComp' components.
  * 'func' is a string that is the expression to evaluate.
@@ -119,7 +246,7 @@ MEDCouplingFieldDouble *MEDCouplingMesh::fillFromAnalytic(TypeOfField t, int nbO
     {
       try
         {
-          expr.evaluateExpr(nbOfComp,ptToFill,locPtr+nbCompIn*i);
+          expr.evaluateExpr(nbOfComp,locPtr+nbCompIn*i,ptToFill);
         }
       catch(INTERP_KERNEL::Exception& e)
         {
index 8d11cd5731646207faeb8ca91a94007235d17dd2..3cdbe20a8f1a49acb05627846383e71955e5d224 100644 (file)
@@ -38,6 +38,7 @@ namespace ParaMEDMEM
       EXTRUDED = 8
     } MEDCouplingMeshType;
 
+  class DataArrayInt;
   class DataArrayDouble;
   class MEDCouplingFieldDouble;
 
@@ -46,19 +47,35 @@ namespace ParaMEDMEM
   public:
     void setName(const char *name) { _name=name; }
     const char *getName() const { return _name.c_str(); }
+    virtual MEDCouplingMesh *deepCpy() const = 0;
     virtual MEDCouplingMeshType getType() const = 0;
-    virtual bool isEqual(const MEDCouplingMesh *other, double prec) const { return _name==other->_name; }
+    bool isStructured() const;
+    virtual void copyTinyStringsFrom(const MEDCouplingMesh *other) throw(INTERP_KERNEL::Exception);
+    // comparison methods
+    virtual bool isEqual(const MEDCouplingMesh *other, double prec) const;
+    virtual bool isEqualWithoutConsideringStr(const MEDCouplingMesh *other, double prec) const = 0;
+    virtual void checkDeepEquivalWith(const MEDCouplingMesh *other, int cellCompPol, double prec,
+                                      DataArrayInt *&cellCor, DataArrayInt *&nodeCor) const throw(INTERP_KERNEL::Exception) = 0;
+    virtual void checkDeepEquivalOnSameNodesWith(const MEDCouplingMesh *other, int cellCompPol, double prec,
+                                                 DataArrayInt *&cellCor) const throw(INTERP_KERNEL::Exception) = 0;
+    virtual void checkFastEquivalWith(const MEDCouplingMesh *other, double prec) const throw(INTERP_KERNEL::Exception);
+    void checkGeoEquivalWith(const MEDCouplingMesh *other, int levOfCheck, double prec,
+                             DataArrayInt *&cellCor, DataArrayInt *&nodeCor) const throw(INTERP_KERNEL::Exception);
+    //
     virtual void checkCoherency() const throw(INTERP_KERNEL::Exception) = 0;
-    virtual bool isStructured() const = 0;
     virtual int getNumberOfCells() const = 0;
     virtual int getNumberOfNodes() const = 0;
     virtual int getSpaceDimension() const = 0;
     virtual int getMeshDimension() const = 0;
     virtual DataArrayDouble *getCoordinatesAndOwner() const = 0;
     virtual DataArrayDouble *getBarycenterAndOwner() const = 0;
+    virtual int getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType type) const = 0;
     virtual INTERP_KERNEL::NormalizedCellType getTypeOfCell(int cellId) const = 0;
     virtual void getNodeIdsOfCell(int cellId, std::vector<int>& conn) const = 0;
+    virtual DataArrayInt *getCellIdsFullyIncludedInNodeIds(const int *partBg, const int *partEnd) const;
     virtual void getCoordinatesOfNode(int nodeId, std::vector<double>& coo) const = 0;
+    virtual std::string simpleRepr() const = 0;
+    virtual std::string advancedRepr() const = 0;
     // tools
     virtual void getBoundingBox(double *bbox) const = 0;
     virtual MEDCouplingFieldDouble *getMeasureField(bool isAbs) const = 0;
@@ -69,9 +86,18 @@ namespace ParaMEDMEM
     virtual MEDCouplingFieldDouble *buildOrthogonalField() const = 0;
     virtual void rotate(const double *center, const double *vector, double angle) = 0;
     virtual void translate(const double *vector) = 0;
+    virtual void renumberCells(const int *old2NewBg, bool check) throw(INTERP_KERNEL::Exception) = 0;
     virtual MEDCouplingMesh *mergeMyselfWith(const MEDCouplingMesh *other) const = 0;
-    virtual bool areCompatible(const MEDCouplingMesh *other) const;
+    virtual MEDCouplingMesh *buildPart(const int *start, const int *end) const = 0;
+    virtual MEDCouplingMesh *buildPartAndReduceNodes(const int *start, const int *end, DataArrayInt*& arr) const = 0;
+    virtual bool areCompatibleForMerge(const MEDCouplingMesh *other) const;
     static MEDCouplingMesh *mergeMeshes(const MEDCouplingMesh *mesh1, const MEDCouplingMesh *mesh2);
+    //serialisation-unserialization
+    virtual void getTinySerializationInformation(std::vector<int>& tinyInfo, std::vector<std::string>& littleStrings) const = 0;
+    virtual void resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings) const = 0;
+    virtual void serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const = 0;
+    virtual void unserialization(const std::vector<int>& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2,
+                                 const std::vector<std::string>& littleStrings) = 0;
   protected:
     MEDCouplingMesh() { }
     MEDCouplingMesh(const MEDCouplingMesh& other):_name(other._name) { }
diff --git a/src/MEDCoupling/MEDCouplingNatureOfField.cxx b/src/MEDCoupling/MEDCouplingNatureOfField.cxx
new file mode 100644 (file)
index 0000000..7969909
--- /dev/null
@@ -0,0 +1,44 @@
+//  Copyright (C) 2007-2010  CEA/DEN, EDF R&D
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU Lesser General Public
+//  License as published by the Free Software Foundation; either
+//  version 2.1 of the License.
+//
+//  This library is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  Lesser General Public License for more details.
+//
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+//  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+#include "MEDCouplingNatureOfField.hxx"
+
+#include <algorithm>
+
+namespace ParaMEDMEM
+{
+  const char *MEDCouplingNatureOfField::REPR_OF_NATUREOFFIELD[NB_OF_POSSIBILITIES]=
+    { "NoNature",
+      "ConservativeVolumic",
+      "Integral",
+      "IntegralGlobConstraint",
+      "RevIntegral"};
+  
+  const int MEDCouplingNatureOfField::POS_OF_NATUREOFFIELD[NB_OF_POSSIBILITIES]={17,26,32,35,37};
+
+  const char *MEDCouplingNatureOfField::getRepr(NatureOfField nat) throw(INTERP_KERNEL::Exception)
+  {
+    const int *pos=std::find(POS_OF_NATUREOFFIELD,POS_OF_NATUREOFFIELD+NB_OF_POSSIBILITIES,(int)nat);
+    if(pos==POS_OF_NATUREOFFIELD+NB_OF_POSSIBILITIES)
+      throw INTERP_KERNEL::Exception("MEDCouplingNatureOfField::getRepr : Unrecognized nature of field !");
+    int pos2=std::distance(POS_OF_NATUREOFFIELD,pos);
+    return REPR_OF_NATUREOFFIELD[pos2];
+  }
+}
index bdc1c78ddf18e21c40164740ecde0570b2975f49..89f9125e03eb95b66a3070fc4b993e96f88cbc7d 100644 (file)
 //  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
 //
 
-#ifndef __MEDCOUPLINGNATUREOFFIELD_HXX__
-#define __MEDCOUPLINGNATUREOFFIELD_HXX__
+#ifndef __PARAMEDMEM_MEDCOUPLINGNATUREOFFIELD_HXX__
+#define __PARAMEDMEM_MEDCOUPLINGNATUREOFFIELD_HXX__
+
+#include "MEDCoupling.hxx"
+#include "InterpKernelException.hxx"
 
 namespace ParaMEDMEM
 {
@@ -30,6 +33,16 @@ namespace ParaMEDMEM
       IntegralGlobConstraint = 35,
       RevIntegral            = 37
     } NatureOfField;
+
+  class MEDCouplingNatureOfField
+  {
+  public:
+    MEDCOUPLING_EXPORT static const char *getRepr(NatureOfField nat) throw(INTERP_KERNEL::Exception);
+  private:
+    static const int NB_OF_POSSIBILITIES=5;
+    static const char *REPR_OF_NATUREOFFIELD[NB_OF_POSSIBILITIES];
+    static const int POS_OF_NATUREOFFIELD[NB_OF_POSSIBILITIES];
+  };
 }
 
 #endif
index ebb12e01a96c59737cfad183e1c2913452199036..c2643f327ec16aa84d5aa442fc1b0c885ff8e5f6 100644 (file)
@@ -17,8 +17,8 @@
 //  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
 //
 
-#ifndef __MEDCouplingNormalizedCartesianMesh_HXX__
-#define __MEDCouplingNormalizedCartesianMesh_HXX__
+#ifndef __PARAMEDMEM_MEDCOUPLINGNORMALIZEDCARTESIANMESH_HXX__
+#define __PARAMEDMEM_MEDCOUPLINGNORMALIZEDCARTESIANMESH_HXX__
 
 #include "NormalizedUnstructuredMesh.hxx"
 
index b3ebcbc7f0da924eb75334e396ea02616e997e2a..5ebd3ae1947b516d983a15e372018e85801ee0c0 100644 (file)
@@ -17,8 +17,8 @@
 //  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
 //
 
-#ifndef __MEDCOUPLINGNORMALIZEDUNSTRUCTUREDMESH_HXX__
-#define __MEDCOUPLINGNORMALIZEDUNSTRUCTUREDMESH_HXX__
+#ifndef __PARAMEDMEM_MEDCOUPLINGNORMALIZEDUNSTRUCTUREDMESH_HXX__
+#define __PARAMEDMEM_MEDCOUPLINGNORMALIZEDUNSTRUCTUREDMESH_HXX__
 
 #include "NormalizedUnstructuredMesh.hxx"
 
index 0c0ce18879bbcfe90a320f561d39cd326ab02a3e..f451ea61ad6b787029a223afeb971608f20acb10 100644 (file)
@@ -73,11 +73,6 @@ void MEDCouplingPointSet::updateTime()
     }
 }
 
-bool MEDCouplingPointSet::isStructured() const
-{
-  return false;
-}
-
 void MEDCouplingPointSet::setCoords(DataArrayDouble *coords)
 {
   if( coords != _coords )
@@ -98,6 +93,20 @@ DataArrayDouble *MEDCouplingPointSet::getCoordinatesAndOwner() const
   return _coords;
 }
 
+/*!
+ * This method copyies all tiny strings from other (name and components name).
+ * @throw if other and this have not same mesh type.
+ */
+void MEDCouplingPointSet::copyTinyStringsFrom(const MEDCouplingMesh *other) throw(INTERP_KERNEL::Exception)
+{
+  const MEDCouplingPointSet *otherC=dynamic_cast<const MEDCouplingPointSet *>(other);
+  if(!otherC)
+    throw INTERP_KERNEL::Exception("MEDCouplingPointSet::copyTinyStringsFrom : meshes have not same type !");
+  MEDCouplingMesh::copyTinyStringsFrom(other);
+  if(_coords && otherC->_coords)
+    _coords->copyStringInfoFrom(*otherC->_coords);
+}
+
 bool MEDCouplingPointSet::isEqual(const MEDCouplingMesh *other, double prec) const
 {
   const MEDCouplingPointSet *otherC=dynamic_cast<const MEDCouplingPointSet *>(other);
@@ -110,6 +119,16 @@ bool MEDCouplingPointSet::isEqual(const MEDCouplingMesh *other, double prec) con
   return true;
 }
 
+bool MEDCouplingPointSet::isEqualWithoutConsideringStr(const MEDCouplingMesh *other, double prec) const
+{
+  const MEDCouplingPointSet *otherC=dynamic_cast<const MEDCouplingPointSet *>(other);
+  if(!otherC)
+    return false;
+  if(!areCoordsEqualWithoutConsideringStr(*otherC,prec))
+    return false;
+  return true;
+}
+
 bool MEDCouplingPointSet::areCoordsEqual(const MEDCouplingPointSet& other, double prec) const
 {
   if(_coords==0 && other._coords==0)
@@ -121,13 +140,45 @@ bool MEDCouplingPointSet::areCoordsEqual(const MEDCouplingPointSet& other, doubl
   return _coords->isEqual(*other._coords,prec);
 }
 
+bool MEDCouplingPointSet::areCoordsEqualWithoutConsideringStr(const MEDCouplingPointSet& other, double prec) const
+{
+  if(_coords==0 && other._coords==0)
+    return true;
+  if(_coords==0 || other._coords==0)
+    return false;
+  if(_coords==other._coords)
+    return true;
+  return _coords->isEqualWithoutConsideringStr(*other._coords,prec);
+}
+
+/*!
+ * This method is typically the base method used for implementation of mergeNodes. This method computes this permutation array using as input,
+ * This method is const ! So this method simply computes the array, no permutation of nodes is done.
+ * a precision 'precision' and a 'limitNodeId' that is the node id so that every nodes which id is strictly lower than 'limitNodeId' will not be merged.
+ * To desactivate this advanced feature put -1 to this argument.
+ * @param areNodesMerged output parameter that states if some nodes have been "merged" in returned array
+ * @param newNbOfNodes output parameter too this is the maximal id in returned array to avoid to recompute it.
+ */
+DataArrayInt *MEDCouplingPointSet::buildPermArrayForMergeNode(int limitNodeId, double precision, bool& areNodesMerged, int& newNbOfNodes) const
+{
+  DataArrayInt *comm,*commI;
+  findCommonNodes(limitNodeId,precision,comm,commI);
+  int oldNbOfNodes=getNumberOfNodes();
+  DataArrayInt *ret=buildNewNumberingFromCommNodesFrmt(comm,commI,newNbOfNodes);
+  areNodesMerged=(oldNbOfNodes!=newNbOfNodes);
+  comm->decrRef();
+  commI->decrRef();
+  return ret;
+}
+
 /*!
  * This methods searches for each node n1 nodes in _coords that are less far than 'prec' from n1. if any these nodes are stored in params
  * comm and commIndex.
+ * @param limitNodeId is the limit node id. All nodes which id is strictly lower than 'limitNodeId' will not be merged.
  * @param comm out parameter (not inout)
  * @param commIndex out parameter (not inout)
  */
-void MEDCouplingPointSet::findCommonNodes(DataArrayInt *&comm, DataArrayInt *&commIndex, double prec) const
+void MEDCouplingPointSet::findCommonNodes(int limitNodeId, double prec, DataArrayInt *&comm, DataArrayInt *&commIndex) const
 {
   comm=DataArrayInt::New();
   commIndex=DataArrayInt::New();
@@ -149,13 +200,13 @@ void MEDCouplingPointSet::findCommonNodes(DataArrayInt *&comm, DataArrayInt *&co
   switch(spaceDim)
     {
     case 3:
-      findCommonNodesAlg<3>(bbox,nbNodesOld,prec,c,cI);
+      findCommonNodesAlg<3>(bbox,nbNodesOld,limitNodeId,prec,c,cI);
       break;
     case 2:
-      findCommonNodesAlg<2>(bbox,nbNodesOld,prec,c,cI);
+      findCommonNodesAlg<2>(bbox,nbNodesOld,limitNodeId,prec,c,cI);
       break;
     case 1:
-      findCommonNodesAlg<1>(bbox,nbNodesOld,prec,c,cI);
+      findCommonNodesAlg<1>(bbox,nbNodesOld,limitNodeId,prec,c,cI);
       break;
     default:
       throw INTERP_KERNEL::Exception("Unexpected spacedim of coords. Must be 1,2 or 3.");
@@ -272,6 +323,25 @@ void MEDCouplingPointSet::zipCoords()
   traducer->decrRef();
 }
 
+struct MEDCouplingCompAbs
+{
+  bool operator()(double x, double y) { return std::abs(x)<std::abs(y);}
+};
+
+/*!
+ * This method expects that _coords attribute is set.
+ * @return the carateristic dimension of point set. This caracteristic dimension is the max of difference 
+ * @exception If _coords attribute not set.
+ */
+double MEDCouplingPointSet::getCaracteristicDimension() const
+{
+  if(!_coords)
+    throw INTERP_KERNEL::Exception("MEDCouplingPointSet::getCaracteristicDimension : Coordinates not set !");
+  const double *coords=_coords->getConstPointer();
+  int nbOfValues=_coords->getNbOfElems();
+  return std::abs(*std::max_element(coords,coords+nbOfValues,MEDCouplingCompAbs()));
+}
+
 /*!
  * Non const method that operates a rotation of 'this'.
  * If spaceDim==2 'vector' parameter is ignored (and could be 0) and the rotation is done around 'center' with angle specified by 'angle'.
@@ -339,7 +409,7 @@ void MEDCouplingPointSet::scale(const double *point, double factor)
  * - by ignoring each \f$ i^{th} \f$ components of each coord of nodes so that i >= 'newSpaceDim', 'newSpaceDim'<getSpaceDimension()
  * If newSpaceDim==getSpaceDim() nothing is done by this method.
  */
-void MEDCouplingPointSet::changeSpaceDimension(int newSpaceDim) throw(INTERP_KERNEL::Exception)
+void MEDCouplingPointSet::changeSpaceDimension(int newSpaceDim, double dftValue) throw(INTERP_KERNEL::Exception)
 {
   if(getCoords()==0)
     throw INTERP_KERNEL::Exception("changeSpaceDimension must be called on an MEDCouplingPointSet instance with coordinates set !");
@@ -348,25 +418,10 @@ void MEDCouplingPointSet::changeSpaceDimension(int newSpaceDim) throw(INTERP_KER
   int oldSpaceDim=getSpaceDimension();
   if(newSpaceDim==oldSpaceDim)
     return ;
-  DataArrayDouble *newCoords=DataArrayDouble::New();
-  newCoords->alloc(getCoords()->getNumberOfTuples(),newSpaceDim);
-  const double *oldc=getCoords()->getConstPointer();
-  double *nc=newCoords->getPointer();
-  int nbOfNodes=getNumberOfNodes();
-  int dim=std::min(oldSpaceDim,newSpaceDim);
-  for(int i=0;i<nbOfNodes;i++)
-    {
-      int j=0;
-      for(;j<dim;j++)
-        nc[newSpaceDim*i+j]=oldc[i*oldSpaceDim+j];
-      for(;j<newSpaceDim;j++)
-        nc[newSpaceDim*i+j]=0.;
-    }
-  newCoords->setName(getCoords()->getName().c_str());
-  for(int i=0;i<dim;i++)
-    newCoords->setInfoOnComponent(i,getCoords()->getInfoOnComponent(i).c_str());
+  DataArrayDouble *newCoords=getCoords()->changeNbOfComponents(newSpaceDim,dftValue);
   setCoords(newCoords);
   newCoords->decrRef();
+  updateTime();
 }
 
 /*!
@@ -381,7 +436,7 @@ void MEDCouplingPointSet::tryToShareSameCoords(const MEDCouplingPointSet& other,
     throw INTERP_KERNEL::Exception("Current instance has no coords whereas other has !");
   if(!other._coords)
     throw INTERP_KERNEL::Exception("Other instance has no coords whereas current has !");
-  if(!_coords->isEqual(*other._coords,epsilon))
+  if(!_coords->isEqualWithoutConsideringStr(*other._coords,epsilon))
     throw INTERP_KERNEL::Exception("Coords are not the same !");
   setCoords(other._coords);
 }
@@ -485,7 +540,7 @@ void MEDCouplingPointSet::serialize(DataArrayInt *&a1, DataArrayDouble *&a2) con
  * Second step of serialization process.
  * @param tinyInfo must be equal to the result given by getTinySerializationInformation method.
  */
-void MEDCouplingPointSet::resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings)
+void MEDCouplingPointSet::resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings) const
 {
   if(tinyInfo[2]>=0 && tinyInfo[1]>=1)
     {
@@ -502,7 +557,7 @@ void MEDCouplingPointSet::resizeForUnserialization(const std::vector<int>& tinyI
  * Second and final unserialization process.
  * @param tinyInfo must be equal to the result given by getTinySerializationInformation method.
  */
-void MEDCouplingPointSet::unserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, const std::vector<std::string>& littleStrings)
+void MEDCouplingPointSet::unserialization(const std::vector<int>& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2, const std::vector<std::string>& littleStrings)
 {
   if(tinyInfo[2]>=0 && tinyInfo[1]>=1)
     {
@@ -624,6 +679,33 @@ void MEDCouplingPointSet::rotate3DAlg(const double *center, const double *vect,
     }
 }
 
+/*!
+ * This method implements pure virtual method MEDCouplingMesh::buildPart.
+ * This method build a part of 'this' by simply keeping cells whose ids are in ['start','end').
+ * The coords are kept unchanged contrary to pure virtual method MEDCouplingMesh::buildPartAndReduceNodes.
+ * The returned mesh has to be managed by the caller.
+ */
+MEDCouplingMesh *MEDCouplingPointSet::buildPart(const int *start, const int *end) const
+{
+  return buildPartOfMySelf(start,end,false);
+}
+
+/*!
+ * This method implements pure virtual method MEDCouplingMesh::buildPartAndReduceNodes.
+ * This method build a part of 'this' by simply keeping cells whose ids are in ['start','end') \b and potentially reduces the nodes set
+ * behind returned mesh. This cause an overhead but it is more little in memory.
+ * This method returns an array too. This array allows to the caller to know the mapping between nodeids in 'this' and nodeids in 
+ * returned mesh. This is quite usefull for MEDCouplingFieldDouble on nodes for example...
+ * The returned mesh has to be managed by the caller.
+ */
+MEDCouplingMesh *MEDCouplingPointSet::buildPartAndReduceNodes(const int *start, const int *end, DataArrayInt*& arr) const
+{
+  MEDCouplingPointSet *ret=buildPartOfMySelf(start,end,true);
+  arr=ret->zipCoordsTraducer();
+  return ret;
+}
+
+
 /*!
  * 'This' is expected to be of spaceDim==2. Idem for 'center' and 'vect'
  */
index 601777efc1a6338045e4f41b0808e692605244d4..687124fa83e1e3cd85be4c24ed64db2d169a4b76 100644 (file)
@@ -43,43 +43,50 @@ namespace ParaMEDMEM
     ~MEDCouplingPointSet();
   public:
     void updateTime();
-    bool isStructured() const;
     int getNumberOfNodes() const;
     int getSpaceDimension() const;
     void setCoords(DataArrayDouble *coords);
     DataArrayDouble *getCoords() const { return _coords; }
     DataArrayDouble *getCoordinatesAndOwner() const;
+    void copyTinyStringsFrom(const MEDCouplingMesh *other) throw(INTERP_KERNEL::Exception);
     bool isEqual(const MEDCouplingMesh *other, double prec) const;
+    bool isEqualWithoutConsideringStr(const MEDCouplingMesh *other, double prec) const;
     bool areCoordsEqual(const MEDCouplingPointSet& other, double prec) const;
-    virtual DataArrayInt *mergeNodes(double precision, bool& areNodesMerged) = 0;
-    void findCommonNodes(DataArrayInt *&comm, DataArrayInt *&commIndex, double prec) const;
+    bool areCoordsEqualWithoutConsideringStr(const MEDCouplingPointSet& other, double prec) const;
+    virtual DataArrayInt *mergeNodes(double precision, bool& areNodesMerged, int& newNbOfNodes) = 0;
+    DataArrayInt *buildPermArrayForMergeNode(int limitNodeId, double precision, bool& areNodesMerged, int& newNbOfNodes) const;
+    void findCommonNodes(int limitNodeId, double prec, DataArrayInt *&comm, DataArrayInt *&commIndex) const;
     DataArrayInt *buildNewNumberingFromCommNodesFrmt(const DataArrayInt *comm, const DataArrayInt *commIndex,
                                                      int& newNbOfNodes) const;
     void getBoundingBox(double *bbox) const;
     void zipCoords();
+    double getCaracteristicDimension() const;
     void rotate(const double *center, const double *vector, double angle);
     void translate(const double *vector);
     void scale(const double *point, double factor);
-    void changeSpaceDimension(int newSpaceDim) throw(INTERP_KERNEL::Exception);
+    void changeSpaceDimension(int newSpaceDim, double dftVal=0.) throw(INTERP_KERNEL::Exception);
     void tryToShareSameCoords(const MEDCouplingPointSet& other, double epsilon) throw(INTERP_KERNEL::Exception);
+    virtual void tryToShareSameCoordsPermute(const MEDCouplingPointSet& other, double epsilon) throw(INTERP_KERNEL::Exception) = 0;
     void findNodesOnPlane(const double *pt, const double *vec, double eps, std::vector<int>& nodes) const throw(INTERP_KERNEL::Exception);
     static DataArrayDouble *mergeNodesArray(const MEDCouplingPointSet *m1, const MEDCouplingPointSet *m2);
     static MEDCouplingPointSet *buildInstanceFromMeshType(MEDCouplingMeshType type);
     static void rotate2DAlg(const double *center, double angle, int nbNodes, double *coords);
     static void rotate3DAlg(const double *center, const double *vect, double angle, int nbNodes, double *coords);
+    MEDCouplingMesh *buildPart(const int *start, const int *end) const;
+    MEDCouplingMesh *buildPartAndReduceNodes(const int *start, const int *end, DataArrayInt*& arr) const;
     virtual MEDCouplingPointSet *buildPartOfMySelf(const int *start, const int *end, bool keepCoords) const = 0;
     virtual MEDCouplingPointSet *buildPartOfMySelfNode(const int *start, const int *end, bool fullyIn) const = 0;
     virtual MEDCouplingPointSet *buildFacePartOfMySelfNode(const int *start, const int *end, bool fullyIn) const = 0;
     virtual void findBoundaryNodes(std::vector<int>& nodes) const = 0;
     virtual MEDCouplingPointSet *buildBoundaryMesh(bool keepCoords) const = 0;
     virtual void renumberNodes(const int *newNodeNumbers, int newNbOfNodes);
-    //! size of returned tinyInfo must be always the same.
-    virtual void getTinySerializationInformation(std::vector<int>& tinyInfo, std::vector<std::string>& littleStrings) const;
     virtual bool isEmptyMesh(const std::vector<int>& tinyInfo) const = 0;
-    virtual void resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings);
-    virtual void serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const;
-    virtual void unserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2,
-                                 const std::vector<std::string>& littleStrings);
+    //! size of returned tinyInfo must be always the same.
+    void getTinySerializationInformation(std::vector<int>& tinyInfo, std::vector<std::string>& littleStrings) const;
+    void resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings) const;
+    void serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const;
+    void unserialization(const std::vector<int>& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2,
+                         const std::vector<std::string>& littleStrings);
     virtual void giveElemsInBoundingBox(const double *bbox, double eps, std::vector<int>& elems) = 0;
     virtual void giveElemsInBoundingBox(const INTERP_KERNEL::DirectedBoundingBox& bbox, double eps, std::vector<int>& elems) = 0;
     virtual DataArrayInt *zipCoordsTraducer() = 0;
@@ -93,7 +100,7 @@ namespace ParaMEDMEM
     static bool isButterfly2DCell(const std::vector<double>& res, bool isQuad);
     template<int SPACEDIM>
     void findCommonNodesAlg(std::vector<double>& bbox,
-                            int nbNodes, double prec, std::vector<int>& c, std::vector<int>& cI) const;
+                            int nbNodes, int limitNodeId, double prec, std::vector<int>& c, std::vector<int>& cI) const;
   protected:
     DataArrayDouble *_coords;
   };
index 300aab2352ec854ec68fea03008ee153aa86a438..bae1955669521d800191c474531e4e76168d8ce1 100644 (file)
@@ -29,7 +29,7 @@ namespace ParaMEDMEM
 {
   template<int SPACEDIM>
   void MEDCouplingPointSet::findCommonNodesAlg(std::vector<double>& bbox,
-                                               int nbNodes, double prec,
+                                               int nbNodes, int limitNodeId, double prec,
                                                std::vector<int>& c, std::vector<int>& cI) const
   {
     const double *coordsPtr=_coords->getConstPointer();
@@ -52,8 +52,9 @@ namespace ParaMEDMEM
             std::vector<int> commonNodes;
             for(std::vector<int>::const_iterator it=intersectingElems.begin();it!=intersectingElems.end();it++)
               if(*it!=i)
-                if(INTERP_KERNEL::distance2<SPACEDIM>(coordsPtr+SPACEDIM*i,coordsPtr+SPACEDIM*(*it))<prec2)
-                  commonNodes.push_back(*it);
+                if(*it>=limitNodeId)
+                  if(INTERP_KERNEL::distance2<SPACEDIM>(coordsPtr+SPACEDIM*i,coordsPtr+SPACEDIM*(*it))<prec2)
+                    commonNodes.push_back(*it);
             if(!commonNodes.empty())
               {
                 cI.push_back(cI.back()+commonNodes.size()+1);
index 6929b85331b180ad3dbb2a4624380c29ad115960..7a473b6da726029ebac29149fc17e0d128359249 100644 (file)
@@ -33,7 +33,9 @@ namespace ParaMEDMEM
   typedef enum
     {
       ON_CELLS = 0,
-      ON_NODES = 1
+      ON_NODES = 1,
+      ON_GAUSS_PT = 2,
+      ON_GAUSS_NE = 3
     } TypeOfField;
 
   typedef enum
index ca57b48a6dc1b8d3c9dc69dbbd49865f9f643050..3337b8b4e1a711c5f0a6fe851bbe0a1a54b41152 100644 (file)
@@ -41,7 +41,7 @@ MEDCouplingRemapper::~MEDCouplingRemapper()
   releaseData(false);
 }
 
-int MEDCouplingRemapper::prepare(const MEDCouplingMesh *srcMesh, const MEDCouplingMesh *targetMesh, const char *method)
+int MEDCouplingRemapper::prepare(const MEDCouplingMesh *srcMesh, const MEDCouplingMesh *targetMesh, const char *method) throw(INTERP_KERNEL::Exception)
 {
   releaseData(true);
   _src_mesh=(MEDCouplingMesh *)srcMesh; _target_mesh=(MEDCouplingMesh *)targetMesh;
@@ -58,7 +58,7 @@ int MEDCouplingRemapper::prepare(const MEDCouplingMesh *srcMesh, const MEDCoupli
     }
 }
 
-void MEDCouplingRemapper::transfer(const MEDCouplingFieldDouble *srcField, MEDCouplingFieldDouble *targetField, double dftValue)
+void MEDCouplingRemapper::transfer(const MEDCouplingFieldDouble *srcField, MEDCouplingFieldDouble *targetField, double dftValue) throw(INTERP_KERNEL::Exception)
 {
   if(_src_method!=srcField->getDiscretization()->getStringRepr())
     throw INTERP_KERNEL::Exception("Incoherency with prepare call for source field");
@@ -86,7 +86,7 @@ void MEDCouplingRemapper::transfer(const MEDCouplingFieldDouble *srcField, MEDCo
   computeProduct(inputPointer,srcNbOfCompo,dftValue,resPointer);
 }
 
-void MEDCouplingRemapper::reverseTransfer(MEDCouplingFieldDouble *srcField, const MEDCouplingFieldDouble *targetField, double dftValue)
+void MEDCouplingRemapper::reverseTransfer(MEDCouplingFieldDouble *srcField, const MEDCouplingFieldDouble *targetField, double dftValue) throw(INTERP_KERNEL::Exception)
 {
   if(_src_method!=srcField->getDiscretization()->getStringRepr())
     throw INTERP_KERNEL::Exception("Incoherency with prepare call for source field");
@@ -114,7 +114,7 @@ void MEDCouplingRemapper::reverseTransfer(MEDCouplingFieldDouble *srcField, cons
   computeReverseProduct(inputPointer,trgNbOfCompo,dftValue,resPointer);
 }
 
-MEDCouplingFieldDouble *MEDCouplingRemapper::transferField(const MEDCouplingFieldDouble *srcField, double dftValue)
+MEDCouplingFieldDouble *MEDCouplingRemapper::transferField(const MEDCouplingFieldDouble *srcField, double dftValue) throw(INTERP_KERNEL::Exception)
 {
   if(_src_method!=srcField->getDiscretization()->getStringRepr())
     throw INTERP_KERNEL::Exception("Incoherency with prepare call for source field");
@@ -125,7 +125,7 @@ MEDCouplingFieldDouble *MEDCouplingRemapper::transferField(const MEDCouplingFiel
   return ret;
 }
 
-MEDCouplingFieldDouble *MEDCouplingRemapper::reverseTransferField(const MEDCouplingFieldDouble *targetField, double dftValue)
+MEDCouplingFieldDouble *MEDCouplingRemapper::reverseTransferField(const MEDCouplingFieldDouble *targetField, double dftValue) throw(INTERP_KERNEL::Exception)
 {
   if(_target_method!=targetField->getDiscretization()->getStringRepr())
     throw INTERP_KERNEL::Exception("Incoherency with prepare call for target field");
@@ -146,12 +146,12 @@ bool MEDCouplingRemapper::setOptionDouble(const std::string& key, double value)
   return INTERP_KERNEL::InterpolationOptions::setOptionDouble(key,value);
 }
 
-bool MEDCouplingRemapper::setOptionString(const std::string& key, std::string& value)
+bool MEDCouplingRemapper::setOptionString(const std::string& key, const std::string& value)
 {
   return INTERP_KERNEL::InterpolationOptions::setOptionString(key,value);
 }
 
-int MEDCouplingRemapper::prepareUU(const char *method)
+int MEDCouplingRemapper::prepareUU(const char *method) throw(INTERP_KERNEL::Exception)
 {
   MEDCouplingUMesh *src_mesh=(MEDCouplingUMesh *)_src_mesh;
   MEDCouplingUMesh *target_mesh=(MEDCouplingUMesh *)_target_mesh;
@@ -168,7 +168,21 @@ int MEDCouplingRemapper::prepareUU(const char *method)
     if(trgSpaceDim!=-1 && srcSpaceDim!=-1)
       throw INTERP_KERNEL::Exception("Incoherent space dimension detected between target and source.");
   int nbCols;
-  if(srcMeshDim==2 && trgMeshDim==2 && srcSpaceDim==2)
+  if(srcMeshDim==1 && trgMeshDim==1 && srcSpaceDim==1)
+    {
+      MEDCouplingNormalizedUnstructuredMesh<1,1> source_mesh_wrapper(src_mesh);
+      MEDCouplingNormalizedUnstructuredMesh<1,1> target_mesh_wrapper(target_mesh);
+      INTERP_KERNEL::Interpolation1D interpolation(*this);
+      nbCols=interpolation.interpolateMeshes(source_mesh_wrapper,target_mesh_wrapper,_matrix,method);
+    }
+  else if(srcMeshDim==1 && trgMeshDim==1 && srcSpaceDim==2)
+    {
+      MEDCouplingNormalizedUnstructuredMesh<2,1> source_mesh_wrapper(src_mesh);
+      MEDCouplingNormalizedUnstructuredMesh<2,1> target_mesh_wrapper(target_mesh);
+      INTERP_KERNEL::Interpolation2DCurve interpolation(*this);
+      nbCols=interpolation.interpolateMeshes(source_mesh_wrapper,target_mesh_wrapper,_matrix,method);
+    }
+  else if(srcMeshDim==2 && trgMeshDim==2 && srcSpaceDim==2)
     {
       MEDCouplingNormalizedUnstructuredMesh<2,2> source_mesh_wrapper(src_mesh);
       MEDCouplingNormalizedUnstructuredMesh<2,2> target_mesh_wrapper(target_mesh);
@@ -287,7 +301,7 @@ int MEDCouplingRemapper::prepareUU(const char *method)
   return 1;
 }
 
-int MEDCouplingRemapper::prepareEE(const char *method)
+int MEDCouplingRemapper::prepareEE(const char *method) throw(INTERP_KERNEL::Exception)
 {
   MEDCouplingExtrudedMesh *src_mesh=(MEDCouplingExtrudedMesh *)_src_mesh;
   MEDCouplingExtrudedMesh *target_mesh=(MEDCouplingExtrudedMesh *)_target_mesh;
@@ -351,7 +365,7 @@ void MEDCouplingRemapper::computeDeno(NatureOfField nat, const MEDCouplingFieldD
     return computeDenoFromScratch(nat,srcField,trgField);
 }
 
-void MEDCouplingRemapper::computeDenoFromScratch(NatureOfField nat, const MEDCouplingFieldDouble *srcField, const MEDCouplingFieldDouble *trgField)
+void MEDCouplingRemapper::computeDenoFromScratch(NatureOfField nat, const MEDCouplingFieldDouble *srcField, const MEDCouplingFieldDouble *trgField) throw(INTERP_KERNEL::Exception)
 {
   _nature_of_deno=nat;
   _time_deno_update=getTimeOfThis();
index 5e2bd63dd357ab4a7c7890aca4e5dd25438a717b..14d402d0365d5a45e3db4e631866af24db86ea7a 100644 (file)
@@ -24,6 +24,7 @@
 #include "MEDCouplingTimeLabel.hxx"
 #include "InterpolationOptions.hxx"
 #include "MEDCouplingNatureOfField.hxx"
+#include "InterpKernelException.hxx"
 
 #include <map>
 #include <vector>
@@ -42,23 +43,23 @@ namespace ParaMEDMEM
   public:
     MEDCOUPLINGREMAPPER_EXPORT MEDCouplingRemapper();
     MEDCOUPLINGREMAPPER_EXPORT ~MEDCouplingRemapper();
-    MEDCOUPLINGREMAPPER_EXPORT int prepare(const MEDCouplingMesh *srcMesh, const MEDCouplingMesh *targetMesh, const char *method);
-    MEDCOUPLINGREMAPPER_EXPORT void transfer(const MEDCouplingFieldDouble *srcField, MEDCouplingFieldDouble *targetField, double dftValue);
-    MEDCOUPLINGREMAPPER_EXPORT void reverseTransfer(MEDCouplingFieldDouble *srcField, const MEDCouplingFieldDouble *targetField, double dftValue);
-    MEDCOUPLINGREMAPPER_EXPORT MEDCouplingFieldDouble *transferField(const MEDCouplingFieldDouble *srcField, double dftValue);
-    MEDCOUPLINGREMAPPER_EXPORT MEDCouplingFieldDouble *reverseTransferField(const MEDCouplingFieldDouble *targetField, double dftValue);
+    MEDCOUPLINGREMAPPER_EXPORT int prepare(const MEDCouplingMesh *srcMesh, const MEDCouplingMesh *targetMesh, const char *method) throw(INTERP_KERNEL::Exception);
+    MEDCOUPLINGREMAPPER_EXPORT void transfer(const MEDCouplingFieldDouble *srcField, MEDCouplingFieldDouble *targetField, double dftValue) throw(INTERP_KERNEL::Exception);
+    MEDCOUPLINGREMAPPER_EXPORT void reverseTransfer(MEDCouplingFieldDouble *srcField, const MEDCouplingFieldDouble *targetField, double dftValue) throw(INTERP_KERNEL::Exception);
+    MEDCOUPLINGREMAPPER_EXPORT MEDCouplingFieldDouble *transferField(const MEDCouplingFieldDouble *srcField, double dftValue) throw(INTERP_KERNEL::Exception);
+    MEDCOUPLINGREMAPPER_EXPORT MEDCouplingFieldDouble *reverseTransferField(const MEDCouplingFieldDouble *targetField, double dftValue) throw(INTERP_KERNEL::Exception);
     MEDCOUPLINGREMAPPER_EXPORT bool setOptionInt(const std::string& key, int value);
     MEDCOUPLINGREMAPPER_EXPORT bool setOptionDouble(const std::string& key, double value);
-    MEDCOUPLINGREMAPPER_EXPORT bool setOptionString(const std::string& key, std::string& value);
+    MEDCOUPLINGREMAPPER_EXPORT bool setOptionString(const std::string& key, const std::string& value);
   public:
     MEDCOUPLINGREMAPPER_EXPORT static void printMatrix(const std::vector<std::map<int,double> >& m);
   private:
-    int prepareUU(const char *method);
-    int prepareEE(const char *method);
+    int prepareUU(const char *method) throw(INTERP_KERNEL::Exception);
+    int prepareEE(const char *method) throw(INTERP_KERNEL::Exception);
     void updateTime();
     void releaseData(bool matrixSuppression);
     void computeDeno(NatureOfField nat, const MEDCouplingFieldDouble *srcField, const MEDCouplingFieldDouble *trgField);
-    void computeDenoFromScratch(NatureOfField nat, const MEDCouplingFieldDouble *srcField, const MEDCouplingFieldDouble *trgField);
+    void computeDenoFromScratch(NatureOfField nat, const MEDCouplingFieldDouble *srcField, const MEDCouplingFieldDouble *trgField) throw(INTERP_KERNEL::Exception);
     void computeProduct(const double *inputPointer, int inputNbOfCompo, double dftValue, double *resPointer);
     void computeReverseProduct(const double *inputPointer, int inputNbOfCompo, double dftValue, double *resPointer);
     void buildFinalInterpolationMatrixByConvolution(const std::vector< std::map<int,double> >& m1D,
index a030e1b4c148250a1e4c3690e4a33171db34ca39..c9c8a41d22ae27083d4bb7a97893cc9c88d67c05 100644 (file)
 
 #include "MEDCouplingTimeDiscretization.hxx"
 #include "MEDCouplingMemArray.hxx"
-
-#include "InterpKernelExprParser.hxx"
+#include "MEDCouplingAutoRefCountObjectPtr.hxx"
 
 #include <cmath>
 #include <iterator>
+#include <functional>
 
 using namespace ParaMEDMEM;
 
+const double MEDCouplingTimeDiscretization::TIME_TOLERANCE_DFT=1.e-12;
+
 const char MEDCouplingNoTimeLabel::EXCEPTION_MSG[]="MEDCouplingNoTimeLabel::setTime : no time info attached.";
 
+const char MEDCouplingNoTimeLabel::REPR[]="No time label defined.";
+
 const char MEDCouplingWithTimeStep::EXCEPTION_MSG[]="No data on this time.";
 
+const char MEDCouplingWithTimeStep::REPR[]="One time label.";
+
 const char MEDCouplingConstOnTimeInterval::EXCEPTION_MSG[]="No data on this time.";
 
-const double MEDCouplingTimeDiscretization::TIME_TOLERANCE_DFT=1.e-12;
+const char MEDCouplingConstOnTimeInterval::REPR[]="Constant on a time interval.";
+
+const char MEDCouplingTwoTimeSteps::EXCEPTION_MSG[]="No data on this time.";
+
+const char MEDCouplingLinearTime::REPR[]="Linear time between 2 time steps.";
 
 MEDCouplingTimeDiscretization *MEDCouplingTimeDiscretization::New(TypeOfTimeDiscretization type)
 {
@@ -45,11 +55,32 @@ MEDCouplingTimeDiscretization *MEDCouplingTimeDiscretization::New(TypeOfTimeDisc
       return new MEDCouplingWithTimeStep;
     case MEDCouplingConstOnTimeInterval::DISCRETIZATION:
       return new MEDCouplingConstOnTimeInterval;
+    case MEDCouplingLinearTime::DISCRETIZATION:
+      return new MEDCouplingLinearTime;
     default:
       throw INTERP_KERNEL::Exception("Time discretization not implemented yet");
     }
 }
 
+void MEDCouplingTimeDiscretization::copyTinyAttrFrom(const MEDCouplingTimeDiscretization& other)
+{
+  _time_tolerance=other._time_tolerance;
+}
+
+void MEDCouplingTimeDiscretization::copyTinyStringsFrom(const MEDCouplingTimeDiscretization& other)
+{
+  if(_array && other._array)
+    _array->copyStringInfoFrom(*other._array);
+}
+
+void MEDCouplingTimeDiscretization::checkCoherency() const throw(INTERP_KERNEL::Exception)
+{
+  if(!_array)
+    throw INTERP_KERNEL::Exception("Field invalid because no values set !");
+  if(_time_tolerance<0.)
+    throw INTERP_KERNEL::Exception("time tolerance is expected to be greater than 0. !");
+}
+
 void MEDCouplingTimeDiscretization::updateTime()
 {
   if(_array)
@@ -69,7 +100,22 @@ bool MEDCouplingTimeDiscretization::areCompatible(const MEDCouplingTimeDiscretiz
   return true;
 }
 
-bool MEDCouplingTimeDiscretization::areCompatibleForMul(const MEDCouplingTimeDiscretization *other) const
+bool MEDCouplingTimeDiscretization::areStrictlyCompatible(const MEDCouplingTimeDiscretization *other) const
+{
+  if(std::fabs(_time_tolerance-other->_time_tolerance)>1.e-16)
+    return false;
+  if(_array==0 && other->_array==0)
+    return true;
+  if(_array==0 || other->_array==0)
+    return false;
+  if(_array->getNumberOfComponents()!=other->_array->getNumberOfComponents())
+    return false;
+  if(_array->getNumberOfTuples()!=other->_array->getNumberOfTuples())
+    return false;
+  return true;
+}
+
+bool MEDCouplingTimeDiscretization::areStrictlyCompatibleForMul(const MEDCouplingTimeDiscretization *other) const
 {
   if(std::fabs(_time_tolerance-other->_time_tolerance)>1.e-16)
     return false;
@@ -87,13 +133,22 @@ bool MEDCouplingTimeDiscretization::areCompatibleForMul(const MEDCouplingTimeDis
 
 bool MEDCouplingTimeDiscretization::isEqual(const MEDCouplingTimeDiscretization *other, double prec) const
 {
-  if(!areCompatible(other))
+  if(!areStrictlyCompatible(other))
     return false;
   if(_array==other->_array)
     return true;
   return _array->isEqual(*other->_array,prec);
 }
 
+bool MEDCouplingTimeDiscretization::isEqualWithoutConsideringStr(const MEDCouplingTimeDiscretization *other, double prec) const
+{
+  if(!areStrictlyCompatible(other))
+    return false;
+  if(_array==other->_array)
+    return true;
+  return _array->isEqualWithoutConsideringStr(*other->_array,prec);
+}
+
 MEDCouplingTimeDiscretization *MEDCouplingTimeDiscretization::buildNewTimeReprFromThis(const MEDCouplingTimeDiscretization *other,
                                                                                        TypeOfTimeDiscretization type, bool deepCpy) const
 {
@@ -190,6 +245,16 @@ void MEDCouplingTimeDiscretization::setArray(DataArrayDouble *array, TimeLabel *
     }
 }
 
+DataArrayDouble *MEDCouplingTimeDiscretization::getEndArray() const
+{
+  throw INTERP_KERNEL::Exception("getEndArray not available for this type of time discretization !");
+}
+
+void MEDCouplingTimeDiscretization::setEndArray(DataArrayDouble *array, TimeLabel *owner)
+{
+  throw INTERP_KERNEL::Exception("setEndArray not available for this type of time discretization !");
+}
+
 void MEDCouplingTimeDiscretization::setArrays(const std::vector<DataArrayDouble *>& arrays, TimeLabel *owner) throw(INTERP_KERNEL::Exception)
 {
   if(arrays.size()!=1)
@@ -205,122 +270,314 @@ void MEDCouplingTimeDiscretization::getArrays(std::vector<DataArrayDouble *>& ar
 
 bool MEDCouplingTimeDiscretization::isBefore(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception)
 {
-  int dt,it;
-  double time1=getEndTime(dt,it)-_time_tolerance;
-  double time2=other->getStartTime(dt,it)+other->getTimeTolerance();
+  int iteration,order;
+  double time1=getEndTime(iteration,order)-_time_tolerance;
+  double time2=other->getStartTime(iteration,order)+other->getTimeTolerance();
   return time1<=time2;
 }
 
 bool MEDCouplingTimeDiscretization::isStrictlyBefore(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception)
 {
-  int dt,it;
-  double time1=getEndTime(dt,it)+_time_tolerance;
-  double time2=other->getStartTime(dt,it)-other->getTimeTolerance();
+  int iteration,order;
+  double time1=getEndTime(iteration,order)+_time_tolerance;
+  double time2=other->getStartTime(iteration,order)-other->getTimeTolerance();
   return time1<time2;
 }
 
+MEDCouplingTimeDiscretization *MEDCouplingTimeDiscretization::doublyContractedProduct() const throw(INTERP_KERNEL::Exception)
+{
+  MEDCouplingTimeDiscretization *ret=MEDCouplingTimeDiscretization::New(getEnum());
+  std::vector<DataArrayDouble *> arrays;
+  getArrays(arrays);
+  std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> > arrays2(arrays.size());
+  for(int j=0;j<(int)arrays.size();j++)
+    {
+      if(arrays[j])
+        arrays2[j]=arrays[j]->doublyContractedProduct();
+      else
+        arrays2[j]=0;
+    }
+  std::vector<DataArrayDouble *> arrays3(arrays.size());
+  for(int j=0;j<(int)arrays.size();j++)
+    arrays3[j]=arrays2[j];
+  ret->setArrays(arrays3,0);
+  return ret;
+}
+
+MEDCouplingTimeDiscretization *MEDCouplingTimeDiscretization::determinant() const throw(INTERP_KERNEL::Exception)
+{
+  MEDCouplingTimeDiscretization *ret=MEDCouplingTimeDiscretization::New(getEnum());
+  std::vector<DataArrayDouble *> arrays;
+  getArrays(arrays);
+  std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> > arrays2(arrays.size());
+  for(int j=0;j<(int)arrays.size();j++)
+    {
+      if(arrays[j])
+        arrays2[j]=arrays[j]->determinant();
+      else
+        arrays2[j]=0;
+    }
+  std::vector<DataArrayDouble *> arrays3(arrays.size());
+  for(int j=0;j<(int)arrays.size();j++)
+    arrays3[j]=arrays2[j];
+  ret->setArrays(arrays3,0);
+  return ret;
+}
+
+MEDCouplingTimeDiscretization *MEDCouplingTimeDiscretization::eigenValues() const throw(INTERP_KERNEL::Exception)
+{
+  MEDCouplingTimeDiscretization *ret=MEDCouplingTimeDiscretization::New(getEnum());
+  std::vector<DataArrayDouble *> arrays;
+  getArrays(arrays);
+  std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> > arrays2(arrays.size());
+  for(int j=0;j<(int)arrays.size();j++)
+    {
+      if(arrays[j])
+        arrays2[j]=arrays[j]->eigenValues();
+      else
+        arrays2[j]=0;
+    }
+  std::vector<DataArrayDouble *> arrays3(arrays.size());
+  for(int j=0;j<(int)arrays.size();j++)
+    arrays3[j]=arrays2[j];
+  ret->setArrays(arrays3,0);
+  return ret;
+}
+
+MEDCouplingTimeDiscretization *MEDCouplingTimeDiscretization::eigenVectors() const throw(INTERP_KERNEL::Exception)
+{
+  MEDCouplingTimeDiscretization *ret=MEDCouplingTimeDiscretization::New(getEnum());
+  std::vector<DataArrayDouble *> arrays;
+  getArrays(arrays);
+  std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> > arrays2(arrays.size());
+  for(int j=0;j<(int)arrays.size();j++)
+    {
+      if(arrays[j])
+        arrays2[j]=arrays[j]->eigenVectors();
+      else
+        arrays2[j]=0;
+    }
+  std::vector<DataArrayDouble *> arrays3(arrays.size());
+  for(int j=0;j<(int)arrays.size();j++)
+    arrays3[j]=arrays2[j];
+  ret->setArrays(arrays3,0);
+  return ret;
+}
+
+MEDCouplingTimeDiscretization *MEDCouplingTimeDiscretization::inverse() const throw(INTERP_KERNEL::Exception)
+{
+  MEDCouplingTimeDiscretization *ret=MEDCouplingTimeDiscretization::New(getEnum());
+  std::vector<DataArrayDouble *> arrays;
+  getArrays(arrays);
+  std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> > arrays2(arrays.size());
+  for(int j=0;j<(int)arrays.size();j++)
+    {
+      if(arrays[j])
+        arrays2[j]=arrays[j]->inverse();
+      else
+        arrays2[j]=0;
+    }
+  std::vector<DataArrayDouble *> arrays3(arrays.size());
+  for(int j=0;j<(int)arrays.size();j++)
+    arrays3[j]=arrays2[j];
+  ret->setArrays(arrays3,0);
+  return ret;
+}
+
+MEDCouplingTimeDiscretization *MEDCouplingTimeDiscretization::trace() const throw(INTERP_KERNEL::Exception)
+{
+  MEDCouplingTimeDiscretization *ret=MEDCouplingTimeDiscretization::New(getEnum());
+  std::vector<DataArrayDouble *> arrays;
+  getArrays(arrays);
+  std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> > arrays2(arrays.size());
+  for(int j=0;j<(int)arrays.size();j++)
+    {
+      if(arrays[j])
+        arrays2[j]=arrays[j]->trace();
+      else
+        arrays2[j]=0;
+    }
+  std::vector<DataArrayDouble *> arrays3(arrays.size());
+  for(int j=0;j<(int)arrays.size();j++)
+    arrays3[j]=arrays2[j];
+  ret->setArrays(arrays3,0);
+  return ret;
+}
+
+MEDCouplingTimeDiscretization *MEDCouplingTimeDiscretization::deviator() const throw(INTERP_KERNEL::Exception)
+{
+  MEDCouplingTimeDiscretization *ret=MEDCouplingTimeDiscretization::New(getEnum());
+  std::vector<DataArrayDouble *> arrays;
+  getArrays(arrays);
+  std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> > arrays2(arrays.size());
+  for(int j=0;j<(int)arrays.size();j++)
+    {
+      if(arrays[j])
+        arrays2[j]=arrays[j]->deviator();
+      else
+        arrays2[j]=0;
+    }
+  std::vector<DataArrayDouble *> arrays3(arrays.size());
+  for(int j=0;j<(int)arrays.size();j++)
+    arrays3[j]=arrays2[j];
+  ret->setArrays(arrays3,0);
+  return ret;
+}
+
+MEDCouplingTimeDiscretization *MEDCouplingTimeDiscretization::magnitude() const throw(INTERP_KERNEL::Exception)
+{
+  MEDCouplingTimeDiscretization *ret=MEDCouplingTimeDiscretization::New(getEnum());
+  std::vector<DataArrayDouble *> arrays;
+  getArrays(arrays);
+  std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> > arrays2(arrays.size());
+  for(int j=0;j<(int)arrays.size();j++)
+    {
+      if(arrays[j])
+        arrays2[j]=arrays[j]->magnitude();
+      else
+        arrays2[j]=0;
+    }
+  std::vector<DataArrayDouble *> arrays3(arrays.size());
+  for(int j=0;j<(int)arrays.size();j++)
+    arrays3[j]=arrays2[j];
+  ret->setArrays(arrays3,0);
+  return ret;
+}
+
+MEDCouplingTimeDiscretization *MEDCouplingTimeDiscretization::maxPerTuple() const throw(INTERP_KERNEL::Exception)
+{
+  MEDCouplingTimeDiscretization *ret=MEDCouplingTimeDiscretization::New(getEnum());
+  std::vector<DataArrayDouble *> arrays;
+  getArrays(arrays);
+  std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> > arrays2(arrays.size());
+  for(int j=0;j<(int)arrays.size();j++)
+    {
+      if(arrays[j])
+        arrays2[j]=arrays[j]->maxPerTuple();
+      else
+        arrays2[j]=0;
+    }
+  std::vector<DataArrayDouble *> arrays3(arrays.size());
+  for(int j=0;j<(int)arrays.size();j++)
+    arrays3[j]=arrays2[j];
+  ret->setArrays(arrays3,0);
+  return ret;
+}
+
+void MEDCouplingTimeDiscretization::changeNbOfComponents(int newNbOfComp, double dftValue) throw(INTERP_KERNEL::Exception)
+{
+  std::vector<DataArrayDouble *> arrays;
+  getArrays(arrays);
+  std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> > arrays2(arrays.size());
+  for(int j=0;j<(int)arrays.size();j++)
+    {
+      if(arrays[j])
+        arrays2[j]=arrays[j]->changeNbOfComponents(newNbOfComp,dftValue);
+      else
+        arrays2[j]=0;
+    }
+  std::vector<DataArrayDouble *> arrays3(arrays.size());
+  for(int j=0;j<(int)arrays.size();j++)
+    arrays3[j]=arrays2[j];
+  setArrays(arrays3,0);
+}
+
+void MEDCouplingTimeDiscretization::sortPerTuple(bool asc) throw(INTERP_KERNEL::Exception)
+{
+  std::vector<DataArrayDouble *> arrays;
+  getArrays(arrays);
+  for(int j=0;j<(int)arrays.size();j++)
+    {
+      if(arrays[j])
+        arrays[j]->sortPerTuple(asc);
+    }
+}
+
 void MEDCouplingTimeDiscretization::applyLin(double a, double b, int compoId)
 {
-  double *ptr=_array->getPointer()+compoId;
-  int nbOfComp=_array->getNumberOfComponents();
-  int nbOfTuple=_array->getNumberOfTuples();
-  for(int i=0;i<nbOfTuple;i++,ptr+=nbOfComp)
-    *ptr=a*(*ptr)+b;
+  std::vector<DataArrayDouble *> arrays;
+  getArrays(arrays);
+  for(int j=0;j<(int)arrays.size();j++)
+    {
+      if(arrays[j])
+        arrays[j]->applyLin(a,b,compoId);
+    }
 }
 
 void MEDCouplingTimeDiscretization::applyFunc(int nbOfComp, FunctionToEvaluate func)
 {
-  DataArrayDouble *newArr=DataArrayDouble::New();
-  int nbOfTuples=_array->getNumberOfTuples();
-  int oldNbOfComp=_array->getNumberOfComponents();
-  newArr->alloc(nbOfTuples,nbOfComp);
-  const double *ptr=_array->getConstPointer();
-  double *ptrToFill=newArr->getPointer();
-  for(int i=0;i<nbOfTuples;i++)
+  std::vector<DataArrayDouble *> arrays;
+  getArrays(arrays);
+  std::vector<DataArrayDouble *> arrays2(arrays.size());
+  for(int j=0;j<(int)arrays.size();j++)
     {
-      if(!func(ptr+i*oldNbOfComp,ptrToFill+i*nbOfComp))
-        {
-          std::ostringstream oss; oss << "For tuple # " << i << " with value (";
-          std::copy(ptr+oldNbOfComp*i,ptr+oldNbOfComp*(i+1),std::ostream_iterator<double>(oss,", "));
-          oss << ") : Evaluation of function failed !";
-          newArr->decrRef();
-          throw INTERP_KERNEL::Exception(oss.str().c_str());
-        }
+      if(arrays[j])
+        arrays2[j]=arrays[j]->applyFunc(nbOfComp,func);
+      else
+        arrays2[j]=0;
     }
-  _array->decrRef();
-  _array=newArr;
+  setArrays(arrays2,0);
+  for(int j=0;j<(int)arrays.size();j++)
+    if(arrays2[j])
+      arrays2[j]->decrRef();
 }
 
 void MEDCouplingTimeDiscretization::applyFunc(int nbOfComp, const char *func)
 {
-  INTERP_KERNEL::ExprParser expr(func);
-  expr.parse();
-  std::set<std::string> vars;
-  expr.getTrueSetOfVars(vars);
-  int oldNbOfComp=_array->getNumberOfComponents();
-  if((int)vars.size()>oldNbOfComp)
+ std::vector<DataArrayDouble *> arrays;
+  getArrays(arrays);
+  std::vector<DataArrayDouble *> arrays2(arrays.size());
+  for(int j=0;j<(int)arrays.size();j++)
     {
-      std::ostringstream oss; oss << "The field has a " << oldNbOfComp << " components and there are ";
-      oss << vars.size() << " variables : ";
-      std::copy(vars.begin(),vars.end(),std::ostream_iterator<std::string>(oss," "));
-      throw INTERP_KERNEL::Exception(oss.str().c_str());
+      if(arrays[j])
+        arrays2[j]=arrays[j]->applyFunc(nbOfComp,func);
+      else
+        arrays2[j]=0;
     }
-  std::vector<std::string> varsV(vars.begin(),vars.end());
-  expr.prepareExprEvaluation(varsV);
-  //
-  DataArrayDouble *newArr=DataArrayDouble::New();
-  int nbOfTuples=_array->getNumberOfTuples();
-  newArr->alloc(nbOfTuples,nbOfComp);
-  const double *ptr=_array->getConstPointer();
-  double *ptrToFill=newArr->getPointer();
-  for(int i=0;i<nbOfTuples;i++)
+  setArrays(arrays2,0);
+  for(int j=0;j<(int)arrays.size();j++)
+    if(arrays2[j])
+      arrays2[j]->decrRef();
+}
+
+void MEDCouplingTimeDiscretization::applyFunc(const char *func)
+{
+  std::vector<DataArrayDouble *> arrays;
+  getArrays(arrays);
+  std::vector<DataArrayDouble *> arrays2(arrays.size());
+  for(int j=0;j<(int)arrays.size();j++)
     {
-      try
-        {
-          expr.evaluateExpr(nbOfComp,ptrToFill+i*nbOfComp,ptr+i*oldNbOfComp);
-        }
-      catch(INTERP_KERNEL::Exception& e)
-        {
-          std::ostringstream oss; oss << "For tuple # " << i << " with value (";
-          std::copy(ptr+oldNbOfComp*i,ptr+oldNbOfComp*(i+1),std::ostream_iterator<double>(oss,", "));
-          oss << ") : Evaluation of function failed !" << e.what();
-          newArr->decrRef();
-          throw INTERP_KERNEL::Exception(oss.str().c_str());
-        }
+      if(arrays[j])
+        arrays2[j]=arrays[j]->applyFunc(func);
+      else
+        arrays2[j]=0;
     }
-  _array->decrRef();
-  _array=newArr;
+  setArrays(arrays2,0);
+  for(int j=0;j<(int)arrays.size();j++)
+    if(arrays2[j])
+      arrays2[j]->decrRef();
 }
 
-void MEDCouplingTimeDiscretization::applyFunc(const char *func)
+void MEDCouplingTimeDiscretization::applyFuncFast32(const char *func)
+{
+  std::vector<DataArrayDouble *> arrays;
+  getArrays(arrays);
+  for(int j=0;j<(int)arrays.size();j++)
+    {
+      if(arrays[j])
+        arrays[j]->applyFuncFast32(func);
+    }
+}
+
+void MEDCouplingTimeDiscretization::applyFuncFast64(const char *func)
 {
-  INTERP_KERNEL::ExprParser expr(func);
-  expr.parse();
-  expr.prepareExprEvaluationVec();
-  //
-  DataArrayDouble *newArr=DataArrayDouble::New();
-  int nbOfTuples=_array->getNumberOfTuples();
-  int nbOfComp=_array->getNumberOfComponents();
-  newArr->alloc(nbOfTuples,nbOfComp);
-  const double *ptr=_array->getConstPointer();
-  double *ptrToFill=newArr->getPointer();
-  for(int i=0;i<nbOfTuples;i++)
+  std::vector<DataArrayDouble *> arrays;
+  getArrays(arrays);
+  for(int j=0;j<(int)arrays.size();j++)
     {
-      try
-        {
-          expr.evaluateExpr(nbOfComp,ptrToFill+i*nbOfComp,ptr+i*nbOfComp);
-        }
-      catch(INTERP_KERNEL::Exception& e)
-        {
-          std::ostringstream oss; oss << "For tuple # " << i << " with value (";
-          std::copy(ptr+nbOfComp*i,ptr+nbOfComp*(i+1),std::ostream_iterator<double>(oss,", "));
-          oss << ") : Evaluation of function failed ! " << e.what();
-          newArr->decrRef();
-          throw INTERP_KERNEL::Exception(oss.str().c_str());
-        }
+      if(arrays[j])
+        arrays[j]->applyFuncFast64(func);
     }
-  _array->decrRef();
-  _array=newArr;
 }
 
 MEDCouplingNoTimeLabel::MEDCouplingNoTimeLabel()
@@ -331,6 +588,13 @@ MEDCouplingNoTimeLabel::MEDCouplingNoTimeLabel(const MEDCouplingTimeDiscretizati
 {
 }
 
+std::string MEDCouplingNoTimeLabel::getStringRepr() const
+{
+  std::ostringstream stream;
+  stream << REPR;
+  return stream.str();
+}
+
 bool MEDCouplingNoTimeLabel::areCompatible(const MEDCouplingTimeDiscretization *other) const
 {
   if(!MEDCouplingTimeDiscretization::areCompatible(other))
@@ -339,9 +603,17 @@ bool MEDCouplingNoTimeLabel::areCompatible(const MEDCouplingTimeDiscretization *
   return otherC!=0;
 }
 
-bool MEDCouplingNoTimeLabel::areCompatibleForMul(const MEDCouplingTimeDiscretization *other) const
+bool MEDCouplingNoTimeLabel::areStrictlyCompatible(const MEDCouplingTimeDiscretization *other) const
+{
+  if(!MEDCouplingTimeDiscretization::areStrictlyCompatible(other))
+    return false;
+  const MEDCouplingNoTimeLabel *otherC=dynamic_cast<const MEDCouplingNoTimeLabel *>(other);
+  return otherC!=0;
+}
+
+bool MEDCouplingNoTimeLabel::areStrictlyCompatibleForMul(const MEDCouplingTimeDiscretization *other) const
 {
-  if(!MEDCouplingTimeDiscretization::areCompatibleForMul(other))
+  if(!MEDCouplingTimeDiscretization::areStrictlyCompatibleForMul(other))
     return false;
   const MEDCouplingNoTimeLabel *otherC=dynamic_cast<const MEDCouplingNoTimeLabel *>(other);
   return otherC!=0;
@@ -355,6 +627,14 @@ bool MEDCouplingNoTimeLabel::isEqual(const MEDCouplingTimeDiscretization *other,
   return MEDCouplingTimeDiscretization::isEqual(other,prec);
 }
 
+bool MEDCouplingNoTimeLabel::isEqualWithoutConsideringStr(const MEDCouplingTimeDiscretization *other, double prec) const
+{
+  const MEDCouplingNoTimeLabel *otherC=dynamic_cast<const MEDCouplingNoTimeLabel *>(other);
+  if(!otherC)
+    return false;
+  return MEDCouplingTimeDiscretization::isEqualWithoutConsideringStr(other,prec);
+}
+
 MEDCouplingTimeDiscretization *MEDCouplingNoTimeLabel::aggregate(const MEDCouplingTimeDiscretization *other) const
 {
   const MEDCouplingNoTimeLabel *otherC=dynamic_cast<const MEDCouplingNoTimeLabel *>(other);
@@ -368,6 +648,54 @@ MEDCouplingTimeDiscretization *MEDCouplingNoTimeLabel::aggregate(const MEDCoupli
   return ret;
 }
 
+MEDCouplingTimeDiscretization *MEDCouplingNoTimeLabel::dot(const MEDCouplingTimeDiscretization *other) const
+{
+  const MEDCouplingNoTimeLabel *otherC=dynamic_cast<const MEDCouplingNoTimeLabel *>(other);
+  if(!otherC)
+    throw INTERP_KERNEL::Exception("NoTimeLabel::dot on mismatched time discretization !");
+  MEDCouplingNoTimeLabel *ret=new MEDCouplingNoTimeLabel;
+  DataArrayDouble *arr=DataArrayDouble::dot(getArray(),other->getArray());
+  ret->setArray(arr,0);
+  arr->decrRef();
+  return ret;
+}
+
+MEDCouplingTimeDiscretization *MEDCouplingNoTimeLabel::crossProduct(const MEDCouplingTimeDiscretization *other) const
+{
+  const MEDCouplingNoTimeLabel *otherC=dynamic_cast<const MEDCouplingNoTimeLabel *>(other);
+  if(!otherC)
+    throw INTERP_KERNEL::Exception("NoTimeLabel::crossProduct on mismatched time discretization !");
+  MEDCouplingNoTimeLabel *ret=new MEDCouplingNoTimeLabel;
+  DataArrayDouble *arr=DataArrayDouble::crossProduct(getArray(),other->getArray());
+  ret->setArray(arr,0);
+  arr->decrRef();
+  return ret;
+}
+
+MEDCouplingTimeDiscretization *MEDCouplingNoTimeLabel::max(const MEDCouplingTimeDiscretization *other) const
+{
+  const MEDCouplingNoTimeLabel *otherC=dynamic_cast<const MEDCouplingNoTimeLabel *>(other);
+  if(!otherC)
+    throw INTERP_KERNEL::Exception("NoTimeLabel::max on mismatched time discretization !");
+  MEDCouplingNoTimeLabel *ret=new MEDCouplingNoTimeLabel;
+  DataArrayDouble *arr=DataArrayDouble::max(getArray(),other->getArray());
+  ret->setArray(arr,0);
+  arr->decrRef();
+  return ret;
+}
+
+MEDCouplingTimeDiscretization *MEDCouplingNoTimeLabel::min(const MEDCouplingTimeDiscretization *other) const
+{
+  const MEDCouplingNoTimeLabel *otherC=dynamic_cast<const MEDCouplingNoTimeLabel *>(other);
+  if(!otherC)
+    throw INTERP_KERNEL::Exception("NoTimeLabel::max on mismatched time discretization !");
+  MEDCouplingNoTimeLabel *ret=new MEDCouplingNoTimeLabel;
+  DataArrayDouble *arr=DataArrayDouble::min(getArray(),other->getArray());
+  ret->setArray(arr,0);
+  arr->decrRef();
+  return ret;
+}
+
 MEDCouplingTimeDiscretization *MEDCouplingNoTimeLabel::add(const MEDCouplingTimeDiscretization *other) const
 {
   const MEDCouplingNoTimeLabel *otherC=dynamic_cast<const MEDCouplingNoTimeLabel *>(other);
@@ -478,22 +806,22 @@ bool MEDCouplingNoTimeLabel::isStrictlyBefore(const MEDCouplingTimeDiscretizatio
   throw INTERP_KERNEL::Exception(EXCEPTION_MSG);
 }
 
-double MEDCouplingNoTimeLabel::getStartTime(int& dt, int& it) const throw(INTERP_KERNEL::Exception)
+double MEDCouplingNoTimeLabel::getStartTime(int& iteration, int& order) const throw(INTERP_KERNEL::Exception)
 {
   throw INTERP_KERNEL::Exception(EXCEPTION_MSG);
 }
 
-double MEDCouplingNoTimeLabel::getEndTime(int& dt, int& it) const throw(INTERP_KERNEL::Exception)
+double MEDCouplingNoTimeLabel::getEndTime(int& iteration, int& order) const throw(INTERP_KERNEL::Exception)
 {
   throw INTERP_KERNEL::Exception(EXCEPTION_MSG);
 }
 
-void MEDCouplingNoTimeLabel::setStartTime(double time, int dt, int it) throw(INTERP_KERNEL::Exception)
+void MEDCouplingNoTimeLabel::setStartTime(double time, int iteration, int order) throw(INTERP_KERNEL::Exception)
 {
   throw INTERP_KERNEL::Exception(EXCEPTION_MSG);
 }
 
-void MEDCouplingNoTimeLabel::setEndTime(double time, int dt, int it) throw(INTERP_KERNEL::Exception)
+void MEDCouplingNoTimeLabel::setEndTime(double time, int iteration, int order) throw(INTERP_KERNEL::Exception)
 {
   throw INTERP_KERNEL::Exception(EXCEPTION_MSG);
 }
@@ -503,25 +831,32 @@ void MEDCouplingNoTimeLabel::getValueOnTime(int eltId, double time, double *valu
   throw INTERP_KERNEL::Exception(EXCEPTION_MSG);
 }
 
-void MEDCouplingNoTimeLabel::getValueOnDiscTime(int eltId, int dt, int it, double *value) const throw(INTERP_KERNEL::Exception)
+void MEDCouplingNoTimeLabel::getValueOnDiscTime(int eltId, int iteration, int order, double *value) const throw(INTERP_KERNEL::Exception)
 {
   throw INTERP_KERNEL::Exception(EXCEPTION_MSG);
 }
 
 MEDCouplingWithTimeStep::MEDCouplingWithTimeStep(const MEDCouplingWithTimeStep& other, bool deepCpy):MEDCouplingTimeDiscretization(other,deepCpy),
-                                                                                                     _time(other._time),_dt(other._dt),_it(other._it)
+                                                                                                     _time(other._time),_iteration(other._iteration),_order(other._order)
+{
+}
+
+MEDCouplingWithTimeStep::MEDCouplingWithTimeStep():_time(0.),_iteration(-1),_order(-1)
 {
 }
 
-MEDCouplingWithTimeStep::MEDCouplingWithTimeStep():_time(0.),_dt(-1),_it(-1)
+std::string MEDCouplingWithTimeStep::getStringRepr() const
 {
+  std::ostringstream stream;
+  stream << REPR << " Time is defined by iteration=" << _iteration << " order=" << _order << " and time=" << _time << ".";
+  return stream.str();
 }
 
 void MEDCouplingWithTimeStep::getTinySerializationIntInformation(std::vector<int>& tinyInfo) const
 {
   MEDCouplingTimeDiscretization::getTinySerializationIntInformation(tinyInfo);
-  tinyInfo.push_back(_dt);
-  tinyInfo.push_back(_it);
+  tinyInfo.push_back(_iteration);
+  tinyInfo.push_back(_order);
 }
 
 void MEDCouplingWithTimeStep::getTinySerializationDbleInformation(std::vector<double>& tinyInfo) const
@@ -534,8 +869,8 @@ void MEDCouplingWithTimeStep::finishUnserialization(const std::vector<int>& tiny
 {
   MEDCouplingTimeDiscretization::finishUnserialization(tinyInfoI,tinyInfoD,tinyInfoS);
   _time=tinyInfoD[1];
-  _dt=tinyInfoI[2];
-  _it=tinyInfoI[3];
+  _iteration=tinyInfoI[2];
+  _order=tinyInfoI[3];
 }
 
 bool MEDCouplingWithTimeStep::areCompatible(const MEDCouplingTimeDiscretization *other) const
@@ -543,19 +878,23 @@ bool MEDCouplingWithTimeStep::areCompatible(const MEDCouplingTimeDiscretization
   if(!MEDCouplingTimeDiscretization::areCompatible(other))
     return false;
   const MEDCouplingWithTimeStep *otherC=dynamic_cast<const MEDCouplingWithTimeStep *>(other);
-  if(!otherC)
-    return false;
-  return std::fabs(_time-otherC->_time)<_time_tolerance;
+  return otherC!=0;
 }
 
-bool MEDCouplingWithTimeStep::areCompatibleForMul(const MEDCouplingTimeDiscretization *other) const
+bool MEDCouplingWithTimeStep::areStrictlyCompatible(const MEDCouplingTimeDiscretization *other) const
 {
-  if(!MEDCouplingTimeDiscretization::areCompatibleForMul(other))
+  if(!MEDCouplingTimeDiscretization::areStrictlyCompatible(other))
     return false;
   const MEDCouplingWithTimeStep *otherC=dynamic_cast<const MEDCouplingWithTimeStep *>(other);
-  if(!otherC)
+  return otherC!=0;
+}
+
+bool MEDCouplingWithTimeStep::areStrictlyCompatibleForMul(const MEDCouplingTimeDiscretization *other) const
+{
+  if(!MEDCouplingTimeDiscretization::areStrictlyCompatibleForMul(other))
     return false;
-  return std::fabs(_time-otherC->_time)<_time_tolerance;
+  const MEDCouplingWithTimeStep *otherC=dynamic_cast<const MEDCouplingWithTimeStep *>(other);
+  return otherC!=0;
 }
 
 bool MEDCouplingWithTimeStep::isEqual(const MEDCouplingTimeDiscretization *other, double prec) const
@@ -563,15 +902,38 @@ bool MEDCouplingWithTimeStep::isEqual(const MEDCouplingTimeDiscretization *other
   const MEDCouplingWithTimeStep *otherC=dynamic_cast<const MEDCouplingWithTimeStep *>(other);
   if(!otherC)
     return false;
-  if(_dt!=otherC->_dt)
+  if(_iteration!=otherC->_iteration)
     return false;
-  if(_it!=otherC->_it)
+  if(_order!=otherC->_order)
     return false;
   if(std::fabs(_time-otherC->_time)>_time_tolerance)
     return false;
   return MEDCouplingTimeDiscretization::isEqual(other,prec);
 }
 
+bool MEDCouplingWithTimeStep::isEqualWithoutConsideringStr(const MEDCouplingTimeDiscretization *other, double prec) const
+{
+  const MEDCouplingWithTimeStep *otherC=dynamic_cast<const MEDCouplingWithTimeStep *>(other);
+  if(!otherC)
+    return false;
+  if(_iteration!=otherC->_iteration)
+    return false;
+  if(_order!=otherC->_order)
+    return false;
+  if(std::fabs(_time-otherC->_time)>_time_tolerance)
+    return false;
+  return MEDCouplingTimeDiscretization::isEqualWithoutConsideringStr(other,prec);
+}
+
+void MEDCouplingWithTimeStep::copyTinyAttrFrom(const MEDCouplingTimeDiscretization& other)
+{
+  MEDCouplingTimeDiscretization::copyTinyAttrFrom(other);
+  const MEDCouplingWithTimeStep& otherC=dynamic_cast<const MEDCouplingWithTimeStep& >(other);
+  _time=otherC._time;
+  _iteration=otherC._iteration;
+  _order=otherC._order;
+}
+
 MEDCouplingTimeDiscretization *MEDCouplingWithTimeStep::aggregate(const MEDCouplingTimeDiscretization *other) const
 {
   const MEDCouplingWithTimeStep *otherC=dynamic_cast<const MEDCouplingWithTimeStep *>(other);
@@ -588,6 +950,54 @@ MEDCouplingTimeDiscretization *MEDCouplingWithTimeStep::aggregate(const MEDCoupl
   return ret;
 }
 
+MEDCouplingTimeDiscretization *MEDCouplingWithTimeStep::dot(const MEDCouplingTimeDiscretization *other) const
+{
+  const MEDCouplingWithTimeStep *otherC=dynamic_cast<const MEDCouplingWithTimeStep *>(other);
+  if(!otherC)
+    throw INTERP_KERNEL::Exception("WithTimeStep::dot on mismatched time discretization !");
+  MEDCouplingWithTimeStep *ret=new MEDCouplingWithTimeStep;
+  DataArrayDouble *arr=DataArrayDouble::dot(getArray(),other->getArray());
+  ret->setArray(arr,0);
+  arr->decrRef();
+  return ret;
+}
+
+MEDCouplingTimeDiscretization *MEDCouplingWithTimeStep::crossProduct(const MEDCouplingTimeDiscretization *other) const
+{
+  const MEDCouplingWithTimeStep *otherC=dynamic_cast<const MEDCouplingWithTimeStep *>(other);
+  if(!otherC)
+    throw INTERP_KERNEL::Exception("WithTimeStep::crossProduct on mismatched time discretization !");
+  MEDCouplingWithTimeStep *ret=new MEDCouplingWithTimeStep;
+  DataArrayDouble *arr=DataArrayDouble::crossProduct(getArray(),other->getArray());
+  ret->setArray(arr,0);
+  arr->decrRef();
+  return ret;
+}
+
+MEDCouplingTimeDiscretization *MEDCouplingWithTimeStep::max(const MEDCouplingTimeDiscretization *other) const
+{
+  const MEDCouplingWithTimeStep *otherC=dynamic_cast<const MEDCouplingWithTimeStep *>(other);
+  if(!otherC)
+    throw INTERP_KERNEL::Exception("WithTimeStep::max on mismatched time discretization !");
+  MEDCouplingWithTimeStep *ret=new MEDCouplingWithTimeStep;
+  DataArrayDouble *arr=DataArrayDouble::max(getArray(),other->getArray());
+  ret->setArray(arr,0);
+  arr->decrRef();
+  return ret;
+}
+
+MEDCouplingTimeDiscretization *MEDCouplingWithTimeStep::min(const MEDCouplingTimeDiscretization *other) const
+{
+  const MEDCouplingWithTimeStep *otherC=dynamic_cast<const MEDCouplingWithTimeStep *>(other);
+  if(!otherC)
+    throw INTERP_KERNEL::Exception("WithTimeStep::min on mismatched time discretization !");
+  MEDCouplingWithTimeStep *ret=new MEDCouplingWithTimeStep;
+  DataArrayDouble *arr=DataArrayDouble::min(getArray(),other->getArray());
+  ret->setArray(arr,0);
+  arr->decrRef();
+  return ret;
+}
+
 MEDCouplingTimeDiscretization *MEDCouplingWithTimeStep::add(const MEDCouplingTimeDiscretization *other) const
 {
   const MEDCouplingWithTimeStep *otherC=dynamic_cast<const MEDCouplingWithTimeStep *>(other);
@@ -728,9 +1138,9 @@ void MEDCouplingWithTimeStep::getValueOnTime(int eltId, double time, double *val
     throw INTERP_KERNEL::Exception(EXCEPTION_MSG);
 }
 
-void MEDCouplingWithTimeStep::getValueOnDiscTime(int eltId, int dt, int it, double *value) const throw(INTERP_KERNEL::Exception)
+void MEDCouplingWithTimeStep::getValueOnDiscTime(int eltId, int iteration, int order, double *value) const throw(INTERP_KERNEL::Exception)
 {
-  if(_dt==dt && _it==it)
+  if(_iteration==iteration && _order==order)
     if(_array)
       _array->getTuple(eltId,value);
     else
@@ -739,17 +1149,29 @@ void MEDCouplingWithTimeStep::getValueOnDiscTime(int eltId, int dt, int it, doub
     throw INTERP_KERNEL::Exception("No data on this discrete time.");
 }
 
-MEDCouplingConstOnTimeInterval::MEDCouplingConstOnTimeInterval():_start_time(0.),_end_time(0.),_start_dt(-1),_end_dt(-1),_start_it(-1),_end_it(-1)
+MEDCouplingConstOnTimeInterval::MEDCouplingConstOnTimeInterval():_start_time(0.),_end_time(0.),_start_iteration(-1),_end_iteration(-1),_start_order(-1),_end_order(-1)
 {
 }
 
+void MEDCouplingConstOnTimeInterval::copyTinyAttrFrom(const MEDCouplingTimeDiscretization& other)
+{
+  MEDCouplingTimeDiscretization::copyTinyAttrFrom(other);
+  const MEDCouplingConstOnTimeInterval& otherC=dynamic_cast<const MEDCouplingConstOnTimeInterval& >(other);
+  _start_time=otherC._start_time;
+  _end_time=otherC._end_time;
+  _start_iteration=otherC._start_iteration;
+  _end_iteration=otherC._end_iteration;
+  _start_order=otherC._start_order;
+  _end_order=otherC._end_order;
+}
+
 void MEDCouplingConstOnTimeInterval::getTinySerializationIntInformation(std::vector<int>& tinyInfo) const
 {
   MEDCouplingTimeDiscretization::getTinySerializationIntInformation(tinyInfo);
-  tinyInfo.push_back(_start_dt);
-  tinyInfo.push_back(_start_it);
-  tinyInfo.push_back(_end_dt);
-  tinyInfo.push_back(_end_it);
+  tinyInfo.push_back(_start_iteration);
+  tinyInfo.push_back(_start_order);
+  tinyInfo.push_back(_end_iteration);
+  tinyInfo.push_back(_end_order);
 }
 
 void MEDCouplingConstOnTimeInterval::getTinySerializationDbleInformation(std::vector<double>& tinyInfo) const
@@ -764,16 +1186,24 @@ void MEDCouplingConstOnTimeInterval::finishUnserialization(const std::vector<int
   MEDCouplingTimeDiscretization::finishUnserialization(tinyInfoI,tinyInfoD,tinyInfoS);
   _start_time=tinyInfoD[1];
   _end_time=tinyInfoD[2];
-  _start_dt=tinyInfoI[2];
-  _start_it=tinyInfoI[3];
-  _end_dt=tinyInfoI[4];
-  _end_it=tinyInfoI[5];
+  _start_iteration=tinyInfoI[2];
+  _start_order=tinyInfoI[3];
+  _end_iteration=tinyInfoI[4];
+  _end_order=tinyInfoI[5];
 }
 
 MEDCouplingConstOnTimeInterval::MEDCouplingConstOnTimeInterval(const MEDCouplingConstOnTimeInterval& other, bool deepCpy):
-  MEDCouplingTimeDiscretization(other,deepCpy),_start_time(other._start_time),_end_time(other._end_time),_start_dt(other._start_dt),
-  _end_dt(other._end_dt),_start_it(other._start_it),_end_it(other._end_it)
+  MEDCouplingTimeDiscretization(other,deepCpy),_start_time(other._start_time),_end_time(other._end_time),_start_iteration(other._start_iteration),
+  _end_iteration(other._end_iteration),_start_order(other._start_order),_end_order(other._end_order)
+{
+}
+
+std::string MEDCouplingConstOnTimeInterval::getStringRepr() const
 {
+  std::ostringstream stream;
+  stream << REPR << " Time interval is defined by :\niteration_start=" << _start_iteration << " order_start=" << _start_order << " and time_start=" << _start_time << "\n";
+  stream << "iteration_end=" << _end_iteration << " order_end=" << _end_order << " and end_time=" << _end_time << "\n";
+  return stream.str();
 }
 
 MEDCouplingTimeDiscretization *MEDCouplingConstOnTimeInterval::performCpy(bool deepCpy) const
@@ -803,19 +1233,23 @@ bool MEDCouplingConstOnTimeInterval::areCompatible(const MEDCouplingTimeDiscreti
   if(!MEDCouplingTimeDiscretization::areCompatible(other))
     return false;
   const MEDCouplingConstOnTimeInterval *otherC=dynamic_cast<const MEDCouplingConstOnTimeInterval *>(other);
-  if(!otherC)
-    return false;
-  return (std::fabs(_start_time-otherC->_start_time)<_time_tolerance && std::fabs(_end_time-otherC->_end_time)<_time_tolerance);
+  return otherC!=0;
 }
 
-bool MEDCouplingConstOnTimeInterval::areCompatibleForMul(const MEDCouplingTimeDiscretization *other) const
+bool MEDCouplingConstOnTimeInterval::areStrictlyCompatible(const MEDCouplingTimeDiscretization *other) const
 {
-  if(!MEDCouplingTimeDiscretization::areCompatible(other))
+  if(!MEDCouplingTimeDiscretization::areStrictlyCompatible(other))
     return false;
   const MEDCouplingConstOnTimeInterval *otherC=dynamic_cast<const MEDCouplingConstOnTimeInterval *>(other);
-  if(!otherC)
+  return otherC!=0;
+}
+
+bool MEDCouplingConstOnTimeInterval::areStrictlyCompatibleForMul(const MEDCouplingTimeDiscretization *other) const
+{
+  if(!MEDCouplingTimeDiscretization::areStrictlyCompatible(other))
     return false;
-  return (std::fabs(_start_time-otherC->_start_time)<_time_tolerance && std::fabs(_end_time-otherC->_end_time)<_time_tolerance);
+  const MEDCouplingConstOnTimeInterval *otherC=dynamic_cast<const MEDCouplingConstOnTimeInterval *>(other);
+  return otherC!=0;
 }
 
 bool MEDCouplingConstOnTimeInterval::isEqual(const MEDCouplingTimeDiscretization *other, double prec) const
@@ -823,21 +1257,41 @@ bool MEDCouplingConstOnTimeInterval::isEqual(const MEDCouplingTimeDiscretization
   const MEDCouplingConstOnTimeInterval *otherC=dynamic_cast<const MEDCouplingConstOnTimeInterval *>(other);
   if(!otherC)
     return false;
-  if(_start_dt!=otherC->_start_dt)
+  if(_start_iteration!=otherC->_start_iteration)
     return false;
-  if(_start_it!=otherC->_start_it)
+  if(_start_order!=otherC->_start_order)
     return false;
   if(std::fabs(_start_time-otherC->_start_time)>_time_tolerance)
     return false;
-  if(_end_dt!=otherC->_end_dt)
+  if(_end_iteration!=otherC->_end_iteration)
     return false;
-  if(_end_it!=otherC->_end_it)
+  if(_end_order!=otherC->_end_order)
     return false;
   if(std::fabs(_end_time-otherC->_end_time)>_time_tolerance)
     return false;
   return MEDCouplingTimeDiscretization::isEqual(other,prec);
 }
 
+bool MEDCouplingConstOnTimeInterval::isEqualWithoutConsideringStr(const MEDCouplingTimeDiscretization *other, double prec) const
+{
+  const MEDCouplingConstOnTimeInterval *otherC=dynamic_cast<const MEDCouplingConstOnTimeInterval *>(other);
+  if(!otherC)
+    return false;
+  if(_start_iteration!=otherC->_start_iteration)
+    return false;
+  if(_start_order!=otherC->_start_order)
+    return false;
+  if(std::fabs(_start_time-otherC->_start_time)>_time_tolerance)
+    return false;
+  if(_end_iteration!=otherC->_end_iteration)
+    return false;
+  if(_end_order!=otherC->_end_order)
+    return false;
+  if(std::fabs(_end_time-otherC->_end_time)>_time_tolerance)
+    return false;
+  return MEDCouplingTimeDiscretization::isEqualWithoutConsideringStr(other,prec);
+}
+
 void MEDCouplingConstOnTimeInterval::getValueOnTime(int eltId, double time, double *value) const throw(INTERP_KERNEL::Exception)
 {
   if(time>_start_time-_time_tolerance && time<_end_time+_time_tolerance)
@@ -849,9 +1303,9 @@ void MEDCouplingConstOnTimeInterval::getValueOnTime(int eltId, double time, doub
     throw INTERP_KERNEL::Exception(EXCEPTION_MSG);
 }
 
-void MEDCouplingConstOnTimeInterval::getValueOnDiscTime(int eltId, int dt, int it, double *value) const throw(INTERP_KERNEL::Exception)
+void MEDCouplingConstOnTimeInterval::getValueOnDiscTime(int eltId, int iteration, int order, double *value) const throw(INTERP_KERNEL::Exception)
 {
-  if(dt>=_start_dt && dt<=_end_dt)
+  if(iteration>=_start_iteration && iteration<=_end_iteration)
     if(_array)
       _array->getTuple(eltId,value);
     else
@@ -870,7 +1324,7 @@ void MEDCouplingConstOnTimeInterval::checkTimePresence(double time) const throw(
   if(time<_start_time-_time_tolerance || time>_end_time+_time_tolerance)
     {
       std::ostringstream stream;
-      stream << "The field is defined between times " << _start_time << " and " << _end_time << " with tolerance ";
+      stream << "The field is defined between times " << _start_time << " and " << _end_time << " worderh tolerance ";
       stream << _time_tolerance << " and trying to access on time = " << time;
       throw INTERP_KERNEL::Exception(stream.str().c_str());
     }
@@ -894,6 +1348,54 @@ MEDCouplingTimeDiscretization *MEDCouplingConstOnTimeInterval::aggregate(const M
   return ret;
 }
 
+MEDCouplingTimeDiscretization *MEDCouplingConstOnTimeInterval::dot(const MEDCouplingTimeDiscretization *other) const
+{
+  const MEDCouplingConstOnTimeInterval *otherC=dynamic_cast<const MEDCouplingConstOnTimeInterval *>(other);
+  if(!otherC)
+    throw INTERP_KERNEL::Exception("ConstOnTimeInterval::dot on mismatched time discretization !");
+  MEDCouplingConstOnTimeInterval *ret=new MEDCouplingConstOnTimeInterval;
+  DataArrayDouble *arr=DataArrayDouble::dot(getArray(),other->getArray());
+  ret->setArray(arr,0);
+  arr->decrRef();
+  return ret;
+}
+
+MEDCouplingTimeDiscretization *MEDCouplingConstOnTimeInterval::crossProduct(const MEDCouplingTimeDiscretization *other) const
+{
+  const MEDCouplingConstOnTimeInterval *otherC=dynamic_cast<const MEDCouplingConstOnTimeInterval *>(other);
+  if(!otherC)
+    throw INTERP_KERNEL::Exception("ConstOnTimeInterval::crossProduct on mismatched time discretization !");
+  MEDCouplingConstOnTimeInterval *ret=new MEDCouplingConstOnTimeInterval;
+  DataArrayDouble *arr=DataArrayDouble::crossProduct(getArray(),other->getArray());
+  ret->setArray(arr,0);
+  arr->decrRef();
+  return ret;
+}
+
+MEDCouplingTimeDiscretization *MEDCouplingConstOnTimeInterval::max(const MEDCouplingTimeDiscretization *other) const
+{
+  const MEDCouplingConstOnTimeInterval *otherC=dynamic_cast<const MEDCouplingConstOnTimeInterval *>(other);
+  if(!otherC)
+    throw INTERP_KERNEL::Exception("ConstOnTimeInterval::max on mismatched time discretization !");
+  MEDCouplingConstOnTimeInterval *ret=new MEDCouplingConstOnTimeInterval;
+  DataArrayDouble *arr=DataArrayDouble::max(getArray(),other->getArray());
+  ret->setArray(arr,0);
+  arr->decrRef();
+  return ret;
+}
+
+MEDCouplingTimeDiscretization *MEDCouplingConstOnTimeInterval::min(const MEDCouplingTimeDiscretization *other) const
+{
+  const MEDCouplingConstOnTimeInterval *otherC=dynamic_cast<const MEDCouplingConstOnTimeInterval *>(other);
+  if(!otherC)
+    throw INTERP_KERNEL::Exception("ConstOnTimeInterval::min on mismatched time discretization !");
+  MEDCouplingConstOnTimeInterval *ret=new MEDCouplingConstOnTimeInterval;
+  DataArrayDouble *arr=DataArrayDouble::min(getArray(),other->getArray());
+  ret->setArray(arr,0);
+  arr->decrRef();
+  return ret;
+}
+
 MEDCouplingTimeDiscretization *MEDCouplingConstOnTimeInterval::add(const MEDCouplingTimeDiscretization *other) const
 {
   const MEDCouplingConstOnTimeInterval *otherC=dynamic_cast<const MEDCouplingConstOnTimeInterval *>(other);
@@ -994,7 +1496,109 @@ void MEDCouplingConstOnTimeInterval::divideEqual(const MEDCouplingTimeDiscretiza
   getArray()->divideEqual(other->getArray());
 }
 
-MEDCouplingTwoTimeSteps::MEDCouplingTwoTimeSteps():_start_time(0.),_end_time(0.),_start_dt(-1),_end_dt(-1),_start_it(-1),_end_it(-1),_end_array(0)
+MEDCouplingTwoTimeSteps::MEDCouplingTwoTimeSteps(const MEDCouplingTwoTimeSteps& other, bool deepCpy):MEDCouplingTimeDiscretization(other,deepCpy),
+                                                                                                     _start_time(other._start_time),_end_time(other._end_time),
+                                                                                                     _start_iteration(other._start_iteration),_end_iteration(other._end_iteration),
+                                                                                                     _start_order(other._start_order),_end_order(other._end_order)
+{
+  if(other._end_array)
+    _end_array=other._end_array->performCpy(deepCpy);
+  else
+    _end_array=0;
+}
+
+void MEDCouplingTwoTimeSteps::updateTime()
+{
+  MEDCouplingTimeDiscretization::updateTime();
+  if(_end_array)
+    updateTimeWith(*_end_array);
+}
+
+void MEDCouplingTwoTimeSteps::copyTinyAttrFrom(const MEDCouplingTimeDiscretization& other)
+{
+  MEDCouplingTimeDiscretization::copyTinyAttrFrom(other);
+  const MEDCouplingTwoTimeSteps& otherC=dynamic_cast<const MEDCouplingTwoTimeSteps& >(other);
+  _start_time=otherC._start_time;
+  _end_time=otherC._end_time;
+  _start_iteration=otherC._start_iteration;
+  _end_iteration=otherC._end_iteration;
+  _start_order=otherC._start_order;
+  _end_order=otherC._end_order;
+}
+
+void MEDCouplingTwoTimeSteps::copyTinyStringsFrom(const MEDCouplingTimeDiscretization& other)
+{
+  MEDCouplingTimeDiscretization::copyTinyStringsFrom(other);
+  const MEDCouplingTwoTimeSteps* otherC=dynamic_cast<const MEDCouplingTwoTimeSteps* >(&other);
+  if(!otherC)
+    throw INTERP_KERNEL::Exception("Trying to operate copyTinyStringsFrom on different field type (two times//one time) !");
+  if(_end_array && otherC->_end_array)
+    _end_array->copyStringInfoFrom(*otherC->_end_array);
+}
+
+DataArrayDouble *MEDCouplingTwoTimeSteps::getEndArray() const
+{
+  return _end_array;
+}
+
+void MEDCouplingTwoTimeSteps::checkCoherency() const throw(INTERP_KERNEL::Exception)
+{
+  MEDCouplingTimeDiscretization::checkCoherency();
+  if(!_end_array)
+    throw INTERP_KERNEL::Exception("No end array specified !");
+  if(_array->getNumberOfComponents()!=_end_array->getNumberOfComponents())
+    throw INTERP_KERNEL::Exception("The number of components mismatch between the start and the end arrays !");
+  if(_array->getNumberOfTuples()!=_end_array->getNumberOfTuples())
+    throw INTERP_KERNEL::Exception("The number of tuples mismatch between the start and the end arrays !");
+}
+
+bool MEDCouplingTwoTimeSteps::isEqual(const MEDCouplingTimeDiscretization *other, double prec) const
+{
+  const MEDCouplingTwoTimeSteps *otherC=dynamic_cast<const MEDCouplingTwoTimeSteps *>(other);
+  if(!otherC)
+    return false;
+  if(_start_iteration!=otherC->_start_iteration)
+    return false;
+  if(_end_iteration!=otherC->_end_iteration)
+    return false;
+  if(_start_order!=otherC->_start_order)
+    return false;
+  if(_end_order!=otherC->_end_order)
+    return false;
+  if(std::fabs(_start_time-otherC->_start_time)>_time_tolerance)
+    return false;
+  if(std::fabs(_end_time-otherC->_end_time)>_time_tolerance)
+    return false;
+  if(_end_array!=otherC->_end_array)
+    if(!_end_array->isEqual(*otherC->_end_array,prec))
+      return false;
+  return MEDCouplingTimeDiscretization::isEqual(other,prec);
+}
+
+bool MEDCouplingTwoTimeSteps::isEqualWithoutConsideringStr(const MEDCouplingTimeDiscretization *other, double prec) const
+{
+  const MEDCouplingTwoTimeSteps *otherC=dynamic_cast<const MEDCouplingTwoTimeSteps *>(other);
+  if(!otherC)
+    return false;
+  if(_start_iteration!=otherC->_start_iteration)
+    return false;
+  if(_end_iteration!=otherC->_end_iteration)
+    return false;
+  if(_start_order!=otherC->_start_order)
+    return false;
+  if(_end_order!=otherC->_end_order)
+    return false;
+  if(std::fabs(_start_time-otherC->_start_time)>_time_tolerance)
+    return false;
+  if(std::fabs(_end_time-otherC->_end_time)>_time_tolerance)
+    return false;
+  if(_end_array!=otherC->_end_array)
+    if(!_end_array->isEqualWithoutConsideringStr(*otherC->_end_array,prec))
+      return false;
+  return MEDCouplingTimeDiscretization::isEqualWithoutConsideringStr(other,prec);
+}
+
+MEDCouplingTwoTimeSteps::MEDCouplingTwoTimeSteps():_start_time(0.),_end_time(0.),_start_iteration(-1),_end_iteration(-1),_start_order(-1),_end_order(-1),_end_array(0)
 {
 }
 
@@ -1014,7 +1618,7 @@ void MEDCouplingTwoTimeSteps::checkTimePresence(double time) const throw(INTERP_
   if(time<_start_time-_time_tolerance || time>_end_time+_time_tolerance)
     {
       std::ostringstream stream;
-      stream << "The field is defined between times " << _start_time << " and " << _end_time << " with tolerance ";
+      stream << "The field is defined between times " << _start_time << " and " << _end_time << " worderh tolerance ";
       stream << _time_tolerance << " and trying to access on time = " << time;
       throw INTERP_KERNEL::Exception(stream.str().c_str());
     }
@@ -1027,6 +1631,55 @@ void MEDCouplingTwoTimeSteps::getArrays(std::vector<DataArrayDouble *>& arrays)
   arrays[1]=_end_array;
 }
 
+void MEDCouplingTwoTimeSteps::setEndArray(DataArrayDouble *array, TimeLabel *owner)
+{
+  if(array!=_end_array)
+    {
+      if(_end_array)
+        _end_array->decrRef();
+      _end_array=array;
+      if(_end_array)
+        _end_array->incrRef();
+      if(owner)
+        owner->declareAsNew();
+    }
+}
+
+void MEDCouplingTwoTimeSteps::getTinySerializationIntInformation(std::vector<int>& tinyInfo) const
+{
+  MEDCouplingTimeDiscretization::getTinySerializationIntInformation(tinyInfo);
+  tinyInfo.push_back(_start_iteration);
+  tinyInfo.push_back(_start_order);
+  tinyInfo.push_back(_end_iteration);
+  tinyInfo.push_back(_end_order);
+  if(_end_array)
+    {
+      tinyInfo.push_back(_end_array->getNumberOfTuples());
+      tinyInfo.push_back(_end_array->getNumberOfComponents());
+    }
+  else
+    {
+      tinyInfo.push_back(-1);
+      tinyInfo.push_back(-1);
+    }
+}
+
+void MEDCouplingTwoTimeSteps::getTinySerializationDbleInformation(std::vector<double>& tinyInfo) const
+{
+  MEDCouplingTimeDiscretization::getTinySerializationDbleInformation(tinyInfo);
+  tinyInfo.push_back(_start_time);
+  tinyInfo.push_back(_end_time);
+}
+
+void MEDCouplingTwoTimeSteps::getTinySerializationStrInformation(std::vector<std::string>& tinyInfo) const
+{
+  int nbOfCompo=_array->getNumberOfComponents();
+  for(int i=0;i<nbOfCompo;i++)
+    tinyInfo.push_back(_array->getInfoOnComponent(i));
+  for(int i=0;i<nbOfCompo;i++)
+    tinyInfo.push_back(_end_array->getInfoOnComponent(i));
+}
+
 void MEDCouplingTwoTimeSteps::resizeForUnserialization(const std::vector<int>& tinyInfoI, std::vector<DataArrayDouble *>& arrays)
 {
   arrays.resize(2);
@@ -1043,10 +1696,10 @@ void MEDCouplingTwoTimeSteps::resizeForUnserialization(const std::vector<int>& t
   _array=arr;
   arrays[0]=arr;
   arr=0;
-  if(tinyInfoI[2]!=-1 && tinyInfoI[3]!=-1)
+  if(tinyInfoI[6]!=-1 && tinyInfoI[7]!=-1)
     {
       arr=DataArrayDouble::New();
-      arr->alloc(tinyInfoI[2],tinyInfoI[3]);
+      arr->alloc(tinyInfoI[6],tinyInfoI[7]);
     }
   _end_array=arr;
   arrays[1]=arr;
@@ -1057,8 +1710,305 @@ void MEDCouplingTwoTimeSteps::finishUnserialization(const std::vector<int>& tiny
   MEDCouplingTimeDiscretization::finishUnserialization(tinyInfoI,tinyInfoD,tinyInfoS);
   _start_time=tinyInfoD[1];
   _end_time=tinyInfoD[2];
-  _start_dt=tinyInfoI[2];
-  _end_dt=tinyInfoI[3];
-  _start_it=tinyInfoI[4];
-  _end_it=tinyInfoI[5];
+  _start_iteration=tinyInfoI[2];
+  _start_order=tinyInfoI[3];
+  _end_iteration=tinyInfoI[4];
+  _end_order=tinyInfoI[5];
+}
+
+std::vector< const DataArrayDouble *> MEDCouplingTwoTimeSteps::getArraysForTime(double time) const throw(INTERP_KERNEL::Exception)
+{
+   if(time>_start_time-_time_tolerance && time<_end_time+_time_tolerance)
+    {
+      std::vector< const DataArrayDouble *> ret(2);
+      ret[0]=_array;
+      ret[1]=_end_array;
+      return ret;
+    }
+  else
+    throw INTERP_KERNEL::Exception(EXCEPTION_MSG);
+}
+
+void MEDCouplingTwoTimeSteps::setArrays(const std::vector<DataArrayDouble *>& arrays, TimeLabel *owner) throw(INTERP_KERNEL::Exception)
+{
+  if(arrays.size()!=2)
+    throw INTERP_KERNEL::Exception("MEDCouplingTwoTimeSteps::setArrays : number of arrays must be two.");
+  setArray(arrays.front(),owner);
+  setEndArray(arrays.back(),owner);
+}
+
+MEDCouplingLinearTime::MEDCouplingLinearTime(const MEDCouplingLinearTime& other, bool deepCpy):MEDCouplingTwoTimeSteps(other,deepCpy)
+{
+}
+
+MEDCouplingLinearTime::MEDCouplingLinearTime()
+{
+}
+
+std::string MEDCouplingLinearTime::getStringRepr() const
+{
+  std::ostringstream stream;
+  stream << REPR << " Time interval is defined by :\niteration_start=" << _start_iteration << " order_start=" << _start_order << " and time_start=" << _start_time << "\n";
+  stream << "iteration_end=" << _end_iteration << " order_end=" << _end_order << " and end_time=" << _end_time << "\n";
+  return stream.str();
+}
+
+void MEDCouplingLinearTime::checkCoherency() const throw(INTERP_KERNEL::Exception)
+{
+  MEDCouplingTwoTimeSteps::checkCoherency();
+  if(std::fabs(_start_time-_end_time)<_time_tolerance)
+    throw INTERP_KERNEL::Exception("Start time and end time are equals regarding time tolerance.");
+}
+
+MEDCouplingTimeDiscretization *MEDCouplingLinearTime::performCpy(bool deepCpy) const
+{
+  return new MEDCouplingLinearTime(*this,deepCpy);
+}
+
+bool MEDCouplingLinearTime::areCompatible(const MEDCouplingTimeDiscretization *other) const
+{
+  if(!MEDCouplingTimeDiscretization::areCompatible(other))
+    return false;
+  const MEDCouplingLinearTime *otherC=dynamic_cast<const MEDCouplingLinearTime *>(other);
+  return otherC!=0;
+}
+
+bool MEDCouplingLinearTime::areStrictlyCompatible(const MEDCouplingTimeDiscretization *other) const
+{
+  if(!MEDCouplingTimeDiscretization::areStrictlyCompatible(other))
+    return false;
+  const MEDCouplingLinearTime *otherC=dynamic_cast<const MEDCouplingLinearTime *>(other);
+  return otherC!=0;
+}
+
+bool MEDCouplingLinearTime::areStrictlyCompatibleForMul(const MEDCouplingTimeDiscretization *other) const
+{
+  if(!MEDCouplingTimeDiscretization::areStrictlyCompatibleForMul(other))
+    return false;
+  const MEDCouplingLinearTime *otherC=dynamic_cast<const MEDCouplingLinearTime *>(other);
+  return otherC!=0;
+}
+
+/*!
+ * vals is expected to be of size 2*_array->getNumberOfTuples()==_array->getNumberOfTuples()+_end_array->getNumberOfTuples()
+ */
+void MEDCouplingLinearTime::getValueForTime(double time, const std::vector<double>& vals, double *res) const
+{
+  double alpha=(_end_time-time)/(_end_time-_start_time);
+  int nbComp=vals.size()/2;
+  std::transform(vals.begin(),vals.begin()+nbComp,res,std::bind2nd(std::multiplies<double>(),alpha));
+  std::vector<double> tmp(nbComp);
+  std::transform(vals.begin()+nbComp,vals.end(),tmp.begin(),std::bind2nd(std::multiplies<double>(),1-alpha));
+  std::transform(tmp.begin(),tmp.end(),res,res,std::plus<double>());
+}
+
+void MEDCouplingLinearTime::getValueOnTime(int eltId, double time, double *value) const throw(INTERP_KERNEL::Exception)
+{
+  double alpha=(_end_time-time)/(_end_time-_start_time);
+  int nbComp;
+  if(_array)
+    _array->getTuple(eltId,value);
+  else
+    throw INTERP_KERNEL::Exception("No start array existing.");
+  nbComp=_array->getNumberOfComponents();
+  std::transform(value,value+nbComp,value,std::bind2nd(std::multiplies<double>(),alpha));
+  std::vector<double> tmp(nbComp);
+  if(_end_array)
+    _end_array->getTuple(eltId,&tmp[0]);
+  else
+    throw INTERP_KERNEL::Exception("No end array existing.");
+  std::transform(tmp.begin(),tmp.end(),tmp.begin(),std::bind2nd(std::multiplies<double>(),1-alpha));
+  std::transform(tmp.begin(),tmp.end(),value,value,std::plus<double>());
+}
+
+void MEDCouplingLinearTime::getValueOnDiscTime(int eltId, int iteration, int order, double *value) const throw(INTERP_KERNEL::Exception)
+{
+  if(iteration==_start_iteration && order==_start_order)
+    {
+      if(_array)
+        _array->getTuple(eltId,value);
+      else
+        throw INTERP_KERNEL::Exception("iteration order match with start time but no start array existing.");
+    }
+  if(iteration==_end_iteration && order==_end_order)
+    {
+      if(_end_array)
+        _end_array->getTuple(eltId,value);
+      else
+        throw INTERP_KERNEL::Exception("iteration order match with end time but no end array existing.");
+    }
+  else
+    throw INTERP_KERNEL::Exception(EXCEPTION_MSG);
+}
+
+MEDCouplingTimeDiscretization *MEDCouplingLinearTime::aggregate(const MEDCouplingTimeDiscretization *other) const
+{
+  const MEDCouplingLinearTime *otherC=dynamic_cast<const MEDCouplingLinearTime *>(other);
+  if(!otherC)
+    throw INTERP_KERNEL::Exception("LinearTime::aggregation on mismatched time discretization !");
+  MEDCouplingLinearTime *ret=new MEDCouplingLinearTime;
+  ret->setTimeTolerance(getTimeTolerance());
+  DataArrayDouble *arr1=DataArrayDouble::aggregate(getArray(),other->getArray());
+  ret->setArray(arr1,0);
+  arr1->decrRef();
+  DataArrayDouble *arr2=DataArrayDouble::aggregate(getEndArray(),other->getEndArray());
+  ret->setEndArray(arr2,0);
+  arr2->decrRef();
+  return ret;
+}
+
+MEDCouplingTimeDiscretization *MEDCouplingLinearTime::dot(const MEDCouplingTimeDiscretization *other) const
+{
+  const MEDCouplingLinearTime *otherC=dynamic_cast<const MEDCouplingLinearTime *>(other);
+  if(!otherC)
+    throw INTERP_KERNEL::Exception("LinearTime::dot on mismatched time discretization !");
+  MEDCouplingLinearTime *ret=new MEDCouplingLinearTime;
+  DataArrayDouble *arr1=DataArrayDouble::dot(getArray(),other->getArray());
+  ret->setArray(arr1,0);
+  arr1->decrRef();
+  DataArrayDouble *arr2=DataArrayDouble::dot(getEndArray(),other->getEndArray());
+  ret->setEndArray(arr2,0);
+  arr2->decrRef();
+  return ret;
+}
+
+MEDCouplingTimeDiscretization *MEDCouplingLinearTime::crossProduct(const MEDCouplingTimeDiscretization *other) const
+{
+  const MEDCouplingLinearTime *otherC=dynamic_cast<const MEDCouplingLinearTime *>(other);
+  if(!otherC)
+    throw INTERP_KERNEL::Exception("LinearTime::crossProduct on mismatched time discretization !");
+  MEDCouplingLinearTime *ret=new MEDCouplingLinearTime;
+  DataArrayDouble *arr1=DataArrayDouble::crossProduct(getArray(),other->getArray());
+  ret->setArray(arr1,0);
+  arr1->decrRef();
+  DataArrayDouble *arr2=DataArrayDouble::crossProduct(getEndArray(),other->getEndArray());
+  ret->setEndArray(arr2,0);
+  arr2->decrRef();
+  return ret;
+}
+
+MEDCouplingTimeDiscretization *MEDCouplingLinearTime::max(const MEDCouplingTimeDiscretization *other) const
+{
+  const MEDCouplingLinearTime *otherC=dynamic_cast<const MEDCouplingLinearTime *>(other);
+  if(!otherC)
+    throw INTERP_KERNEL::Exception("LinearTime::max on mismatched time discretization !");
+  MEDCouplingLinearTime *ret=new MEDCouplingLinearTime;
+  DataArrayDouble *arr1=DataArrayDouble::max(getArray(),other->getArray());
+  ret->setArray(arr1,0);
+  arr1->decrRef();
+  DataArrayDouble *arr2=DataArrayDouble::max(getEndArray(),other->getEndArray());
+  ret->setEndArray(arr2,0);
+  arr2->decrRef();
+  return ret;
+}
+
+MEDCouplingTimeDiscretization *MEDCouplingLinearTime::min(const MEDCouplingTimeDiscretization *other) const
+{
+  const MEDCouplingLinearTime *otherC=dynamic_cast<const MEDCouplingLinearTime *>(other);
+  if(!otherC)
+    throw INTERP_KERNEL::Exception("LinearTime::min on mismatched time discretization !");
+  MEDCouplingLinearTime *ret=new MEDCouplingLinearTime;
+  DataArrayDouble *arr1=DataArrayDouble::min(getArray(),other->getArray());
+  ret->setArray(arr1,0);
+  arr1->decrRef();
+  DataArrayDouble *arr2=DataArrayDouble::min(getEndArray(),other->getEndArray());
+  ret->setEndArray(arr2,0);
+  arr2->decrRef();
+  return ret;
+}
+
+MEDCouplingTimeDiscretization *MEDCouplingLinearTime::add(const MEDCouplingTimeDiscretization *other) const
+{
+  const MEDCouplingLinearTime *otherC=dynamic_cast<const MEDCouplingLinearTime *>(other);
+  if(!otherC)
+    throw INTERP_KERNEL::Exception("LinearTime::add on mismatched time discretization !");
+  MEDCouplingLinearTime *ret=new MEDCouplingLinearTime;
+  DataArrayDouble *arr1=DataArrayDouble::add(getArray(),other->getArray());
+  ret->setArray(arr1,0);
+  arr1->decrRef();
+  DataArrayDouble *arr2=DataArrayDouble::add(getEndArray(),other->getEndArray());
+  ret->setEndArray(arr2,0);
+  arr2->decrRef();
+  return ret;
+}
+
+void MEDCouplingLinearTime::addEqual(const MEDCouplingTimeDiscretization *other)
+{
+  const MEDCouplingLinearTime *otherC=dynamic_cast<const MEDCouplingLinearTime *>(other);
+  if(!otherC)
+    throw INTERP_KERNEL::Exception("LinearTime::addEqual on mismatched time discretization !");
+  getArray()->addEqual(other->getArray());
+  getEndArray()->addEqual(other->getEndArray());
+}
+
+MEDCouplingTimeDiscretization *MEDCouplingLinearTime::substract(const MEDCouplingTimeDiscretization *other) const
+{
+  const MEDCouplingLinearTime *otherC=dynamic_cast<const MEDCouplingLinearTime *>(other);
+  if(!otherC)
+    throw INTERP_KERNEL::Exception("LinearTime::substract on mismatched time discretization !");
+  MEDCouplingLinearTime *ret=new MEDCouplingLinearTime;
+  DataArrayDouble *arr1=DataArrayDouble::substract(getArray(),other->getArray());
+  ret->setArray(arr1,0);
+  arr1->decrRef();
+  DataArrayDouble *arr2=DataArrayDouble::substract(getEndArray(),other->getEndArray());
+  ret->setEndArray(arr2,0);
+  arr2->decrRef();
+  return ret;
+}
+
+void MEDCouplingLinearTime::substractEqual(const MEDCouplingTimeDiscretization *other)
+{
+  const MEDCouplingLinearTime *otherC=dynamic_cast<const MEDCouplingLinearTime *>(other);
+  if(!otherC)
+    throw INTERP_KERNEL::Exception("LinearTime::addEqual on mismatched time discretization !");
+  getArray()->substractEqual(other->getArray());
+  getEndArray()->substractEqual(other->getEndArray());
+}
+
+MEDCouplingTimeDiscretization *MEDCouplingLinearTime::multiply(const MEDCouplingTimeDiscretization *other) const
+{
+  const MEDCouplingLinearTime *otherC=dynamic_cast<const MEDCouplingLinearTime *>(other);
+  if(!otherC)
+    throw INTERP_KERNEL::Exception("LinearTime::multiply on mismatched time discretization !");
+  MEDCouplingLinearTime *ret=new MEDCouplingLinearTime;
+  DataArrayDouble *arr1=DataArrayDouble::multiply(getArray(),other->getArray());
+  ret->setArray(arr1,0);
+  arr1->decrRef();
+  DataArrayDouble *arr2=DataArrayDouble::multiply(getEndArray(),other->getEndArray());
+  ret->setEndArray(arr2,0);
+  arr2->decrRef();
+  return ret;
+}
+
+void MEDCouplingLinearTime::multiplyEqual(const MEDCouplingTimeDiscretization *other)
+{
+  const MEDCouplingLinearTime *otherC=dynamic_cast<const MEDCouplingLinearTime *>(other);
+  if(!otherC)
+    throw INTERP_KERNEL::Exception("LinearTime::addEqual on mismatched time discretization !");
+  getArray()->multiplyEqual(other->getArray());
+  getEndArray()->multiplyEqual(other->getEndArray());
+}
+
+MEDCouplingTimeDiscretization *MEDCouplingLinearTime::divide(const MEDCouplingTimeDiscretization *other) const
+{
+  const MEDCouplingLinearTime *otherC=dynamic_cast<const MEDCouplingLinearTime *>(other);
+  if(!otherC)
+    throw INTERP_KERNEL::Exception("LinearTime::divide on mismatched time discretization !");
+  MEDCouplingLinearTime *ret=new MEDCouplingLinearTime;
+  DataArrayDouble *arr1=DataArrayDouble::divide(getArray(),other->getArray());
+  ret->setArray(arr1,0);
+  arr1->decrRef();
+  DataArrayDouble *arr2=DataArrayDouble::divide(getEndArray(),other->getEndArray());
+  ret->setEndArray(arr2,0);
+  arr2->decrRef();
+  return ret;
+}
+
+void MEDCouplingLinearTime::divideEqual(const MEDCouplingTimeDiscretization *other)
+{
+  const MEDCouplingLinearTime *otherC=dynamic_cast<const MEDCouplingLinearTime *>(other);
+  if(!otherC)
+    throw INTERP_KERNEL::Exception("LinearTime::addEqual on mismatched time discretization !");
+  getArray()->divideEqual(other->getArray());
+  getEndArray()->divideEqual(other->getEndArray());
 }
index 8ea2f8c6df465abcf9ea0cbfbaedfe723774b969..a9f1de097f45d5c04dc5f24cc040d97a29720d65 100644 (file)
@@ -17,8 +17,8 @@
 //  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
 //
 
-#ifndef __MEDCOUPLINGTIMEDISCRETIZATION_HXX__
-#define __MEDCOUPLINGTIMEDISCRETIZATION_HXX__
+#ifndef __PARAMEDMEM_MEDCOUPLINGTIMEDISCRETIZATION_HXX__
+#define __PARAMEDMEM_MEDCOUPLINGTIMEDISCRETIZATION_HXX__
 
 #include "MEDCoupling.hxx"
 #include "MEDCouplingTimeLabel.hxx"
@@ -40,13 +40,23 @@ namespace ParaMEDMEM
   public:
     void updateTime();
     static MEDCouplingTimeDiscretization *New(TypeOfTimeDiscretization type);
+    virtual void copyTinyAttrFrom(const MEDCouplingTimeDiscretization& other);
+    virtual void copyTinyStringsFrom(const MEDCouplingTimeDiscretization& other);
+    virtual void checkCoherency() const throw(INTERP_KERNEL::Exception);
     virtual bool areCompatible(const MEDCouplingTimeDiscretization *other) const;
-    virtual bool areCompatibleForMul(const MEDCouplingTimeDiscretization *other) const;
+    virtual bool areStrictlyCompatible(const MEDCouplingTimeDiscretization *other) const;
+    virtual bool areStrictlyCompatibleForMul(const MEDCouplingTimeDiscretization *other) const;
     virtual bool isEqual(const MEDCouplingTimeDiscretization *other, double prec) const;
+    virtual bool isEqualWithoutConsideringStr(const MEDCouplingTimeDiscretization *other, double prec) const;
     virtual MEDCouplingTimeDiscretization *buildNewTimeReprFromThis(const MEDCouplingTimeDiscretization *other,
                                                                     TypeOfTimeDiscretization type, bool deepCpy) const;
+    virtual std::string getStringRepr() const = 0;
     virtual TypeOfTimeDiscretization getEnum() const = 0;
     virtual MEDCouplingTimeDiscretization *aggregate(const MEDCouplingTimeDiscretization *other) const = 0;
+    virtual MEDCouplingTimeDiscretization *dot(const MEDCouplingTimeDiscretization *other) const = 0;
+    virtual MEDCouplingTimeDiscretization *crossProduct(const MEDCouplingTimeDiscretization *other) const = 0;
+    virtual MEDCouplingTimeDiscretization *max(const MEDCouplingTimeDiscretization *other) const = 0;
+    virtual MEDCouplingTimeDiscretization *min(const MEDCouplingTimeDiscretization *other) const = 0;
     virtual MEDCouplingTimeDiscretization *add(const MEDCouplingTimeDiscretization *other) const = 0;
     virtual void addEqual(const MEDCouplingTimeDiscretization *other) = 0;
     virtual MEDCouplingTimeDiscretization *substract(const MEDCouplingTimeDiscretization *other) const = 0;
@@ -66,27 +76,42 @@ namespace ParaMEDMEM
     virtual void checkNoTimePresence() const throw(INTERP_KERNEL::Exception) = 0;
     virtual void checkTimePresence(double time) const throw(INTERP_KERNEL::Exception) = 0;
     virtual void setArray(DataArrayDouble *array, TimeLabel *owner);
+    virtual void setEndArray(DataArrayDouble *array, TimeLabel *owner);
     virtual void setArrays(const std::vector<DataArrayDouble *>& arrays, TimeLabel *owner) throw(INTERP_KERNEL::Exception);
     DataArrayDouble *getArray() const { return _array; }
-    virtual DataArrayDouble *getEndArray() const { return _array; }
+    virtual DataArrayDouble *getEndArray() const;
     virtual std::vector< const DataArrayDouble *> getArraysForTime(double time) const throw(INTERP_KERNEL::Exception) = 0;
     virtual void getValueForTime(double time, const std::vector<double>& vals, double *res) const = 0; 
     virtual void getArrays(std::vector<DataArrayDouble *>& arrays) const;
     virtual bool isBefore(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception);
     virtual bool isStrictlyBefore(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception);
-    double getTime(int& dt, int& it) const throw(INTERP_KERNEL::Exception) { return getStartTime(dt,it); }
-    virtual double getStartTime(int& dt, int& it) const throw(INTERP_KERNEL::Exception) = 0;
-    virtual double getEndTime(int& dt, int& it) const throw(INTERP_KERNEL::Exception) = 0;
-    void setTime(double time, int dt, int it) throw(INTERP_KERNEL::Exception) { setStartTime(time,dt,it); }
-    virtual void setStartTime(double time, int dt, int it) throw(INTERP_KERNEL::Exception) = 0;
-    virtual void setEndTime(double time, int dt, int it) throw(INTERP_KERNEL::Exception) = 0;
+    double getTime(int& iteration, int& order) const throw(INTERP_KERNEL::Exception) { return getStartTime(iteration,order); }
+    virtual double getStartTime(int& iteration, int& order) const throw(INTERP_KERNEL::Exception) = 0;
+    virtual double getEndTime(int& iteration, int& order) const throw(INTERP_KERNEL::Exception) = 0;
+    void setTime(double time, int iteration, int order) throw(INTERP_KERNEL::Exception) { setStartTime(time,iteration,order); }
+    virtual void setStartTime(double time, int iteration, int order) throw(INTERP_KERNEL::Exception) = 0;
+    virtual void setEndTime(double time, int iteration, int order) throw(INTERP_KERNEL::Exception) = 0;
     virtual void getValueOnTime(int eltId, double time, double *value) const throw(INTERP_KERNEL::Exception) = 0;
-    virtual void getValueOnDiscTime(int eltId, int dt, int it, double *value) const throw(INTERP_KERNEL::Exception) = 0;
+    virtual void getValueOnDiscTime(int eltId, int iteration, int order, double *value) const throw(INTERP_KERNEL::Exception) = 0;
     //
+    virtual MEDCouplingTimeDiscretization *doublyContractedProduct() const throw(INTERP_KERNEL::Exception);
+    virtual MEDCouplingTimeDiscretization *determinant() const throw(INTERP_KERNEL::Exception);
+    virtual MEDCouplingTimeDiscretization *eigenValues() const throw(INTERP_KERNEL::Exception);
+    virtual MEDCouplingTimeDiscretization *eigenVectors() const throw(INTERP_KERNEL::Exception);
+    virtual MEDCouplingTimeDiscretization *inverse() const throw(INTERP_KERNEL::Exception);
+    virtual MEDCouplingTimeDiscretization *trace() const throw(INTERP_KERNEL::Exception);
+    virtual MEDCouplingTimeDiscretization *deviator() const throw(INTERP_KERNEL::Exception);
+    virtual MEDCouplingTimeDiscretization *magnitude() const throw(INTERP_KERNEL::Exception);
+    virtual MEDCouplingTimeDiscretization *maxPerTuple() const throw(INTERP_KERNEL::Exception);
+    virtual void changeNbOfComponents(int newNbOfComp, double dftValue) throw(INTERP_KERNEL::Exception);
+    virtual void sortPerTuple(bool asc) throw(INTERP_KERNEL::Exception);
     virtual void applyLin(double a, double b, int compoId);
     virtual void applyFunc(int nbOfComp, FunctionToEvaluate func);
     virtual void applyFunc(int nbOfComp, const char *func);
     virtual void applyFunc(const char *func);
+    virtual void applyFuncFast32(const char *func);
+    virtual void applyFuncFast64(const char *func);
+    
     //
     virtual ~MEDCouplingTimeDiscretization();
   protected:
@@ -101,8 +126,13 @@ namespace ParaMEDMEM
   public:
     MEDCouplingNoTimeLabel();
     MEDCouplingNoTimeLabel(const MEDCouplingTimeDiscretization& other, bool deepCpy);
+    std::string getStringRepr() const;
     TypeOfTimeDiscretization getEnum() const { return DISCRETIZATION; }
     MEDCouplingTimeDiscretization *aggregate(const MEDCouplingTimeDiscretization *other) const;
+    MEDCouplingTimeDiscretization *dot(const MEDCouplingTimeDiscretization *other) const;
+    MEDCouplingTimeDiscretization *crossProduct(const MEDCouplingTimeDiscretization *other) const;
+    MEDCouplingTimeDiscretization *max(const MEDCouplingTimeDiscretization *other) const;
+    MEDCouplingTimeDiscretization *min(const MEDCouplingTimeDiscretization *other) const;
     MEDCouplingTimeDiscretization *add(const MEDCouplingTimeDiscretization *other) const;
     void addEqual(const MEDCouplingTimeDiscretization *other);
     MEDCouplingTimeDiscretization *substract(const MEDCouplingTimeDiscretization *other) const;
@@ -112,8 +142,10 @@ namespace ParaMEDMEM
     MEDCouplingTimeDiscretization *divide(const MEDCouplingTimeDiscretization *other) const;
     void divideEqual(const MEDCouplingTimeDiscretization *other);
     bool isEqual(const MEDCouplingTimeDiscretization *other, double prec) const;
+    bool isEqualWithoutConsideringStr(const MEDCouplingTimeDiscretization *other, double prec) const;
     bool areCompatible(const MEDCouplingTimeDiscretization *other) const;
-    bool areCompatibleForMul(const MEDCouplingTimeDiscretization *other) const;
+    bool areStrictlyCompatible(const MEDCouplingTimeDiscretization *other) const;
+    bool areStrictlyCompatibleForMul(const MEDCouplingTimeDiscretization *other) const;
     MEDCouplingTimeDiscretization *performCpy(bool deepCpy) const;
     void checkNoTimePresence() const throw(INTERP_KERNEL::Exception) { }
     void checkTimePresence(double time) const throw(INTERP_KERNEL::Exception);
@@ -121,14 +153,15 @@ namespace ParaMEDMEM
     void getValueForTime(double time, const std::vector<double>& vals, double *res) const;
     bool isBefore(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception);
     bool isStrictlyBefore(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception);
-    double getStartTime(int& dt, int& it) const throw(INTERP_KERNEL::Exception);
-    double getEndTime(int& dt, int& it) const throw(INTERP_KERNEL::Exception);
-    void setStartTime(double time, int dt, int it) throw(INTERP_KERNEL::Exception);
-    void setEndTime(double time, int dt, int it) throw(INTERP_KERNEL::Exception);
+    double getStartTime(int& iteration, int& order) const throw(INTERP_KERNEL::Exception);
+    double getEndTime(int& iteration, int& order) const throw(INTERP_KERNEL::Exception);
+    void setStartTime(double time, int iteration, int order) throw(INTERP_KERNEL::Exception);
+    void setEndTime(double time, int iteration, int order) throw(INTERP_KERNEL::Exception);
     void getValueOnTime(int eltId, double time, double *value) const throw(INTERP_KERNEL::Exception);
-    void getValueOnDiscTime(int eltId, int dt, int it, double *value) const throw(INTERP_KERNEL::Exception);
+    void getValueOnDiscTime(int eltId, int iteration, int order, double *value) const throw(INTERP_KERNEL::Exception);
   public:
     static const TypeOfTimeDiscretization DISCRETIZATION=NO_TIME;
+    static const char REPR[];
   private:
     static const char EXCEPTION_MSG[];
   };
@@ -139,8 +172,14 @@ namespace ParaMEDMEM
     MEDCouplingWithTimeStep(const MEDCouplingWithTimeStep& other, bool deepCpy);
   public:
     MEDCouplingWithTimeStep();
+    std::string getStringRepr() const;
+    void copyTinyAttrFrom(const MEDCouplingTimeDiscretization& other);
     TypeOfTimeDiscretization getEnum() const { return DISCRETIZATION; }
     MEDCouplingTimeDiscretization *aggregate(const MEDCouplingTimeDiscretization *other) const;
+    MEDCouplingTimeDiscretization *dot(const MEDCouplingTimeDiscretization *other) const;
+    MEDCouplingTimeDiscretization *crossProduct(const MEDCouplingTimeDiscretization *other) const;
+    MEDCouplingTimeDiscretization *max(const MEDCouplingTimeDiscretization *other) const;
+    MEDCouplingTimeDiscretization *min(const MEDCouplingTimeDiscretization *other) const;
     MEDCouplingTimeDiscretization *add(const MEDCouplingTimeDiscretization *other) const;
     void addEqual(const MEDCouplingTimeDiscretization *other);
     MEDCouplingTimeDiscretization *substract(const MEDCouplingTimeDiscretization *other) const;
@@ -150,31 +189,33 @@ namespace ParaMEDMEM
     MEDCouplingTimeDiscretization *divide(const MEDCouplingTimeDiscretization *other) const;
     void divideEqual(const MEDCouplingTimeDiscretization *other);
     bool isEqual(const MEDCouplingTimeDiscretization *other, double prec) const;
+    bool isEqualWithoutConsideringStr(const MEDCouplingTimeDiscretization *other, double prec) const;
     bool areCompatible(const MEDCouplingTimeDiscretization *other) const;
-    bool areCompatibleForMul(const MEDCouplingTimeDiscretization *other) const;
+    bool areStrictlyCompatible(const MEDCouplingTimeDiscretization *other) const;
+    bool areStrictlyCompatibleForMul(const MEDCouplingTimeDiscretization *other) const;
     void getTinySerializationIntInformation(std::vector<int>& tinyInfo) const;
     void getTinySerializationDbleInformation(std::vector<double>& tinyInfo) const;
     void finishUnserialization(const std::vector<int>& tinyInfoI, const std::vector<double>& tinyInfoD, const std::vector<std::string>& tinyInfoS);
     MEDCouplingTimeDiscretization *performCpy(bool deepCpy) const;
     void checkNoTimePresence() const throw(INTERP_KERNEL::Exception);
     void checkTimePresence(double time) const throw(INTERP_KERNEL::Exception);
-    void setStartTime(double time, int dt, int it) throw(INTERP_KERNEL::Exception) { _time=time; _dt=dt; _it=it; }
-    void setEndTime(double time, int dt, int it) throw(INTERP_KERNEL::Exception) { _time=time; _dt=dt; _it=it; }
-    double getStartTime(int& dt, int& it) const throw(INTERP_KERNEL::Exception) { dt=_dt; it=_it; return _time; }
-    double getEndTime(int& dt, int& it) const throw(INTERP_KERNEL::Exception) { dt=_dt; it=_it; return _time; }
-    DataArrayDouble *getArrayOnTime(double time) const throw(INTERP_KERNEL::Exception);
+    void setStartTime(double time, int iteration, int order) throw(INTERP_KERNEL::Exception) { _time=time; _iteration=iteration; _order=order; }
+    void setEndTime(double time, int iteration, int order) throw(INTERP_KERNEL::Exception) { _time=time; _iteration=iteration; _order=order; }
+    double getStartTime(int& iteration, int& order) const throw(INTERP_KERNEL::Exception) { iteration=_iteration; order=_order; return _time; }
+    double getEndTime(int& iteration, int& order) const throw(INTERP_KERNEL::Exception) { iteration=_iteration; order=_order; return _time; }
     std::vector< const DataArrayDouble *> getArraysForTime(double time) const throw(INTERP_KERNEL::Exception);
     void getValueForTime(double time, const std::vector<double>& vals, double *res) const;
     void getValueOnTime(int eltId, double time, double *value) const throw(INTERP_KERNEL::Exception);
-    void getValueOnDiscTime(int eltId, int dt, int it, double *value) const throw(INTERP_KERNEL::Exception);
+    void getValueOnDiscTime(int eltId, int iteration, int order, double *value) const throw(INTERP_KERNEL::Exception);
   public:
     static const TypeOfTimeDiscretization DISCRETIZATION=ONE_TIME;
+    static const char REPR[];
   private:
     static const char EXCEPTION_MSG[];
   protected:
     double _time;
-    int _dt;
-    int _it;
+    int _iteration;
+    int _order;
   };
 
   class MEDCOUPLING_EXPORT MEDCouplingConstOnTimeInterval : public MEDCouplingTimeDiscretization
@@ -183,19 +224,27 @@ namespace ParaMEDMEM
     MEDCouplingConstOnTimeInterval(const MEDCouplingConstOnTimeInterval& other, bool deepCpy);
   public:
     MEDCouplingConstOnTimeInterval();
+    void copyTinyAttrFrom(const MEDCouplingTimeDiscretization& other);
     void getTinySerializationIntInformation(std::vector<int>& tinyInfo) const;
     void getTinySerializationDbleInformation(std::vector<double>& tinyInfo) const;
     void finishUnserialization(const std::vector<int>& tinyInfoI, const std::vector<double>& tinyInfoD, const std::vector<std::string>& tinyInfoS);
     MEDCouplingTimeDiscretization *performCpy(bool deepCpy) const;
     bool areCompatible(const MEDCouplingTimeDiscretization *other) const;
-    bool areCompatibleForMul(const MEDCouplingTimeDiscretization *other) const;
+    bool areStrictlyCompatible(const MEDCouplingTimeDiscretization *other) const;
+    bool areStrictlyCompatibleForMul(const MEDCouplingTimeDiscretization *other) const;
     bool isEqual(const MEDCouplingTimeDiscretization *other, double prec) const;
+    bool isEqualWithoutConsideringStr(const MEDCouplingTimeDiscretization *other, double prec) const;
     std::vector< const DataArrayDouble *> getArraysForTime(double time) const throw(INTERP_KERNEL::Exception);
     void getValueForTime(double time, const std::vector<double>& vals, double *res) const;
     void getValueOnTime(int eltId, double time, double *value) const throw(INTERP_KERNEL::Exception);
-    void getValueOnDiscTime(int eltId, int dt, int it, double *value) const throw(INTERP_KERNEL::Exception);
+    void getValueOnDiscTime(int eltId, int iteration, int order, double *value) const throw(INTERP_KERNEL::Exception);
     TypeOfTimeDiscretization getEnum() const { return DISCRETIZATION; }
+    std::string getStringRepr() const;
     MEDCouplingTimeDiscretization *aggregate(const MEDCouplingTimeDiscretization *other) const;
+    MEDCouplingTimeDiscretization *dot(const MEDCouplingTimeDiscretization *other) const;
+    MEDCouplingTimeDiscretization *crossProduct(const MEDCouplingTimeDiscretization *other) const;
+    MEDCouplingTimeDiscretization *max(const MEDCouplingTimeDiscretization *other) const;
+    MEDCouplingTimeDiscretization *min(const MEDCouplingTimeDiscretization *other) const;
     MEDCouplingTimeDiscretization *add(const MEDCouplingTimeDiscretization *other) const;
     void addEqual(const MEDCouplingTimeDiscretization *other);
     MEDCouplingTimeDiscretization *substract(const MEDCouplingTimeDiscretization *other) const;
@@ -204,56 +253,99 @@ namespace ParaMEDMEM
     void multiplyEqual(const MEDCouplingTimeDiscretization *other);
     MEDCouplingTimeDiscretization *divide(const MEDCouplingTimeDiscretization *other) const;
     void divideEqual(const MEDCouplingTimeDiscretization *other);
-    void setStartTime(double time, int dt, int it) throw(INTERP_KERNEL::Exception) { _start_time=time; _start_dt=dt; _start_it=it; }
-    void setEndTime(double time, int dt, int it) throw(INTERP_KERNEL::Exception) { _end_time=time; _end_dt=dt; _end_it=it; }
-    double getStartTime(int& dt, int& it) const throw(INTERP_KERNEL::Exception) { dt=_start_dt; it=_start_it; return _start_time; }
-    double getEndTime(int& dt, int& it) const throw(INTERP_KERNEL::Exception) { dt=_end_dt; it=_end_it; return _end_time; }
+    void setStartTime(double time, int iteration, int order) throw(INTERP_KERNEL::Exception) { _start_time=time; _start_iteration=iteration; _start_order=order; }
+    void setEndTime(double time, int iteration, int order) throw(INTERP_KERNEL::Exception) { _end_time=time; _end_iteration=iteration; _end_order=order; }
+    double getStartTime(int& iteration, int& order) const throw(INTERP_KERNEL::Exception) { iteration=_start_iteration; order=_start_order; return _start_time; }
+    double getEndTime(int& iteration, int& order) const throw(INTERP_KERNEL::Exception) { iteration=_end_iteration; order=_end_order; return _end_time; }
     void checkNoTimePresence() const throw(INTERP_KERNEL::Exception);
     void checkTimePresence(double time) const throw(INTERP_KERNEL::Exception);
   public:
     static const TypeOfTimeDiscretization DISCRETIZATION=CONST_ON_TIME_INTERVAL;
+    static const char REPR[];
   private:
     static const char EXCEPTION_MSG[];
   protected:
     double _start_time;
     double _end_time;
-    int _start_dt;
-    int _end_dt;
-    int _start_it;
-    int _end_it;
+    int _start_iteration;
+    int _end_iteration;
+    int _start_order;
+    int _end_order;
   };
 
   class MEDCOUPLING_EXPORT MEDCouplingTwoTimeSteps : public MEDCouplingTimeDiscretization
   {
   protected:
+    MEDCouplingTwoTimeSteps(const MEDCouplingTwoTimeSteps& other, bool deepCpy);
     MEDCouplingTwoTimeSteps();
     ~MEDCouplingTwoTimeSteps();
   public:
+    void updateTime();
+    void copyTinyAttrFrom(const MEDCouplingTimeDiscretization& other);
+    void copyTinyStringsFrom(const MEDCouplingTimeDiscretization& other);
+    DataArrayDouble *getEndArray() const;
+    void checkCoherency() const throw(INTERP_KERNEL::Exception);
+    bool isEqual(const MEDCouplingTimeDiscretization *other, double prec) const;
+    bool isEqualWithoutConsideringStr(const MEDCouplingTimeDiscretization *other, double prec) const;
     void checkNoTimePresence() const throw(INTERP_KERNEL::Exception);
     void checkTimePresence(double time) const throw(INTERP_KERNEL::Exception);
     void getArrays(std::vector<DataArrayDouble *>& arrays) const;
-    DataArrayDouble *getEndArray() const { return _end_array; }
-    void setStartTime(double time, int dt, int it) throw(INTERP_KERNEL::Exception) { _start_time=time; _start_dt=dt; _start_it=it; }
-    void setEndTime(double time, int dt, int it) throw(INTERP_KERNEL::Exception) { _end_time=time; _end_dt=dt; _end_it=it; }
-    double getStartTime(int& dt, int& it) const throw(INTERP_KERNEL::Exception) { dt=_start_dt; it=_start_it; return _start_time; }
-    double getEndTime(int& dt, int& it) const throw(INTERP_KERNEL::Exception) { dt=_end_dt; it=_end_it; return _end_time; }
+    void setEndArray(DataArrayDouble *array, TimeLabel *owner);
+    void setStartTime(double time, int iteration, int order) throw(INTERP_KERNEL::Exception) { _start_time=time; _start_iteration=iteration; _start_order=order; }
+    void setEndTime(double time, int iteration, int order) throw(INTERP_KERNEL::Exception) { _end_time=time; _end_iteration=iteration; _end_order=order; }
+    double getStartTime(int& iteration, int& order) const throw(INTERP_KERNEL::Exception) { iteration=_start_iteration; order=_start_order; return _start_time; }
+    double getEndTime(int& iteration, int& order) const throw(INTERP_KERNEL::Exception) { iteration=_end_iteration; order=_end_order; return _end_time; }
+    void getTinySerializationIntInformation(std::vector<int>& tinyInfo) const;
+    void getTinySerializationDbleInformation(std::vector<double>& tinyInfo) const;
+    void getTinySerializationStrInformation(std::vector<std::string>& tinyInfo) const;
     void resizeForUnserialization(const std::vector<int>& tinyInfoI, std::vector<DataArrayDouble *>& arrays);
     void finishUnserialization(const std::vector<int>& tinyInfoI, const std::vector<double>& tinyInfoD, const std::vector<std::string>& tinyInfoS);
+    std::vector< const DataArrayDouble *> getArraysForTime(double time) const throw(INTERP_KERNEL::Exception);
+    void setArrays(const std::vector<DataArrayDouble *>& arrays, TimeLabel *owner) throw(INTERP_KERNEL::Exception);
+  protected:
+    static const char EXCEPTION_MSG[];
   protected:
     double _start_time;
     double _end_time;
-    int _start_dt;
-    int _end_dt;
-    int _start_it;
-    int _end_it;
+    int _start_iteration;
+    int _end_iteration;
+    int _start_order;
+    int _end_order;
     DataArrayDouble *_end_array;
   };
 
   class MEDCOUPLING_EXPORT MEDCouplingLinearTime : public MEDCouplingTwoTimeSteps
   {
+  protected:
+    MEDCouplingLinearTime(const MEDCouplingLinearTime& other, bool deepCpy);
   public:
+    MEDCouplingLinearTime();
+    std::string getStringRepr() const;
     TypeOfTimeDiscretization getEnum() const { return DISCRETIZATION; }
+    void checkCoherency() const throw(INTERP_KERNEL::Exception);
+    MEDCouplingTimeDiscretization *performCpy(bool deepCpy) const;
+    bool areCompatible(const MEDCouplingTimeDiscretization *other) const;
+    bool areStrictlyCompatible(const MEDCouplingTimeDiscretization *other) const;
+    bool areStrictlyCompatibleForMul(const MEDCouplingTimeDiscretization *other) const;
+    void getValueForTime(double time, const std::vector<double>& vals, double *res) const;
+    void getValueOnTime(int eltId, double time, double *value) const throw(INTERP_KERNEL::Exception);
+    void getValueOnDiscTime(int eltId, int iteration, int order, double *value) const throw(INTERP_KERNEL::Exception);
+    MEDCouplingTimeDiscretization *aggregate(const MEDCouplingTimeDiscretization *other) const;
+    MEDCouplingTimeDiscretization *dot(const MEDCouplingTimeDiscretization *other) const;
+    MEDCouplingTimeDiscretization *crossProduct(const MEDCouplingTimeDiscretization *other) const;
+    MEDCouplingTimeDiscretization *max(const MEDCouplingTimeDiscretization *other) const;
+    MEDCouplingTimeDiscretization *min(const MEDCouplingTimeDiscretization *other) const;
+    MEDCouplingTimeDiscretization *add(const MEDCouplingTimeDiscretization *other) const;
+    void addEqual(const MEDCouplingTimeDiscretization *other);
+    MEDCouplingTimeDiscretization *substract(const MEDCouplingTimeDiscretization *other) const;
+    void substractEqual(const MEDCouplingTimeDiscretization *other);
+    MEDCouplingTimeDiscretization *multiply(const MEDCouplingTimeDiscretization *other) const;
+    void multiplyEqual(const MEDCouplingTimeDiscretization *other);
+    MEDCouplingTimeDiscretization *divide(const MEDCouplingTimeDiscretization *other) const;
+    void divideEqual(const MEDCouplingTimeDiscretization *other);
+  public:
     static const TypeOfTimeDiscretization DISCRETIZATION=LINEAR_TIME;
+    static const char REPR[];
   };
 }
 
index 62e64ce7e639a51b6427b2a47cf32f941d29adf2..e27fe875cc0dfabf7d2e7443728505f2dd01fdfd 100644 (file)
 #include "PointLocatorAlgos.txx"
 #include "BBTree.txx"
 #include "DirectedBoundingBox.hxx"
+#include "MEDCouplingAutoRefCountObjectPtr.hxx"
 
 #include <sstream>
 #include <numeric>
+#include <cstring>
 #include <limits>
 #include <list>
 
@@ -35,6 +37,8 @@ using namespace ParaMEDMEM;
 
 const char MEDCouplingUMesh::PART_OF_NAME[]="PartOf_";
 
+double MEDCouplingUMesh::EPS_FOR_POLYH_ORIENTATION=1.e-14;
+
 MEDCouplingUMesh *MEDCouplingUMesh::New()
 {
   return new MEDCouplingUMesh;
@@ -48,6 +52,11 @@ MEDCouplingUMesh *MEDCouplingUMesh::New(const char *meshName, int meshDim)
   return ret;
 }
 
+MEDCouplingMesh *MEDCouplingUMesh::deepCpy() const
+{
+  return clone(true);
+}
+
 MEDCouplingUMesh *MEDCouplingUMesh::clone(bool recDeepCpy) const
 {
   return new MEDCouplingUMesh(*this,recDeepCpy);
@@ -84,6 +93,20 @@ void MEDCouplingUMesh::checkCoherency() const throw(INTERP_KERNEL::Exception)
           throw INTERP_KERNEL::Exception(message.str().c_str());
         }
     }
+  if(_nodal_connec)
+    {
+      if(_nodal_connec->getNumberOfComponents()!=1)
+        throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to be with number of components set to one !");
+      if(_nodal_connec->getInfoOnComponent(0)!="")
+        throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to have no info on its single component !");
+    }
+  if(_nodal_connec_index)
+    {
+      if(_nodal_connec_index->getNumberOfComponents()!=1)
+        throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to be with number of components set to one !");
+      if(_nodal_connec_index->getInfoOnComponent(0)!="")
+        throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to have no info on its single component !");
+    }
 }
 
 void MEDCouplingUMesh::setMeshDimension(int meshDim)
@@ -178,6 +201,150 @@ bool MEDCouplingUMesh::isEqual(const MEDCouplingMesh *other, double prec) const
   return true;
 }
 
+bool MEDCouplingUMesh::isEqualWithoutConsideringStr(const MEDCouplingMesh *other, double prec) const
+{
+  const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
+  if(!otherC)
+    return false;
+  if(!MEDCouplingPointSet::isEqualWithoutConsideringStr(other,prec))
+    return false;
+  if(_mesh_dim!=otherC->_mesh_dim)
+    return false;
+  if(_types!=otherC->_types)
+    return false;
+  if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
+    if(_nodal_connec==0 || otherC->_nodal_connec==0)
+      return false;
+  if(_nodal_connec!=otherC->_nodal_connec)
+    if(!_nodal_connec->isEqualWithoutConsideringStr(*otherC->_nodal_connec))
+      return false;
+  if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
+    if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
+      return false;
+  if(_nodal_connec_index!=otherC->_nodal_connec_index)
+    if(!_nodal_connec_index->isEqualWithoutConsideringStr(*otherC->_nodal_connec_index))
+      return false;
+  return true;
+}
+
+/*!
+ * This method looks if 'this' and 'other' are geometrically equivalent that is to say if each cell in 'other' correspond to one cell and only one
+ * in 'this' is found regarding 'prec' parameter and 'cellCompPol' parameter.
+ * 
+ * In case of success cellCor and nodeCor are informed both. 
+ * @param cellCompPol values are described in MEDCouplingUMesh::zipConnectivityTraducer method.
+ * @param cellCor output array giving the correspondance of cells from 'other' to 'this'.
+ * @param nodeCor output array giving the correspondance of nodes from 'other' to 'this'.
+ */
+void MEDCouplingUMesh::checkDeepEquivalWith(const MEDCouplingMesh *other, int cellCompPol, double prec,
+                                            DataArrayInt *&cellCor, DataArrayInt *&nodeCor) const throw(INTERP_KERNEL::Exception)
+{
+  const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
+  if(!otherC)
+    throw INTERP_KERNEL::Exception("checkDeepEquivalWith : Two meshes are not not unstructured !");
+  MEDCouplingMesh::checkFastEquivalWith(other,prec);
+  if(_types!=otherC->_types)
+    throw INTERP_KERNEL::Exception("checkDeepEquivalWith : Types are not equal !");
+  MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=mergeUMeshes(this,otherC);
+  bool areNodesMerged;
+  int newNbOfNodes;
+  int oldNbOfNodes=getNumberOfNodes();
+  MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=m->buildPermArrayForMergeNode(oldNbOfNodes,prec,areNodesMerged,newNbOfNodes);
+  //mergeNodes
+  if(!areNodesMerged)
+    throw INTERP_KERNEL::Exception("checkDeepEquivalWith : Nodes are incompatible ! ");
+  const int *pt=std::find_if(da->getConstPointer()+oldNbOfNodes,da->getConstPointer()+da->getNbOfElems(),std::bind2nd(std::greater<int>(),oldNbOfNodes-1));
+  if(pt!=da->getConstPointer()+da->getNbOfElems())
+    throw INTERP_KERNEL::Exception("checkDeepEquivalWith : some nodes in other are not in this !");
+  m->renumberNodes(da->getConstPointer(),newNbOfNodes);
+  //
+  nodeCor=da->substr(oldNbOfNodes);
+  da=m->mergeNodes(prec,areNodesMerged,newNbOfNodes);
+  if(nodeCor->isIdentity())
+    {
+      nodeCor->decrRef();
+      nodeCor=0;
+    }
+  //
+  da=m->zipConnectivityTraducer(cellCompPol);
+  int maxId=*std::max_element(da->getConstPointer(),da->getConstPointer()+getNumberOfCells());
+  pt=std::find_if(da->getConstPointer()+getNumberOfCells(),da->getConstPointer()+da->getNbOfElems(),std::bind2nd(std::greater<int>(),maxId));
+  if(pt!=da->getConstPointer()+da->getNbOfElems())
+    {
+      nodeCor->decrRef(); nodeCor=0;
+      throw INTERP_KERNEL::Exception("checkDeepEquivalWith : some cells in other are not in this !");
+    }
+  cellCor=DataArrayInt::New();
+  cellCor->alloc(otherC->getNumberOfCells(),1);
+  std::copy(da->getConstPointer()+getNumberOfCells(),da->getConstPointer()+da->getNbOfElems(),cellCor->getPointer());
+  if(cellCor->isIdentity())
+    {
+      cellCor->decrRef();
+      cellCor=0;
+    }
+}
+
+/*!
+ * This method looks if 'this' and 'other' are geometrically equivalent that is to say if each cell in 'other' correspond to one cell and only one
+ * in 'this' is found regarding 'prec' parameter and 'cellCompPol' parameter. The difference with MEDCouplingUMesh::checkDeepEquivalWith method is that
+ * coordinates of 'this' and 'other' are expected to be the same. If not an exception will be thrown.
+ * 
+ * In case of success cellCor are informed both. 
+ * @param cellCompPol values are described in MEDCouplingUMesh::zipConnectivityTraducer method.
+ * @param cellCor output array giving the correspondance of cells from 'other' to 'this'.
+ */
+void MEDCouplingUMesh::checkDeepEquivalOnSameNodesWith(const MEDCouplingMesh *other, int cellCompPol, double prec,
+                                                       DataArrayInt *&cellCor) const throw(INTERP_KERNEL::Exception)
+{
+  const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
+  if(!otherC)
+    throw INTERP_KERNEL::Exception("checkDeepEquivalOnSameNodesWith : Two meshes are not not unstructured !");
+  MEDCouplingMesh::checkFastEquivalWith(other,prec);
+  if(_types!=otherC->_types)
+    throw INTERP_KERNEL::Exception("checkDeepEquivalOnSameNodesWith : Types are not equal !");
+  if(_coords!=otherC->_coords)
+    throw INTERP_KERNEL::Exception("checkDeepEquivalOnSameNodesWith : meshes do not share the same coordinates ! Use tryToShareSameCoordinates or call checkDeepEquivalWith !");
+  std::vector<MEDCouplingUMesh *> ms(2);
+  ms[0]=const_cast<MEDCouplingUMesh *>(this);
+  ms[1]=const_cast<MEDCouplingUMesh *>(otherC);
+  MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=mergeUMeshesOnSameCoords(ms);
+  MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=m->zipConnectivityTraducer(cellCompPol);
+  int maxId=*std::max_element(da->getConstPointer(),da->getConstPointer()+getNumberOfCells());
+  const int *pt=std::find_if(da->getConstPointer()+getNumberOfCells(),da->getConstPointer()+da->getNbOfElems(),std::bind2nd(std::greater<int>(),maxId));
+  if(pt!=da->getConstPointer()+da->getNbOfElems())
+    {
+      throw INTERP_KERNEL::Exception("checkDeepEquivalOnSameNodesWith : some cells in other are not in this !");
+    }
+  cellCor=DataArrayInt::New();
+  cellCor->alloc(otherC->getNumberOfCells(),1);
+  std::copy(da->getConstPointer()+getNumberOfCells(),da->getConstPointer()+da->getNbOfElems(),cellCor->getPointer());
+  if(cellCor->isIdentity())
+    {
+      cellCor->decrRef();
+      cellCor=0;
+    }
+}
+
+/*!
+ * This method checks fastly that 'this' and 'other' are equal. 
+ */
+void MEDCouplingUMesh::checkFastEquivalWith(const MEDCouplingMesh *other, double prec) const throw(INTERP_KERNEL::Exception)
+{
+  const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
+  if(!otherC)
+    throw INTERP_KERNEL::Exception("checkFastEquivalWith : Two meshes are not not unstructured !");
+  MEDCouplingPointSet::checkFastEquivalWith(other,prec);
+  int nbOfCells=getNumberOfCells();
+  if(nbOfCells<1)
+    return ;
+  bool status=true;
+  status&=areCellsFrom2MeshEqual(otherC,0,prec);
+  status&=areCellsFrom2MeshEqual(otherC,nbOfCells/2,prec);
+  status&=areCellsFrom2MeshEqual(otherC,nbOfCells-1,prec);
+  if(!status)
+    throw INTERP_KERNEL::Exception("checkFastEquivalWith : Two meshes are not equal because on 3 test cells some difference have been detected !");
+}
+
 /*!
  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
  * For speed reasons no check of this will be done.
@@ -386,22 +553,20 @@ void MEDCouplingUMesh::convertToPolyTypes(const std::vector<int>& cellIdsToConve
       int *newConnPtr=_nodal_connec->getPointer();
       std::copy(connNew.begin(),connNew.end(),newConnPtr);
     }
+  computeTypes();
 }
 
 /*!
- * Array returned is the correspondance old to new.
+ * Array returned is the correspondance new to old.
  * The maximum value stored in returned array is the number of nodes of 'this' minus 1 after call of this method.
  * The size of returned array is the number of nodes of the old (previous to the call of this method) number of nodes.
  * -1 values in returned array means that the corresponding old node is no more used.
  */
 DataArrayInt *MEDCouplingUMesh::zipCoordsTraducer()
 {
-  DataArrayInt *ret=DataArrayInt::New();
   int nbOfNodes=getNumberOfNodes();
-  int spaceDim=getSpaceDimension();
   int *traducer=new int[nbOfNodes];
   std::fill(traducer,traducer+nbOfNodes,-1);
-  ret->useArray(traducer,true,CPP_DEALLOC,nbOfNodes,1);
   int nbOfCells=getNumberOfCells();
   const int *connIndex=_nodal_connec_index->getConstPointer();
   int *conn=_nodal_connec->getPointer();
@@ -415,40 +580,312 @@ DataArrayInt *MEDCouplingUMesh::zipCoordsTraducer()
     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
       if(conn[j]>=0)
         conn[j]=traducer[conn[j]];
-  DataArrayDouble *newCoords=DataArrayDouble::New();
-  double *newCoordsPtr=new double[newNbOfNodes*spaceDim];
-  const double *oldCoordsPtr=_coords->getConstPointer();
-  newCoords->useArray(newCoordsPtr,true,CPP_DEALLOC,newNbOfNodes,spaceDim);
-  int *work=std::find_if(traducer,traducer+nbOfNodes,std::bind2nd(std::not_equal_to<int>(),-1));
-  for(;work!=traducer+nbOfNodes;work=std::find_if(work,traducer+nbOfNodes,std::bind2nd(std::not_equal_to<int>(),-1)))
-    {
-      newCoordsPtr=std::copy(oldCoordsPtr+spaceDim*(work-traducer),oldCoordsPtr+spaceDim*(work-traducer+1),newCoordsPtr);
-      work++;
-    }
+  DataArrayInt *ret=DataArrayInt::New();
+  ret->alloc(newNbOfNodes,1);
+  int *retPtr=ret->getPointer();
+  for(int i=0;i<nbOfNodes;i++)
+    if(traducer[i]!=-1)
+      retPtr[traducer[i]]=i;
+  delete [] traducer;
+  DataArrayDouble *newCoords=_coords->selectByTupleId(retPtr,retPtr+newNbOfNodes);
   setCoords(newCoords);
   newCoords->decrRef();
   return ret;
 }
 
+/*!
+ * This method stands if 'cell1' and 'cell2' are equals regarding 'compType' policy.
+ * The semantic of 'compType' is specified in MEDCouplingUMesh::zipConnectivityTraducer method.
+ */
+bool MEDCouplingUMesh::areCellsEqual(int cell1, int cell2, int compType) const
+{
+  switch(compType)
+    {
+    case 0:
+      return areCellsEqual0(cell1,cell2);
+    case 1:
+      return areCellsEqual1(cell1,cell2);
+    case 2:
+      return areCellsEqual2(cell1,cell2);
+    }
+  throw INTERP_KERNEL::Exception("Unknown comparison asked ! Must be in 0,1 or 2.");
+}
+
+/*!
+ * This method is the last step of the MEDCouplingUMesh::zipConnectivityTraducer with policy 0.
+ */
+bool MEDCouplingUMesh::areCellsEqual0(int cell1, int cell2) const
+{
+  const int *conn=getNodalConnectivity()->getConstPointer();
+  const int *connI=getNodalConnectivityIndex()->getConstPointer();
+  return std::equal(conn+connI[cell1],conn+connI[cell1+1],conn+connI[cell2]);
+}
+
+/*!
+ * This method is the last step of the MEDCouplingUMesh::zipConnectivityTraducer with policy 1.
+ */
+bool MEDCouplingUMesh::areCellsEqual1(int cell1, int cell2) const
+{
+  throw INTERP_KERNEL::Exception("Policy comparison, not implemented yet !");
+}
+
+/*!
+ * This method is the last step of the MEDCouplingUMesh::zipConnectivityTraducer with policy 2.
+ */
+bool MEDCouplingUMesh::areCellsEqual2(int cell1, int cell2) const
+{
+  const int *conn=getNodalConnectivity()->getConstPointer();
+  const int *connI=getNodalConnectivityIndex()->getConstPointer();
+  std::set<int> s1(conn+connI[cell1],conn+connI[cell1+1]);
+  std::set<int> s2(conn+connI[cell2],conn+connI[cell2+1]);
+  return s1==s2;
+}
+
+/*!
+ * This method compares 2 cells coming from two unstructured meshes : 'this' and 'other'.
+ * This method compares 2 cells having the same id 'cellId' in 'this' and 'other'.
+ */
+bool MEDCouplingUMesh::areCellsFrom2MeshEqual(const MEDCouplingUMesh *other, int cellId, double prec) const
+{
+  if(getTypeOfCell(cellId)!=other->getTypeOfCell(cellId))
+    return false;
+  std::vector<int> c1,c2;
+  getNodeIdsOfCell(cellId,c1);
+  other->getNodeIdsOfCell(cellId,c2);
+  int sz=c1.size();
+  if(sz!=(int)c2.size())
+    return false;
+  for(int i=0;i<sz;i++)
+    {
+      std::vector<double> n1,n2;
+      getCoordinatesOfNode(c1[0],n1);
+      other->getCoordinatesOfNode(c2[0],n2);
+      std::transform(n1.begin(),n1.end(),n2.begin(),n1.begin(),std::minus<double>());
+      std::transform(n1.begin(),n1.end(),n1.begin(),std::ptr_fun<double,double>(fabs));
+      if(*std::max_element(n1.begin(),n1.end())>prec)
+        return false;
+    }
+  return true;
+}
+
+/*!
+ * This method find in candidate pool defined by 'candidates' the cells equal following the polycy 'compType'.
+ * If any true is returned and the results will be put at the end of 'result' output parameter. If not false is returned
+ * and result remains unchanged.
+ * The semantic of 'compType' is specified in MEDCouplingUMesh::zipConnectivityTraducer method.
+ * If in 'candidates' pool -1 value is considered as an empty value.
+ * WARNING this method returns only ONE set of result !
+ */
+bool MEDCouplingUMesh::areCellsEqualInPool(const std::vector<int>& candidates, int compType, std::vector<int>& result) const
+{
+  std::set<int> cand(candidates.begin(),candidates.end());
+  cand.erase(-1);
+  if(cand.size()<=1)
+    return false;
+  std::set<int>::const_iterator end=cand.end(); end--;
+  bool ret=false;
+  for(std::set<int>::const_iterator iter=cand.begin();iter!=end && !ret;iter++)
+    {
+      std::set<int>::const_iterator begin2=iter; begin2++;
+      for(std::set<int>::const_iterator iter2=begin2;iter2!=cand.end();iter2++)
+        {
+          if(areCellsEqual(*iter,*iter2,compType))
+            {
+              if(!ret)
+                {
+                  result.push_back(*iter);
+                  ret=true;
+                }
+              result.push_back(*iter2);
+            }
+        }
+    }
+  return ret;
+}
+
+/*!
+ * This method common cells base regarding 'compType' comparison policy described in ParaMEDMEM::MEDCouplingUMesh::zipConnectivityTraducer for details.
+ * This method returns 2 values 'res' and 'resI'.
+ * If 'res' and 'resI' are not empty before calling this method they will be cleared before set.
+ * The format of 'res' and 'resI' is as explained here.
+ * resI.size()-1 is the number of set of cells equal.
+ * The nth set is [res.begin()+resI[n];res.begin()+resI[n+1]) with 0<=n<resI.size()-1 
+ */
+template<int SPACEDIM>
+void MEDCouplingUMesh::findCommonCellsBase(int compType, std::vector<int>& res, std::vector<int>& resI) const
+{
+  res.clear(); resI.clear();
+  resI.push_back(0);
+  std::vector<double> bbox;
+  int nbOfCells=getNumberOfCells();
+  getBoundingBoxForBBTree(bbox);
+  double bb[2*SPACEDIM];
+  double eps=getCaracteristicDimension();
+  eps*=1.e-12;
+  BBTree<SPACEDIM,int> myTree(&bbox[0],0,0,nbOfCells,-eps);
+  const int *conn=getNodalConnectivity()->getConstPointer();
+  const int *connI=getNodalConnectivityIndex()->getConstPointer();
+  const double *coords=getCoords()->getConstPointer();
+  std::vector<bool> isFetched(nbOfCells);
+  for(int k=0;k<nbOfCells;k++)
+    {
+      if(!isFetched[k])
+        {
+          for(int j=0;j<SPACEDIM;j++)
+            { bb[2*j]=std::numeric_limits<double>::max(); bb[2*j+1]=-std::numeric_limits<double>::max(); }
+          for(const int *pt=conn+connI[k]+1;pt!=conn+connI[k+1];pt++)
+            if(*pt>-1)
+              {
+                for(int j=0;j<SPACEDIM;j++)
+                  {
+                    bb[2*j]=std::min(bb[2*j],coords[SPACEDIM*(*pt)+j]);
+                    bb[2*j+1]=std::max(bb[2*j+1],coords[SPACEDIM*(*pt)+j]);
+                  }
+              }
+          std::vector<int> candidates1;
+          myTree.getIntersectingElems(bb,candidates1);
+          std::vector<int> candidates;
+          for(std::vector<int>::const_iterator iter=candidates1.begin();iter!=candidates1.end();iter++)
+            if(!isFetched[*iter])
+              candidates.push_back(*iter);
+          if(areCellsEqualInPool(candidates,compType,res))
+            {
+              int pos=resI.back();
+              resI.push_back(res.size());
+              for(std::vector<int>::const_iterator it=res.begin()+pos;it!=res.end();it++)
+                isFetched[*it]=true;
+            }
+          isFetched[k]=true;
+        }
+    }
+}
+
+/*!
+ * This method could potentially modify 'this'. This method merges cells if there are cells equal in 'this'. The comparison is specified by 'compType'.
+ * This method keeps the coordiantes of 'this'.
+ *
+ * @param compType input specifying the technique used to compare cells each other.
+ *                 0 : exactly. A cell is detected to be the same if and only if the connectivity is exactly the same without permutation and types same too. This is the strongest policy.
+ *                 1 : permutation. cell1 and cell2 are equal if and the connectivity of cell2 can be deduced by those of cell1 by direct permutation and their type equal.
+ *                 2 : nodal. cell1 and cell2 are equal if and only if cell1 and cell2 have same type and have the same nodes constituting connectivity. This is the laziest policy.
+ * @return the correspondance array old to new.
+ */
+DataArrayInt *MEDCouplingUMesh::zipConnectivityTraducer(int compType)
+{
+  int spaceDim=getSpaceDimension();
+  int nbOfCells=getNumberOfCells();
+  std::vector<int> commonCells;
+  std::vector<int> commonCellsI;
+  switch(spaceDim)
+    {
+    case 3:
+      {
+        findCommonCellsBase<3>(compType,commonCells,commonCellsI);
+        break;
+      }
+    case 2:
+      {
+        findCommonCellsBase<2>(compType,commonCells,commonCellsI);
+        break;
+      }
+    case 1:
+      {
+        findCommonCellsBase<1>(compType,commonCells,commonCellsI);
+        break;
+      }
+    default:
+      throw INTERP_KERNEL::Exception("Invalid spaceDimension : must be 1, 2 or 3.");
+    }
+  DataArrayInt *ret=DataArrayInt::New();
+  ret->alloc(nbOfCells,1);
+  int *retPtr=ret->getPointer();
+  std::fill(retPtr,retPtr+nbOfCells,0);
+  const int nbOfTupleSmCells=commonCellsI.size()-1;
+  int id=-1;
+  std::vector<int> cellsToKeep;
+  for(int i=0;i<nbOfTupleSmCells;i++)
+    {
+      for(std::vector<int>::const_iterator it=commonCells.begin()+commonCellsI[i];it!=commonCells.begin()+commonCellsI[i+1];it++)
+        retPtr[*it]=id;
+      id--;
+    }
+  id=0;
+  std::map<int,int> m;
+  for(int i=0;i<nbOfCells;i++)
+    {
+      int val=retPtr[i];
+      if(val==0)
+        {
+          retPtr[i]=id++;
+          cellsToKeep.push_back(i);
+        }
+      else
+        {
+          std::map<int,int>::const_iterator iter=m.find(val);
+          if(iter==m.end())
+            {
+              m[val]=id;
+              retPtr[i]=id++;
+              cellsToKeep.push_back(i);
+            }
+          else
+            retPtr[i]=(*iter).second;
+        }
+    }
+  MEDCouplingUMesh *self=(MEDCouplingUMesh *)buildPartOfMySelf(&cellsToKeep[0],&cellsToKeep[0]+cellsToKeep.size(),true);
+  setConnectivity(self->getNodalConnectivity(),self->getNodalConnectivityIndex(),true);
+  self->decrRef();
+  return ret;
+}
+
 /*!
  * @param areNodesMerged if at least two nodes have been merged.
  * @return old to new node correspondance.
  */
-DataArrayInt *MEDCouplingUMesh::mergeNodes(double precision, bool& areNodesMerged)
+DataArrayInt *MEDCouplingUMesh::mergeNodes(double precision, bool& areNodesMerged, int& newNbOfNodes)
 {
-  DataArrayInt *comm,*commI;
-  findCommonNodes(comm,commI,precision);
-  int newNbOfNodes;
-  int oldNbOfNodes=getNumberOfNodes();
-  DataArrayInt *ret=buildNewNumberingFromCommNodesFrmt(comm,commI,newNbOfNodes);
-  areNodesMerged=(oldNbOfNodes!=newNbOfNodes);
-  comm->decrRef();
-  commI->decrRef();
+  DataArrayInt *ret=buildPermArrayForMergeNode(-1,precision,areNodesMerged,newNbOfNodes);
   if(areNodesMerged)
     renumberNodes(ret->getConstPointer(),newNbOfNodes);
   return ret;
 }
 
+/*!
+ * This method tries to use 'other' coords and use it for 'this'. If no exception was thrown after the call of this method :
+ * this->_coords==other->_coords. If not a exception is thrown this remains unchanged.
+ */
+void MEDCouplingUMesh::tryToShareSameCoordsPermute(const MEDCouplingPointSet& other, double epsilon) throw(INTERP_KERNEL::Exception)
+{
+  DataArrayDouble *coords=other.getCoords();
+  if(!coords)
+    throw INTERP_KERNEL::Exception("tryToShareSameCoordsPermute : No coords specified in other !");
+  if(!_coords)
+    throw INTERP_KERNEL::Exception("tryToShareSameCoordsPermute : No coords specified in this whereas there is any in other !");
+  int otherNbOfNodes=other.getNumberOfNodes();
+  MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=mergeNodesArray(&other,this);
+  _coords->incrRef();
+  MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> oldCoords=_coords;
+  setCoords(newCoords);
+  bool areNodesMerged;
+  int newNbOfNodes;
+  MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=buildPermArrayForMergeNode(otherNbOfNodes,epsilon,areNodesMerged,newNbOfNodes);
+  if(!areNodesMerged)
+    {
+      setCoords(oldCoords);
+      throw INTERP_KERNEL::Exception("tryToShareSameCoordsPermute fails : no nodes are mergeable with specified given epsilon !");
+    }
+  int maxId=*std::max_element(da->getConstPointer(),da->getConstPointer()+otherNbOfNodes);
+  const int *pt=std::find_if(da->getConstPointer()+otherNbOfNodes,da->getConstPointer()+da->getNbOfElems(),std::bind2nd(std::greater<int>(),maxId));
+  if(pt!=da->getConstPointer()+da->getNbOfElems())
+    {
+      setCoords(oldCoords);
+      throw INTERP_KERNEL::Exception("tryToShareSameCoordsPermute fails : some nodes in this are not in other !");
+    }
+  setCoords(oldCoords);
+  renumberNodesInConn(da->getConstPointer()+otherNbOfNodes);
+  setCoords(coords);
+}
+
 /*!
  * build a sub part of 'this'. This sub part is defined by the cell ids contained in the array in [start,end).
  * @param start start of array containing the cell ids to keep.
@@ -585,12 +1022,23 @@ void MEDCouplingUMesh::findBoundaryNodes(std::vector<int>& nodes) const
  * This method renumber 'this' using 'newNodeNumbers' array of size this->getNumberOfNodes.
  * newNbOfNodes specifies the *std::max_element(newNodeNumbers,newNodeNumbers+this->getNumberOfNodes())
  * This value is asked because often known by the caller of this method.
+ * This method, contrary to MEDCouplingMesh::renumberCells does NOT conserve the number of nodes before and after.
+ *
  * @param newNodeNumbers array specifying the new numbering.
  * @param newNbOfNodes the new number of nodes.
  */
 void MEDCouplingUMesh::renumberNodes(const int *newNodeNumbers, int newNbOfNodes)
 {
   MEDCouplingPointSet::renumberNodes(newNodeNumbers,newNbOfNodes);
+  renumberNodesInConn(newNodeNumbers);
+}
+
+/*!
+ * This method renumbers nodes in connectivity only without any reference with coords.
+ * Use it with care !
+ */
+void MEDCouplingUMesh::renumberNodesInConn(const int *newNodeNumbers)
+{
   int *conn=getNodalConnectivity()->getPointer();
   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
   int nbOfCells=getNumberOfCells();
@@ -608,8 +1056,10 @@ void MEDCouplingUMesh::renumberNodes(const int *newNodeNumbers, int newNbOfNodes
 }
 
 /*!
- * This method renumbers cells of 'this' using the array specified by [old2NewBg;old2NewEnd)
- * If std::distance(old2NewBg,old2NewEnd)!=this->getNumberOfCells() an INTERP_KERNEL::Exception will be thrown.
+ * This method renumbers cells of 'this' using the array specified by [old2NewBg;old2NewBg+getNumberOfCells())
+ *
+ * Contrary to MEDCouplingPointSet::renumberNodes, this method makes a permutation without any fuse of cell.
+ * After the call of this method the number of cells remains the same as before.
  *
  * If 'check' equals true the method will check that any elements in [old2NewBg;old2NewEnd) is unique ; if not
  * an INTERP_KERNEL::Exception will be thrown. When 'check' equals true [old2NewBg;old2NewEnd) is not expected to
@@ -619,14 +1069,12 @@ void MEDCouplingUMesh::renumberNodes(const int *newNodeNumbers, int newNbOfNodes
  * To avoid any throw of SIGSEGV when 'check' equals false, the elements in [old2NewBg;old2NewEnd) should be unique and
  * should be contained in[0;this->getNumberOfCells()).
  */
-void MEDCouplingUMesh::renumberCells(const int *old2NewBg, const int *old2NewEnd, bool check)
+void MEDCouplingUMesh::renumberCells(const int *old2NewBg, bool check) throw(INTERP_KERNEL::Exception)
 {
   int nbCells=getNumberOfCells();
   const int *array=old2NewBg;
-  if(std::distance(old2NewBg,old2NewEnd)!=nbCells)
-    throw INTERP_KERNEL::Exception("MEDCouplingUMesh::renumberCells expected to take an array of size getNumberOfCells !");
   if(check)
-    array=DataArrayInt::checkAndPreparePermutation(old2NewBg,old2NewEnd);
+    array=DataArrayInt::checkAndPreparePermutation(old2NewBg,old2NewBg+nbCells);
   //
   const int *conn=_nodal_connec->getConstPointer();
   const int *connI=_nodal_connec_index->getConstPointer();
@@ -772,8 +1220,25 @@ INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::getTypeOfCell(int cellId) co
   return (INTERP_KERNEL::NormalizedCellType) pt[ptI[cellId]];
 }
 
+/*!
+ * Returns nb of cells having the geometric type 'type'.
+ */
+int MEDCouplingUMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
+{
+  const int *ptI=_nodal_connec_index->getConstPointer();
+  const int *pt=_nodal_connec->getConstPointer();
+  int nbOfCells=getNumberOfCells();
+  int ret=0;
+  for(int i=0;i<nbOfCells;i++)
+    if((INTERP_KERNEL::NormalizedCellType) pt[ptI[i]]==type)
+      ret++;
+  return ret;
+}
+
 /*!
  * Appends the nodal connectivity in 'conn' of cell with id 'cellId'.
+ * All elements added in conn can be used by MEDCouplingUMesh::getCoordinatesOfNode method.
+ * That is to say -1 separator is omitted in returned conn.
  */
 void MEDCouplingUMesh::getNodeIdsOfCell(int cellId, std::vector<int>& conn) const
 {
@@ -794,6 +1259,75 @@ void MEDCouplingUMesh::getCoordinatesOfNode(int nodeId, std::vector<double>& coo
   coo.insert(coo.end(),cooPtr+spaceDim*nodeId,cooPtr+spaceDim*(nodeId+1));
 }
 
+std::string MEDCouplingUMesh::simpleRepr() const
+{
+  static const char msg0[]="No coordinates specified !";
+  std::ostringstream ret;
+  ret << "Unstructured mesh with name : \"" << getName() << "\"\n";
+  ret << "Mesh dimension : " << _mesh_dim << "\nSpace dimension : ";
+  if(_coords!=0)
+    ret << getSpaceDimension() << "\n";
+  else
+    ret << msg0 << "\n";
+  ret << "Number of nodes : ";
+  if(_coords!=0)
+    ret << getNumberOfNodes() << "\n";
+  else
+    ret << msg0 << "\n";
+  ret << "Number of cells : ";
+  if(_nodal_connec!=0 && _nodal_connec_index!=0)
+    ret << getNumberOfCells() << "\n";
+  else
+    ret << "No connectivity specified !" << "\n";
+  ret << "Cell types present : ";
+  for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
+    {
+      const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::getCellModel(*iter);
+      ret << cm.getRepr() << " ";
+    }
+  ret << "\n";
+  return ret.str();
+}
+
+std::string MEDCouplingUMesh::advancedRepr() const
+{
+  std::ostringstream ret;
+  ret << simpleRepr();
+  ret << "\nCoordinates array : \n___________________\n\n";
+  if(_coords)
+    _coords->reprWithoutNameStream(ret);
+  else
+    ret << "No array set !\n";
+  ret << "\n\nConnectivity arrays : \n_____________________\n\n";
+  reprConnectivityOfThisLL(ret);
+  return ret.str();
+}
+std::string MEDCouplingUMesh::reprConnectivityOfThis() const
+{
+  std::ostringstream ret;
+  reprConnectivityOfThisLL(ret);
+  return ret.str();
+}
+
+void MEDCouplingUMesh::reprConnectivityOfThisLL(std::ostringstream& stream) const
+{
+  if(_nodal_connec!=0 && _nodal_connec_index!=0)
+    {
+      int nbOfCells=getNumberOfCells();
+      const int *c=_nodal_connec->getConstPointer();
+      const int *ci=_nodal_connec_index->getConstPointer();
+      for(int i=0;i<nbOfCells;i++)
+        {
+          const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::getCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[i]]);
+          stream << "Cell #" << i << " " << cm.getRepr() << " : ";
+          std::copy(c+ci[i]+1,c+ci[i+1],std::ostream_iterator<int>(stream," "));
+          stream << "\n";
+        }
+    }
+  else
+    stream << "Connectivity not defined !\n";
+}
+
 int MEDCouplingUMesh::getNumberOfNodesInCell(int cellId) const
 {
   const int *ptI=_nodal_connec_index->getConstPointer();
@@ -919,7 +1453,7 @@ bool MEDCouplingUMesh::isEmptyMesh(const std::vector<int>& tinyInfo) const
  * Second step of serialization process.
  * @param tinyInfo must be equal to the result given by getTinySerializationInformation method.
  */
-void MEDCouplingUMesh::resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings)
+void MEDCouplingUMesh::resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings) const
 {
   MEDCouplingPointSet::resizeForUnserialization(tinyInfo,a1,a2,littleStrings);
   if(tinyInfo[5]!=-1)
@@ -950,7 +1484,7 @@ void MEDCouplingUMesh::serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const
  * Second and final unserialization process.
  * @param tinyInfo must be equal to the result given by getTinySerializationInformation method.
  */
-void MEDCouplingUMesh::unserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, const std::vector<std::string>& littleStrings)
+void MEDCouplingUMesh::unserialization(const std::vector<int>& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2, const std::vector<std::string>& littleStrings)
 {
   MEDCouplingPointSet::unserialization(tinyInfo,a1,a2,littleStrings);
   setMeshDimension(tinyInfo[3]);
@@ -979,8 +1513,17 @@ MEDCouplingUMesh *MEDCouplingUMesh::buildPartOfMySelfKeepCoords(const int *start
 {
   checkFullyDefined();
   MEDCouplingUMesh *ret=MEDCouplingUMesh::New();
-  std::ostringstream stream; stream << PART_OF_NAME << getName();
-  ret->setName(stream.str().c_str());
+  std::string name(getName());
+  int sz=strlen(PART_OF_NAME);
+  if((int)name.length()>=sz)
+    name=name.substr(0,sz);
+  if(name!=PART_OF_NAME)
+    {
+      std::ostringstream stream; stream << PART_OF_NAME << getName();
+      ret->setName(stream.str().c_str());
+    }
+  else
+    ret->setName(getName());
   ret->_mesh_dim=_mesh_dim;
   ret->setCoords(_coords);
   int nbOfElemsRet=end-start;
@@ -1047,8 +1590,7 @@ MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureField(bool isAbs) const
           area_vol[iel]=INTERP_KERNEL::computeVolSurfOfCell2<int,INTERP_KERNEL::ALL_C_MODE>(type,connec+ipt+1,connec_index[iel+1]-ipt-1,coords,dim_space);
         }
       if(isAbs)
-        for(int iel=0;iel<nbelem;iel++)
-          area_vol[iel]=fabs(area_vol[iel]);
+        std::transform(area_vol,area_vol+nbelem,area_vol,std::ptr_fun<double,double>(fabs));
     }
   else
     {
@@ -1352,32 +1894,391 @@ void MEDCouplingUMesh::checkButterflyCells(std::vector<int>& cells) const
 }
 
 /*!
- * This method aggregate the bbox of each cell and put it into bbox parameter.
- * @param bbox out parameter of size 2*spacedim*nbOfcells.
+ * This method is \b NOT const because it can modify 'this'.
+ * 'this' is expected to be an unstructured mesh with meshDim==2 and spaceDim==3. If not an exception will be thrown.
+ * @param mesh1D is an unstructured mesh with MeshDim==1 and spaceDim==3. If not an exception will be thrown.
+ * @param policy specifies the type of extrusion chosen. \b 0 for translation (most simple),
+ * \b 1 for translation and rotation around point of 'mesh1D'.
+ * @return an unstructured mesh with meshDim==3 and spaceDim==3. The returned mesh has the same coords than 'this'.  
  */
-void MEDCouplingUMesh::getBoundingBoxForBBTree(std::vector<double>& bbox) const
+MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMeshFromThis(const MEDCouplingUMesh *mesh1D, int policy)
 {
-  int spaceDim=getSpaceDimension();
-  int nbOfCells=getNumberOfCells();
-  bbox.resize(2*nbOfCells*spaceDim);
-  for(int i=0;i<nbOfCells*spaceDim;i++)
+  checkFullyDefined();
+  mesh1D->checkFullyDefined();
+  if(getMeshDimension()!=2 || getSpaceDimension()!=3)
+    throw INTERP_KERNEL::Exception("Invalid 'this' for buildExtrudedMeshFromThis method : must be meshDim==2 and spaceDim ==3 !");
+  if(mesh1D->getMeshDimension()!=1 || mesh1D->getSpaceDimension()!=3)
+    throw INTERP_KERNEL::Exception("Invalid 'mesh1D' for buildExtrudedMeshFromThis method : must be meshDim==1 and spaceDim ==3 !");
+  bool isQuad=false;
+  if(isPresenceOfQuadratic())
     {
-      bbox[2*i]=std::numeric_limits<double>::max();
-      bbox[2*i+1]=-std::numeric_limits<double>::max();
+      if(mesh1D->isFullyQuadratic())
+        isQuad=true;
+      else
+        throw INTERP_KERNEL::Exception("Invalid 2D mesh and 1D mesh because 2D mesh has quadratic cells and 1D is not fully quadratic !");
     }
-  const double *coordsPtr=_coords->getConstPointer();
-  const int *conn=_nodal_connec->getConstPointer();
-  const int *connI=_nodal_connec_index->getConstPointer();
-  for(int i=0;i<nbOfCells;i++)
+  zipCoords();
+  int oldNbOfNodes=getNumberOfNodes();
+  DataArrayDouble *newCoords=0;
+  switch(policy)
     {
-      int offset=connI[i]+1;
-      int nbOfNodesForCell=connI[i+1]-offset;
-      for(int j=0;j<nbOfNodesForCell;j++)
-        {
-          int nodeId=conn[offset+j];
-          if(nodeId>=0)
-            for(int k=0;k<spaceDim;k++)
-              {
+    case 0:
+      {
+        newCoords=fillExtCoordsUsingTranslation(mesh1D,isQuad);
+        break;
+      }
+    default:
+      throw INTERP_KERNEL::Exception("Not implemented extrusion policy : must be in (0) !");
+    }
+  setCoords(newCoords);
+  newCoords->decrRef();
+  MEDCouplingUMesh *ret=buildExtrudedMeshFromThisLowLev(oldNbOfNodes,isQuad);
+  updateTime();
+  return ret;
+}
+
+/*!
+ * This method incarnates the policy 0 for MEDCouplingUMesh::buildExtrudedMeshFromThis method.
+ * @param mesh1D is the input 1D mesh used for translation computation.
+ * @return newCoords new coords filled by this method. 
+ */
+DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
+{
+  int oldNbOfNodes=getNumberOfNodes();
+  int nbOf1DCells=mesh1D->getNumberOfCells();
+  DataArrayDouble *ret=DataArrayDouble::New();
+  std::vector<bool> isQuads;
+  int nbOfLevsInVec=isQuad?2*nbOf1DCells+1:nbOf1DCells+1;
+  ret->alloc(oldNbOfNodes*nbOfLevsInVec,3);
+  double *retPtr=ret->getPointer();
+  const double *coords=getCoords()->getConstPointer();
+  double *work=std::copy(coords,coords+3*oldNbOfNodes,retPtr);
+  std::vector<int> v;
+  std::vector<double> c;
+  double vec[3];
+  v.reserve(3);
+  c.reserve(6);
+  for(int i=0;i<nbOf1DCells;i++)
+    {
+      v.resize(0);
+      mesh1D->getNodeIdsOfCell(i,v);
+      c.resize(0);
+      mesh1D->getCoordinatesOfNode(v[isQuad?2:1],c);
+      mesh1D->getCoordinatesOfNode(v[0],c);
+      std::transform(c.begin(),c.begin()+3,c.begin()+3,vec,std::minus<double>());
+      for(int j=0;j<oldNbOfNodes;j++)
+        work=std::transform(vec,vec+3,retPtr+3*(i*oldNbOfNodes+j),work,std::plus<double>());
+      if(isQuad)
+        {
+          c.resize(0);
+          mesh1D->getCoordinatesOfNode(v[1],c);
+          mesh1D->getCoordinatesOfNode(v[0],c);
+          std::transform(c.begin(),c.begin()+3,c.begin()+3,vec,std::minus<double>());
+          for(int j=0;j<oldNbOfNodes;j++)
+            work=std::transform(vec,vec+3,retPtr+3*(i*oldNbOfNodes+j),work,std::plus<double>());
+        }
+    }
+  ret->copyStringInfoFrom(*getCoords());
+  return ret;
+}
+
+/*!
+ * This method is private because not easy to use for end user. This method is const contrary to
+ * MEDCouplingUMesh::buildExtrudedMeshFromThis method because this->_coords are expected to contain
+ * the coords sorted slice by slice.
+ * @param isQuad specifies presence of quadratic cells.
+ */
+MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMeshFromThisLowLev(int nbOfNodesOf1Lev, bool isQuad) const
+{
+  int nbOf1DCells=getNumberOfNodes()/nbOfNodesOf1Lev-1;
+  int nbOf2DCells=getNumberOfCells();
+  int nbOf3DCells=nbOf2DCells*nbOf1DCells;
+  MEDCouplingUMesh *ret=MEDCouplingUMesh::New("Extruded",3);
+  const int *conn=_nodal_connec->getConstPointer();
+  const int *connI=_nodal_connec_index->getConstPointer();
+  DataArrayInt *newConn=DataArrayInt::New();
+  DataArrayInt *newConnI=DataArrayInt::New();
+  newConnI->alloc(nbOf3DCells+1,1);
+  int *newConnIPtr=newConnI->getPointer();
+  *newConnIPtr++=0;
+  std::vector<int> newc;
+  for(int j=0;j<nbOf2DCells;j++)
+    {
+      appendExtrudedCell(conn+connI[j],conn+connI[j+1],nbOfNodesOf1Lev,isQuad,newc);
+      *newConnIPtr++=newc.size();
+    }
+  newConn->alloc(newc.size()*nbOf1DCells,1);
+  int *newConnPtr=newConn->getPointer();
+  int deltaPerLev=isQuad?2*nbOfNodesOf1Lev:nbOfNodesOf1Lev;
+  newConnIPtr=newConnI->getPointer();
+  for(int iz=0;iz<nbOf1DCells;iz++)
+    {
+      if(iz!=0)
+        std::transform(newConnIPtr+1,newConnIPtr+1+nbOf2DCells,newConnIPtr+1+iz*nbOf2DCells,std::bind2nd(std::plus<int>(),newConnIPtr[iz*nbOf2DCells]));
+      for(std::vector<int>::const_iterator iter=newc.begin();iter!=newc.end();iter++,newConnPtr++)
+        {
+          int icell=iter-newc.begin();
+          if(std::find(newConnIPtr,newConnIPtr+nbOf2DCells,icell)==newConnIPtr+nbOf2DCells)
+            {
+              if(*iter!=-1)
+                *newConnPtr=(*iter)+iz*deltaPerLev;
+              else
+                *newConnPtr=-1;
+            }
+          else
+            *newConnPtr=(*iter);
+        }
+    }
+  ret->setConnectivity(newConn,newConnI,true);
+  newConn->decrRef();
+  newConnI->decrRef();
+  ret->setCoords(getCoords());
+  return ret;
+}
+
+/*!
+ * This method returns if 'this' is constituted by only quadratic cells.
+ */
+bool MEDCouplingUMesh::isFullyQuadratic() const
+{
+  checkFullyDefined();
+  bool ret=true;
+  int nbOfCells=getNumberOfCells();
+  for(int i=0;i<nbOfCells && ret;i++)
+    {
+      INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
+      const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::getCellModel(type);
+      ret=cm.isQuadratic();
+    }
+  return ret;
+}
+
+/*!
+ * This method returns if there is at least one quadratic cell.
+ */
+bool MEDCouplingUMesh::isPresenceOfQuadratic() const
+{
+  checkFullyDefined();
+  bool ret=false;
+  int nbOfCells=getNumberOfCells();
+  for(int i=0;i<nbOfCells && !ret;i++)
+    {
+      INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
+      const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::getCellModel(type);
+      ret=cm.isQuadratic();
+    }
+  return ret;
+}
+
+/*!
+ * This method convert quadratic cells to linear cells if any was found.
+ * If no such cells exists 'this' remains unchanged.
+ */
+void MEDCouplingUMesh::convertQuadraticCellsToLinear() throw(INTERP_KERNEL::Exception)
+{
+  checkFullyDefined();
+  int nbOfCells=getNumberOfCells();
+  int delta=0;
+  for(int i=0;i<nbOfCells;i++)
+    {
+      INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
+      const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::getCellModel(type);
+      if(cm.isQuadratic())
+        {
+          INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
+          const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::getCellModel(typel);
+          delta+=cm.getNumberOfNodes()-cml.getNumberOfNodes();
+        }
+    }
+  if(delta==0)
+    return ;
+  MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
+  MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
+  newConn->alloc(getMeshLength()-delta,1);
+  newConnI->alloc(nbOfCells+1,1);
+  const int *icptr=_nodal_connec->getConstPointer();
+  const int *iciptr=_nodal_connec_index->getConstPointer();
+  int *ocptr=newConn->getPointer();
+  int *ociptr=newConnI->getPointer();
+  *ociptr=0;
+  _types.clear();
+  for(int i=0;i<nbOfCells;i++,ociptr++)
+    {
+      INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
+      const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::getCellModel(type);
+      if(!cm.isQuadratic())
+        {
+          _types.insert(type);
+          ocptr=std::copy(icptr+iciptr[i],icptr+iciptr[i+1],ocptr);
+          ociptr[1]=ociptr[0]+iciptr[i+1]-iciptr[i];
+        }
+      else
+        {
+          INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
+          _types.insert(typel);
+          const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::getCellModel(typel);
+          int newNbOfNodes=cml.getNumberOfNodes();
+          *ocptr++=(int)typel;
+          ocptr=std::copy(icptr+iciptr[i]+1,icptr+iciptr[i]+newNbOfNodes+1,ocptr);
+          ociptr[1]=ociptr[0]+newNbOfNodes+1;
+        }
+    }
+  setConnectivity(newConn,newConnI,false);
+}
+
+/*!
+ * This method checks that all or only polygons (depending 'polyOnly' parameter) 2D cells are correctly oriented relative to 'vec' vector.
+ * The 'vec' vector has to have a non nul norm.
+ * If not 'cells' parameter will be appended with cellIds of incorrect cells.
+ * @throw when 'this' is not a mesh with meshdim==2 and spacedim==3
+ */
+void MEDCouplingUMesh::are2DCellsNotCorrectlyOriented(const double *vec, bool polyOnly, std::vector<int>& cells) const throw(INTERP_KERNEL::Exception)
+{
+  if(getMeshDimension()!=2 || getSpaceDimension()!=3)
+    throw INTERP_KERNEL::Exception("Invalid mesh to apply are2DCellsNotCorrectlyOriented on it : must be meshDim==2 and spaceDim==3 !");
+  int nbOfCells=getNumberOfCells();
+  const int *conn=_nodal_connec->getConstPointer();
+  const int *connI=_nodal_connec_index->getConstPointer();
+  const double *coordsPtr=_coords->getConstPointer();
+  for(int i=0;i<nbOfCells;i++)
+    {
+      INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
+      if(!polyOnly || type==INTERP_KERNEL::NORM_POLYGON)
+        {
+          if(!isPolygonWellOriented(vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
+            cells.push_back(i);
+        }
+    }
+}
+
+/*!
+ * This method orient correctly (if needed) all or only polygons (depending 'polyOnly' parameter)  2D cells are correctly oriented relative to 'vec' vector.
+ * The 'vec' vector has to have a non nul norm.
+ * @throw when 'this' is not a mesh with meshdim==2 and spacedim==3
+ */
+void MEDCouplingUMesh::orientCorrectly2DCells(const double *vec, bool polyOnly) throw(INTERP_KERNEL::Exception)
+{
+  if(getMeshDimension()!=2 || getSpaceDimension()!=3)
+    throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectly2DCells on it : must be meshDim==2 and spaceDim==3 !");
+  int nbOfCells=getNumberOfCells();
+  int *conn=_nodal_connec->getPointer();
+  const int *connI=_nodal_connec_index->getConstPointer();
+  const double *coordsPtr=_coords->getConstPointer();
+  bool isModified=false;
+  for(int i=0;i<nbOfCells;i++)
+    {
+      INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
+      if(!polyOnly || type==INTERP_KERNEL::NORM_POLYGON)
+        if(!isPolygonWellOriented(vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
+          {
+            isModified=true;
+            std::vector<int> tmp(connI[i+1]-connI[i]-2);
+            std::copy(conn+connI[i]+2,conn+connI[i+1],tmp.rbegin());
+            std::copy(tmp.begin(),tmp.end(),conn+connI[i]+2);
+          }
+    }
+  if(isModified)
+    _nodal_connec->declareAsNew();
+  updateTime();
+}
+
+/*!
+ * This method checks that all polyhedrons cells have correctly oriented faces.
+ * If not, 'cells' parameter will be appended with cellIds of incorrect cells.
+ * @throw when 'this' is not a mesh with meshdim==3 and spacedim==3
+ */
+void MEDCouplingUMesh::arePolyhedronsNotCorrectlyOriented(std::vector<int>& cells) const throw(INTERP_KERNEL::Exception)
+{
+  if(getMeshDimension()!=3 || getSpaceDimension()!=3)
+    throw INTERP_KERNEL::Exception("Invalid mesh to apply arePolyhedronsNotCorrectlyOriented on it : must be meshDim==3 and spaceDim==3 !");
+  int nbOfCells=getNumberOfCells();
+  const int *conn=_nodal_connec->getConstPointer();
+  const int *connI=_nodal_connec_index->getConstPointer();
+  const double *coordsPtr=_coords->getConstPointer();
+  for(int i=0;i<nbOfCells;i++)
+    {
+      INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
+      if(type==INTERP_KERNEL::NORM_POLYHED)
+        {
+          if(!isPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
+            cells.push_back(i);
+        }
+    }
+}
+
+/*!
+ * This method tries to orient correctly polhedrons cells.
+ * @throw when 'this' is not a mesh with meshdim==3 and spacedim==3. An exception is also thrown when the attempt of reparation fails.
+ */
+void MEDCouplingUMesh::orientCorrectlyPolyhedrons() throw(INTERP_KERNEL::Exception)
+{
+  if(getMeshDimension()!=3 || getSpaceDimension()!=3)
+    throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectlyPolyhedrons on it : must be meshDim==3 and spaceDim==3 !");
+  int nbOfCells=getNumberOfCells();
+  int *conn=_nodal_connec->getPointer();
+  const int *connI=_nodal_connec_index->getConstPointer();
+  const double *coordsPtr=_coords->getConstPointer();
+  bool isModified=false;
+  for(int i=0;i<nbOfCells;i++)
+    {
+      INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
+      if(type==INTERP_KERNEL::NORM_POLYHED)
+        if(!isPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
+          {
+            tryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
+            isModified=true;
+          }
+    }
+  if(isModified)
+    _nodal_connec->declareAsNew();
+  updateTime();
+}
+
+/*!
+ * This method has a sense for meshes with spaceDim==3 and meshDim==2.
+ * If it is not the case an exception will be thrown.
+ * This method is fast because the first cell of 'this' is used to compute the plane.
+ * @param vec output of size at least 3 used to store the normal vector (with norm equal to Area ) of searched plane.
+ * @param pos output of size at least 3 used to store a point owned of searched plane.
+ */
+void MEDCouplingUMesh::getFastMiddlePlaneOfThis(double *vec, double *pos) const throw(INTERP_KERNEL::Exception)
+{
+  if(getMeshDimension()!=2 || getSpaceDimension()!=3)
+    throw INTERP_KERNEL::Exception("Invalid mesh to apply getFastMiddlePlaneOfThis on it : must be meshDim==2 and spaceDim==3 !");
+  const int *conn=_nodal_connec->getConstPointer();
+  const int *connI=_nodal_connec_index->getConstPointer();
+  const double *coordsPtr=_coords->getConstPointer();
+  INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(conn+1,connI[1]-connI[0]-1,coordsPtr,vec);
+  std::copy(coordsPtr+3*conn[1],coordsPtr+3*conn[1]+3,pos);
+}
+
+/*!
+ * This method aggregate the bbox of each cell and put it into bbox parameter.
+ * @param bbox out parameter of size 2*spacedim*nbOfcells.
+ */
+void MEDCouplingUMesh::getBoundingBoxForBBTree(std::vector<double>& bbox) const
+{
+  int spaceDim=getSpaceDimension();
+  int nbOfCells=getNumberOfCells();
+  bbox.resize(2*nbOfCells*spaceDim);
+  for(int i=0;i<nbOfCells*spaceDim;i++)
+    {
+      bbox[2*i]=std::numeric_limits<double>::max();
+      bbox[2*i+1]=-std::numeric_limits<double>::max();
+    }
+  const double *coordsPtr=_coords->getConstPointer();
+  const int *conn=_nodal_connec->getConstPointer();
+  const int *connI=_nodal_connec_index->getConstPointer();
+  for(int i=0;i<nbOfCells;i++)
+    {
+      int offset=connI[i]+1;
+      int nbOfNodesForCell=connI[i+1]-offset;
+      for(int j=0;j<nbOfNodesForCell;j++)
+        {
+          int nodeId=conn[offset+j];
+          if(nodeId>=0)
+            for(int k=0;k<spaceDim;k++)
+              {
                 bbox[2*spaceDim*i+2*k]=std::min(bbox[2*spaceDim*i+2*k],coordsPtr[spaceDim*nodeId+k]);
                 bbox[2*spaceDim*i+2*k+1]=std::max(bbox[2*spaceDim*i+2*k+1],coordsPtr[spaceDim*nodeId+k]);
               }
@@ -1398,8 +2299,13 @@ namespace ParaMEDMEMImpl
   };
 }
 
+/*!
+ * This methods checks that cells are sorted by their types.
+ * This method makes asumption (no check) that connectivity is correctly set before calling.
+ */
 bool MEDCouplingUMesh::checkConsecutiveCellTypes() const
 {
+  checkFullyDefined();
   const int *conn=_nodal_connec->getConstPointer();
   const int *connI=_nodal_connec_index->getConstPointer();
   int nbOfCells=getNumberOfCells();
@@ -1415,6 +2321,198 @@ bool MEDCouplingUMesh::checkConsecutiveCellTypes() const
   return true;
 }
 
+/*!
+ * This method performs the same job as checkConsecutiveCellTypes except that the order of types sequence is analyzed to check
+ * that the order is specified in array defined by [orderBg,orderEnd). 
+ */
+bool MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
+{
+  checkFullyDefined();
+  const int *conn=_nodal_connec->getConstPointer();
+  const int *connI=_nodal_connec_index->getConstPointer();
+  int nbOfCells=getNumberOfCells();
+  int lastPos=-1;
+  for(const int *i=connI;i!=connI+nbOfCells;)
+    {
+      INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
+      int pos=std::distance(orderBg,std::find(orderBg,orderEnd,curType));
+      if(pos<=lastPos)
+        return false;
+      lastPos=pos;
+      i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
+    }
+  return true;
+}
+
+/*!
+ * This method is similar to method MEDCouplingUMesh::rearrange2ConsecutiveCellTypes except that the type order is specfied by [orderBg,orderEnd) (as MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method) and that this method is \b const and performs \b NO permutation is 'this'.
+ * This method returns an array of size getNumberOfCells() that gives a renumber array old2New that can be used as input of MEDCouplingMesh::renumberCells.
+ * The mesh after this call will pass the test of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder with the same inputs.
+ * The returned array minimizes the permutations that is to say the order of cells inside same geometric type remains the same.
+ */
+DataArrayInt *MEDCouplingUMesh::getRenumArrForConsctvCellTypesSpe(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
+{
+  checkFullyDefined();
+  int nbOfCells=getNumberOfCells();
+  const int *conn=_nodal_connec->getConstPointer();
+  const int *connI=_nodal_connec_index->getConstPointer();
+  int *tmp=new int[nbOfCells];
+  int minPos=std::numeric_limits<int>::max();
+  for(const int *i=connI;i!=connI+nbOfCells;i++)
+    {
+      int pos=std::distance(orderBg,std::find(orderBg,orderEnd,(INTERP_KERNEL::NormalizedCellType)conn[*i]));
+      tmp[std::distance(connI,i)]=pos;
+      minPos=std::min(minPos,pos);
+    }
+  DataArrayInt *ret=DataArrayInt::New();
+  ret->alloc(nbOfCells,1);
+  int *optr=ret->getPointer();
+  int k=0;
+  while(minPos!=std::numeric_limits<int>::max())
+    {    
+      int nextMinPos=std::numeric_limits<int>::max();
+      for(int j=0;j<nbOfCells;j++)
+        {
+          if(tmp[j]==minPos)
+            {
+              optr[j]=k++;
+              tmp[j]=std::numeric_limits<int>::max();
+            }
+          else
+            nextMinPos=std::min(nextMinPos,tmp[j]);
+        }
+      minPos=nextMinPos;
+    }
+  delete [] tmp;
+  return ret;
+}
+
+/*!
+ * This method reorganize the cells of 'this' so that the cells with same geometric types are put together.
+ * If checkConsecutiveCellTypes() returns true, this method do not change anything of this.
+ * The number of cells remains unchanged after the call of this method.
+ * @return the array giving the correspondance old to new.
+ */
+DataArrayInt *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes()
+{
+  checkFullyDefined();
+  computeTypes();
+  const int *conn=_nodal_connec->getConstPointer();
+  const int *connI=_nodal_connec_index->getConstPointer();
+  int nbOfCells=getNumberOfCells();
+  std::vector<INTERP_KERNEL::NormalizedCellType> types;
+  for(const int *i=connI;i!=connI+nbOfCells && (types.size()!=_types.size());)
+    if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)conn[*i])==types.end())
+      {
+        INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
+        types.push_back(curType);
+        for(i++;i!=connI+nbOfCells && (INTERP_KERNEL::NormalizedCellType)conn[*i]==curType;i++);
+      }
+  DataArrayInt *ret=DataArrayInt::New();
+  ret->alloc(nbOfCells,1);
+  int *retPtr=ret->getPointer();
+  std::fill(retPtr,retPtr+nbOfCells,-1);
+  int newCellId=0;
+  for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
+    {
+      for(const int *i=connI;i!=connI+nbOfCells;i++)
+        if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
+          retPtr[std::distance(connI,i)]=newCellId++;
+    }
+  renumberCells(retPtr,false);
+  return ret;
+}
+
+/*!
+ * This methods split this into as mush as untructured meshes that consecutive set of same type cells.
+ * So this method has typically a sense if MEDCouplingUMesh::checkConsecutiveCellTypes has a sense.
+ * This method makes asumption that connectivity is correctly set before calling.
+ */
+std::vector<MEDCouplingUMesh *> MEDCouplingUMesh::splitByType() const
+{
+  checkFullyDefined();
+  const int *conn=_nodal_connec->getConstPointer();
+  const int *connI=_nodal_connec_index->getConstPointer();
+  int nbOfCells=getNumberOfCells();
+  std::vector<MEDCouplingUMesh *> ret;
+  for(const int *i=connI;i!=connI+nbOfCells;)
+    {
+      INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
+      int startCellId=std::distance(connI,i);
+      i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
+      int endCellId=std::distance(connI,i);
+      int sz=endCellId-startCellId;
+      int *cells=new int[sz];
+      for(int j=0;j<sz;j++)
+        cells[j]=startCellId+j;
+      MEDCouplingUMesh *m=(MEDCouplingUMesh *)buildPartOfMySelf(cells,cells+sz,true);
+      delete [] cells;
+      ret.push_back(m);
+    }
+  return ret;
+}
+
+/*!
+ * This method makes the assumption that da->getNumberOfTuples()<this->getNumberOfCells(). This method makes the assumption that ids contained in 'da'
+ * are in [0:getNumberOfCells())
+ */
+DataArrayInt *MEDCouplingUMesh::convertCellArrayPerGeoType(const DataArrayInt *da) const throw(INTERP_KERNEL::Exception)
+{
+  checkFullyDefined();
+  const int *conn=_nodal_connec->getConstPointer();
+  const int *connI=_nodal_connec_index->getConstPointer();
+  int nbOfCells=getNumberOfCells();
+  std::set<INTERP_KERNEL::NormalizedCellType> types=getAllTypes();
+  int *tmp=new int[nbOfCells];
+  for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
+    {
+      int j=0;
+      for(const int *i=connI;i!=connI+nbOfCells;i++)
+        if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
+          tmp[std::distance(connI,i)]=j++;
+    }
+  DataArrayInt *ret=DataArrayInt::New();
+  ret->alloc(da->getNumberOfTuples(),da->getNumberOfComponents());
+  ret->copyStringInfoFrom(*da);
+  int *retPtr=ret->getPointer();
+  const int *daPtr=da->getConstPointer();
+  int nbOfElems=da->getNbOfElems();
+  for(int k=0;k<nbOfElems;k++)
+    retPtr[k]=tmp[daPtr[k]];
+  delete [] tmp;
+  return ret;
+}
+
+/*!
+ * This method reduced number of cells of this by keeping cells whose type is different from 'type' and if type=='type'
+ * cells whose ids is in 'idsPerGeoType' array.
+ * This method conserves coords and name of mesh.
+ */
+MEDCouplingUMesh *MEDCouplingUMesh::keepSpecifiedCells(INTERP_KERNEL::NormalizedCellType type, const std::vector<int>& idsPerGeoType) const
+{
+  std::vector<int> idsTokeep;
+  int nbOfCells=getNumberOfCells();
+  int j=0;
+  for(int i=0;i<nbOfCells;i++)
+    if(getTypeOfCell(i)!=type)
+      idsTokeep.push_back(i);
+    else
+      {
+        if(std::find(idsPerGeoType.begin(),idsPerGeoType.end(),j)!=idsPerGeoType.end())
+          idsTokeep.push_back(i);
+        j++;
+      }
+  MEDCouplingPointSet *ret=buildPartOfMySelf(&idsTokeep[0],&idsTokeep[0]+idsTokeep.size(),true);
+  MEDCouplingUMesh *ret2=dynamic_cast<MEDCouplingUMesh *>(ret);
+  if(!ret2)
+    {
+      ret->decrRef();
+      return 0;
+    }
+  ret2->setName(getName());
+  return ret2;
+}
+
 /*!
  * Returns a newly created mesh (with ref count ==1) that contains merge of 'this' and 'other'.
  */
@@ -1444,15 +2542,9 @@ DataArrayDouble *MEDCouplingUMesh::getBarycenterAndOwner() const
   const double *coor=_coords->getConstPointer();
   for(int i=0;i<nbOfCells;i++)
     {
-      int nbOfPts=0;
-      std::fill(tmp,tmp+spaceDim,0.);
-      for(const int *node=nodal+nodalI[i]+1;node!=nodal+nodalI[i+1];node++)
-        if(*node!=-1)
-          {
-            std::transform(tmp,tmp+spaceDim,coor+(*node)*spaceDim,tmp,std::plus<double>());
-            nbOfPts++;
-          }
-      ptToFill=std::transform(tmp,tmp+spaceDim,ptToFill,std::bind2nd(std::divides<double>(),(double)nbOfPts));
+      INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
+      INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[i]+1,nodalI[i+1]-nodalI[i]-1,coor,spaceDim,ptToFill);
+      ptToFill+=spaceDim;
     }
   delete [] tmp;
   return ret;
@@ -1460,6 +2552,7 @@ DataArrayDouble *MEDCouplingUMesh::getBarycenterAndOwner() const
 
 /*!
  * Returns a newly created mesh (with ref count ==1) that contains merge of 'mesh1' and 'other'.
+ * The coords of 'mesh2' are added at the end of coords of 'mesh1'.
  */
 MEDCouplingUMesh *MEDCouplingUMesh::mergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
 {
@@ -1498,3 +2591,269 @@ MEDCouplingUMesh *MEDCouplingUMesh::mergeUMeshes(const MEDCouplingUMesh *mesh1,
   nodal->decrRef();
   return ret;
 }
+
+/*!
+ * Idem mergeUMeshes except that 'meshes' are expected to lyie on the same coords and 'meshes' have the same meshdim.
+ * 'meshes' must be a non empty vector.
+ */
+MEDCouplingUMesh *MEDCouplingUMesh::mergeUMeshesOnSameCoords(const std::vector<MEDCouplingUMesh *>& meshes)
+{
+  if(meshes.empty())
+    throw INTERP_KERNEL::Exception("meshes input parameter is expected to be non empty.");
+  DataArrayDouble *coords=meshes.front()->getCoords();
+  int meshDim=meshes.front()->getMeshDimension();
+  std::vector<MEDCouplingUMesh *>::const_iterator iter=meshes.begin();
+  int meshLgth=0;
+  int meshIndexLgth=0;
+  for(;iter!=meshes.end();iter++)
+    {
+      if(coords!=(*iter)->getCoords())
+        throw INTERP_KERNEL::Exception("meshes does not share the same coords ! Try using tryToShareSameCoords method !");
+      if(meshDim!=(*iter)->getMeshDimension())
+        throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, fuseUMeshesOnSameCoords impossible !");
+      meshLgth+=(*iter)->getMeshLength();
+      meshIndexLgth+=(*iter)->getNumberOfCells();
+    }
+  DataArrayInt *nodal=DataArrayInt::New();
+  nodal->alloc(meshLgth,1);
+  int *nodalPtr=nodal->getPointer();
+  DataArrayInt *nodalIndex=DataArrayInt::New();
+  nodalIndex->alloc(meshIndexLgth+1,1);
+  int *nodalIndexPtr=nodalIndex->getPointer();
+  int offset=0;
+  for(iter=meshes.begin();iter!=meshes.end();iter++)
+    {
+      const int *nod=(*iter)->getNodalConnectivity()->getConstPointer();
+      const int *index=(*iter)->getNodalConnectivityIndex()->getConstPointer();
+      int nbOfCells=(*iter)->getNumberOfCells();
+      int meshLgth=(*iter)->getMeshLength();
+      nodalPtr=std::copy(nod,nod+meshLgth,nodalPtr);
+      if(iter!=meshes.begin())
+        nodalIndexPtr=std::transform(index+1,index+nbOfCells+1,nodalIndexPtr,std::bind2nd(std::plus<int>(),offset));
+      else
+        nodalIndexPtr=std::copy(index,index+nbOfCells+1,nodalIndexPtr);
+      offset+=meshLgth;
+    }
+  MEDCouplingUMesh *ret=MEDCouplingUMesh::New();
+  ret->setName("merge");
+  ret->setMeshDimension(meshDim);
+  ret->setConnectivity(nodal,nodalIndex,true);
+  ret->setCoords(coords);
+  nodalIndex->decrRef();
+  nodal->decrRef();
+  return ret;
+}
+
+/*!
+ * This method fuses meshes 'meshes' and returns the fused mesh and the correspondances arrays for each mesh in 'meshes' in returned mesh.
+ * If a same cell is detected in several meshes in 'meshes', this cell will appear only once in returned mesh (see ParaMEDMEM::MEDCouplingUMesh::zipConnectivityTraducer for more details)
+ *
+ * @param meshes input non empty vector containing meshes having same coordiantes array and same mesh dimension.
+ * @param compType see MEDCouplingUMesh::zipConnectivityTraducer
+ * @param corr output vector with same size as 'meshes' parameter. corr[i] is the correspondance array of mesh meshes[i] in returned mesh.
+ *             The arrays contained in 'corr' parameter are returned with refcounter set to one.
+ *             To avoid memory leaks the caller have to deal with each instances of DataArrayInt contained in 'corr' parameter.
+ * @return The mesh lying on the same coordinates than those in meshes. All cells in 'meshes' are in returned mesh with 
+ * @exception if meshes is a empty vector or meshes are not lying on same coordinates or meshes not have the same dimension.
+ */
+MEDCouplingUMesh *MEDCouplingUMesh::fuseUMeshesOnSameCoords(const std::vector<MEDCouplingUMesh *>& meshes, int compType, std::vector<DataArrayInt *>& corr)
+{
+  //All checks are delegated to mergeUMeshesOnSameCoords
+  MEDCouplingUMesh *ret=mergeUMeshesOnSameCoords(meshes);
+  DataArrayInt *o2n=ret->zipConnectivityTraducer(compType);
+  corr.resize(meshes.size());
+  int nbOfMeshes=meshes.size();
+  int offset=0;
+  const int *o2nPtr=o2n->getConstPointer();
+  for(int i=0;i<nbOfMeshes;i++)
+    {
+      DataArrayInt *tmp=DataArrayInt::New();
+      int curNbOfCells=meshes[i]->getNumberOfCells();
+      tmp->alloc(curNbOfCells,1);
+      std::copy(o2nPtr+offset,o2nPtr+offset+curNbOfCells,tmp->getPointer());
+      offset+=curNbOfCells;
+      corr[i]=tmp;
+    }
+  o2n->decrRef();
+  return ret;
+}
+
+/*!
+ * This method takes in input a cell defined by its MEDcouplingUMesh connectivity [connBg,connEnd) and returns its extruded cell by inserting the result at the end of ret.
+ * @param nbOfNodesPerLev in parameter that specifies the number of nodes of one slice of global dataset
+ * @param isQuad specifies the policy of connectivity.
+ * @ret in/out parameter in which the result will be append
+ */
+void MEDCouplingUMesh::appendExtrudedCell(const int *connBg, const int *connEnd, int nbOfNodesPerLev, bool isQuad, std::vector<int>& ret)
+{
+  INTERP_KERNEL::NormalizedCellType flatType=(INTERP_KERNEL::NormalizedCellType)connBg[0];
+  const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::getCellModel(flatType);
+  ret.push_back(cm.getExtrudedType());
+  int deltaz=isQuad?2*nbOfNodesPerLev:nbOfNodesPerLev;
+  switch(flatType)
+    {
+    case INTERP_KERNEL::NORM_POINT0:
+      {
+        ret.push_back(connBg[1]);
+        ret.push_back(connBg[1]+nbOfNodesPerLev);
+        break;
+      }
+    case INTERP_KERNEL::NORM_SEG2:
+      {
+        int conn[4]={connBg[1],connBg[2],connBg[2]+deltaz,connBg[1]+deltaz};
+        ret.insert(ret.end(),conn,conn+4);
+        break;
+      }
+    case INTERP_KERNEL::NORM_SEG3:
+      {
+        int conn[8]={connBg[1],connBg[3],connBg[3]+deltaz,connBg[1]+deltaz,connBg[2],connBg[3]+nbOfNodesPerLev,connBg[2]+deltaz,connBg[1]+nbOfNodesPerLev};
+        ret.insert(ret.end(),conn,conn+8);
+        break;
+      }
+    case INTERP_KERNEL::NORM_QUAD4:
+      {
+        int conn[8]={connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz};
+        ret.insert(ret.end(),conn,conn+8);
+        break;
+      }
+    case INTERP_KERNEL::NORM_TRI3:
+      {
+        int conn[6]={connBg[1],connBg[2],connBg[3],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz};
+        ret.insert(ret.end(),conn,conn+6);
+        break;
+      }
+    case INTERP_KERNEL::NORM_TRI6:
+      {
+        int conn[15]={connBg[1],connBg[2],connBg[3],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4],connBg[5],connBg[6],connBg[4]+deltaz,connBg[5]+deltaz,connBg[6]+deltaz,
+                      connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev};
+        ret.insert(ret.end(),conn,conn+15);
+        break;
+      }
+    case INTERP_KERNEL::NORM_QUAD8:
+      {
+        int conn[20]={
+          connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz,
+          connBg[5],connBg[6],connBg[7],connBg[8],connBg[5]+deltaz,connBg[6]+deltaz,connBg[7]+deltaz,connBg[8]+deltaz,
+          connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev,connBg[4]+nbOfNodesPerLev
+        };
+        ret.insert(ret.end(),conn,conn+20);
+        break;
+      }
+    case INTERP_KERNEL::NORM_POLYGON:
+      {
+        std::back_insert_iterator< std::vector<int> > ii(ret);
+        std::copy(connBg+1,connEnd,ii);
+        *ii++=-1;
+        std::reverse_iterator<const int *> rConnBg(connEnd);
+        std::reverse_iterator<const int *> rConnEnd(connBg+1);
+        std::transform(rConnBg,rConnEnd,ii,std::bind2nd(std::plus<int>(),deltaz));
+        int nbOfRadFaces=std::distance(connBg+1,connEnd);
+        for(int i=0;i<nbOfRadFaces;i++)
+          {
+            *ii++=-1;
+            int conn[4]={connBg[(i+1)%nbOfRadFaces+1],connBg[i+1],connBg[i+1]+deltaz,connBg[(i+1)%nbOfRadFaces+1]+deltaz};
+            std::copy(conn,conn+4,ii);
+          }
+        break;
+      }
+    default:
+      throw INTERP_KERNEL::Exception("A flat type has been detected that has not its extruded representation !");
+    }
+}
+
+/*!
+ * This static operates only for coords in 3D. The polygon is specfied by its connectivity nodes in [begin,end).
+ */
+bool MEDCouplingUMesh::isPolygonWellOriented(const double *vec, const int *begin, const int *end, const double *coords)
+{
+  double v[3]={0.,0.,0.};
+  int sz=std::distance(begin,end);
+  for(int i=0;i<sz;i++)
+    {
+      v[0]+=coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]+2]-coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]+1];
+      v[1]+=coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]]-coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+2];
+      v[2]+=coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+1]-coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]];
+    }
+  return vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2]<0.;
+}
+
+/*!
+ * The polyhedron is specfied by its connectivity nodes in [begin,end).
+ */
+bool MEDCouplingUMesh::isPolyhedronWellOriented(const int *begin, const int *end, const double *coords)
+{
+  std::vector<std::pair<int,int> > edges;
+  int nbOfFaces=std::count(begin,end,-1)+1;
+  const int *bgFace=begin;
+  for(int i=0;i<nbOfFaces;i++)
+    {
+      const int *endFace=std::find(bgFace+1,end,-1);
+      int nbOfEdgesInFace=std::distance(bgFace,endFace);
+      for(int j=0;j<nbOfEdgesInFace;j++)
+        {
+          std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
+          if(std::find(edges.begin(),edges.end(),p1)!=edges.end())
+            return false;
+          edges.push_back(p1);
+        }
+      bgFace=endFace+1;
+    }
+  return INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,std::distance(begin,end),coords)>-EPS_FOR_POLYH_ORIENTATION;
+}
+
+/*!
+ * This method tries to obtain a well oriented polyhedron.
+ * If the algorithm fails, an exception will be thrown.
+ */
+void MEDCouplingUMesh::tryToCorrectPolyhedronOrientation(int *begin, int *end, const double *coords) throw(INTERP_KERNEL::Exception)
+{
+  std::vector<std::pair<int,int> > edges;
+  int nbOfFaces=std::count(begin,end,-1)+1;
+  int *bgFace=begin;
+  std::vector<bool> isPerm(nbOfFaces);
+  for(int i=0;i<nbOfFaces;i++)
+    {
+      int *endFace=std::find(bgFace+1,end,-1);
+      int nbOfEdgesInFace=std::distance(bgFace,endFace);
+      for(int l=0;l<nbOfEdgesInFace;l++)
+        {
+          std::pair<int,int> p1(bgFace[l],bgFace[(l+1)%nbOfEdgesInFace]);
+          edges.push_back(p1);
+        }
+      int *bgFace2=endFace+1;
+      for(int k=i+1;k<nbOfFaces;k++)
+        {
+          int *endFace2=std::find(bgFace2+1,end,-1);
+          int nbOfEdgesInFace2=std::distance(bgFace2,endFace2);
+          for(int j=0;j<nbOfEdgesInFace2;j++)
+            {
+              std::pair<int,int> p2(bgFace2[j],bgFace2[(j+1)%nbOfEdgesInFace2]);
+              if(std::find(edges.begin(),edges.end(),p2)!=edges.end())
+                {
+                  if(isPerm[k])
+                    throw INTERP_KERNEL::Exception("Fail to repare polyhedron ! Polyedron looks bad !");
+                  std::vector<int> tmp(nbOfEdgesInFace2-1);
+                  std::copy(bgFace2+1,endFace2,tmp.rbegin());
+                  std::copy(tmp.begin(),tmp.end(),bgFace2+1);
+                  isPerm[k]=true;
+                  continue;
+                }
+            }
+          bgFace2=endFace2+1;
+        }
+      bgFace=endFace+1;
+    }
+  if(INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,std::distance(begin,end),coords)<-EPS_FOR_POLYH_ORIENTATION)
+    {//not lucky ! The first face was not correctly oriented : reorient all faces...
+      bgFace=begin;
+      for(int i=0;i<nbOfFaces;i++)
+        {
+          int *endFace=std::find(bgFace+1,end,-1);
+          int nbOfEdgesInFace=std::distance(bgFace,endFace);
+          std::vector<int> tmp(nbOfEdgesInFace-1);
+          std::copy(bgFace+1,endFace,tmp.rbegin());
+          std::copy(tmp.begin(),tmp.end(),bgFace+1);
+          bgFace=endFace+1;
+        }
+    }
+}
index 074de0b7b5de9a8fcba41928c9a9563abaf77b3d..0d06ef235d278a638a69cdd95548051929bc2682 100644 (file)
@@ -33,10 +33,17 @@ namespace ParaMEDMEM
   public:
     MEDCOUPLING_EXPORT static MEDCouplingUMesh *New();
     MEDCOUPLING_EXPORT static MEDCouplingUMesh *New(const char *meshName, int meshDim);
+    MEDCOUPLING_EXPORT MEDCouplingMesh *deepCpy() const;
     MEDCOUPLING_EXPORT MEDCouplingUMesh *clone(bool recDeepCpy) const;
     MEDCOUPLING_EXPORT void updateTime();
     MEDCOUPLING_EXPORT MEDCouplingMeshType getType() const { return UNSTRUCTURED; }
     MEDCOUPLING_EXPORT bool isEqual(const MEDCouplingMesh *other, double prec) const;
+    MEDCOUPLING_EXPORT bool isEqualWithoutConsideringStr(const MEDCouplingMesh *other, double prec) const;
+    MEDCOUPLING_EXPORT void checkDeepEquivalWith(const MEDCouplingMesh *other, int cellCompPol, double prec,
+                                                 DataArrayInt *&cellCor, DataArrayInt *&nodeCor) const throw(INTERP_KERNEL::Exception);
+    MEDCOUPLING_EXPORT void checkDeepEquivalOnSameNodesWith(const MEDCouplingMesh *other, int cellCompPol, double prec,
+                                                            DataArrayInt *&cellCor) const throw(INTERP_KERNEL::Exception);
+    MEDCOUPLING_EXPORT void checkFastEquivalWith(const MEDCouplingMesh *other, double prec) const throw(INTERP_KERNEL::Exception);
     MEDCOUPLING_EXPORT void checkCoherency() const throw(INTERP_KERNEL::Exception);
     MEDCOUPLING_EXPORT void setMeshDimension(int meshDim);
     MEDCOUPLING_EXPORT void allocateCells(int nbOfCells);
@@ -47,31 +54,43 @@ namespace ParaMEDMEM
     MEDCOUPLING_EXPORT DataArrayInt *getNodalConnectivity() const { return _nodal_connec; }
     MEDCOUPLING_EXPORT DataArrayInt *getNodalConnectivityIndex() const { return _nodal_connec_index; }
     MEDCOUPLING_EXPORT INTERP_KERNEL::NormalizedCellType getTypeOfCell(int cellId) const;
+    MEDCOUPLING_EXPORT int getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType type) const;
     MEDCOUPLING_EXPORT void getNodeIdsOfCell(int cellId, std::vector<int>& conn) const;
     MEDCOUPLING_EXPORT void getCoordinatesOfNode(int nodeId, std::vector<double>& coo) const;
+    MEDCOUPLING_EXPORT std::string simpleRepr() const;
+    MEDCOUPLING_EXPORT std::string advancedRepr() const;
+    MEDCOUPLING_EXPORT std::string reprConnectivityOfThis() const;
     MEDCOUPLING_EXPORT int getNumberOfNodesInCell(int cellId) const;
     MEDCOUPLING_EXPORT int getNumberOfCells() const;
     MEDCOUPLING_EXPORT int getMeshDimension() const;
     MEDCOUPLING_EXPORT int getMeshLength() const;
+    MEDCOUPLING_EXPORT void computeTypes();
     //! size of returned tinyInfo must be always the same.
     MEDCOUPLING_EXPORT void getTinySerializationInformation(std::vector<int>& tinyInfo, std::vector<std::string>& littleStrings) const;
     MEDCOUPLING_EXPORT bool isEmptyMesh(const std::vector<int>& tinyInfo) const;
-    MEDCOUPLING_EXPORT void resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings);
+    MEDCOUPLING_EXPORT void resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings) const;
     MEDCOUPLING_EXPORT void serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const;
-    MEDCOUPLING_EXPORT void unserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, const std::vector<std::string>& littleStrings);
+    MEDCOUPLING_EXPORT void unserialization(const std::vector<int>& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2, const std::vector<std::string>& littleStrings);
     //tools
+    MEDCOUPLING_EXPORT bool areCellsEqual(int cell1, int cell2, int compType) const;
+    MEDCOUPLING_EXPORT bool areCellsEqual0(int cell1, int cell2) const;
+    MEDCOUPLING_EXPORT bool areCellsEqual1(int cell1, int cell2) const;
+    MEDCOUPLING_EXPORT bool areCellsEqual2(int cell1, int cell2) const;
+    MEDCOUPLING_EXPORT bool areCellsFrom2MeshEqual(const MEDCouplingUMesh *other, int cellId, double prec) const;
     MEDCOUPLING_EXPORT void convertToPolyTypes(const std::vector<int>& cellIdsToConvert);
     MEDCOUPLING_EXPORT DataArrayInt *zipCoordsTraducer();
+    MEDCOUPLING_EXPORT DataArrayInt *zipConnectivityTraducer(int compType);
     MEDCOUPLING_EXPORT void getReverseNodalConnectivity(DataArrayInt *revNodal, DataArrayInt *revNodalIndx) const;
     MEDCOUPLING_EXPORT MEDCouplingUMesh *buildDescendingConnectivity(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const;
-    MEDCOUPLING_EXPORT DataArrayInt *mergeNodes(double precision, bool& areNodesMerged);
+    MEDCOUPLING_EXPORT DataArrayInt *mergeNodes(double precision, bool& areNodesMerged, int& newNbOfNodes);
+    MEDCOUPLING_EXPORT void tryToShareSameCoordsPermute(const MEDCouplingPointSet& other, double epsilon) throw(INTERP_KERNEL::Exception);
     MEDCOUPLING_EXPORT MEDCouplingPointSet *buildPartOfMySelf(const int *start, const int *end, bool keepCoords) const;
     MEDCOUPLING_EXPORT MEDCouplingPointSet *buildPartOfMySelfNode(const int *start, const int *end, bool fullyIn) const;
     MEDCOUPLING_EXPORT MEDCouplingPointSet *buildFacePartOfMySelfNode(const int *start, const int *end, bool fullyIn) const;
     MEDCOUPLING_EXPORT void findBoundaryNodes(std::vector<int>& nodes) const;
     MEDCOUPLING_EXPORT MEDCouplingPointSet *buildBoundaryMesh(bool keepCoords) const;
     MEDCOUPLING_EXPORT void renumberNodes(const int *newNodeNumbers, int newNbOfNodes);
-    MEDCOUPLING_EXPORT void renumberCells(const int *old2NewBg, const int *old2NewEnd, bool check);
+    MEDCOUPLING_EXPORT void renumberCells(const int *old2NewBg, bool check) throw(INTERP_KERNEL::Exception);
     MEDCOUPLING_EXPORT void giveElemsInBoundingBox(const double *bbox, double eps, std::vector<int>& elems);
     MEDCOUPLING_EXPORT void giveElemsInBoundingBox(const INTERP_KERNEL::DirectedBoundingBox& bbox, double eps, std::vector<int>& elems);
     MEDCOUPLING_EXPORT MEDCouplingFieldDouble *getMeasureField(bool isAbs) const;
@@ -84,21 +103,50 @@ namespace ParaMEDMEM
     MEDCOUPLING_EXPORT void getCellsContainingPoints(const double *pos, int nbOfPoints, double eps, std::vector<int>& elts, std::vector<int>& eltsIndex) const;
     MEDCOUPLING_EXPORT void checkButterflyCells(std::vector<int>& cells) const;
     MEDCOUPLING_EXPORT void getBoundingBoxForBBTree(std::vector<double>& bbox) const;
+    MEDCOUPLING_EXPORT MEDCouplingUMesh *buildExtrudedMeshFromThis(const MEDCouplingUMesh *mesh1D, int policy);
+    MEDCOUPLING_EXPORT bool isFullyQuadratic() const;
+    MEDCOUPLING_EXPORT bool isPresenceOfQuadratic() const;
+    MEDCOUPLING_EXPORT void convertQuadraticCellsToLinear() throw(INTERP_KERNEL::Exception);
+    MEDCOUPLING_EXPORT void are2DCellsNotCorrectlyOriented(const double *vec, bool polyOnly, std::vector<int>& cells) const throw(INTERP_KERNEL::Exception);
+    MEDCOUPLING_EXPORT void orientCorrectly2DCells(const double *vec, bool polyOnly) throw(INTERP_KERNEL::Exception);
+    MEDCOUPLING_EXPORT void arePolyhedronsNotCorrectlyOriented(std::vector<int>& cells) const throw(INTERP_KERNEL::Exception);
+    MEDCOUPLING_EXPORT void orientCorrectlyPolyhedrons() throw(INTERP_KERNEL::Exception);
+    MEDCOUPLING_EXPORT void getFastMiddlePlaneOfThis(double *vec, double *pos) const throw(INTERP_KERNEL::Exception);
+    //utilities for MED File RW
     MEDCOUPLING_EXPORT bool checkConsecutiveCellTypes() const;
+    MEDCOUPLING_EXPORT bool checkConsecutiveCellTypesAndOrder(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const;
+    MEDCOUPLING_EXPORT DataArrayInt *getRenumArrForConsctvCellTypesSpe(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const;
+    MEDCOUPLING_EXPORT DataArrayInt *rearrange2ConsecutiveCellTypes();
+    MEDCOUPLING_EXPORT std::vector<MEDCouplingUMesh *> splitByType() const;
+    MEDCOUPLING_EXPORT DataArrayInt *convertCellArrayPerGeoType(const DataArrayInt *da) const throw(INTERP_KERNEL::Exception);
+    MEDCOUPLING_EXPORT MEDCouplingUMesh *keepSpecifiedCells(INTERP_KERNEL::NormalizedCellType type, const std::vector<int>& idsPerGeoType) const;
+    //
     MEDCOUPLING_EXPORT MEDCouplingMesh *mergeMyselfWith(const MEDCouplingMesh *other) const;
     MEDCOUPLING_EXPORT DataArrayDouble *getBarycenterAndOwner() const;
     MEDCOUPLING_EXPORT static MEDCouplingUMesh *mergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2);
+    MEDCOUPLING_EXPORT static MEDCouplingUMesh *mergeUMeshesOnSameCoords(const std::vector<MEDCouplingUMesh *>& meshes);
+    MEDCOUPLING_EXPORT static MEDCouplingUMesh *fuseUMeshesOnSameCoords(const std::vector<MEDCouplingUMesh *>& meshes, int compType, std::vector<DataArrayInt *>& corr);
+    MEDCOUPLING_EXPORT static bool isPolygonWellOriented(const double *vec, const int *begin, const int *end, const double *coords);
+    MEDCOUPLING_EXPORT static bool isPolyhedronWellOriented(const int *begin, const int *end, const double *coords);
+    MEDCOUPLING_EXPORT static void tryToCorrectPolyhedronOrientation(int *begin, int *end, const double *coords) throw(INTERP_KERNEL::Exception);
   private:
     MEDCouplingUMesh();
     MEDCouplingUMesh(const MEDCouplingUMesh& other, bool deepCpy);
     ~MEDCouplingUMesh();
-    void computeTypes();
     void checkFullyDefined() const throw(INTERP_KERNEL::Exception);
+    void reprConnectivityOfThisLL(std::ostringstream& stream) const;
     //tools
+    void renumberNodesInConn(const int *newNodeNumbers);
+    MEDCouplingUMesh *buildExtrudedMeshFromThisLowLev(int nbOfNodesOf1Lev, bool isQuad) const;
+    DataArrayDouble *fillExtCoordsUsingTranslation(const MEDCouplingUMesh *mesh1D, bool isQuad) const;
+    template<int SPACEDIM>
+    void findCommonCellsBase(int compType, std::vector<int>& res, std::vector<int>& resI) const;
+    bool areCellsEqualInPool(const std::vector<int>& candidates, int compType, std::vector<int>& result) const;
     MEDCouplingUMesh *buildPartOfMySelfKeepCoords(const int *start, const int *end) const;
     template<int SPACEDIM>
     void getCellsContainingPointsAlg(const double *coords, const double *pos, int nbOfPoints,
                                      double eps, std::vector<int>& elts, std::vector<int>& eltsIndex) const;
+    static void appendExtrudedCell(const int *connBg, const int *connEnd, int nbOfNodesPerLev, bool isQuad, std::vector<int>& ret);
   private:
     //! this iterator stores current position in _nodal_connec array.
     mutable int _iterator;
@@ -108,6 +156,8 @@ namespace ParaMEDMEM
     std::set<INTERP_KERNEL::NormalizedCellType> _types;
   private:
     static const char PART_OF_NAME[];
+  public:
+    static double EPS_FOR_POLYH_ORIENTATION;
   };
 }
 
index 29f1e58e3c1d8bb242fb31b9375b665b1f7a51fc..f45cd5eba7e3eedfde41065a0ba3e3dedc7d94c3 100644 (file)
@@ -55,6 +55,14 @@ MEDCouplingUMeshDesc *MEDCouplingUMeshDesc::New(const char *meshName, int meshDi
   return ret;
 }
 
+/*!
+ * not implemented
+ */
+MEDCouplingMesh *MEDCouplingUMeshDesc::deepCpy() const
+{
+  return 0;
+}
+
 void MEDCouplingUMeshDesc::checkCoherency() const throw(INTERP_KERNEL::Exception)
 {
   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
@@ -68,6 +76,18 @@ void MEDCouplingUMeshDesc::checkCoherency() const throw(INTERP_KERNEL::Exception
     }
 }
 
+void MEDCouplingUMeshDesc::checkDeepEquivalWith(const MEDCouplingMesh *other, int cellCompPol, double prec,
+                                                DataArrayInt *&cellCor, DataArrayInt *&nodeCor) const throw(INTERP_KERNEL::Exception)
+{
+  throw INTERP_KERNEL::Exception("MEDCouplingUMeshDesc::checkDeepEquivalWith : not implemented yet !");
+}
+
+void MEDCouplingUMeshDesc::checkDeepEquivalOnSameNodesWith(const MEDCouplingMesh *other, int cellCompPol, double prec,
+                                                           DataArrayInt *&cellCor) const throw(INTERP_KERNEL::Exception)
+{
+  throw INTERP_KERNEL::Exception("MEDCouplingUMeshDesc::checkDeepEquivalOnSameNodesWith : not implemented yet !");
+}
+
 void MEDCouplingUMeshDesc::setMeshDimension(unsigned meshDim)
 {
   _mesh_dim=meshDim;
@@ -107,6 +127,18 @@ INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshDesc::getTypeOfCell(int cellId
   return (INTERP_KERNEL::NormalizedCellType)desc_connec[desc_connec_index[cellId]+1];
 }
 
+int MEDCouplingUMeshDesc::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
+{
+  const int *desc_connec=_desc_connec->getConstPointer();
+  const int *desc_connec_index=_desc_connec_index->getConstPointer();
+  int nbOfCells=getNumberOfCells();
+  int ret=0;
+  for(int i=0;i<nbOfCells;i++)
+    if((INTERP_KERNEL::NormalizedCellType) desc_connec[desc_connec_index[i]]==type)
+      ret++;
+  return ret;
+}
+
 void MEDCouplingUMeshDesc::getNodeIdsOfCell(int cellId, std::vector<int>& conn) const
 {
   //not implemented yet.
@@ -117,6 +149,22 @@ void MEDCouplingUMeshDesc::getCoordinatesOfNode(int nodeId, std::vector<double>&
   //not implemented yet.
 }
 
+std::string MEDCouplingUMeshDesc::simpleRepr() const
+{
+  std::string ret("Unstructured mesh with descending connectivity : ");
+  ret+=getName();
+  ret+="\n";
+  return ret;
+}
+
+std::string MEDCouplingUMeshDesc::advancedRepr() const
+{
+  std::string ret("Unstructured mesh with descending connectivity : ");
+  ret+=getName();
+  ret+="\n";
+  return ret;
+}
+
 void MEDCouplingUMeshDesc::setConnectivity(DataArrayInt *descConn, DataArrayInt *descConnIndex, DataArrayInt *nodalFaceConn, DataArrayInt *nodalFaceConnIndx)
 {
   DataArrayInt::setArrayIn(descConn,_desc_connec);
@@ -283,13 +331,18 @@ void MEDCouplingUMeshDesc::giveElemsInBoundingBox(const INTERP_KERNEL::DirectedB
   delete [] elem_bb;
 }
 
-DataArrayInt *MEDCouplingUMeshDesc::mergeNodes(double precision, bool& areNodesMerged)
+DataArrayInt *MEDCouplingUMeshDesc::mergeNodes(double precision, bool& areNodesMerged, int& newNbOfNodes)
 {
   //not implemented yet.
   areNodesMerged=false;
   return 0;
 }
 
+void MEDCouplingUMeshDesc::tryToShareSameCoordsPermute(const MEDCouplingPointSet& other, double epsilon) throw(INTERP_KERNEL::Exception)
+{
+  throw INTERP_KERNEL::Exception("Not implemented yet !");
+}
+
 MEDCouplingPointSet *MEDCouplingUMeshDesc::buildPartOfMySelf(const int *start, const int *end, bool keepCoords) const
 {
   //not implemented yet.
@@ -319,6 +372,11 @@ MEDCouplingPointSet *MEDCouplingUMeshDesc::buildBoundaryMesh(bool keepCoords) co
   return 0;
 }
 
+void MEDCouplingUMeshDesc::renumberCells(const int *old2NewBg, bool check) throw(INTERP_KERNEL::Exception)
+{
+  throw INTERP_KERNEL::Exception("Available for UMesh desc but not implemented yet !");
+}
+
 void MEDCouplingUMeshDesc::renumberNodes(const int *newNodeNumbers, int newNbOfNodes)
 {
   MEDCouplingPointSet::renumberNodes(newNodeNumbers,newNbOfNodes);
index 91ce649ed75a0f4fd76dc675a5c25a7726136e82..7c965a31c6335a24909caff07e4b002f21257b48 100644 (file)
@@ -33,7 +33,12 @@ namespace ParaMEDMEM
   public:
     MEDCOUPLING_EXPORT static MEDCouplingUMeshDesc *New();
     MEDCOUPLING_EXPORT static MEDCouplingUMeshDesc *New(const char *meshName, int meshDim);
+    MEDCOUPLING_EXPORT MEDCouplingMesh *deepCpy() const;
     MEDCOUPLING_EXPORT void checkCoherency() const throw(INTERP_KERNEL::Exception);
+    MEDCOUPLING_EXPORT void checkDeepEquivalWith(const MEDCouplingMesh *other, int cellCompPol, double prec,
+                                                 DataArrayInt *&cellCor, DataArrayInt *&nodeCor) const throw(INTERP_KERNEL::Exception);
+    MEDCOUPLING_EXPORT void checkDeepEquivalOnSameNodesWith(const MEDCouplingMesh *other, int cellCompPol, double prec,
+                                                            DataArrayInt *&cellCor) const throw(INTERP_KERNEL::Exception);
     MEDCOUPLING_EXPORT void setMeshDimension(unsigned meshDim);
     MEDCOUPLING_EXPORT int getNumberOfCells() const;
     MEDCOUPLING_EXPORT int getNumberOfFaces() const;
@@ -41,8 +46,11 @@ namespace ParaMEDMEM
     MEDCOUPLING_EXPORT int getFaceMeshLength() const;
     MEDCOUPLING_EXPORT int getMeshDimension() const { return _mesh_dim; }
     MEDCOUPLING_EXPORT INTERP_KERNEL::NormalizedCellType getTypeOfCell(int cellId) const;
+    MEDCOUPLING_EXPORT int getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType type) const;
     MEDCOUPLING_EXPORT void getNodeIdsOfCell(int cellId, std::vector<int>& conn) const;
     MEDCOUPLING_EXPORT void getCoordinatesOfNode(int nodeId, std::vector<double>& coo) const;
+    MEDCOUPLING_EXPORT std::string simpleRepr() const;
+    MEDCOUPLING_EXPORT std::string advancedRepr() const;
     MEDCOUPLING_EXPORT MEDCouplingMeshType getType() const { return UNSTRUCTURED_DESC; }
     MEDCOUPLING_EXPORT void setConnectivity(DataArrayInt *descConn, DataArrayInt *descConnIndex, DataArrayInt *nodalFaceConn, DataArrayInt *nodalFaceConnIndx);
     //tools to overload
@@ -53,12 +61,14 @@ namespace ParaMEDMEM
     MEDCOUPLING_EXPORT void unserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, const std::vector<std::string>& littleStrings);
     MEDCOUPLING_EXPORT void giveElemsInBoundingBox(const double *bbox, double eps, std::vector<int>& elems);
     MEDCOUPLING_EXPORT void giveElemsInBoundingBox(const INTERP_KERNEL::DirectedBoundingBox &bbox, double eps, std::vector<int>& elems);
-    MEDCOUPLING_EXPORT DataArrayInt *mergeNodes(double precision, bool& areNodesMerged);
+    MEDCOUPLING_EXPORT DataArrayInt *mergeNodes(double precision, bool& areNodesMerged, int& newNbOfNodes);
+    MEDCOUPLING_EXPORT void tryToShareSameCoordsPermute(const MEDCouplingPointSet& other, double epsilon) throw(INTERP_KERNEL::Exception);
     MEDCOUPLING_EXPORT MEDCouplingPointSet *buildPartOfMySelf(const int *start, const int *end, bool keepCoords) const;
     MEDCOUPLING_EXPORT MEDCouplingPointSet *buildPartOfMySelfNode(const int *start, const int *end, bool fullyIn) const;
     MEDCOUPLING_EXPORT MEDCouplingPointSet *buildFacePartOfMySelfNode(const int *start, const int *end, bool fullyIn) const;
     MEDCOUPLING_EXPORT void findBoundaryNodes(std::vector<int>& nodes) const;
     MEDCOUPLING_EXPORT MEDCouplingPointSet *buildBoundaryMesh(bool keepCoords) const;
+    MEDCOUPLING_EXPORT void renumberCells(const int *old2NewBg, bool check) throw(INTERP_KERNEL::Exception);
     MEDCOUPLING_EXPORT void renumberNodes(const int *newNodeNumbers, int newNbOfNodes);
     MEDCOUPLING_EXPORT MEDCouplingFieldDouble *getMeasureField(bool isAbs) const;
     MEDCOUPLING_EXPORT MEDCouplingFieldDouble *getMeasureFieldOnNode(bool isAbs) const;
index 20117023a8115898bf359d9aac9087e480821bf6..28553f2880da23db04fac15f2cc94e472cc04424 100644 (file)
@@ -36,17 +36,19 @@ MEDCouplingCMesh.hxx MEDCouplingTimeDiscretization.hxx
 MEDCouplingFieldDiscretization.hxx MEDCouplingPointSet.hxx MEDCouplingPointSet.txx                \
 MEDCouplingUMeshDesc.hxx MEDCouplingNatureOfField.hxx                                             \
 MEDCouplingNormalizedCartesianMesh.hxx MEDCouplingNormalizedCartesianMesh.txx                     \
-MEDCouplingRemapper.hxx MEDCouplingExtrudedMesh.hxx
+MEDCouplingRemapper.hxx MEDCouplingExtrudedMesh.hxx MEDCouplingGaussLocalization.hxx              \
+MEDCouplingAutoRefCountObjectPtr.hxx
 
 # Libraries targets
 
 dist_libmedcoupling_la_SOURCES = \
-       MEDCouplingField.cxx  MEDCouplingFieldDouble.cxx                          \
-       MEDCouplingUMesh.cxx  MEDCouplingMemArray.cxx  MEDCouplingTimeLabel.cxx   \
-       MEDCouplingCMesh.cxx MEDCouplingTimeDiscretization.cxx                    \
-       MEDCouplingFieldDiscretization.cxx MEDCouplingRefCountObject.cxx          \
-       MEDCouplingPointSet.cxx MEDCouplingUMeshDesc.cxx                          \
-       MEDCouplingExtrudedMesh.cxx MEDCouplingMesh.cxx
+       MEDCouplingField.cxx  MEDCouplingFieldDouble.cxx                                    \
+       MEDCouplingUMesh.cxx  MEDCouplingMemArray.cxx  MEDCouplingTimeLabel.cxx             \
+       MEDCouplingCMesh.cxx MEDCouplingTimeDiscretization.cxx                              \
+       MEDCouplingFieldDiscretization.cxx MEDCouplingRefCountObject.cxx                    \
+       MEDCouplingPointSet.cxx MEDCouplingUMeshDesc.cxx                                    \
+       MEDCouplingExtrudedMesh.cxx MEDCouplingMesh.cxx MEDCouplingGaussLocalization.cxx    \
+       MEDCouplingNatureOfField.cxx
 
 libmedcoupling_la_LDFLAGS= 
 
@@ -70,9 +72,6 @@ libmedcouplingremapper_la_LIBADD = libmedcoupling.la
 
 AM_CPPFLAGS += $(libinterpkernel_la_CPPFLAGS)
 LDADD= $(libinterpkernel_la_LDFLAGS)
-if MED_ENABLE_KERNEL
-     LDADD+=-lSALOMEBasics
-endif
 
 EXTRA_DIST += \
        MEDCouplingFieldDouble.hxx                \
@@ -92,4 +91,6 @@ EXTRA_DIST += \
        MEDCouplingPointSet.txx                   \
        MEDCouplingUMeshDesc.hxx                  \
        MEDCouplingNatureOfField.hxx              \
-       MEDCouplingRemapper.hxx
+       MEDCouplingRemapper.hxx                   \
+       MEDCouplingExtrudedMesh.hxx               \
+       MEDCouplingGaussLocalization.hxx 
index 87393c8f962c2a060db2b4cbe2d22375ea0d8dd8..9bbdb8519fde4e6c1bcd0f8ed2c69bc0aae21cf5 100644 (file)
@@ -32,7 +32,10 @@ namespace ParaMEDMEM
   class MEDCouplingBasicsTest : public CppUnit::TestFixture
   {
     CPPUNIT_TEST_SUITE(MEDCouplingBasicsTest);
+    //MEDCouplingBasicsTest1.cxx
     CPPUNIT_TEST( testArray );
+    CPPUNIT_TEST( testArray2 );
+    CPPUNIT_TEST( testArray3 );
     CPPUNIT_TEST( testMesh );
     CPPUNIT_TEST( testMeshPointsCloud );
     CPPUNIT_TEST( testMeshM1D );
@@ -46,15 +49,19 @@ namespace ParaMEDMEM
     CPPUNIT_TEST( testBuildPartOfMySelf );
     CPPUNIT_TEST( testBuildPartOfMySelfNode );
     CPPUNIT_TEST( testZipCoords );
+    CPPUNIT_TEST( testZipConnectivity );
     CPPUNIT_TEST( testEqualMesh );
     CPPUNIT_TEST( testEqualFieldDouble );
     CPPUNIT_TEST( testNatureChecking );
     CPPUNIT_TEST( testBuildSubMeshData );
     CPPUNIT_TEST( testExtrudedMesh1 );
     CPPUNIT_TEST( testExtrudedMesh2 );
+    CPPUNIT_TEST( testExtrudedMesh3 );
+    CPPUNIT_TEST( testExtrudedMesh4 );
     CPPUNIT_TEST( testFindCommonNodes );
     CPPUNIT_TEST( testCheckButterflyCells );
     CPPUNIT_TEST( testMergeMesh1 );
+    CPPUNIT_TEST( testMergeMeshOnSameCoords1 );
     CPPUNIT_TEST( testMergeField1 );
     CPPUNIT_TEST( testFillFromAnalytic );
     CPPUNIT_TEST( testFillFromAnalytic2 );
@@ -63,8 +70,13 @@ namespace ParaMEDMEM
     CPPUNIT_TEST( testOperationsOnFields );
     CPPUNIT_TEST( testOperationsOnFields2 );
     CPPUNIT_TEST( testOperationsOnFields3 );
+    CPPUNIT_TEST( testOperationsOnFields4 );
     CPPUNIT_TEST( testMergeNodesOnField );
     CPPUNIT_TEST( testCheckConsecutiveCellTypes );
+    CPPUNIT_TEST( testRearrange2ConsecutiveCellTypes );
+    CPPUNIT_TEST( testSplitByType );
+    CPPUNIT_TEST( testFuseUMeshesOnSameCoords );
+    CPPUNIT_TEST( testFuseUMeshesOnSameCoords2 );
     CPPUNIT_TEST( testBuildOrthogonalField );
     CPPUNIT_TEST( testGetCellsContainingPoint );
     CPPUNIT_TEST( testGetValueOn1 );
@@ -74,6 +86,45 @@ namespace ParaMEDMEM
     CPPUNIT_TEST( testFindNodeOnPlane );
     CPPUNIT_TEST( testRenumberCells );
     CPPUNIT_TEST( testChangeSpaceDimension );
+    //MEDCouplingBasicsTest2.cxx
+    CPPUNIT_TEST( testGaussPointField1 );
+    CPPUNIT_TEST( testGaussPointNEField1 );
+    CPPUNIT_TEST( testCellOrientation1 );
+    CPPUNIT_TEST( testCellOrientation2 );
+    CPPUNIT_TEST( testPolyhedronBarycenter );
+    CPPUNIT_TEST( testNormL12Integ1D );
+    CPPUNIT_TEST( testAreaBary2D );
+    CPPUNIT_TEST( testAreaBary3D );
+    CPPUNIT_TEST( testRenumberCellsForFields );
+    CPPUNIT_TEST( testRenumberNodesForFields );
+    CPPUNIT_TEST( testConvertQuadraticCellsToLinear );
+    CPPUNIT_TEST( testCheckGeoEquivalWith );
+    CPPUNIT_TEST( testCheckGeoEquivalWith2 );
+    CPPUNIT_TEST( testCopyTinyStringsFromOnFields );
+    CPPUNIT_TEST( testTryToShareSameCoordsPermute );
+    CPPUNIT_TEST( testTryToShareSameCoordsPermute2 );
+    CPPUNIT_TEST( testChangeUnderlyingMesh1 );
+    CPPUNIT_TEST( testGetMaxValue1 );
+    CPPUNIT_TEST( testSubstractInPlaceDM1 );
+    CPPUNIT_TEST( testDotCrossProduct1 );
+    CPPUNIT_TEST( testMinMaxFields1 );
+    CPPUNIT_TEST( testApplyLin1 );
+    CPPUNIT_TEST( testGetIdsInRange1 );
+    CPPUNIT_TEST( testBuildSubPart1 );
+    CPPUNIT_TEST( testDoublyContractedProduct1 );
+    CPPUNIT_TEST( testDeterminant1 );
+    CPPUNIT_TEST( testEigenValues1 );
+    CPPUNIT_TEST( testEigenVectors1 );
+    CPPUNIT_TEST( testInverse1 );
+    CPPUNIT_TEST( testTrace1 );
+    CPPUNIT_TEST( testDeviator1 );
+    CPPUNIT_TEST( testMagnitude1 );
+    CPPUNIT_TEST( testMaxPerTuple1 );
+    CPPUNIT_TEST( testChangeNbOfComponents );
+    CPPUNIT_TEST( testSortPerTuple1 );
+    CPPUNIT_TEST( testIsEqualWithoutConsideringStr1 );
+    CPPUNIT_TEST( testGetNodeIdsOfCell1 );
+    //MEDCouplingBasicsTestInterp.cxx
     CPPUNIT_TEST( test2DInterpP0P0_1 );
     CPPUNIT_TEST( test2DInterpP0P0PL_1 );
     CPPUNIT_TEST( test2DInterpP0P0PL_2 );
@@ -131,10 +182,12 @@ namespace ParaMEDMEM
     CPPUNIT_TEST( test2DCurveInterpP0P1_1 );
     CPPUNIT_TEST( test2DCurveInterpP1P0_1 );
     CPPUNIT_TEST( test2DCurveInterpP1P1_1 );
-
     CPPUNIT_TEST_SUITE_END();
   public:
+    //MEDCouplingBasicsTest1.cxx
     void testArray();
+    void testArray2();
+    void testArray3();
     void testMesh();
     void testMeshPointsCloud();
     void testMeshM1D();
@@ -148,15 +201,19 @@ namespace ParaMEDMEM
     void testBuildPartOfMySelf();
     void testBuildPartOfMySelfNode();
     void testZipCoords();
+    void testZipConnectivity();
     void testEqualMesh();
     void testEqualFieldDouble();
     void testNatureChecking();
     void testBuildSubMeshData();
     void testExtrudedMesh1();
     void testExtrudedMesh2();
+    void testExtrudedMesh3();
+    void testExtrudedMesh4();
     void testFindCommonNodes();
     void testCheckButterflyCells();
     void testMergeMesh1();
+    void testMergeMeshOnSameCoords1();
     void testMergeField1();
     void testFillFromAnalytic();
     void testFillFromAnalytic2();
@@ -165,8 +222,13 @@ namespace ParaMEDMEM
     void testOperationsOnFields();
     void testOperationsOnFields2();
     void testOperationsOnFields3();
+    void testOperationsOnFields4();
     void testMergeNodesOnField();
     void testCheckConsecutiveCellTypes();
+    void testRearrange2ConsecutiveCellTypes();
+    void testSplitByType();
+    void testFuseUMeshesOnSameCoords();
+    void testFuseUMeshesOnSameCoords2();
     void testBuildOrthogonalField();
     void testGetCellsContainingPoint();
     void testGetValueOn1();
@@ -176,6 +238,45 @@ namespace ParaMEDMEM
     void testFindNodeOnPlane();
     void testRenumberCells();
     void testChangeSpaceDimension();
+    //MEDCouplingBasicsTest2.cxx
+    void testGaussPointField1();
+    void testGaussPointNEField1();
+    void testCellOrientation1();
+    void testCellOrientation2();
+    void testPolyhedronBarycenter();
+    void testNormL12Integ1D();
+    void testAreaBary2D();
+    void testAreaBary3D();
+    void testRenumberCellsForFields();
+    void testRenumberNodesForFields();
+    void testConvertQuadraticCellsToLinear();
+    void testCheckGeoEquivalWith();
+    void testCheckGeoEquivalWith2();
+    void testCopyTinyStringsFromOnFields();
+    void testTryToShareSameCoordsPermute();
+    void testTryToShareSameCoordsPermute2();
+    void testChangeUnderlyingMesh1();
+    void testGetMaxValue1();
+    void testSubstractInPlaceDM1();
+    void testDotCrossProduct1();
+    void testMinMaxFields1();
+    void testApplyLin1();
+    void testGetIdsInRange1();
+    void testBuildSubPart1();
+    void testDoublyContractedProduct1();
+    void testDeterminant1();
+    void testEigenValues1();
+    void testEigenVectors1();
+    void testInverse1();
+    void testTrace1();
+    void testDeviator1();
+    void testMagnitude1();
+    void testMaxPerTuple1();
+    void testChangeNbOfComponents();
+    void testSortPerTuple1();
+    void testIsEqualWithoutConsideringStr1();
+    void testGetNodeIdsOfCell1();
+    //MEDCouplingBasicsTestInterp.cxx
     void test2DInterpP0P0_1();
     void test2DInterpP0P0PL_1();
     void test2DInterpP0P0PL_2();
@@ -259,6 +360,15 @@ namespace ParaMEDMEM
     static MEDCouplingUMesh *build2DTargetMeshMerged_1();
     static MEDCouplingUMesh *build2DCurveMesh(double dx, double dy);
     static MEDCouplingUMesh *build1DMesh(double dx);
+    static MEDCouplingUMesh *build1DSourceMesh_2();
+    static MEDCouplingUMesh *build1DTargetMesh_2();
+    static MEDCouplingUMesh *build2DCurveSourceMesh_2();
+    static MEDCouplingUMesh *build2DCurveTargetMesh_2();
+    static MEDCouplingUMesh *build1DTargetMesh_3();
+    static MEDCouplingUMesh *build2DCurveTargetMesh_3();
+    static MEDCouplingUMesh *build2DTargetMesh_3();
+    static MEDCouplingUMesh *build3DTargetMesh_3();
+    static MEDCouplingUMesh *build2DTargetMesh_4();
     static double sumAll(const std::vector< std::map<int,double> >& matrix);
   };
 }
index 959a8c2c32c5a889adfe4be781e484d5761454e3..3f7adf58ad5bc03c762eda70eac166b985ecd641 100644 (file)
@@ -678,6 +678,170 @@ MEDCouplingUMesh *MEDCouplingBasicsTest::build1DMesh(double dx)
   return targetMesh;
 }
 
+MEDCouplingUMesh *MEDCouplingBasicsTest::build1DSourceMesh_2()
+{
+  MEDCouplingUMesh *ret=MEDCouplingUMesh::New("1DSourceMesh",1);
+  ret->allocateCells(4);
+  int conn[8]={0,1,2,3,1,2,3,4};
+  for(int i=0;i<4;i++)
+    ret->insertNextCell(INTERP_KERNEL::NORM_SEG2,2,conn+2*i);
+  ret->finishInsertingCells();
+  double coords[5]={0.3,0.7,0.9,1.0,1.12};
+  DataArrayDouble *myCoords=DataArrayDouble::New();
+  myCoords->alloc(5,1);
+  std::copy(coords,coords+5,myCoords->getPointer());
+  ret->setCoords(myCoords);
+  myCoords->decrRef();
+  return ret;
+}
+
+MEDCouplingUMesh *MEDCouplingBasicsTest::build1DTargetMesh_2()
+{
+  MEDCouplingUMesh *ret=MEDCouplingUMesh::New("1DTargetMesh",1);
+  ret->allocateCells(2);
+  int conn[4]={1,2,0,1};
+  for(int i=0;i<2;i++)
+    ret->insertNextCell(INTERP_KERNEL::NORM_SEG2,2,conn+2*i);
+  ret->finishInsertingCells();
+  double coords[3]={0.5,0.75,1.2};
+  DataArrayDouble *myCoords=DataArrayDouble::New();
+  myCoords->alloc(3,1);
+  std::copy(coords,coords+3,myCoords->getPointer());
+  ret->setCoords(myCoords);
+  myCoords->decrRef();
+  return ret;
+}
+
+MEDCouplingUMesh *MEDCouplingBasicsTest::build2DCurveSourceMesh_2()
+{
+  MEDCouplingUMesh *ret=MEDCouplingUMesh::New("1DSourceMesh",1);
+  ret->allocateCells(4);
+  int conn[8]={0,1,2,3,1,2,3,4};
+  for(int i=0;i<4;i++)
+    ret->insertNextCell(INTERP_KERNEL::NORM_SEG2,2,conn+2*i);
+  ret->finishInsertingCells();
+  double coords[10]={0.3,0.3,0.7,0.7,0.9,0.9,1.0,1.0,1.12,1.12};
+  DataArrayDouble *myCoords=DataArrayDouble::New();
+  myCoords->alloc(5,2);
+  std::copy(coords,coords+10,myCoords->getPointer());
+  ret->setCoords(myCoords);
+  myCoords->decrRef();
+  return ret;
+}
+
+MEDCouplingUMesh *MEDCouplingBasicsTest::build2DCurveTargetMesh_2()
+{
+  MEDCouplingUMesh *ret=MEDCouplingUMesh::New("1DTargetMesh",1);
+  ret->allocateCells(2);
+  int conn[4]={1,2,0,1};
+  for(int i=0;i<2;i++)
+    ret->insertNextCell(INTERP_KERNEL::NORM_SEG2,2,conn+2*i);
+  ret->finishInsertingCells();
+  double coords[6]={0.5,0.5,0.75,0.75,1.2,1.2};
+  DataArrayDouble *myCoords=DataArrayDouble::New();
+  myCoords->alloc(3,2);
+  std::copy(coords,coords+6,myCoords->getPointer());
+  ret->setCoords(myCoords);
+  myCoords->decrRef();
+  return ret;
+}
+
+MEDCouplingUMesh *MEDCouplingBasicsTest::build1DTargetMesh_3()
+{
+  MEDCouplingUMesh *ret=MEDCouplingUMesh::New("1DMesh_3",1);
+  ret->allocateCells(4);
+  int conn[10]={0,1,2, 3,4, 6,5,7 ,9,8};
+  ret->insertNextCell(INTERP_KERNEL::NORM_SEG3,3,conn);
+  ret->insertNextCell(INTERP_KERNEL::NORM_SEG2,2,conn+3);
+  ret->insertNextCell(INTERP_KERNEL::NORM_SEG3,3,conn+5);
+  ret->insertNextCell(INTERP_KERNEL::NORM_SEG2,2,conn+8);
+  ret->finishInsertingCells();
+  double coords[10]={0.5,1.,0.8,5.,5.21,0.5,1.1,0.7,5.,5.31};
+  DataArrayDouble *myCoords=DataArrayDouble::New();
+  myCoords->alloc(10,1);
+  std::copy(coords,coords+10,myCoords->getPointer());
+  ret->setCoords(myCoords);
+  myCoords->decrRef();
+  return ret;
+}
+
+MEDCouplingUMesh *MEDCouplingBasicsTest::build2DCurveTargetMesh_3()
+{
+  MEDCouplingUMesh *ret=MEDCouplingUMesh::New("2DCurveMesh_3",1);
+  ret->allocateCells(4);
+  int conn[10]={0,1,2, 3,4, 6,5,7 ,9,8};
+  ret->insertNextCell(INTERP_KERNEL::NORM_SEG3,3,conn);
+  ret->insertNextCell(INTERP_KERNEL::NORM_SEG2,2,conn+3);
+  ret->insertNextCell(INTERP_KERNEL::NORM_SEG3,3,conn+5);
+  ret->insertNextCell(INTERP_KERNEL::NORM_SEG2,2,conn+8);
+  ret->finishInsertingCells();
+  double coords[20]={0.5,0.5,1.,1.,0.8,0.8,5.,5.,5.21,5.21,0.5,0.5,1.1,1.1,0.7,0.7,5.,5.,5.31,5.31};
+  DataArrayDouble *myCoords=DataArrayDouble::New();
+  myCoords->alloc(10,2);
+  std::copy(coords,coords+20,myCoords->getPointer());
+  ret->setCoords(myCoords);
+  myCoords->decrRef();
+  return ret;
+}
+
+MEDCouplingUMesh *MEDCouplingBasicsTest::build2DTargetMesh_3()
+{
+  MEDCouplingUMesh *ret=MEDCouplingUMesh::New("2DMesh_3",2);
+  ret->allocateCells(10);
+  int conn[52]={
+    0,1,2, 0,1,3,4, 0,1,3,5,4, 0,1,2,6,7,8, 0,1,3,4,6,9,2,10,
+    0,2,1, 0,4,3,1, 0,4,5,3,1, 0,2,1,8,7,6, 0,4,3,1,10,2,9,6
+  };
+  ret->insertNextCell(INTERP_KERNEL::NORM_TRI3,3,conn);
+  ret->insertNextCell(INTERP_KERNEL::NORM_QUAD4,4,conn+3);
+  ret->insertNextCell(INTERP_KERNEL::NORM_POLYGON,5,conn+7);
+  ret->insertNextCell(INTERP_KERNEL::NORM_TRI6,6,conn+12);
+  ret->insertNextCell(INTERP_KERNEL::NORM_QUAD8,8,conn+18);
+  ret->insertNextCell(INTERP_KERNEL::NORM_TRI3,3,conn+26);
+  ret->insertNextCell(INTERP_KERNEL::NORM_QUAD4,4,conn+29);
+  ret->insertNextCell(INTERP_KERNEL::NORM_POLYGON,5,conn+33);
+  ret->insertNextCell(INTERP_KERNEL::NORM_TRI6,6,conn+38);
+  ret->insertNextCell(INTERP_KERNEL::NORM_QUAD8,8,conn+44);
+  ret->finishInsertingCells();
+  double coords[22]={0.,0.,1.,0.,0.5,1.,1.,1.,0.,1.,0.5,2.,0.5,0.,0.75,0.5,0.25,0.5,1.,0.5,0.,0.5};
+  DataArrayDouble *myCoords=DataArrayDouble::New();
+  myCoords->alloc(11,2);
+  std::copy(coords,coords+22,myCoords->getPointer());
+  ret->setCoords(myCoords);
+  myCoords->decrRef();
+  ret->checkCoherency();
+  return ret;
+}
+
+/*!
+ * Same as build2DTargetMesh_1 but with more nodes than needed. To check tryToShareSameCoordsPermute method.
+ */
+MEDCouplingUMesh *MEDCouplingBasicsTest::build2DTargetMesh_4()
+{
+  double targetCoords[20]={-0.3,-0.3, 0.2,-0.3, 0.7,-0.3, 0.7,-0.3, -0.3,0.2, 0.2,0.2, 0.7,0.2, -0.3,0.7, 0.2,0.7, 0.7,0.7 };
+  int targetConn[18]={0,4,5,1, 1,5,3, 5,6,2, 7,8,5,4, 8,9,6,5};
+  MEDCouplingUMesh *targetMesh=MEDCouplingUMesh::New();
+  targetMesh->setMeshDimension(2);
+  targetMesh->allocateCells(5);
+  targetMesh->insertNextCell(INTERP_KERNEL::NORM_QUAD4,4,targetConn);
+  targetMesh->insertNextCell(INTERP_KERNEL::NORM_TRI3,3,targetConn+4);
+  targetMesh->insertNextCell(INTERP_KERNEL::NORM_TRI3,3,targetConn+7);
+  targetMesh->insertNextCell(INTERP_KERNEL::NORM_QUAD4,4,targetConn+10);
+  targetMesh->insertNextCell(INTERP_KERNEL::NORM_QUAD4,4,targetConn+14);
+  targetMesh->finishInsertingCells();
+  DataArrayDouble *myCoords=DataArrayDouble::New();
+  myCoords->alloc(10,2);
+  std::copy(targetCoords,targetCoords+20,myCoords->getPointer());
+  targetMesh->setCoords(myCoords);
+  myCoords->decrRef();
+  return targetMesh;
+}
+
+MEDCouplingUMesh *MEDCouplingBasicsTest::build3DTargetMesh_3()
+{
+  return 0;
+}
+
 double MEDCouplingBasicsTest::sumAll(const std::vector< std::map<int,double> >& matrix)
 {
   double ret=0.;
index dbd2a6ff95ed8e23d3e36e60de0eef70a6013c52..fb96af12d22379071605152d258ed60f2140124b 100644 (file)
@@ -59,6 +59,68 @@ void MEDCouplingBasicsTest::testArray()
   }
 }
 
+void MEDCouplingBasicsTest::testArray2()
+{
+  DataArrayDouble *arr=DataArrayDouble::New();
+  arr->alloc(3,4);
+  double *tmp=arr->getPointer();
+  const double arrRef[12]={12.,11.,10.,9.,8.,7.,6.,5.,4.,3.,2.,1.};
+  std::copy(arrRef,arrRef+12,tmp);
+  arr->setInfoOnComponent(0,"ggg");
+  arr->setInfoOnComponent(1,"hhhh");
+  arr->setInfoOnComponent(2,"jj");
+  arr->setInfoOnComponent(3,"kkkkkk");
+  DataArrayInt *arr2=arr->convertToIntArr();
+  DataArrayDouble *arr3=arr2->convertToDblArr();
+  arr2->decrRef();
+  CPPUNIT_ASSERT(arr->isEqual(*arr3,1e-14));
+  arr3->decrRef();
+  arr->decrRef();
+}
+
+void MEDCouplingBasicsTest::testArray3()
+{
+  DataArrayInt *arr1=DataArrayInt::New();
+  arr1->alloc(7,2);
+  int *tmp=arr1->getPointer();
+  const int arr1Ref[14]={0,10,1,11,2,12,3,13,4,14,5,15,6,16};
+  std::copy(arr1Ref,arr1Ref+14,tmp);
+  CPPUNIT_ASSERT_EQUAL(7,arr1->getNumberOfTuples());
+  CPPUNIT_ASSERT_EQUAL(2,arr1->getNumberOfComponents());
+  CPPUNIT_ASSERT(std::equal(arr1Ref,arr1Ref+14,arr1->getConstPointer()));
+  DataArrayInt *arr2=arr1->substr(3);
+  CPPUNIT_ASSERT_EQUAL(4,arr2->getNumberOfTuples());
+  CPPUNIT_ASSERT_EQUAL(2,arr2->getNumberOfComponents());
+  CPPUNIT_ASSERT(std::equal(arr1Ref+6,arr1Ref+14,arr2->getConstPointer()));
+  arr2->decrRef();
+  DataArrayInt *arr3=arr1->substr(2,5);
+  CPPUNIT_ASSERT_EQUAL(3,arr3->getNumberOfTuples());
+  CPPUNIT_ASSERT_EQUAL(2,arr3->getNumberOfComponents());
+  CPPUNIT_ASSERT(std::equal(arr1Ref+4,arr1Ref+10,arr3->getConstPointer()));
+  arr1->decrRef();
+  arr3->decrRef();
+  //
+  DataArrayDouble *arr4=DataArrayDouble::New();
+  arr4->alloc(7,2);
+  double *tmp2=arr4->getPointer();
+  const int arr4Ref[14]={0.8,10.8,1.9,11.9,2.1,12.1,3.2,13.2,4.3,14.3,5.4,15.4,6.5,16.5};
+  std::copy(arr4Ref,arr4Ref+14,tmp2);
+  CPPUNIT_ASSERT_EQUAL(7,arr4->getNumberOfTuples());
+  CPPUNIT_ASSERT_EQUAL(2,arr4->getNumberOfComponents());
+  CPPUNIT_ASSERT(std::equal(arr4Ref,arr4Ref+14,arr4->getConstPointer()));
+  DataArrayDouble *arr5=arr4->substr(3);
+  CPPUNIT_ASSERT_EQUAL(4,arr5->getNumberOfTuples());
+  CPPUNIT_ASSERT_EQUAL(2,arr5->getNumberOfComponents());
+  CPPUNIT_ASSERT(std::equal(arr4Ref+6,arr4Ref+14,arr5->getConstPointer()));
+  arr5->decrRef();
+  DataArrayDouble *arr6=arr4->substr(2,5);
+  CPPUNIT_ASSERT_EQUAL(3,arr6->getNumberOfTuples());
+  CPPUNIT_ASSERT_EQUAL(2,arr6->getNumberOfComponents());
+  CPPUNIT_ASSERT(std::equal(arr4Ref+4,arr4Ref+10,arr6->getConstPointer()));
+  arr4->decrRef();
+  arr6->decrRef();
+}
+
 void MEDCouplingBasicsTest::testMesh()
 {
   const int nbOfCells=6;
@@ -542,7 +604,12 @@ void MEDCouplingBasicsTest::testBuildPartOfMySelf()
   CPPUNIT_ASSERT_EQUAL(4,subMesh->getNodalConnectivityIndex()->getNbOfElems());
   CPPUNIT_ASSERT(std::equal(subConn2,subConn2+14,subMesh->getNodalConnectivity()->getPointer()));
   CPPUNIT_ASSERT(std::equal(subConnIndex2,subConnIndex2+4,subMesh->getNodalConnectivityIndex()->getPointer()));
+  const int tab3[3]={0,1,2};
+  MEDCouplingPointSet *subMeshSimple2=subMeshSimple->buildPartOfMySelf(tab3,tab3+3,true);
   subMesh->decrRef();
+  name=subMeshSimple2->getName();
+  CPPUNIT_ASSERT(name=="PartOf_Toto");
+  subMeshSimple2->decrRef();
   //
   mesh->decrRef();
 }
@@ -624,8 +691,8 @@ void MEDCouplingBasicsTest::testZipCoords()
   MEDCouplingUMesh *subMesh=dynamic_cast<MEDCouplingUMesh *>(subMeshPtSet);
   CPPUNIT_ASSERT(subMesh);
   DataArrayInt *traducer=subMesh->zipCoordsTraducer();
-  const int expectedTraducer[9]={0,1,-1,2,3,4,-1,5,6};
-  CPPUNIT_ASSERT(std::equal(expectedTraducer,expectedTraducer+9,traducer->getPointer()));
+  const int expectedTraducer[7]={0,1,3,4,5,7,8};
+  CPPUNIT_ASSERT(std::equal(expectedTraducer,expectedTraducer+7,traducer->getPointer()));
   traducer->decrRef();
   CPPUNIT_ASSERT_EQUAL(INTERP_KERNEL::NORM_QUAD4,*subMesh->getAllTypes().begin());
   CPPUNIT_ASSERT_EQUAL(2,subMesh->getNumberOfCells());
@@ -653,6 +720,47 @@ void MEDCouplingBasicsTest::testZipCoords()
   mesh->decrRef();
 }
 
+void MEDCouplingBasicsTest::testZipConnectivity()
+{
+  MEDCouplingUMesh *m1=build2DTargetMesh_1();
+  MEDCouplingUMesh *m2=build2DTargetMesh_1();
+  int cells1[3]={2,3,4};
+  MEDCouplingPointSet *m3_1=m2->buildPartOfMySelf(cells1,cells1+3,true);
+  MEDCouplingUMesh *m3=dynamic_cast<MEDCouplingUMesh *>(m3_1);
+  CPPUNIT_ASSERT(m3);
+  m2->decrRef();
+  MEDCouplingUMesh *m4=build2DSourceMesh_1();
+  MEDCouplingUMesh *m5=MEDCouplingUMesh::mergeUMeshes(m1,m3);
+  m1->decrRef();
+  m3->decrRef();
+  MEDCouplingUMesh *m6=MEDCouplingUMesh::mergeUMeshes(m5,m4);
+  m4->decrRef();
+  m5->decrRef();
+  //
+  bool areNodesMerged;
+  int newNbOfNodes;
+  CPPUNIT_ASSERT_EQUAL(10,m6->getNumberOfCells());
+  CPPUNIT_ASSERT_EQUAL(22,m6->getNumberOfNodes());
+  DataArrayInt *arr=m6->mergeNodes(1e-13,areNodesMerged,newNbOfNodes);
+  arr->decrRef();
+  CPPUNIT_ASSERT(areNodesMerged);
+  CPPUNIT_ASSERT_EQUAL(10,m6->getNumberOfCells());
+  CPPUNIT_ASSERT_EQUAL(9,m6->getNumberOfNodes());
+  CPPUNIT_ASSERT_EQUAL(9,newNbOfNodes);
+  //
+  arr=m6->zipConnectivityTraducer(0);
+  CPPUNIT_ASSERT_EQUAL(7,m6->getNumberOfCells());
+  arr->decrRef();
+  MEDCouplingUMesh *m7=m6->clone(true);
+  arr=m6->zipConnectivityTraducer(0);
+  CPPUNIT_ASSERT(m7->isEqual(m6,1e-12));
+  CPPUNIT_ASSERT_EQUAL(7,m6->getNumberOfCells());
+  arr->decrRef();
+  //
+  m7->decrRef();
+  m6->decrRef();
+}
+
 void MEDCouplingBasicsTest::testEqualMesh()
 {
   MEDCouplingUMesh *mesh1=build2DTargetMesh_1();
@@ -887,7 +995,8 @@ void MEDCouplingBasicsTest::testExtrudedMesh2()
   build3DExtrudedUMesh_2(mN,mTT,mTF);
   //
   bool b=false;
-  DataArrayInt *da=mTT->mergeNodes(1e-12,b);
+  int newNbOfNodes;
+  DataArrayInt *da=mTT->mergeNodes(1e-12,b,newNbOfNodes);
   CPPUNIT_ASSERT(b);
   da->decrRef();
   std::vector<int> n;
@@ -903,7 +1012,7 @@ void MEDCouplingBasicsTest::testExtrudedMesh2()
   mTT3dSurf->decrRef();
   //
   b=false;
-  da=mN->mergeNodes(1e-12,b);
+  da=mN->mergeNodes(1e-12,b,newNbOfNodes);
   da->decrRef();
   CPPUNIT_ASSERT(!b);
   n.clear();
@@ -917,7 +1026,7 @@ void MEDCouplingBasicsTest::testExtrudedMesh2()
   mN3dSurf->decrRef();
   //
   b=false;
-  da=mTF->mergeNodes(1e-12,b);
+  da=mTF->mergeNodes(1e-12,b,newNbOfNodes);
   da->decrRef();
   CPPUNIT_ASSERT(!b);
   n.clear();
@@ -939,11 +1048,118 @@ void MEDCouplingBasicsTest::testExtrudedMesh2()
   mTF->decrRef();
 }
 
+/*!
+ * This test check MEDCouplingUMesh::buildExtrudedMeshFromThis method.
+ */
+void MEDCouplingBasicsTest::testExtrudedMesh3()
+{
+  MEDCouplingUMesh *m1=build2DTargetMesh_1();
+  m1->changeSpaceDimension(3);
+  MEDCouplingUMesh *m2=buildCU1DMesh_U();
+  m2->changeSpaceDimension(3);
+  double center[3]={0.,0.,0.};
+  double vector[3]={0,1,0};
+  m2->rotate(center,vector,-M_PI/2.);
+  MEDCouplingUMesh *m3=m1->buildExtrudedMeshFromThis(m2,0);
+  //
+  MEDCouplingExtrudedMesh *m4=MEDCouplingExtrudedMesh::New(m3,m1,0);
+  CPPUNIT_ASSERT_EQUAL(15,m4->getNumberOfCells());
+  CPPUNIT_ASSERT_EQUAL(5,m4->getMesh2D()->getNumberOfCells());
+  CPPUNIT_ASSERT_EQUAL(3,m4->getMesh1D()->getNumberOfCells());
+  const int *m3DIds=m4->getMesh3DIds()->getConstPointer();
+  for(int i=0;i<15;i++)
+    CPPUNIT_ASSERT_EQUAL(i,m3DIds[i]);
+  m4->decrRef();
+  //some random in cells to check that extrusion alg find it correctly
+  const int expected1[15]={1,3,2,0,6,5,7,10,11,8,12,9,14,13,4};
+  m3->renumberCells(expected1,false);
+  m4=MEDCouplingExtrudedMesh::New(m3,m1,0);
+  CPPUNIT_ASSERT_EQUAL(15,m4->getNumberOfCells());
+  CPPUNIT_ASSERT_EQUAL(5,m4->getMesh2D()->getNumberOfCells());
+  CPPUNIT_ASSERT_EQUAL(3,m4->getMesh1D()->getNumberOfCells());
+  m3DIds=m4->getMesh3DIds()->getConstPointer();
+  for(int i=0;i<15;i++)
+    CPPUNIT_ASSERT_EQUAL(expected1[i],m3DIds[i]);
+  m4->decrRef();
+  m3->decrRef();
+  //play with polygons and polyedrons
+  std::vector<int> cells(2); cells[0]=2; cells[1]=3;
+  m1->convertToPolyTypes(cells);
+  m3=m1->buildExtrudedMeshFromThis(m2,0);
+  CPPUNIT_ASSERT_EQUAL((int)INTERP_KERNEL::NORM_HEXA8,(int)m3->getTypeOfCell(0));
+  CPPUNIT_ASSERT_EQUAL((int)INTERP_KERNEL::NORM_PENTA6,(int)m3->getTypeOfCell(1));
+  CPPUNIT_ASSERT_EQUAL((int)INTERP_KERNEL::NORM_POLYHED,(int)m3->getTypeOfCell(2));
+  CPPUNIT_ASSERT_EQUAL((int)INTERP_KERNEL::NORM_POLYHED,(int)m3->getTypeOfCell(3));
+  CPPUNIT_ASSERT_EQUAL((int)INTERP_KERNEL::NORM_HEXA8,(int)m3->getTypeOfCell(4));
+  m3->renumberCells(expected1,false);
+  m4=MEDCouplingExtrudedMesh::New(m3,m1,0);
+  CPPUNIT_ASSERT_EQUAL(15,m4->getNumberOfCells());
+  CPPUNIT_ASSERT_EQUAL(5,m4->getMesh2D()->getNumberOfCells());
+  CPPUNIT_ASSERT_EQUAL(3,m4->getMesh1D()->getNumberOfCells());
+  m3DIds=m4->getMesh3DIds()->getConstPointer();
+  for(int i=0;i<15;i++)
+    CPPUNIT_ASSERT_EQUAL(expected1[i],m3DIds[i]);
+  m4->decrRef();
+  m3->decrRef();
+  //
+  m2->decrRef();
+  m1->decrRef();
+}
+
+/*!
+ * This test check MEDCouplingUMesh::buildExtrudedMeshFromThis method, but also, MEDCouplingExtrudedMesh following methods :
+ * getCellContainingPoint getMeasureField getNodeIdsOfCell getCoordinateOfNode getTypeOfCell build3DUnstructuredMesh.
+ */
+void MEDCouplingBasicsTest::testExtrudedMesh4()
+{
+  MEDCouplingUMesh *m1=build2DTargetMesh_1();
+  std::vector<int> cells(2); cells[0]=2; cells[1]=4;
+  m1->convertToPolyTypes(cells);
+  m1->changeSpaceDimension(3);
+  MEDCouplingUMesh *m2=buildCU1DMesh_U();
+  m2->changeSpaceDimension(3);
+  double center[3]={0.,0.,0.};
+  double vector[3]={0.,1.,0.};
+  m2->rotate(center,vector,-M_PI/2.);
+  MEDCouplingUMesh *m3=m1->buildExtrudedMeshFromThis(m2,0);
+  const int expected1[15]= {1,3,2,0,6,5,7,10,11,8,12,9,14,13,4};
+  const int rexpected1[15]={3, 0, 2, 1, 14, 5, 4, 6, 9, 11, 7, 8, 10, 13, 12};
+  m3->renumberCells(expected1,false);
+  MEDCouplingExtrudedMesh *m4=MEDCouplingExtrudedMesh::New(m3,m1,0);
+  CPPUNIT_ASSERT_EQUAL(INTERP_KERNEL::NORM_HEXA8,m4->getTypeOfCell(0));
+  CPPUNIT_ASSERT_EQUAL(INTERP_KERNEL::NORM_HEXA8,m4->getTypeOfCell(1));
+  CPPUNIT_ASSERT_EQUAL(INTERP_KERNEL::NORM_POLYHED,m4->getTypeOfCell(2));
+  CPPUNIT_ASSERT_EQUAL(INTERP_KERNEL::NORM_PENTA6,m4->getTypeOfCell(7));
+  MEDCouplingFieldDouble *f=m4->getMeasureField(true);
+  DataArrayDouble *arr=f->getArray();
+  CPPUNIT_ASSERT_EQUAL(15,arr->getNumberOfTuples());
+  CPPUNIT_ASSERT_EQUAL(1,arr->getNumberOfComponents());
+  const double *arrPtr=arr->getConstPointer();
+  const double expected2[15]={0.075,0.0375,0.0375,0.075,0.075,   0.1125,0.05625,0.05625,0.1125,0.1125,   0.0625,0.03125,0.03125,0.0625,0.0625};
+  for(int i=0;i<15;i++)
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(expected2[rexpected1[i]],arrPtr[i],1e-16);
+  f->decrRef();
+  MEDCouplingUMesh *m5=m4->build3DUnstructuredMesh();
+  CPPUNIT_ASSERT(m5->isEqual(m3,1e-12));
+  f=m5->getMeasureField(true);
+  arr=f->getArray();
+  arrPtr=arr->getConstPointer();
+  for(int i=0;i<15;i++)
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(expected2[rexpected1[i]],arrPtr[i],1e-16);
+  f->decrRef();
+  m5->decrRef();
+  //
+  m4->decrRef();
+  m3->decrRef();
+  m2->decrRef();
+  m1->decrRef();
+}
+
 void MEDCouplingBasicsTest::testFindCommonNodes()
 {
   DataArrayInt *comm,*commI;
   MEDCouplingUMesh *targetMesh=build3DTargetMesh_1();
-  targetMesh->findCommonNodes(comm,commI,1e-10);
+  targetMesh->findCommonNodes(-1,1e-10,comm,commI);
   CPPUNIT_ASSERT_EQUAL(1,commI->getNumberOfTuples());
   CPPUNIT_ASSERT_EQUAL(0,comm->getNumberOfTuples());
   int newNbOfNodes;
@@ -963,7 +1179,7 @@ void MEDCouplingBasicsTest::testFindCommonNodes()
   //
   targetMesh=build3DTargetMeshMergeNode_1();
   CPPUNIT_ASSERT_EQUAL(31,targetMesh->getNumberOfNodes());
-  targetMesh->findCommonNodes(comm,commI,1e-10);
+  targetMesh->findCommonNodes(-1,1e-10,comm,commI);
   CPPUNIT_ASSERT_EQUAL(3,commI->getNumberOfTuples());
   CPPUNIT_ASSERT_EQUAL(6,comm->getNumberOfTuples());
   const int commExpected[6]={1,27,28,29,23,30};
@@ -987,7 +1203,7 @@ void MEDCouplingBasicsTest::testFindCommonNodes()
   targetMesh=build3DTargetMesh_1();
   bool areNodesMerged;
   unsigned int time=targetMesh->getTimeOfThis();
-  o2n=targetMesh->mergeNodes(1e-10,areNodesMerged);
+  o2n=targetMesh->mergeNodes(1e-10,areNodesMerged,newNbOfNodes);
   targetMesh->updateTime();
   CPPUNIT_ASSERT(time==targetMesh->getTimeOfThis());
   CPPUNIT_ASSERT(!areNodesMerged);
@@ -996,7 +1212,7 @@ void MEDCouplingBasicsTest::testFindCommonNodes()
   //
   targetMesh=build3DTargetMeshMergeNode_1();
   time=targetMesh->getTimeOfThis();
-  o2n=targetMesh->mergeNodes(1e-10,areNodesMerged);
+  o2n=targetMesh->mergeNodes(1e-10,areNodesMerged,newNbOfNodes);
   targetMesh->updateTime();
   CPPUNIT_ASSERT(time!=targetMesh->getTimeOfThis());
   CPPUNIT_ASSERT(areNodesMerged);
@@ -1021,7 +1237,7 @@ void MEDCouplingBasicsTest::testFindCommonNodes()
   targetMesh=build2DTargetMeshMergeNode_1();
   CPPUNIT_ASSERT_EQUAL(18,targetMesh->getNumberOfNodes());
   time=targetMesh->getTimeOfThis();
-  o2n=targetMesh->mergeNodes(1e-10,areNodesMerged);
+  o2n=targetMesh->mergeNodes(1e-10,areNodesMerged,newNbOfNodes);
   CPPUNIT_ASSERT(time!=targetMesh->getTimeOfThis());
   CPPUNIT_ASSERT(areNodesMerged);
   CPPUNIT_ASSERT_EQUAL(9,targetMesh->getNumberOfNodes());
@@ -1081,8 +1297,10 @@ void MEDCouplingBasicsTest::testMergeMesh1()
   CPPUNIT_ASSERT(m3->isEqual(m4,1.e-12));
   m4->decrRef();
   bool isMerged;
-  DataArrayInt *da=m3C->mergeNodes(1.e-12,isMerged);
+  int newNbOfNodes;
+  DataArrayInt *da=m3C->mergeNodes(1.e-12,isMerged,newNbOfNodes);
   CPPUNIT_ASSERT_EQUAL(11,m3C->getNumberOfNodes());
+  CPPUNIT_ASSERT_EQUAL(11,newNbOfNodes);
   CPPUNIT_ASSERT(isMerged);
   da->decrRef();
   m3->decrRef();
@@ -1090,6 +1308,43 @@ void MEDCouplingBasicsTest::testMergeMesh1()
   m2->decrRef();
 }
 
+void MEDCouplingBasicsTest::testMergeMeshOnSameCoords1()
+{
+  MEDCouplingUMesh *m1=build2DTargetMesh_1();
+  MEDCouplingUMesh *m2=build2DTargetMesh_1();
+  std::vector<int> cells(5);
+  for(int i=0;i<5;i++)
+    cells[i]=i;
+  m2->convertToPolyTypes(cells);
+  m1->tryToShareSameCoords(*m2,1e-12);
+  MEDCouplingUMesh *m3=build2DTargetMesh_1();
+  m3->tryToShareSameCoords(*m2,1e-12);
+  std::vector<MEDCouplingUMesh *> meshes;
+  meshes.push_back(m1); meshes.push_back(m2); meshes.push_back(m3);
+  MEDCouplingUMesh *m4=MEDCouplingUMesh::mergeUMeshesOnSameCoords(meshes);
+  m4->checkCoherency();
+  CPPUNIT_ASSERT(m4->getCoords()==m1->getCoords());
+  CPPUNIT_ASSERT_EQUAL(15,m4->getNumberOfCells());
+  const int cells1[5]={0,1,2,3,4};
+  MEDCouplingPointSet *m1_1=m4->buildPartOfMySelf(cells1,cells1+5,true);
+  m1_1->setName(m1->getName());
+  CPPUNIT_ASSERT(m1->isEqual(m1_1,1e-12));
+  const int cells2[5]={5,6,7,8,9};
+  MEDCouplingPointSet *m2_1=m4->buildPartOfMySelf(cells2,cells2+5,true);
+  m2_1->setName(m2->getName());
+  CPPUNIT_ASSERT(m2->isEqual(m2_1,1e-12));
+  const int cells3[5]={10,11,12,13,14};
+  MEDCouplingPointSet *m3_1=m4->buildPartOfMySelf(cells3,cells3+5,true);
+  m3_1->setName(m3->getName());
+  CPPUNIT_ASSERT(m3->isEqual(m3_1,1e-12));
+  m1_1->decrRef(); m2_1->decrRef(); m3_1->decrRef();
+  //
+  m4->decrRef();
+  m1->decrRef();
+  m2->decrRef();
+  m3->decrRef();
+}
+
 void MEDCouplingBasicsTest::testMergeField1()
 {
   MEDCouplingUMesh *m1=build2DTargetMesh_1();
@@ -1195,7 +1450,7 @@ void MEDCouplingBasicsTest::testFillFromAnalytic()
   f1->accumulate(values4);
   CPPUNIT_ASSERT_DOUBLES_EQUAL(3.6,values4[0],1.e-12);
   CPPUNIT_ASSERT_DOUBLES_EQUAL(7.2,values4[1],1.e-12);
-  f1->measureAccumulate(true,values4);
+  f1->integral(true,values4);
   CPPUNIT_ASSERT_DOUBLES_EQUAL(0.5,values4[0],1.e-12);
   CPPUNIT_ASSERT_DOUBLES_EQUAL(1.,values4[1],1.e-12);
   f1->decrRef();
@@ -1265,7 +1520,7 @@ void MEDCouplingBasicsTest::testFillFromAnalytic2()
   f1->accumulate(values4);
   CPPUNIT_ASSERT_DOUBLES_EQUAL(3.6,values4[0],1.e-12);
   CPPUNIT_ASSERT_DOUBLES_EQUAL(7.2,values4[1],1.e-12);
-  f1->measureAccumulate(true,values4);
+  f1->integral(true,values4);
   CPPUNIT_ASSERT_DOUBLES_EQUAL(0.5,values4[0],1.e-12);
   CPPUNIT_ASSERT_DOUBLES_EQUAL(1.,values4[1],1.e-12);
   f1->decrRef();
@@ -1525,6 +1780,105 @@ void MEDCouplingBasicsTest::testOperationsOnFields3()
   m->decrRef();
 }
 
+/*!
+ * Check of LINEAR_TIME and CONST_ON_TIME_INTERVAL policies
+ */
+void MEDCouplingBasicsTest::testOperationsOnFields4()
+{
+  MEDCouplingUMesh *m=build2DTargetMesh_1();
+  int nbOfCells=m->getNumberOfCells();
+  MEDCouplingFieldDouble *f1=MEDCouplingFieldDouble::New(ON_CELLS,CONST_ON_TIME_INTERVAL);
+  f1->setMesh(m);
+  DataArrayDouble *array=DataArrayDouble::New();
+  array->alloc(nbOfCells,3);
+  f1->setArray(array);
+  CPPUNIT_ASSERT_THROW(f1->setEndArray(array),INTERP_KERNEL::Exception);
+  CPPUNIT_ASSERT_THROW(f1->getEndArray(),INTERP_KERNEL::Exception);
+  array->decrRef();
+  double *tmp=array->getPointer();
+  const double arr1[15]={0.,10.,20.,1.,11.,21.,2.,12.,22.,3.,13.,23.,4.,14.,24.};
+  const double arr2[15]={5.,15.,25.,6.,16.,26.,7.,17.,27.,8.,18.,28.,9.,19.,29.};
+  std::copy(arr1,arr1+15,tmp);
+  f1->setStartTime(2.,0,0);
+  f1->setEndTime(3.,0,0);
+  f1->checkCoherency();
+  double res[3];
+  const double pos[2]={0.3,-0.2};
+  f1->getValueOn(pos,res);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(arr1[3],res[0],1.e-12);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(arr1[4],res[1],1.e-12);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(arr1[5],res[2],1.e-12);
+  std::fill(res,res+3,0.);
+  f1->getValueOn(pos,2.2,res);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(arr1[3],res[0],1.e-12);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(arr1[4],res[1],1.e-12);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(arr1[5],res[2],1.e-12);
+  std::fill(res,res+3,0.);
+  CPPUNIT_ASSERT_THROW(f1->getValueOn(pos,3.2,res),INTERP_KERNEL::Exception);
+  MEDCouplingFieldDouble *f2=MEDCouplingFieldDouble::New(ON_CELLS,LINEAR_TIME);
+  f2->setMesh(m);
+  f2->setArray(f1->getArray());
+  f2->setStartTime(2.,3,0);
+  f2->setEndTime(4.,13,0);
+  CPPUNIT_ASSERT_THROW(f2->checkCoherency(),INTERP_KERNEL::Exception);
+  DataArrayDouble *array2=DataArrayDouble::New();
+  array2->alloc(nbOfCells,3);
+  tmp=array2->getPointer();
+  std::copy(arr2,arr2+15,tmp);
+  f2->setEndArray(array2);
+  array2->decrRef();
+  f2->checkCoherency();
+  //
+  std::fill(res,res+3,0.);
+  f2->getValueOn(pos,3.21,res);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(4.025,res[0],1.e-12);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(14.025,res[1],1.e-12);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(24.025,res[2],1.e-12);
+  MEDCouplingFieldDouble *f3=f2->clone(true);
+  CPPUNIT_ASSERT(f2->isEqual(f3,1e-12,1e-12));
+  f3->getEndArray()->getPointer()[0]=5.001;
+  CPPUNIT_ASSERT(!f2->isEqual(f3,1e-12,1e-12));
+  CPPUNIT_ASSERT(f2->isEqual(f3,1e-12,1e-2));
+  f3->setStartTime(2.1,3,0);
+  CPPUNIT_ASSERT(!f2->isEqual(f3,1e-12,1e-2));
+  f3->setStartTime(2.,3,0);
+  CPPUNIT_ASSERT(f2->isEqual(f3,1e-12,1e-2));
+  f3->setStartTime(2.,4,0);
+  CPPUNIT_ASSERT(!f2->isEqual(f3,1e-12,1e-2));
+  f3->setStartTime(2.,3,1);
+  CPPUNIT_ASSERT(!f2->isEqual(f3,1e-12,1e-2));
+  f3->setStartTime(2.,3,0);
+  CPPUNIT_ASSERT(f2->isEqual(f3,1e-12,1e-2));
+  f3->setEndTime(4.1,13,0);
+  CPPUNIT_ASSERT(!f2->isEqual(f3,1e-12,1e-2));
+  f3->setEndTime(4.,13,0);
+  CPPUNIT_ASSERT(f2->isEqual(f3,1e-12,1e-2));
+  f3->setEndTime(4.,14,0);
+  CPPUNIT_ASSERT(!f2->isEqual(f3,1e-12,1e-2));
+  f3->setEndTime(4.,13,1);
+  CPPUNIT_ASSERT(!f2->isEqual(f3,1e-12,1e-2));
+  f3->setEndTime(4.,13,0);
+  CPPUNIT_ASSERT(f2->isEqual(f3,1e-12,1e-2));
+  f3->decrRef();
+  MEDCouplingFieldDouble *f4=(*f2)+(*f2);
+  std::fill(res,res+3,0.);
+  f4->getValueOn(pos,3.21,res);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(8.05,res[0],1.e-12);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(28.05,res[1],1.e-12);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(48.05,res[2],1.e-12);
+  (*f4)+=*f2;
+  std::fill(res,res+3,0.);
+  f4->getValueOn(pos,3.21,res);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(12.075,res[0],1.e-12);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(42.075,res[1],1.e-12);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(72.075,res[2],1.e-12);
+  f4->decrRef();
+  //
+  f2->decrRef();
+  f1->decrRef();
+  m->decrRef();
+}
+
 bool func4(const double *pt, double *res)
 {
   res[0]=pt[0]+pt[1]+pt[2];
@@ -1562,11 +1916,178 @@ void MEDCouplingBasicsTest::testCheckConsecutiveCellTypes()
   MEDCouplingUMesh *sourceMesh=build2DSourceMesh_1();
   MEDCouplingUMesh *targetMesh=build2DTargetMesh_1();
   CPPUNIT_ASSERT(sourceMesh->checkConsecutiveCellTypes());
+  const INTERP_KERNEL::NormalizedCellType order1[]={INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4};
+  const INTERP_KERNEL::NormalizedCellType order2[]={INTERP_KERNEL::NORM_QUAD4, INTERP_KERNEL::NORM_TRI3};
   CPPUNIT_ASSERT(!targetMesh->checkConsecutiveCellTypes());
+  CPPUNIT_ASSERT(!targetMesh->checkConsecutiveCellTypesAndOrder(order1,order1+2));
+  CPPUNIT_ASSERT(!targetMesh->checkConsecutiveCellTypesAndOrder(order2,order2+2));
+  DataArrayInt *da=targetMesh->getRenumArrForConsctvCellTypesSpe(order1,order1+2);
+  CPPUNIT_ASSERT_EQUAL(5,da->getNumberOfTuples());
+  CPPUNIT_ASSERT_EQUAL(1,da->getNumberOfComponents());
+  const int expected1[5]={2,0,1,3,4};
+  CPPUNIT_ASSERT(std::equal(expected1,expected1+5,da->getConstPointer()));
+  da->decrRef();
+  da=targetMesh->getRenumArrForConsctvCellTypesSpe(order2,order2+2);
+  CPPUNIT_ASSERT_EQUAL(5,da->getNumberOfTuples());
+  CPPUNIT_ASSERT_EQUAL(1,da->getNumberOfComponents());
+  const int expected2[5]={0,3,4,1,2};
+  CPPUNIT_ASSERT(std::equal(expected2,expected2+5,da->getConstPointer()));
+  da->decrRef();
+  const int renumber1[5]={4,0,1,2,3};
+  targetMesh->renumberCells(renumber1,false);
+  CPPUNIT_ASSERT(targetMesh->checkConsecutiveCellTypes());
+  CPPUNIT_ASSERT(targetMesh->checkConsecutiveCellTypesAndOrder(order1,order1+2));
+  CPPUNIT_ASSERT(!targetMesh->checkConsecutiveCellTypesAndOrder(order2,order2+2));
   targetMesh->decrRef();
   sourceMesh->decrRef();
 }
 
+void MEDCouplingBasicsTest::testRearrange2ConsecutiveCellTypes()
+{
+  MEDCouplingUMesh *m1_1=build2DSourceMesh_1();
+  MEDCouplingUMesh *m2_1=build2DTargetMesh_1();
+  DataArrayInt *arr1=m1_1->rearrange2ConsecutiveCellTypes();
+  MEDCouplingUMesh *m1_2=build2DSourceMesh_1();
+  CPPUNIT_ASSERT(m1_2->isEqual(m1_1,1e-12));
+  const int expected1[2]={0,1};
+  CPPUNIT_ASSERT_EQUAL(2,arr1->getNumberOfTuples());
+  CPPUNIT_ASSERT_EQUAL(1,arr1->getNumberOfComponents());
+  CPPUNIT_ASSERT(std::equal(expected1,expected1+2,arr1->getConstPointer()));
+  arr1->decrRef();
+  const int expected2[5]={0,3,4,1,2};
+  arr1=m2_1->rearrange2ConsecutiveCellTypes();
+  CPPUNIT_ASSERT_EQUAL(5,arr1->getNumberOfTuples());
+  CPPUNIT_ASSERT_EQUAL(1,arr1->getNumberOfComponents());
+  CPPUNIT_ASSERT(std::equal(expected2,expected2+5,arr1->getConstPointer()));
+  MEDCouplingUMesh *m2_2=build2DTargetMesh_1();
+  CPPUNIT_ASSERT_EQUAL(5,arr1->getNumberOfTuples());
+  CPPUNIT_ASSERT_EQUAL(1,arr1->getNumberOfComponents());
+  CPPUNIT_ASSERT(std::equal(expected2,expected2+5,arr1->getConstPointer()));
+  CPPUNIT_ASSERT(!m2_2->isEqual(m2_1,1e-12));
+  m2_2->renumberCells(expected2,false);
+  CPPUNIT_ASSERT(m2_2->isEqual(m2_1,1e-12));
+  arr1->decrRef();
+  m1_1->decrRef();
+  m1_2->decrRef();
+  m2_1->decrRef();
+  m2_2->decrRef();
+}
+
+void MEDCouplingBasicsTest::testSplitByType()
+{
+  MEDCouplingUMesh *m1=build3DSurfTargetMesh_1();
+  std::vector<MEDCouplingUMesh *> v=m1->splitByType();
+  CPPUNIT_ASSERT_EQUAL(3,(int)v.size());
+  MEDCouplingUMesh *m2=MEDCouplingUMesh::mergeUMeshesOnSameCoords(v);
+  m2->setName(m1->getName());
+  CPPUNIT_ASSERT(m1->isEqual(m2,1.e-12));
+  for(std::vector<MEDCouplingUMesh *>::const_iterator iter=v.begin();iter!=v.end();iter++)
+    (*iter)->decrRef();
+  m2->decrRef();
+  m1->decrRef();
+}
+
+void MEDCouplingBasicsTest::testFuseUMeshesOnSameCoords()
+{
+  std::vector<MEDCouplingUMesh *> meshes;
+  MEDCouplingUMesh *m2=build2DTargetMesh_1();
+  int cells1[3]={2,3,4};
+  MEDCouplingPointSet *m3_1=m2->buildPartOfMySelf(cells1,cells1+3,true);
+  MEDCouplingUMesh *m3=dynamic_cast<MEDCouplingUMesh *>(m3_1);
+  CPPUNIT_ASSERT(m3);
+  meshes.push_back(m3);
+  int cells2[3]={1,2,4};
+  MEDCouplingPointSet *m4_1=m2->buildPartOfMySelf(cells2,cells2+3,true);
+  MEDCouplingUMesh *m4=dynamic_cast<MEDCouplingUMesh *>(m4_1);
+  CPPUNIT_ASSERT(m4);
+  meshes.push_back(m4);
+  int cells3[2]={1,2};
+  MEDCouplingPointSet *m5_1=m2->buildPartOfMySelf(cells3,cells3+2,true);
+  MEDCouplingUMesh *m5=dynamic_cast<MEDCouplingUMesh *>(m5_1);
+  CPPUNIT_ASSERT(m5);
+  meshes.push_back(m5);
+  m2->decrRef();
+  //
+  std::vector<DataArrayInt *> corr;
+  MEDCouplingUMesh *m7=MEDCouplingUMesh::fuseUMeshesOnSameCoords(meshes,0,corr);
+  CPPUNIT_ASSERT_EQUAL(4,m7->getNumberOfCells());
+  CPPUNIT_ASSERT_EQUAL(3,(int)corr.size());
+  const int expectedVals1[3]={3,3,2};
+  const int expectedVals2[3][3]={{0,1,2},{3,0,2},{3,0,111111}};
+  for(int i=0;i<3;i++)
+    {
+      DataArrayInt *arr=corr[i];
+      CPPUNIT_ASSERT_EQUAL(1,arr->getNumberOfComponents());
+      int nbOfVals=expectedVals1[i];
+      CPPUNIT_ASSERT_EQUAL(nbOfVals,arr->getNumberOfTuples());
+      const int *vals=arr->getConstPointer();
+      for(int j=0;j<nbOfVals;j++)
+        CPPUNIT_ASSERT_EQUAL(expectedVals2[i][j],vals[j]);
+    }
+  std::vector< std::vector<int> > fidsOfGroups;
+  DataArrayInt *arr2=DataArrayInt::makePartition(corr,m7->getNumberOfCells(),fidsOfGroups);
+  const int fidExp[4]={5,1,3,4};
+  const int fidsGrp[3][3]={{1,3,5},{3,4,5},{4,5,23344}};
+  CPPUNIT_ASSERT_EQUAL(3,(int)fidsOfGroups.size());
+  CPPUNIT_ASSERT_EQUAL(1,arr2->getNumberOfComponents());
+  CPPUNIT_ASSERT_EQUAL(4,arr2->getNumberOfTuples());
+  CPPUNIT_ASSERT(std::equal(fidExp,fidExp+4,arr2->getConstPointer()));
+  for(int i=0;i<3;i++)
+    {
+      int nbOfVals=expectedVals1[i];
+      CPPUNIT_ASSERT_EQUAL(nbOfVals,(int)fidsOfGroups[i].size());
+      CPPUNIT_ASSERT(std::equal(fidsOfGroups[i].begin(),fidsOfGroups[i].end(),fidsGrp[i]));
+    }
+  for(std::vector<DataArrayInt *>::iterator iter=corr.begin();iter!=corr.end();iter++)
+    (*iter)->decrRef();
+  arr2->decrRef();
+  m7->decrRef();
+  //
+  m3->decrRef();
+  m4->decrRef();
+  m5->decrRef();
+}
+
+void MEDCouplingBasicsTest::testFuseUMeshesOnSameCoords2()
+{
+  MEDCouplingUMesh *m2;
+  MEDCouplingUMesh *m1=build3DExtrudedUMesh_1(m2);
+  m2->decrRef();
+  const int part1[5]={2,3,6,4,10};
+  MEDCouplingUMesh *m3=(MEDCouplingUMesh *)m1->buildPartOfMySelf(part1,part1+5,true);
+  const int part2[4]={5,6,4,7};
+  MEDCouplingUMesh *m4=(MEDCouplingUMesh *)m1->buildPartOfMySelf(part2,part2+4,true);
+  std::vector<MEDCouplingUMesh *> meshes;
+  meshes.push_back(m1);
+  meshes.push_back(m3);
+  meshes.push_back(m3);
+  meshes.push_back(m4);
+  std::vector<DataArrayInt *> corr;
+  MEDCouplingUMesh *m5=MEDCouplingUMesh::fuseUMeshesOnSameCoords(meshes,0,corr);
+  CPPUNIT_ASSERT_EQUAL(18,m5->getNumberOfCells());
+  std::vector<DataArrayInt *>::iterator it=corr.begin();
+  const int exp1[4]={18,5,5,4};
+  const int exp2[4][18]={
+    {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17},
+    {2,3,6,4,10,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
+    {2,3,6,4,10,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
+    {5,6,4,7,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1}
+  };
+  int i=0;
+  for(;it!=corr.end();it++,i++)
+    {
+      int sz=(*it)->getNumberOfTuples();
+      CPPUNIT_ASSERT_EQUAL(exp1[i],sz);
+      CPPUNIT_ASSERT(std::equal(exp2[i],exp2[i]+sz,(*it)->getConstPointer()));
+    }
+  for(it=corr.begin();it!=corr.end();it++)
+    (*it)->decrRef();
+  m5->decrRef();
+  m4->decrRef();
+  m3->decrRef();
+  m1->decrRef();
+}
+
 void MEDCouplingBasicsTest::testBuildOrthogonalField()
 {
   MEDCouplingUMesh *targetMesh=build3DSurfTargetMesh_1();
@@ -1845,7 +2366,7 @@ void MEDCouplingBasicsTest::testRenumberCells()
   MEDCouplingUMesh *m2=build3DSurfTargetMesh_1();
   CPPUNIT_ASSERT(m->isEqual(m2,0));
   const int arr[5]={12,3,25,2,26};
-  m->renumberCells(arr,arr+5,true);
+  m->renumberCells(arr,true);
   CPPUNIT_ASSERT(!m->isEqual(m2,0));
   CPPUNIT_ASSERT_EQUAL(INTERP_KERNEL::NORM_QUAD4,m->getTypeOfCell(0));
   CPPUNIT_ASSERT_EQUAL(INTERP_KERNEL::NORM_TRI3,m->getTypeOfCell(1));
@@ -1853,7 +2374,7 @@ void MEDCouplingBasicsTest::testRenumberCells()
   CPPUNIT_ASSERT_EQUAL(INTERP_KERNEL::NORM_TRI3,m->getTypeOfCell(3));
   CPPUNIT_ASSERT_EQUAL(INTERP_KERNEL::NORM_QUAD4,m->getTypeOfCell(4));
   const int arr2[5]={5,-1,-5,4,8};
-  m->renumberCells(arr2,arr2+5,true);
+  m->renumberCells(arr2,true);
   CPPUNIT_ASSERT(m->isEqual(m2,0));
   m->decrRef();
   m2->decrRef();
diff --git a/src/MEDCoupling/Test/MEDCouplingBasicsTest2.cxx b/src/MEDCoupling/Test/MEDCouplingBasicsTest2.cxx
new file mode 100644 (file)
index 0000000..acf8efe
--- /dev/null
@@ -0,0 +1,1979 @@
+//  Copyright (C) 2007-2010  CEA/DEN, EDF R&D
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU Lesser General Public
+//  License as published by the Free Software Foundation; either
+//  version 2.1 of the License.
+//
+//  This library is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  Lesser General Public License for more details.
+//
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+//  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+#include "MEDCouplingBasicsTest.hxx"
+#include "MEDCouplingUMesh.hxx"
+#include "MEDCouplingCMesh.hxx"
+#include "MEDCouplingExtrudedMesh.hxx"
+#include "MEDCouplingFieldDouble.hxx"
+#include "MEDCouplingMemArray.hxx"
+#include "MEDCouplingGaussLocalization.hxx"
+
+#include <cmath>
+#include <functional>
+#include <iterator>
+
+using namespace ParaMEDMEM;
+
+void MEDCouplingBasicsTest::testGaussPointField1()
+{
+  const double _a=0.446948490915965;
+  const double _b=0.091576213509771;
+  const double _p1=0.11169079483905;
+  const double _p2=0.0549758718227661;
+  const double refCoo1[6]={ 0.,0., 1.,0., 0.,1. };
+  const double gsCoo1[12]={ 2*_b-1, 1-4*_b, 2*_b-1, 2.07*_b-1, 1-4*_b,
+                            2*_b-1, 1-4*_a, 2*_a-1, 2*_a-1, 1-4*_a, 2*_a-1, 2*_a-1 };
+  const double wg1[6]={ 4*_p2, 4*_p2, 4*_p2, 4*_p1, 4*_p1, 4*_p1 };
+  std::vector<double> _refCoo1(refCoo1,refCoo1+6);
+  std::vector<double> _gsCoo1(gsCoo1,gsCoo1+12);
+  std::vector<double> _wg1(wg1,wg1+6);
+  //
+  MEDCouplingUMesh *m=build2DTargetMesh_1();
+  MEDCouplingFieldDouble *f=MEDCouplingFieldDouble::New(ON_GAUSS_PT,NO_TIME);
+  f->setMesh(m);
+  CPPUNIT_ASSERT_EQUAL(0,f->getNbOfGaussLocalization());
+  f->setGaussLocalizationOnType(INTERP_KERNEL::NORM_TRI3,_refCoo1,_gsCoo1,_wg1);
+  CPPUNIT_ASSERT_THROW(f->setGaussLocalizationOnType(INTERP_KERNEL::NORM_QUAD4,_refCoo1,_gsCoo1,_wg1),INTERP_KERNEL::Exception);
+  CPPUNIT_ASSERT_EQUAL(1,f->getNbOfGaussLocalization());
+  const double refCoo2[8]={ 0.,0., 1.,0., 1.,1., 0.,1. };
+  std::vector<double> _refCoo2(refCoo2,refCoo2+8);
+  _gsCoo1.resize(4); _wg1.resize(2);
+  f->setGaussLocalizationOnType(INTERP_KERNEL::NORM_QUAD4,_refCoo2,_gsCoo1,_wg1);
+  CPPUNIT_ASSERT_EQUAL(2,f->getNbOfGaussLocalization());
+  DataArrayDouble *array=DataArrayDouble::New();
+  array->alloc(18,2);
+  double *ptr=array->getPointer();
+  for(int i=0;i<18*2;i++)
+    ptr[i]=(double)(i+1);
+  f->setArray(array);
+  f->setName("MyFirstFieldOnGaussPoint");
+  array->decrRef();
+  f->checkCoherency();
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(27.,f->getIJK(2,5,0),1e-14);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(16.,f->getIJK(1,5,1),1e-14);
+  //
+  f->clearGaussLocalizations();
+  CPPUNIT_ASSERT_EQUAL(0,f->getNbOfGaussLocalization());
+  CPPUNIT_ASSERT_THROW(f->checkCoherency(),INTERP_KERNEL::Exception);
+  int ids1[4]={0,1,3,4};
+  CPPUNIT_ASSERT_THROW(f->setGaussLocalizationOnCells(ids1,ids1+4,_refCoo2,_gsCoo1,_wg1),INTERP_KERNEL::Exception);
+  CPPUNIT_ASSERT_EQUAL(0,f->getNbOfGaussLocalization());
+  int ids2[2]={0,4};
+  f->setGaussLocalizationOnCells(ids2,ids2+2,_refCoo2,_gsCoo1,_wg1);
+  CPPUNIT_ASSERT_EQUAL(1,f->getNbOfGaussLocalization());
+  CPPUNIT_ASSERT_EQUAL(0,f->getGaussLocalizationIdOfOneCell(0));
+  CPPUNIT_ASSERT_THROW(f->getGaussLocalizationIdOfOneCell(1),INTERP_KERNEL::Exception);
+  int ids3[2]={1,2};
+  f->setGaussLocalizationOnCells(ids3,ids3+2,_refCoo1,_gsCoo1,_wg1);
+  CPPUNIT_ASSERT_EQUAL(2,f->getNbOfGaussLocalization());
+  CPPUNIT_ASSERT_EQUAL(0,f->getGaussLocalizationIdOfOneCell(0));
+  CPPUNIT_ASSERT_EQUAL(1,f->getGaussLocalizationIdOfOneCell(1));
+  CPPUNIT_ASSERT_EQUAL(1,f->getGaussLocalizationIdOfOneCell(2));
+  CPPUNIT_ASSERT_THROW(f->checkCoherency(),INTERP_KERNEL::Exception);//<- cell 3 has no localization
+  int ids4[1]={3};
+  std::vector<double> _gsCoo2(_gsCoo1);
+  std::vector<double> _wg2(_wg1);
+  _gsCoo2[0]=0.8888777776666; _wg2[0]=0.1234567892377;
+  f->setGaussLocalizationOnCells(ids4,ids4+1,_refCoo2,_gsCoo2,_wg2);
+  CPPUNIT_ASSERT_EQUAL(3,f->getNbOfGaussLocalization());
+  std::vector<int> tmpIds;
+  f->getCellIdsHavingGaussLocalization(0,tmpIds);
+  CPPUNIT_ASSERT_EQUAL(2,(int)tmpIds.size());
+  CPPUNIT_ASSERT(std::equal(ids2,ids2+2,tmpIds.begin()));
+  CPPUNIT_ASSERT_THROW(f->checkCoherency(),INTERP_KERNEL::Exception);//<- it's always not ok because undelying array not with the good size.
+  DataArrayDouble *array2=f->getArray()->substr(0,10);
+  f->setArray(array2);
+  array2->decrRef();
+  f->checkCoherency();//<- here it is OK
+  MEDCouplingFieldDouble *f2=f->clone(true);
+  CPPUNIT_ASSERT(f->isEqual(f2,1e-14,1e-14));
+  MEDCouplingGaussLocalization& gl1=f2->getGaussLocalization(0);
+  double tmp=gl1.getGaussCoord(1,1);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(2.07*_b-1,tmp,1e-14);
+  gl1.setGaussCoord(1,1,0.07);
+  CPPUNIT_ASSERT(!f->isEqual(f2,1e-14,1e-14));
+  gl1.setGaussCoord(1,1,tmp);
+  CPPUNIT_ASSERT(f->isEqual(f2,1e-14,1e-14));
+  f->decrRef();
+  f2->checkCoherency();
+  //
+  f2->decrRef();
+  m->decrRef();
+}
+
+void MEDCouplingBasicsTest::testGaussPointNEField1()
+{
+  MEDCouplingUMesh *m=build2DTargetMesh_1();
+  MEDCouplingFieldDouble *f=MEDCouplingFieldDouble::New(ON_GAUSS_NE,NO_TIME);
+  f->setMesh(m);
+  f->setName("MyFirstFieldOnNE");
+  f->setDescription("MyDescriptionNE");
+  DataArrayDouble *array=DataArrayDouble::New();
+  array->alloc(18,2);
+  double *ptr=array->getPointer();
+  for(int i=0;i<18*2;i++)
+    ptr[i]=(double)(i+7);
+  f->setArray(array);
+  array->decrRef();
+  //
+  f->checkCoherency();
+  MEDCouplingFieldDouble *f2=f->clone(true);
+  CPPUNIT_ASSERT(f->isEqual(f2,1e-14,1e-14));
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(21.,f->getIJK(2,0,0),1e-14);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(18.,f->getIJK(1,1,1),1e-14);
+  f2->decrRef();
+  //
+  f->decrRef();
+  m->decrRef();
+}
+
+void MEDCouplingBasicsTest::testCellOrientation1()
+{
+  MEDCouplingUMesh *m=build2DTargetMesh_1();
+  double vec[3]={0.,0.,1.};
+  std::vector<int> res1;
+  CPPUNIT_ASSERT_THROW(m->are2DCellsNotCorrectlyOriented(vec,false,res1),INTERP_KERNEL::Exception);
+  m->changeSpaceDimension(3);
+  res1.clear();
+  m->are2DCellsNotCorrectlyOriented(vec,false,res1);
+  CPPUNIT_ASSERT(res1.empty());
+  vec[2]=-1;
+  m->are2DCellsNotCorrectlyOriented(vec,false,res1);
+  CPPUNIT_ASSERT_EQUAL(5,(int)res1.size());
+  res1.clear();
+  //
+  vec[2]=1.;
+  // connectivity inversion
+  int *conn=m->getNodalConnectivity()->getPointer();
+  int tmp=conn[11];
+  conn[11]=conn[12];
+  conn[12]=tmp;
+  m->are2DCellsNotCorrectlyOriented(vec,false,res1);
+  CPPUNIT_ASSERT_EQUAL(1,(int)res1.size());
+  CPPUNIT_ASSERT_EQUAL(2,res1[0]);
+  res1.clear();
+  m->orientCorrectly2DCells(vec,false);
+  m->are2DCellsNotCorrectlyOriented(vec,false,res1);
+  CPPUNIT_ASSERT(res1.empty());
+  MEDCouplingUMesh *m2=build2DTargetMesh_1();
+  m2->changeSpaceDimension(3);
+  CPPUNIT_ASSERT(m->isEqual(m2,1e-12));
+  m2->decrRef();
+  //
+  m->decrRef();
+}
+
+void MEDCouplingBasicsTest::testCellOrientation2()
+{
+  MEDCouplingUMesh *m1=0;
+  MEDCouplingUMesh *m2=build3DExtrudedUMesh_1(m1);
+  m1->decrRef();
+  std::vector<int> res1;
+  m2->arePolyhedronsNotCorrectlyOriented(res1);
+  CPPUNIT_ASSERT_EQUAL(6,(int)res1.size());
+  m2->orientCorrectlyPolyhedrons();
+  res1.clear();
+  m2->arePolyhedronsNotCorrectlyOriented(res1);
+  CPPUNIT_ASSERT(res1.empty());
+  m2->checkCoherency();
+  CPPUNIT_ASSERT_EQUAL(18,m2->getNumberOfCells());
+  int cellIds[3]={0,6,12};
+  std::vector<int> cellIds2(cellIds,cellIds+3);
+  m2->convertToPolyTypes(cellIds2);
+  m2->orientCorrectlyPolyhedrons();
+  res1.clear();
+  m2->arePolyhedronsNotCorrectlyOriented(res1);
+  CPPUNIT_ASSERT(res1.empty());
+  MEDCouplingFieldDouble *f2=m2->getMeasureField(false);
+  //Test to check global reverse in MEDCouplingUMesh::tryToCorrectPolyhedronOrientation
+  MEDCouplingUMesh *m3=build2DTargetMesh_1();
+  double vec[3]={0.,0.,-1.};//<- important for the test
+  m3->changeSpaceDimension(3);
+  const int ids1[5]={0,1,2,3,4};
+  std::vector<int> ids2(ids1,ids1+5);
+  m3->convertToPolyTypes(ids2);
+  m3->orientCorrectly2DCells(vec,false);
+  MEDCouplingUMesh *m4=buildCU1DMesh_U();
+  m4->changeSpaceDimension(3);
+  double center[3]={0.,0.,0.};
+  double vector[3]={0.,1.,0.};
+  m4->rotate(center,vector,-M_PI/2.);
+  MEDCouplingUMesh *m5=m3->buildExtrudedMeshFromThis(m4,0);
+  res1.clear();
+  m5->arePolyhedronsNotCorrectlyOriented(res1);
+  CPPUNIT_ASSERT_EQUAL(15,(int)res1.size());
+  m5->orientCorrectlyPolyhedrons();
+  res1.clear();
+  m5->arePolyhedronsNotCorrectlyOriented(res1);
+  CPPUNIT_ASSERT(res1.empty());
+  MEDCouplingFieldDouble *f3=m5->getMeasureField(false);
+  CPPUNIT_ASSERT_EQUAL(15,f3->getArray()->getNumberOfTuples());
+  CPPUNIT_ASSERT_EQUAL(1,f3->getNumberOfComponents());
+  const double *f3Ptr=f3->getArray()->getConstPointer();
+  const double expected1[15]={
+    0.075,0.0375,0.0375,0.075,0.075,
+    0.1125,0.05625,0.05625,0.1125,0.1125,
+    0.0625,0.03125,0.03125,0.0625,0.0625
+  };
+  for(int i=0;i<15;i++)
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(std::abs(expected1[i]),f3Ptr[i],1e-12);
+  f3->decrRef();
+  DataArrayDouble *f4=m5->getBarycenterAndOwner();
+  CPPUNIT_ASSERT_EQUAL(15,f4->getNumberOfTuples());
+  CPPUNIT_ASSERT_EQUAL(3,f4->getNumberOfComponents());
+  const double *f4Ptr=f4->getConstPointer();
+  const double expected2[45]={
+    -0.05,-0.05,0.15, 0.3666666666666667,-0.13333333333333333,0.15, 0.53333333333333333,0.033333333333333333,0.15, -0.05,0.45,0.15, 0.45,0.45,0.15,
+    -0.05,-0.05,0.525, 0.3666666666666667,-0.13333333333333333,0.525, 0.53333333333333333,0.033333333333333333,0.525, -0.05,0.45,0.525, 0.45,0.45,0.525,
+    -0.05,-0.05,0.875, 0.3666666666666667,-0.13333333333333333,0.875, 0.53333333333333333,0.033333333333333333,0.875, -0.05,0.45,0.875, 0.45,0.45,0.875
+  };
+  for(int i=0;i<45;i++)
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(expected2[i],f4Ptr[i],1e-12);
+  f4->decrRef();
+  m5->decrRef();
+  m3->decrRef();
+  m4->decrRef();
+  //
+  f2->decrRef();
+  m2->decrRef();
+}
+
+/*!
+ * This test check polyhedron true barycenter computation. 
+ */
+void MEDCouplingBasicsTest::testPolyhedronBarycenter()
+{
+  int connN[]={0,3,2,1, -1, 4,5,6,7, -1, 0,4,7,3, -1, 3,7,6,2, -1, 2,6,5,1, -1, 1,5,4,0};
+  double coords[]={0.,0.,0., 1.,0.,0., 1.,1.,0., 0.,1.,0., 0.,0.,1., 1.,0.,1., 1.,1.,1., 0.,1.,1., 0.5, 0.5, 0.5};
+  MEDCouplingUMesh *meshN=MEDCouplingUMesh::New();
+  meshN->setName("ForBary");
+  meshN->setMeshDimension(3);
+  meshN->allocateCells(4);
+  meshN->insertNextCell(INTERP_KERNEL::NORM_POLYHED,29,connN);
+  meshN->finishInsertingCells();
+  DataArrayDouble *myCoords=DataArrayDouble::New();
+  myCoords->alloc(9,3);
+  std::copy(coords,coords+27,myCoords->getPointer());
+  meshN->setCoords(myCoords);
+  myCoords->decrRef();
+  meshN->checkCoherency();
+  //
+  std::vector<int> res1;
+  meshN->arePolyhedronsNotCorrectlyOriented(res1);
+  meshN->orientCorrectlyPolyhedrons();
+  CPPUNIT_ASSERT(res1.empty());
+  const double *ref,*daPtr;
+  DataArrayDouble *da=meshN->getBarycenterAndOwner();
+  CPPUNIT_ASSERT_EQUAL(1,da->getNumberOfTuples());
+  CPPUNIT_ASSERT_EQUAL(3,da->getNumberOfComponents());
+  daPtr=da->getConstPointer();
+  ref=meshN->getCoords()->getConstPointer()+24;
+  for(int i=0;i<3;i++)
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(ref[i],daPtr[i],1e-12);
+  da->decrRef();
+  //
+  const double center[]={0.,0.,0.};
+  const double vec[]={0.,2.78,0.};
+  da=meshN->getBarycenterAndOwner();
+  daPtr=da->getConstPointer();
+  ref=meshN->getCoords()->getConstPointer()+24;
+  for(int i=0;i<3;i++)
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(ref[i],daPtr[i],1e-12);
+  da->decrRef();
+  //
+  meshN->rotate(center,vec,M_PI/7.);
+  meshN->translate(vec);
+  da=meshN->getBarycenterAndOwner();
+  daPtr=da->getConstPointer();
+  ref=meshN->getCoords()->getConstPointer()+24;
+  for(int i=0;i<3;i++)
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(ref[i],daPtr[i],1e-12);
+  da->decrRef();
+  //
+  const double center2[]={1.12,3.45,6.78};
+  const double vec2[]={4.5,9.3,2.8};
+  meshN->rotate(center2,vec2,M_E);
+  meshN->translate(vec2);
+  da=meshN->getBarycenterAndOwner();
+  daPtr=da->getConstPointer();
+  ref=meshN->getCoords()->getConstPointer()+24;
+  for(int i=0;i<3;i++)
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(ref[i],daPtr[i],1e-10);
+  da->decrRef();
+  //
+  meshN->decrRef();
+}
+
+void MEDCouplingBasicsTest::testNormL12Integ1D()
+{
+  MEDCouplingUMesh *m1=build1DTargetMesh_3();
+  MEDCouplingFieldDouble *f1=MEDCouplingFieldDouble::New(ON_CELLS,NO_TIME);
+  f1->setMesh(m1);
+  DataArrayDouble *array=DataArrayDouble::New();
+  array->alloc(m1->getNumberOfCells(),3);
+  const double arr[12]={-5.23,15.45,-25.56,6.67,-16.78,26.89,-7.91,17.23,-27.43,8.21,-18.63,28.72};
+  std::copy(arr,arr+12,array->getPointer());
+  f1->setArray(array);
+  array->decrRef();
+  //
+  const double *ptr;
+  DataArrayDouble *f3=m1->getBarycenterAndOwner();
+  CPPUNIT_ASSERT_EQUAL(4,f3->getNumberOfTuples());
+  CPPUNIT_ASSERT_EQUAL(1,f3->getNumberOfComponents());
+  double expected9[4]={0.75,5.105,0.8,5.155};
+  ptr=f3->getConstPointer();
+   for(int i=0;i<4;i++)
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(expected9[i],ptr[i],1e-12);
+  f3->decrRef();
+  //
+  MEDCouplingFieldDouble *f2=m1->getMeasureField(false);
+  CPPUNIT_ASSERT_EQUAL(4,f2->getArray()->getNumberOfTuples());
+  CPPUNIT_ASSERT_EQUAL(1,f2->getNumberOfComponents());
+  double expected1[4]={0.5,0.21,-0.6,-0.31};
+  ptr=f2->getArray()->getConstPointer();
+  for(int i=0;i<4;i++)
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(expected1[i],ptr[i],1e-12);
+  f2->decrRef();
+  double expected2[4]={0.5,0.21,0.6,0.31};
+  f2=m1->getMeasureField(true);
+  ptr=f2->getArray()->getConstPointer();
+  for(int i=0;i<4;i++)
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(expected2[i],ptr[i],1e-12);
+  f2->decrRef();
+  //integral
+  double res[3];
+  f1->integral(false,res);
+  double expected3[3]={0.9866,-0.3615,0.4217};
+  for(int i=0;i<3;i++)
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(expected3[i],res[i],1e-12);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(expected3[0],f1->integral(0,false),1e-12);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(expected3[1],f1->integral(1,false),1e-12);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(expected3[2],f1->integral(2,false),1e-12);
+  f1->integral(true,res);
+  double expected4[3]={-3.4152,8.7639,-14.6879};
+  for(int i=0;i<3;i++)
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(expected4[i],res[i],1e-12);
+  //normL1
+  f1->normL1(res);
+  double expected5[3]={11.3068,27.3621,43.7881};
+  for(int i=0;i<3;i++)
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(expected5[i],res[i],1e-12);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(expected5[0],f1->normL1(0),1e-12);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(expected5[1],f1->normL1(1),1e-12);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(expected5[2],f1->normL1(2),1e-12);
+  //normL2
+  f1->normL2(res);
+  double expected7[3]={9.0252562290496776, 21.545259176904789, 34.433193070059595};
+  for(int i=0;i<3;i++)
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(expected7[i],res[i],1e-9);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(expected7[0],f1->normL2(0),1e-9);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(expected7[1],f1->normL2(1),1e-9);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(expected7[2],f1->normL2(2),1e-9);
+  //buildWeightingField
+  MEDCouplingFieldDouble *f4=f1->buildWeightingField(false);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(-0.2,f4->accumulate(0),1e-12);
+  f4->decrRef();
+  f4=f1->buildWeightingField(true);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(1.62,f4->accumulate(0),1e-12);
+  f4->decrRef();
+  //
+  f1->decrRef();
+  m1->decrRef();
+  // Testing with 2D Curve
+  m1=build2DCurveTargetMesh_3();
+  f2=m1->getMeasureField(false);
+  CPPUNIT_ASSERT_EQUAL(4,f2->getArray()->getNumberOfTuples());
+  CPPUNIT_ASSERT_EQUAL(1,f2->getNumberOfComponents());
+  ptr=f2->getArray()->getConstPointer();
+  for(int i=0;i<4;i++)
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(sqrt(2.)*expected2[i],ptr[i],1e-12);
+  f2->decrRef();
+  f2=m1->getMeasureField(true);
+  CPPUNIT_ASSERT_EQUAL(4,f2->getArray()->getNumberOfTuples());
+  CPPUNIT_ASSERT_EQUAL(1,f2->getNumberOfComponents());
+  ptr=f2->getArray()->getConstPointer();
+  for(int i=0;i<4;i++)
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(expected2[i]*sqrt(2.),ptr[i],1e-12);
+  f2->decrRef();
+  //bary
+  f3=m1->getBarycenterAndOwner();
+  CPPUNIT_ASSERT_EQUAL(4,f3->getNumberOfTuples());
+  CPPUNIT_ASSERT_EQUAL(2,f3->getNumberOfComponents());
+  double expected10[8]={0.75,0.75,5.105,5.105,0.8,0.8,5.155,5.155};
+  ptr=f3->getConstPointer();
+   for(int i=0;i<8;i++)
+     CPPUNIT_ASSERT_DOUBLES_EQUAL(expected10[i],ptr[i],1e-12);
+  f3->decrRef();
+  //
+  f1=MEDCouplingFieldDouble::New(ON_CELLS,NO_TIME);
+  f1->setMesh(m1);
+  array=DataArrayDouble::New();
+  array->alloc(m1->getNumberOfCells(),3);
+  std::copy(arr,arr+12,array->getPointer());
+  f1->setArray(array);
+  array->decrRef();
+  f1->integral(false,res);
+  for(int i=0;i<3;i++)
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(sqrt(2.)*expected4[i],res[i],1e-12);
+  f1->integral(true,res);
+  for(int i=0;i<3;i++)
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(sqrt(2.)*expected4[i],res[i],1e-12);
+  f1->normL1(res);
+  for(int i=0;i<3;i++)
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(sqrt(2.)*expected5[i],res[i],1e-12);
+  f1->normL2(res);
+  for(int i=0;i<3;i++)
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(sqrt(sqrt(2.))*expected7[i],res[i],1e-12);
+  //
+  f1->decrRef();
+  m1->decrRef();
+}
+
+void MEDCouplingBasicsTest::testAreaBary2D()
+{
+  MEDCouplingUMesh *m1=build2DTargetMesh_3();
+  MEDCouplingFieldDouble *f1=m1->getMeasureField(false);
+  CPPUNIT_ASSERT_EQUAL(10,f1->getArray()->getNumberOfTuples());
+  CPPUNIT_ASSERT_EQUAL(1,f1->getNumberOfComponents());
+  double expected1[10]={-0.5,-1,-1.5,-0.5,-1,  0.5,1,1.5,0.5,1};
+  const double *ptr=f1->getArray()->getConstPointer();
+  for(int i=0;i<10;i++)
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(expected1[i],ptr[i],1e-12);
+  f1->decrRef();
+  f1=m1->getMeasureField(true);
+  ptr=f1->getArray()->getConstPointer();
+  for(int i=0;i<10;i++)
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(std::abs(expected1[i]),ptr[i],1e-12);
+  f1->decrRef();
+  DataArrayDouble *f2=m1->getBarycenterAndOwner();
+  CPPUNIT_ASSERT_EQUAL(10,f2->getNumberOfTuples());
+  CPPUNIT_ASSERT_EQUAL(2,f2->getNumberOfComponents());
+  double expected2[20]={
+    0.5,0.3333333333333333,0.5,0.5,0.5,0.77777777777777777,0.5,0.3333333333333333,0.5,0.5,
+    0.5,0.3333333333333333,0.5,0.5,0.5,0.77777777777777777,0.5,0.3333333333333333,0.5,0.5,
+  };
+  ptr=f2->getConstPointer();
+  for(int i=0;i<20;i++)
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(expected2[i],ptr[i],1e-12);
+  f2->decrRef();
+  m1->changeSpaceDimension(3);
+  f1=m1->getMeasureField(false);
+  CPPUNIT_ASSERT_EQUAL(10,f1->getArray()->getNumberOfTuples());
+  CPPUNIT_ASSERT_EQUAL(1,f1->getNumberOfComponents());
+  ptr=f1->getArray()->getConstPointer();
+  for(int i=0;i<10;i++)
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(std::abs(expected1[i]),ptr[i],1e-12);
+  f1->decrRef();
+  f2=m1->getBarycenterAndOwner();
+  CPPUNIT_ASSERT_EQUAL(10,f2->getNumberOfTuples());
+  CPPUNIT_ASSERT_EQUAL(3,f2->getNumberOfComponents());
+  ptr=f2->getConstPointer();
+  double expected3[30]={
+    0.5,0.3333333333333333,0.,0.5,0.5,0.,0.5,0.77777777777777777,0.,0.5,0.3333333333333333,0.,0.5,0.5,0.,
+    0.5,0.3333333333333333,0.,0.5,0.5,0.,0.5,0.77777777777777777,0.,0.5,0.3333333333333333,0.,0.5,0.5,0.
+  };
+  for(int i=0;i<30;i++)
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(expected3[i],ptr[i],1e-12);
+  f2->decrRef();
+  m1->decrRef();
+}
+
+/*!
+ * This test check polyhedron true barycenter computation 2. 
+ */
+void MEDCouplingBasicsTest::testAreaBary3D()
+{
+  double coords [] = { 0.241310763507 , 0.0504777305619 , 0.0682283524903 , 0.252501053866 , -0.0625176732937 , 0.137272639894 ,
+                       0.152262663601 , 0.241816569527 , 0.133812556197 , 0.18047750211 , -0.0789949051358 , 0.339098173401 ,
+                       0.151741971857 , 0.238885278571 , 0.137715037333 , 0.242532155481 , -0.0928169086456 , 0.0678043417367 ,
+                       0.240941965335 , -0.015461491464 , 0.0617186345825 , 0.24127650112 , 0.0499427876717 , 0.0679634099148 ,
+                       -0.145828917428 , 0.206291632565 , 0.0310071927543 , 0.0125651775307 , 0.266262085828 , 0.105228430543 ,
+                       -0.0994066533286 , 0.233224271238 , 0.0572213839567 , -0.0951345338317 , 0.234819509426 , 0.0592126284538 ,
+                       0.136580574205 , -0.205486212579 , 0.0572866072014 , 0.0637270784978 , -0.168886355238 , 0.446614057077 ,
+                       0.041337157151 , -0.213402568198 , 0.372407095999 , 0.0411601970268 , -0.202387875756 , 0.411334979491 ,
+                       -0.108355701857 , 0.193636239335 , 0.204886756738 , 0.00639779029829 , 0.155296981517 , 0.252585892979 ,
+                       0.0262473111702 , -0.112919732543 , 0.424286639249 ,-0.224103052733 , -0.139430015438 , -0.0122352295701 ,
+                       -0.0312760589481 , -0.274272003594 , 0.0323959636568 , -0.166663422532 , -0.217754445175 , 0.00392109070364 ,
+                       -0.30586619777 , -0.0475168041091 , -0.0144585228182 , -0.280881480586 , 0.135571293538 , 0.00623923647986 ,
+                       -0.25548538234 , 0.156819217766 , 0.0645277879769 , -0.131567009284 , 0.184133752309 , 0.206021802753 ,
+                       -0.196204010965 , 0.151602971681 , 0.212974777736 , -0.183713879463 , 0.0802946639531 , 0.260115662599 ,
+                       -0.244241178767 , -0.0738873389604 , 0.144590565817 , -0.155804057829 , -0.164892720025 , 0.210613950558 ,
+                       -0.170950800428 , -0.215099334026 , 0.00610122860092 , -0.30552634869 , -0.0490020791904 , -0.0132786533145 ,
+                       0.271831011884 , 0.15105657296 , 0.0230534827908 , 0.281919192283 , 0.0898544306288 , -0.0625201489143 ,
+                       0.260240727276 , -0.0120688706637 , -0.0532316588626 , 0.244947737722 , 0.0197984684293 , 0.0309341209233 ,
+                       0.23439631578 , 0.229825279875 , 0.0508520585381 , 0.160921316875 , 0.265078502128 , 0.121716560626 ,
+                       -0.315088694175 , 0.0747700471918 , -0.245836615071 , -0.327728781776 , 0.0857114674649 , -0.239431905957 ,
+                       -0.308385460634 , 0.145142997084 , -0.149886828433 , 0.0488236045164 , 0.309462801914 , 0.0849169148265 ,
+                       -0.0244964803395 , 0.33145611751 , -0.0476415818061 , 0.0060567994229 , 0.32418412014 , 0.0367779543812 ,
+                       -0.0950221448063 , 0.236675326003 , 0.0572594453983 , 0.248723023186 , 0.0886648784791 , -0.176629430538 ,
+                       0.116796984 , 0.256596599567 , -0.292863523603 , 0.118024552914 , 0.229154257843 , -0.34233232501 ,
+                       0.217507892549 , -0.0417822335742 , -0.176771782888 , -0.224429321304 , 0.0125595300114 , -0.362064725588 ,
+                       0.0937301100955 , -0.0500824832657 , -0.299713548444 , -0.244162220397 , 0.0383853931293 , -0.389856984411 ,
+                       -0.0281989366102 , 0.097392811563 , -0.458244577284 , -0.385010847162 , 0.10122766194 , -0.140052859922 ,
+                       -0.377936358012 , 0.110875172128 , -0.176207095463 , 0.244483045556 , -0.0991073977045 , 0.0575134372934 ,
+                       0.262605120167 , -0.100243191645 , -0.0495620806935 , 0.240306880972 , -0.136153701579 , -0.114745281696 ,
+                       0.215763176129 , -0.0836766059189 , -0.183249640616 , 0.237870396603 , -0.132449578286 , -0.121598854639 ,
+                       -0.0637683083097 , -0.27921020214 , -0.149112321992 , -0.0856211014977 , -0.2973233473 , -0.0446878139589 ,
+                       0.104675342288 , -0.0625908305324 , -0.290346256534 , 0.0248264249186 , -0.247797708548 , -0.165830884019 ,
+                       0.0719302438309 , -0.178468260473 , -0.211432157345 , 0.142871843159 , -0.208769948542 , 0.0454101128246 ,
+                       0.167803379307 , -0.207851396623 , -0.088802726124 , 0.12868717152 , -0.230920439715 , 0.00760508389036 ,
+                       -0.0372812069535 , -0.286740286332 , 0.00963701291166 };
+
+  int connN [] = { /*polyhedron 0*/
+    0 , 1 , 3 , 4 , 2 , -1 , 1 , 5 , 6 , 7 , 0 , -1 , 0 , 7 , 8 , 10 , 11 , 9 , 2 , -1 , 1 , 5 , 12 , 14 , 15 , 13 , 3 , -1 , 16 , 9 , 2 , 4 , 17 , -1
+    , 4 , 3 , 13 , 18 , 17 , -1 , 5 , 6 , 19 , 21 , 20 , 12 , -1 , 6 , 7 , 8 , 23 , 22 , 19 , -1 , 23 , 24 , 10 , 8 , -1 , 25 , 11 , 9 , 16 , -1
+    , 24 , 26 , 25 , 11 , 10 , -1 , 12 , 14 , 20 , -1 , 27 , 28 , 29 , 15 , 13 , 18 , -1 , 14 , 15 , 29 , 30 , 21 , 20 , -1 , 26 , 27 , 18 , 17 , 16 , 25 , -1
+    , 22 , 19 , 21 , 30 , 31 , -1 , 22 , 31 , 28 , 27 , 26 , 24 , 23 , -1 , 31 , 30 , 29 , 28,
+    /* polyhedron 1*/
+    0 , 7 , 8 , 10 , 11 , 9 , 2 , -1 , 32 , 0 , 7 , 35 , 34 , 33 , -1 , 32 , 0 , 2 , 37 , 36 , -1 , 35 , 7 , 8 , 40 , 39 , 38 , -1
+    , 2 , 37 , 41 , 9 , -1 , 40 , 8 , 10 , 44 , 43 , 42 , -1 , 41 , 9 , 11 , 44 , 43 , -1 , 44 , 11 , 10 , -1 , 32 , 33 , 45 , 47 , 46 , 36 , -1
+    , 33 , 34 , 48 , 45 , -1 , 35 , 34 , 48 , 50 , 49 , 38 , -1 , 41 , 43 , 42 , 46 , 36 , 37 , -1 , 38 , 39 , 51 , 49 , -1
+    , 39 , 40 , 42 , 46 , 47 , 52 , 51 , -1 , 45 , 47 , 52 , 50 , 48 , -1 , 52 , 51 , 49 , 50,
+    /* polyhedron 2*/
+    6 , 7 , 8 , 23 , 22 , 19 , -1 , 6 , 35 , 7 , -1 , 6 , 35 , 38 , 19 , -1 , 35 , 7 , 8 , 40 , 39 , 38 , -1 , 53 , 22 , 19 , 38 , 39 , 54 , -1
+    , 23 , 53 , 54 , 40 , 8 , -1 , 53 , 22 , 23 , -1 , 39 , 54 , 40,
+    /*polyhedron 3*/
+    35 , 34 , 48 , 50 , 49 , 38 , -1 , 6 , 35 , 34 , 56 , 55 , 5 , -1 , 6 , 35 , 38 , 19 , -1 , 34 , 56 , 57 , 59 , 58 , 48 , -1
+    , 60 , 61 , 21 , 19 , 38 , 49 , -1 , 62 , 50 , 48 , 58 , -1 , 60 , 63 , 64 , 62 , 50 , 49 , -1 , 5 , 6 , 19 , 21 , 20 , 12 , -1
+    , 55 , 5 , 12 , 65 , -1 , 66 , 67 , 65 , 55 , 56 , 57 , -1 , 63 , 66 , 57 , 59 , 64 , -1 , 64 , 62 , 58 , 59 , -1
+    , 60 , 63 , 66 , 67 , 68 , 61 , -1 , 61 , 68 , 20 , 21 , -1 , 67 , 68 , 20 , 12 , 65};
+
+  double barys[]={ -0.0165220465527 , -0.0190922868195 , 0.158882733414 ,
+                   0.0287618656076 , 0.135874379934 , -0.14601588119 ,
+                   -0.147128055553 , 0.0465995097041 , -0.049391174453 ,
+                   -0.00142506732317 , -0.0996953090351 , -0.115159183132 };
+  MEDCouplingUMesh *meshN=MEDCouplingUMesh::New();
+  meshN->setName("ForBary");
+  meshN->setMeshDimension(3);
+  meshN->allocateCells(4);
+  meshN->insertNextCell(INTERP_KERNEL::NORM_POLYHED,113,connN);
+  meshN->insertNextCell(INTERP_KERNEL::NORM_POLYHED,99,connN+113);
+  meshN->insertNextCell(INTERP_KERNEL::NORM_POLYHED,43,connN+212);
+  meshN->insertNextCell(INTERP_KERNEL::NORM_POLYHED,92,connN+255);
+  meshN->finishInsertingCells();
+  DataArrayDouble *myCoords=DataArrayDouble::New();
+  myCoords->alloc(69,3);
+  std::copy(coords,coords+207,myCoords->getPointer());
+  meshN->setCoords(myCoords);
+  myCoords->decrRef();
+  meshN->checkCoherency();
+  std::vector<int> res1;
+  meshN->arePolyhedronsNotCorrectlyOriented(res1);
+  meshN->orientCorrectlyPolyhedrons();
+  res1.clear();
+  meshN->arePolyhedronsNotCorrectlyOriented(res1);
+  CPPUNIT_ASSERT(res1.empty());
+  //
+  DataArrayDouble *da=meshN->getBarycenterAndOwner();
+  CPPUNIT_ASSERT_EQUAL(4,da->getNumberOfTuples());
+  CPPUNIT_ASSERT_EQUAL(3,da->getNumberOfComponents());
+  const double *daPtr=da->getConstPointer();
+  for(int i=0;i<12;i++)
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(barys[i],daPtr[i],1e-12);
+  da->decrRef();
+  //
+  meshN->decrRef();
+}
+
+void MEDCouplingBasicsTest::testRenumberCellsForFields()
+{
+  MEDCouplingUMesh *m=build2DTargetMesh_1();
+  MEDCouplingFieldDouble *f=MEDCouplingFieldDouble::New(ON_CELLS,NO_TIME);
+  f->setMesh(m);
+  DataArrayDouble *arr=DataArrayDouble::New();
+  int nbOfCells=m->getNumberOfCells();
+  arr->alloc(nbOfCells,3);
+  f->setArray(arr);
+  arr->decrRef();
+  const double values1[15]={7.,107.,10007.,8.,108.,10008.,9.,109.,10009.,10.,110.,10010.,11.,111.,10011.};
+  std::copy(values1,values1+15,arr->getPointer());
+  const int renumber1[5]={3,1,0,4,2};
+  double res[3];
+  const double loc[]={-0.05,-0.05, 0.55,-0.25, 0.55,0.15, -0.05,0.45, 0.45,0.45};
+  for(int j=0;j<5;j++)
+    {
+      f->getValueOn(loc+2*j,res);
+      for(int i=0;i<3;i++)
+        CPPUNIT_ASSERT_DOUBLES_EQUAL(values1[i+3*j],res[i],1e-12);
+    }
+  f->renumberCells(renumber1,false);
+  const double *ptr=f->getArray()->getConstPointer();
+  const double expected1[15]={9.,109.,10009.,8.,108.,10008.,11.,111.,10011.,7.,107.,10007.,10.,110.,10010.};
+  for(int i=0;i<15;i++)
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(expected1[i],ptr[i],1e-12);
+  //check that fields remains the same geometrically
+  for(int j=0;j<5;j++)
+    {
+      f->getValueOn(loc+2*j,res);
+      for(int i=0;i<3;i++)
+        CPPUNIT_ASSERT_DOUBLES_EQUAL(values1[i+3*j],res[i],1e-12);
+    }
+  f->decrRef();
+  //On gauss
+  f=MEDCouplingFieldDouble::New(ON_GAUSS_PT,NO_TIME);
+  f->setMesh(m);
+  const double _a=0.446948490915965;
+  const double _b=0.091576213509771;
+  const double _p1=0.11169079483905;
+  const double _p2=0.0549758718227661;
+  const double refCoo1[6]={ 0.,0., 1.,0., 0.,1. };
+  const double gsCoo1[12]={ 2*_b-1, 1-4*_b, 2*_b-1, 2.07*_b-1, 1-4*_b,
+                            2*_b-1, 1-4*_a, 2*_a-1, 2*_a-1, 1-4*_a, 2*_a-1, 2*_a-1 };
+  const double wg1[6]={ 4*_p2, 4*_p2, 4*_p2, 4*_p1, 4*_p1, 4*_p1 };
+  std::vector<double> _refCoo1(refCoo1,refCoo1+6);
+  std::vector<double> _gsCoo1(gsCoo1,gsCoo1+12);
+  std::vector<double> _wg1(wg1,wg1+6);
+  f->setGaussLocalizationOnType(INTERP_KERNEL::NORM_TRI3,_refCoo1,_gsCoo1,_wg1);
+  const double refCoo2[8]={ 0.,0., 1.,0., 1.,1., 0.,1. };
+  std::vector<double> _refCoo2(refCoo2,refCoo2+8);
+  _gsCoo1.resize(4); _wg1.resize(2);
+  f->setGaussLocalizationOnType(INTERP_KERNEL::NORM_QUAD4,_refCoo2,_gsCoo1,_wg1);
+  arr=DataArrayDouble::New();
+  arr->alloc(18,2);
+  const double values2[36]={1.,1001.,2.,1002., 11.,1011.,12.,1012.,13.,1013.,14.,1014.,15.,1015.,16.,1016., 21.,1021.,22.,1022.,23.,1023.,24.,1024.,25.,1025.,26.,1026., 31.,1031.,32.,1032., 41.,1041.,42.,1042.};
+  std::copy(values2,values2+36,arr->getPointer());
+  f->setArray(arr);
+  arr->decrRef();
+  f->checkCoherency();
+  MEDCouplingFieldDouble *fCpy=f->clone(true);
+  CPPUNIT_ASSERT(f->isEqual(fCpy,1e-12,1e-12));
+  f->renumberCells(renumber1,false);
+  CPPUNIT_ASSERT(!f->isEqual(fCpy,1e-12,1e-12));
+  double expected2[36]={21.,1021.,22.,1022.,23.,1023.,24.,1024.,25.,1025.,26.,1026., 11.,1011.,12.,1012.,13.,1013.,14.,1014.,15.,1015.,16.,1016., 41.,1041.,42.,1042., 1.,1001.,2.,1002., 31.,1031.,32.,1032.};
+  ptr=f->getArray()->getConstPointer();
+  for(int i=0;i<36;i++)
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(expected2[i],ptr[i],1e-12);
+  const int renumber2[5]={2,1,4,0,3};//reverse renumber1
+  f->renumberCells(renumber2,false);
+  CPPUNIT_ASSERT(f->isEqual(fCpy,1e-12,1e-12));
+  fCpy->decrRef();
+  f->decrRef();
+  //GaussNE
+  f=MEDCouplingFieldDouble::New(ON_GAUSS_NE,NO_TIME);
+  f->setMesh(m);
+  arr=DataArrayDouble::New();
+  arr->alloc(18,2);
+  const double values3[36]={1.,1001.,2.,1002.,3.,1003.,4.,1004., 11.,1011.,12.,1012.,13.,1013., 21.,1021.,22.,1022.,23.,1023., 31.,1031.,32.,1032.,33.,1033.,34.,1034., 41.,1041.,42.,1042.,43.,1043.,44.,1044.};
+  std::copy(values3,values3+36,arr->getPointer());
+  f->setArray(arr);
+  arr->decrRef();
+  f->checkCoherency();
+  fCpy=f->clone(true);
+  CPPUNIT_ASSERT(f->isEqual(fCpy,1e-12,1e-12));
+  f->renumberCells(renumber1,false);
+  CPPUNIT_ASSERT(!f->isEqual(fCpy,1e-12,1e-12));
+  double expected3[36]={21.,1021.,22.,1022.,23.,1023.,11.,1011.,12.,1012.,13.,1013.,41.,1041.,42.,1042.,43.,1043.,44.,1044.,1.,1001.,2.,1002.,3.,1003.,4.,1004.,31.,1031.,32.,1032.,33.,1033.,34.,1034.};
+  ptr=f->getArray()->getConstPointer();
+  for(int i=0;i<36;i++)
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(expected3[i],ptr[i],1e-12);
+  f->renumberCells(renumber2,false);//perform reverse operation of renumbering to check that the resulting field is equal.
+  CPPUNIT_ASSERT(f->isEqual(fCpy,1e-12,1e-12));
+  fCpy->decrRef();
+  f->decrRef();
+  //
+  m->decrRef();
+}
+
+void MEDCouplingBasicsTest::testRenumberNodesForFields()
+{
+  MEDCouplingUMesh *m=build2DTargetMesh_1();
+  MEDCouplingFieldDouble *f=MEDCouplingFieldDouble::New(ON_NODES,NO_TIME);
+  f->setMesh(m);
+  DataArrayDouble *arr=DataArrayDouble::New();
+  int nbOfNodes=m->getNumberOfNodes();
+  arr->alloc(nbOfNodes,3);
+  f->setArray(arr);
+  arr->decrRef();
+  const double values1[27]={7.,107.,10007.,8.,108.,10008.,9.,109.,10009.,10.,110.,10010.,11.,111.,10011.,12.,112.,10012.,13.,113.,10013.,14.,114.,10014.,15.,115.,10015.};
+  std::copy(values1,values1+27,arr->getPointer());
+  f->checkCoherency();
+  const int renumber1[9]={0,4,1,3,5,2,6,7,8};
+  double res[3];
+  const double loc[]={0.5432,-0.2432, 0.5478,0.1528};
+  const double expected1[6]={9.0272, 109.0272, 10009.0272, 11.4124,111.4124,10011.4124};
+  for(int j=0;j<2;j++)
+    {
+      f->getValueOn(loc+2*j,res);
+      for(int i=0;i<3;i++)
+        CPPUNIT_ASSERT_DOUBLES_EQUAL(expected1[i+3*j],res[i],1e-12);
+    }
+  MEDCouplingFieldDouble *fCpy=f->clone(true);
+  CPPUNIT_ASSERT(f->isEqual(fCpy,1e-12,1e-12));
+  f->renumberNodes(renumber1);
+  CPPUNIT_ASSERT(!f->isEqual(fCpy,1e-12,1e-12));
+  for(int j=0;j<2;j++)
+    {
+      f->getValueOn(loc+2*j,res);
+      for(int i=0;i<3;i++)
+        CPPUNIT_ASSERT_DOUBLES_EQUAL(expected1[i+3*j],res[i],1e-12);
+    }
+  const double expected2[27]={7.,107.,10007.,9.,109.,10009.,12.,112.,10012.,10.,110.,10010.,8.,108.,10008.,11.,111.,10011.,13.,113.,10013.,14.,114.,10014.,15.,115.,10015.};
+  for(int i=0;i<27;i++)
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(expected2[i],f->getArray()->getConstPointer()[i],1e-12);
+  const int renumber2[9]={0,2,5,3,1,4,6,7,8};//reverse of renumber2
+  f->renumberNodes(renumber2);
+  CPPUNIT_ASSERT(f->isEqual(fCpy,1e-12,1e-12));
+  fCpy->decrRef();
+  //
+  m->decrRef();
+  f->decrRef();
+}
+
+void MEDCouplingBasicsTest::testConvertQuadraticCellsToLinear()
+{
+  MEDCouplingUMesh *mesh=build2DTargetMesh_3();
+  mesh->checkCoherency();
+  const std::set<INTERP_KERNEL::NormalizedCellType>& types=mesh->getAllTypes();
+  CPPUNIT_ASSERT_EQUAL(5,(int)types.size());
+  INTERP_KERNEL::NormalizedCellType expected1[5]={INTERP_KERNEL::NORM_POLYGON, INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4, INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QUAD8};
+  std::set<INTERP_KERNEL::NormalizedCellType> expected1Bis(expected1,expected1+5);
+  CPPUNIT_ASSERT(expected1Bis==types);
+  CPPUNIT_ASSERT(mesh->isPresenceOfQuadratic());
+  CPPUNIT_ASSERT_EQUAL(62,mesh->getMeshLength());
+  MEDCouplingFieldDouble *f1=mesh->getMeasureField(false);
+  //
+  mesh->convertQuadraticCellsToLinear();
+  CPPUNIT_ASSERT(!mesh->isPresenceOfQuadratic());
+  //
+  mesh->checkCoherency();
+  MEDCouplingFieldDouble *f2=mesh->getMeasureField(false);
+  CPPUNIT_ASSERT(f1->getArray()->isEqual(*f2->getArray(),1e-12));
+  CPPUNIT_ASSERT_EQUAL(48,mesh->getMeshLength());
+  const std::set<INTERP_KERNEL::NormalizedCellType>& types2=mesh->getAllTypes();
+  CPPUNIT_ASSERT_EQUAL(3,(int)types.size());
+  INTERP_KERNEL::NormalizedCellType expected2[3]={INTERP_KERNEL::NORM_POLYGON, INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4};
+  std::set<INTERP_KERNEL::NormalizedCellType> expected2Bis(expected2,expected2+3);
+  CPPUNIT_ASSERT(expected2Bis==types2);
+  //
+  f1->decrRef();
+  f2->decrRef();
+  mesh->decrRef();
+}
+
+void MEDCouplingBasicsTest::testCheckGeoEquivalWith()
+{
+  MEDCouplingUMesh *mesh1=build2DTargetMesh_3();
+  MEDCouplingUMesh *mesh2=build2DTargetMesh_3();
+  DataArrayInt *cellCor,*nodeCor;
+  //First test mesh1
+  mesh1->checkGeoEquivalWith(mesh1,0,1e-12,cellCor,nodeCor);//deepEqual
+  CPPUNIT_ASSERT(cellCor==0);
+  CPPUNIT_ASSERT(nodeCor==0);
+  mesh1->checkGeoEquivalWith(mesh1,1,1e-12,cellCor,nodeCor);//fastEqual
+  CPPUNIT_ASSERT(cellCor==0);
+  CPPUNIT_ASSERT(nodeCor==0);
+  mesh1->checkGeoEquivalWith(mesh1,10,1e-12,cellCor,nodeCor);//deepEqual with geo permutations
+  CPPUNIT_ASSERT(cellCor==0);
+  CPPUNIT_ASSERT(nodeCor==0);
+  //Second test mesh1 and mesh2 are 2 different meshes instance
+  mesh1->checkGeoEquivalWith(mesh2,0,1e-12,cellCor,nodeCor);//deepEqual
+  CPPUNIT_ASSERT(cellCor==0);
+  CPPUNIT_ASSERT(nodeCor==0);
+  mesh1->checkGeoEquivalWith(mesh2,1,1e-12,cellCor,nodeCor);//fastEqual
+  CPPUNIT_ASSERT(cellCor==0);
+  CPPUNIT_ASSERT(nodeCor==0);
+  mesh1->checkGeoEquivalWith(mesh2,10,1e-12,cellCor,nodeCor);//deepEqual with geo permutations
+  CPPUNIT_ASSERT(cellCor==0);
+  CPPUNIT_ASSERT(nodeCor==0);
+  //Third test : cell permutation by keeping the first the middle and the last as it is.
+  const int renum[]={0,2,1,3,4,5,6,8,7,9};
+  mesh2->renumberCells(renum,false);
+  CPPUNIT_ASSERT_THROW(mesh1->checkGeoEquivalWith(mesh2,0,1e-12,cellCor,nodeCor),INTERP_KERNEL::Exception);//deepEqual fails
+  CPPUNIT_ASSERT(cellCor==0);
+  CPPUNIT_ASSERT(nodeCor==0);
+  mesh1->checkGeoEquivalWith(mesh2,1,1e-12,cellCor,nodeCor);//fastEqual do not see anything
+  CPPUNIT_ASSERT(cellCor==0);
+  CPPUNIT_ASSERT(nodeCor==0);
+  mesh1->checkGeoEquivalWith(mesh2,10,1e-12,cellCor,nodeCor);//deepEqual with geo permutations
+  CPPUNIT_ASSERT(cellCor);
+  CPPUNIT_ASSERT_EQUAL(10,cellCor->getNumberOfTuples());
+  CPPUNIT_ASSERT_EQUAL(1,cellCor->getNumberOfComponents());
+  CPPUNIT_ASSERT(std::equal(renum,renum+10,cellCor->getConstPointer()));
+  CPPUNIT_ASSERT(nodeCor==0);
+  cellCor->decrRef();
+  cellCor=0;
+  CPPUNIT_ASSERT(nodeCor==0);
+  //4th test : cell and node permutation by keeping the first the middle and the last as it is.
+  mesh2->decrRef();
+  mesh2=build2DTargetMesh_3();
+  const int renum2[]={0,2,1,3,4,5,6,8,7,9,10};
+  mesh2->renumberCells(renum,false);
+  mesh2->renumberNodes(renum2,11);
+  CPPUNIT_ASSERT_THROW(mesh1->checkGeoEquivalWith(mesh2,0,1e-12,cellCor,nodeCor),INTERP_KERNEL::Exception);//deepEqual fails
+  CPPUNIT_ASSERT(cellCor==0);
+  CPPUNIT_ASSERT(nodeCor==0);
+  mesh1->checkGeoEquivalWith(mesh2,1,1e-12,cellCor,nodeCor);//fastEqual do not see anything
+  CPPUNIT_ASSERT(cellCor==0);
+  CPPUNIT_ASSERT(nodeCor==0);
+  mesh1->checkGeoEquivalWith(mesh2,10,1e-12,cellCor,nodeCor);//deepEqual with geo permutations
+  CPPUNIT_ASSERT(cellCor);
+  CPPUNIT_ASSERT_EQUAL(10,cellCor->getNumberOfTuples());
+  CPPUNIT_ASSERT_EQUAL(1,cellCor->getNumberOfComponents());
+  CPPUNIT_ASSERT(std::equal(renum,renum+10,cellCor->getConstPointer()));
+  CPPUNIT_ASSERT(nodeCor);
+  CPPUNIT_ASSERT_EQUAL(11,nodeCor->getNumberOfTuples());
+  CPPUNIT_ASSERT_EQUAL(1,nodeCor->getNumberOfComponents());
+  CPPUNIT_ASSERT(std::equal(renum2,renum2+11,nodeCor->getConstPointer()));
+  cellCor->decrRef();
+  cellCor=0;
+  nodeCor->decrRef();
+  nodeCor=0;
+  //5th test : modification of the last cell to check fastCheck detection.
+  mesh2->decrRef();
+  mesh2=build2DTargetMesh_3();
+  const int renum3[]={0,2,1,3,4,5,6,8,9,7};
+  mesh2->renumberCells(renum3,false);
+  mesh2->renumberNodes(renum2,11);
+  bool isExcep=false;
+  try { mesh1->checkGeoEquivalWith(mesh2,0,1e-12,cellCor,nodeCor);//deepEqual fails
+  }
+  catch(INTERP_KERNEL::Exception& e) { isExcep=true; }
+  CPPUNIT_ASSERT(isExcep); isExcep=false;
+  CPPUNIT_ASSERT(cellCor==0);
+  CPPUNIT_ASSERT(nodeCor==0);
+  try { mesh1->checkGeoEquivalWith(mesh2,1,1e-12,cellCor,nodeCor);//fastEqual has detected something
+  }
+  catch(INTERP_KERNEL::Exception& e) { isExcep=true; }
+  CPPUNIT_ASSERT(isExcep); isExcep=false;
+  CPPUNIT_ASSERT(cellCor==0);
+  CPPUNIT_ASSERT(nodeCor==0);
+  mesh2->checkGeoEquivalWith(mesh1,10,1e-12,cellCor,nodeCor);//deepEqual with geo permutations
+  CPPUNIT_ASSERT(cellCor);
+  CPPUNIT_ASSERT_EQUAL(10,cellCor->getNumberOfTuples());
+  CPPUNIT_ASSERT_EQUAL(1,cellCor->getNumberOfComponents());
+  CPPUNIT_ASSERT(std::equal(renum3,renum3+10,cellCor->getConstPointer()));
+  CPPUNIT_ASSERT(nodeCor);
+  CPPUNIT_ASSERT_EQUAL(11,nodeCor->getNumberOfTuples());
+  CPPUNIT_ASSERT_EQUAL(1,nodeCor->getNumberOfComponents());
+  CPPUNIT_ASSERT(std::equal(renum2,renum2+11,nodeCor->getConstPointer()));
+  cellCor->decrRef();
+  cellCor=0;
+  nodeCor->decrRef();
+  nodeCor=0;
+  //
+  mesh1->decrRef();
+  mesh2->decrRef();
+}
+
+void MEDCouplingBasicsTest::testCheckGeoEquivalWith2()
+{
+  MEDCouplingUMesh *mesh1=build2DTargetMesh_4();
+  MEDCouplingUMesh *mesh2=build2DTargetMesh_1();
+  DataArrayInt *cellCor,*nodeCor;
+  mesh1->checkGeoEquivalWith(mesh2,10,1e-12,cellCor,nodeCor);
+  CPPUNIT_ASSERT(cellCor==0);
+  CPPUNIT_ASSERT(nodeCor!=0);
+  const int expected1[9]={0, 1, 3, 4, 5, 6, 7, 8, 9};
+  for(int i=0;i<9;i++)
+    CPPUNIT_ASSERT_EQUAL(expected1[i],nodeCor->getIJ(i,0));
+  nodeCor->decrRef();
+  //
+  mesh1->decrRef();
+  mesh2->decrRef();
+}
+
+void MEDCouplingBasicsTest::testCopyTinyStringsFromOnFields()
+{
+  MEDCouplingUMesh *m=build3DSurfTargetMesh_1();
+  int nbOfCells=m->getNumberOfCells();
+  MEDCouplingFieldDouble *f=MEDCouplingFieldDouble::New(ON_CELLS,LINEAR_TIME);
+  f->setMesh(m);
+  f->setName("a");
+  f->setDescription("b");
+  DataArrayDouble *a1=DataArrayDouble::New();
+  a1->alloc(nbOfCells,2);
+  a1->fillWithZero();
+  a1->setInfoOnComponent(0,"c");
+  a1->setInfoOnComponent(1,"d");
+  DataArrayDouble *a2=a1->deepCopy();
+  a2->setInfoOnComponent(0,"e");
+  a2->setInfoOnComponent(1,"f");
+  f->setArray(a1);
+  f->setEndArray(a2);
+  f->setEndTime(3.,3,4);
+  a2->decrRef();
+  a1->decrRef();
+  m->setName("g");
+  m->getCoords()->setInfoOnComponent(0,"h");
+  m->getCoords()->setInfoOnComponent(1,"i");
+  m->getCoords()->setInfoOnComponent(2,"j");
+  //
+  f->checkCoherency();
+  MEDCouplingFieldDouble *f2=f->clone(true);
+  CPPUNIT_ASSERT(f2->isEqual(f,1e-12,1e-12));
+  f2->setName("smth");
+  CPPUNIT_ASSERT(!f2->isEqual(f,1e-12,1e-12));
+  f2->copyTinyStringsFrom(f);
+  CPPUNIT_ASSERT(f2->isEqual(f,1e-12,1e-12));
+  f2->setDescription("GGG");
+  CPPUNIT_ASSERT(!f2->isEqual(f,1e-12,1e-12));
+  f2->copyTinyStringsFrom(f);
+  CPPUNIT_ASSERT(f2->isEqual(f,1e-12,1e-12));
+  f2->getArray()->setInfoOnComponent(0,"mmmm");
+  CPPUNIT_ASSERT(!f2->isEqual(f,1e-12,1e-12));
+  f2->copyTinyStringsFrom(f);
+  CPPUNIT_ASSERT(f2->isEqual(f,1e-12,1e-12));
+  f2->getEndArray()->setInfoOnComponent(1,"mmmm");
+  CPPUNIT_ASSERT(!f2->isEqual(f,1e-12,1e-12));
+  f2->copyTinyStringsFrom(f);
+  CPPUNIT_ASSERT(f2->isEqual(f,1e-12,1e-12));
+  f2->decrRef();
+  MEDCouplingUMesh *m2=m->clone(true);
+  CPPUNIT_ASSERT(m2->isEqual(m,1e-12));
+  m2->setName("123");
+  CPPUNIT_ASSERT(!m2->isEqual(m,1e-12));
+  m2->copyTinyStringsFrom(m);
+  CPPUNIT_ASSERT(m2->isEqual(m,1e-12));
+  m2->getCoords()->setInfoOnComponent(1,"eee");
+  CPPUNIT_ASSERT(!m2->isEqual(m,1e-12));
+  m2->copyTinyStringsFrom(m);
+  CPPUNIT_ASSERT(m2->isEqual(m,1e-12));
+  m2->decrRef();
+  //
+  f->decrRef();
+  m->decrRef();
+}
+
+void MEDCouplingBasicsTest::testTryToShareSameCoordsPermute()
+{
+  MEDCouplingUMesh *m=build3DSurfTargetMesh_1();
+  MEDCouplingUMesh *m2=build3DSurfTargetMesh_1();
+  CPPUNIT_ASSERT(m->getCoords()!=m2->getCoords());
+  m->tryToShareSameCoordsPermute(*m2,1e-12);
+  CPPUNIT_ASSERT(m->getCoords()==m2->getCoords());
+  CPPUNIT_ASSERT(m2->isEqual(m,1e-12));
+  const int renum1[9]={1,2,0,5,8,7,4,3,6};
+  m->renumberNodes(renum1,9);
+  CPPUNIT_ASSERT(m->getCoords()!=m2->getCoords());
+  CPPUNIT_ASSERT(!m2->isEqual(m,1e-12));
+  m->tryToShareSameCoordsPermute(*m2,1e-12);
+  CPPUNIT_ASSERT(m->getCoords()==m2->getCoords());
+  CPPUNIT_ASSERT(m2->isEqual(m,1e-12));
+  m2->decrRef();
+  m->decrRef();
+}
+
+void MEDCouplingBasicsTest::testTryToShareSameCoordsPermute2()
+{
+  MEDCouplingUMesh *m1=build2DTargetMesh_4();
+  double targetCoords[8]={-0.3,-0.3, 0.2,-0.3, -0.3,0.2, 0.2,0.2 };
+  int targetConn[4]={0,2,3,1};
+  MEDCouplingUMesh *m2=MEDCouplingUMesh::New();
+  m2->setMeshDimension(2);
+  m2->allocateCells(1);
+  m2->insertNextCell(INTERP_KERNEL::NORM_QUAD4,4,targetConn);
+  m2->finishInsertingCells();
+  DataArrayDouble *myCoords=DataArrayDouble::New();
+  myCoords->alloc(4,2);
+  std::copy(targetCoords,targetCoords+8,myCoords->getPointer());
+  m2->setCoords(myCoords);
+  myCoords->decrRef();
+  m2->checkCoherency();
+  m1->checkCoherency();
+  //
+  const double expected1[5]={0.25,0.125,0.125,0.25,0.25};
+  MEDCouplingFieldDouble *f1=m1->getMeasureField(false);
+  MEDCouplingFieldDouble *f2=m2->getMeasureField(false);
+  CPPUNIT_ASSERT_EQUAL(5,f1->getArray()->getNumberOfTuples());
+  CPPUNIT_ASSERT_EQUAL(1,f2->getArray()->getNumberOfTuples());
+  for(int i=0;i<5;i++)
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(expected1[i],f1->getIJ(i,0),1e-12);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(expected1[0],f2->getIJ(0,0),1e-12);
+  f2->decrRef();
+  f1->decrRef();
+  CPPUNIT_ASSERT_THROW(m1->tryToShareSameCoordsPermute(*m2,1e-12),INTERP_KERNEL::Exception);// <- here in this order the sharing is impossible.
+  // Let's go for deeper test of tryToShareSameCoordsPermute
+  m2->tryToShareSameCoordsPermute(*m1,1e-12);
+  f1=m1->getMeasureField(false);
+  f2=m2->getMeasureField(false);
+  CPPUNIT_ASSERT_EQUAL(5,f1->getArray()->getNumberOfTuples());
+  CPPUNIT_ASSERT_EQUAL(1,f2->getArray()->getNumberOfTuples());
+  for(int i=0;i<5;i++)
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(expected1[i],f1->getIJ(i,0),1e-12);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(expected1[0],f2->getIJ(0,0),1e-12);
+  //
+  f2->decrRef();
+  f1->decrRef();
+  //
+  m1->decrRef();
+  m2->decrRef();
+}
+
+void MEDCouplingBasicsTest::testChangeUnderlyingMesh1()
+{
+  MEDCouplingUMesh *mesh1=build2DTargetMesh_3();
+  MEDCouplingUMesh *mesh2=build2DTargetMesh_3();
+  MEDCouplingFieldDouble *f1=MEDCouplingFieldDouble::New(ON_CELLS,NO_TIME);
+  f1->setMesh(mesh1);
+  DataArrayDouble *array=DataArrayDouble::New();
+  array->alloc(mesh1->getNumberOfCells(),2);
+  const double arr[20]={7.,107.,8.,108.,9.,109.,10.,110.,11.,111.,12.,112.,13.,113.,14.,114.,15.,115.,16.,116.};
+  std::copy(arr,arr+20,array->getPointer());
+  f1->setArray(array);
+  array->decrRef();
+  //
+  const int renum[]={0,2,1,3,4,5,6,8,7,9};
+  mesh2->renumberCells(renum,false);
+  CPPUNIT_ASSERT(f1->getMesh()==mesh1);
+  f1->changeUnderlyingMesh(mesh1,10,1e-12);// nothing done only to check that nothing done.
+  CPPUNIT_ASSERT(f1->getMesh()==mesh1);
+  f1->changeUnderlyingMesh(mesh2,10,1e-12);
+  CPPUNIT_ASSERT(f1->getMesh()==mesh2);
+  const double expected1[20]={7.,107.,9.,109.,8.,108.,10.,110.,11.,111.,12.,112.,13.,113.,15.,115.,14.,114.,16.,116.};
+  for(int i=0;i<20;i++)
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(expected1[i],f1->getArray()->getIJ(0,i),1e-12);
+  f1->decrRef();
+  //
+  f1=MEDCouplingFieldDouble::New(ON_NODES,NO_TIME);
+  f1->setMesh(mesh1);
+  array=DataArrayDouble::New();
+  array->alloc(mesh1->getNumberOfNodes(),2);
+  const double arr2[22]={7.,107.,8.,108.,9.,109.,10.,110.,11.,111.,12.,112.,13.,113.,14.,114.,15.,115.,16.,116.,17.,117.};
+  std::copy(arr2,arr2+22,array->getPointer());
+  f1->setArray(array);
+  array->decrRef();
+  //
+  const int renum2[]={0,2,10,3,4,5,6,8,7,9,1};
+  mesh2->renumberNodes(renum2,11);
+  CPPUNIT_ASSERT(f1->getMesh()==mesh1);
+  f1->changeUnderlyingMesh(mesh2,10,1e-12);
+  CPPUNIT_ASSERT(f1->getMesh()==mesh2);
+  const double expected2[22]={7.,107.,9.,109.,17.,117.,10.,110.,11.,111.,12.,112.,13.,113.,15.,115.,14.,114.,16.,116.,8.,108.};
+  for(int i=0;i<22;i++)
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(expected2[i],f1->getArray()->getIJ(0,i),1e-12);
+  f1->decrRef();
+  //
+  mesh1->decrRef();
+  mesh2->decrRef();
+}
+
+void MEDCouplingBasicsTest::testGetMaxValue1()
+{
+  MEDCouplingUMesh *m=build3DSurfTargetMesh_1();
+  int nbOfCells=m->getNumberOfCells();
+  MEDCouplingFieldDouble *f=MEDCouplingFieldDouble::New(ON_CELLS,LINEAR_TIME);
+  f->setMesh(m);
+  DataArrayDouble *a1=DataArrayDouble::New();
+  a1->alloc(nbOfCells,1);
+  const double val1[5]={3.,4.,5.,6.,7.};
+  std::copy(val1,val1+5,a1->getPointer());
+  DataArrayDouble *a2=DataArrayDouble::New();
+  a2->alloc(nbOfCells,1);
+  const double val2[5]={0.,1.,2.,8.,7.};
+  std::copy(val2,val2+5,a2->getPointer());
+  f->setArray(a1);
+  f->setEndArray(a2);
+  f->setEndTime(3.,3,4);
+  f->checkCoherency();
+  //
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(8.,f->getMaxValue(),1e-14);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(0.,f->getMinValue(),1e-14);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(5.,f->getAverageValue(),1e-14);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(5.125,f->getWeightedAverageValue(),1e-14);
+  a1->setIJ(0,2,9.5);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(9.5,f->getMaxValue(),1e-14);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(0.,f->getMinValue(),1e-14);
+  a2->setIJ(0,0,9.);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(9.5,f->getMaxValue(),1e-14);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(1.,f->getMinValue(),1e-14);
+  //
+  a2->decrRef();
+  a1->decrRef();
+  m->decrRef();
+  f->decrRef();
+}
+
+void MEDCouplingBasicsTest::testSubstractInPlaceDM1()
+{
+  MEDCouplingUMesh *mesh1=build2DTargetMesh_3();
+  MEDCouplingUMesh *mesh2=build2DTargetMesh_3();
+  MEDCouplingFieldDouble *f1=MEDCouplingFieldDouble::New(ON_CELLS,NO_TIME);
+  f1->setMesh(mesh1);
+  DataArrayDouble *array=DataArrayDouble::New();
+  array->alloc(mesh1->getNumberOfCells(),2);
+  const double arr[20]={7.,107.,8.,108.,9.,109.,10.,110.,11.,111.,12.,112.,13.,113.,14.,114.,15.,115.,16.,116.};
+  std::copy(arr,arr+20,array->getPointer());
+  f1->setArray(array);
+  array->decrRef();
+  //
+  CPPUNIT_ASSERT_EQUAL(10,f1->getNumberOfTuples());
+  CPPUNIT_ASSERT_EQUAL(2,f1->getNumberOfComponents());
+  CPPUNIT_ASSERT_EQUAL(20,f1->getNumberOfValues());
+  //
+  const int renum[]={0,2,1,3,4,5,6,8,7,9};
+  mesh2->renumberCells(renum,false);
+  //
+  MEDCouplingFieldDouble *f2=MEDCouplingFieldDouble::New(ON_CELLS,NO_TIME);
+  f2->setMesh(mesh2);
+  array=DataArrayDouble::New();
+  array->alloc(mesh2->getNumberOfCells(),2);
+  const double arr2[20]={7.1,107.1,9.1,109.1,8.1,108.1,10.1,110.1,11.1,111.1,12.1,112.1,13.1,113.1,15.1,115.1,14.1,114.1,16.1,116.1};
+  std::copy(arr2,arr2+20,array->getPointer());
+  f2->setArray(array);
+  array->decrRef();
+  //
+  f1->substractInPlaceDM(f2,10,1e-12);
+  f1->applyFunc(1,"abs(x+y+0.2)");
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(0.,f1->getMaxValue(),1e-14);
+  //
+  f1->decrRef();
+  f2->decrRef();
+  mesh1->decrRef();
+  mesh2->decrRef();
+}
+
+void MEDCouplingBasicsTest::testDotCrossProduct1()
+{
+  MEDCouplingUMesh *mesh1=build2DTargetMesh_3();
+  MEDCouplingFieldDouble *f1=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
+  f1->setTime(2.3,5,6);
+  f1->setMesh(mesh1);
+  DataArrayDouble *array=DataArrayDouble::New();
+  array->alloc(mesh1->getNumberOfCells(),3);
+  const double arr1[30]={7.,107.,207.,8.,108.,208.,9.,109.,209.,10.,110.,210.,11.,111.,211.,12.,112.,212.,13.,113.,213.,14.,114.,214.,15.,115.,215.,16.,116.,216.};
+  std::copy(arr1,arr1+30,array->getPointer());
+  f1->setArray(array);
+  array->decrRef();
+  MEDCouplingFieldDouble *f2=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
+  f2->setTime(7.8,4,5);
+  f2->setMesh(mesh1);
+  array=DataArrayDouble::New();
+  array->alloc(mesh1->getNumberOfCells(),3);
+  const double arr2[30]={1.,2.,3.,4.,5.,6.,7.,8.,9.,10.,11.,12.,13.,14.,15.,16.,17.,18.,19.,20.,21.,22.,23.,24.,25.,26.,27.,28.,29.,30.};
+  std::copy(arr2,arr2+30,array->getPointer());
+  f2->setArray(array);
+  array->decrRef();
+  //
+  MEDCouplingFieldDouble *f3=f1->dot(*f2);
+  const double expected1[10]={842.,1820.,2816.,3830.,4862.,5912.,6980.,8066.,9170.,10292.};
+  for(int i=0;i<10;i++)
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(expected1[i],f3->getIJ(i,0),1e-9);
+  f3->decrRef();
+  //
+  MEDCouplingFieldDouble *f4=f1->crossProduct(*f2);
+  const double expected2[30]={-93., 186., -93., -392., 784., -392., -691., 1382., -691., -990., 1980., -990., -1289., 2578., -1289., -1588., 3176., -1588., -1887., 3774., -1887., -2186., 4372., -2186., -2485., 4970., -2485., -2784., 5568., -2784.};
+  for(int i=0;i<30;i++)
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(expected2[i],f4->getIJ(0,i),1e-9);
+  f4->decrRef();
+  //
+  f2->decrRef();
+  f1->decrRef();
+  mesh1->decrRef();
+}
+
+void MEDCouplingBasicsTest::testMinMaxFields1()
+{
+  MEDCouplingUMesh *mesh1=build2DTargetMesh_3();
+  MEDCouplingFieldDouble *f1=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
+  f1->setTime(2.3,5,6);
+  f1->setMesh(mesh1);
+  DataArrayDouble *array=DataArrayDouble::New();
+  array->alloc(mesh1->getNumberOfCells(),3);
+  const double arr1[30]={7.,107.,207.,8.,108.,208.,9.,109.,209.,10.,110.,210.,11.,111.,211.,12.,112.,212.,13.,113.,213.,14.,114.,214.,15.,115.,215.,16.,116.,216.};
+  std::copy(arr1,arr1+30,array->getPointer());
+  f1->setArray(array);
+  array->decrRef();
+  MEDCouplingFieldDouble *f2=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
+  f2->setTime(7.8,4,5);
+  f2->setMesh(mesh1);
+  array=DataArrayDouble::New();
+  array->alloc(mesh1->getNumberOfCells(),3);
+  const double arr2[30]={6.,108.,206.,9.,107.,209.,8.,110.,208.,11.,109.,211.,10.,112.,210.,13.,111.,213.,12.,114.,212.,15.,113.,215.,14.,116.,214.,17.,115.,217.};
+  std::copy(arr2,arr2+30,array->getPointer());
+  f2->setArray(array);
+  array->decrRef();
+  //
+  MEDCouplingFieldDouble *f3=f1->max(*f2);
+  const double expected1[30]={7.,108.,207.,9.,108.,209.,9.,110.,209.,11.,110.,211.,11.,112.,211.,13.,112.,213.,13.,114.,213.,15.,114.,215.,15.,116.,215.,17.,116.,217.};
+  for(int i=0;i<30;i++)
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(expected1[i],f3->getIJ(0,i),1e-9);
+  f3->decrRef();
+  //
+  MEDCouplingFieldDouble *f4=f1->min(*f2);
+  const double expected2[30]={6.,107.,206.,8.,107.,208.,8.,109.,208.,10.,109.,210.,10.,111.,210.,12.,111.,212.,12.,113.,212.,14.,113.,214.,14.,115.,214.,16.,115.,216.};
+  for(int i=0;i<30;i++)
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(expected2[i],f4->getIJ(0,i),1e-9);
+  f4->decrRef();
+  //
+  f2->decrRef();
+  f1->decrRef();
+  mesh1->decrRef();
+}
+
+void MEDCouplingBasicsTest::testApplyLin1()
+{
+  MEDCouplingUMesh *mesh1=build2DTargetMesh_3();
+  MEDCouplingFieldDouble *f1=MEDCouplingFieldDouble::New(ON_CELLS,LINEAR_TIME);
+  f1->setMesh(mesh1);
+  DataArrayDouble *array=DataArrayDouble::New();
+  array->alloc(mesh1->getNumberOfCells(),2);
+  const double arr[20]={7.,107.,8.,108.,9.,109.,10.,110.,11.,111.,12.,112.,13.,113.,14.,114.,15.,115.,16.,116.};
+  std::copy(arr,arr+20,array->getPointer());
+  f1->setArray(array);
+  array->decrRef();
+  //
+  f1->applyLin(2.,3.,0);
+  const double expected1[20]={17.,107.,19.,108.,21.,109.,23.,110.,25.,111.,27.,112.,29.,113.,31.,114.,33.,115.,35.,116.};
+  for(int i=0;i<20;i++)
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(expected1[i],f1->getIJ(0,i),1e-9);
+  //
+  const double arr2[20]={2.,102.,3.,103.,4.,104.,5.,105.,6.,106.,7.,107.,8.,108.,9.,109.,10.,110.,11.,111.};
+  array=DataArrayDouble::New();
+  array->alloc(mesh1->getNumberOfCells(),2);
+  std::copy(arr2,arr2+20,array->getPointer());
+  f1->setEndArray(array);
+  array->decrRef();
+  //
+  f1->applyLin(4.,5.,1);
+  //
+  const double expected2[20]={17.,433.,19.,437.,21.,441.,23.,445.,25.,449.,27.,453.,29.,457.,31.,461.,33.,465.,35.,469.};
+  for(int i=0;i<20;i++)
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(expected2[i],f1->getIJ(0,i),1e-9);
+  const double expected3[20]={2.,413.,3.,417.,4.,421.,5.,425.,6.,429.,7.,433.,8.,437.,9.,441.,10.,445.,11.,449.};
+  for(int i=0;i<20;i++)
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(expected3[i],f1->getEndArray()->getIJ(0,i),1e-9);
+  //
+  mesh1->decrRef();
+  f1->decrRef();
+}
+
+void MEDCouplingBasicsTest::testGetIdsInRange1()
+{
+  MEDCouplingUMesh *mesh1=build2DTargetMesh_3();
+  MEDCouplingFieldDouble *f1=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
+  f1->setTime(2.3,5,6);
+  f1->setMesh(mesh1);
+  DataArrayDouble *array=DataArrayDouble::New();
+  array->alloc(mesh1->getNumberOfCells(),1);
+  const double arr1[10]={2.,8.,6.,5.,11.,7.,9.,3.,10.,4.};
+  std::copy(arr1,arr1+10,array->getPointer());
+  f1->setArray(array);
+  array->decrRef();
+  //
+  f1->checkCoherency();
+  DataArrayInt *da=f1->getIdsInRange(2.9,7.1);
+  CPPUNIT_ASSERT_EQUAL(5,da->getNbOfElems());
+  const int expected1[5]={2,3,5,7,9};
+  CPPUNIT_ASSERT(std::equal(expected1,expected1+5,da->getConstPointer()));
+  da->decrRef();
+  da=f1->getIdsInRange(8.,12.);
+  CPPUNIT_ASSERT_EQUAL(4,da->getNbOfElems());
+  const int expected2[4]={1,4,6,8};
+  CPPUNIT_ASSERT(std::equal(expected2,expected2+4,da->getConstPointer()));
+  da->decrRef();
+  //
+  f1->decrRef();
+  mesh1->decrRef();
+}
+
+void MEDCouplingBasicsTest::testBuildSubPart1()
+{
+  MEDCouplingUMesh *mesh1=build2DTargetMesh_1();
+  MEDCouplingFieldDouble *f1=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
+  f1->setTime(2.3,5,6);
+  f1->setMesh(mesh1);
+  DataArrayDouble *array=DataArrayDouble::New();
+  array->alloc(mesh1->getNumberOfCells(),2);
+  const double arr1[10]={3.,103.,4.,104.,5.,105.,6.,106.,7.,107.};
+  std::copy(arr1,arr1+10,array->getPointer());
+  f1->setArray(array);
+  array->decrRef();
+  //
+  const int part1[3]={2,1,4};
+  MEDCouplingFieldDouble *f2=f1->buildSubPart(part1,part1+3);
+  CPPUNIT_ASSERT_EQUAL(3,f2->getNumberOfTuples());
+  CPPUNIT_ASSERT_EQUAL(2,f2->getNumberOfComponents());
+  const double expected1[6]={5.,105.,4.,104.,7.,107.};
+  for(int i=0;i<6;i++)
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(f2->getIJ(0,i),expected1[i],1e-12);
+  CPPUNIT_ASSERT_EQUAL(3,f2->getMesh()->getNumberOfCells());
+  CPPUNIT_ASSERT_EQUAL(6,f2->getMesh()->getNumberOfNodes());
+  CPPUNIT_ASSERT_EQUAL(2,f2->getMesh()->getSpaceDimension());
+  CPPUNIT_ASSERT_EQUAL(2,f2->getMesh()->getMeshDimension());
+  MEDCouplingUMesh *m2C=dynamic_cast<MEDCouplingUMesh *>(const_cast<MEDCouplingMesh *>(f2->getMesh()));
+  CPPUNIT_ASSERT_EQUAL(13,m2C->getMeshLength());
+  const double expected2[12]={0.2, -0.3, 0.7, -0.3, 0.2, 0.2, 0.7, 0.2, 0.2, 0.7, 0.7, 0.7};
+  for(int i=0;i<12;i++)
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(expected2[i],m2C->getCoords()->getIJ(0,i),1.e-12);
+  const double expected3[13]={3,2,3,1,3,0,2,1,4,4,5,3,2};
+  CPPUNIT_ASSERT(std::equal(expected3,expected3+13,m2C->getNodalConnectivity()->getConstPointer()));
+  const double expected4[4]={0,4,8,13};
+  CPPUNIT_ASSERT(std::equal(expected4,expected4+4,m2C->getNodalConnectivityIndex()->getConstPointer()));
+  f2->decrRef();
+  f1->decrRef();
+  // Test with field on nodes.
+  f1=MEDCouplingFieldDouble::New(ON_NODES,ONE_TIME);
+  f1->setTime(2.3,5,6);
+  f1->setMesh(mesh1);
+  array=DataArrayDouble::New();
+  array->alloc(mesh1->getNumberOfNodes(),2);
+  const double arr2[18]={3.,103.,4.,104.,5.,105.,6.,106.,7.,107.,8.,108.,9.,109.,10.,110.,11.,111.};
+  std::copy(arr2,arr2+18,array->getPointer());  
+  f1->setArray(array);
+  array->decrRef();
+  const int part2[4]={1,4,2,5};
+  f2=f1->buildSubPart(part2,part2+4);
+  CPPUNIT_ASSERT_EQUAL(4,f2->getNumberOfTuples());
+  CPPUNIT_ASSERT_EQUAL(2,f2->getNumberOfComponents());
+  const double expected5[8]={4.,104.,5.,105.,7.,107.,8.,108.};
+  for(int i=0;i<8;i++)
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(f2->getIJ(0,i),expected5[i],1e-12);
+  CPPUNIT_ASSERT_EQUAL(2,f2->getMesh()->getNumberOfCells());
+  CPPUNIT_ASSERT_EQUAL(4,f2->getMesh()->getNumberOfNodes());
+  CPPUNIT_ASSERT_EQUAL(2,f2->getMesh()->getSpaceDimension());
+  CPPUNIT_ASSERT_EQUAL(2,f2->getMesh()->getMeshDimension());
+  m2C=dynamic_cast<MEDCouplingUMesh *>(const_cast<MEDCouplingMesh *>(f2->getMesh()));
+  CPPUNIT_ASSERT_EQUAL(8,m2C->getMeshLength());
+  for(int i=0;i<8;i++)//8 is not an error
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(expected2[i],m2C->getCoords()->getIJ(0,i),1.e-12);
+  CPPUNIT_ASSERT(std::equal(expected3,expected3+4,m2C->getNodalConnectivity()->getConstPointer()+4));
+  CPPUNIT_ASSERT(std::equal(expected3+4,expected3+8,m2C->getNodalConnectivity()->getConstPointer()));
+  CPPUNIT_ASSERT(std::equal(expected4,expected4+3,m2C->getNodalConnectivityIndex()->getConstPointer()));
+  f2->decrRef();
+  //idem previous because nodes of cell#4 are not fully present in part3 
+  const int part3[5]={1,4,2,5,7};
+  DataArrayInt *arrr=DataArrayInt::New();
+  arrr->alloc(5,1);
+  std::copy(part3,part3+5,arrr->getPointer());
+  f2=f1->buildSubPart(arrr);
+  arrr->decrRef();
+  CPPUNIT_ASSERT_EQUAL(4,f2->getNumberOfTuples());
+  CPPUNIT_ASSERT_EQUAL(2,f2->getNumberOfComponents());
+  for(int i=0;i<8;i++)
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(f2->getIJ(0,i),expected5[i],1e-12);
+  CPPUNIT_ASSERT_EQUAL(2,f2->getMesh()->getNumberOfCells());
+  CPPUNIT_ASSERT_EQUAL(4,f2->getMesh()->getNumberOfNodes());
+  CPPUNIT_ASSERT_EQUAL(2,f2->getMesh()->getSpaceDimension());
+  CPPUNIT_ASSERT_EQUAL(2,f2->getMesh()->getMeshDimension());
+  m2C=dynamic_cast<MEDCouplingUMesh *>(const_cast<MEDCouplingMesh *>(f2->getMesh()));
+  CPPUNIT_ASSERT_EQUAL(8,m2C->getMeshLength());
+  for(int i=0;i<8;i++)//8 is not an error
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(expected2[i],m2C->getCoords()->getIJ(0,i),1.e-12);
+  CPPUNIT_ASSERT(std::equal(expected3,expected3+4,m2C->getNodalConnectivity()->getConstPointer()+4));
+  CPPUNIT_ASSERT(std::equal(expected3+4,expected3+8,m2C->getNodalConnectivity()->getConstPointer()));
+  CPPUNIT_ASSERT(std::equal(expected4,expected4+3,m2C->getNodalConnectivityIndex()->getConstPointer()));
+  f2->decrRef();
+  //
+  const int part4[6]={1,4,2,5,7,8};
+  f2=f1->buildSubPart(part4,part4+6);
+  CPPUNIT_ASSERT_EQUAL(6,f2->getNumberOfTuples());
+  CPPUNIT_ASSERT_EQUAL(2,f2->getNumberOfComponents());
+  const double expected6[12]={4.,104.,5.,105.,7.,107.,8.,108.,10.,110.,11.,111.};
+  for(int i=0;i<12;i++)
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(f2->getIJ(0,i),expected6[i],1e-12);
+  CPPUNIT_ASSERT_EQUAL(3,f2->getMesh()->getNumberOfCells());
+  CPPUNIT_ASSERT_EQUAL(6,f2->getMesh()->getNumberOfNodes());
+  CPPUNIT_ASSERT_EQUAL(2,f2->getMesh()->getSpaceDimension());
+  CPPUNIT_ASSERT_EQUAL(2,f2->getMesh()->getMeshDimension());
+  m2C=dynamic_cast<MEDCouplingUMesh *>(const_cast<MEDCouplingMesh *>(f2->getMesh()));
+  CPPUNIT_ASSERT_EQUAL(13,m2C->getMeshLength());
+  for(int i=0;i<12;i++)
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(expected2[i],m2C->getCoords()->getIJ(0,i),1.e-12);
+  CPPUNIT_ASSERT(std::equal(expected3,expected3+4,m2C->getNodalConnectivity()->getConstPointer()+4));
+  CPPUNIT_ASSERT(std::equal(expected3+4,expected3+8,m2C->getNodalConnectivity()->getConstPointer()));
+  CPPUNIT_ASSERT(std::equal(expected3+8,expected3+13,m2C->getNodalConnectivity()->getConstPointer()+8));
+  CPPUNIT_ASSERT(std::equal(expected4,expected4+4,m2C->getNodalConnectivityIndex()->getConstPointer()));
+  f2->decrRef();
+  //
+  f1->decrRef();
+  mesh1->decrRef();
+}
+
+void MEDCouplingBasicsTest::testDoublyContractedProduct1()
+{
+  MEDCouplingUMesh *mesh1=build2DTargetMesh_1();
+  MEDCouplingFieldDouble *f1=MEDCouplingFieldDouble::New(ON_CELLS,NO_TIME);
+  f1->setMesh(mesh1);
+  DataArrayDouble *array=DataArrayDouble::New();
+  array->alloc(mesh1->getNumberOfCells(),6);
+  const double arr1[30]={7.8,8.9,9.1,10.2,23.4,34.5, 7.8,8.9,9.1,10.2,23.4,34.5, 7.8,8.9,9.1,10.2,23.4,34.5, 7.8,8.9,9.1,10.2,23.4,34.5, 7.8,8.9,9.1,10.2,23.4,34.5};
+  std::copy(arr1,arr1+30,array->getPointer());
+  f1->setArray(array);
+  array->decrRef();
+  f1->checkCoherency();
+  //
+  MEDCouplingFieldDouble *f2=f1->doublyContractedProduct();
+  f2->checkCoherency();
+  CPPUNIT_ASSERT_EQUAL(1,f2->getNumberOfComponents());
+  CPPUNIT_ASSERT_EQUAL(5,f2->getNumberOfTuples());
+  for(int i=0;i<5;i++)
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(3906.56,f2->getIJ(i,0),1e-9);
+  f2->decrRef();
+  //
+  mesh1->decrRef();
+  f1->decrRef();
+}
+
+void MEDCouplingBasicsTest::testDeterminant1()
+{
+  MEDCouplingUMesh *mesh1=build2DTargetMesh_1();
+  MEDCouplingFieldDouble *f1=MEDCouplingFieldDouble::New(ON_CELLS,CONST_ON_TIME_INTERVAL);
+  f1->setTime(2.3,5,6);
+  f1->setEndTime(3.8,7,3);
+  f1->setMesh(mesh1);
+  DataArrayDouble *array=DataArrayDouble::New();
+  array->alloc(mesh1->getNumberOfCells(),4);
+  const double arr1[20]={1.2,2.3,3.4,4.5, 1.2,2.3,3.4,4.5, 1.2,2.3,3.4,4.5, 1.2,2.3,3.4,4.5, 1.2,2.3,3.4,4.5};
+  std::copy(arr1,arr1+20,array->getPointer());
+  f1->setArray(array);
+  array->decrRef();
+  //4 components
+  f1->checkCoherency();
+  MEDCouplingFieldDouble *f2=f1->determinant();
+  f2->checkCoherency();
+  CPPUNIT_ASSERT_EQUAL(CONST_ON_TIME_INTERVAL,f2->getTimeDiscretization());
+  CPPUNIT_ASSERT_EQUAL(1,f2->getNumberOfComponents());
+  CPPUNIT_ASSERT_EQUAL(5,f2->getNumberOfValues());
+  for(int i=0;i<5;i++)
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(-2.42,f2->getIJ(i,0),1e-13);
+  f2->decrRef();
+  f1->decrRef();
+  //6 components multi arrays with end array not defined
+  f1=MEDCouplingFieldDouble::New(ON_NODES,LINEAR_TIME);
+  f1->setTime(2.3,5,6);
+  f1->setEndTime(3.8,7,3);
+  f1->setMesh(mesh1);
+  array=DataArrayDouble::New();
+  array->alloc(mesh1->getNumberOfNodes(),6);
+  const double arr2[54]={1.2,2.3,3.4,4.5,5.6,6.7, 1.2,2.3,3.4,4.5,5.6,6.7, 1.2,2.3,3.4,4.5,5.6,6.7, 1.2,2.3,3.4,4.5,5.6,6.7, 1.2,2.3,3.4,4.5,5.6,6.7,
+                         1.2,2.3,3.4,4.5,5.6,6.7, 1.2,2.3,3.4,4.5,5.6,6.7, 1.2,2.3,3.4,4.5,5.6,6.7, 1.2,2.3,3.4,4.5,5.6,6.7};
+  std::copy(arr2,arr2+54,array->getPointer());
+  f1->setArray(array);
+  array->decrRef();
+  CPPUNIT_ASSERT_THROW(f1->checkCoherency(),INTERP_KERNEL::Exception);//no end array specified !
+  //
+  f2=f1->determinant();
+  CPPUNIT_ASSERT_EQUAL(LINEAR_TIME,f2->getTimeDiscretization());
+  CPPUNIT_ASSERT_EQUAL(1,f2->getArray()->getNumberOfComponents());
+  CPPUNIT_ASSERT_EQUAL(9,f2->getNumberOfTuples());
+  for(int i=0;i<9;i++)
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(137.335,f2->getIJ(i,0),1e-10);
+  f2->decrRef();
+  //6 components multi arrays with end array defined
+  array=DataArrayDouble::New();
+  array->alloc(mesh1->getNumberOfNodes(),6);
+  const double arr3[54]={7.8,8.9,9.1,10.2,23.4,34.5, 7.8,8.9,9.1,10.2,23.4,34.5, 7.8,8.9,9.1,10.2,23.4,34.5, 7.8,8.9,9.1,10.2,23.4,34.5, 7.8,8.9,9.1,10.2,23.4,34.5,
+                         7.8,8.9,9.1,10.2,23.4,34.5, 7.8,8.9,9.1,10.2,23.4,34.5, 7.8,8.9,9.1,10.2,23.4,34.5, 7.8,8.9,9.1,10.2,23.4,34.5};
+  std::copy(arr3,arr3+54,array->getPointer());
+  f1->setEndArray(array);
+  array->decrRef();
+  f1->checkCoherency();
+  f2=f1->determinant();
+  f2->checkCoherency();
+  CPPUNIT_ASSERT_EQUAL(LINEAR_TIME,f2->getTimeDiscretization());
+  CPPUNIT_ASSERT_EQUAL(1,f2->getNumberOfComponents());
+  CPPUNIT_ASSERT_EQUAL(9,f2->getNumberOfTuples());
+  int it,order;
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(2.3,f2->getTime(it,order),1e-12);
+  CPPUNIT_ASSERT_EQUAL(5,it); CPPUNIT_ASSERT_EQUAL(6,order);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(3.8,f2->getEndTime(it,order),1e-12);
+  CPPUNIT_ASSERT_EQUAL(7,it); CPPUNIT_ASSERT_EQUAL(3,order);
+  for(int i=0;i<9;i++)
+    {
+      CPPUNIT_ASSERT_DOUBLES_EQUAL(137.335,f2->getIJ(i,0),1e-10);
+      CPPUNIT_ASSERT_DOUBLES_EQUAL(1289.685,f2->getEndArray()->getIJ(i,0),1e-9);
+    }
+  f2->decrRef();
+  f1->decrRef();
+  //9 components
+  f1=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
+  f1->setTime(7.8,10,2);
+  f1->setMesh(mesh1);
+  array=DataArrayDouble::New();
+  array->alloc(mesh1->getNumberOfCells(),9);
+  const double arr4[45]={1.2,2.3,3.4,4.5,5.6,6.7,7.8,8.9,9.1, 1.2,2.3,3.4,4.5,5.6,6.7,7.8,8.9,9.1, 1.2,2.3,3.4,4.5,5.6,6.7,7.8,8.9,9.1, 1.2,2.3,3.4,4.5,5.6,6.7,7.8,8.9,9.1, 1.2,2.3,3.4,4.5,5.6,6.7,7.8,8.9,9.1};
+  std::copy(arr4,arr4+45,array->getPointer());
+  f1->setArray(array);
+  array->decrRef();
+  //
+  f1->checkCoherency();
+  f2=f1->determinant();
+  f2->checkCoherency();
+  CPPUNIT_ASSERT_EQUAL(ONE_TIME,f2->getTimeDiscretization());
+  CPPUNIT_ASSERT_EQUAL(1,f2->getNumberOfComponents());
+  CPPUNIT_ASSERT_EQUAL(5,f2->getNumberOfTuples());
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(7.8,f2->getTime(it,order),1e-12);
+  CPPUNIT_ASSERT_EQUAL(10,it); CPPUNIT_ASSERT_EQUAL(2,order);
+  for(int i=0;i<5;i++)
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(3.267,f2->getIJ(i,0),1e-13);
+  f2->decrRef();
+  //
+  mesh1->decrRef();
+  f1->decrRef();
+}
+
+void MEDCouplingBasicsTest::testEigenValues1()
+{
+  MEDCouplingUMesh *mesh1=build2DTargetMesh_1();
+  MEDCouplingFieldDouble *f1=MEDCouplingFieldDouble::New(ON_CELLS,NO_TIME);
+  f1->setMesh(mesh1);
+  DataArrayDouble *array=DataArrayDouble::New();
+  array->alloc(mesh1->getNumberOfCells(),6);
+  const double arr1[30]={1.2,2.3,3.4,4.5,5.6,6.7, 1.2,2.3,3.4,4.5,5.6,6.7, 1.2,2.3,3.4,4.5,5.6,6.7, 1.2,2.3,3.4,4.5,5.6,6.7, 1.2,2.3,3.4,4.5,5.6,6.7};
+  std::copy(arr1,arr1+30,array->getPointer());
+  f1->setArray(array);
+  array->decrRef();
+  f1->checkCoherency();
+  //
+  MEDCouplingFieldDouble *f2=f1->eigenValues();
+  f2->checkCoherency();
+  CPPUNIT_ASSERT_EQUAL(3,f2->getNumberOfComponents());
+  CPPUNIT_ASSERT_EQUAL(5,f2->getNumberOfTuples());
+  const double expected1[3]={13.638813677891717,-4.502313844635971,-2.2364998332557486};
+  for(int i=0;i<5;i++)
+    {
+      CPPUNIT_ASSERT_DOUBLES_EQUAL(expected1[0],f2->getIJ(i,0),1e-13);
+      CPPUNIT_ASSERT_DOUBLES_EQUAL(expected1[1],f2->getIJ(i,1),1e-13);
+      CPPUNIT_ASSERT_DOUBLES_EQUAL(expected1[2],f2->getIJ(i,2),1e-13);
+    }
+  f2->decrRef();
+  //
+  mesh1->decrRef();
+  f1->decrRef();
+}
+
+void MEDCouplingBasicsTest::testEigenVectors1()
+{
+  MEDCouplingUMesh *mesh1=build2DTargetMesh_1();
+  MEDCouplingFieldDouble *f1=MEDCouplingFieldDouble::New(ON_CELLS,NO_TIME);
+  f1->setMesh(mesh1);
+  DataArrayDouble *array=DataArrayDouble::New();
+  array->alloc(mesh1->getNumberOfCells(),6);
+  const double arr1[30]={1.2,2.3,3.4,4.5,5.6,6.7, 1.2,2.3,3.4,4.5,5.6,6.7, 1.2,2.3,3.4,4.5,5.6,6.7, 1.2,2.3,3.4,4.5,5.6,6.7, 1.2,2.3,3.4,4.5,5.6,6.7};
+  std::copy(arr1,arr1+30,array->getPointer());
+  f1->setArray(array);
+  array->decrRef();
+  f1->checkCoherency();
+  //
+  MEDCouplingFieldDouble *f2=f1->eigenVectors();
+  f2->checkCoherency();
+  CPPUNIT_ASSERT_EQUAL(9,f2->getNumberOfComponents());
+  CPPUNIT_ASSERT_EQUAL(5,f2->getNumberOfTuples());
+  const double expected1[9]={
+    0.5424262364180696, 0.5351201064614425, 0.6476266283176001,//eigenvect 0
+    0.7381111277307373, 0.06458838384003074, -0.6715804522117897,//eigenvect 1
+    -0.4012053603397987, 0.8423032781211455, -0.3599436712889738//eigenvect 2
+  };
+  for(int i=0;i<5;i++)
+    {
+      CPPUNIT_ASSERT_DOUBLES_EQUAL(expected1[0],f2->getIJ(i,0),1e-13);
+      CPPUNIT_ASSERT_DOUBLES_EQUAL(expected1[1],f2->getIJ(i,1),1e-13);
+      CPPUNIT_ASSERT_DOUBLES_EQUAL(expected1[2],f2->getIJ(i,2),1e-13);
+      CPPUNIT_ASSERT_DOUBLES_EQUAL(expected1[3],f2->getIJ(i,3),1e-13);
+      CPPUNIT_ASSERT_DOUBLES_EQUAL(expected1[4],f2->getIJ(i,4),1e-13);
+      CPPUNIT_ASSERT_DOUBLES_EQUAL(expected1[5],f2->getIJ(i,5),1e-13);
+      CPPUNIT_ASSERT_DOUBLES_EQUAL(expected1[6],f2->getIJ(i,6),1e-13);
+      CPPUNIT_ASSERT_DOUBLES_EQUAL(expected1[7],f2->getIJ(i,7),1e-13);
+      CPPUNIT_ASSERT_DOUBLES_EQUAL(expected1[8],f2->getIJ(i,8),1e-13);
+    }
+  f2->decrRef();
+  //
+  mesh1->decrRef();
+  f1->decrRef();
+}
+
+void MEDCouplingBasicsTest::testInverse1()
+{
+  MEDCouplingUMesh *mesh1=build2DTargetMesh_1();
+  MEDCouplingFieldDouble *f1=MEDCouplingFieldDouble::New(ON_CELLS,NO_TIME);
+  f1->setMesh(mesh1);
+  DataArrayDouble *array=DataArrayDouble::New();
+  array->alloc(mesh1->getNumberOfCells(),9);
+  const double arr1[45]={1.2,2.3,3.4,4.5,5.6,6.7,7.8,8.9,9.1, 1.2,2.3,3.4,4.5,5.6,6.7,7.8,8.9,9.1, 1.2,2.3,3.4,4.5,5.6,6.7,7.8,8.9,9.1, 1.2,2.3,3.4,4.5,5.6,6.7,7.8,8.9,9.1, 1.2,2.3,3.4,4.5,5.6,6.7,7.8,8.9,9.1};
+  std::copy(arr1,arr1+45,array->getPointer());
+  f1->setArray(array);
+  array->decrRef();
+  f1->checkCoherency();
+  //
+  MEDCouplingFieldDouble *f2=f1->inverse();
+  f2->checkCoherency();
+  CPPUNIT_ASSERT_EQUAL(9,f2->getNumberOfComponents());
+  CPPUNIT_ASSERT_EQUAL(5,f2->getNumberOfTuples());
+  const double expected1[9]={-2.6538108356290113, 2.855831037649208, -1.1111111111111067, 3.461891643709813, -4.775022956841121, 2.2222222222222143, -1.1111111111111054, 2.222222222222214, -1.1111111111111072};
+  for(int i=0;i<5;i++)
+    {
+      CPPUNIT_ASSERT_DOUBLES_EQUAL(expected1[0],f2->getIJ(i,0),1e-13);
+      CPPUNIT_ASSERT_DOUBLES_EQUAL(expected1[1],f2->getIJ(i,1),1e-13);
+      CPPUNIT_ASSERT_DOUBLES_EQUAL(expected1[2],f2->getIJ(i,2),1e-13);
+      CPPUNIT_ASSERT_DOUBLES_EQUAL(expected1[3],f2->getIJ(i,3),1e-13);
+      CPPUNIT_ASSERT_DOUBLES_EQUAL(expected1[4],f2->getIJ(i,4),1e-13);
+      CPPUNIT_ASSERT_DOUBLES_EQUAL(expected1[5],f2->getIJ(i,5),1e-13);
+      CPPUNIT_ASSERT_DOUBLES_EQUAL(expected1[6],f2->getIJ(i,6),1e-13);
+      CPPUNIT_ASSERT_DOUBLES_EQUAL(expected1[7],f2->getIJ(i,7),1e-13);
+      CPPUNIT_ASSERT_DOUBLES_EQUAL(expected1[8],f2->getIJ(i,8),1e-13);
+    }
+  f2->decrRef();
+  //
+  array=DataArrayDouble::New();
+  array->alloc(mesh1->getNumberOfCells(),6);
+  const double arr3[30]={7.8,8.9,9.1,10.2,23.4,34.5, 7.8,8.9,9.1,10.2,23.4,34.5, 7.8,8.9,9.1,10.2,23.4,34.5, 7.8,8.9,9.1,10.2,23.4,34.5, 7.8,8.9,9.1,10.2,23.4,34.5};
+  std::copy(arr3,arr3+30,array->getPointer());
+  f1->setArray(array);
+  array->decrRef();
+  f1->checkCoherency();
+  //
+  f2=f1->inverse();
+  f2->checkCoherency();
+  CPPUNIT_ASSERT_EQUAL(6,f2->getNumberOfComponents());
+  CPPUNIT_ASSERT_EQUAL(5,f2->getNumberOfTuples());
+  const double expected3[6]={-0.3617705098531818, -0.8678630828458127, -0.026843764174972983, 0.5539957431465833, 0.13133439560823013, -0.05301294502145887};
+  for(int i=0;i<5;i++)
+    {
+      CPPUNIT_ASSERT_DOUBLES_EQUAL(expected3[0],f2->getIJ(i,0),1e-13);
+      CPPUNIT_ASSERT_DOUBLES_EQUAL(expected3[1],f2->getIJ(i,1),1e-13);
+      CPPUNIT_ASSERT_DOUBLES_EQUAL(expected3[2],f2->getIJ(i,2),1e-13);
+      CPPUNIT_ASSERT_DOUBLES_EQUAL(expected3[3],f2->getIJ(i,3),1e-13);
+      CPPUNIT_ASSERT_DOUBLES_EQUAL(expected3[4],f2->getIJ(i,4),1e-13);
+      CPPUNIT_ASSERT_DOUBLES_EQUAL(expected3[5],f2->getIJ(i,5),1e-13);
+    }
+  f2->decrRef();
+  //
+  array=DataArrayDouble::New();
+  array->alloc(mesh1->getNumberOfCells(),4);
+  const double arr2[20]={1.2,2.3,3.4,4.5, 1.2,2.3,3.4,4.5, 1.2,2.3,3.4,4.5, 1.2,2.3,3.4,4.5, 1.2,2.3,3.4,4.5};
+  std::copy(arr2,arr2+20,array->getPointer());
+  f1->setArray(array);
+  array->decrRef();
+  f1->checkCoherency();
+  //
+  f2=f1->inverse();
+  f2->checkCoherency();
+  CPPUNIT_ASSERT_EQUAL(4,f2->getNumberOfComponents());
+  CPPUNIT_ASSERT_EQUAL(5,f2->getNumberOfTuples());
+  const double expected2[4]={-1.8595041322314059, 0.9504132231404963, 1.404958677685951, -0.49586776859504156};
+  for(int i=0;i<5;i++)
+    {
+      CPPUNIT_ASSERT_DOUBLES_EQUAL(expected2[0],f2->getIJ(i,0),1e-13);
+      CPPUNIT_ASSERT_DOUBLES_EQUAL(expected2[1],f2->getIJ(i,1),1e-13);
+      CPPUNIT_ASSERT_DOUBLES_EQUAL(expected2[2],f2->getIJ(i,2),1e-13);
+      CPPUNIT_ASSERT_DOUBLES_EQUAL(expected2[3],f2->getIJ(i,3),1e-13);
+    }
+  f2->decrRef();
+  //
+  mesh1->decrRef();
+  f1->decrRef();
+}
+
+void MEDCouplingBasicsTest::testTrace1()
+{
+  MEDCouplingUMesh *mesh1=build2DTargetMesh_1();
+  MEDCouplingFieldDouble *f1=MEDCouplingFieldDouble::New(ON_CELLS,NO_TIME);
+  f1->setMesh(mesh1);
+  DataArrayDouble *array=DataArrayDouble::New();
+  array->alloc(mesh1->getNumberOfCells(),9);
+  const double arr1[45]={1.2,2.3,3.4,4.5,5.6,6.7,7.8,8.9,9.1, 1.2,2.3,3.4,4.5,5.6,6.7,7.8,8.9,9.1, 1.2,2.3,3.4,4.5,5.6,6.7,7.8,8.9,9.1, 1.2,2.3,3.4,4.5,5.6,6.7,7.8,8.9,9.1, 1.2,2.3,3.4,4.5,5.6,6.7,7.8,8.9,9.1};
+  std::copy(arr1,arr1+45,array->getPointer());
+  f1->setArray(array);
+  array->decrRef();
+  f1->checkCoherency();
+  //
+  MEDCouplingFieldDouble *f2=f1->trace();
+  f2->checkCoherency();
+  CPPUNIT_ASSERT_EQUAL(1,f2->getNumberOfComponents());
+  CPPUNIT_ASSERT_EQUAL(5,f2->getNumberOfTuples());
+  for(int i=0;i<5;i++)
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(15.9,f2->getIJ(i,0),1e-13);
+  f2->decrRef();
+  //
+  array=DataArrayDouble::New();
+  array->alloc(mesh1->getNumberOfCells(),6);
+  const double arr3[30]={7.8,8.9,9.1,10.2,23.4,34.5, 7.8,8.9,9.1,10.2,23.4,34.5, 7.8,8.9,9.1,10.2,23.4,34.5, 7.8,8.9,9.1,10.2,23.4,34.5, 7.8,8.9,9.1,10.2,23.4,34.5};
+  std::copy(arr3,arr3+30,array->getPointer());
+  f1->setArray(array);
+  array->decrRef();
+  f1->checkCoherency();
+  //
+  f2=f1->trace();
+  f2->checkCoherency();
+  CPPUNIT_ASSERT_EQUAL(1,f2->getNumberOfComponents());
+  CPPUNIT_ASSERT_EQUAL(5,f2->getNumberOfTuples());
+  for(int i=0;i<5;i++)
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(25.8,f2->getIJ(i,0),1e-13);
+  f2->decrRef();
+  //
+  array=DataArrayDouble::New();
+  array->alloc(mesh1->getNumberOfCells(),4);
+  const double arr2[20]={1.2,2.3,3.4,4.5, 1.2,2.3,3.4,4.5, 1.2,2.3,3.4,4.5, 1.2,2.3,3.4,4.5, 1.2,2.3,3.4,4.5};
+  std::copy(arr2,arr2+20,array->getPointer());
+  f1->setArray(array);
+  array->decrRef();
+  f1->checkCoherency();
+  //
+  f2=f1->trace();
+  f2->checkCoherency();
+  CPPUNIT_ASSERT_EQUAL(1,f2->getNumberOfComponents());
+  CPPUNIT_ASSERT_EQUAL(5,f2->getNumberOfTuples());
+  for(int i=0;i<5;i++)
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(5.7,f2->getIJ(i,0),1e-13);
+  f2->decrRef();
+  //
+  mesh1->decrRef();
+  f1->decrRef();
+}
+
+void MEDCouplingBasicsTest::testDeviator1()
+{
+  MEDCouplingUMesh *mesh1=build2DTargetMesh_1();
+  MEDCouplingFieldDouble *f1=MEDCouplingFieldDouble::New(ON_CELLS,NO_TIME);
+  f1->setMesh(mesh1);
+  DataArrayDouble *array=DataArrayDouble::New();
+  array->alloc(mesh1->getNumberOfCells(),6);
+  const double arr1[30]={1.2,2.3,3.4,4.5,5.6,6.7, 1.2,2.3,3.4,4.5,5.6,6.7, 1.2,2.3,3.4,4.5,5.6,6.7, 1.2,2.3,3.4,4.5,5.6,6.7, 1.2,2.3,3.4,4.5,5.6,6.7};
+  std::copy(arr1,arr1+30,array->getPointer());
+  f1->setArray(array);
+  array->decrRef();
+  f1->checkCoherency();
+  //
+  MEDCouplingFieldDouble *f2=f1->deviator();
+  f2->checkCoherency();
+  CPPUNIT_ASSERT_EQUAL(6,f2->getNumberOfComponents());
+  CPPUNIT_ASSERT_EQUAL(5,f2->getNumberOfTuples());
+  const double expected1[6]={-1.1,0.,1.1,4.5,5.6,6.7};
+  for(int i=0;i<5;i++)
+    {
+      CPPUNIT_ASSERT_DOUBLES_EQUAL(expected1[0],f2->getIJ(i,0),1e-13);
+      CPPUNIT_ASSERT_DOUBLES_EQUAL(expected1[1],f2->getIJ(i,1),1e-13);
+      CPPUNIT_ASSERT_DOUBLES_EQUAL(expected1[2],f2->getIJ(i,2),1e-13);
+      CPPUNIT_ASSERT_DOUBLES_EQUAL(expected1[3],f2->getIJ(i,3),1e-13);
+      CPPUNIT_ASSERT_DOUBLES_EQUAL(expected1[4],f2->getIJ(i,4),1e-13);
+      CPPUNIT_ASSERT_DOUBLES_EQUAL(expected1[5],f2->getIJ(i,5),1e-13);
+    }
+  f2->decrRef();
+  //
+  mesh1->decrRef();
+  f1->decrRef();
+}
+
+void MEDCouplingBasicsTest::testMagnitude1()
+{
+  MEDCouplingUMesh *mesh1=build2DTargetMesh_1();
+  MEDCouplingFieldDouble *f1=MEDCouplingFieldDouble::New(ON_CELLS,NO_TIME);
+  f1->setMesh(mesh1);
+  DataArrayDouble *array=DataArrayDouble::New();
+  array->alloc(mesh1->getNumberOfCells(),5);
+  const double arr1[25]={1.2,2.3,3.4,4.5,5.6, 1.2,2.3,3.4,4.5,5.6, 1.2,2.3,3.4,4.5,5.6, 1.2,2.3,3.4,4.5,5.6, 1.2,2.3,3.4,4.5,5.6};
+  std::copy(arr1,arr1+25,array->getPointer());
+  f1->setArray(array);
+  array->decrRef();
+  f1->checkCoherency();
+  //
+  MEDCouplingFieldDouble *f2=f1->magnitude();
+  f2->checkCoherency();
+  CPPUNIT_ASSERT_EQUAL(1,f2->getNumberOfComponents());
+  CPPUNIT_ASSERT_EQUAL(5,f2->getNumberOfTuples());
+  for(int i=0;i<5;i++)
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(8.3606219864313918,f2->getIJ(i,0),1e-13);
+  f2->decrRef();
+  //
+  mesh1->decrRef();
+  f1->decrRef();
+}
+
+void MEDCouplingBasicsTest::testMaxPerTuple1()
+{
+  MEDCouplingUMesh *mesh1=build2DTargetMesh_1();
+  MEDCouplingFieldDouble *f1=MEDCouplingFieldDouble::New(ON_CELLS,NO_TIME);
+  f1->setMesh(mesh1);
+  DataArrayDouble *array=DataArrayDouble::New();
+  array->alloc(mesh1->getNumberOfCells(),5);
+  const double arr1[25]={1.2,2.3,3.4,4.5,5.6, 1.2,3.4,4.5,5.6,2.3, 3.4,4.5,5.6,1.2,2.3, 5.6,1.2,2.3,3.4,4.5, 4.5,5.6,1.2,2.3,3.4};
+  std::copy(arr1,arr1+25,array->getPointer());
+  f1->setArray(array);
+  array->decrRef();
+  f1->checkCoherency();
+  //
+  MEDCouplingFieldDouble *f2=f1->maxPerTuple();
+  f2->checkCoherency();
+  CPPUNIT_ASSERT_EQUAL(1,f2->getNumberOfComponents());
+  CPPUNIT_ASSERT_EQUAL(5,f2->getNumberOfTuples());
+  for(int i=0;i<5;i++)
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(5.6,f2->getIJ(i,0),1e-13);
+  f2->decrRef();
+  //
+  mesh1->decrRef();
+  f1->decrRef();
+}
+
+void MEDCouplingBasicsTest::testChangeNbOfComponents()
+{
+  MEDCouplingUMesh *mesh1=build2DTargetMesh_1();
+  MEDCouplingFieldDouble *f1=MEDCouplingFieldDouble::New(ON_CELLS,NO_TIME);
+  f1->setMesh(mesh1);
+  DataArrayDouble *array=DataArrayDouble::New();
+  array->alloc(mesh1->getNumberOfCells(),5);
+  const double arr1[25]={1.2,2.3,3.4,4.5,5.6, 1.2,3.4,4.5,5.6,2.3, 3.4,4.5,5.6,1.2,2.3, 5.6,1.2,2.3,3.4,4.5, 4.5,5.6,1.2,2.3,3.4};
+  std::copy(arr1,arr1+25,array->getPointer());
+  f1->setArray(array);
+  array->decrRef();
+  f1->checkCoherency();
+  //
+  f1->changeNbOfComponents(3,7.77);
+  f1->checkCoherency();
+  CPPUNIT_ASSERT_EQUAL(3,f1->getNumberOfComponents());
+  CPPUNIT_ASSERT_EQUAL(5,f1->getNumberOfTuples());
+  const double expected1[15]={1.2,2.3,3.4, 1.2,3.4,4.5, 3.4,4.5,5.6, 5.6,1.2,2.3, 4.5,5.6,1.2};
+  for(int i=0;i<15;i++)
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(expected1[i],f1->getIJ(0,i),1e-13);
+  f1->changeNbOfComponents(4,7.77);
+  f1->checkCoherency();
+  CPPUNIT_ASSERT_EQUAL(4,f1->getNumberOfComponents());
+  CPPUNIT_ASSERT_EQUAL(5,f1->getNumberOfTuples());
+  const double expected2[20]={1.2,2.3,3.4,7.77, 1.2,3.4,4.5,7.77, 3.4,4.5,5.6,7.77, 5.6,1.2,2.3,7.77, 4.5,5.6,1.2,7.77};
+  for(int i=0;i<20;i++)
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(expected2[i],f1->getIJ(0,i),1e-13);
+  //
+  mesh1->decrRef();
+  f1->decrRef();
+}
+
+void MEDCouplingBasicsTest::testSortPerTuple1()
+{
+  MEDCouplingUMesh *mesh1=build2DTargetMesh_1();
+  MEDCouplingFieldDouble *f1=MEDCouplingFieldDouble::New(ON_CELLS,NO_TIME);
+  f1->setMesh(mesh1);
+  DataArrayDouble *array=DataArrayDouble::New();
+  array->alloc(mesh1->getNumberOfCells(),5);
+  const double arr1[25]={1.2,2.3,3.4,4.5,5.6, 1.2,3.4,4.5,5.6,2.3, 3.4,4.5,5.6,1.2,2.3, 5.6,1.2,2.3,3.4,4.5, 4.5,5.6,1.2,2.3,3.4};
+  std::copy(arr1,arr1+25,array->getPointer());
+  f1->setArray(array);
+  array->decrRef();
+  f1->checkCoherency();
+  //
+  f1->sortPerTuple(true);
+  f1->checkCoherency();
+  CPPUNIT_ASSERT_EQUAL(5,f1->getNumberOfComponents());
+  CPPUNIT_ASSERT_EQUAL(5,f1->getNumberOfTuples());
+  for(int i=0;i<5;i++)
+    {
+      CPPUNIT_ASSERT_DOUBLES_EQUAL(arr1[0],f1->getIJ(i,0),1e-13);
+      CPPUNIT_ASSERT_DOUBLES_EQUAL(arr1[1],f1->getIJ(i,1),1e-13);
+      CPPUNIT_ASSERT_DOUBLES_EQUAL(arr1[2],f1->getIJ(i,2),1e-13);
+      CPPUNIT_ASSERT_DOUBLES_EQUAL(arr1[3],f1->getIJ(i,3),1e-13);
+      CPPUNIT_ASSERT_DOUBLES_EQUAL(arr1[4],f1->getIJ(i,4),1e-13);
+    }
+  //
+  f1->sortPerTuple(false);
+  f1->checkCoherency();
+  CPPUNIT_ASSERT_EQUAL(5,f1->getNumberOfComponents());
+  CPPUNIT_ASSERT_EQUAL(5,f1->getNumberOfTuples());
+  for(int i=0;i<5;i++)
+    {
+      CPPUNIT_ASSERT_DOUBLES_EQUAL(arr1[4],f1->getIJ(i,0),1e-13);
+      CPPUNIT_ASSERT_DOUBLES_EQUAL(arr1[3],f1->getIJ(i,1),1e-13);
+      CPPUNIT_ASSERT_DOUBLES_EQUAL(arr1[2],f1->getIJ(i,2),1e-13);
+      CPPUNIT_ASSERT_DOUBLES_EQUAL(arr1[1],f1->getIJ(i,3),1e-13);
+      CPPUNIT_ASSERT_DOUBLES_EQUAL(arr1[0],f1->getIJ(i,4),1e-13);
+    }
+  //
+  mesh1->decrRef();
+  f1->decrRef();
+}
+
+void MEDCouplingBasicsTest::testIsEqualWithoutConsideringStr1()
+{
+  MEDCouplingUMesh *mesh1=build2DTargetMesh_1();
+  MEDCouplingUMesh *mesh2=build2DTargetMesh_1();
+  DataArrayInt *da1,*da2;
+  //
+  CPPUNIT_ASSERT(mesh1->isEqual(mesh2,1e-12));
+  CPPUNIT_ASSERT(mesh1->isEqualWithoutConsideringStr(mesh2,1e-12));
+  mesh2->setName("rr");
+  CPPUNIT_ASSERT(!mesh1->isEqual(mesh2,1e-12));
+  CPPUNIT_ASSERT(mesh1->isEqualWithoutConsideringStr(mesh2,1e-12));
+  mesh1->checkDeepEquivalWith(mesh2,2,1e-12,da1,da2);
+  CPPUNIT_ASSERT_THROW(mesh1->checkGeoEquivalWith(mesh2,0,1e-12,da1,da2),INTERP_KERNEL::Exception);
+  mesh2->setName("");
+  CPPUNIT_ASSERT(mesh1->isEqual(mesh2,1e-12));
+  CPPUNIT_ASSERT(mesh1->isEqualWithoutConsideringStr(mesh2,1e-12));
+  mesh2->getCoords()->setInfoOnComponent(0,"tty");
+  CPPUNIT_ASSERT(!mesh1->isEqual(mesh2,1e-12));
+  CPPUNIT_ASSERT(mesh1->isEqualWithoutConsideringStr(mesh2,1e-12));
+  mesh2->getCoords()->setInfoOnComponent(0,"");
+  CPPUNIT_ASSERT(mesh1->isEqual(mesh2,1e-12));
+  CPPUNIT_ASSERT(mesh1->isEqualWithoutConsideringStr(mesh2,1e-12));
+  mesh2->getCoords()->setInfoOnComponent(1,"tty");
+  CPPUNIT_ASSERT(!mesh1->isEqual(mesh2,1e-12));
+  CPPUNIT_ASSERT(mesh1->isEqualWithoutConsideringStr(mesh2,1e-12));
+  mesh2->getCoords()->setInfoOnComponent(1,"");
+  CPPUNIT_ASSERT(mesh1->isEqual(mesh2,1e-12));
+  CPPUNIT_ASSERT(mesh1->isEqualWithoutConsideringStr(mesh2,1e-12));
+  double tmp=mesh2->getCoords()->getIJ(0,3);
+  mesh2->getCoords()->setIJ(0,3,9999.);
+  CPPUNIT_ASSERT(!mesh1->isEqual(mesh2,1e-12));
+  CPPUNIT_ASSERT(!mesh1->isEqualWithoutConsideringStr(mesh2,1e-12));
+  mesh2->getCoords()->setIJ(0,3,tmp);
+  CPPUNIT_ASSERT(mesh1->isEqual(mesh2,1e-12));
+  CPPUNIT_ASSERT(mesh1->isEqualWithoutConsideringStr(mesh2,1e-12));
+  int tmp2=mesh2->getNodalConnectivity()->getIJ(0,4);
+  mesh2->getNodalConnectivity()->setIJ(0,4,0);
+  CPPUNIT_ASSERT(!mesh1->isEqual(mesh2,1e-12));
+  CPPUNIT_ASSERT(!mesh1->isEqualWithoutConsideringStr(mesh2,1e-12));
+  mesh2->getNodalConnectivity()->setIJ(0,4,tmp2);
+  CPPUNIT_ASSERT(mesh1->isEqual(mesh2,1e-12));
+  CPPUNIT_ASSERT(mesh1->isEqualWithoutConsideringStr(mesh2,1e-12));
+  //
+  MEDCouplingFieldDouble *f1=mesh1->getMeasureField(true);
+  MEDCouplingFieldDouble *f2=mesh2->getMeasureField(true);
+  CPPUNIT_ASSERT(f1->isEqual(f2,1e-12,1e-12));
+  CPPUNIT_ASSERT(f1->isEqualWithoutConsideringStr(f2,1e-12,1e-12));
+  f2->setName("ftest");
+  CPPUNIT_ASSERT(!f1->isEqual(f2,1e-12,1e-12));
+  CPPUNIT_ASSERT(f1->isEqualWithoutConsideringStr(f2,1e-12,1e-12));
+  f1->setName("ftest");
+  CPPUNIT_ASSERT(f1->isEqual(f2,1e-12,1e-12));
+  CPPUNIT_ASSERT(f1->isEqualWithoutConsideringStr(f2,1e-12,1e-12));
+  //
+  f2->getArray()->setInfoOnComponent(0,"eee");
+  CPPUNIT_ASSERT(!f1->isEqual(f2,1e-12,1e-12));
+  CPPUNIT_ASSERT(f1->isEqualWithoutConsideringStr(f2,1e-12,1e-12));
+  f2->getArray()->setInfoOnComponent(0,"");
+  CPPUNIT_ASSERT(f1->isEqual(f2,1e-12,1e-12));
+  CPPUNIT_ASSERT(f1->isEqualWithoutConsideringStr(f2,1e-12,1e-12));
+  //
+  f2->getArray()->setIJ(1,0,0.123);
+  CPPUNIT_ASSERT(!f1->isEqual(f2,1e-12,1e-12));
+  CPPUNIT_ASSERT(!f1->isEqualWithoutConsideringStr(f2,1e-12,1e-12));
+  f2->getArray()->setIJ(1,0,0.125);
+  CPPUNIT_ASSERT(f1->isEqual(f2,1e-12,1e-12));
+  CPPUNIT_ASSERT(f1->isEqualWithoutConsideringStr(f2,1e-12,1e-12));
+  //
+  f1->decrRef();
+  f2->decrRef();
+  //
+  mesh1->decrRef();
+  mesh2->decrRef();
+}
+
+void MEDCouplingBasicsTest::testGetNodeIdsOfCell1()
+{
+  MEDCouplingUMesh *mesh1=build2DTargetMesh_1();
+  std::vector<int> nodeIds;
+  mesh1->getNodeIdsOfCell(1,nodeIds);
+  CPPUNIT_ASSERT_EQUAL(3,(int)nodeIds.size());
+  CPPUNIT_ASSERT_EQUAL(1,nodeIds[0]);
+  CPPUNIT_ASSERT_EQUAL(4,nodeIds[1]);
+  CPPUNIT_ASSERT_EQUAL(2,nodeIds[2]);
+  std::vector<double> coords;
+  mesh1->getCoordinatesOfNode(4,coords);
+  CPPUNIT_ASSERT_EQUAL(2,(int)coords.size());
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(0.2,coords[0],1e-13);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(0.2,coords[1],1e-13);
+  mesh1->decrRef();
+}
index b7c30b71262302df4672f5b61c1c92584fdf0b7a..1050f75ce5735cad96707d1edcc9e57d73cf34fe 100644 (file)
@@ -158,6 +158,119 @@ void MEDCouplingRemapperTest::test2DInterpP0P0R_1()
   targetMesh->decrRef();
 }
 
+void MEDCouplingRemapperTest::test1DInterp_1()
+{
+  MEDCouplingUMesh *sourceMesh=MEDCouplingBasicsTest::build1DSourceMesh_2();
+  MEDCouplingUMesh *targetMesh=MEDCouplingBasicsTest::build1DTargetMesh_2();
+  //
+  MEDCouplingRemapper remapper;
+  CPPUNIT_ASSERT_EQUAL(1,remapper.prepare(sourceMesh,targetMesh,"P0P0"));
+  MEDCouplingFieldDouble *srcField=MEDCouplingFieldDouble::New(ON_CELLS);
+  srcField->setNature(ConservativeVolumic);
+  srcField->setMesh(sourceMesh);
+  DataArrayDouble *array=DataArrayDouble::New();
+  array->alloc(sourceMesh->getNumberOfCells(),1);
+  srcField->setArray(array);
+  double *ptr=array->getPointer();
+  for(int i=0;i<sourceMesh->getNumberOfCells();i++)
+    ptr[i]=(double)(i+7);
+  array->decrRef();
+  //
+  MEDCouplingFieldDouble *trgfield=remapper.transferField(srcField,4.57);
+  const double *values=trgfield->getArray()->getConstPointer();
+  const double valuesExpected1[2]={9.0540540540540526,7.4};
+  CPPUNIT_ASSERT_EQUAL(2,trgfield->getArray()->getNumberOfTuples());
+  CPPUNIT_ASSERT_EQUAL(1,trgfield->getArray()->getNumberOfComponents());
+  for(int i0=0;i0<2;i0++)
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(valuesExpected1[i0],values[i0],1e-12);
+  trgfield->decrRef();
+  const double valuesExpected2[2]={24.75,5.75};
+  srcField->setNature(Integral);
+  trgfield=remapper.transferField(srcField,4.57);
+  values=trgfield->getArray()->getConstPointer();
+  CPPUNIT_ASSERT_EQUAL(2,trgfield->getArray()->getNumberOfTuples());
+  CPPUNIT_ASSERT_EQUAL(1,trgfield->getArray()->getNumberOfComponents());
+  for(int i0=0;i0<2;i0++)
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(valuesExpected2[i0],values[i0],1e-12);
+  trgfield->decrRef();
+  //
+  const double valuesExpected3[2]={24.75,9.25};
+  srcField->setNature(IntegralGlobConstraint);
+  trgfield=remapper.transferField(srcField,4.57);
+  values=trgfield->getArray()->getConstPointer();
+  CPPUNIT_ASSERT_EQUAL(2,trgfield->getArray()->getNumberOfTuples());
+  CPPUNIT_ASSERT_EQUAL(1,trgfield->getArray()->getNumberOfComponents());
+  for(int i0=0;i0<2;i0++)
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(valuesExpected3[i0],values[i0],1e-12);
+  trgfield->decrRef();
+  //
+  const double valuesExpected4[2]={7.4444444444444446,7.4};
+  srcField->setNature(RevIntegral);
+  trgfield=remapper.transferField(srcField,4.57);
+  values=trgfield->getArray()->getConstPointer();
+  CPPUNIT_ASSERT_EQUAL(2,trgfield->getArray()->getNumberOfTuples());
+  CPPUNIT_ASSERT_EQUAL(1,trgfield->getArray()->getNumberOfComponents());
+  for(int i0=0;i0<2;i0++)
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(valuesExpected4[i0],values[i0],1e-12);
+  trgfield->decrRef();
+  //
+  srcField->decrRef();
+  sourceMesh->decrRef();
+  targetMesh->decrRef();
+  //2D Curve
+  sourceMesh=MEDCouplingBasicsTest::build2DCurveSourceMesh_2();
+  targetMesh=MEDCouplingBasicsTest::build2DCurveTargetMesh_2();
+  CPPUNIT_ASSERT_EQUAL(1,remapper.prepare(sourceMesh,targetMesh,"P0P0"));
+  srcField=MEDCouplingFieldDouble::New(ON_CELLS);
+  srcField->setNature(ConservativeVolumic);
+  srcField->setMesh(sourceMesh);
+  array=DataArrayDouble::New();
+  array->alloc(sourceMesh->getNumberOfCells(),1);
+  srcField->setArray(array);
+  ptr=array->getPointer();
+  for(int i=0;i<sourceMesh->getNumberOfCells();i++)
+    ptr[i]=(double)(i+7);
+  array->decrRef();
+  //
+  trgfield=remapper.transferField(srcField,4.57);
+  values=trgfield->getArray()->getConstPointer();
+  CPPUNIT_ASSERT_EQUAL(2,trgfield->getArray()->getNumberOfTuples());
+  CPPUNIT_ASSERT_EQUAL(1,trgfield->getArray()->getNumberOfComponents());
+  for(int i0=0;i0<2;i0++)
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(valuesExpected1[i0],values[i0],1e-12);
+  trgfield->decrRef();
+  srcField->setNature(Integral);
+  trgfield=remapper.transferField(srcField,4.57);
+  values=trgfield->getArray()->getConstPointer();
+  CPPUNIT_ASSERT_EQUAL(2,trgfield->getArray()->getNumberOfTuples());
+  CPPUNIT_ASSERT_EQUAL(1,trgfield->getArray()->getNumberOfComponents());
+  for(int i0=0;i0<2;i0++)
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(valuesExpected2[i0],values[i0],1e-12);
+  trgfield->decrRef();
+  //
+  srcField->setNature(IntegralGlobConstraint);
+  trgfield=remapper.transferField(srcField,4.57);
+  values=trgfield->getArray()->getConstPointer();
+  CPPUNIT_ASSERT_EQUAL(2,trgfield->getArray()->getNumberOfTuples());
+  CPPUNIT_ASSERT_EQUAL(1,trgfield->getArray()->getNumberOfComponents());
+  for(int i0=0;i0<2;i0++)
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(valuesExpected3[i0],values[i0],1e-12);
+  trgfield->decrRef();
+  //
+  srcField->setNature(RevIntegral);
+  trgfield=remapper.transferField(srcField,4.57);
+  values=trgfield->getArray()->getConstPointer();
+  CPPUNIT_ASSERT_EQUAL(2,trgfield->getArray()->getNumberOfTuples());
+  CPPUNIT_ASSERT_EQUAL(1,trgfield->getArray()->getNumberOfComponents());
+  for(int i0=0;i0<2;i0++)
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(valuesExpected4[i0],values[i0],1e-12);
+  trgfield->decrRef();
+  //
+  srcField->decrRef();
+  sourceMesh->decrRef();
+  targetMesh->decrRef();
+}
+
 void MEDCouplingRemapperTest::test2DInterpMultiMethods()
 {
   MEDCouplingUMesh *sourceMesh=MEDCouplingBasicsTest::build2DSourceMesh_1();
@@ -709,7 +822,8 @@ void MEDCouplingRemapperTest::testExtruded2()
   MEDCouplingUMesh *meshN2D=(MEDCouplingUMesh *)meshN->buildFacePartOfMySelfNode(&n[0],&n[0]+n.size(),true);
   n.clear();
   bool b=false;
-  DataArrayInt *da=meshTT->mergeNodes(1e-12,b);
+  int newNbOfNodes;
+  DataArrayInt *da=meshTT->mergeNodes(1e-12,b,newNbOfNodes);
   CPPUNIT_ASSERT(b);
   da->decrRef();
   meshTT->findNodesOnPlane(pt,v,1e-12,n);
index 61dc0e70141b39b2aa0e82226e0d8b622f38b4c7..2b45b4b0665d2b31e60c78cfc333ccec0796fb8d 100644 (file)
@@ -34,6 +34,7 @@ namespace ParaMEDMEM
     CPPUNIT_TEST_SUITE(MEDCouplingRemapperTest);
     CPPUNIT_TEST( test2DInterpP0P0_1 );
     CPPUNIT_TEST( test2DInterpP0P0R_1 );
+    CPPUNIT_TEST( test1DInterp_1 );
     CPPUNIT_TEST( test2DInterpMultiMethods );
     CPPUNIT_TEST( testMultiDimCombi );
     CPPUNIT_TEST( testNatureOfField );
@@ -43,6 +44,7 @@ namespace ParaMEDMEM
   public:
     void test2DInterpP0P0_1();
     void test2DInterpP0P0R_1();
+    void test1DInterp_1();
     void test2DInterpMultiMethods();
     void testMultiDimCombi();
     void testNatureOfField();
index 2db4726a9774ef05e0785c42998e25ae09cd850a..bab460971e42860984408c7700ab6e9db7d9afd9 100755 (executable)
@@ -26,10 +26,18 @@ TestMEDCoupling_CPPFLAGS=@CPPUNIT_INCLUDES@ @PTHREAD_CFLAGS@ -I$(srcdir)/.. -I$(
 TestMEDCoupling_LDFLAGS = @CPPUNIT_LIBS@ ../libmedcoupling.la ../../INTERP_KERNEL/libinterpkernel.la
 
 dist_TestMEDCoupling_SOURCES = TestMEDCoupling.cxx MEDCouplingBasicsTest.hxx MEDCouplingBasicsTest0.cxx MEDCouplingBasicsTest1.cxx \
-       MEDCouplingBasicsTestInterp.cxx MEDCouplingBasicsTestData1.hxx
+       MEDCouplingBasicsTest2.cxx MEDCouplingBasicsTestInterp.cxx MEDCouplingBasicsTestData1.hxx
 
 TestMEDCouplingRemapper_CPPFLAGS=@CPPUNIT_INCLUDES@ @PTHREAD_CFLAGS@ -I$(srcdir)/.. -I$(srcdir)/../../INTERP_KERNEL/Bases -I$(srcdir)/../../INTERP_KERNELTest -I$(srcdir)/../../INTERP_KERNEL -I$(srcdir)/../../INTERP_KERNEL/Geometric2D
 
 TestMEDCouplingRemapper_LDFLAGS = @CPPUNIT_LIBS@ ../libmedcouplingremapper.la ../../INTERP_KERNEL/libinterpkernel.la
 
-dist_TestMEDCouplingRemapper_SOURCES = TestMEDCouplingRemapper.cxx MEDCouplingRemapperTest.hxx MEDCouplingRemapperTest.cxx MEDCouplingBasicsTest0.cxx
\ No newline at end of file
+dist_TestMEDCouplingRemapper_SOURCES = TestMEDCouplingRemapper.cxx MEDCouplingRemapperTest.hxx MEDCouplingRemapperTest.cxx MEDCouplingBasicsTest0.cxx
+
+UNIT_TEST_PROG = TestMEDCoupling TestMEDCouplingRemapper
+
+check : tests
+
+CLEANFILES = \
+        UnitTestsResult
+       
\ No newline at end of file