From 2f9783b7a7db1a04a481e8384e97830438e34a5e Mon Sep 17 00:00:00 2001 From: ageay Date: Wed, 13 Oct 2010 10:24:39 +0000 Subject: [PATCH] Update from V515BR --- src/INTERP_KERNEL/CellModel.cxx | 45 +- src/INTERP_KERNEL/CellModel.hxx | 6 + src/INTERP_KERNEL/CurveIntersectorP0P1.txx | 2 +- src/INTERP_KERNEL/CurveIntersectorP1P0.txx | 2 +- src/INTERP_KERNEL/CurveIntersectorP1P1.txx | 4 +- src/INTERP_KERNEL/DirectedBoundingBox.cxx | 22 +- src/INTERP_KERNEL/DirectedBoundingBox.hxx | 11 +- .../ExprEval/InterpKernelAsmX86.cxx | 477 ++++ .../ExprEval/InterpKernelAsmX86.hxx | 67 + .../ExprEval/InterpKernelExprParser.cxx | 196 +- .../ExprEval/InterpKernelExprParser.hxx | 21 +- .../ExprEval/InterpKernelFunction.cxx | 85 +- .../ExprEval/InterpKernelFunction.hxx | 18 + src/INTERP_KERNEL/ExprEval/Makefile.am | 7 +- src/INTERP_KERNEL/GenMathFormulae.hxx | 95 + src/INTERP_KERNEL/InterpolationOptions.cxx | 2 +- src/INTERP_KERNEL/InterpolationOptions.hxx | 4 +- src/INTERP_KERNEL/InterpolationUtils.hxx | 8 +- src/INTERP_KERNEL/Makefile.am | 12 +- .../TranslationRotationMatrix.cxx | 22 + .../TranslationRotationMatrix.hxx | 5 +- src/INTERP_KERNEL/VolSurfFormulae.hxx | 186 +- src/INTERP_KERNEL/VolSurfUser.hxx | 6 + src/INTERP_KERNEL/VolSurfUser.txx | 112 +- .../MEDCouplingAutoRefCountObjectPtr.hxx | 50 + src/MEDCoupling/MEDCouplingCMesh.cxx | 304 ++- src/MEDCoupling/MEDCouplingCMesh.hxx | 23 +- src/MEDCoupling/MEDCouplingExtrudedMesh.cxx | 322 ++- src/MEDCoupling/MEDCouplingExtrudedMesh.hxx | 27 +- src/MEDCoupling/MEDCouplingField.cxx | 183 +- src/MEDCoupling/MEDCouplingField.hxx | 22 +- .../MEDCouplingFieldDiscretization.cxx | 900 +++++++- .../MEDCouplingFieldDiscretization.hxx | 169 +- src/MEDCoupling/MEDCouplingFieldDouble.cxx | 821 ++++++- src/MEDCoupling/MEDCouplingFieldDouble.hxx | 85 +- .../MEDCouplingGaussLocalization.cxx | 215 ++ .../MEDCouplingGaussLocalization.hxx | 70 + src/MEDCoupling/MEDCouplingMemArray.cxx | 1002 ++++++++- src/MEDCoupling/MEDCouplingMemArray.hxx | 90 +- src/MEDCoupling/MEDCouplingMemArray.txx | 88 + src/MEDCoupling/MEDCouplingMesh.cxx | 131 +- src/MEDCoupling/MEDCouplingMesh.hxx | 32 +- src/MEDCoupling/MEDCouplingNatureOfField.cxx | 44 + src/MEDCoupling/MEDCouplingNatureOfField.hxx | 17 +- .../MEDCouplingNormalizedCartesianMesh.hxx | 4 +- .../MEDCouplingNormalizedUnstructuredMesh.hxx | 4 +- src/MEDCoupling/MEDCouplingPointSet.cxx | 142 +- src/MEDCoupling/MEDCouplingPointSet.hxx | 29 +- src/MEDCoupling/MEDCouplingPointSet.txx | 7 +- src/MEDCoupling/MEDCouplingRefCountObject.hxx | 4 +- src/MEDCoupling/MEDCouplingRemapper.cxx | 34 +- src/MEDCoupling/MEDCouplingRemapper.hxx | 19 +- .../MEDCouplingTimeDiscretization.cxx | 1248 +++++++++-- .../MEDCouplingTimeDiscretization.hxx | 182 +- src/MEDCoupling/MEDCouplingUMesh.cxx | 1489 ++++++++++++- src/MEDCoupling/MEDCouplingUMesh.hxx | 60 +- src/MEDCoupling/MEDCouplingUMeshDesc.cxx | 60 +- src/MEDCoupling/MEDCouplingUMeshDesc.hxx | 12 +- src/MEDCoupling/Makefile.am | 23 +- .../Test/MEDCouplingBasicsTest.hxx | 112 +- .../Test/MEDCouplingBasicsTest0.cxx | 164 ++ .../Test/MEDCouplingBasicsTest1.cxx | 551 ++++- .../Test/MEDCouplingBasicsTest2.cxx | 1979 +++++++++++++++++ .../Test/MEDCouplingRemapperTest.cxx | 116 +- .../Test/MEDCouplingRemapperTest.hxx | 2 + src/MEDCoupling/Test/Makefile.am | 12 +- 66 files changed, 11614 insertions(+), 649 deletions(-) create mode 100644 src/INTERP_KERNEL/ExprEval/InterpKernelAsmX86.cxx create mode 100644 src/INTERP_KERNEL/ExprEval/InterpKernelAsmX86.hxx create mode 100644 src/INTERP_KERNEL/GenMathFormulae.hxx create mode 100644 src/INTERP_KERNEL/TranslationRotationMatrix.cxx create mode 100644 src/MEDCoupling/MEDCouplingAutoRefCountObjectPtr.hxx create mode 100644 src/MEDCoupling/MEDCouplingGaussLocalization.cxx create mode 100644 src/MEDCoupling/MEDCouplingGaussLocalization.hxx create mode 100644 src/MEDCoupling/MEDCouplingNatureOfField.cxx create mode 100644 src/MEDCoupling/Test/MEDCouplingBasicsTest2.cxx diff --git a/src/INTERP_KERNEL/CellModel.cxx b/src/INTERP_KERNEL/CellModel.cxx index af6dac5ad..88bc7a820 100644 --- a/src/INTERP_KERNEL/CellModel.cxx +++ b/src/INTERP_KERNEL/CellModel.cxx @@ -27,6 +27,16 @@ 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 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; diff --git a/src/INTERP_KERNEL/CellModel.hxx b/src/INTERP_KERNEL/CellModel.hxx index 393fea0eb..23b735512 100644 --- a/src/INTERP_KERNEL/CellModel.hxx +++ b/src/INTERP_KERNEL/CellModel.hxx @@ -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 _map_of_unique_instance; + static const char *CELL_TYPES_REPR[]; }; } diff --git a/src/INTERP_KERNEL/CurveIntersectorP0P1.txx b/src/INTERP_KERNEL/CurveIntersectorP0P1.txx index c25136b5d..1947a9f5b 100644 --- a/src/INTERP_KERNEL/CurveIntersectorP0P1.txx +++ b/src/INTERP_KERNEL/CurveIntersectorP0P1.txx @@ -60,7 +60,7 @@ namespace INTERP_KERNEL { std::vector 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::ind2C( segmentsT[t]._nodeId )]; for(typename std::vector::const_iterator diff --git a/src/INTERP_KERNEL/CurveIntersectorP1P0.txx b/src/INTERP_KERNEL/CurveIntersectorP1P0.txx index bafd3ad9e..f4e136dd3 100644 --- a/src/INTERP_KERNEL/CurveIntersectorP1P0.txx +++ b/src/INTERP_KERNEL/CurveIntersectorP1P0.txx @@ -69,7 +69,7 @@ namespace INTERP_KERNEL int iS = *iter; BASE_INTERSECTOR::getDualSegments( OTT::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); diff --git a/src/INTERP_KERNEL/CurveIntersectorP1P1.txx b/src/INTERP_KERNEL/CurveIntersectorP1P1.txx index fd43fe7fc..7be7429bb 100644 --- a/src/INTERP_KERNEL/CurveIntersectorP1P1.txx +++ b/src/INTERP_KERNEL/CurveIntersectorP1P1.txx @@ -54,7 +54,7 @@ namespace INTERP_KERNEL { std::vector 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::ind2C( segmentsT[t]._nodeId )]; for(typename std::vector::const_iterator @@ -63,7 +63,7 @@ namespace INTERP_KERNEL int iS = *iter; BASE_INTERSECTOR::getDualSegments( OTT::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]); diff --git a/src/INTERP_KERNEL/DirectedBoundingBox.cxx b/src/INTERP_KERNEL/DirectedBoundingBox.cxx index 72b5c5101..b59f78db6 100644 --- a/src/INTERP_KERNEL/DirectedBoundingBox.cxx +++ b/src/INTERP_KERNEL/DirectedBoundingBox.cxx @@ -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; } diff --git a/src/INTERP_KERNEL/DirectedBoundingBox.hxx b/src/INTERP_KERNEL/DirectedBoundingBox.hxx index 93874acdb..344f65909 100644 --- a/src/INTERP_KERNEL/DirectedBoundingBox.hxx +++ b/src/INTERP_KERNEL/DirectedBoundingBox.hxx @@ -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 index 000000000..ee7116fd2 --- /dev/null +++ b/src/INTERP_KERNEL/ExprEval/InterpKernelAsmX86.cxx @@ -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 +#include +#include + +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 INTERP_KERNEL::AsmX86::convertIntoMachineLangage(const std::vector& asmb) const throw(INTERP_KERNEL::Exception) +{ + std::vector ret; + for(std::vector::const_iterator iter=asmb.begin();iter!=asmb.end();iter++) + convertOneInstructionInML(*iter,ret); + return ret; +} + +char *INTERP_KERNEL::AsmX86::convertMachineLangageInBasic(const std::vector& 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& 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 + +void INTERP_KERNEL::AsmX86::convertMov(const std::string& inst, std::vector& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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>=8; + } +} diff --git a/src/INTERP_KERNEL/ExprEval/InterpKernelAsmX86.hxx b/src/INTERP_KERNEL/ExprEval/InterpKernelAsmX86.hxx new file mode 100644 index 000000000..11b8733e5 --- /dev/null +++ b/src/INTERP_KERNEL/ExprEval/InterpKernelAsmX86.hxx @@ -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 +#include + +namespace INTERP_KERNEL +{ + class AsmX86 + { + public: + std::vector convertIntoMachineLangage(const std::vector& asmb) const throw(INTERP_KERNEL::Exception); + char *convertMachineLangageInBasic(const std::vector& ml, int& lgth) const; + private: + void convertOneInstructionInML(const std::string& inst, std::vector& ml) const throw(INTERP_KERNEL::Exception); + private: + static void convertMov(const std::string& inst, std::vector& ml) throw(INTERP_KERNEL::Exception); + static void convertPush(const std::string& inst, std::vector& ml) throw(INTERP_KERNEL::Exception); + static void convertPop(const std::string& inst, std::vector& ml) throw(INTERP_KERNEL::Exception); + static void convertFld(const std::string& inst, std::vector& ml) throw(INTERP_KERNEL::Exception); + static void convertFaddp(const std::string& inst, std::vector& ml) throw(INTERP_KERNEL::Exception); + static void convertFsubp(const std::string& inst, std::vector& ml) throw(INTERP_KERNEL::Exception); + static void convertFmulp(const std::string& inst, std::vector& ml) throw(INTERP_KERNEL::Exception); + static void convertFdivp(const std::string& inst, std::vector& ml) throw(INTERP_KERNEL::Exception); + static void convertFcos(const std::string& inst, std::vector& ml) throw(INTERP_KERNEL::Exception); + static void convertFsin(const std::string& inst, std::vector& ml) throw(INTERP_KERNEL::Exception); + static void convertFabs(const std::string& inst, std::vector& ml) throw(INTERP_KERNEL::Exception); + static void convertFchs(const std::string& inst, std::vector& ml) throw(INTERP_KERNEL::Exception); + static void convertFsqrt(const std::string& inst, std::vector& ml) throw(INTERP_KERNEL::Exception); + static void convertSub(const std::string& inst, std::vector& ml) throw(INTERP_KERNEL::Exception); + static void convertAdd(const std::string& inst, std::vector& ml) throw(INTERP_KERNEL::Exception); + static void convertRet(const std::string& inst, std::vector& ml) throw(INTERP_KERNEL::Exception); + static void convertLeave(const std::string& inst, std::vector& ml) throw(INTERP_KERNEL::Exception); + static void convertMovsd(const std::string& inst, std::vector& ml) throw(INTERP_KERNEL::Exception); + static void convertFst(const std::string& inst, std::vector& ml) throw(INTERP_KERNEL::Exception); + // + static void convertMovToEsp(const std::string& inst1, const std::string& inst2, std::vector& ml) throw(INTERP_KERNEL::Exception); + static void appendAddress(const std::string& addr, int nbOfByte, std::vector& ml) throw(INTERP_KERNEL::Exception); + private: + static const int NB_OF_OPS=19; + static const char *OPS[NB_OF_OPS]; + }; +} + +#endif diff --git a/src/INTERP_KERNEL/ExprEval/InterpKernelExprParser.cxx b/src/INTERP_KERNEL/ExprEval/InterpKernelExprParser.cxx index 5dde84961..585fac2f8 100644 --- a/src/INTERP_KERNEL/ExprEval/InterpKernelExprParser.cxx +++ b/src/INTERP_KERNEL/ExprEval/InterpKernelExprParser.cxx @@ -19,13 +19,23 @@ #include "InterpKernelExprParser.hxx" #include "InterpKernelValue.hxx" +#include "InterpKernelAsmX86.hxx" #include #include #include #include +#include #include +#ifdef _POSIX_MAPPED_FILES +#include +#else +#ifdef WNT +#include +#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 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::const_iterator iter=ass.begin();iter!=ass.end();iter++) + std::cout << " " << *iter << std::endl; + AsmX86 asmb; + std::vector output=asmb.convertIntoMachineLangage(ass); + for(std::vector::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 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::const_iterator iter=ass.begin();iter!=ass.end();iter++) + std::cout << " " << *iter << std::endl; + AsmX86 asmb; + std::vector output=asmb.convertIntoMachineLangage(ass); + for(std::vector::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& ass) const +{ + if(_leaf) + _leaf->compileX86(ass); + else + { + for(std::list::const_iterator iter=_sub_expr.begin();iter!=_sub_expr.end();iter++) + (*iter).compileX86LowLev(ass); + for(std::list::const_iterator iter2=_func_btw_sub_expr.begin();iter2!=_func_btw_sub_expr.end();iter2++) + (*iter2)->operateX86(ass); + } +} + +void ExprParser::compileX86_64LowLev(std::vector& ass) const +{ + if(_leaf) + _leaf->compileX86_64(ass); + else + { + for(std::list::const_iterator iter=_sub_expr.begin();iter!=_sub_expr.end();iter++) + (*iter).compileX86_64LowLev(ass); + for(std::list::const_iterator iter2=_func_btw_sub_expr.begin();iter2!=_func_btw_sub_expr.end();iter2++) + (*iter2)->operateX86(ass); + } +} + +void LeafExprVal::compileX86(std::vector& 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& 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& ass) const +{ + ass.push_back("fld qword [ebp+8]"); +} + +void LeafExprVar::compileX86_64(std::vector& 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::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); + } +} diff --git a/src/INTERP_KERNEL/ExprEval/InterpKernelExprParser.hxx b/src/INTERP_KERNEL/ExprEval/InterpKernelExprParser.hxx index 032f7070a..7ff8babb5 100644 --- a/src/INTERP_KERNEL/ExprEval/InterpKernelExprParser.hxx +++ b/src/INTERP_KERNEL/ExprEval/InterpKernelExprParser.hxx @@ -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& ass) const = 0; + virtual void compileX86_64(std::vector& 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& ass) const; + void compileX86_64(std::vector& 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& ass) const; + void compileX86_64(std::vector& ass) const; void fillValue(Value *val) const throw(INTERP_KERNEL::Exception); std::string getVar() const { return _var_name; } void prepareExprEvaluation(const std::vector& 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& 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& vars) const; void getTrueSetOfVars(std::set& vars) const; + // + char *compileX86() const; + char *compileX86_64() const; + void compileX86LowLev(std::vector& ass) const; + void compileX86_64LowLev(std::vector& 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 _sub_expr; std::list _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[]; }; diff --git a/src/INTERP_KERNEL/ExprEval/InterpKernelFunction.cxx b/src/INTERP_KERNEL/ExprEval/InterpKernelFunction.cxx index 6e8316526..dd16329f6 100644 --- a/src/INTERP_KERNEL/ExprEval/InterpKernelFunction.cxx +++ b/src/INTERP_KERNEL/ExprEval/InterpKernelFunction.cxx @@ -140,6 +140,10 @@ void IdentityFunction::operate(std::vector& stack) const throw(INTERP_K { } +void IdentityFunction::operateX86(std::vector& asmb) const throw(INTERP_KERNEL::Exception) +{ +} + const char *IdentityFunction::getRepr() const { return REPR; @@ -163,6 +167,10 @@ void PositiveFunction::operate(std::vector& stack) const throw(INTERP_K { } +void PositiveFunction::operateX86(std::vector& asmb) const throw(INTERP_KERNEL::Exception) +{ +} + const char *PositiveFunction::getRepr() const { return REPR; @@ -183,6 +191,11 @@ void NegateFunction::operate(std::vector& stack) const throw(INTERP_KER val->negate(); } +void NegateFunction::operateX86(std::vector& 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& stack) const throw(INTERP_KERNEL val->cos(); } +void CosFunction::operateX86(std::vector& 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& stack) const throw(INTERP_KERNEL val->sin(); } +void SinFunction::operateX86(std::vector& 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& stack) const throw(INTERP_KERNEL val->tan(); } +void TanFunction::operateX86(std::vector& 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& stack) const throw(INTERP_KERNE val->sqrt(); } +void SqrtFunction::operateX86(std::vector& 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& stack) const throw(INTERP_KERNEL val->abs(); } +void AbsFunction::operateX86(std::vector& 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& stack) const throw(INTERP_KERNEL Value *val=stack.back(); val->exp(); } - + +void ExpFunction::operateX86(std::vector& 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& stack) const throw(INTERP_KERNEL: val->ln(); } +void LnFunction::operateX86(std::vector& 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& stack) const throw(INTERP_KERNE val2=val3; } +void PlusFunction::operateX86(std::vector& 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& stack) const throw(INTERP_KERN val2=val3; } +void MinusFunction::operateX86(std::vector& 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& stack) const throw(INTERP_KERNE val2=val3; } +void MultFunction::operateX86(std::vector& 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& stack) const throw(INTERP_KERNEL val2=val3; } +void DivFunction::operateX86(std::vector& 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& stack) const throw(INTERP_KERNEL val2=val3; } +void PowFunction::operateX86(std::vector& 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& stack) const throw(INTERP_KERNEL val2=val3; } +void MaxFunction::operateX86(std::vector& 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& stack) const throw(INTERP_KERNEL val2=val3; } +void MinFunction::operateX86(std::vector& asmb) const throw(INTERP_KERNEL::Exception) +{ + throw INTERP_KERNEL::Exception("Assembly Not implemented yet !"); +} + const char *MinFunction::getRepr() const { return REPR; diff --git a/src/INTERP_KERNEL/ExprEval/InterpKernelFunction.hxx b/src/INTERP_KERNEL/ExprEval/InterpKernelFunction.hxx index 548a09f1e..160e15ba9 100644 --- a/src/INTERP_KERNEL/ExprEval/InterpKernelFunction.hxx +++ b/src/INTERP_KERNEL/ExprEval/InterpKernelFunction.hxx @@ -46,6 +46,7 @@ namespace INTERP_KERNEL virtual ~Function(); virtual int getNbInputParams() const = 0; virtual void operate(std::vector& stack) const throw(INTERP_KERNEL::Exception) = 0; + virtual void operateX86(std::vector& 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& stack) const throw(INTERP_KERNEL::Exception); + void operateX86(std::vector& 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& stack) const throw(INTERP_KERNEL::Exception); + void operateX86(std::vector& 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& stack) const throw(INTERP_KERNEL::Exception); + void operateX86(std::vector& 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& stack) const throw(INTERP_KERNEL::Exception); + void operateX86(std::vector& 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& stack) const throw(INTERP_KERNEL::Exception); + void operateX86(std::vector& 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& stack) const throw(INTERP_KERNEL::Exception); + void operateX86(std::vector& 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& stack) const throw(INTERP_KERNEL::Exception); + void operateX86(std::vector& 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& stack) const throw(INTERP_KERNEL::Exception); + void operateX86(std::vector& 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& stack) const throw(INTERP_KERNEL::Exception); + void operateX86(std::vector& 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& stack) const throw(INTERP_KERNEL::Exception); + void operateX86(std::vector& 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& stack) const throw(INTERP_KERNEL::Exception); + void operateX86(std::vector& 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& stack) const throw(INTERP_KERNEL::Exception); + void operateX86(std::vector& 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& stack) const throw(INTERP_KERNEL::Exception); + void operateX86(std::vector& 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& stack) const throw(INTERP_KERNEL::Exception); + void operateX86(std::vector& 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& stack) const throw(INTERP_KERNEL::Exception); + void operateX86(std::vector& 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& stack) const throw(INTERP_KERNEL::Exception); + void operateX86(std::vector& 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& stack) const throw(INTERP_KERNEL::Exception); + void operateX86(std::vector& asmb) const throw(INTERP_KERNEL::Exception); const char *getRepr() const; bool isACall() const; public: diff --git a/src/INTERP_KERNEL/ExprEval/Makefile.am b/src/INTERP_KERNEL/ExprEval/Makefile.am index 4a67afba5..28f5e9124 100644 --- a/src/INTERP_KERNEL/ExprEval/Makefile.am +++ b/src/INTERP_KERNEL/ExprEval/Makefile.am @@ -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 index 000000000..42ce4f43f --- /dev/null +++ b/src/INTERP_KERNEL/GenMathFormulae.hxx @@ -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 + +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 diff --git a/src/INTERP_KERNEL/InterpolationOptions.cxx b/src/INTERP_KERNEL/InterpolationOptions.cxx index 6eb93e9aa..6069bf22d 100644 --- a/src/INTERP_KERNEL/InterpolationOptions.cxx +++ b/src/INTERP_KERNEL/InterpolationOptions.cxx @@ -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) { diff --git a/src/INTERP_KERNEL/InterpolationOptions.hxx b/src/INTERP_KERNEL/InterpolationOptions.hxx index 49068a01a..667e320b6 100644 --- a/src/INTERP_KERNEL/InterpolationOptions.hxx +++ b/src/INTERP_KERNEL/InterpolationOptions.hxx @@ -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; diff --git a/src/INTERP_KERNEL/InterpolationUtils.hxx b/src/INTERP_KERNEL/InterpolationUtils.hxx index 2d5ca00df..e96f3fc1b 100644 --- a/src/INTERP_KERNEL/InterpolationUtils.hxx +++ b/src/INTERP_KERNEL/InterpolationUtils.hxx @@ -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 ) diff --git a/src/INTERP_KERNEL/Makefile.am b/src/INTERP_KERNEL/Makefile.am index a12507012..afbe7285d 100644 --- a/src/INTERP_KERNEL/Makefile.am +++ b/src/INTERP_KERNEL/Makefile.am @@ -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 index 000000000..0e31b21e0 --- /dev/null +++ b/src/INTERP_KERNEL/TranslationRotationMatrix.cxx @@ -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; diff --git a/src/INTERP_KERNEL/TranslationRotationMatrix.hxx b/src/INTERP_KERNEL/TranslationRotationMatrix.hxx index 8258cf18e..e1108573b 100644 --- a/src/INTERP_KERNEL/TranslationRotationMatrix.hxx +++ b/src/INTERP_KERNEL/TranslationRotationMatrix.hxx @@ -20,11 +20,13 @@ #ifndef __TRANSLATIONROTATIONMATRIX_HXX__ #define __TRANSLATIONROTATIONMATRIX_HXX__ +#include "INTERPKERNELDefines.hxx" + #include 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 diff --git a/src/INTERP_KERNEL/VolSurfFormulae.hxx b/src/INTERP_KERNEL/VolSurfFormulae.hxx index e62956e29..e9bdd855d 100644 --- a/src/INTERP_KERNEL/VolSurfFormulae.hxx +++ b/src/INTERP_KERNEL/VolSurfFormulae.hxx @@ -20,7 +20,9 @@ #ifndef __VOLSURFFORMULAE_HXX__ #define __VOLSURFFORMULAE_HXX__ -#include +#include "InterpolationUtils.hxx" + +#include 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 + 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::coo2C(work[ptId]); + const double *pti1=coords+3*OTT::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 + 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::coo2C(connec[ptId]); + const double *pti1=coords+3*OTT::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 + 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(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::coo2C(work[0])]+ + normal[1]*coords[3*OTT::coo2C(work[0])+1]+ + normal[2]*coords[3*OTT::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::coo2C(work[j]); + const double *p2=coords+3*OTT::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(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 + 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::coo2C(connec[i])]*coords[2*OTT::coo2C(connec[(i+1)%lgth])+1]- + coords[2*OTT::coo2C(connec[i])+1]*coords[2*OTT::coo2C(connec[(i+1)%lgth])]; + area+=cp; + res[0]+=cp*(coords[2*OTT::coo2C(connec[i])]+coords[2*OTT::coo2C(connec[(i+1)%lgth])]); + res[1]+=cp*(coords[2*OTT::coo2C(connec[i])+1]+coords[2*OTT::coo2C(connec[(i+1)%lgth])+1]); + } + res[0]/=3.*area; + res[1]/=3.*area; + } + + template + inline void computePolygonBarycenter3D(const ConnType *connec, int lgth, const double *coords, double *res) + { + double area[3]; + areaVectorOfPolygon(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::coo2C(connec[0])]+ + coords[3*OTT::coo2C(connec[i])]+ + coords[3*OTT::coo2C(connec[i+1])])/3.; + v[1]=(coords[3*OTT::coo2C(connec[0])+1]+ + coords[3*OTT::coo2C(connec[i])+1]+ + coords[3*OTT::coo2C(connec[i+1])+1])/3.; + v[2]=(coords[3*OTT::coo2C(connec[0])+2]+ + coords[3*OTT::coo2C(connec[i])+2]+ + coords[3*OTT::coo2C(connec[i+1])+2])/3.; + ConnType tmpConn[3]={connec[0],connec[i],connec[i+1]}; + areaVectorOfPolygon(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 diff --git a/src/INTERP_KERNEL/VolSurfUser.hxx b/src/INTERP_KERNEL/VolSurfUser.hxx index a0eafd221..99083c319 100644 --- a/src/INTERP_KERNEL/VolSurfUser.hxx +++ b/src/INTERP_KERNEL/VolSurfUser.hxx @@ -29,6 +29,12 @@ namespace INTERP_KERNEL template double computeVolSurfOfCell2(NormalizedCellType type, const ConnType *connec, int lgth, const double *coords, int spaceDim); + + template + void computeBarycenter(NormalizedCellType type, const ConnType *connec, int lgth, const double *coords, double *res); + + template + void computeBarycenter2(NormalizedCellType type, const ConnType *connec, int lgth, const double *coords, int spaceDim, double *res); } #endif diff --git a/src/INTERP_KERNEL/VolSurfUser.txx b/src/INTERP_KERNEL/VolSurfUser.txx index d6fcd11bf..5a0109a43 100644 --- a/src/INTERP_KERNEL/VolSurfUser.txx +++ b/src/INTERP_KERNEL/VolSurfUser.txx @@ -23,6 +23,8 @@ #include "VolSurfFormulae.hxx" #include "InterpolationUtils.hxx" +#include + namespace INTERP_KERNEL { template @@ -30,6 +32,13 @@ namespace INTERP_KERNEL { switch(type) { + case INTERP_KERNEL::NORM_SEG2 : + case INTERP_KERNEL::NORM_SEG3 : + { + int N1 = OTT::coo2C(connec[0]); + int N2 = OTT::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::coo2C(connec[inod]); + pts[inod] = coords+SPACEDIM*OTT::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(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(type,connec,lgth,coords); if(spaceDim==2) return computeVolSurfOfCell(type,connec,lgth,coords); - throw INTERP_KERNEL::Exception("Invalid spaceDim specified : must be 2 or 3"); + if(spaceDim==1) + return computeVolSurfOfCell(type,connec,lgth,coords); + throw INTERP_KERNEL::Exception("Invalid spaceDim specified : must be 1, 2 or 3"); + } + + template + 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::coo2C(connec[0]), + coords+SPACEDIM*OTT::coo2C(connec[0]+1),res); + std::transform(res,res+SPACEDIM,coords+SPACEDIM*OTT::coo2C(connec[1]),res,std::plus()); + std::transform(res,res+SPACEDIM,res,std::bind2nd(std::multiplies(),0.5)); + break; + } + case NORM_TRI3: + case NORM_TRI6: + { + std::copy(coords+SPACEDIM*OTT::coo2C(connec[0]), + coords+SPACEDIM*OTT::coo2C(connec[0]+1),res); + std::transform(res,res+SPACEDIM,coords+SPACEDIM*OTT::coo2C(connec[1]),res,std::plus()); + std::transform(res,res+SPACEDIM,coords+SPACEDIM*OTT::coo2C(connec[2]),res,std::plus()); + std::transform(res,res+SPACEDIM,res,std::bind2nd(std::multiplies(),1./3.)); + break; + } + case NORM_QUAD4: + case NORM_POLYGON: + { + if(SPACEDIM==2) + computePolygonBarycenter2D(connec,lgth,coords,res); + else if(SPACEDIM==3) + computePolygonBarycenter3D(connec,lgth,coords,res); + else + throw INTERP_KERNEL::Exception("Impossible spacedim linked to cell 2D Cell !"); + break; + } + case NORM_QUAD8: + { + if(SPACEDIM==2) + computePolygonBarycenter2D(connec,lgth/2,coords,res); + else if(SPACEDIM==3) + computePolygonBarycenter3D(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::coo2C(connec[0])]; + res[1]=coords[3*OTT::coo2C(connec[0])+1]; + res[2]=coords[3*OTT::coo2C(connec[0])+2]; + res[0]+=coords[3*OTT::coo2C(connec[1])]; + res[1]+=coords[3*OTT::coo2C(connec[1])+1]; + res[2]+=coords[3*OTT::coo2C(connec[1])+2]; + res[0]+=coords[3*OTT::coo2C(connec[2])]; + res[1]+=coords[3*OTT::coo2C(connec[2])+1]; + res[2]+=coords[3*OTT::coo2C(connec[2])+2]; + res[0]+=coords[3*OTT::coo2C(connec[3])]; + res[1]+=coords[3*OTT::coo2C(connec[3])+1]; + res[2]+=coords[3*OTT::coo2C(connec[3])+2]; + res[0]/=4.; res[1]/=4.; res[2]/=4.; + break; + } + case NORM_PYRA5: + { + double tmp[3]; + computePolygonBarycenter3D(connec,lgth,coords,tmp); + res[0]=(coords[3*OTT::coo2C(connec[4])]+3.*tmp[0])/4.; + res[1]=(coords[3*OTT::coo2C(connec[4])+1]+3.*tmp[1])/4.; + res[1]=(coords[3*OTT::coo2C(connec[4])+2]+3.*tmp[2])/4.; + break; + } + case NORM_POLYHED: + { + barycenterOfPolyhedron(connec,lgth,coords,res); + break; + } + default: + throw INTERP_KERNEL::Exception("Not recognized cell type to get Barycenter on it !"); + } + } + + template + void computeBarycenter2(NormalizedCellType type, const ConnType *connec, int lgth, const double *coords, int spaceDim, double *res) + { + if(spaceDim==3) + return computeBarycenter(type,connec,lgth,coords,res); + if(spaceDim==2) + return computeBarycenter(type,connec,lgth,coords,res); + if(spaceDim==1) + return computeBarycenter(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 index 000000000..9a30b7d8f --- /dev/null +++ b/src/MEDCoupling/MEDCouplingAutoRefCountObjectPtr.hxx @@ -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 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 diff --git a/src/MEDCoupling/MEDCouplingCMesh.cxx b/src/MEDCoupling/MEDCouplingCMesh.cxx index 8829b19de..3fd5fd404 100644 --- a/src/MEDCoupling/MEDCouplingCMesh.cxx +++ b/src/MEDCoupling/MEDCouplingCMesh.cxx @@ -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(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(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(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& conn) const { //not implemented yet @@ -214,6 +348,34 @@ void MEDCouplingCMesh::getCoordinatesOfNode(int nodeId, std::vector& 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& tinyInfo, std::vector& 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& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector& 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& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2, + const std::vector& 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]; + } + } +} + diff --git a/src/MEDCoupling/MEDCouplingCMesh.hxx b/src/MEDCoupling/MEDCouplingCMesh.hxx index a8f0b5301..e08226512 100644 --- a/src/MEDCoupling/MEDCouplingCMesh.hxx +++ b/src/MEDCoupling/MEDCouplingCMesh.hxx @@ -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& conn) const; void getCoordinatesOfNode(int nodeId, std::vector& 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& tinyInfo, std::vector& littleStrings) const; + void resizeForUnserialization(const std::vector& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector& littleStrings) const; + void serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const; + void unserialization(const std::vector& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2, + const std::vector& littleStrings); private: MEDCouplingCMesh(); + MEDCouplingCMesh(const MEDCouplingCMesh& other, bool deepCpy); ~MEDCouplingCMesh(); private: DataArrayDouble *_x_array; diff --git a/src/MEDCoupling/MEDCouplingExtrudedMesh.cxx b/src/MEDCoupling/MEDCouplingExtrudedMesh.cxx index 3233ac549..29d27ade9 100644 --- a/src/MEDCoupling/MEDCouplingExtrudedMesh.cxx +++ b/src/MEDCoupling/MEDCouplingExtrudedMesh.cxx @@ -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(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(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(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;igetTypeOfCell(i); + if(INTERP_KERNEL::CellModel::getCellModel(t).getExtrudedType()==type) + ret++; + } + return ret*_mesh1D->getNumberOfCells(); +} + void MEDCouplingExtrudedMesh::getNodeIdsOfCell(int cellId, std::vector& conn) const { int nbOfCells2D=_mesh2D->getNumberOfCells(); @@ -127,6 +253,31 @@ void MEDCouplingExtrudedMesh::getCoordinatesOfNode(int nodeId, std::vectorgetNumberOfCells() << "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;isetArray(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& tinyInfo, std::vector& littleStrings) const +{ + std::vector tinyInfo1; + std::vector ls1; + _mesh2D->getTinySerializationInformation(tinyInfo1,ls1); + std::vector tinyInfo2; + std::vector 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& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector& littleStrings) const +{ + int sz=tinyInfo.size(); + int sz1=tinyInfo[sz-2]; + std::vector ti1(tinyInfo.begin(),tinyInfo.begin()+sz1); + std::vector 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 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& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2, const std::vector& littleStrings) +{ + setName(littleStrings.back().c_str()); + int sz=tinyInfo.size(); + int sz1=tinyInfo[sz-2]; + _cell_2D_id=tinyInfo[sz-3]; + std::vector ti1(tinyInfo.begin(),tinyInfo.begin()+sz1); + std::vector 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 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()); +} diff --git a/src/MEDCoupling/MEDCouplingExtrudedMesh.hxx b/src/MEDCoupling/MEDCouplingExtrudedMesh.hxx index 60f46c047..e8915f4ee 100644 --- a/src/MEDCoupling/MEDCouplingExtrudedMesh.hxx +++ b/src/MEDCoupling/MEDCouplingExtrudedMesh.hxx @@ -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& conn) const; void getCoordinatesOfNode(int nodeId, std::vector& 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& tinyInfo, std::vector& littleStrings) const; + void resizeForUnserialization(const std::vector& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector& littleStrings) const; + void serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const; + void unserialization(const std::vector& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2, + const std::vector& 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; }; diff --git a/src/MEDCoupling/MEDCouplingField.cxx b/src/MEDCoupling/MEDCouplingField.cxx index d64a03822..3a917c753 100644 --- a/src/MEDCoupling/MEDCouplingField.cxx +++ b/src/MEDCoupling/MEDCouplingField.cxx @@ -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& refCoo, + const std::vector& gsCoo, const std::vector& 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& refCoo, + const std::vector& gsCoo, const std::vector& 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& 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); } diff --git a/src/MEDCoupling/MEDCouplingField.hxx b/src/MEDCoupling/MEDCouplingField.hxx index 932c5d54c..d1ed3a27f 100644 --- a/src/MEDCoupling/MEDCouplingField.hxx +++ b/src/MEDCoupling/MEDCouplingField.hxx @@ -23,22 +23,28 @@ #include "MEDCoupling.hxx" #include "MEDCouplingTimeLabel.hxx" #include "MEDCouplingRefCountObject.hxx" +#include "NormalizedUnstructuredMesh.hxx" #include "InterpKernelException.hxx" #include +#include 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& refCoo, + const std::vector& gsCoo, const std::vector& wg) throw(INTERP_KERNEL::Exception); + void setGaussLocalizationOnCells(const int *begin, const int *end, const std::vector& refCoo, + const std::vector& gsCoo, const std::vector& 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& 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; diff --git a/src/MEDCoupling/MEDCouplingFieldDiscretization.cxx b/src/MEDCoupling/MEDCouplingFieldDiscretization.cxx index 7e7c7b298..8633dc1f3 100644 --- a/src/MEDCoupling/MEDCouplingFieldDiscretization.cxx +++ b/src/MEDCoupling/MEDCouplingFieldDiscretization.cxx @@ -18,15 +18,16 @@ // #include "MEDCouplingFieldDiscretization.hxx" -#include "MEDCouplingPointSet.hxx" #include "MEDCouplingCMesh.hxx" #include "MEDCouplingFieldDouble.hxx" +#include "CellModel.hxx" #include "InterpolationUtils.hxx" +#include #include #include -#include +#include 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;idecrRef(); +} + +/*! + * 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(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(),volPtr[i])); + std::transform(tmp,tmp+nbOfCompo,res,res,std::plus()); + } + delete [] tmp; + vol->decrRef(); +} + +void MEDCouplingFieldDiscretization::getSerializationIntArray(DataArrayInt *& arr) const +{ + arr=0; +} + +/*! + * Empty : Not a bug + */ +void MEDCouplingFieldDiscretization::getTinySerializationIntInformation(std::vector& tinyInfo) const +{ +} + +/*! + * Empty : Not a bug + */ +void MEDCouplingFieldDiscretization::getTinySerializationDbleInformation(std::vector& tinyInfo) const +{ +} + +void MEDCouplingFieldDiscretization::resizeForUnserialization(const std::vector& tinyInfo, DataArrayInt *& arr) +{ + arr=0; +} + +/*! + * Empty : Not a bug + */ +void MEDCouplingFieldDiscretization::finishUnserialization(const std::vector& 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& refCoo, + const std::vector& gsCoo, const std::vector& 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& refCoo, + const std::vector& gsCoo, const std::vector& 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& 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(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& 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::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(other); return otherC!=0; } +/*! + * Nothing to do here. + */ +void MEDCouplingFieldDiscretizationP1::renumberArraysForCell(const MEDCouplingMesh *, const std::vector& 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(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(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(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_loc[i],eps)) + return false; + return true; +} + +bool MEDCouplingFieldDiscretizationGauss::isEqualWithoutConsideringStr(const MEDCouplingFieldDiscretization *other, double eps) const +{ + const MEDCouplingFieldDiscretizationGauss *otherC=dynamic_cast(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_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& 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::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& 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::const_iterator iter=_loc.begin();iter!=_loc.end();iter++) + (*iter).pushTinySerializationIntInfo(tinyInfo); +} + +void MEDCouplingFieldDiscretizationGauss::getTinySerializationDbleInformation(std::vector& tinyInfo) const +{ + for(std::vector::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& 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 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& tinyInfo) +{ + double *tmp=new double[tinyInfo.size()]; + std::copy(tinyInfo.begin(),tinyInfo.end(),tmp); + const double *work=tmp; + for(std::vector::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::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=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& refCoo, + const std::vector& gsCoo, const std::vector& 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;igetTypeOfCell(i)==type) + ptr[i]=id; + zipGaussLocalizations(); +} + +void MEDCouplingFieldDiscretizationGauss::setGaussLocalizationOnCells(const MEDCouplingMesh *m, const int *begin, const int *end, const std::vector& refCoo, + const std::vector& gsCoo, const std::vector& 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 ret; + int id=0; + for(std::vector::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& 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=(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 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(other); + return otherC!=0; +} + +int MEDCouplingFieldDiscretizationGaussNE::getNumberOfTuples(const MEDCouplingMesh *mesh) const +{ + int ret=0; + int nbOfCells=mesh->getNumberOfCells(); + for(int i=0;igetTypeOfCell(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& 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;igetTypeOfCell(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;igetTypeOfCell(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::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;igetTypeOfCell(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) +{ +} + diff --git a/src/MEDCoupling/MEDCouplingFieldDiscretization.hxx b/src/MEDCoupling/MEDCouplingFieldDiscretization.hxx index 25d52f542..0773d13e7 100644 --- a/src/MEDCoupling/MEDCouplingFieldDiscretization.hxx +++ b/src/MEDCoupling/MEDCouplingFieldDiscretization.hxx @@ -17,13 +17,17 @@ // 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 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& 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& tinyInfo) const; + virtual void getTinySerializationDbleInformation(std::vector& tinyInfo) const; + virtual void finishUnserialization(const std::vector& tinyInfo); + virtual void resizeForUnserialization(const std::vector& tinyInfo, DataArrayInt *& arr); + virtual void setGaussLocalizationOnType(const MEDCouplingMesh *m, INTERP_KERNEL::NormalizedCellType type, const std::vector& refCoo, + const std::vector& gsCoo, const std::vector& wg) throw(INTERP_KERNEL::Exception); + virtual void setGaussLocalizationOnCells(const MEDCouplingMesh *m, const int *begin, const int *end, const std::vector& refCoo, + const std::vector& gsCoo, const std::vector& 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& 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& 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& 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& 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& tinyInfo) const; + void getTinySerializationDbleInformation(std::vector& tinyInfo) const; + void finishUnserialization(const std::vector& tinyInfo); + void getSerializationIntArray(DataArrayInt *& arr) const; + void resizeForUnserialization(const std::vector& 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& refCoo, + const std::vector& gsCoo, const std::vector& wg) throw(INTERP_KERNEL::Exception); + void setGaussLocalizationOnCells(const MEDCouplingMesh *m, const int *begin, const int *end, const std::vector& refCoo, + const std::vector& gsCoo, const std::vector& 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& 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 _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& 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; diff --git a/src/MEDCoupling/MEDCouplingFieldDouble.cxx b/src/MEDCoupling/MEDCouplingFieldDouble.cxx index fcbfd84f7..81758deda 100644 --- a/src/MEDCoupling/MEDCouplingFieldDouble.cxx +++ b/src/MEDCoupling/MEDCouplingFieldDouble.cxx @@ -21,8 +21,11 @@ #include "MEDCouplingPointSet.hxx" #include "MEDCouplingTimeDiscretization.hxx" #include "MEDCouplingFieldDiscretization.hxx" +#include "MEDCouplingAutoRefCountObjectPtr.hxx" +#include "MEDCouplingNatureOfField.hxx" #include +#include #include 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 arrays; + _time_discr->getArrays(arrays); + int arrayId=0; + for(std::vector::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(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(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(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(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(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 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 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(_mesh); + if(!meshC) + throw INTERP_KERNEL::Exception("Invalid mesh to apply renumberNodes on it !"); + int nbOfNodes=meshC->getNumberOfNodes(); + MEDCouplingAutoRefCountObjectPtr 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 arrays; + _time_discr->getArrays(arrays); + for(std::vector::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 arrays; + _time_discr->getArrays(arrays); + std::vector arrs; + const int *arrSelBg=arrSelect->getConstPointer(); + const int *arrSelEnd=arrSelBg+arrSelect->getNbOfElems(); + for(std::vector::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::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 arrays; + _time_discr->getArrays(arrays); + double ret=-std::numeric_limits::max(); + bool isExistingArr=false; + for(std::vector::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 arrays; + _time_discr->getArrays(arrays); + double ret=std::numeric_limits::max(); + bool isExistingArr=false; + for(std::vector::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=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()); + 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; idecrRef(); + 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(),ptr[i])); - std::transform(tmp,tmp+nbComps,res,res,std::plus()); - } - 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& tinyInfo) const { tinyInfo.clear(); @@ -320,6 +762,10 @@ void MEDCouplingFieldDouble::getTinySerializationIntInformation(std::vector tinyInfo.push_back((int)_time_discr->getEnum()); tinyInfo.push_back((int)_nature); _time_discr->getTinySerializationIntInformation(tinyInfo); + std::vector 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::vectorgetTinySerializationDbleInformation(tinyInfo); + std::vector 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& tinyInfoI, std::vector& arrays) +void MEDCouplingFieldDouble::resizeForUnserialization(const std::vector& tinyInfoI, DataArrayInt *&dataInt, std::vector& arrays) { - std::vector tinyInfoI2(tinyInfoI.begin()+3,tinyInfoI.end()); + dataInt=0; + std::vector tinyInfoITmp(tinyInfoI); + int sz=tinyInfoITmp.back(); + tinyInfoITmp.pop_back(); + std::vector tinyInfoITmp2(tinyInfoITmp.begin(),tinyInfoITmp.end()-sz); + std::vector tinyInfoI2(tinyInfoITmp2.begin()+3,tinyInfoITmp2.end()); _time_discr->resizeForUnserialization(tinyInfoI2,arrays); + std::vector tinyInfoITmp3(tinyInfoITmp.end()-sz,tinyInfoITmp.end()); + _type->resizeForUnserialization(tinyInfoITmp3,dataInt); } void MEDCouplingFieldDouble::finishUnserialization(const std::vector& tinyInfoI, const std::vector& tinyInfoD, const std::vector& tinyInfoS) { std::vector tinyInfoI2(tinyInfoI.begin()+3,tinyInfoI.end()); - _time_discr->finishUnserialization(tinyInfoI2,tinyInfoD,tinyInfoS); + // + std::vector tmp(tinyInfoD); + int sz=tinyInfoD.back(); + tmp.pop_back(); + std::vector tmp1(tmp.begin(),tmp.end()-sz); + std::vector 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& 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& arrays) const +void MEDCouplingFieldDouble::serialize(DataArrayInt *&dataInt, std::vector& 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((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(_mesh); if(!meshC) throw INTERP_KERNEL::Exception("Invalid mesh to apply mergeNodes on it !"); + MEDCouplingAutoRefCountObjectPtr meshC2((MEDCouplingPointSet *)meshC->deepCpy()); bool ret; - DataArrayInt *arr=meshC->mergeNodes(eps,ret); + int ret2; + MEDCouplingAutoRefCountObjectPtr arr=meshC2->mergeNodes(eps,ret,ret2); if(!ret)//no nodes have been merged. return ret; std::vector arrays; _time_discr->getArrays(arrays); - try - { - for(std::vector::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::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; } diff --git a/src/MEDCoupling/MEDCouplingFieldDouble.hxx b/src/MEDCoupling/MEDCouplingFieldDouble.hxx index bffdc3e17..cbc0cf924 100644 --- a/src/MEDCoupling/MEDCouplingFieldDouble.hxx +++ b/src/MEDCoupling/MEDCouplingFieldDouble.hxx @@ -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& tinyInfo) const; void getTinySerializationDbleInformation(std::vector& tinyInfo) const; void getTinySerializationStrInformation(std::vector& tinyInfo) const; - void resizeForUnserialization(const std::vector& tinyInfoI, std::vector& arrays); + void resizeForUnserialization(const std::vector& tinyInfoI, DataArrayInt *&dataInt, std::vector& arrays); void finishUnserialization(const std::vector& tinyInfoI, const std::vector& tinyInfoD, const std::vector& tinyInfoS); - void serialize(std::vector& arrays) const; - bool mergeNodes(double eps); + void serialize(DataArrayInt *&dataInt, std::vector& 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 index 000000000..68c9a0611 --- /dev/null +++ b/src/MEDCoupling/MEDCouplingGaussLocalization.cxx @@ -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 +#include +#include +#include + +ParaMEDMEM::MEDCouplingGaussLocalization::MEDCouplingGaussLocalization(INTERP_KERNEL::NormalizedCellType type, const std::vector& refCoo, + const std::vector& gsCoo, const std::vector& 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& 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& 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=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& tinyData) +{ + std::vector 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& v1, const std::vector& v2, double eps) +{ + int sz=v1.size(); + if(sz!=(int)v2.size()) + return false; + std::vector tmp(sz); + std::transform(v1.begin(),v1.end(),v2.begin(),tmp.begin(),std::minus()); + std::transform(tmp.begin(),tmp.end(),tmp.begin(),std::ptr_fun(fabs)); + return *std::max_element(tmp.begin(),tmp.end()) + +namespace ParaMEDMEM +{ + class MEDCouplingMesh; + + class MEDCOUPLING_EXPORT MEDCouplingGaussLocalization + { + public: + MEDCouplingGaussLocalization(INTERP_KERNEL::NormalizedCellType type, const std::vector& refCoo, + const std::vector& gsCoo, const std::vector& 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& tinyInfo) const; + void pushTinySerializationDblInfo(std::vector& tinyInfo) const; + const double *fillWithValues(const double *vals); + // + const std::vector& getRefCoords() const { return _ref_coord; } + double getRefCoord(int ptIdInCell, int comp) const throw(INTERP_KERNEL::Exception); + const std::vector& getGaussCoords() const { return _gauss_coord; } + double getGaussCoord(int gaussPtIdInCell, int comp) const throw(INTERP_KERNEL::Exception); + const std::vector& 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& tinyData); + private: + int checkCoherencyOfRequest(int gaussPtIdInCell, int comp) const throw(INTERP_KERNEL::Exception); + static bool areAlmostEqual(const std::vector& v1, const std::vector& v2, double eps); + private: + INTERP_KERNEL::NormalizedCellType _type; + std::vector _ref_coord; + std::vector _gauss_coord; + std::vector _weight; + }; +} + +#endif diff --git a/src/MEDCoupling/MEDCouplingMemArray.cxx b/src/MEDCoupling/MEDCouplingMemArray.cxx index 3456e329b..7ced3782b 100644 --- a/src/MEDCoupling/MEDCouplingMemArray.cxx +++ b/src/MEDCoupling/MEDCouplingMemArray.cxx @@ -19,8 +19,16 @@ #include "MEDCouplingMemArray.txx" +#include "GenMathFormulae.hxx" +#include "InterpKernelExprParser.hxx" + +#include +#include +#include #include +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::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;ialloc(nbTuples,nbOfCompo); + ret->copyStringInfoFrom(*this); + const double *iptr=getConstPointer(); + double *optr=ret->getPointer(); + for(int i=0;iend()) 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;isetName(getName().c_str()); + for(int i=0;isetInfoOnComponent(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()); +} + +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;ialloc(nbOfTuple,1); + const double *src=getConstPointer(); + double *dest=ret->getPointer(); + for(int i=0;ialloc(nbOfTuple,1); + const double *src=getConstPointer(); + double *dest=ret->getPointer(); + switch(getNumberOfComponents()) + { + case 6: + for(int i=0;idecrRef(); + 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;ialloc(nbOfTuple,9); + const double *src=getConstPointer(); + double *dest=ret->getPointer(); + for(int i=0;ialloc(nbOfTuple,nbOfComp); + const double *src=getConstPointer(); + double *dest=ret->getPointer(); +if(nbOfComp==6) + for(int i=0;ialloc(nbOfTuple,1); + const double *src=getConstPointer(); + double *dest=ret->getPointer(); + if(nbOfComp==6) + for(int i=0;ialloc(nbOfTuple,6); + const double *src=getConstPointer(); + double *dest=ret->getPointer(); + for(int i=0;ialloc(nbOfTuple,1); + const double *src=getConstPointer(); + double *dest=ret->getPointer(); + for(int i=0;ialloc(nbOfTuple,1); + const double *src=getConstPointer(); + double *dest=ret->getPointer(); + for(int i=0;i()); + declareAsNew(); +} + +void DataArrayDouble::applyLin(double a, double b, int compoId) +{ + double *ptr=getPointer()+compoId; + int nbOfComp=getNumberOfComponents(); + int nbOfTuple=getNumberOfTuples(); + for(int i=0;ialloc(nbOfTuples,nbOfComp); + const double *ptr=getConstPointer(); + double *ptrToFill=newArr->getPointer(); + for(int i=0;i(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 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(oss," ")); + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } + std::vector 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(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(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 res; + int nbOfTuples=getNumberOfTuples(); + for(int i=0;i=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;isetInfoOnComponent(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;icopyStringInfoFrom(*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;icopyStringInfoFrom(*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;icopyStringInfoFrom(*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()); } 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;ialloc(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;ialloc(nbTuples,nbOfCompo); + ret->copyStringInfoFrom(*this); + const int *iptr=getConstPointer(); + int *optr=ret->getPointer(); + for(int i=0;ialloc(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;isetName(getName().c_str()); + for(int i=0;isetInfoOnComponent(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& groups, int newNb, std::vector< std::vector >& 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::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::const_iterator iter=groups.begin();iter!=groups.end();iter++,grId++) + { + std::set 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); diff --git a/src/MEDCoupling/MEDCouplingMemArray.hxx b/src/MEDCoupling/MEDCouplingMemArray.hxx index 74d165bb9..33b8896b6 100644 --- a/src/MEDCoupling/MEDCouplingMemArray.hxx +++ b/src/MEDCoupling/MEDCouplingMemArray.hxx @@ -27,6 +27,7 @@ #include #include +#include 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& 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 _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 &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& groups, int newNb, std::vector< std::vector >& 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. diff --git a/src/MEDCoupling/MEDCouplingMemArray.txx b/src/MEDCoupling/MEDCouplingMemArray.txx index 476f147ae..5a1a048d5 100644 --- a/src/MEDCoupling/MEDCouplingMemArray.txx +++ b/src/MEDCoupling/MEDCouplingMemArray.txx @@ -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 + void MemArray::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(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 + void MemArray::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(stream," ")); + stream << "| "; + data+=sl; + } + stream << "\n"; + } + else + stream << "Empty Data\n"; + } + else + stream << "No data !\n"; + } + + template + void MemArray::fillWithValue(const T& val) + { + T *pt=_pointer.getPointer(); + std::fill(pt,pt+_nb_of_elem,val); + } template void MemArray::alloc(int nbOfElements) diff --git a/src/MEDCoupling/MEDCouplingMesh.cxx b/src/MEDCoupling/MEDCouplingMesh.cxx index a552ea588..1f60dc669 100644 --- a/src/MEDCoupling/MEDCouplingMesh.cxx +++ b/src/MEDCoupling/MEDCouplingMesh.cxx @@ -29,7 +29,125 @@ 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 crest; + std::set p(partBg,partEnd); + int nbOfCells=getNumberOfCells(); + for(int i=0;i conn; + getNodeIdsOfCell(i,conn); + bool cont=true; + for(std::vector::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) { diff --git a/src/MEDCoupling/MEDCouplingMesh.hxx b/src/MEDCoupling/MEDCouplingMesh.hxx index 8d11cd573..3cdbe20a8 100644 --- a/src/MEDCoupling/MEDCouplingMesh.hxx +++ b/src/MEDCoupling/MEDCouplingMesh.hxx @@ -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& conn) const = 0; + virtual DataArrayInt *getCellIdsFullyIncludedInNodeIds(const int *partBg, const int *partEnd) const; virtual void getCoordinatesOfNode(int nodeId, std::vector& 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& tinyInfo, std::vector& littleStrings) const = 0; + virtual void resizeForUnserialization(const std::vector& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector& littleStrings) const = 0; + virtual void serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const = 0; + virtual void unserialization(const std::vector& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2, + const std::vector& 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 index 000000000..7969909f1 --- /dev/null +++ b/src/MEDCoupling/MEDCouplingNatureOfField.cxx @@ -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 + +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]; + } +} + diff --git a/src/MEDCoupling/MEDCouplingNatureOfField.hxx b/src/MEDCoupling/MEDCouplingNatureOfField.hxx index bdc1c78dd..89f9125e0 100644 --- a/src/MEDCoupling/MEDCouplingNatureOfField.hxx +++ b/src/MEDCoupling/MEDCouplingNatureOfField.hxx @@ -17,8 +17,11 @@ // 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 diff --git a/src/MEDCoupling/MEDCouplingNormalizedCartesianMesh.hxx b/src/MEDCoupling/MEDCouplingNormalizedCartesianMesh.hxx index ebb12e01a..c2643f327 100644 --- a/src/MEDCoupling/MEDCouplingNormalizedCartesianMesh.hxx +++ b/src/MEDCoupling/MEDCouplingNormalizedCartesianMesh.hxx @@ -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" diff --git a/src/MEDCoupling/MEDCouplingNormalizedUnstructuredMesh.hxx b/src/MEDCoupling/MEDCouplingNormalizedUnstructuredMesh.hxx index b3ebcbc7f..5ebd3ae19 100644 --- a/src/MEDCoupling/MEDCouplingNormalizedUnstructuredMesh.hxx +++ b/src/MEDCoupling/MEDCouplingNormalizedUnstructuredMesh.hxx @@ -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" diff --git a/src/MEDCoupling/MEDCouplingPointSet.cxx b/src/MEDCoupling/MEDCouplingPointSet.cxx index 0c0ce1887..f451ea61a 100644 --- a/src/MEDCoupling/MEDCouplingPointSet.cxx +++ b/src/MEDCoupling/MEDCouplingPointSet.cxx @@ -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(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(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(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)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'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;isetName(getCoords()->getName().c_str()); - for(int i=0;isetInfoOnComponent(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& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector& littleStrings) +void MEDCouplingPointSet::resizeForUnserialization(const std::vector& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector& littleStrings) const { if(tinyInfo[2]>=0 && tinyInfo[1]>=1) { @@ -502,7 +557,7 @@ void MEDCouplingPointSet::resizeForUnserialization(const std::vector& tinyI * Second and final unserialization process. * @param tinyInfo must be equal to the result given by getTinySerializationInformation method. */ -void MEDCouplingPointSet::unserialization(const std::vector& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, const std::vector& littleStrings) +void MEDCouplingPointSet::unserialization(const std::vector& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2, const std::vector& 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' */ diff --git a/src/MEDCoupling/MEDCouplingPointSet.hxx b/src/MEDCoupling/MEDCouplingPointSet.hxx index 601777efc..687124fa8 100644 --- a/src/MEDCoupling/MEDCouplingPointSet.hxx +++ b/src/MEDCoupling/MEDCouplingPointSet.hxx @@ -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& 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& 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& tinyInfo, std::vector& littleStrings) const; virtual bool isEmptyMesh(const std::vector& tinyInfo) const = 0; - virtual void resizeForUnserialization(const std::vector& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector& littleStrings); - virtual void serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const; - virtual void unserialization(const std::vector& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, - const std::vector& littleStrings); + //! size of returned tinyInfo must be always the same. + void getTinySerializationInformation(std::vector& tinyInfo, std::vector& littleStrings) const; + void resizeForUnserialization(const std::vector& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector& littleStrings) const; + void serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const; + void unserialization(const std::vector& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2, + const std::vector& littleStrings); virtual void giveElemsInBoundingBox(const double *bbox, double eps, std::vector& elems) = 0; virtual void giveElemsInBoundingBox(const INTERP_KERNEL::DirectedBoundingBox& bbox, double eps, std::vector& elems) = 0; virtual DataArrayInt *zipCoordsTraducer() = 0; @@ -93,7 +100,7 @@ namespace ParaMEDMEM static bool isButterfly2DCell(const std::vector& res, bool isQuad); template void findCommonNodesAlg(std::vector& bbox, - int nbNodes, double prec, std::vector& c, std::vector& cI) const; + int nbNodes, int limitNodeId, double prec, std::vector& c, std::vector& cI) const; protected: DataArrayDouble *_coords; }; diff --git a/src/MEDCoupling/MEDCouplingPointSet.txx b/src/MEDCoupling/MEDCouplingPointSet.txx index 300aab235..bae195566 100644 --- a/src/MEDCoupling/MEDCouplingPointSet.txx +++ b/src/MEDCoupling/MEDCouplingPointSet.txx @@ -29,7 +29,7 @@ namespace ParaMEDMEM { template void MEDCouplingPointSet::findCommonNodesAlg(std::vector& bbox, - int nbNodes, double prec, + int nbNodes, int limitNodeId, double prec, std::vector& c, std::vector& cI) const { const double *coordsPtr=_coords->getConstPointer(); @@ -52,8 +52,9 @@ namespace ParaMEDMEM std::vector commonNodes; for(std::vector::const_iterator it=intersectingElems.begin();it!=intersectingElems.end();it++) if(*it!=i) - if(INTERP_KERNEL::distance2(coordsPtr+SPACEDIM*i,coordsPtr+SPACEDIM*(*it))=limitNodeId) + if(INTERP_KERNEL::distance2(coordsPtr+SPACEDIM*i,coordsPtr+SPACEDIM*(*it))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(); diff --git a/src/MEDCoupling/MEDCouplingRemapper.hxx b/src/MEDCoupling/MEDCouplingRemapper.hxx index 5e2bd63dd..14d402d03 100644 --- a/src/MEDCoupling/MEDCouplingRemapper.hxx +++ b/src/MEDCoupling/MEDCouplingRemapper.hxx @@ -24,6 +24,7 @@ #include "MEDCouplingTimeLabel.hxx" #include "InterpolationOptions.hxx" #include "MEDCouplingNatureOfField.hxx" +#include "InterpKernelException.hxx" #include #include @@ -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 >& 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 >& m1D, diff --git a/src/MEDCoupling/MEDCouplingTimeDiscretization.cxx b/src/MEDCoupling/MEDCouplingTimeDiscretization.cxx index a030e1b4c..c9c8a41d2 100644 --- a/src/MEDCoupling/MEDCouplingTimeDiscretization.cxx +++ b/src/MEDCoupling/MEDCouplingTimeDiscretization.cxx @@ -19,21 +19,31 @@ #include "MEDCouplingTimeDiscretization.hxx" #include "MEDCouplingMemArray.hxx" - -#include "InterpKernelExprParser.hxx" +#include "MEDCouplingAutoRefCountObjectPtr.hxx" #include #include +#include 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& arrays, TimeLabel *owner) throw(INTERP_KERNEL::Exception) { if(arrays.size()!=1) @@ -205,122 +270,314 @@ void MEDCouplingTimeDiscretization::getArrays(std::vector& 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 arrays; + getArrays(arrays); + std::vector< MEDCouplingAutoRefCountObjectPtr > 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 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 arrays; + getArrays(arrays); + std::vector< MEDCouplingAutoRefCountObjectPtr > 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 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 arrays; + getArrays(arrays); + std::vector< MEDCouplingAutoRefCountObjectPtr > 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 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 arrays; + getArrays(arrays); + std::vector< MEDCouplingAutoRefCountObjectPtr > 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 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 arrays; + getArrays(arrays); + std::vector< MEDCouplingAutoRefCountObjectPtr > 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 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 arrays; + getArrays(arrays); + std::vector< MEDCouplingAutoRefCountObjectPtr > 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 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 arrays; + getArrays(arrays); + std::vector< MEDCouplingAutoRefCountObjectPtr > 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 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 arrays; + getArrays(arrays); + std::vector< MEDCouplingAutoRefCountObjectPtr > 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 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 arrays; + getArrays(arrays); + std::vector< MEDCouplingAutoRefCountObjectPtr > 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 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 arrays; + getArrays(arrays); + std::vector< MEDCouplingAutoRefCountObjectPtr > 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 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 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 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 arrays; + getArrays(arrays); + std::vector 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(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 vars; - expr.getTrueSetOfVars(vars); - int oldNbOfComp=_array->getNumberOfComponents(); - if((int)vars.size()>oldNbOfComp) + std::vector arrays; + getArrays(arrays); + std::vector 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(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 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;idecrRef(); +} + +void MEDCouplingTimeDiscretization::applyFunc(const char *func) +{ + std::vector arrays; + getArrays(arrays); + std::vector 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(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 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 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(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(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(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(other); + if(!otherC) + return false; + return MEDCouplingTimeDiscretization::isEqualWithoutConsideringStr(other,prec); +} + MEDCouplingTimeDiscretization *MEDCouplingNoTimeLabel::aggregate(const MEDCouplingTimeDiscretization *other) const { const MEDCouplingNoTimeLabel *otherC=dynamic_cast(other); @@ -368,6 +648,54 @@ MEDCouplingTimeDiscretization *MEDCouplingNoTimeLabel::aggregate(const MEDCoupli return ret; } +MEDCouplingTimeDiscretization *MEDCouplingNoTimeLabel::dot(const MEDCouplingTimeDiscretization *other) const +{ + const MEDCouplingNoTimeLabel *otherC=dynamic_cast(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(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(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(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(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& 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& tinyInfo) const @@ -534,8 +869,8 @@ void MEDCouplingWithTimeStep::finishUnserialization(const std::vector& 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(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(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(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(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(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(other); + _time=otherC._time; + _iteration=otherC._iteration; + _order=otherC._order; +} + MEDCouplingTimeDiscretization *MEDCouplingWithTimeStep::aggregate(const MEDCouplingTimeDiscretization *other) const { const MEDCouplingWithTimeStep *otherC=dynamic_cast(other); @@ -588,6 +950,54 @@ MEDCouplingTimeDiscretization *MEDCouplingWithTimeStep::aggregate(const MEDCoupl return ret; } +MEDCouplingTimeDiscretization *MEDCouplingWithTimeStep::dot(const MEDCouplingTimeDiscretization *other) const +{ + const MEDCouplingWithTimeStep *otherC=dynamic_cast(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(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(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(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(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(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& 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& tinyInfo) const @@ -764,16 +1186,24 @@ void MEDCouplingConstOnTimeInterval::finishUnserialization(const std::vector(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(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(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(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(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(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(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(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(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(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(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(&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(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(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& 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& 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& tinyInfo) const +{ + MEDCouplingTimeDiscretization::getTinySerializationDbleInformation(tinyInfo); + tinyInfo.push_back(_start_time); + tinyInfo.push_back(_end_time); +} + +void MEDCouplingTwoTimeSteps::getTinySerializationStrInformation(std::vector& tinyInfo) const +{ + int nbOfCompo=_array->getNumberOfComponents(); + for(int i=0;igetInfoOnComponent(i)); + for(int i=0;igetInfoOnComponent(i)); +} + void MEDCouplingTwoTimeSteps::resizeForUnserialization(const std::vector& tinyInfoI, std::vector& arrays) { arrays.resize(2); @@ -1043,10 +1696,10 @@ void MEDCouplingTwoTimeSteps::resizeForUnserialization(const std::vector& 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& 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& 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(other); + return otherC!=0; +} + +bool MEDCouplingLinearTime::areStrictlyCompatible(const MEDCouplingTimeDiscretization *other) const +{ + if(!MEDCouplingTimeDiscretization::areStrictlyCompatible(other)) + return false; + const MEDCouplingLinearTime *otherC=dynamic_cast(other); + return otherC!=0; +} + +bool MEDCouplingLinearTime::areStrictlyCompatibleForMul(const MEDCouplingTimeDiscretization *other) const +{ + if(!MEDCouplingTimeDiscretization::areStrictlyCompatibleForMul(other)) + return false; + const MEDCouplingLinearTime *otherC=dynamic_cast(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& 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(),alpha)); + std::vector tmp(nbComp); + std::transform(vals.begin()+nbComp,vals.end(),tmp.begin(),std::bind2nd(std::multiplies(),1-alpha)); + std::transform(tmp.begin(),tmp.end(),res,res,std::plus()); +} + +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(),alpha)); + std::vector 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(),1-alpha)); + std::transform(tmp.begin(),tmp.end(),value,value,std::plus()); +} + +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(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(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(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(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(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(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(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(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(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(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(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(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(other); + if(!otherC) + throw INTERP_KERNEL::Exception("LinearTime::addEqual on mismatched time discretization !"); + getArray()->divideEqual(other->getArray()); + getEndArray()->divideEqual(other->getEndArray()); } diff --git a/src/MEDCoupling/MEDCouplingTimeDiscretization.hxx b/src/MEDCoupling/MEDCouplingTimeDiscretization.hxx index 8ea2f8c6d..a9f1de097 100644 --- a/src/MEDCoupling/MEDCouplingTimeDiscretization.hxx +++ b/src/MEDCoupling/MEDCouplingTimeDiscretization.hxx @@ -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& 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& vals, double *res) const = 0; virtual void getArrays(std::vector& 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& 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& tinyInfo) const; void getTinySerializationDbleInformation(std::vector& tinyInfo) const; void finishUnserialization(const std::vector& tinyInfoI, const std::vector& tinyInfoD, const std::vector& 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& 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& tinyInfo) const; void getTinySerializationDbleInformation(std::vector& tinyInfo) const; void finishUnserialization(const std::vector& tinyInfoI, const std::vector& tinyInfoD, const std::vector& 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& 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& 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& tinyInfo) const; + void getTinySerializationDbleInformation(std::vector& tinyInfo) const; + void getTinySerializationStrInformation(std::vector& tinyInfo) const; void resizeForUnserialization(const std::vector& tinyInfoI, std::vector& arrays); void finishUnserialization(const std::vector& tinyInfoI, const std::vector& tinyInfoD, const std::vector& tinyInfoS); + std::vector< const DataArrayDouble *> getArraysForTime(double time) const throw(INTERP_KERNEL::Exception); + void setArrays(const std::vector& 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& 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[]; }; } diff --git a/src/MEDCoupling/MEDCouplingUMesh.cxx b/src/MEDCoupling/MEDCouplingUMesh.cxx index 62e64ce7e..e27fe875c 100644 --- a/src/MEDCoupling/MEDCouplingUMesh.cxx +++ b/src/MEDCoupling/MEDCouplingUMesh.cxx @@ -25,9 +25,11 @@ #include "PointLocatorAlgos.txx" #include "BBTree.txx" #include "DirectedBoundingBox.hxx" +#include "MEDCouplingAutoRefCountObjectPtr.hxx" #include #include +#include #include #include @@ -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(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(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 m=mergeUMeshes(this,otherC); + bool areNodesMerged; + int newNbOfNodes; + int oldNbOfNodes=getNumberOfNodes(); + MEDCouplingAutoRefCountObjectPtr 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(),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(),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(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 ms(2); + ms[0]=const_cast(this); + ms[1]=const_cast(otherC); + MEDCouplingAutoRefCountObjectPtr m=mergeUMeshesOnSameCoords(ms); + MEDCouplingAutoRefCountObjectPtr 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(),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(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& 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=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(),-1)); - for(;work!=traducer+nbOfNodes;work=std::find_if(work,traducer+nbOfNodes,std::bind2nd(std::not_equal_to(),-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;iselectByTupleId(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 s1(conn+connI[cell1],conn+connI[cell1+1]); + std::set 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 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 n1,n2; + getCoordinatesOfNode(c1[0],n1); + other->getCoordinatesOfNode(c2[0],n2); + std::transform(n1.begin(),n1.end(),n2.begin(),n1.begin(),std::minus()); + std::transform(n1.begin(),n1.end(),n1.begin(),std::ptr_fun(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& candidates, int compType, std::vector& result) const +{ + std::set cand(candidates.begin(),candidates.end()); + cand.erase(-1); + if(cand.size()<=1) + return false; + std::set::const_iterator end=cand.end(); end--; + bool ret=false; + for(std::set::const_iterator iter=cand.begin();iter!=end && !ret;iter++) + { + std::set::const_iterator begin2=iter; begin2++; + for(std::set::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 +void MEDCouplingUMesh::findCommonCellsBase(int compType, std::vector& res, std::vector& resI) const +{ + res.clear(); resI.clear(); + resI.push_back(0); + std::vector bbox; + int nbOfCells=getNumberOfCells(); + getBoundingBoxForBBTree(bbox); + double bb[2*SPACEDIM]; + double eps=getCaracteristicDimension(); + eps*=1.e-12; + BBTree myTree(&bbox[0],0,0,nbOfCells,-eps); + const int *conn=getNodalConnectivity()->getConstPointer(); + const int *connI=getNodalConnectivityIndex()->getConstPointer(); + const double *coords=getCoords()->getConstPointer(); + std::vector isFetched(nbOfCells); + for(int k=0;k::max(); bb[2*j+1]=-std::numeric_limits::max(); } + for(const int *pt=conn+connI[k]+1;pt!=conn+connI[k+1];pt++) + if(*pt>-1) + { + for(int j=0;j candidates1; + myTree.getIntersectingElems(bb,candidates1); + std::vector candidates; + for(std::vector::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::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 commonCells; + std::vector 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 cellsToKeep; + for(int i=0;i::const_iterator it=commonCells.begin()+commonCellsI[i];it!=commonCells.begin()+commonCellsI[i+1];it++) + retPtr[*it]=id; + id--; + } + id=0; + std::map m; + for(int i=0;i::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 newCoords=mergeNodesArray(&other,this); + _coords->incrRef(); + MEDCouplingAutoRefCountObjectPtr oldCoords=_coords; + setCoords(newCoords); + bool areNodesMerged; + int newNbOfNodes; + MEDCouplingAutoRefCountObjectPtr 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(),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& 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& conn) const { @@ -794,6 +1259,75 @@ void MEDCouplingUMesh::getCoordinatesOfNode(int nodeId, std::vector& 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::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(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& 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& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector& littleStrings) +void MEDCouplingUMesh::resizeForUnserialization(const std::vector& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector& 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& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, const std::vector& littleStrings) +void MEDCouplingUMesh::unserialization(const std::vector& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2, const std::vector& 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(type,connec+ipt+1,connec_index[iel+1]-ipt-1,coords,dim_space); } if(isAbs) - for(int iel=0;iel(fabs)); } else { @@ -1352,32 +1894,391 @@ void MEDCouplingUMesh::checkButterflyCells(std::vector& 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& 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;icheckFullyDefined(); + 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::max(); - bbox[2*i+1]=-std::numeric_limits::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=0) - for(int k=0;kdecrRef(); + 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 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 v; + std::vector c; + double vec[3]; + v.reserve(3); + c.reserve(6); + for(int i=0;igetNodeIdsOfCell(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()); + for(int j=0;j()); + 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()); + for(int j=0;j()); + } + } + 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 newc; + for(int j=0;jalloc(newc.size()*nbOf1DCells,1); + int *newConnPtr=newConn->getPointer(); + int deltaPerLev=isQuad?2*nbOfNodesOf1Lev:nbOfNodesOf1Lev; + newConnIPtr=newConnI->getPointer(); + for(int iz=0;iz(),newConnIPtr[iz*nbOf2DCells])); + for(std::vector::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 newConn=DataArrayInt::New(); + MEDCouplingAutoRefCountObjectPtr 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& 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;igetPointer(); + const int *connI=_nodal_connec_index->getConstPointer(); + const double *coordsPtr=_coords->getConstPointer(); + bool isModified=false; + for(int i=0;i 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& 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;igetPointer(); + const int *connI=_nodal_connec_index->getConstPointer(); + const double *coordsPtr=_coords->getConstPointer(); + bool isModified=false; + for(int i=0;ideclareAsNew(); + 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(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& bbox) const +{ + int spaceDim=getSpaceDimension(); + int nbOfCells=getNumberOfCells(); + bbox.resize(2*nbOfCells*spaceDim); + for(int i=0;i::max(); + bbox[2*i+1]=-std::numeric_limits::max(); + } + const double *coordsPtr=_coords->getConstPointer(); + const int *conn=_nodal_connec->getConstPointer(); + const int *connI=_nodal_connec_index->getConstPointer(); + for(int i=0;i=0) + for(int k=0;kgetConstPointer(); 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::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::max()) + { + int nextMinPos=std::numeric_limits::max(); + for(int j=0;j::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 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::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::splitByType() const +{ + checkFullyDefined(); + const int *conn=_nodal_connec->getConstPointer(); + const int *connI=_nodal_connec_index->getConstPointer(); + int nbOfCells=getNumberOfCells(); + std::vector 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;jgetNumberOfTuples()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 types=getAllTypes(); + int *tmp=new int[nbOfCells]; + for(std::set::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& idsPerGeoType) const +{ + std::vector idsTokeep; + int nbOfCells=getNumberOfCells(); + int j=0; + for(int i=0;i(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()); - nbOfPts++; - } - ptToFill=std::transform(tmp,tmp+spaceDim,ptToFill,std::bind2nd(std::divides(),(double)nbOfPts)); + INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]]; + INTERP_KERNEL::computeBarycenter2(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& 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::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(),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& meshes, int compType, std::vector& 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;igetNumberOfCells(); + 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& 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 > ii(ret); + std::copy(connBg+1,connEnd,ii); + *ii++=-1; + std::reverse_iterator rConnBg(connEnd); + std::reverse_iterator rConnEnd(connBg+1); + std::transform(rConnBg,rConnEnd,ii,std::bind2nd(std::plus(),deltaz)); + int nbOfRadFaces=std::distance(connBg+1,connEnd); + for(int i=0;i > edges; + int nbOfFaces=std::count(begin,end,-1)+1; + const int *bgFace=begin; + for(int i=0;i 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(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 > edges; + int nbOfFaces=std::count(begin,end,-1)+1; + int *bgFace=begin; + std::vector isPerm(nbOfFaces); + for(int i=0;i p1(bgFace[l],bgFace[(l+1)%nbOfEdgesInFace]); + edges.push_back(p1); + } + int *bgFace2=endFace+1; + for(int k=i+1;k 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 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(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 tmp(nbOfEdgesInFace-1); + std::copy(bgFace+1,endFace,tmp.rbegin()); + std::copy(tmp.begin(),tmp.end(),bgFace+1); + bgFace=endFace+1; + } + } +} diff --git a/src/MEDCoupling/MEDCouplingUMesh.hxx b/src/MEDCoupling/MEDCouplingUMesh.hxx index 074de0b7b..0d06ef235 100644 --- a/src/MEDCoupling/MEDCouplingUMesh.hxx +++ b/src/MEDCoupling/MEDCouplingUMesh.hxx @@ -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& conn) const; MEDCOUPLING_EXPORT void getCoordinatesOfNode(int nodeId, std::vector& 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& tinyInfo, std::vector& littleStrings) const; MEDCOUPLING_EXPORT bool isEmptyMesh(const std::vector& tinyInfo) const; - MEDCOUPLING_EXPORT void resizeForUnserialization(const std::vector& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector& littleStrings); + MEDCOUPLING_EXPORT void resizeForUnserialization(const std::vector& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector& littleStrings) const; MEDCOUPLING_EXPORT void serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const; - MEDCOUPLING_EXPORT void unserialization(const std::vector& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, const std::vector& littleStrings); + MEDCOUPLING_EXPORT void unserialization(const std::vector& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2, const std::vector& 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& 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& 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& elems); MEDCOUPLING_EXPORT void giveElemsInBoundingBox(const INTERP_KERNEL::DirectedBoundingBox& bbox, double eps, std::vector& 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& elts, std::vector& eltsIndex) const; MEDCOUPLING_EXPORT void checkButterflyCells(std::vector& cells) const; MEDCOUPLING_EXPORT void getBoundingBoxForBBTree(std::vector& 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& 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& 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 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& 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& meshes); + MEDCOUPLING_EXPORT static MEDCouplingUMesh *fuseUMeshesOnSameCoords(const std::vector& meshes, int compType, std::vector& 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 + void findCommonCellsBase(int compType, std::vector& res, std::vector& resI) const; + bool areCellsEqualInPool(const std::vector& candidates, int compType, std::vector& result) const; MEDCouplingUMesh *buildPartOfMySelfKeepCoords(const int *start, const int *end) const; template void getCellsContainingPointsAlg(const double *coords, const double *pos, int nbOfPoints, double eps, std::vector& elts, std::vector& eltsIndex) const; + static void appendExtrudedCell(const int *connBg, const int *connEnd, int nbOfNodesPerLev, bool isQuad, std::vector& ret); private: //! this iterator stores current position in _nodal_connec array. mutable int _iterator; @@ -108,6 +156,8 @@ namespace ParaMEDMEM std::set _types; private: static const char PART_OF_NAME[]; + public: + static double EPS_FOR_POLYH_ORIENTATION; }; } diff --git a/src/MEDCoupling/MEDCouplingUMeshDesc.cxx b/src/MEDCoupling/MEDCouplingUMeshDesc.cxx index 29f1e58e3..f45cd5eba 100644 --- a/src/MEDCoupling/MEDCouplingUMeshDesc.cxx +++ b/src/MEDCoupling/MEDCouplingUMeshDesc.cxx @@ -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::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& conn) const { //not implemented yet. @@ -117,6 +149,22 @@ void MEDCouplingUMeshDesc::getCoordinatesOfNode(int nodeId, std::vector& //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); diff --git a/src/MEDCoupling/MEDCouplingUMeshDesc.hxx b/src/MEDCoupling/MEDCouplingUMeshDesc.hxx index 91ce649ed..7c965a31c 100644 --- a/src/MEDCoupling/MEDCouplingUMeshDesc.hxx +++ b/src/MEDCoupling/MEDCouplingUMeshDesc.hxx @@ -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& conn) const; MEDCOUPLING_EXPORT void getCoordinatesOfNode(int nodeId, std::vector& 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& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, const std::vector& littleStrings); MEDCOUPLING_EXPORT void giveElemsInBoundingBox(const double *bbox, double eps, std::vector& elems); MEDCOUPLING_EXPORT void giveElemsInBoundingBox(const INTERP_KERNEL::DirectedBoundingBox &bbox, double eps, std::vector& 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& 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; diff --git a/src/MEDCoupling/Makefile.am b/src/MEDCoupling/Makefile.am index 20117023a..28553f288 100644 --- a/src/MEDCoupling/Makefile.am +++ b/src/MEDCoupling/Makefile.am @@ -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 diff --git a/src/MEDCoupling/Test/MEDCouplingBasicsTest.hxx b/src/MEDCoupling/Test/MEDCouplingBasicsTest.hxx index 87393c8f9..9bbdb8519 100644 --- a/src/MEDCoupling/Test/MEDCouplingBasicsTest.hxx +++ b/src/MEDCoupling/Test/MEDCouplingBasicsTest.hxx @@ -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 >& matrix); }; } diff --git a/src/MEDCoupling/Test/MEDCouplingBasicsTest0.cxx b/src/MEDCoupling/Test/MEDCouplingBasicsTest0.cxx index 959a8c2c3..3f7adf58a 100644 --- a/src/MEDCoupling/Test/MEDCouplingBasicsTest0.cxx +++ b/src/MEDCoupling/Test/MEDCouplingBasicsTest0.cxx @@ -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 >& matrix) { double ret=0.; diff --git a/src/MEDCoupling/Test/MEDCouplingBasicsTest1.cxx b/src/MEDCoupling/Test/MEDCouplingBasicsTest1.cxx index dbd2a6ff9..fb96af12d 100644 --- a/src/MEDCoupling/Test/MEDCouplingBasicsTest1.cxx +++ b/src/MEDCoupling/Test/MEDCouplingBasicsTest1.cxx @@ -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(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(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 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 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 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 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 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 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::const_iterator iter=v.begin();iter!=v.end();iter++) + (*iter)->decrRef(); + m2->decrRef(); + m1->decrRef(); +} + +void MEDCouplingBasicsTest::testFuseUMeshesOnSameCoords() +{ + std::vector meshes; + MEDCouplingUMesh *m2=build2DTargetMesh_1(); + int cells1[3]={2,3,4}; + MEDCouplingPointSet *m3_1=m2->buildPartOfMySelf(cells1,cells1+3,true); + MEDCouplingUMesh *m3=dynamic_cast(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(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(m5_1); + CPPUNIT_ASSERT(m5); + meshes.push_back(m5); + m2->decrRef(); + // + std::vector 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 > 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::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 meshes; + meshes.push_back(m1); + meshes.push_back(m3); + meshes.push_back(m3); + meshes.push_back(m4); + std::vector corr; + MEDCouplingUMesh *m5=MEDCouplingUMesh::fuseUMeshesOnSameCoords(meshes,0,corr); + CPPUNIT_ASSERT_EQUAL(18,m5->getNumberOfCells()); + std::vector::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 index 000000000..acf8efe7d --- /dev/null +++ b/src/MEDCoupling/Test/MEDCouplingBasicsTest2.cxx @@ -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 +#include +#include + +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 _refCoo1(refCoo1,refCoo1+6); + std::vector _gsCoo1(gsCoo1,gsCoo1+12); + std::vector _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 _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 _gsCoo2(_gsCoo1); + std::vector _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 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 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 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 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 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 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 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 _refCoo1(refCoo1,refCoo1+6); + std::vector _gsCoo1(gsCoo1,gsCoo1+12); + std::vector _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 _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& 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 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& 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 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(const_cast(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(const_cast(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(const_cast(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(const_cast(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 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 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(); +} diff --git a/src/MEDCoupling/Test/MEDCouplingRemapperTest.cxx b/src/MEDCoupling/Test/MEDCouplingRemapperTest.cxx index b7c30b712..1050f75ce 100644 --- a/src/MEDCoupling/Test/MEDCouplingRemapperTest.cxx +++ b/src/MEDCoupling/Test/MEDCouplingRemapperTest.cxx @@ -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;igetNumberOfCells();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;igetNumberOfCells();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); diff --git a/src/MEDCoupling/Test/MEDCouplingRemapperTest.hxx b/src/MEDCoupling/Test/MEDCouplingRemapperTest.hxx index 61dc0e701..2b45b4b06 100644 --- a/src/MEDCoupling/Test/MEDCouplingRemapperTest.hxx +++ b/src/MEDCoupling/Test/MEDCouplingRemapperTest.hxx @@ -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(); diff --git a/src/MEDCoupling/Test/Makefile.am b/src/MEDCoupling/Test/Makefile.am index 2db4726a9..bab460971 100755 --- a/src/MEDCoupling/Test/Makefile.am +++ b/src/MEDCoupling/Test/Makefile.am @@ -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 -- 2.39.2